diff --git a/gdb/ChangeLog b/gdb/ChangeLog index d4996331037..c3ce8f83ff8 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,13 @@ +2005-12-04 Mark Kettenis + + * 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. + 2005-12-02 Andrew Stubbs * breakpoint.c (BREAK_ARGS_HELP): New mecro. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 8d8a79e6abb..b3d71ca28d4 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1716,9 +1716,9 @@ amd64obsd-nat.o: amd64obsd-nat.c $(defs_h) $(gdbcore_h) $(regcache_h) \ $(target_h) $(gdb_assert_h) $(amd64_tdep_h) $(amd64_nat_h) \ $(bsd_kvm_h) amd64obsd-tdep.o: amd64obsd-tdep.c $(defs_h) $(frame_h) $(gdbcore_h) \ - $(symtab_h) $(objfiles_h) $(osabi_h) $(regset_h) $(target_h) \ - $(gdb_assert_h) $(gdb_string_h) $(amd64_tdep_h) $(i387_tdep_h) \ - $(solib_svr4_h) + $(symtab_h) $(objfiles_h) $(osabi_h) $(regcache_h) $(regset_h) \ + $(target_h) $(gdb_assert_h) $(gdb_string_h) $(amd64_tdep_h) \ + $(i387_tdep_h) $(solib_svr4_h) $(bsd_uthread_h) amd64-sol2-tdep.o: amd64-sol2-tdep.c $(defs_h) $(frame_h) $(gdbcore_h) \ $(regcache_h) $(osabi_h) $(symtab_h) $(gdb_string_h) $(amd64_tdep_h) \ $(solib_svr4_h) 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);