diff --git a/gdb/ChangeLog b/gdb/ChangeLog index adb24d45c1..2f34a314fc 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,17 @@ +2014-12-19 Maciej W. Rozycki + Nigel Stephens + Chris Dearman + Luis Machado + + * Makefile.in (ALL_TARGET_OBS): Add mips-sde-tdep.o. + (ALLDEPFILES): Add mips-sde-tdep.c. + * mips-sde-tdep.c: New file containg SDE specific code. + * configure.tgt (mips*-sde*-elf*): Add mips-sde-dep.o to + gdb_target_obs. + * defs.h (gdb_osabi): Add GDB_OSABI_SDE. + * osabi.c (gdb_osabi_names): Add SDE. + * NEWS: Mention the change. + 2014-12-18 Simon Marchi * elfread.c (elf_symfile_init): Remove stale comment. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 2f69eb2cb4..be69b6fe92 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -664,7 +664,7 @@ ALL_TARGET_OBS = \ m88k-tdep.o \ mep-tdep.o \ microblaze-tdep.o microblaze-linux-tdep.o \ - mips-linux-tdep.o \ + mips-linux-tdep.o mips-sde-tdep.o \ mipsnbsd-tdep.o mips-tdep.o \ mn10300-linux-tdep.o mn10300-tdep.o \ moxie-tdep.o \ @@ -1682,6 +1682,7 @@ ALLDEPFILES = \ microblaze-tdep.c microblaze-linux-tdep.c \ mingw-hdep.c \ mips-linux-nat.c mips-linux-tdep.c \ + mips-sde-tdep.c \ mips-tdep.c \ mipsnbsd-nat.c mipsnbsd-tdep.c \ mips64obsd-nat.c mips64obsd-tdep.c \ diff --git a/gdb/NEWS b/gdb/NEWS index 955dd2390a..c34cf2b613 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -95,6 +95,10 @@ show debug symbol-lookup ** The -list-thread-groups command outputs an exit-code field for inferiors that have exited. +* New targets + +MIPS SDE mips*-sde*-elf* + * Removed targets Support for these obsolete configurations has been removed. diff --git a/gdb/configure.tgt b/gdb/configure.tgt index 1d7f54bd83..065e797186 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -364,6 +364,11 @@ mips64*-*-openbsd*) # Target: OpenBSD/mips64 gdb_target_obs="mips-tdep.o mips64obsd-tdep.o obsd-tdep.o solib-svr4.o" ;; +mips*-sde*-elf*) + # Target: MIPS SDE + gdb_target_obs="mips-tdep.o mips-sde-tdep.o remote-mips.o" + gdb_sim=../sim/mips/libsim.a + ;; mips*-*-elf) # Target: MIPS ELF gdb_target_obs="mips-tdep.o remote-mips.o" diff --git a/gdb/defs.h b/gdb/defs.h index 7b5bc0628a..d74cc3c939 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -562,6 +562,7 @@ enum gdb_osabi GDB_OSABI_OPENVMS, GDB_OSABI_LYNXOS178, GDB_OSABI_NEWLIB, + GDB_OSABI_SDE, GDB_OSABI_INVALID /* keep this last */ }; diff --git a/gdb/mips-sde-tdep.c b/gdb/mips-sde-tdep.c new file mode 100644 index 0000000000..fa4d2a0466 --- /dev/null +++ b/gdb/mips-sde-tdep.c @@ -0,0 +1,270 @@ +/* Target-dependent code for SDE on MIPS processors. + + Copyright (C) 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 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 . */ + +#include "defs.h" +#include "osabi.h" +#include "elf-bfd.h" +#include "block.h" +#include "symtab.h" + +#include "frame.h" +#include "frame-unwind.h" +#include "frame-base.h" +#include "trad-frame.h" + +#include "mips-tdep.h" + +/* Fill in the register cache *THIS_CACHE for THIS_FRAME for use + in the SDE frame unwinder. */ + +static struct trad_frame_cache * +mips_sde_frame_cache (struct frame_info *this_frame, void **this_cache) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + const struct mips_regnum *regs = mips_regnum (gdbarch); + const int sizeof_reg_t = mips_abi_regsize (gdbarch); + enum mips_abi abi = mips_abi (gdbarch); + struct trad_frame_cache *cache; + CORE_ADDR xcpt_frame; + CORE_ADDR start_addr; + CORE_ADDR stack_addr; + CORE_ADDR pc; + int i; + + if (*this_cache != NULL) + return *this_cache; + cache = trad_frame_cache_zalloc (this_frame); + *this_cache = cache; + + /* The previous registers are held in struct xcptcontext + which is at $sp+offs + + struct xcptcontext { + reg_t sr; CP0 Status + reg_t cr; CP0 Cause + reg_t epc; CP0 EPC + reg_t vaddr; CP0 BadVAddr + reg_t regs[32]; General registers + reg_t mdlo; LO + reg_t mdhi; HI + reg_t mdex; ACX + ... + }; + */ + + stack_addr = get_frame_register_signed (this_frame, + gdbarch_sp_regnum (gdbarch)); + switch (abi) + { + case MIPS_ABI_O32: + /* 40: XCPTCONTEXT + 24: xcpt_gen() argspace (16 bytes) + 16: _xcptcall() saved ra, rounded up ( 8 bytes) + 00: _xcptcall() argspace (16 bytes) */ + xcpt_frame = stack_addr + 40; + break; + case MIPS_ABI_N32: + case MIPS_ABI_N64: + default: /* Wild guess. */ + /* 16: XCPTCONTEXT + 16: xcpt_gen() argspace ( 0 bytes) + 00: _xcptcall() saved ra, rounded up (16 bytes) */ + xcpt_frame = stack_addr + 16; + break; + } + + trad_frame_set_reg_addr (cache, + MIPS_PS_REGNUM + gdbarch_num_regs (gdbarch), + xcpt_frame + 0 * sizeof_reg_t); + trad_frame_set_reg_addr (cache, + regs->cause + gdbarch_num_regs (gdbarch), + xcpt_frame + 1 * sizeof_reg_t); + trad_frame_set_reg_addr (cache, + regs->pc + gdbarch_num_regs (gdbarch), + xcpt_frame + 2 * sizeof_reg_t); + trad_frame_set_reg_addr (cache, + regs->badvaddr + gdbarch_num_regs (gdbarch), + xcpt_frame + 3 * sizeof_reg_t); + for (i = 0; i < MIPS_NUMREGS; i++) + trad_frame_set_reg_addr (cache, + i + MIPS_ZERO_REGNUM + gdbarch_num_regs (gdbarch), + xcpt_frame + (4 + i) * sizeof_reg_t); + trad_frame_set_reg_addr (cache, + regs->lo + gdbarch_num_regs (gdbarch), + xcpt_frame + 36 * sizeof_reg_t); + trad_frame_set_reg_addr (cache, + regs->hi + gdbarch_num_regs (gdbarch), + xcpt_frame + 37 * sizeof_reg_t); + + pc = get_frame_pc (this_frame); + find_pc_partial_function (pc, NULL, &start_addr, NULL); + trad_frame_set_id (cache, frame_id_build (start_addr, stack_addr)); + + return cache; +} + +/* Implement the this_id function for the SDE frame unwinder. */ + +static void +mips_sde_frame_this_id (struct frame_info *this_frame, void **this_cache, + struct frame_id *this_id) +{ + struct trad_frame_cache *this_trad_cache + = mips_sde_frame_cache (this_frame, this_cache); + + trad_frame_get_id (this_trad_cache, this_id); +} + +/* Implement the prev_register function for the SDE frame unwinder. */ + +static struct value * +mips_sde_frame_prev_register (struct frame_info *this_frame, + void **this_cache, + int prev_regnum) +{ + struct trad_frame_cache *trad_cache + = mips_sde_frame_cache (this_frame, this_cache); + + return trad_frame_get_register (trad_cache, this_frame, prev_regnum); +} + +/* Implement the sniffer function for the SDE frame unwinder. */ + +static int +mips_sde_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_cache) +{ + CORE_ADDR pc = get_frame_pc (this_frame); + const char *name; + + find_pc_partial_function (pc, &name, NULL, NULL); + return (name + && (strcmp (name, "_xcptcall") == 0 + || strcmp (name, "_sigtramp") == 0)); +} + +/* Data structure for the SDE frame unwinder. */ + +static const struct frame_unwind mips_sde_frame_unwind = +{ + SIGTRAMP_FRAME, + default_frame_unwind_stop_reason, + mips_sde_frame_this_id, + mips_sde_frame_prev_register, + NULL, + mips_sde_frame_sniffer +}; + +/* Implement the this_base, this_locals, and this_args hooks + for the normal unwinder. */ + +static CORE_ADDR +mips_sde_frame_base_address (struct frame_info *this_frame, void **this_cache) +{ + struct trad_frame_cache *this_trad_cache + = mips_sde_frame_cache (this_frame, this_cache); + + return trad_frame_get_this_base (this_trad_cache); +} + +static const struct frame_base mips_sde_frame_base = +{ + &mips_sde_frame_unwind, + mips_sde_frame_base_address, + mips_sde_frame_base_address, + mips_sde_frame_base_address +}; + +static const struct frame_base * +mips_sde_frame_base_sniffer (struct frame_info *this_frame) +{ + if (mips_sde_frame_sniffer (&mips_sde_frame_unwind, this_frame, NULL)) + return &mips_sde_frame_base; + else + return NULL; +} + +static void +mips_sde_elf_osabi_sniff_abi_tag_sections (bfd *abfd, asection *sect, + void *obj) +{ + enum gdb_osabi *os_ident_ptr = obj; + const char *name; + + name = bfd_get_section_name (abfd, sect); + + /* The presence of a section with a ".sde" prefix is indicative + of an SDE binary. */ + if (strncmp (name, ".sde", 4) == 0) + *os_ident_ptr = GDB_OSABI_SDE; +} + +/* OSABI sniffer for MIPS SDE. */ + +static enum gdb_osabi +mips_sde_elf_osabi_sniffer (bfd *abfd) +{ + enum gdb_osabi osabi = GDB_OSABI_UNKNOWN; + unsigned int elfosabi; + + /* If the generic sniffer gets a hit, return and let other sniffers + get a crack at it. */ + bfd_map_over_sections (abfd, + generic_elf_osabi_sniff_abi_tag_sections, + &osabi); + if (osabi != GDB_OSABI_UNKNOWN) + return GDB_OSABI_UNKNOWN; + + elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI]; + + if (elfosabi == ELFOSABI_NONE) + { + /* When elfosabi is ELFOSABI_NONE (0), then the ELF structures in the + file are conforming to the base specification for that machine + (there are no OS-specific extensions). In order to determine the + real OS in use we must look for OS notes that have been added. + + For SDE, we simply look for sections named with .sde as prefixes. */ + bfd_map_over_sections (abfd, + mips_sde_elf_osabi_sniff_abi_tag_sections, + &osabi); + } + return osabi; +} + +static void +mips_sde_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + frame_unwind_append_unwinder (gdbarch, &mips_sde_frame_unwind); + frame_base_append_sniffer (gdbarch, mips_sde_frame_base_sniffer); +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_mips_sde_tdep; + +void +_initialize_mips_sde_tdep (void) +{ + gdbarch_register_osabi_sniffer (bfd_arch_mips, + bfd_target_elf_flavour, + mips_sde_elf_osabi_sniffer); + + gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_SDE, mips_sde_init_abi); +} diff --git a/gdb/osabi.c b/gdb/osabi.c index 50d391afef..895b476ce3 100644 --- a/gdb/osabi.c +++ b/gdb/osabi.c @@ -83,6 +83,7 @@ static const struct osabi_names gdb_osabi_names[] = { "OpenVMS", NULL }, { "LynxOS178", NULL }, { "Newlib", NULL }, + { "SDE", NULL }, { "", NULL } };