diff options
Diffstat (limited to 'gdb/bfin-linux-tdep.c')
-rw-r--r-- | gdb/bfin-linux-tdep.c | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/gdb/bfin-linux-tdep.c b/gdb/bfin-linux-tdep.c new file mode 100644 index 0000000..545bdcf --- /dev/null +++ b/gdb/bfin-linux-tdep.c @@ -0,0 +1,175 @@ +/* Target-dependent code for Analog Devices Blackfin processor, for GDB. + + Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 + Free Software Foundation, Inc. + + Contributed by Analog Devices, 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see <http://www.gnu.org/licenses/>. */ + +#include "defs.h" +#include "arch-utils.h" +#include "regcache.h" +#include "tramp-frame.h" +#include "trad-frame.h" +#include "osabi.h" +#include "xml-syscall.h" +#include "linux-tdep.h" +#include "bfin-tdep.h" + +/* From <asm/sigcontext.h>. */ + +#define SIGCONTEXT_OFFSET 168 + +static const int bfin_linux_sigcontext_reg_offset[BFIN_NUM_REGS] = +{ + 0 * 4, /* %r0 */ + 1 * 4, /* %r1 */ + 2 * 4, /* %r2 */ + 3 * 4, /* %r3 */ + 4 * 4, /* %r4 */ + 5 * 4, /* %r5 */ + 6 * 4, /* %r6 */ + 7 * 4, /* %r7 */ + 8 * 4, /* %p0 */ + 9 * 4, /* %p1 */ + 10 * 4, /* %p2 */ + 11 * 4, /* %p3 */ + 12 * 4, /* %p4 */ + 13 * 4, /* %p5 */ + 14 * 4, /* %sp */ + 23 * 4, /* %fp */ + 24 * 4, /* %i0 */ + 25 * 4, /* %i1 */ + 26 * 4, /* %i2 */ + 27 * 4, /* %i3 */ + 28 * 4, /* %m0 */ + 29 * 4, /* %m1 */ + 30 * 4, /* %m2 */ + 31 * 4, /* %m3 */ + 36 * 4, /* %b0 */ + 37 * 4, /* %b1 */ + 38 * 4, /* %b2 */ + 39 * 4, /* %b3 */ + 32 * 4, /* %l0 */ + 33 * 4, /* %l1 */ + 34 * 4, /* %l2 */ + 35 * 4, /* %l3 */ + 17 * 4, /* %a0x */ + 15 * 4, /* %a0w */ + 18 * 4, /* %a1x */ + 16 * 4, /* %a1w */ + 19 * 4, /* %astat */ + 20 * 4, /* %rets */ + 40 * 4, /* %lc0 */ + 42 * 4, /* %lt0 */ + 44 * 4, /* %lb0 */ + 41 * 4, /* %lc1 */ + 43 * 4, /* %lt1 */ + 45 * 4, /* %lb1 */ + -1, /* %cycles */ + -1, /* %cycles2 */ + -1, /* %usp */ + 46 * 4, /* %seqstat */ + -1, /* syscfg */ + 21 * 4, /* %reti */ + 22 * 4, /* %retx */ + -1, /* %retn */ + -1, /* %rete */ + 21 * 4, /* %pc */ +}; + +/* Signal trampolines. */ + +static void +bfin_linux_sigframe_init (const struct tramp_frame *self, + struct frame_info *this_frame, + struct trad_frame_cache *this_cache, + CORE_ADDR func) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + CORE_ADDR sp = get_frame_sp (this_frame); + CORE_ADDR pc = get_frame_pc (this_frame); + CORE_ADDR sigcontext = sp + SIGCONTEXT_OFFSET; + struct frame_id this_id; + const int *reg_offset = bfin_linux_sigcontext_reg_offset; + int i; + + for (i = 0; i < BFIN_NUM_REGS; i++) + if (reg_offset[i] != -1) + trad_frame_set_reg_addr (this_cache, i, sigcontext + reg_offset[i]); + + /* This would come after the LINK instruction in the ret_from_signal + function, hence the frame id would be SP + 8. */ + trad_frame_set_id (this_cache, frame_id_build (sp + 8, pc)); +} + +static const struct tramp_frame bfin_linux_sigframe = +{ + SIGTRAMP_FRAME, + 4, + { + { 0x00ADE128, 0xffffffff }, /* P0 = __NR_rt_sigreturn; */ + { 0x00A0, 0xffff }, /* EXCPT 0; */ + { TRAMP_SENTINEL_INSN, -1 }, + }, + bfin_linux_sigframe_init, +}; + +static LONGEST +bfin_linux_get_syscall_number (struct gdbarch *gdbarch, + ptid_t ptid) +{ + struct regcache *regcache = get_thread_regcache (ptid); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + /* The content of a register. */ + gdb_byte buf[4]; + /* The result. */ + LONGEST ret; + + /* Getting the system call number from the register. + When dealing with Blackfin architecture, this information + is stored at %p0 register. */ + regcache_cooked_read (regcache, BFIN_P0_REGNUM, buf); + + ret = extract_signed_integer (buf, 4, byte_order); + + return ret; +} + +static void +bfin_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + linux_init_abi (info, gdbarch); + + /* Set the sigtramp frame sniffer. */ + tramp_frame_prepend_unwinder (gdbarch, &bfin_linux_sigframe); + + /* Functions for 'catch syscall'. */ + set_xml_syscall_file_name ("syscalls/bfin-linux.xml"); + set_gdbarch_get_syscall_number (gdbarch, + bfin_linux_get_syscall_number); +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_bfin_linux_tdep; + +void +_initialize_bfin_linux_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_bfin, 0, GDB_OSABI_LINUX, + bfin_linux_init_abi); +} |