client is reporting a problem w/ the way gcc is producing debug symbol tables under RHEL3. ---------- Action by: dmaley By default, gcc and g++/c++ do not produce debug symbol tables in the correct format for debugging on RedHat Enterprise Linux 3.0. This seems to be the case for RHEL 3 on x86, x86-64 (Opteron) AND ia64 (Itanium). One *should* simply be able to add the flag "-g" to the compile line to get an executable that can be debugged by gdb. This appears to be broken on RHEL3. Using the attached source files: ## the following will produce an executable that gdb ## on RedHat Enterprise Linux will not properly debug g++ -g -o stuff main1.C IntArray.C ## the following will produce the proper debug symbol table information ## for gdb on RedHat Enterprise Linux g++ -gstabs+ -o stuff2 main1.C IntArray.C If you look at the debug symbol tables that are generated, by examining the assembly code, it looks like the default debug information is going into seperate .debug_* sections. It appears that gdb expects to see the debug information as .stabs.
Created attachment 98388 [details] C++ test case that results in 2 copies of each constructor
Ok, after digging some more I came across this: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=3187 - gcc lays down two copies of constructors This appears to be what is happening here: gdb) p IntArray $1 = {void (IntArray * const, int)} 0x8048ae8 <IntArray> ... gdb) where #0 0x08048ca3 in IntArray::init(int const*, int) (this=0xbfffb660, array=0x0, sz=12) at IntArray.C:42 #1 0x08048b47 in IntArray (this=0xbfffb660, sz=12) at IntArray.C:11 This could be the cause of gdb's confusion, so I am setting this back as a gcc bug... 08048ae8 <_ZN8IntArrayC2Ei>: 8048ae8: 55 push %ebp 8048ae9: 89 e5 mov %esp,%ebp 8048aeb: 83 ec 08 sub $0x8,%esp 8048aee: 8b 45 08 mov 0x8(%ebp),%eax 8048af1: c7 00 a8 a7 04 08 movl $0x804a7a8,(%eax) 8048af7: 8b 45 0c mov 0xc(%ebp),%eax 8048afa: 89 45 fc mov %eax,0xfffffffc(%ebp) 8048afd: c7 45 f8 00 00 00 00 movl $0x0,0xfffffff8(%ebp) 8048b04: 83 ec 04 sub $0x4,%esp 8048b07: ff 75 fc pushl 0xfffffffc(%ebp) 8048b0a: ff 75 f8 pushl 0xfffffff8(%ebp) 8048b0d: ff 75 08 pushl 0x8(%ebp) 8048b10: e8 0b 01 00 00 call 8048c20 <_ZN8IntArray4initEPKii> 8048b15: 83 c4 10 add $0x10,%esp 8048b18: c9 leave 8048b19: c3 ret 08048b1a <_ZN8IntArrayC1Ei>: 8048b1a: 55 push %ebp 8048b1b: 89 e5 mov %esp,%ebp 8048b1d: 83 ec 08 sub $0x8,%esp 8048b20: 8b 45 08 mov 0x8(%ebp),%eax 8048b23: c7 00 a8 a7 04 08 movl $0x804a7a8,(%eax) 8048b29: 8b 45 0c mov 0xc(%ebp),%eax 8048b2c: 89 45 fc mov %eax,0xfffffffc(%ebp) 8048b2f: c7 45 f8 00 00 00 00 movl $0x0,0xfffffff8(%ebp) 8048b36: 83 ec 04 sub $0x4,%esp 8048b39: ff 75 fc pushl 0xfffffffc(%ebp) 8048b3c: ff 75 f8 pushl 0xfffffff8(%ebp) 8048b3f: ff 75 08 pushl 0x8(%ebp) 8048b42: e8 d9 00 00 00 call 8048c20 <_ZN8IntArray4initEPKii> 8048b47: 83 c4 10 add $0x10,%esp 8048b4a: c9 leave 8048b4b: c3 ret
gnu bug reports: for gcc http://gcc.gnu.org/bugzilla/show_bug.cgi?id=3187 for gdb http://gcc.gnu.org/bugzilla/show_bug.cgi?id=10512
The 2 entry-points of a C++ constructor (in-charge vs. not-in-charge) is required by the ABI (http://www.codesourcery.com/cxx-abi/). gdb handles DWARF2 debugging information, if gdb shipped in RHEL3 doesn't handle multiple entry points, it is likely gdb's fault.
Changing product and version.
When I asked about fixing this in gdb the response was "maybe in RHEL 4". There is some chance that it can be fixed in gcc with a decloning patch described here: http://gcc.gnu.org/ml/gcc-patches/2002-08/msg00354.html I asked gcc folks about this last month, but I've not been able to persue it. I'll try to get this issue moving again.
After a further interview with Jason Merrill, it turns out that the patch mentioned above won't address the problem.
So this issue should be removed from the U3 blocker list and added to the U4 one? Just trying to close the loop and get U3 out the door.
A patch has been applied to gdb as of release .48 to expose the multiple constructors and destructors for the purpose of setting breakpoints. The "new" constructor will have the regular name. The base constructor will have $base appended to the constructor name, and the allocation constructor will have $allocate appended. For example, if the constructor is A::A(), the end-user can set breakpoints on A::A(), A::A$base(), and A::$allocate(). Using single-quotes and the tab key will show what constructors there are (usually just the new constructor and base constructor). The base constructor is called when an inheriting class runs its constructor. It is recommended that the end-user apply breakpoints to all versions of the constructor that exist. There are likewise, 3 destructor names. Regular, $base, and $delete. Again, the single-quote and tab-key can be used to expose the names or the breakpoints can be set explicitly. Additional work is required in gdb internals to make this transparent to the end-user (i.e. so only one breakpoint is set using the regular constructor/destructor names). For the mean-time, this patch will allow debugging to work.
An advisory has been issued which should help the problem described in this bug report. This report is therefore being closed with a resolution of ERRATA. For more information on the solution and/or where to find the updated files, please follow the link below. You may reopen this bug report if the solution does not work for you. http://rhn.redhat.com/errata/RHBA-2004-561.html
client does not feel that the original problem she reported has been resolved - reopening ******************************************************* I have another very simple example of the mismatch between the native compiler and the native debugger on RedHat EL3. In this example, the debugger WILL NOT stop at a valid breakpoint. The breakpoint is set in a constructor; the constructor is *declared* in a header file, but *defined* in a .C file. The interesting thing is that if the program is built on RedHat 7.2, then it can be successfully debugged on RHEL3. *HOWEVER* if the program is built on RHEL3, then it will not stop on breakpoints set on line numbers. If you look at the debug symbol tables generated by the two systems, they are very different. On RH 7.2 -g produces the SAME debug information as -gstabs+. On RHEL3 -g produces the SAME debug information as -gdwarf-2. However, the -gstabs+ information produced on RHEL3 is *NOT THE SAME* as the -gstabs+ generated on RH 7.2. PLEASE try it yourself. Build it simply like this: c++ -g A.C main.C -o test.schizo Here are some examples: ------------------------------------------------------------------------------ Built on RH 7.2, debugged on RH 7.2: [psycho:134] gdb test.g.psycho GNU gdb Red Hat Linux 7.x (5.0rh-15) (MI_OUT) Copyright 2001 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux"... (gdb) b 'A::A(void)' Breakpoint 1 at 0x8048759: file A.C, line 6. (gdb) r Starting program: /wv/cst1/qa/project/tests/sst/GdbTestCase/evelyn/test.g.psycho Before A ctor Breakpoint 1, A::A (this=0x8049c00) at A.C:6 6 int foobar = 0; (gdb) b 11 Breakpoint 2 at 0x804876d: file A.C, line 11. (gdb) c Continuing. Breakpoint 2, A::A (this=0x8049c00) at A.C:11 11 foobar = foo * bar; (gdb) quit ** Note that it successfully stops on line 11 in the A::A constructor. ------------------------------------------------------------------------------ Built on RH 7.2, debugged on RHEL 3: [schizo:147] gdb test.g.psycho GNU gdb Red Hat Linux (6.1post-1.20040607.52rh) Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) b 'A::A(void)' Breakpoint 1 at 0x8048759: file A.C, line 6. (gdb) r Starting program: /wv/cst1/qa/project/tests/sst/GdbTestCase/evelyn/test.g.psycho Before A ctor Breakpoint 1, A::A (this=0x8049c00) at A.C:6 6 int foobar = 0; (gdb) b 11 Breakpoint 2 at 0x804876d: file A.C, line 11. (gdb) c Continuing. Breakpoint 2, A::A (this=0x8049c00) at A.C:11 11 foobar = foo * bar; (gdb) quit ** Note that it successfully stops on line 11 in the A::A constructor. ------------------------------------------------------------------------------ Built on RHEL 3, debugged on RHEL 3: [schizo:149] gdb test.g.schizo GNU gdb Red Hat Linux (6.1post-1.20040607.52rh) Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) b 'A:: A::A$base() A::A() A::callme() A::~A$base() A::~A() (gdb) b 'A::A()' Breakpoint 1 at 0x80487d0: file A.C, line 5. (gdb) r Starting program: /wv/cst1/qa/project/tests/sst/GdbTestCase/evelyn/test.g.schizo Before A ctor Breakpoint 1, A (this=0x8049f50) at A.C:6 6 int foobar = 0; (gdb) b 11 Breakpoint 2 at 0x8048784: file A.C, line 11. (gdb) c Continuing. In ctor ; foobar = 200 After A ctor In callme After callme Program exited normally. (gdb) ** Note that it *DOES NOT STOP* on line 11 in the A::A constructor. ------------------------------------------------------------------------------ she then followed-up in a voicemail stating that when she compiled this second test case on 7.2 using the GNUPRO 03R1 compiler, which is gcc3.2 based, and tried to debug under the GNUPRO 03R1 GDB, it also fails like above. So she feels that her original assertion was correct when she opened this ticket almost a year ago in that the debuug symbol table being generated by 3.2 based GCC is mismatched and doesn't work w/ current GDB versions.
Created attachment 109682 [details] new test case provided by client
I have reproduced the problem. What is happening is that it is yet another problem with gcc creating two versions of the constructor with the same name at different locations. When you set the breakpoint at line 11, it is setting this in the function based on the current file you are in. In this case it finds the first A::A which is A::A$base (i.e. the base constructor called by classes which inherit A). You are running A::A and so never hit the breakpoint. I am looking into a fix for this.
update provided by client: --------------------------- I can't seem to figure out how to force the debugger to stop on that line. (I even tried building gdb 6.3) Here is another thing I tried: ------------------------------------------------------------------------------ [schizo:154] gdb test.g.schizo GNU gdb Red Hat Linux (6.1post-1.20040607.52rh) Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) b 'A::A A::A$base() A::A() (gdb) b 'A::A$base()' Breakpoint 1 at 0x804876a: file A.C, line 5. (gdb) b 'A::A A::A$base() A::A() (gdb) b 'A::A()' Breakpoint 2 at 0x80487d0: file A.C, line 5. (gdb) r Starting program: /wv/cst1/qa/project/tests/sst/GdbTestCase/evelyn/test.g.schizo Before A ctor Breakpoint 2, A (this=0x8049f50) at A.C:6 6 int foobar = 0; (gdb) s 8 foo = 10; (gdb) s 9 bar = 20; (gdb) b 11 Breakpoint 3 at 0x8048784: file A.C, line 11. (gdb) c Continuing. In ctor ; foobar = 200 After A ctor In callme After callme Program exited normally. (gdb) quit
You would have to break by address. If you do a readelf -wl on the executable you will notice that the constructor is repeated in the line table. Gdb looks for line 11 in the file and finds essentially the first reference. It can't just always look forward for another line 11 as you will note that multiple instructions can make up line 11 and with optimization line 11 can be strewn about the executable. In this case, the first line 11 is in the base constructor which is not getting called in your run of the executable. What you can do is note the difference between the line 11 breakpoint and the A$base() breakpoint. Next add that difference to the A() breakpoint address to give you the address you want to break at. It is extremely ugly, but it does work around the problem in the sample program. Remember to specify b *0x.... where 0x..... is the calculated address. When you reach the breakpoint, gdb prints out line 11 as desired.
A patch has been built into gdb as of gdb-6.3.0.0-0.7 The following is an excerpt of running the test program with the new patch. Breakpoint 1, main () at main.C:5 5 int foo = 1; (gdb) b 'A::A A::A$base() A::A() (gdb) b 'A::A()' Breakpoint 2 at 0x8048bc0: file a.C, line 5. (gdb) c Continuing. Before A ctor Breakpoint 2, A (this=0x9f85008) at a.C:6 6 int foobar = 0; (gdb) b 11 Breakpoint 3 at 0x8048b74: file a.C, line 11. Breakpoint 4 at 0x8048bda: file a.C, line 11. warning: Multiple breakpoints were set. warning: Use the "delete" command to delete unwanted breakpoints. (gdb) c Continuing. Breakpoint 4, A (this=0x9f85008) at a.C:11 11 foobar = foo * bar; (gdb) c Continuing. In ctor ; foobar = 200 After A ctor In callme After callme Program exited normally. (gdb) quit
feedback from client on her 6.1post-1.20040607.52.3 testing: ------------------------------------------------------------------------------------------- Dave- This latest version of gdb appears to fix the breakpointing problems, but not the local variable display problems. So we are closer, but not done yet. Here is the new gdb, run on RHEL3, using the second testcase produced on a RH 7.2 system: [schizo:124] gdb test.g.psycho GNU gdb Red Hat Linux (6.1post-1.20040607.52.3rh) Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) b 'A::A(void)' Breakpoint 1 at 0x8048759: file A.C, line 6. (gdb) r Starting program: /wv/cst1/qa/project/tests/sst/GdbTestCase/evelyn/test.g.psycho Before A ctor Breakpoint 1, A::A (this=0x8049c00) at A.C:6 6 int foobar = 0; (gdb) b 11 Breakpoint 2 at 0x804876d: file A.C, line 11. (gdb) c Continuing. Breakpoint 2, A::A (this=0x8049c00) at A.C:11 11 foobar = foo * bar; (gdb) s 13 cout << "In ctor ; foobar = " << foobar << endl; (gdb) p foobar $1 = 200 (gdb) c Continuing. In ctor ; foobar = 200 After A ctor In callme After callme Program exited normally. (gdb) q ------------------------------------------------------------------------------ Here is the same test, but compiled on RHEL3, using the new gdb: [schizo:130] gdb test.g.schizo GNU gdb Red Hat Linux (6.1post-1.20040607.52.3rh) Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) b 'A::A A::A$base() A::A() (gdb) b 'A::A()' Breakpoint 1 at 0x80487d0: file A.C, line 5. (gdb) r Starting program: /wv/cst1/qa/project/tests/sst/GdbTestCase/evelyn/test.g.schizo Before A ctor Breakpoint 1, A (this=0x8049f50) at A.C:6 6 int foobar = 0; (gdb) b 11 Breakpoint 2 at 0x8048784: file A.C, line 11. Breakpoint 3 at 0x80487ea: file A.C, line 11. warning: Multiple breakpoints were set. warning: Use the "delete" command to delete unwanted breakpoints. (gdb) c Continuing. Breakpoint 3, A (this=0x8049f50) at A.C:11 11 foobar = foo * bar; (gdb) s 13 cout << "In ctor ; foobar = " << foobar << endl; (gdb) p foobar No symbol "foobar" in current context. (gdb) p foo $1 = 10 (gdb) p bar $2 = 20 (gdb) c Continuing. In ctor ; foobar = 200 After A ctor In callme After callme Program exited normally. (gdb) q
An update. The 3.2.3 compiler was not generating sufficient debug info for gdb to find the local variable foobar in the "in-charge" constructor. It was generating information about the variable in the "not-in-charge" constructor (one that that gets called by an inheriting classes constructor). I had noticed that the 3.4.3 compiler "was" generating the correct information and the fixes I have been making above work with the test case. Note that with optimization, the variable foobar is removed by the compiler and the cout statement is reduced to use a constant of 200 (i.e. gdb will not find foobar in this case). A backport of gcc code has been made and a fix has been built into gcc-3.2.3-51. I have confirmed that gdb can break in both constructors, break by line in both constructors, and that foobar prints correctly.
Please, see bugzilla 146416.
An advisory has been issued which should help the problem described in this bug report. This report is therefore being closed with a resolution of ERRATA. For more information on the solution and/or where to find the updated files, please follow the link below. You may reopen this bug report if the solution does not work for you. http://rhn.redhat.com/errata/RHBA-2005-187.html