diff options
author | Kevin Buettner <kevinb@redhat.com> | 2004-03-20 04:51:21 +0000 |
---|---|---|
committer | Kevin Buettner <kevinb@redhat.com> | 2004-03-20 04:51:21 +0000 |
commit | 61a650991d2ab71dc4b78e665e3fb53b41346c81 (patch) | |
tree | 1a8e2422e355f8637b41dfaf92feba44473c1d5c /gdb/ppc-linux-tdep.c | |
parent | 36751eee4a66500933eef5cb40ba76792b78b6c9 (diff) | |
download | gdb-61a650991d2ab71dc4b78e665e3fb53b41346c81.zip gdb-61a650991d2ab71dc4b78e665e3fb53b41346c81.tar.gz gdb-61a650991d2ab71dc4b78e665e3fb53b41346c81.tar.bz2 |
Commit Andrew Cagney's rs6000 / PPC framification patch.
Diffstat (limited to 'gdb/ppc-linux-tdep.c')
-rw-r--r-- | gdb/ppc-linux-tdep.c | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index a8173ea..901ae5c 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -35,6 +35,8 @@ #include "regset.h" #include "solib-svr4.h" #include "ppc-tdep.h" +#include "trad-frame.h" +#include "frame-unwind.h" /* The following instructions are used in the signal trampoline code on GNU/Linux PPC. The kernel used to use magic syscalls 0x6666 and @@ -1017,6 +1019,110 @@ static struct regset ppc32_linux_gregset = { NULL, ppc32_linux_supply_gregset }; +struct ppc_linux_sigtramp_cache +{ + CORE_ADDR base; + struct trad_frame_saved_reg *saved_regs; +}; + +static struct ppc_linux_sigtramp_cache * +ppc_linux_sigtramp_cache (struct frame_info *next_frame, void **this_cache) +{ + CORE_ADDR regs; + CORE_ADDR gpregs; + CORE_ADDR fpregs; + int i; + struct ppc_linux_sigtramp_cache *cache; + struct gdbarch *gdbarch = get_frame_arch (next_frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + if ((*this_cache) != NULL) + return (*this_cache); + cache = FRAME_OBSTACK_ZALLOC (struct ppc_linux_sigtramp_cache); + (*this_cache) = cache; + cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); + + cache->base = frame_unwind_register_unsigned (next_frame, SP_REGNUM); + + /* Find the register pointer, which gives the address of the + register buffers. */ + if (tdep->wordsize == 4) + regs = (cache->base + + 0xd0 /* Offset to ucontext_t. */ + + 0x30 /* Offset to .reg. */); + else + regs = (cache->base + + 0x80 /* Offset to ucontext_t. */ + + 0xe0 /* Offset to .reg. */); + /* And the corresponding register buffers. */ + gpregs = read_memory_unsigned_integer (regs, tdep->wordsize); + fpregs = gpregs + 48 * tdep->wordsize; + + /* General purpose. */ + for (i = 0; i < 32; i++) + { + int regnum = i + tdep->ppc_gp0_regnum; + cache->saved_regs[regnum].addr = gpregs + i * tdep->wordsize; + } + cache->saved_regs[PC_REGNUM].addr = gpregs + 32 * tdep->wordsize; + cache->saved_regs[tdep->ppc_ctr_regnum].addr = gpregs + 35 * tdep->wordsize; + cache->saved_regs[tdep->ppc_lr_regnum].addr = gpregs + 36 * tdep->wordsize; + cache->saved_regs[tdep->ppc_xer_regnum].addr = gpregs + 37 * tdep->wordsize; + cache->saved_regs[tdep->ppc_cr_regnum].addr = gpregs + 38 * tdep->wordsize; + + /* Floating point registers. */ + for (i = 0; i < 32; i++) + { + int regnum = i + FP0_REGNUM; + cache->saved_regs[regnum].addr = fpregs + i * tdep->wordsize; + } + cache->saved_regs[tdep->ppc_fpscr_regnum].addr = fpregs + 32 * tdep->wordsize; + + return cache; +} + +static void +ppc_linux_sigtramp_this_id (struct frame_info *next_frame, void **this_cache, + struct frame_id *this_id) +{ + struct ppc_linux_sigtramp_cache *info + = ppc_linux_sigtramp_cache (next_frame, this_cache); + (*this_id) = frame_id_build (info->base, frame_pc_unwind (next_frame)); +} + +static void +ppc_linux_sigtramp_prev_register (struct frame_info *next_frame, + void **this_cache, + int regnum, int *optimizedp, + enum lval_type *lvalp, CORE_ADDR *addrp, + int *realnump, void *valuep) +{ + struct ppc_linux_sigtramp_cache *info + = ppc_linux_sigtramp_cache (next_frame, this_cache); + trad_frame_prev_register (next_frame, info->saved_regs, regnum, + optimizedp, lvalp, addrp, realnump, valuep); +} + +static const struct frame_unwind ppc_linux_sigtramp_unwind = +{ + SIGTRAMP_FRAME, + ppc_linux_sigtramp_this_id, + ppc_linux_sigtramp_prev_register +}; + +static const struct frame_unwind * +ppc_linux_sigtramp_sniffer (struct frame_info *next_frame) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (next_frame)); + if (frame_pc_unwind (next_frame) + > frame_unwind_register_unsigned (next_frame, SP_REGNUM)) + /* Assume anything that is vaguely on the stack is a signal + trampoline. */ + return &ppc_linux_sigtramp_unwind; + else + return NULL; +} + static void ppc64_linux_supply_gregset (const struct regset *regset, struct regcache * regcache, @@ -1084,6 +1190,7 @@ ppc_linux_init_abi (struct gdbarch_info info, PowerOpen struct convention. */ set_gdbarch_return_value (gdbarch, ppc_linux_return_value); +#if 0 /* Note: kevinb/2002-04-12: See note in rs6000_gdbarch_init regarding *_push_arguments(). The same remarks hold for the methods below. */ set_gdbarch_deprecated_frameless_function_invocation (gdbarch, ppc_linux_frameless_function_invocation); @@ -1094,9 +1201,11 @@ ppc_linux_init_abi (struct gdbarch_info info, ppc_linux_frame_init_saved_regs); set_gdbarch_deprecated_init_extra_frame_info (gdbarch, ppc_linux_init_extra_frame_info); +#endif set_gdbarch_memory_remove_breakpoint (gdbarch, ppc_linux_memory_remove_breakpoint); + /* Shared library handling. */ set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section); set_gdbarch_skip_trampoline_code (gdbarch, @@ -1120,6 +1229,7 @@ ppc_linux_init_abi (struct gdbarch_info info, set_gdbarch_name_of_malloc (gdbarch, ".malloc"); } set_gdbarch_regset_from_core_section (gdbarch, ppc_linux_regset_from_core_section); + frame_unwind_append_sniffer (gdbarch, ppc_linux_sigtramp_sniffer); } void |