So I've been successful with funneling class X { public: X(int r) : res(r) {} int get() { return res; } private: int res; }; int main() { X x(0); return x.get (); }
all the way through LTO and gdb recognizing all the nice early debug info for X: > gdb ./a.out (gdb) start Temporary breakpoint 1 at 0x400514: file t.C, line 2. Starting program: /home/abuild/rguenther/obj-debug-early-g/gcc/a.out Temporary breakpoint 1, main () at t.C:2 2 int main() { X x(0); return x.get (); } (gdb) info locals x = {res = -8560} (gdb) ptype x type = class X { private: int res; public: X(int); int get(void); } the late dwarf generation is a bit awkward because it insists on creating type DIEs for all sort of contexts when we process scope vars. The type DIEs already exist, but only in early debug info. I suspect we need to do quite some dwarf2out refactoring to split early from late debug generation in areas like that. For the C++ example above we get some stray unused type DIEs still. So what is missing? Missing is the driver side - currently you need to re-link the executable with the compile-time object file: > ./xg++ -B. -B ../x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs t.C -g -dA > -flto -flto-partition=none -save-temps /tmp/ccY1C3Bg.lto.o:(.debug_info+0x23): undefined reference to `t.C.14231d22' /tmp/ccY1C3Bg.lto.o:(.debug_info+0x28): undefined reference to `t.C.14231d22' /tmp/ccY1C3Bg.lto.o:(.debug_info+0x47): undefined reference to `t.C.14231d22' /tmp/ccY1C3Bg.lto.o:(.debug_info+0x4f): undefined reference to `t.C.14231d22' /tmp/ccY1C3Bg.lto.o:(.debug_info+0x58): undefined reference to `t.C.14231d22' /tmp/ccY1C3Bg.lto.o:(.debug_info+0x77): more undefined references to `t.C.14231d22' follow collect2: error: ld returned 1 exit status > ./as --64 -o /tmp/ccY1C3Bg.lto.o t.s > ./xgcc -B. t.o /tmp/ccY1C3Bg.lto.o -fno-lto that's for tomorrow to simplify. I've attached the current patch ontop of the branch as well as a.out. I'm now creating a sinlge CU DIE during LTRANS and import the early generated CUs there, re-parenting all generated code to the LTRANS CU DIE. That seems to work best with current gdb. For the above example the early generated DWARF part is <0><166>: Abbrev Number: 1 (DW_TAG_compile_unit) <167> DW_AT_producer : (indirect string, offset: 0x195): GNU C++ 5.0.0 20150316 (experimental) -mtune=generic -march=x86-64 -g -flto -flto-partition=no ne <16b> DW_AT_language : 4 (C++) <16c> DW_AT_name : t.C <170> DW_AT_comp_dir : (indirect string, offset: 0x16d): /abuild/rguenther/obj-debug-early-g/gcc <1><174>: Abbrev Number: 2 (DW_TAG_class_type) <175> DW_AT_name : X <177> DW_AT_byte_size : 4 <178> DW_AT_decl_file : 1 <179> DW_AT_decl_line : 1 <17a> DW_AT_sibling : <0x1c2> <2><17e>: Abbrev Number: 3 (DW_TAG_member) <17f> DW_AT_name : res <183> DW_AT_decl_file : 1 <184> DW_AT_decl_line : 1 <185> DW_AT_type : <0x1c2> <189> DW_AT_data_member_location: 0 <2><18a>: Abbrev Number: 4 (DW_TAG_subprogram) <18b> DW_AT_external : 1 <18b> DW_AT_name : X <18d> DW_AT_decl_file : 1 <18e> DW_AT_decl_line : 1 <18f> DW_AT_linkage_name: (indirect string, offset: 0x163): _ZN1XC4Ei <193> DW_AT_accessibility: 1 (public) <194> DW_AT_declaration : 1 <194> DW_AT_object_pointer: <0x19c> <198> DW_AT_sibling : <0x1a7> <3><19c>: Abbrev Number: 5 (DW_TAG_formal_parameter) <19d> DW_AT_type : <0x1c9> <1a1> DW_AT_artificial : 1 <3><1a1>: Abbrev Number: 6 (DW_TAG_formal_parameter) <1a2> DW_AT_type : <0x1c2> <3><1a6>: Abbrev Number: 0 <2><1a7>: Abbrev Number: 7 (DW_TAG_subprogram) <1a8> DW_AT_external : 1 <1a8> DW_AT_name : get <1ac> DW_AT_decl_file : 1 <1ad> DW_AT_decl_line : 1 <1ae> DW_AT_linkage_name: (indirect string, offset: 0x200): _ZN1X3getEv <1b2> DW_AT_type : <0x1c2> <1b6> DW_AT_accessibility: 1 (public) <1b7> DW_AT_declaration : 1 <1b7> DW_AT_object_pointer: <0x1bb> <3><1bb>: Abbrev Number: 5 (DW_TAG_formal_parameter) <1bc> DW_AT_type : <0x1c9> <1c0> DW_AT_artificial : 1 <3><1c0>: Abbrev Number: 0 <2><1c1>: Abbrev Number: 0 <1><1c2>: Abbrev Number: 8 (DW_TAG_base_type) <1c3> DW_AT_byte_size : 4 <1c4> DW_AT_encoding : 5 (signed) <1c5> DW_AT_name : int <1><1c9>: Abbrev Number: 9 (DW_TAG_pointer_type) <1ca> DW_AT_byte_size : 8 <1cb> DW_AT_type : <0x174> <1><1cf>: Abbrev Number: 10 (DW_TAG_subprogram) <1d0> DW_AT_external : 1 <1d0> DW_AT_name : (indirect string, offset: 0x211): main <1d4> DW_AT_decl_file : 1 <1d5> DW_AT_decl_line : 2 <1d6> DW_AT_type : <0x1c2> <1da> DW_AT_sibling : <0x1e8> <2><1de>: Abbrev Number: 11 (DW_TAG_variable) <1df> DW_AT_name : x <1e1> DW_AT_decl_file : 1 <1e2> DW_AT_decl_line : 2 <1e3> DW_AT_type : <0x174> <2><1e7>: Abbrev Number: 0 <1><1e8>: Abbrev Number: 12 (DW_TAG_subprogram) <1e9> DW_AT_specification: <0x1a7> <1ed> DW_AT_object_pointer: <0x1f5> <1f1> DW_AT_sibling : <0x1ff> <2><1f5>: Abbrev Number: 13 (DW_TAG_formal_parameter) <1f6> DW_AT_name : (indirect string, offset: 0x20c): this <1fa> DW_AT_type : <0x1ff> <1fe> DW_AT_artificial : 1 <2><1fe>: Abbrev Number: 0 <1><1ff>: Abbrev Number: 14 (DW_TAG_const_type) <200> DW_AT_type : <0x1c9> <1><204>: Abbrev Number: 15 (DW_TAG_subprogram) <205> DW_AT_specification: <0x18a> <209> DW_AT_inline : 2 (declared as inline but ignored) <20a> DW_AT_object_pointer: <0x212> <20e> DW_AT_sibling : <0x225> <2><212>: Abbrev Number: 13 (DW_TAG_formal_parameter) <213> DW_AT_name : (indirect string, offset: 0x20c): this <217> DW_AT_type : <0x1ff> <21b> DW_AT_artificial : 1 <2><21b>: Abbrev Number: 16 (DW_TAG_formal_parameter) <21c> DW_AT_name : r <21e> DW_AT_decl_file : 1 <21f> DW_AT_decl_line : 1 <220> DW_AT_type : <0x1c2> <2><224>: Abbrev Number: 0 <1><225>: Abbrev Number: 17 (DW_TAG_subprogram) <226> DW_AT_abstract_origin: <0x204> <22a> DW_AT_linkage_name: (indirect string, offset: 0x1f6): _ZN1XC2Ei <22e> DW_AT_object_pointer: <0x232> <2><232>: Abbrev Number: 18 (DW_TAG_formal_parameter) <233> DW_AT_abstract_origin: <0x212> <2><237>: Abbrev Number: 18 (DW_TAG_formal_parameter) <238> DW_AT_abstract_origin: <0x21b> <2><23c>: Abbrev Number: 0 <1><23d>: Abbrev Number: 0 while late during LTRANS we generate <0><249>: Abbrev Number: 1 (DW_TAG_compile_unit) <24a> DW_AT_producer : <24b> DW_AT_language : 4 (C++) <24c> DW_AT_low_pc : 0x4004e6 <254> DW_AT_high_pc : 0x4d <25c> DW_AT_stmt_list : 0x10c <1><260>: Abbrev Number: 2 (DW_TAG_imported_unit) <261> DW_AT_import : <0x166> [Abbrev Number: 1] <1><265>: Abbrev Number: 3 (DW_TAG_subprogram) <266> DW_AT_abstract_origin: <0x225> <26a> DW_AT_low_pc : 0x4004e6 <272> DW_AT_high_pc : 0x16 <27a> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa) <27c> DW_AT_object_pointer: <0x284> <280> DW_AT_GNU_all_call_sites: 1 <280> DW_AT_sibling : <0x295> <2><284>: Abbrev Number: 4 (DW_TAG_formal_parameter) <285> DW_AT_abstract_origin: <0x232> <289> DW_AT_artificial : 1 <289> DW_AT_location : 2 byte block: 91 68 (DW_OP_fbreg: -24) <2><28c>: Abbrev Number: 5 (DW_TAG_formal_parameter) <28d> DW_AT_abstract_origin: <0x237> <291> DW_AT_location : 2 byte block: 91 64 (DW_OP_fbreg: -28) <2><294>: Abbrev Number: 0 <1><295>: Abbrev Number: 3 (DW_TAG_subprogram) <296> DW_AT_abstract_origin: <0x1e8> <29a> DW_AT_low_pc : 0x4004fc <2a2> DW_AT_high_pc : 0x10 <2aa> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa) <2ac> DW_AT_object_pointer: <0x2b4> <2b0> DW_AT_GNU_all_call_sites: 1 <2b0> DW_AT_sibling : <0x2bd> <2><2b4>: Abbrev Number: 4 (DW_TAG_formal_parameter) <2b5> DW_AT_abstract_origin: <0x1f5> <2b9> DW_AT_artificial : 1 <2b9> DW_AT_location : 2 byte block: 91 68 (DW_OP_fbreg: -24) <2><2bc>: Abbrev Number: 0 <1><2bd>: Abbrev Number: 6 (DW_TAG_subprogram) <2be> DW_AT_abstract_origin: <0x1cf> <2c2> DW_AT_low_pc : 0x40050c <2ca> DW_AT_high_pc : 0x27 <2d2> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa) <2d4> DW_AT_GNU_all_tail_call_sites: 1 <2d4> DW_AT_sibling : <0x2e1> <2><2d8>: Abbrev Number: 7 (DW_TAG_variable) <2d9> DW_AT_abstract_origin: <0x1de> <2dd> DW_AT_location : 2 byte block: 91 60 (DW_OP_fbreg: -32) <2><2e0>: Abbrev Number: 0 <1><2e1>: Abbrev Number: 8 (DW_TAG_structure_type) <2e2> DW_AT_name : X <2e4> DW_AT_byte_size : 4 <2e5> DW_AT_decl_file : 1 <2e6> DW_AT_decl_line : 1 <2e7> DW_AT_sibling : <0x2f9> <2><2eb>: Abbrev Number: 9 (DW_TAG_member) <2ec> DW_AT_name : res <2f0> DW_AT_decl_file : 1 <2f1> DW_AT_decl_line : 1 <2f2> DW_AT_type : <0x2f9> <2f6> DW_AT_data_member_location: 0 <2f7> DW_AT_accessibility: 3 (private) <2><2f8>: Abbrev Number: 0 <1><2f9>: Abbrev Number: 10 (DW_TAG_base_type) <2fa> DW_AT_byte_size : 4 <2fb> DW_AT_encoding : 5 (signed) <2fc> DW_AT_name : int <1><300>: Abbrev Number: 0 notice the stray unused type DIEs at 0x2e1 and following. We'll ultimatively have issues with fat LTO objects and with the linker refusing to link objects with slim LTO data just for its debug info. Currently I'm working to make the slim-LTO but not marked as slim mode work only. Richard.
early-lto-debug-day2
Description: Binary data
a.out
Description: Binary data