From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3384 invoked by alias); 23 Jul 2004 01:11:03 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 3372 invoked from network); 23 Jul 2004 01:11:00 -0000 Received: from unknown (HELO takamaka.act-europe.fr) (142.179.108.108) by sourceware.org with SMTP; 23 Jul 2004 01:11:00 -0000 Received: by takamaka.act-europe.fr (Postfix, from userid 507) id B8C3247D91; Thu, 22 Jul 2004 18:10:59 -0700 (PDT) Date: Fri, 23 Jul 2004 01:11:00 -0000 From: Joel Brobecker To: gdb-patches@sources.redhat.com Subject: [RFA/RFC] fix problems with unwinder on mips-irix Message-ID: <20040723011059.GI20596@gnat.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="zx4FCpZtqtKETZ7O" Content-Disposition: inline User-Agent: Mutt/1.4i X-SW-Source: 2004-07/txt/msg00319.txt.bz2 --zx4FCpZtqtKETZ7O Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 3063 Hello, Still working on this IRIX debugger on mips, the next big thing is that GDB is having problems unwinding the stack. For instance, using gdb.base/store: % gdb store (gdb) b wack_doublest (gdb) run (gdb) bt #0 wack_doublest (u=Unhandled dwarf expression opcode 0x93 ) at ./gdb.base/store.c:125 #1 0x100108d8 in ?? () warning: GDB can't find the start of the function at 0x100108d8. GDB is unable to find the start of the function at 0x100108d8 and thus can't determine the size of that function's stack frame. This means that GDB may be unable to access that stack frame, or the frames below it. This problem is most likely caused by an invalid program counter or stack pointer. However, if you think GDB should simply search farther back from 0x100108d8 for code which looks like the beginning of a function, you can increase the range of the search using the `set heuristic-fence-post' command. Previous frame inner to this frame (corrupt stack?) What happens is that GDB calls heuristic_proc_desc() to "synthesize" a procedure descriptor (I'll abbreviate: PDR). On IRIX, at least with N32, we end up calling mips32_heuristic_proc_desc(). As expected, this function scans the prologue, and computes the frame size, stores which registers are saved, etc. Unfortunately, it seems that we forgot to save one critical piece of information: *where* the registers are saved in the stack. Looking at mips_mdebug_frame_cache(), we see: CORE_ADDR reg_position = (cache->base + PROC_REG_OFFSET (proc_desc)); int ireg; for (ireg = MIPS_NUMREGS - 1; gen_mask; --ireg, gen_mask <<= 1) if (gen_mask & 0x80000000) { cache->saved_regs[NUM_REGS + ireg].addr = reg_position; reg_position -= mips_abi_regsize (gdbarch); } But the thing is, we forgot to set the PROC_REG_OFFSET. This value is the distance between the frame base, and the start of the area where registers are saved. It can be computed when we detect the first register save instruction in the prologue by taking the difference between the offset to SP/FP used in the isntruction, and the frame size. The attached patch implements this, for mips32_heuristic_proc_desc(). I am about to launch the testsuite with this patch. I am guessing that mips16_heuristic_proc_desc() suffers from the same problem and will require the same adjustments. I am happy to fix it too, but it will be blind fixing as I won't be able to test it. Your call. 2004-07-22 Joel Brobecker * mips-tdep.c (mips_mdebug_frame_cache): Minor reformatting. (set_saved_reg_info): New function. (mips32_heuristic_proc_desc): Compute the procedure descriptor PROC_REG_OFFSET. Tested on mips-irix, fixes tons of regressions. OK to commit? If you would like me to fix mips16_heuristic_proc_desc as well, I can submit a separate patch. Thanks, -- Joel --zx4FCpZtqtKETZ7O Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="mips-unwind.diff" Content-length: 2592 Index: mips-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/mips-tdep.c,v retrieving revision 1.301 diff -u -p -r1.301 mips-tdep.c --- mips-tdep.c 10 Jul 2004 01:17:52 -0000 1.301 +++ mips-tdep.c 22 Jul 2004 22:04:56 -0000 @@ -1587,9 +1587,9 @@ mips_mdebug_frame_cache (struct frame_in /* Fill in the offsets for the registers which gen_mask says were saved. */ { - CORE_ADDR reg_position = (cache->base - + PROC_REG_OFFSET (proc_desc)); + CORE_ADDR reg_position = (cache->base + PROC_REG_OFFSET (proc_desc)); int ireg; + for (ireg = MIPS_NUMREGS - 1; gen_mask; --ireg, gen_mask <<= 1) if (gen_mask & 0x80000000) { @@ -1851,6 +1851,23 @@ set_reg_offset (CORE_ADDR *saved_regs, i } } +/* Record in the procedure descriptor INFO the fact that register REGNO + was saved at OFFSET bytes from the procedure descriptor frame register. + Also updates the offset between the frame base and the area in the stack + where the registers are stored. */ + +static void +set_saved_reg_info (struct mips_extra_func_info *info, + int regno, int offset) +{ + /* If this is the first register saved, then OFFSET points to + the begining of the stack where the registers are saved. + We can use this to compute the PROC_REG_OFFSET of this frame. */ + if (PROC_REG_MASK (info) == 0) + PROC_REG_OFFSET (info) = offset - PROC_FRAME_OFFSET (info); + + PROC_REG_MASK (info) |= 1 << regno; +} /* Test whether the PC points to the return instruction at the end of a function. */ @@ -2179,14 +2196,14 @@ restart: } else if ((high_word & 0xFFE0) == 0xafa0) /* sw reg,offset($sp) */ { - PROC_REG_MASK (&temp_proc_desc) |= 1 << reg; + set_saved_reg_info (&temp_proc_desc, reg, low_word); set_reg_offset (temp_saved_regs, reg, sp + low_word); } else if ((high_word & 0xFFE0) == 0xffa0) /* sd reg,offset($sp) */ { /* Irix 6.2 N32 ABI uses sd instructions for saving $gp and $ra. */ - PROC_REG_MASK (&temp_proc_desc) |= 1 << reg; + set_saved_reg_info (&temp_proc_desc, reg, low_word); set_reg_offset (temp_saved_regs, reg, sp + low_word); } else if (high_word == 0x27be) /* addiu $30,$sp,size */ @@ -2236,7 +2253,7 @@ restart: } else if ((high_word & 0xFFE0) == 0xafc0) /* sw reg,offset($30) */ { - PROC_REG_MASK (&temp_proc_desc) |= 1 << reg; + set_saved_reg_info (&temp_proc_desc, reg, low_word); set_reg_offset (temp_saved_regs, reg, frame_addr + low_word); } } --zx4FCpZtqtKETZ7O--