diff options
author | asou <asou@cvs.openbsd.org> | 2021-05-05 03:03:17 +0000 |
---|---|---|
committer | asou <asou@cvs.openbsd.org> | 2021-05-05 03:03:17 +0000 |
commit | 2a0f4318b835e005a7e9930ece15f9fd655d863a (patch) | |
tree | 23483c28f2e515337547c1522516ad8faaf7a1a3 /gnu | |
parent | 90caad1b1327c8bd25efa79073726ce6eef0e5a9 (diff) |
Fix backtrace command with kernel core.
ok mpi@
Diffstat (limited to 'gnu')
-rw-r--r-- | gnu/usr.bin/binutils/gdb/amd64obsd-tdep.c | 60 |
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; } |