Hi, I have a simple patch attached to improve the output addr2line -fi. The problem I had is it failed to identify the parent function name if there was any lexical_block in the scope hierarchy. For example, try the following, compiled as the attached testfile-lex-inlines.bz2:
1 // g++ x.cpp -g -fPIC -olibx.so -shared -O3 -fvisibility=hidden 2 3 void foobar() 4 { 5 __asm__ ( "nop" ::: ); 6 } 7 8 void foo() 9 { 10 { 11 void (*bar) () = foobar; 12 bar(); 13 } 14 } $ eu-addr2line -f -i -e testfile-lex-inlines.bz2 0x690 foobar inlined at /tmp/x.cpp:12 in _Z3foov /tmp/x.cpp:9 ?? /tmp/x.cpp:12 With my patch: $ ./src/addr2line -fi -e testfile-lex-inlines.bz2 0x690 foobar inlined at /tmp/x.cpp:12 in _Z3foov /tmp/x.cpp:9 _Z3foov /tmp/x.cpp:12 So the name is resolved, and I'm happier. But, as I went to make this a testcase, I noticed that the ":9" line isn't really correct for "foobar" -- that's the start of "foo". There are two candidate lines for 0x690: [ 33] special opcode 246: address+16 = +0x690 <_Z3foov>, line+4 = 9 [ 34] special opcode 14: address+0 = +0x690 <_Z3foov>, line-4 = 5 So what happens AFAICT, the name is found with dwarf_getscopes(), which will find the innermost address match. The line is found with dwfl_module_getsrc, which uses a binary search, making no guarantees if there are multiple matches. The bsearch happened to pick the first one in this case. Perhaps this should choose the last matching address to be approximately innermost? I also noticed that addr2line's print_dwarf_function() doesn't try to read linkage_name, although that wouldn't matter for this foobar inline. It also looks like it's trying to walk up the inline / subprogram stack, but since dwarf_getscopes chases the abstract_origin, it doesn't have any of that. So print_dwarf_function() returns false, and it falls back to dwfl_module_addrname to get the outer name. With dwarf_getscopes_die this would work, including multiple layers of inlines, as it later does for -i. But actually, I think having -i makes this "inlined at ..." message redundant. Binutils addr2line -fi doesn't print anything like this. Should we just kill that part? Patch review and other thoughts appreciated... Josh
diff --git a/src/addr2line.c b/src/addr2line.c index 50fc2b38c367..eea39da97e2c 100644 --- a/src/addr2line.c +++ b/src/addr2line.c @@ -672,7 +672,22 @@ handle_address (const char *string, Dwfl *dwfl) continue; if (show_functions) - print_diesym (&scopes[i + 1]); + { + /* Search for the parent inline or function. It + might not be directly above this inline -- e.g. + there could be a lexical_block in between. */ + for (int j = i + 1; j < nscopes; j++) + { + Dwarf_Die *parent = &scopes[j]; + int tag = dwarf_tag (parent); + if (tag == DW_TAG_inlined_subroutine + || tag == DW_TAG_subprogram) + { + print_diesym (parent); + break; + } + } + } src = NULL; lineno = 0;
testfile-lex-inlines.bz2
Description: application/bzip
Call frame search table section [13] '.eh_frame_hdr': version: 1 eh_frame_ptr_enc: 0x1b (sdata4 pcrel) fde_count_enc: 0x3 (udata4) table_enc: 0x3b (sdata4 datarel) eh_frame_ptr: 0x24 (offset: 0x6c8) fde_count: 3 Table: 0xfffffec0 (offset: 0x560) -> 0x40 fde=[ 18] 0xffffffe0 (offset: 0x680) -> 0x68 fde=[ 40] 0xfffffff0 (offset: 0x690) -> 0x80 fde=[ 58] Call frame information section [14] '.eh_frame' at offset 0x6c8: [ 0] CIE length=20 CIE_id: 0 version: 1 augmentation: "zR" code_alignment_factor: 1 data_alignment_factor: -8 return_address_register: 16 Augmentation data: 0x1b (FDE address encoding: sdata4 pcrel) Program: def_cfa r7 (rsp) at offset 8 offset r16 (rip) at cfa-8 nop nop [ 18] FDE length=36 cie=[ 0] CIE_pointer: 28 initial_location: +0x0000000000000560 (offset: 0x560) address_range: 0x30 (end offset: 0x590) Program: def_cfa_offset 16 advance_loc 6 to 0x566 def_cfa_offset 24 advance_loc 10 to 0x570 def_cfa_expression 11 [ 0] breg7 8 [ 2] breg16 0 [ 4] lit15 [ 5] and [ 6] lit11 [ 7] ge [ 8] lit3 [ 9] shl [ 10] plus nop nop nop nop [ 40] FDE length=20 cie=[ 0] CIE_pointer: 68 initial_location: +0x0000000000000680 <_Z6foobarv> (offset: 0x680) address_range: 0x2 (end offset: 0x682) Program: nop nop nop nop nop nop nop [ 58] FDE length=20 cie=[ 0] CIE_pointer: 92 initial_location: +0x0000000000000690 <_Z3foov> (offset: 0x690) address_range: 0x2 (end offset: 0x692) Program: nop nop nop nop nop nop nop [ 70] Zero terminator DWARF section [24] '.debug_aranges' at offset 0x1054: Table at offset 0: Length: 44 DWARF version: 2 CU offset: 0 Address size: 8 Segment size: 0 +0x0000000000000680 <_Z6foobarv>..+0x0000000000000691 <_Z3foov+0x1> DWARF section [25] '.debug_info' at offset 0x1084: [Offset] Compilation unit at offset 0: Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4 [ b] compile_unit producer (strp) "GNU C++ 4.8.3 20140911 (Red Hat 4.8.3-7) -mtune=generic -march=x86-64 -g -O3 -fPIC -fvisibility=hidden" language (data1) C_plus_plus (4) name (strp) "x.cpp" comp_dir (strp) "/tmp" low_pc (addr) +0x0000000000000680 <_Z6foobarv> high_pc (data8) 18 (+0x0000000000000692) stmt_list (sec_offset) 0 [ 2d] subprogram external (flag_present) Yes name (strp) "foobar" decl_file (data1) 1 decl_line (data1) 3 inline (data1) inlined (1) [ 35] subprogram abstract_origin (ref4) [ 2d] linkage_name (strp) "_Z6foobarv" low_pc (addr) +0x0000000000000680 <_Z6foobarv> high_pc (data8) 2 (+0x0000000000000682) frame_base (exprloc) [ 0] call_frame_cfa GNU_all_call_sites (flag_present) Yes [ 50] subprogram external (flag_present) Yes name (string) "foo" decl_file (data1) 1 decl_line (data1) 8 linkage_name (strp) "_Z3foov" low_pc (addr) +0x0000000000000690 <_Z3foov> high_pc (data8) 2 (+0x0000000000000692) frame_base (exprloc) [ 0] call_frame_cfa GNU_all_call_sites (flag_present) Yes sibling (ref4) [ b1] [ 71] lexical_block low_pc (addr) +0x0000000000000690 <_Z3foov> high_pc (data8) 2 (+0x0000000000000692) [ 82] variable name (string) "bar" decl_file (data1) 1 decl_line (data1) 11 type (ref4) [ b2] location (exprloc) [ 0] addr +0x680 <_Z6foobarv> [ 9] stack_value [ 98] inlined_subroutine abstract_origin (ref4) [ 2d] low_pc (addr) +0x0000000000000690 <_Z3foov> high_pc (data8) 2 (+0x0000000000000692) call_file (data1) 1 call_line (data1) 12 [ b1] subroutine_type [ b2] pointer_type byte_size (data1) 8 type (ref4) [ b1] DWARF section [26] '.debug_abbrev' at offset 0x113d: [ Code] Abbreviation section at offset 0: [ 1] offset: 0, children: yes, tag: compile_unit attr: producer, form: strp, offset: 0 attr: language, form: data1, offset: 0x2 attr: name, form: strp, offset: 0x4 attr: comp_dir, form: strp, offset: 0x6 attr: low_pc, form: addr, offset: 0x8 attr: high_pc, form: data8, offset: 0xa attr: stmt_list, form: sec_offset, offset: 0xc [ 2] offset: 19, children: no, tag: subprogram attr: external, form: flag_present, offset: 0x13 attr: name, form: strp, offset: 0x15 attr: decl_file, form: data1, offset: 0x17 attr: decl_line, form: data1, offset: 0x19 attr: inline, form: data1, offset: 0x1b [ 3] offset: 34, children: no, tag: subprogram attr: abstract_origin, form: ref4, offset: 0x22 attr: linkage_name, form: strp, offset: 0x24 attr: low_pc, form: addr, offset: 0x26 attr: high_pc, form: data8, offset: 0x28 attr: frame_base, form: exprloc, offset: 0x2a attr: GNU_all_call_sites, form: flag_present, offset: 0x2c [ 4] offset: 52, children: yes, tag: subprogram attr: external, form: flag_present, offset: 0x34 attr: name, form: string, offset: 0x36 attr: decl_file, form: data1, offset: 0x38 attr: decl_line, form: data1, offset: 0x3a attr: linkage_name, form: strp, offset: 0x3c attr: low_pc, form: addr, offset: 0x3e attr: high_pc, form: data8, offset: 0x40 attr: frame_base, form: exprloc, offset: 0x42 attr: GNU_all_call_sites, form: flag_present, offset: 0x44 attr: sibling, form: ref4, offset: 0x47 [ 5] offset: 78, children: yes, tag: lexical_block attr: low_pc, form: addr, offset: 0x4e attr: high_pc, form: data8, offset: 0x50 [ 6] offset: 87, children: no, tag: variable attr: name, form: string, offset: 0x57 attr: decl_file, form: data1, offset: 0x59 attr: decl_line, form: data1, offset: 0x5b attr: type, form: ref4, offset: 0x5d attr: location, form: exprloc, offset: 0x5f [ 7] offset: 102, children: no, tag: inlined_subroutine attr: abstract_origin, form: ref4, offset: 0x66 attr: low_pc, form: addr, offset: 0x68 attr: high_pc, form: data8, offset: 0x6a attr: call_file, form: data1, offset: 0x6c attr: call_line, form: data1, offset: 0x6e [ 8] offset: 117, children: no, tag: subroutine_type [ 9] offset: 122, children: no, tag: pointer_type attr: byte_size, form: data1, offset: 0x7a attr: type, form: ref4, offset: 0x7c DWARF section [27] '.debug_line' at offset 0x11c1: Table at offset 0: Length: 54 DWARF version: 2 Prologue length: 28 Minimum instruction length: 1 Maximum operations per instruction: 1 Initial value if 'is_stmt': 1 Line base: -5 Line range: 14 Opcode base: 13 Opcodes: [ 1] 0 arguments [ 2] 1 argument [ 3] 1 argument [ 4] 1 argument [ 5] 1 argument [ 6] 0 arguments [ 7] 0 arguments [ 8] 0 arguments [ 9] 1 argument [10] 0 arguments [11] 0 arguments [12] 1 argument Directory table: File name table: Entry Dir Time Size Name 1 0 0 0 x.cpp Line number statements: [ 26] extended opcode 2: set address to +0x680 <_Z6foobarv> [ 31] special opcode 21: address+0 = +0x680 <_Z6foobarv>, line+3 = 4 [ 32] special opcode 19: address+0 = +0x680 <_Z6foobarv>, line+1 = 5 [ 33] special opcode 246: address+16 = +0x690 <_Z3foov>, line+4 = 9 [ 34] special opcode 14: address+0 = +0x690 <_Z3foov>, line-4 = 5 [ 35] advance address by 2 to +0x692 [ 37] extended opcode 1: end of sequence DWARF section [28] '.debug_str' at offset 0x11fb: Offset String [ 0] "foobar" [ 7] "GNU C++ 4.8.3 20140911 (Red Hat 4.8.3-7) -mtune=generic -march=x86-64 -g -O3 -fPIC -fvisibility=hidden" [ 6e] "/tmp" [ 73] "_Z6foobarv" [ 7e] "_Z3foov" [ 86] "x.cpp"