Bug 20967 - g++ generates same DW_AT_ranges info for two different functions
Summary: g++ generates same DW_AT_ranges info for two different functions
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: debug (show other bugs)
Version: unknown
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-04-12 12:31 UTC by fnf@specifixinc.com
Modified: 2005-07-26 23:51 UTC (History)
3 users (show)

See Also:
Host: i686-pc-linux-gnu
Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu
Known to work:
Known to fail:
Last reconfirmed:


Attachments
Emit DW_AT_call_file and DW_AT_CALL_line for inlined subroutines. (1.32 KB, patch)
2005-04-28 23:58 UTC, Jim Wilson
Details | Diff
Emit DW_AT_call_file and DW_AT_call_line for inlined subroutines. (1.82 KB, patch)
2005-05-12 20:37 UTC, Jim Wilson
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description fnf@specifixinc.com 2005-04-12 12:31:12 UTC
gcc/g++ is generating the same DWARF DW_AT_ranges info for two different
functions. This makes translation from a PC address to the function difficult
since a given PC can map to two different functions.

Using the following test file:

    // Compile as "g++ -O2 -ggdb --save-temps -o t t.cc"
    
    #include <vector>
    
    using namespace std;
    
    int main ()
    {
      vector<int> V(10);
      V[10] = 1;
    }
the DWARF info emitted by gcc assigns a block of addresses to two
different functions, get_allocator and _S_get_pool.  Here is an edited
dump of the DWARF info produced by readelf.

 <2><2523>: Abbrev Number: 38 (DW_TAG_subprogram)
     DW_AT_name        : (indirect string, offset: 0x1d35): get_allocator       
 <1><3807>: Abbrev Number: 77 (DW_TAG_subprogram)
     DW_AT_specification: <2523>        
     DW_AT_inline      : 3      (declared as inline and inlined)
 <3><39de>: Abbrev Number: 92 (DW_TAG_inlined_subroutine)
     DW_AT_abstract_origin: <3807>      
     DW_AT_ranges      : 0x5c8  
    000005c8 080488c9 080488d0
    000005c8 08048a50 08048af6
    000005c8 080488dc 080488e2
    000005c8 <End of list>

 <2><227c>: Abbrev Number: 64 (DW_TAG_subprogram)
     DW_AT_name        : (indirect string, offset: 0x666): _S_get_pool  
 <1><2e03>: Abbrev Number: 77 (DW_TAG_subprogram)
     DW_AT_specification: <227c>        
     DW_AT_inline      : 3      (declared as inline and inlined)
 <6><3a12>: Abbrev Number: 92 (DW_TAG_inlined_subroutine)
     DW_AT_abstract_origin: <2e03>      
     DW_AT_ranges      : 0x628  
    00000628 080488c9 080488d0
    00000628 08048a50 08048af6
    00000628 080488dc 080488e2
    00000628 <End of list>

When one function inlines another, and all of the associated code is generated
for the inlinee with no code generated for the inliner, my reading of the draft
DWARF 3 spec, which describes DW_AT_ranges, would indicate that no  
DW_AT_low_pc, DW_AT_high_pc, or DW_AT_ranges attributes should be generated for
the inliner function:

  2.16 Code Addresses and Ranges

  Any debugging information entry describing an entity that has a
  machine code address or range of machine code addresses, which
  includes compilation units, module initialization, subroutines,
  ordinary blocks, try/catch blocks, labels and the like, may have " A
  DW_AT_low_pc attribute for a single address, " A DW_AT_low_pc and
  DW_AT_high_pc pair of attributes for a single contiguous range of
  addresses, or " A DW_AT_ranges attribute for a non-contiguous range of
  addresses. If an entity has no associated machine code, none of these
  attributes are specified.

My understanding, perhaps incorrect, is that the entire purpose of using the
DW_AT_ranges attribute, instead of the DW_AT_low_pc/DW_AT_high_pc attributes,
is to be able to accurately describe situations like this, where code from
different functions is interleaved due to optimization.  No given address 
should appear in more than one DW_AT_ranges entry.
Comment 1 Daniel Jacobowitz 2005-04-12 13:14:37 UTC
No version information.  Is this HEAD, with Jim's earlier DW_AT_ranges patch?

I don't think your understanding is correct, but you didn't show enough of the
DIE tree to be sure.  Ignore inlined functions for a moment; let's just think
about functions and lexical blocks.  A lexical block normally has a range of
associated PC addresses, and a function normally has a high and low pc.  The
lexical block is a strict subset of the function, so it should be included in
the pc attributes of the function.

I'm guessing from your description that _S_get_pool is inlined into
get_allocator is inlined into main.  Because _S_get_pool is inside of
get_allocator, it makes sense for its PC ranges to be a subset of those for
get_allocator.  A PC always belongs to the innermost block.
Comment 2 fnf@specifixinc.com 2005-04-12 14:00:58 UTC
> No version information.  Is this HEAD, with Jim's earlier DW_AT_ranges patch?

Yes, sorry I didn't mention it.  Originally I tried to report this bug with
"gccbug" but the report seems to have gone into a black hole.  Perhaps gccbug
is broken.

Thanks for the comments.  I'll go back and review the spec again.  The one I'm
looking at is Dwarf3-draft9.pdf, 1320652 bytes.  Can't recall offhand where I
found it but I should probably check around for a newer one.

> I'm guessing from your description that _S_get_pool is inlined into
> get_allocator is inlined into main

Yes, though there is actually a little more inlining going on, so these
aren't the only two duplicates.
 
Comment 3 Daniel Jacobowitz 2005-04-12 14:08:57 UTC
Subject: Re:  g++ generates same DW_AT_ranges info for two different functions

It's a question of what "associated machine code" means.  I think that
the machine code is in fact associated with more than one DIE.

Now, if the two DIEs in question weren't nested - then we'd have a
problem.
Comment 4 Jim Wilson 2005-04-28 23:52:14 UTC
My opinion is roughly the same as Daniel's.  The debug info being emitted by gcc
here is fine.

The underlying problem here is that Fred is trying to improve support for
inlined function calls, and the current structure of the debug info emitted by
gcc makes this difficult.  However, Fred pointed me at the dwarf3 docs for
DW_AT_call_file and DW_AT_call_line.  It turns out to be easy to make gcc emit
this extra debug info, and I have written a patch that does so.  This patch does
not fix this PR, but it does make it moot.
Comment 5 Jim Wilson 2005-04-28 23:58:55 UTC
Created attachment 8760 [details]
Emit DW_AT_call_file and DW_AT_CALL_line for inlined subroutines.

This emits extra debug info that describes where an inlined subroutine was
called from.  This extra info would allow one to construct backtraces that
contain info about inlined subroutines.

This has been tested with an x86-linux bootstrap, make check, and gdb make
check.	There were no regressions.

I haven't checked in the patch yet as I have no proof that it does anything
useful, since neither binutils nor gdb handle this new debug info.  I'm waiting
for patches from Fred that will make use of this new info.
Comment 6 Jim Wilson 2005-05-12 20:37:40 UTC
Created attachment 8881 [details]
Emit DW_AT_call_file and DW_AT_call_line for inlined subroutines.
Comment 7 Jim Wilson 2005-07-26 23:51:51 UTC
The problem reported here is not a bug.  There is nothing wrong with having two
different functions with the same DW_AT_ranges info.

The underlying problem that prompted this bug report, insufficient debug info
for inlined function calls, has been fixed by adding a patch to emit
DW_AT_call_file and DW_AT_call_line info.  The final patch has one additional
bug fix over the one attached here, so take the one on the gcc-patches list if
you need it.