summaryrefslogtreecommitdiff
path: root/gnu
diff options
context:
space:
mode:
authorasou <asou@cvs.openbsd.org>2021-05-05 03:03:17 +0000
committerasou <asou@cvs.openbsd.org>2021-05-05 03:03:17 +0000
commit2a0f4318b835e005a7e9930ece15f9fd655d863a (patch)
tree23483c28f2e515337547c1522516ad8faaf7a1a3 /gnu
parent90caad1b1327c8bd25efa79073726ce6eef0e5a9 (diff)
Fix backtrace command with kernel core.
ok mpi@
Diffstat (limited to 'gnu')
-rw-r--r--gnu/usr.bin/binutils/gdb/amd64obsd-tdep.c60
1 files changed, 59 insertions, 1 deletions
diff --git a/gnu/usr.bin/binutils/gdb/amd64obsd-tdep.c b/gnu/usr.bin/binutils/gdb/amd64obsd-tdep.c
index 48465e9a760..b845c2ec5da 100644
--- a/gnu/usr.bin/binutils/gdb/amd64obsd-tdep.c
+++ b/gnu/usr.bin/binutils/gdb/amd64obsd-tdep.c
@@ -382,14 +382,47 @@ static int amd64obsd_tf_reg_offset[] =
21 * 8, /* %ss */
};
+static int amd64obsd_fromspllower_reg_offset[] =
+{
+ -1, /* %rax */
+ 2 * 8, /* %rbx */
+ -1, /* %rcx */
+ -1, /* %rdx */
+ -1, /* %rsi */
+ -1, /* %rdi */
+ -1, /* %rbp */
+ -1, /* %rsp */
+ -1, /* %r8 ... */
+ -1,
+ -1,
+ 0 * 8,
+ -1,
+ 1 * 8,
+ -1,
+ -1, /* ... %r15 */
+ 3 * 8, /* %rip */
+ -1, /* %rflags */
+ -1, /* %cs */
+ -1, /* %ss */
+};
+
+/* from trad-frame.c */
+struct trad_frame_cache
+{
+ struct frame_info *next_frame;
+ CORE_ADDR this_base;
+ struct trad_frame_saved_reg *prev_regs;
+ struct frame_id this_id;
+};
static struct trad_frame_cache *
amd64obsd_trapframe_cache(struct frame_info *next_frame, void **this_cache)
{
struct trad_frame_cache *cache;
- CORE_ADDR func, sp, addr;
+ CORE_ADDR func, sp, addr, trapcheck;
ULONGEST cs;
int i;
+ char *name = NULL;
if (*this_cache)
return *this_cache;
@@ -401,6 +434,29 @@ amd64obsd_trapframe_cache(struct frame_info *next_frame, void **this_cache)
sp = frame_unwind_register_unsigned (next_frame, AMD64_RSP_REGNUM);
addr = sp;
+ /* adhoc check: from trap/intr? or from spllower()? */
+ /* Xspllower() pushes %rbx, %r13, %r11.
+ so, if *(sp+(8*3)) == spllower(),
+ this frame may not be trapframe, but a frame created by Xspllower(). */
+ trapcheck = read_memory_unsigned_integer (sp+(8*3), 8);
+ find_pc_partial_function (trapcheck, &name, NULL, NULL);
+
+ if (name != NULL && (strcmp (name, "spllower") == 0)) {
+ /* from spllower(). */
+
+ for (i = 0; i < ARRAY_SIZE (amd64obsd_fromspllower_reg_offset); i++)
+ if (amd64obsd_fromspllower_reg_offset[i] != -1)
+ trad_frame_set_reg_addr (cache, i, addr + amd64obsd_fromspllower_reg_offset[i]);
+
+ /* skip rbx,r13,r11(pushed by Xspllower()), rip(pushd by spllower()). */
+ trad_frame_set_value (cache->prev_regs, AMD64_RSP_REGNUM, addr+(8*4));
+
+ /* Construct the frame ID using the function start. */
+ trad_frame_set_id (cache, frame_id_build (sp + (8*4), func));
+
+ } else {
+ /* from trap/intr. */
+
for (i = 0; i < ARRAY_SIZE (amd64obsd_tf_reg_offset); i++)
if (amd64obsd_tf_reg_offset[i] != -1)
trad_frame_set_reg_addr (cache, i, addr + amd64obsd_tf_reg_offset[i]);
@@ -419,6 +475,8 @@ amd64obsd_trapframe_cache(struct frame_info *next_frame, void **this_cache)
trad_frame_set_id (cache, frame_id_build (sp + 16, func));
}
+ }
+
return cache;
}