Hi,
I'm implementing a check that the range of .debug_loc addresses doesn't run off range claimed by DW_AT_low_pc/high_pc pair or DW_AT_ranges. It just so happens that it's also easy to check that ranges of a DIE are sub-range of its parent, since I need that range-tracking logic anyway. Such a check sounded plausible to me, but it wasn't really that hard to found a case that gives me second thoughts (from readelf):
[ 5333] subprogram name "parse_opt" decl_file 1 decl_line 283 prototyped type [ 435] low_pc 0x0000000000403510 <parse_opt> high_pc 0x0000000000403ab0 <print_pubnames> frame_base location list [ 2b1] sibling [ 566d] [ 5358] formal_parameter [...] [ 5368] formal_parameter [...] [ 5378] subprogram name "add_dump_section" decl_file 1 decl_line 286 prototyped low_pc 0x004034b0 <add_dump_section.9838> high_pc 0x0040350e frame_base location list [ 4f7] static_link 1 byte block: 56 [ 0] reg6 sibling [ 53d5]
... so that's a case of internal function add_dump_section inside other function parse_opt. The internal function wasn't inlined, and so occupies different part of address space.
I can't decide whether that case is kosher, I can argue both sides. Shouldn't the parent either claim addresses of its child, or not have that DIE as a child in a first place?
PM
I can't decide whether that case is kosher, I can argue both sides. Shouldn't the parent either claim addresses of its child, or not have that DIE as a child in a first place?
No, I'm pretty confident that's kosher as it is. The DIE nesting there indicates the lexical scope of the inner function. It's right for it to be there, so that you can tell e.g. that the DW_TAG_variable entries of its parent function are visible inside that inner DW_TAG_subprogram scope.
Nesting of DIEs sometimes corresponds to subsets of PC ranges, but not always. I think we can encode this in the dwarf-knowledge tables.
These: inlined_subroutine lexical_block entry_point label with_stmt try_block catch_block can have PC's and those should be entirely inside the containing PC-ful entry.
These: compile_unit partial_unit module should have a PC set that's the union of every PC-ful entry they own.
Thanks, Roland
06.10.2009 08:44, Roland McGrath wrote:
These: inlined_subroutine lexical_block entry_point label with_stmt try_block catch_block can have PC's and those should be entirely inside the containing PC-ful entry.
Thanks. I've implemented it like this, and found no violations so far. It's hacked in as a simple switch statement, there's no fancy logic that would trigger the check just because the above condition holds for given DIE context.
PM
On 10/05/2009 11:44 PM, Roland McGrath wrote:
I can't decide whether that case is kosher, I can argue both sides. Shouldn't the parent either claim addresses of its child, or not have that DIE as a child in a first place?
No, I'm pretty confident that's kosher as it is.
Well, currently dwarf_getscopes assumes that every child is a strict PC-subset of the parent, so it won't ever find a PC in such unclaimed children.
Similarly, dwarf_getfuncs won't return nested functions either. I see no real way to fix these without traversing nearly all DIEs. :(
The DIE nesting there indicates the lexical scope of the inner function. It's right for it to be there, so that you can tell e.g. that the DW_TAG_variable entries of its parent function are visible inside that inner DW_TAG_subprogram scope.
In other nested lexical scopes, like a C++ class method, you get a top-level DW_TAG_subprogram DIE with a DW_AT_specification to the nested definition. Wouldn't that be a better way for these nested functions to generate dwarf too?
Josh
elfutils-devel@lists.fedorahosted.org