X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fm68kbsd-tdep.c;h=e59bc668ce761fa3849b43156b4606b40811ddc1;hb=9f1b45b0da430a7a7abf9e54acbe6f2ef9d3a763;hp=4ae4d423535d030a7711ef59972adc2140a0e629;hpb=e8ce19c0cdf50f1e6caf4f1fe3ceffc765e80439;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/m68kbsd-tdep.c b/gdb/m68kbsd-tdep.c index 4ae4d42353..e59bc668ce 100644 --- a/gdb/m68kbsd-tdep.c +++ b/gdb/m68kbsd-tdep.c @@ -1,12 +1,12 @@ /* Target-dependent code for Motorola 68000 BSD's. - Copyright 2004 Free Software Foundation, Inc. + Copyright (C) 2004-2014 Free Software Foundation, Inc. This file is part of GDB. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -15,18 +15,20 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + along with this program. If not, see . */ #include "defs.h" #include "arch-utils.h" +#include "frame.h" #include "osabi.h" #include "regcache.h" #include "regset.h" +#include "trad-frame.h" +#include "tramp-frame.h" +#include "gdbtypes.h" #include "gdb_assert.h" -#include "gdb_string.h" +#include #include "m68k-tdep.h" #include "solib-svr4.h" @@ -40,12 +42,14 @@ #define M68KBSD_SIZEOF_FPREGS (((8 * 3) + 3) * 4) int -m68kbsd_fpreg_offset (int regnum) +m68kbsd_fpreg_offset (struct gdbarch *gdbarch, int regnum) { + int fp_len = TYPE_LENGTH (gdbarch_register_type (gdbarch, regnum)); + if (regnum >= M68K_FPC_REGNUM) - return 8 * 12 + (regnum - M68K_FPC_REGNUM) * 4; + return 8 * fp_len + (regnum - M68K_FPC_REGNUM) * 4; - return (regnum - M68K_FP0_REGNUM) * 12; + return (regnum - M68K_FP0_REGNUM) * fp_len; } /* Supply register REGNUM from the buffer specified by FPREGS and LEN @@ -57,7 +61,8 @@ m68kbsd_supply_fpregset (const struct regset *regset, struct regcache *regcache, int regnum, const void *fpregs, size_t len) { - const char *regs = fpregs; + struct gdbarch *gdbarch = get_regcache_arch (regcache); + const gdb_byte *regs = fpregs; int i; gdb_assert (len >= M68KBSD_SIZEOF_FPREGS); @@ -65,7 +70,8 @@ m68kbsd_supply_fpregset (const struct regset *regset, for (i = M68K_FP0_REGNUM; i <= M68K_PC_REGNUM; i++) { if (regnum == i || regnum == -1) - regcache_raw_supply (regcache, i, regs + m68kbsd_fpreg_offset (i)); + regcache_raw_supply (regcache, i, + regs + m68kbsd_fpreg_offset (gdbarch, i)); } } @@ -78,7 +84,7 @@ m68kbsd_supply_gregset (const struct regset *regset, struct regcache *regcache, int regnum, const void *gregs, size_t len) { - const char *regs = gregs; + const gdb_byte *regs = gregs; int i; gdb_assert (len >= M68KBSD_SIZEOF_GREGS); @@ -126,6 +132,61 @@ m68kbsd_regset_from_core_section (struct gdbarch *gdbarch, return NULL; } + + +/* Signal trampolines. */ + +static void +m68kobsd_sigtramp_cache_init (const struct tramp_frame *self, + struct frame_info *this_frame, + struct trad_frame_cache *this_cache, + CORE_ADDR func) +{ + CORE_ADDR addr, base, pc; + int regnum; + + base = get_frame_register_unsigned (this_frame, M68K_SP_REGNUM); + + /* The 'addql #4,%sp' instruction at offset 8 adjusts the stack + pointer. Adjust the frame base accordingly. */ + pc = get_frame_register_unsigned (this_frame, M68K_PC_REGNUM); + if ((pc - func) > 8) + base -= 4; + + /* Get frame pointer, stack pointer, program counter and processor + state from `struct sigcontext'. */ + addr = get_frame_memory_unsigned (this_frame, base + 8, 4); + trad_frame_set_reg_addr (this_cache, M68K_FP_REGNUM, addr + 8); + trad_frame_set_reg_addr (this_cache, M68K_SP_REGNUM, addr + 12); + trad_frame_set_reg_addr (this_cache, M68K_PC_REGNUM, addr + 20); + trad_frame_set_reg_addr (this_cache, M68K_PS_REGNUM, addr + 24); + + /* The sc_ap member of `struct sigcontext' points to additional + hardware state. Here we find the missing registers. */ + addr = get_frame_memory_unsigned (this_frame, addr + 16, 4) + 4; + for (regnum = M68K_D0_REGNUM; regnum < M68K_FP_REGNUM; regnum++, addr += 4) + trad_frame_set_reg_addr (this_cache, regnum, addr); + + /* Construct the frame ID using the function start. */ + trad_frame_set_id (this_cache, frame_id_build (base, func)); +} + +static const struct tramp_frame m68kobsd_sigtramp = { + SIGTRAMP_FRAME, + 2, + { + { 0x206f, -1 }, { 0x000c, -1}, /* moveal %sp@(12),%a0 */ + { 0x4e90, -1 }, /* jsr %a0@ */ + { 0x588f, -1 }, /* addql #4,%sp */ + { 0x4e41, -1 }, /* trap #1 */ + { 0x2f40, -1 }, { 0x0004, -1 }, /* moveal %d0,%sp@(4) */ + { 0x7001, -1 }, /* moveq #SYS_exit,%d0 */ + { 0x4e40, -1 }, /* trap #0 */ + { TRAMP_SENTINEL_INSN, -1 } + }, + m68kobsd_sigtramp_cache_init +}; + static void m68kbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) @@ -135,6 +196,8 @@ m68kbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->jb_pc = 5; tdep->jb_elt_size = 4; + set_gdbarch_decr_pc_after_break (gdbarch, 2); + set_gdbarch_regset_from_core_section (gdbarch, m68kbsd_regset_from_core_section); } @@ -149,6 +212,8 @@ m68kbsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) m68kbsd_init_abi (info, gdbarch); tdep->struct_return = reg_struct_return; + + tramp_frame_prepend_unwinder (gdbarch, &m68kobsd_sigtramp); } /* NetBSD ELF. */