From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 29162 invoked by alias); 29 Nov 2003 20:26:10 -0000 Mailing-List: contact gdb-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sources.redhat.com Received: (qmail 28918 invoked from network); 29 Nov 2003 20:26:06 -0000 Received: from unknown (HELO fred.ninemoons.com) (68.14.214.217) by sources.redhat.com with SMTP; 29 Nov 2003 20:26:06 -0000 Received: from fred.ninemoons.com (fred.ninemoons.com [127.0.0.1]) by fred.ninemoons.com (8.12.8/8.12.8) with ESMTP id hATKQ4LX025807; Sat, 29 Nov 2003 13:26:04 -0700 Received: (from fnf@localhost) by fred.ninemoons.com (8.12.8/8.12.8/Submit) id hATKQ3OI025805; Sat, 29 Nov 2003 13:26:03 -0700 From: Fred Fish Message-Id: <200311292026.hATKQ3OI025805@fred.ninemoons.com> Subject: [RFC] Possible gcc/DWARF or gdb/DWARF problem To: gcc-bugs@gcc.gnu.org Date: Sat, 29 Nov 2003 20:26:00 -0000 Cc: gdb@sources.redhat.com, fnf@ninemoons.com Reply-To: fnf@ninemoons.com MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-SW-Source: 2003-11/txt/msg00295.txt.bz2 While chasing a gdb testsuite failure for the sh-elf toolchain, I discovered a problem printing a local variable that appears to be either a generic gcc bug in how it generates DWARF2 info for the local variable, or perhaps a gdb bug in how gdb interprets the DWARF2 information. I've done a quick check of the 2.0.0 revision of the DWARF industry review draft of the DWARF standard and I didn't see anything obvious that relates to this particular situation. But it has been years since I did any serious low level DWARF hacking so I could have easily missed something. Consider the following code, simplified from some "scope" tests in the gdb testsuite: signed char bar (register signed char u) { return (u + 1); } signed char foo (register signed char u) { register signed char l = u; l = bar (l); return (l); } main () { foo (3); } Note that: (1) the register declarations are required to expose the bug. Without them, the generated code and debug information is different and the problem goes away. (2) The example should be compiled without optimization. (3) The problem is masked if the target is little endian. Toolchains such as sh-elf or mipsisa32-elf which are bi-endian help to demonstrate this. Here is an example using the sh-elf toolchain in big endian mode. Note that the value of 'l' after being assigned from 'u' and before calling bar() is printed as 0 and should be 3, the same as 'u': $ sh-elf-gcc -g -m4 -mb -o b b.c $ sh-elf-gdb b GNU gdb 2003-11-29-cvs Copyright 2003 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 "--host=i686-pc-linux-gnu --target=sh-elf"... (gdb) tar sim Connected to the simulator. (gdb) load Loading section .init, size 0x36 vma 0x1000 Loading section .text, size 0x1900 vma 0x1040 Loading section .fini, size 0x2a vma 0x2940 Loading section .rodata, size 0x1e vma 0x296c Loading section .data, size 0x798 vma 0x2a0c Loading section .eh_frame, size 0x4 vma 0x31a4 Loading section .ctors, size 0x8 vma 0x31a8 Loading section .dtors, size 0x8 vma 0x31b0 Loading section .jcr, size 0x4 vma 0x31b8 Loading section .got, size 0xc vma 0x31bc Loading section .stack, size 0x4 vma 0x30000 Start address 0x1040 Transfer rate: 68080 bits/sec. (gdb) br foo Breakpoint 1 at 0x1186: file b.c, line 8. (gdb) run Starting program: /tmp/b Breakpoint 1, foo (u=3 '\003') at b.c:8 8 register signed char l = u; (gdb) n 10 l = bar (l); (gdb) p l $1 = 0 '\0' (gdb) If however we use little endian mode, the value is printed correctly: $ sh-elf-gcc -g -m4 -ml -o b b.c $ sh-elf-gdb b GNU gdb 2003-11-29-cvs Copyright 2003 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 "--host=i686-pc-linux-gnu --target=sh-elf"... (gdb) tar sim Connected to the simulator. (gdb) load Loading section .init, size 0x36 vma 0x1000 Loading section .text, size 0x1900 vma 0x1040 Loading section .fini, size 0x2a vma 0x2940 Loading section .rodata, size 0x1e vma 0x296c Loading section .data, size 0x798 vma 0x2a0c Loading section .eh_frame, size 0x4 vma 0x31a4 Loading section .ctors, size 0x8 vma 0x31a8 Loading section .dtors, size 0x8 vma 0x31b0 Loading section .jcr, size 0x4 vma 0x31b8 Loading section .got, size 0xc vma 0x31bc Loading section .stack, size 0x4 vma 0x30000 Start address 0x1040 Transfer rate: 68080 bits/sec. (gdb) br foo Breakpoint 1 at 0x1186: file b.c, line 8. (gdb) run Starting program: /tmp/b Breakpoint 1, foo (u=3 '\003') at b.c:8 8 register signed char l = u; (gdb) n 10 l = bar (l); (gdb) p l $1 = 3 '\003' (gdb) The problem is that the live value of 'l' at the time we print it is on the stack, and the address computed from the dwarf information is for the lowest address of the 4 byte stack slot that holds the character value. In the big endian case, this is for the most significant byte, which is zero. In the little endian case, this is for the least significant byte, which is 3. Note also that the dwarf info is identical for either endian: $ sh-elf-gcc -g -m4 -mb -c b.c $ dwarfdump -a b.o >b.o.mb $ sh-elf-gcc -g -m4 -ml -c b.c $ dwarfdump -a b.o >b.o.ml $ diff b.o.mb b.o.ml The code is also identical except for a pseudo that indicates the endianness: $ sh-elf-gcc -g -m4 -mb -S b.c $ mv b.s b.s.mb $ sh-elf-gcc -g -m4 -ml -S b.c $ mv b.s b.s.ml $ diff b.s.mb b.s.ml 2a3 > .little $ diff -c b.s.mb b.s.ml *** b.s.mb 2003-11-29 13:00:08.000000000 -0700 --- b.s.ml 2003-11-29 13:00:16.000000000 -0700 *************** *** 1,5 **** --- 1,6 ---- .file "b.c" .text + .little .section .debug_abbrev,"",@progbits .Ldebug_abbrev0: .section .debug_info,"",@progbits $ For reference, here are the relevant parts of the dwarfdump output: <1>< 107> DW_TAG_base_type DW_AT_name signed char DW_AT_byte_size 1 DW_AT_encoding DW_ATE_signed_char <2>< 160> DW_TAG_variable DW_AT_name l DW_AT_decl_file 1 /tmp/b.c DW_AT_decl_line 8 DW_AT_type <107> DW_AT_location DW_OP_fbreg 0 I'd like to get some comments on whether this is a gcc/DWARF or gdb/DWARF issue. If the consensus is that gdb is not doing the right thing, then I'll chase the problem in gdb. If the consensus is that it is gcc, then I'll file a formal gcc bug report. My guess is that since gcc is generating the memory offset of a 1 byte object relative to the frame pointer that the DW_AT_location for the big endian case should be: DW_AT_location DW_OP_fbreg 3 -Fred