With gcc 4.0 checked out at Tue Dec 21 23:14:35 UTC 2004, I got [hjl@gnu-10 thread]$ gdb gdb GNU gdb 6.3.0.90_2004-12-14-cvs 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 "i686-pc-linux-gnu"...Using host libthread_db library "/lib/tls/libthread_db.so.1". Setting up the environment for debugging gdb. Breakpoint 1 at 0x8084ce3: file /net/gnu/export/gnu/src/gdb-6.3/gdb/gdb/utils.c, line 849. Breakpoint 2 at 0x80af162: file /net/gnu/export/gnu/src/gdb-6.3/gdb/gdb/cli/cli-cmds.c, line 193. (top-gdb) r /export/build/gnu/gcc/build-i686-linux/gcc/cc1 Starting program: /usr/local/bin/gdb /export/build/gnu/gcc/build-i686-linux/gcc/cc1 GNU gdb 6.3.0.90_2004-12-14-cvs 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 "i686-pc-linux-gnu"...Using host libthread_db library "/lib/tls/libthread_db.so.1". Setting up the environment for debugging gdb. Breakpoint 1 at 0x812d410: file /net/gnu/export/gnu/src/gcc/gcc/gcc/diagnostic.c, line 496. Function "info_command" not defined. (top-gdb) b tls_symbolic_operand Breakpoint 2 at 0x826c1d0: file insn-preds.c, line 471. (top-gdb) r -fpreprocessed foo.i -quiet -dumpbase foo.i -mtune=pentiumpro -auxbase foo -O -version -o foo.s Starting program: /export/build/gnu/gcc/build-i686-linux/gcc/cc1 -fpreprocessed foo.i -quiet -dumpbase foo.i -mtune=pentiumpro -auxbase foo -O -version -o foo.sDetaching after fork from child process 6975. Detaching after fork from child process 6976. GNU C version 4.0.0 20041221 (experimental) (i686-pc-linux-gnu) compiled by GNU C version 4.0.0 20041221 (experimental). GGC heuristics: --param ggc-min-expand=97 --param ggc-min-heapsize=127207 Program received signal SIGSEGV, Segmentation fault. dwarf_expr_frame_base (baton=0xbfffecf0, start=0xbfffec90, length=0xbfffec94) at /net/gnu/export/gnu/src/gdb-6.3/gdb/gdb/dwarf2loc.c:171 171 *length = symbaton->size; (top-gdb) p symbaton $1 = (struct dwarf2_locexpr_baton *) 0x0 [hjl@gnu-10 gcc]$ readelf -w insn-preds.o > /dev/null readelf: Error: Not enough comp units for .debug_loc section [hjl@gnu-10 gcc]$ readelf -w stage1/insn-preds.o > /dev/null It seems that gcc 4.0 generates incorrect .debug_loc section.
A simple testcase: [hjl@gnu-10 gcc]$ cat foo.c extern char *array; void foo (unsigned int array_members) { unsigned int i; for (i = 0; i < array_members; i++) array[i] = i % 128; } [hjl@gnu-10 gcc]$ ./xgcc -B./ -g -O -c foo.c -fomit-frame-pointer [hjl@gnu-10 gcc]$ readelf -w foo.o > /dev/null readelf: Error: Not enough comp units for .debug_loc section -fomit-frame-pointer may cause gcc to generate .debug_loc section gdb can't handle.
It has nothing to do with -fomit-frame-pointer: [hjl@gnu-10 gcc]$ cat foo.c extern char *array; void foo (unsigned int array_members) { unsigned int i; for (i = 0; i < array_members; i++) array[i] = i % 128; } [hjl@gnu-10 gcc]$ ./xgcc -B./ -g -O -c foo.c [hjl@gnu-10 gcc]$ readelf -w foo.o > /dev/null readelf: Error: Not enough comp units for .debug_loc section
Are you sure that this is not a gdb bug? Also gdb should not being crashing did you at least file a gdb bug? also is this a readelf bug?
One more thing, we now produce variable tracking which I hear don't get along well with gdb or readelf so I assume -fno-var-tracking will get rid of the seg fault but at that point, the seg fault becomes a gdb bug and not a gcc one, I am assuming that gcc is outputting correct dwarf-2 (which it is known to as far as I know). If gdb cannot really handle var-tracking, we can disable it for 4.0 since it is a new feature but it was an important one which was did not make into 3.4.0 because it got reviewed too late.
If gdb can't handle var-tracking, it should be fixed there, and not be disabeld in gcc.
The bug is in both readelf and a gcc bug. The warning in readelf is a bug. One can see by looking at the assembly that their is exactly one debug_loc section, and exactly one debug_info section, in the object file. Thus, the bug is cleraly in readelf. Looking at the readelf source shows the bug quite clearly in display_debug_loc: It assumes that each compilation unit only has one location list. It has an outer loop going through the entire debug_loc section, and increments comp_unit and breaks the inner loop when begin && end == 0, so that a unit with more than one location list will always issue this warning. However, the begin and end == 0 means it's the end of the location list, not the end of the *debug_loc* section, or the debug_loc section for a given compilation unit. There are no terminators in debug_loc for each compilation unit that gets info from debug_loc, so this code can't work as written. In short, there is no backpointer from location list to compilation unit, or way to get a cu number from counting location lists in the section, so randomly incrementing the comp_unit number and then saying "we can't find compilation unit 1" when the location list is clearly referenced from unit 0, is a bogus warning. The only true way to fix this is to get the list of location lists for a given compilation unit from the debug info dies, then printing them separately (or you could print them inline as you see them). So as of right now, the readelf code is broken. The gdb problem (and i'm guessing this is the cause) appears to be a gcc one. What happens is that one entry our location list ends up spanning a basic block, but a no actual instructions, apparently. .LVL2: .L4: # basic block 2 .LVL3: This makes the beginning and end ranges of the location list entry the same, which is invalid according to the standard (which specifies that the ending address *must* be greated than the beginning address. See 2.5.4 in the dwarf3 standard) I'm guessing this is what cuases gdb problems. At least, that's the only thing visibly wrong with the dwarf2 output. I will see if i can fix this in gcc.
Patch here: <http://gcc.gnu.org/ml/gcc-patches/2004-12/msg01984.html>.
With the patch applied, gdb 6.3 still dumps core.
Subject: Re: [4.0 regression] gcc generates incorrect dwarf2 debug info On Tue, 2004-12-28 at 18:37 +0000, hjl at lucon dot org wrote: > ------- Additional Comments From hjl at lucon dot org 2004-12-28 18:37 ------- > With the patch applied, gdb 6.3 still dumps core. > With the patch applied, we generate correct debug info for the case you pasted. I can do nothing more on the gcc side. In fact, I'm seriously considering *not* applying this patch, because we still can't guarantee that the base and end addresses won't end up different anyway. I'm soliciting opinions from gdb folks and the dwarf2 reflector folks as we speak, and based on what they say, i'll either apply the patch or close as wontfix. In any regard, there is a gdb bug here somewhere that needs to be fixed.
While fixing the readelf bug: http://sources.redhat.com/bugzilla/show_bug.cgi?id=615 I added a warning for bad location list. Even with your gcc patch applied, I still get [hjl@gnu-10 gcc]$ /export/build/linux/binutils-debug/build-i686- linux/binutils/readelf -w insn-preds.o > /dev/null readelf: Warning: Bad location list at 00000d3d from 00000a72 to 00000a72 I will see what I can do with gdb.
Subject: Re: [4.0 regression] gcc generates incorrect dwarf2 debug info After talking with gdb folks and dwarf2 folks (who say this isn't the actual bug, there is some other gdb bug causing the crashes, because it doesn't depend on the end and base addresses being different), i'm going to close this as WONTFIX. It's impossible for us to generate location lists with a end address > base address, and nothing with any brainpower would depend on it :) > > ------- Additional Comments From hjl at lucon dot org 2004-12-30 03:38 ------- > While fixing the readelf bug: > > http://sources.redhat.com/bugzilla/show_bug.cgi?id=615 > > I added a warning for bad location list. Even with your gcc patch applied, I > still get > > [hjl@gnu-10 gcc]$ /export/build/linux/binutils-debug/build-i686- > linux/binutils/readelf -w insn-preds.o > /dev/null > readelf: Warning: Bad location list at 00000d3d from 00000a72 to 00000a72 > > I will see what I can do with gdb.
insn-preds.o was compiled with stage2/xgcc -Bstage2/ -B/usr/gcc-4.0/i686-pc-linux-gnu/bin/ -c -O2 -g -fomit- frame-pointer -DIN_GCC -W -Wall -Wwrite-strings -Wstrict-prototypes - Wmissing-prototypes -pedantic -Wno-long-long -Wno-variadic-macros -Wold-style- definition -Werror -DHAVE_CONFIG_H -I. -I. - I/net/gnu/export/gnu/src/gcc/gcc/gcc -I/net/gnu/export/gnu/src/gcc/gcc/gcc/. - I/net/gnu/export/gnu/src/gcc/gcc/gcc/../include - I/net/gnu/export/gnu/src/gcc/gcc/gcc/../libcpp/include insn-preds.c -o insn- preds.o It generates <1><418c>: Abbrev Number: 47 (DW_TAG_subprogram) DW_AT_sibling : <41c6> DW_AT_external : 1 DW_AT_name : (indirect string, offset: 0x3133): tls_symbolic_operand DW_AT_decl_file : 1 DW_AT_decl_line : 471 DW_AT_prototyped : 1 DW_AT_type : <2c> DW_AT_low_pc : 0x2f0 DW_AT_high_pc : 0x31c <2><41a6>: Abbrev Number: 48 (DW_TAG_formal_parameter) DW_AT_name : op DW_AT_decl_file : 1 DW_AT_decl_line : 470 DW_AT_type : <2dc> DW_AT_location : 549 (location list) <2><41b5>: Abbrev Number: 49 (DW_TAG_formal_parameter) DW_AT_name : (indirect string, offset: 0x44e5): mode DW_AT_decl_file : 1 DW_AT_decl_line : 470 DW_AT_type : <6be> DW_AT_location : 5a2 (location list) 00000549 000002f0 000002fe (DW_OP_fbreg: 4) 00000549 000002fe 00000300 (DW_OP_reg0) 00000549 00000300 00000301 (DW_OP_fbreg: 4) 00000549 00000301 0000030b (DW_OP_reg0) 00000549 0000030b 00000311 (DW_OP_fbreg: 4) 00000549 00000311 00000315 (DW_OP_reg0) 00000549 00000315 0000031c (DW_OP_fbreg: 4) 000005a2 000002f0 000002fe (DW_OP_fbreg: 8) 000005a2 000002fe 0000031c (DW_OP_reg2) There is no DW_AT_frame_base. According to DWARF 3 spec, DW_OP_fbreg needs DW_AT_frame_base.
Created attachment 7854 [details] Output from readelf -wio This is the output from readelf -wio for: struct foo_def { int code; int mode; }; extern int foo (struct foo_def *op, int mode); extern int bar (struct foo_def *op, int mode); int foo (struct foo_def *op, int mode __attribute__ ((__unused__))) { return op->code == 1 && (mode == 0 || op->mode == mode); } int bar (struct foo_def *op, int mode __attribute__ ((__unused__))) { return op->code == 1; } compiled with stage2/xgcc -Bstage2/ -mtune=pentiumpro -g -O2 -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -pedantic -Wno-long-long -Wno-variadic-macros -Wold-style-definition -Werror -fomit-frame-pointer x.c -c
Patch coming. This is also a latent bug forever in gcc. We've been generating fbreg for a lot of things we shouldn't, we just never noticed before now because it didn't try to evaluate them at runtime unless you outputted location lists. Thus, it simply statically converted the location expression fbregs into something it could evaluate, regardless of whether there was a real frame base or not.
(In reply to comment #5) > If gdb can't handle var-tracking, it should be fixed there, and not > be disabeld in gcc. Correct. GCC shouldn't hold back features due to a lack of support in GDB. See also http://sources.redhat.com/ml/gdb/2004-11/msg00085.html
Subject: Bug 19124 Please try the attached patch. It shouldn't generate a fbreg entry without a frame base ever anymore :) If it works, i'll add a changelog and submit it for approval.
Created attachment 7894 [details] mypatch.diff
Created attachment 7908 [details] Output from readelf -wio alias.o This is on Linux/x86. There are still many 0000203d 00001aa9 00001c79 (DW_OP_fbreg: 52) [without DW_AT_frame_base] 0000203d 00001c8e 00002178 (DW_OP_fbreg: 52) [without DW_AT_frame_base] 000029f6 00002cbe 00002ccc (DW_OP_fbreg: 32) [without DW_AT_frame_base] 000029f6 00002cfa 00002df3 (DW_OP_fbreg: 32) [without DW_AT_frame_base]
Created attachment 7909 [details] Output from readelf -wio alias.o This is on Linux/x86_64. I got 00004bb8 00002dc7 00002dd6 (DW_OP_fbreg: 16) [without DW_AT_frame_base] 00004bb8 00002dff 00002eec (DW_OP_fbreg: 16) [without DW_AT_frame_base]
Subject: Bug 19124 Okay, this is a modified version that should work. I'm a bit surprised the last one didn't work, but c'est la vie
Created attachment 7914 [details] d2fb.diff
Created attachment 7920 [details] Output from readelf -wio alias.o on Linux/ia32 There are still: 000029df 00002cbe 00002ccc (DW_OP_fbreg: 32) [without DW_AT_frame_base] 000029df 00002cfa 00002df3 (DW_OP_fbreg: 32) [without DW_AT_frame_base] on Linux/ia32.
Created attachment 7921 [details] Output from readelf -wio alias.o on Linux/x86_64 There are still 00004ba5 00002dc7 00002dd6 (DW_OP_fbreg: 16) [without DW_AT_frame_base] 00004ba5 00002dff 00002eec (DW_OP_fbreg: 16) [without DW_AT_frame_base] on Linux/x86_64.
Subject: Re: [4.0 regression] gcc generates incorrect dwarf2 debug info On Mon, 2005-01-10 at 16:39 +0000, hjl at lucon dot org wrote: > There are still: > > 000029df 00002cbe 00002ccc (DW_OP_fbreg: 32) [without DW_AT_frame_base] > 000029df 00002cfa 00002df3 (DW_OP_fbreg: 32) [without DW_AT_frame_base] > This makes no sense to me, since it won't say to use fbreg unless it is absolutely sure there is a frame_base there. Can you attach alias.i and give me the exact options you are using so i can reproduce this on my machine?
Created attachment 7922 [details] alias.i from Linux/x86 I used stage2/xgcc -Bstage2/ -B/usr/gcc-4.0/i686-pc-linux-gnu/bin/ -c -O2 -g -fomit-frame-pointer -DIN_GCC -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -pedantic -Wno-long-long -Wno-variadic-macros -Wold-style-definition -Werror -DHAVE_CONFIG_H -I. -I. -I/net/gnu/export/gnu/src/gcc/gcc/gcc -I/net/gnu/export/gnu/src/gcc/gcc/gcc/. -I/net/gnu/export/gnu/src/gcc/gcc/gcc/../include -I/net/gnu/export/gnu/src/gcc/gcc/gcc/../libcpp/include /net/gnu/export/gnu/src/gcc/gcc/gcc/alias.c to compile alias.o.
The patch is correct, the code printing "without DW_AT_frame_base" is wrong. Note that while the immediate container of the variable, the DW_TAG_inlined_subroutine, does not have a frame_base attribute, *it's* container, the DW_TAG_subprogram, does. The code i have int he patch notices this. In other words, there is a frame base that should be associated with this location list. I see nothing in the standard that disallows this, though i'm happy to ask the standards committee mailing list if you believe i am in error :)
"[without DW_AT_frame_base]" is very much informational and it may not be correct.
Created attachment 7924 [details] Output from readelf -wio tree-chrec.o on Linux/ia32 I updated readelf. I saw 00000b58 00000792 000007a8 (DW_OP_fbreg: 36) [without DW_AT_frame_base] 00000b58 000007fd 00000866 (DW_OP_fbreg: 36) [without DW_AT_frame_base] 00000beb 00000792 000007a8 (DW_OP_fbreg: 40) [without DW_AT_frame_base] 00000beb 00000840 00000866 (DW_OP_fbreg: 40) [without DW_AT_frame_base] 00000beb 000008ea 00000932 (DW_OP_fbreg: 40) [without DW_AT_frame_base] 00000c40 00000792 000007a8 (DW_OP_fbreg: 28) [without DW_AT_frame_base] 00000c40 00000840 00000866 (DW_OP_fbreg: 28) [without DW_AT_frame_base] 00000c40 00000a7c 00000b1a (DW_OP_fbreg: 28) [without DW_AT_frame_base] 00000c95 00000792 000007a8 (DW_OP_fbreg: 32) [without DW_AT_frame_base] 00000c95 00000840 00000866 (DW_OP_fbreg: 32) [without DW_AT_frame_base] 00000c95 00000a12 00000b1a (DW_OP_fbreg: 32) [without DW_AT_frame_base] 00000cea 00000792 000007a8 (DW_OP_fbreg: 20) [without DW_AT_frame_base] 00000cea 00000840 00000866 (DW_OP_fbreg: 20) [without DW_AT_frame_base] 00000cea 00000b25 00000b6d (DW_OP_fbreg: 20) [without DW_AT_frame_base] 00000ffa 00000c29 00000c46 (DW_OP_fbreg: 52) [without DW_AT_frame_base] 00000ffa 00000d9b 00000dc1 (DW_OP_fbreg: 52) [without DW_AT_frame_base] 00000ffa 00000df8 00000e44 (DW_OP_fbreg: 52) [without DW_AT_frame_base] 0000104f 00000c29 00000c46 (DW_OP_fbreg: 48) [without DW_AT_frame_base] 0000104f 00000cba 00000d23 (DW_OP_fbreg: 48) [without DW_AT_frame_base] 0000108d 00000c29 00000c46 (DW_OP_fbreg: 56) [without DW_AT_frame_base] 0000108d 00000d54 00000dc1 (DW_OP_fbreg: 56) [without DW_AT_frame_base] 000010cb 00000c29 00000c46 (DW_OP_fbreg: 44) [without DW_AT_frame_base] 000010cb 00000cfd 00000d23 (DW_OP_fbreg: 44) [without DW_AT_frame_base] 000010cb 00000e4f 00000e97 (DW_OP_fbreg: 44) [without DW_AT_frame_base] 000012f8 00000c29 00000c46 (DW_OP_fbreg: 28) [without DW_AT_frame_base] 000012f8 00000d9b 00000dc1 (DW_OP_fbreg: 28) [without DW_AT_frame_base] 000012f8 00001032 0000107e (DW_OP_fbreg: 28) [without DW_AT_frame_base] 0000134d 00000c29 00000c46 (DW_OP_fbreg: 36) [without DW_AT_frame_base] 0000134d 00000cfd 00000d23 (DW_OP_fbreg: 36) [without DW_AT_frame_base] 0000134d 000010be 00001106 (DW_OP_fbreg: 36) [without DW_AT_frame_base]
Created attachment 7925 [details] Processed tree-chrec.i I am using stage2/xgcc -Bstage2/ -B/usr/gcc-4.0/i686-pc-linux-gnu/bin/ -c -O2 -g -fomit-frame-pointer -DIN_GCC -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -pedantic -Wno-long-long -Wno-variadic-macros -Wold-style-definition -Werror -DHAVE_CONFIG_H -I. -I. -I/net/gnu/export/gnu/src/gcc/gcc/gcc -I/net/gnu/export/gnu/src/gcc/gcc/gcc/. -I/net/gnu/export/gnu/src/gcc/gcc/gcc/../include -I/net/gnu/export/gnu/src/gcc/gcc/gcc/../libcpp/include /net/gnu/export/gnu/src/gcc/gcc/gcc/tree-chrec.c
Subject: Re: [4.0 regression] gcc generates incorrect dwarf2 debug info On Mon, 2005-01-10 at 21:41 +0000, hjl at lucon dot org wrote: > ------- Additional Comments From hjl at lucon dot org 2005-01-10 21:41 ------- > Created an attachment (id=7924) > --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=7924&action=view) > Output from readelf -wio tree-chrec.o on Linux/ia32 > > I updated readelf. I saw > > 00000b58 00000792 000007a8 (DW_OP_fbreg: 36) [without DW_AT_frame_base] > 00000b58 000007fd 00000866 (DW_OP_fbreg: 36) [without DW_AT_frame_base] If you look at the parent of this DIE's parent, you'll see <1><2b83>: Abbrev Number: 40 (DW_TAG_subprogram) DW_AT_sibling : <2d2b> DW_AT_external : 1 DW_AT_name : (indirect string, offset: 0x2ba2): chrec_fold_multiply DW_AT_decl_file : 1 DW_AT_decl_line : 332 DW_AT_prototyped : 1 DW_AT_type : <2dd> DW_AT_low_pc : 0x6d0 DW_AT_high_pc : 0xb6d DW_AT_frame_base : 0x8f9 (location list) (the first number is the nesting level)
readelf may have false postives on [without DW_AT_frame_base]. I will leave it there.
Subject: Bug 19124 CVSROOT: /cvs/gcc Module name: gcc Changes by: dberlin@gcc.gnu.org 2005-01-20 20:09:23 Modified files: gcc : ChangeLog dwarf2out.c Log message: 2005-01-20 Daniel Berlin <dberlin@dberlin.org> Fix PR debug/19124 * dwarf2out.c (concat_loc_descriptor): We don't know we can use fbreg, so we have to assume we can't. (loc_descriptor_from_tree_1): Ditto. (containing_function_has_frame_base): New function. (add_location_or_const_value_attribute): Use it. Also try to generate a frame_base from a single element location list. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.7205&r2=2.7206 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/dwarf2out.c.diff?cvsroot=gcc&r1=1.567&r2=1.568
Fixed