diff options
author | Andrew Burgess <aburgess@redhat.com> | 2024-10-10 11:37:34 +0100 |
---|---|---|
committer | Andrew Burgess <aburgess@redhat.com> | 2024-10-27 20:18:49 +0000 |
commit | f8258cdaf95a80de8375ae54fa968c452733043f (patch) | |
tree | a67cfc08760355347ed416c6411185e3f1bfef3e /gdb/block.h | |
parent | a723c56efb07c4f8b3f6a3ed4b878a2f8f5572cc (diff) | |
download | binutils-users/aburgess/try-gdb-block-entry-pc.zip binutils-users/aburgess/try-gdb-block-entry-pc.tar.gz binutils-users/aburgess/try-gdb-block-entry-pc.tar.bz2 |
gdb: fix handling of DW_AT_entry_pc of inlined subroutinesusers/aburgess/try-gdb-block-entry-pc
The entry PC for a DIE, e.g. an inline function, might not be the base
address of the DIE. Currently though, in block::entry_pc(), GDB
always returns the base address (low-pc or the first address of the
first range) as the entry PC.
This commit extends the block class to carry the entry PC as a
separate member variable. Then the DWARF reader is extended to read
and set the entry PC for the block. Now in block::entry_pc(), if the
entry PC has been set to a specific value, this is the value returned.
I have not removed the old code in block::entry_pc(). If the specific
entry PC value was not set then we still fall back on the old approach
of just returning the base address. Doing this feels more useful than
just claiming there is no entry PC. This should also mean that we
shouldn't see any change in behaviour for compilers that don't emit
the DW_AT_entry_pc, or for debug readers (e.g. stabs) that don't set
the entry PC value within a block.
The DWARF-5 spec for reading the entry PC is a super-set of the spec
as found in DWARF-4. For example, if there is no DW_AT_entry_pc then
DWARF-4 says to use DW_AT_low_pc while DWARF-5 says to use the base
address, which is DW_AT_low_pc or the first address in the first range
specified by DW_AT_ranges if there is no DW_AT_low_pc.
I have taken the approach of just implementing the DWARF-5 spec for
everyone. There doesn't seem to be any benefit to deliberately
ignoring a ranges based entry PC value for DWARF-4. If some naughty
compiler has emitted that, then lets use it.
Similarly, DWARF-4 says that DW_AT_entry_pc is an address. DWARF-5
allows an address or a constant, where the constant is an offset from
the base address. I allow both approaches for all DWARF versions.
There doesn't seem to be any downsides to this approach.
The inline-entry.exp test was originally contributed by Bernd here:
https://inbox.sourceware.org/gdb-patches/AS1PR01MB94659E4D9B3F4A6006CC605FE4922@AS1PR01MB9465.eurprd01.prod.exchangelabs.com
though I have made some edits, making more use of lib/gdb.exp
functions, making the gdb_test output patterns a little tighter, and
updating the test to run with Clang. I also moved the test to
gdb.opt/ as that seemed like a better home for it.
Co-Authored-By: Bernd Edlinger <bernd.edlinger@hotmail.de>
Diffstat (limited to 'gdb/block.h')
-rw-r--r-- | gdb/block.h | 44 |
1 files changed, 32 insertions, 12 deletions
diff --git a/gdb/block.h b/gdb/block.h index c3babad..3bd2c51 100644 --- a/gdb/block.h +++ b/gdb/block.h @@ -179,27 +179,35 @@ struct block : public allocate_on_obstack<block> /* Return the "entry PC" of this block. - The entry PC is the lowest (start) address for the block when all addresses - within the block are contiguous. If non-contiguous, then use the start - address for the first range in the block. - - At the moment, this almost matches what DWARF specifies as the entry - pc. (The missing bit is support for DW_AT_entry_pc which should be - preferred over range data and the low_pc.) + If the entry PC has been set to a specific value then this is + returned. Otherwise, the entry PC is the lowest (start) address for + the block when all addresses within the block are contiguous. If + non-contiguous, then use the start address for the first range in the + block. - Once support for DW_AT_entry_pc is added, I expect that an entry_pc - field will be added to one of these data structures. Once that's done, - the entry_pc field can be set from the dwarf reader (and other readers - too). ENTRY_PC can then be redefined to be less DWARF-centric. */ + This almost matches what DWARF specifies as the entry pc, except that + the final case, using the first address of the first range, is a GDB + extension. However, the DWARF reader sets the specific entry PC + wherever possible, so this non-standard fallback case is only used as + a last resort. */ CORE_ADDR entry_pc () const { - if (this->is_contiguous ()) + if (m_entry_pc != 0) + return m_entry_pc; + else if (this->is_contiguous ()) return this->start (); else return this->ranges ()[0].start (); } + /* Set this block's entry PC. */ + + void set_entry_pc (CORE_ADDR addr) + { + m_entry_pc = addr; + } + /* Return the objfile of this block. */ struct objfile *objfile () const; @@ -344,6 +352,18 @@ private: startaddr and endaddr above. */ struct blockranges *m_ranges = nullptr; + + /* The entry address for this block. The value 0 is special and + indicates that the entry address has not been set. + + Using 0 as a special value is not ideal, targets for which 0 is a + valid code address might run into problems if they want to use 0 as a + block's entry address, but the alternative is to carry a flag + indicating if m_entry_pc is valid or not, but that would make 'struct + block' even bigger, and we want to keep 'struct block' as small as + possible (we might have a lot of blocks). */ + + CORE_ADDR m_entry_pc = 0; }; /* The global block is singled out so that we can provide a back-link |