From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10770 invoked by alias); 29 Apr 2009 18:29:07 -0000 Received: (qmail 10735 invoked by uid 22791); 29 Apr 2009 18:29:04 -0000 X-SWARE-Spam-Status: No, hits=-1.1 required=5.0 tests=AWL,BAYES_00,SPF_SOFTFAIL X-Spam-Check-By: sourceware.org Received: from mtaout7.012.net.il (HELO mtaout7.012.net.il) (84.95.2.19) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 29 Apr 2009 18:28:56 +0000 Received: from conversion-daemon.i-mtaout7.012.net.il by i-mtaout7.012.net.il (HyperSendmail v2007.08) id <0KIV00J00KNDM200@i-mtaout7.012.net.il> for gdb@sourceware.org; Wed, 29 Apr 2009 21:28:52 +0300 (IDT) Received: from HOME-C4E4A596F7 ([77.127.230.216]) by i-mtaout7.012.net.il (HyperSendmail v2007.08) with ESMTPA id <0KIV00ECZKNYVP80@i-mtaout7.012.net.il> for gdb@sourceware.org; Wed, 29 Apr 2009 21:28:48 +0300 (IDT) Date: Wed, 29 Apr 2009 18:39:00 -0000 From: Eli Zaretskii Subject: Debugging a frameless function To: gdb@sourceware.org Reply-to: Eli Zaretskii Message-id: <83zldzco0p.fsf@gnu.org> X-IsSubscribed: yes Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org X-SW-Source: 2009-04/txt/msg00216.txt.bz2 I'm trying to debug a problem in the DJGPP build of a recent GDB snapshot, whereby stepping into a function compiled with "-fomit-frame-pointer" throws an error: Cannot access memory at address 0x12 I reproduce below the test program and the transcript of a GDB session where I try to debug this. Any hints or ideas are welcome. TIA >From what I see, a call to read_reg in dwarf2_frame_cache, that tries to read the value of EBP, ends up calling sentinel_frame_prev_register, and from there eventually target_fetch_registers is called. But since we are in a frameless function, EBP holds a variable, not the frame pointer, so the value fetched by target_fetch_registers is 2, which later causes dwarf2_frame_this_id to call frame_id_build with the first argument whose value is 0x16, so the address of the stack in that frame is bogus. And that is what causes the above error message. When I run the same program on GNU/Linux, the problem does not happen. But the GNU/Linux box to which I have access is a 64-bit machine, so the architecture-dependent bits there are different, and I cannot easily compare what the code does on these two systems. My question is, how should GDB overcome the difficulty of a frameless function, when it tries to unwind a frame where EBP is used for holding a variable? Can someone please spot any missing pieces in the session below, and give me hints on where to look for the source of the trouble? I see other failures in the DJGPP port that somehow seem related to dwarf2-frame.c functions, so I believe solving this problem will let me solve others as well. The problem doesn't happen in the same program compiled with -gstabs+ rather than using DWARF2 debug info. Here's the program I used. Compile it with -g -O -fomit-frame-pointer to get the argument `n' of the function `foo' stored in EBP. --------------------------------- #include #include int foo (register int n) { register int i; register int a = n * 1; register int b = n * 2; register int c = n * 3; register int d = n * 4; register int e = n * 5; for (i = 0; i < n; i++) { if (i & 1) a = b + c; else a = c + e; if (i & 2) b = c + d; else b = d + a; if (i & 4) c = d + e; else c = e + b; if (i & 8) d = e + a; else d = a + c; if (i & 16) e = a + b; else e = b + d; } return a + b + c + d + e; } int main (int argc, char **argv) { if (argc == 2) printf ("%d\n", foo (atoi (argv[1]))); } --------------------------- And here is the debugging session mentioned above. I use GDB 6.1 to debug the April 10th snapshot: D:\usr\djgpp\gnu\gdb-68.410\gdb>d:\usr\djgpp\bin\gdb ./gdb.exe GNU gdb 6.1 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 "--host=i386-pc-msdosdjgpp --target=djgpp"... Setting up the environment for debugging gdb. During symbol reading, debug info gives macro definition outside of any file: __STDC_HOSTED__ 1. During symbol reading, no terminating 0-type entry for macros in `.debug_macinfo' section. Breakpoint 1 at 0x660f: file utils.c, line 993. Breakpoint 2 at 0xaae1: file .././gdb/cli/cli-cmds.c, line 199. (top-gdb) break dwarf2_frame_cache Breakpoint 3 at 0x11f9f2: file dwarf2-frame.c, line 874. (top-gdb) r --nx ./frame_d.exe Starting program: d:/usr/djgpp/gnu/gdb-68.410/gdb/./gdb.exe --nx ./frame_d.exe GNU gdb (GDB) 6.8.50.20090410 Copyright (C) 2009 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later 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 "--host=i586-pc-msdosdjgpp --target=djgpp". For bug reporting instructions, please see: ... (gdb) break foo Breakpoint 1 at 0x1680: file frameless.c, line 6. (gdb) r 2 Starting program: d:/usr/djgpp/gnu/gdb-68.410/gdb/./frame_d.exe 2 Breakpoint 3, dwarf2_frame_cache (this_frame=0x418dec, this_cache=0x418df0) at dwarf2-frame.c:874 874 struct gdbarch *gdbarch = get_frame_arch (this_frame); (top-gdb) c Continuing. Breakpoint 1, foo (n=588648) at frameless.c:6 6 { (gdb) n Breakpoint 3, dwarf2_frame_cache (this_frame=0x418dec, this_cache=0x418df0) at dwarf2-frame.c:874 874 struct gdbarch *gdbarch = get_frame_arch (this_frame); (top-gdb) n 875 const int num_regs = gdbarch_num_regs (gdbarch) (top-gdb) until 932 932 execute_cfa_program (fde, fde->instructions, fde->end, this_frame, fs); (top-gdb) n 935 switch (fs->cfa_how) (top-gdb) 938 cache->cfa = read_reg (this_frame, fs->cfa_reg); (top-gdb) s read_reg (baton=0x418dec, reg=5) at dwarf2-frame.c:277 277 struct gdbarch *gdbarch = get_frame_arch (this_frame); (top-gdb) n 281 regnum = gdbarch_dwarf2_reg_to_regnum (gdbarch, reg); (top-gdb) n 283 buf = alloca (register_size (gdbarch, regnum)); (top-gdb) p regnum $10 = 5 (top-gdb) n 284 get_frame_register (this_frame, regnum, buf); (top-gdb) s get_frame_register (frame=0x20, regnum=5, buf=0x3e84d0 "\005") at frame.c:653 653 frame_unwind_register (frame->next, regnum, buf); (top-gdb) s frame_unwind_register (frame=0x418da0, regnum=5, buf=0x3e84d0 "\005") at frame.c:645 645 frame_register_unwind (frame, regnum, &optimized, &lval, &addr, (top-gdb) s frame_register_unwind (frame=0x418da0, regnum=5, optimizedp=0x3e8488, lvalp=0x3e848c, addrp=0x3e8490, realnump=0x3e8494, bufferp=0x3e84d0 "\005") at frame.c:593 593 gdb_assert (optimizedp != NULL); (top-gdb) n 594 gdb_assert (lvalp != NULL); (top-gdb) 595 gdb_assert (addrp != NULL); (top-gdb) 596 gdb_assert (realnump != NULL); (top-gdb) 599 value = frame_unwind_register_value (frame, regnum); (top-gdb) s frame_unwind_register_value (frame=0x418da0, regnum=5) at frame.c:661 661 gdb_assert (frame != NULL); (top-gdb) n 663 if (frame_debug) (top-gdb) 673 if (frame->unwind == NULL) (top-gdb) 677 value = frame->unwind->prev_register (frame, &frame->prologue_cache , regnum); (top-gdb) s sentinel_frame_prev_register (this_frame=0x418da0, this_prologue_cache=0xbc9a4, regnum=5) at sentinel-frame.c:50 50 struct gdbarch *gdbarch = get_frame_arch (this_frame); (top-gdb) n 51 struct frame_unwind_cache *cache = *this_prologue_cache; (top-gdb) 55 value = allocate_value (register_type (gdbarch, regnum)); (top-gdb) 56 VALUE_LVAL (value) = lval_register; (top-gdb) 57 VALUE_REGNUM (value) = regnum; (top-gdb) 58 VALUE_FRAME_ID (value) = get_frame_id (this_frame); (top-gdb) 63 regcache_cooked_read (cache->regcache, regnum, value_contents_raw (v alue)); (top-gdb) s value_contents_raw (value=0x439ed0) at value.c:399 399 allocate_value_contents (value); (top-gdb) n 400 return value->contents + value->embedded_offset; (top-gdb) p value $12 = (struct value *) 0x439ed0 (top-gdb) p *value $13 = {lval = lval_register, modifiable = 1, location = {address = 0, internalvar = 0x0, computed = {funcs = 0x0, closure = 0x0}}, offset = 0, bitsize = 0, bitpos = 0, frame_id = {stack_addr = 0, code_addr = 0, special_addr = 0, stack_addr_p = 0, code_addr_p = 0, special_addr_p = 0}, type = 0x44ee48, enclosing_type = 0x44ee48, embedded_offset = 0, pointed_to_offset = 0, next = 0x0, regnum = 5, lazy = 0 '\0', optimized_out = 0 '\0', initialized = 1, contents = 0x439f28 ""} (top-gdb) n 401 } (top-gdb) s regcache_cooked_read (regcache=0x44f4d8, regnum=5, buf=0x439f28 "") at regcache.c:581 581 gdb_assert (regnum >= 0); (top-gdb) n 582 gdb_assert (regnum < regcache->descr->nr_cooked_registers); (top-gdb) p regcache->descr $14 = (struct regcache_descr *) 0x435dcc (top-gdb) p *regcache->descr $15 = {gdbarch = 0x435b00, nr_raw_registers = 32, sizeof_raw_registers = 240, sizeof_raw_register_valid_p = 40, nr_cooked_registers = 40, sizeof_cooked_registers = 240, sizeof_cooked_register_valid_p = 40, register_offset = 0x435fa8, sizeof_register = 0x435f08, register_type = 0x435df4} (top-gdb) n 583 if (regnum < regcache->descr->nr_raw_registers) (top-gdb) 584 regcache_raw_read (regcache, regnum, buf); (top-gdb) s regcache_raw_read (regcache=0x44f4d8, regnum=5, buf=0x439f28 "") at regcache.c:500 500 gdb_assert (regcache != NULL && buf != NULL); (top-gdb) n 501 gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registe rs); (top-gdb) 506 if (!regcache->readonly_p) (top-gdb) 508 if (!regcache_valid_p (regcache, regnum)) (top-gdb) 510 struct cleanup *old_chain = save_inferior_ptid (); (top-gdb) 511 inferior_ptid = regcache->ptid; (top-gdb) 512 target_fetch_registers (regcache, regnum); (top-gdb) p regnum $17 = 5 (top-gdb) s target_fetch_registers (regcache=0x44f4d8, regno=5) at target.c:2744 2744 for (t = current_target.beneath; t != NULL; t = t->beneath) (top-gdb) s 2746 if (t->to_fetch_registers != NULL) (top-gdb) 2748 t->to_fetch_registers (t, regcache, regno); (top-gdb) go32_fetch_registers (ops=0x347828, regcache=0x44f4d8, regno=5) at go32-nat.c:490 490 if (regno >= 0) (top-gdb) n 491 fetch_register (regcache, regno); (top-gdb) 500 } (top-gdb) target_fetch_registers (regcache=0x44f4d8, regno=5) at target.c:2749 2749 if (targetdebug) (top-gdb) 2754 } (top-gdb) regcache_raw_read (regcache=0x44f4d8, regnum=5, buf=0x439f28 "") at regcache.c:513 513 do_cleanups (old_chain); (top-gdb) 526 memcpy (buf, register_buffer (regcache, regnum), (top-gdb) 528 } (top-gdb) regcache_cooked_read (regcache=0x5, regnum=5, buf=0x439f28 "\002") at regcache.c:594 594 } (top-gdb) sentinel_frame_prev_register (this_frame=0x418da0, this_prologue_cache=0x5, regnum=5) at sentinel-frame.c:66 66 } (top-gdb) frame_unwind_register_value (frame=0x418da0, regnum=5) at frame.c:679 679 if (frame_debug) (top-gdb) 714 } (top-gdb) frame_register_unwind (frame=0x418da0, regnum=5, optimizedp=0x3e8488, lvalp=0x3e848c, addrp=0x3e8490, realnump=0x3e8494, bufferp=0x3e84d0 "\005") at frame.c:601 601 gdb_assert (value != NULL); (top-gdb) 603 *optimizedp = value_optimized_out (value); (top-gdb) 604 *lvalp = VALUE_LVAL (value); (top-gdb) 605 *addrp = VALUE_ADDRESS (value); (top-gdb) 606 *realnump = VALUE_REGNUM (value); (top-gdb) 608 if (bufferp) (top-gdb) 609 memcpy (bufferp, value_contents_all (value), (top-gdb) 614 release_value (value); (top-gdb) 615 value_free (value); (top-gdb) 616 } (top-gdb) frame_unwind_register (frame=0x418da0, regnum=5, buf=0x3e84d0 "\002") at frame.c:647 647 } (top-gdb) get_frame_register (frame=0x0, regnum=5, buf=0x3e84d0 "\002") at frame.c:654 654 } (top-gdb) read_reg (baton=0x418dec, reg=5) at dwarf2-frame.c:291 291 return unpack_long (register_type (gdbarch, regnum), buf); (top-gdb) 292 } (top-gdb) dwarf2_frame_cache (this_frame=0x418dec, this_cache=0x418df0) at dwarf2-frame.c:939 939 if (fs->armcc_cfa_offsets_reversed) (top-gdb) l 934 /* Calculate the CFA. */ 935 switch (fs->cfa_how) 936 { 937 case CFA_REG_OFFSET: 938 cache->cfa = read_reg (this_frame, fs->cfa_reg); 939 if (fs->armcc_cfa_offsets_reversed) 940 cache->cfa -= fs->cfa_offset; 941 else 942 cache->cfa += fs->cfa_offset; 943 break; (top-gdb) p cache->cfa $18 = 2 (top-gdb) c Continuing. Breakpoint 3, dwarf2_frame_cache (this_frame=0x418dec, this_cache=0x418df0) at dwarf2-frame.c:874 874 struct gdbarch *gdbarch = get_frame_arch (this_frame); (top-gdb) c Continuing. Cannot access memory at address 0x12