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