Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Joel Brobecker <brobecker@gnat.com>
To: gdb-patches@sources.redhat.com
Subject: [RFA/RFC] fix problems with unwinder on mips-irix
Date: Fri, 23 Jul 2004 01:11:00 -0000	[thread overview]
Message-ID: <20040723011059.GI20596@gnat.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 3063 bytes --]

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  <brobecker@gnat.com>

        * 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

[-- Attachment #2: mips-unwind.diff --]
[-- Type: text/plain, Size: 2592 bytes --]

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);
 	}
     }

             reply	other threads:[~2004-07-23  1:11 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-07-23  1:11 Joel Brobecker [this message]
2004-07-30  0:22 ` Andrew Cagney
2004-08-03  4:44   ` Joel Brobecker
2004-08-04  1:43     ` Andrew Cagney
2004-08-06 18:31       ` Joel Brobecker
2004-08-06 19:13         ` Andrew Cagney
2004-08-30 18:18       ` Joel Brobecker
2004-08-30 19:32         ` Andrew Cagney
2004-08-31 23:44           ` Joel Brobecker
2004-09-01 14:57           ` Andrew Cagney
2004-09-02 23:09           ` Joel Brobecker
2004-09-03 20:17             ` Andrew Cagney

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20040723011059.GI20596@gnat.com \
    --to=brobecker@gnat.com \
    --cc=gdb-patches@sources.redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox