Closed llvmbot closed 12 years ago
Thanks a lot Eric and Douglas.
No, I agree completely. The debug info is merely explaining what's going on so there's no difference there. In addition, Daniel's comments in the thread you pointed me at are compelling and explain why we don't want to do anything.
Dear Eric,Douglas Thanks for the quick reply. I had one quick query.
As Douglas mentioned 'C1' name is the complete object constructor and the 'C2' name is the base object constructor. But in the example
class Apple { public: Apple () { int b = 0; } };
int main (void) { Apple b; return 0; }
This class has no base. Why does it have a "complete object constructor" and a "base object constructor" for each?
The Itanium C++ ABI I linked to describes this in detail, but essentially the "complete object constructor" is used when we're building a complete object of type Apple, as in
Apple a;
while the "base object constructor" is used when the Apple object is a base of another class, e.g.,
class Banana : public Apple { }; Banana b;
This dual emission of constructor results in problem with setting breakpoints in constructors as we have two info for same location.
For e.g. In the above code if we run the gdb session as follows-
/opt/home/blitz # gdb a.out GNU gdb (Linaro GDB) 7.2-2011.03-0-SLP Copyright (C) 2010 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "arm-linux-gnueabi". For bug reporting instructions, please see: http://bugs.launchpad.net/gdb-linaro/... Reading symbols from /opt/home/blitz/a.out...done. (gdb) b main Breakpoint 1 at 0x83ca: file ./class.cpp, line 13. (gdb) b 6 Breakpoint 2 at 0x8406: file ./class.cpp, line 6. (gdb) r Starting program: /opt/home/blitz/a.out
Breakpoint 1, main () at ./class.cpp:13 warning: Source file is more recent than executable. 13 Apple a; (gdb) c Continuing.
Breakpoint 2, Apple::Apple (this=0xbe811ab8) at ./class.cpp:6 6 int b = 0; (gdb) bt
0 Apple::Apple (this=0xbe811ab8) at ./class.cpp:6
1 0x000083f2 in Apple::Apple (this=0xbe811ab8) at ./class.cpp:7
2 0x000083d8 in main () at ./class.cpp:13
(gdb) Quit (gdb)
In the above session we can find that we had set break point at line 6 and have not yet reached line 7. But the bt command when run at line 6 also emits the wrong info -
1 0x000083f2 in Apple::Apple (this=0xbe811ab8) at ./class.cpp:7
(line 7 info which comes from C1 constructors prologue_end .loc)
There are few other GDB problems as well when we debug the constructor.
When we looked up we found that the same issue was reported in case of GCC. We can refer-
http://stackoverflow.com/questions/6921295/dual-emission-of-constructor-symbols http://gcc.gnu.org/bugs/#known,
Personally, I don't consider this a bug in either GCC or Clang. This behavior is mandated by the Itanium C++ ABI, and it's GDB that needs to learn to handle C++ constructors emitted for the Itanium C++ ABI properly.
When we checked the same in case of gcc it seems it actually alias the symbols to the same code for both. A temporary patch seems to have been given as per http://sources.redhat.com/ml/gdb/2004-07/msg00163.html
We might need to do something similar in case of clang. Please let us know if our analysis is correct.
Clang does perform this optimization on some platforms, when possible. However, it can't always be done (because the constructors will behave differently when, e.g., there are virtual base classes involved), and therefore can't be relied upon to improve the debugging situation.
Unless Eric thinks there is something specific that the compiler can do here (which I doubt), I think this is not a Clang bug.
Dear Eric,Douglas Thanks for the quick reply. I had one quick query.
As Douglas mentioned 'C1' name is the complete object constructor and the 'C2' name is the base object constructor. But in the example
class Apple { public: Apple () { int b = 0; } };
int main (void) { Apple b; return 0; }
This class has no base. Why does it have a "complete object constructor" and a "base object constructor" for each?
This dual emission of constructor results in problem with setting breakpoints in constructors as we have two info for same location.
For e.g. In the above code if we run the gdb session as follows-
/opt/home/blitz # gdb a.out GNU gdb (Linaro GDB) 7.2-2011.03-0-SLP Copyright (C) 2010 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "arm-linux-gnueabi". For bug reporting instructions, please see: http://bugs.launchpad.net/gdb-linaro/... Reading symbols from /opt/home/blitz/a.out...done. (gdb) b main Breakpoint 1 at 0x83ca: file ./class.cpp, line 13. (gdb) b 6 Breakpoint 2 at 0x8406: file ./class.cpp, line 6. (gdb) r Starting program: /opt/home/blitz/a.out
Breakpoint 1, main () at ./class.cpp:13 warning: Source file is more recent than executable. 13 Apple a; (gdb) c Continuing.
Breakpoint 2, Apple::Apple (this=0xbe811ab8) at ./class.cpp:6 6 int b = 0; (gdb) bt
(gdb) Quit (gdb)
In the above session we can find that we had set break point at line 6 and have not yet reached line 7. But the bt command when run at line 6 also emits the wrong info -
(line 7 info which comes from C1 constructors prologue_end .loc)
There are few other GDB problems as well when we debug the constructor.
When we looked up we found that the same issue was reported in case of GCC. We can refer-
http://stackoverflow.com/questions/6921295/dual-emission-of-constructor-symbols http://gcc.gnu.org/bugs/#known,
When we checked the same in case of gcc it seems it actually alias the symbols to the same code for both. A temporary patch seems to have been given as per http://sources.redhat.com/ml/gdb/2004-07/msg00163.html
We might need to do something similar in case of clang. Please let us know if our analysis is correct. Thanks
You know, I think that's the second time that's come up. I should remember it for next time. Thanks :)
The dwarf is successfully describing the two functions that are there in the assembly. My knowledge of C++ constructor semantics is a bit lacking so I'm going to punt to John or Doug on this...
Multiple versions of the constructors are required by the C++ ABI as documented here:
http://sourcery.mentor.com/public/cxx-abi/abi.html
The 'C1' name is the complete object constructor and the 'C2' name is the base object constructor.
The dwarf is successfully describing the two functions that are there in the assembly. My knowledge of C++ constructor semantics is a bit lacking so I'm going to punt to John or Doug on this...
Here's the dwarf for this:
0x0000008b: TAG_subprogram [10] * AT_MIPS_linkage_name( "_ZN5AppleC1Ev" ) AT_specification( {0x00000074} ( "Apple" ) ) AT_low_pc( 0x00000000000002d0 ) AT_high_pc( 0x00000000000002eb ) AT_frame_base( rbp )
0x000000a6: TAG_formal_parameter [11]
AT_name( "this" )
AT_decl_file( "/Users/echristo/foo.cpp" )
AT_decl_line( 4 )
AT_type( {0x00000101} ( Apple* ) )
AT_artificial( 0x01 )
AT_location( fbreg -8 )
0x000000b5: NULL
0x000000b6: TAG_subprogram [10] * AT_MIPS_linkage_name( "_ZN5AppleC2Ev" ) AT_specification( {0x00000074} ( "Apple" ) ) AT_low_pc( 0x00000000000002f0 ) AT_high_pc( 0x0000000000000301 ) AT_frame_base( rbp )
0x000000d1: TAG_formal_parameter [11]
AT_name( "this" )
AT_decl_file( "/Users/echristo/foo.cpp" )
AT_decl_line( 4 )
AT_type( {0x00000101} ( Apple* ) )
AT_artificial( 0x01 )
AT_location( fbreg -8 )
0x000000e0: TAG_lexical_block [3] * AT_low_pc( 0x00000000000002f8 ) AT_high_pc( 0x0000000000000301 )
0x000000f1: TAG_variable [4]
AT_name( "b" )
AT_decl_file( "/Users/echristo/foo.cpp" )
AT_decl_line( 6 )
AT_type( {0x00000065} ( int ) )
AT_location( fbreg -12 )
0x000000ff: NULL
0x00000100: NULL
Extended Description
In case of inline default constructor debug information in wrongly generated. For e.g. for the below code-
class Apple { public: Apple () { int b = 0; } };
int main (void) { Apple b; return 0; }
Debug info for the default constructor in the assembly is as follows contains 2 entries i.e.
_ZN5AppleC1Ev: .Lfunc_begin1: .loc 2 5 0
@ BB#0: @ %entry push {r7, lr} mov r7, sp sub sp, #24 str r0, [sp, #16] str r0, [sp, #20] sub sp, #4 .loc 2 7 2 prologue_end
.Ltmp3: str r0, [sp, #12] @ 4-byte Spill bl _ZN5AppleC2Ev(PLT) ldr r1, [sp, #20] ldr r2, [sp, #12] @ 4-byte Reload str r0, [sp, #8] @ 4-byte Spill mov r0, r1 str r2, [sp, #4] @ 4-byte Spill add sp, #28 pop {r7, pc} .Ltmp4: .Ltmp5: .size _ZN5AppleC1Ev, .Ltmp5-_ZN5AppleC1Ev .Lfunc_end1:
_ZN5AppleC2Ev: .Lfunc_begin2: .loc 2 5 0
@ BB#0: @ %entry sub sp, #16 @DEBUG_VALUE: Apple:this <- undef str r0, [sp, #8] str r0, [sp, #12] movs r1, #0 sub sp, #4 .loc 2 6 16 prologue_end
.Ltmp6: str r1, [sp, #4] .loc 2 7 2
ldr r1, [sp, #12] str r0, [sp] @ 4-byte Spill mov r0, r1 add sp, #20 bx lr .Ltmp7: .Ltmp8: .size _ZN5AppleC2Ev, .Ltmp8-_ZN5AppleC2Ev .Lfunc_end2:
As shown in the assembly snippet. For the default constructor we get 2 entries one by name _ZN5AppleC1Ev and another by _ZN5AppleC2Ev.