diff options
Diffstat (limited to 'gdb/m68klinux-tdep.c')
-rw-r--r-- | gdb/m68klinux-tdep.c | 102 |
1 files changed, 98 insertions, 4 deletions
diff --git a/gdb/m68klinux-tdep.c b/gdb/m68klinux-tdep.c index 1091951..c174daa 100644 --- a/gdb/m68klinux-tdep.c +++ b/gdb/m68klinux-tdep.c @@ -33,6 +33,8 @@ #include "objfiles.h" #include "symtab.h" #include "m68k-tdep.h" +#include "trad-frame.h" +#include "frame-unwind.h" /* Offsets (in target ints) into jmp_buf. */ @@ -160,12 +162,21 @@ static int m68k_linux_ucontext_reg_offset[M68K_NUM_REGS] = /* Get info about saved registers in sigtramp. */ -static struct m68k_sigtramp_info +struct m68k_linux_sigtramp_info +{ + /* Address of sigcontext. */ + CORE_ADDR sigcontext_addr; + + /* Offset of registers in `struct sigcontext'. */ + int *sc_reg_offset; +}; + +static struct m68k_linux_sigtramp_info m68k_linux_get_sigtramp_info (struct frame_info *next_frame) { CORE_ADDR sp; char buf[4]; - struct m68k_sigtramp_info info; + struct m68k_linux_sigtramp_info info; frame_unwind_register (next_frame, M68K_SP_REGNUM, buf); sp = extract_unsigned_integer (buf, 4); @@ -180,6 +191,90 @@ m68k_linux_get_sigtramp_info (struct frame_info *next_frame) return info; } +/* Signal trampolines. */ + +static struct trad_frame_cache * +m68k_linux_sigtramp_frame_cache (struct frame_info *next_frame, + void **this_cache) +{ + struct frame_id this_id; + struct trad_frame_cache *cache; + struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + struct m68k_linux_sigtramp_info info; + char buf[4]; + int i; + + if (*this_cache) + return *this_cache; + + cache = trad_frame_cache_zalloc (next_frame); + + /* FIXME: cagney/2004-05-01: This is is long standing broken code. + The frame ID's code address should be the start-address of the + signal trampoline and not the current PC within that + trampoline. */ + frame_unwind_register (next_frame, M68K_SP_REGNUM, buf); + /* See the end of m68k_push_dummy_call. */ + this_id = frame_id_build (extract_unsigned_integer (buf, 4) - 4 + 8, + frame_pc_unwind (next_frame)); + trad_frame_set_id (cache, this_id); + + info = m68k_linux_get_sigtramp_info (next_frame); + + for (i = 0; i < M68K_NUM_REGS; i++) + if (info.sc_reg_offset[i] != -1) + trad_frame_set_reg_addr (cache, i, + info.sigcontext_addr + info.sc_reg_offset[i]); + + *this_cache = cache; + return cache; +} + +static void +m68k_linux_sigtramp_frame_this_id (struct frame_info *next_frame, + void **this_cache, + struct frame_id *this_id) +{ + struct trad_frame_cache *cache = + m68k_linux_sigtramp_frame_cache (next_frame, this_cache); + trad_frame_get_id (cache, this_id); +} + +static void +m68k_linux_sigtramp_frame_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) +{ + /* Make sure we've initialized the cache. */ + struct trad_frame_cache *cache = + m68k_linux_sigtramp_frame_cache (next_frame, this_cache); + trad_frame_get_register (cache, next_frame, regnum, optimizedp, lvalp, + addrp, realnump, valuep); +} + +static const struct frame_unwind m68k_linux_sigtramp_frame_unwind = +{ + SIGTRAMP_FRAME, + m68k_linux_sigtramp_frame_this_id, + m68k_linux_sigtramp_frame_prev_register +}; + +static const struct frame_unwind * +m68k_linux_sigtramp_frame_sniffer (struct frame_info *next_frame) +{ + CORE_ADDR pc = frame_pc_unwind (next_frame); + char *name; + + find_pc_partial_function (pc, &name, NULL, NULL); + if (m68k_linux_pc_in_sigtramp (pc, name)) + return &m68k_linux_sigtramp_frame_unwind; + + return NULL; +} + /* Extract from an array REGBUF containing the (raw) register state, a function return value of TYPE, and copy that, in virtual format, into VALBUF. */ @@ -289,14 +384,13 @@ m68k_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->jb_pc = M68K_LINUX_JB_PC; tdep->jb_elt_size = M68K_LINUX_JB_ELEMENT_SIZE; - tdep->get_sigtramp_info = m68k_linux_get_sigtramp_info; tdep->struct_return = reg_struct_return; set_gdbarch_extract_return_value (gdbarch, m68k_linux_extract_return_value); set_gdbarch_store_return_value (gdbarch, m68k_linux_store_return_value); set_gdbarch_deprecated_extract_struct_value_address (gdbarch, m68k_linux_extract_struct_value_address); - set_gdbarch_deprecated_pc_in_sigtramp (gdbarch, m68k_linux_pc_in_sigtramp); + frame_unwind_append_sniffer (gdbarch, m68k_linux_sigtramp_frame_sniffer); /* Shared library handling. */ set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section); |