diff options
author | Mark Kettenis <kettenis@gnu.org> | 2005-12-04 20:19:25 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@gnu.org> | 2005-12-04 20:19:25 +0000 |
commit | d78749b4b8e6a309b5ec3e43de8667cd320b1a4f (patch) | |
tree | 575ee7331bcbb593840bf5c4f74708b553f3058e /gdb/amd64obsd-tdep.c | |
parent | * elf64-hppa.c (elf64_hppa_section_from_phdr): Create .kernel (diff) | |
download | binutils-gdb-d78749b4b8e6a309b5ec3e43de8667cd320b1a4f.tar.gz binutils-gdb-d78749b4b8e6a309b5ec3e43de8667cd320b1a4f.tar.bz2 binutils-gdb-d78749b4b8e6a309b5ec3e43de8667cd320b1a4f.zip |
* amd64obsd-tdep.c: Include "regcache.h" and "bsd-uthread.h".
(amd64obsd_uthread_reg_offset): New variable.
(AMD64OBSD_UTHREAD_RSP_OFFSET): New define.
(amd64obsd_supply_uthread, amd64obsd_collect_uthread): New
functions.
(amd64obsd_init_abi): Set supply_uthread and collect_uthread.
* Makefile.in (amd64obsd-tdep.o): Update dependencies.
Diffstat (limited to 'gdb/amd64obsd-tdep.c')
-rw-r--r-- | gdb/amd64obsd-tdep.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/gdb/amd64obsd-tdep.c b/gdb/amd64obsd-tdep.c index acef49e9d55..66d0ab24ff3 100644 --- a/gdb/amd64obsd-tdep.c +++ b/gdb/amd64obsd-tdep.c @@ -25,6 +25,7 @@ #include "symtab.h" #include "objfiles.h" #include "osabi.h" +#include "regcache.h" #include "regset.h" #include "target.h" @@ -34,6 +35,7 @@ #include "amd64-tdep.h" #include "i387-tdep.h" #include "solib-svr4.h" +#include "bsd-uthread.h" /* Support for core dumps. */ @@ -211,6 +213,127 @@ static int amd64obsd_sc_reg_offset[] = 15 * 8 /* %gs */ }; +/* From /usr/src/lib/libpthread/arch/amd64/uthread_machdep.c. */ +static int amd64obsd_uthread_reg_offset[] = +{ + 19 * 8, /* %rax */ + 16 * 8, /* %rbx */ + 18 * 8, /* %rcx */ + 17 * 8, /* %rdx */ + 14 * 8, /* %rsi */ + 13 * 8, /* %rdi */ + 15 * 8, /* %rbp */ + -1, /* %rsp */ + 12 * 8, /* %r8 ... */ + 11 * 8, + 10 * 8, + 9 * 8, + 8 * 8, + 7 * 8, + 6 * 8, + 5 * 8, /* ... %r15 */ + 20 * 8, /* %rip */ + 4 * 8, /* %eflags */ + 21 * 8, /* %cs */ + -1, /* %ss */ + 3 * 8, /* %ds */ + 2 * 8, /* %es */ + 1 * 8, /* %fs */ + 0 * 8 /* %gs */ +}; + +/* Offset within the thread structure where we can find the saved + stack pointer (%esp). */ +#define AMD64OBSD_UTHREAD_RSP_OFFSET 400 + +static void +amd64obsd_supply_uthread (struct regcache *regcache, + int regnum, CORE_ADDR addr) +{ + CORE_ADDR sp_addr = addr + AMD64OBSD_UTHREAD_RSP_OFFSET; + CORE_ADDR sp = 0; + gdb_byte buf[8]; + int i; + + gdb_assert (regnum >= -1); + + if (regnum == -1 || regnum == AMD64_RSP_REGNUM) + { + int offset; + + /* Fetch stack pointer from thread structure. */ + sp = read_memory_unsigned_integer (sp_addr, 8); + + /* Adjust the stack pointer such that it looks as if we just + returned from _thread_machdep_switch. */ + offset = amd64obsd_uthread_reg_offset[AMD64_RIP_REGNUM] + 8; + store_unsigned_integer (buf, 8, sp + offset); + regcache_raw_supply (regcache, AMD64_RSP_REGNUM, buf); + } + + for (i = 0; i < ARRAY_SIZE (amd64obsd_uthread_reg_offset); i++) + { + if (amd64obsd_uthread_reg_offset[i] != -1 + && (regnum == -1 || regnum == i)) + { + /* Fetch stack pointer from thread structure (if we didn't + do so already). */ + if (sp == 0) + sp = read_memory_unsigned_integer (sp_addr, 8); + + /* Read the saved register from the stack frame. */ + read_memory (sp + amd64obsd_uthread_reg_offset[i], buf, 8); + regcache_raw_supply (regcache, i, buf); + } + } +} + +static void +amd64obsd_collect_uthread (const struct regcache *regcache, + int regnum, CORE_ADDR addr) +{ + CORE_ADDR sp_addr = addr + AMD64OBSD_UTHREAD_RSP_OFFSET; + CORE_ADDR sp = 0; + gdb_byte buf[8]; + int i; + + gdb_assert (regnum >= -1); + + if (regnum == -1 || regnum == AMD64_RSP_REGNUM) + { + int offset; + + /* Calculate the stack pointer (frame pointer) that will be + stored into the thread structure. */ + offset = amd64obsd_uthread_reg_offset[AMD64_RIP_REGNUM] + 8; + regcache_raw_collect (regcache, AMD64_RSP_REGNUM, buf); + sp = extract_unsigned_integer (buf, 8) - offset; + + /* Store the stack pointer. */ + write_memory_unsigned_integer (sp_addr, 8, sp); + + /* The stack pointer was (potentially) modified. Make sure we + build a proper stack frame. */ + regnum = -1; + } + + for (i = 0; i < ARRAY_SIZE (amd64obsd_uthread_reg_offset); i++) + { + if (amd64obsd_uthread_reg_offset[i] != -1 + && (regnum == -1 || regnum == i)) + { + /* Fetch stack pointer from thread structure (if we didn't + calculate it already). */ + if (sp == 0) + sp = read_memory_unsigned_integer (sp_addr, 8); + + /* Write the register into the stack frame. */ + regcache_raw_collect (regcache, i, buf); + write_memory (sp + amd64obsd_uthread_reg_offset[i], buf, 8); + } + } +} + static void amd64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -233,6 +356,10 @@ amd64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->sc_reg_offset = amd64obsd_sc_reg_offset; tdep->sc_num_regs = ARRAY_SIZE (amd64obsd_sc_reg_offset); + /* OpenBSD provides a user-level threads implementation. */ + bsd_uthread_set_supply_uthread (gdbarch, amd64obsd_supply_uthread); + bsd_uthread_set_collect_uthread (gdbarch, amd64obsd_collect_uthread); + /* OpenBSD uses SVR4-style shared libraries. */ set_solib_svr4_fetch_link_map_offsets (gdbarch, svr4_lp64_fetch_link_map_offsets); |