X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;ds=sidebyside;f=gdb%2Ffrv-linux-tdep.c;h=cee2d0c5e24fdb9e06fefdcdf74b45bcc7743007;hb=db178f47dd4c9d2882da42a8915018d1fb90ea17;hp=6ed0a74666fa3e5a4bec42d323e5d30fcdc7da71;hpb=992166eeb0e1058b48048eaa9bd9161f2bd30cb8;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/frv-linux-tdep.c b/gdb/frv-linux-tdep.c index 6ed0a74666..cee2d0c5e2 100644 --- a/gdb/frv-linux-tdep.c +++ b/gdb/frv-linux-tdep.c @@ -1,7 +1,7 @@ /* Target-dependent code for GNU/Linux running on the Fujitsu FR-V, for GDB. - Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 2004-2019 Free Software Foundation, Inc. This file is part of GDB. @@ -30,7 +30,8 @@ #include "trad-frame.h" #include "frame-unwind.h" #include "regset.h" -#include "gdb_string.h" +#include "linux-tdep.h" +#include "gdbarch.h" /* Define the size (in bytes) of an FR-V instruction. */ static const int frv_instr_size = 4; @@ -41,27 +42,29 @@ enum { }; static int -frv_linux_pc_in_sigtramp (CORE_ADDR pc, char *name) +frv_linux_pc_in_sigtramp (struct gdbarch *gdbarch, CORE_ADDR pc, + const char *name) { - char buf[frv_instr_size]; + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + gdb_byte buf[frv_instr_size]; LONGEST instr; int retval = 0; if (target_read_memory (pc, buf, sizeof buf) != 0) return 0; - instr = extract_unsigned_integer (buf, sizeof buf); + instr = extract_unsigned_integer (buf, sizeof buf, byte_order); if (instr == 0x8efc0077) /* setlos #__NR_sigreturn, gr7 */ retval = NORMAL_SIGTRAMP; - else if (instr -= 0x8efc00ad) /* setlos #__NR_rt_sigreturn, gr7 */ + else if (instr == 0x8efc00ad) /* setlos #__NR_rt_sigreturn, gr7 */ retval = RT_SIGTRAMP; else return 0; if (target_read_memory (pc + frv_instr_size, buf, sizeof buf) != 0) return 0; - instr = extract_unsigned_integer (buf, sizeof buf); + instr = extract_unsigned_integer (buf, sizeof buf, byte_order); if (instr != 0xc0700000) /* tira gr0, 0 */ return 0; @@ -165,9 +168,11 @@ frv_linux_pc_in_sigtramp (CORE_ADDR pc, char *name) } __attribute__((aligned(8))); */ static LONGEST -frv_linux_sigcontext_reg_addr (struct frame_info *next_frame, int regno, +frv_linux_sigcontext_reg_addr (struct frame_info *this_frame, int regno, CORE_ADDR *sc_addr_cache_ptr) { + struct gdbarch *gdbarch = get_frame_arch (this_frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); CORE_ADDR sc_addr; if (sc_addr_cache_ptr && *sc_addr_cache_ptr) @@ -177,14 +182,14 @@ frv_linux_sigcontext_reg_addr (struct frame_info *next_frame, int regno, else { CORE_ADDR pc, sp; - char buf[4]; + gdb_byte buf[4]; int tramp_type; - pc = frame_pc_unwind (next_frame); - tramp_type = frv_linux_pc_in_sigtramp (pc, 0); + pc = get_frame_pc (this_frame); + tramp_type = frv_linux_pc_in_sigtramp (gdbarch, pc, 0); - frame_unwind_register (next_frame, sp_regnum, buf); - sp = extract_unsigned_integer (buf, sizeof buf); + get_frame_register (this_frame, sp_regnum, buf); + sp = extract_unsigned_integer (buf, sizeof buf, byte_order); if (tramp_type == NORMAL_SIGTRAMP) { @@ -200,13 +205,13 @@ frv_linux_sigcontext_reg_addr (struct frame_info *next_frame, int regno, uc_mcontext within struct ucontext is derived as follows: stack_t is a 12-byte struct and struct sigcontext is 8-byte aligned. This gives an offset of 8 + 12 + 4 (for - padding) = 24.) */ + padding) = 24.) */ if (target_read_memory (sp + 12, buf, sizeof buf) != 0) { warning (_("Can't read realtime sigtramp frame.")); return 0; } - sc_addr = extract_unsigned_integer (buf, sizeof buf); + sc_addr = extract_unsigned_integer (buf, sizeof buf, byte_order); sc_addr += 24; } else @@ -235,7 +240,7 @@ frv_linux_sigcontext_reg_addr (struct frame_info *next_frame, int regno, sc_addr + 32 is syscallno, the syscall number or -1. sc_addr + 36 is orig_gr8, the original syscall arg #1. sc_addr + 40 is gner[0]. - sc_addr + 44 is gner[1]. */ + sc_addr + 44 is gner[1]. */ case iacc0h_regnum : return sc_addr + 48; case iacc0l_regnum : @@ -246,40 +251,42 @@ frv_linux_sigcontext_reg_addr (struct frame_info *next_frame, int regno, else if (first_fpr_regnum <= regno && regno <= last_fpr_regnum) return sc_addr + 312 + 4 * (regno - first_fpr_regnum); else - return -1; /* not saved. */ + return -1; /* not saved. */ } } /* Signal trampolines. */ static struct trad_frame_cache * -frv_linux_sigtramp_frame_cache (struct frame_info *next_frame, void **this_cache) +frv_linux_sigtramp_frame_cache (struct frame_info *this_frame, + void **this_cache) { + struct gdbarch *gdbarch = get_frame_arch (this_frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); struct trad_frame_cache *cache; - struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (next_frame)); CORE_ADDR addr; - char buf[4]; + gdb_byte buf[4]; int regnum; CORE_ADDR sc_addr_cache_val = 0; struct frame_id this_id; if (*this_cache) - return *this_cache; + return (struct trad_frame_cache *) *this_cache; - cache = trad_frame_cache_zalloc (next_frame); + cache = trad_frame_cache_zalloc (this_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, sp_regnum, buf); - this_id = frame_id_build (extract_unsigned_integer (buf, sizeof buf), - frame_pc_unwind (next_frame)); + get_frame_register (this_frame, sp_regnum, buf); + addr = extract_unsigned_integer (buf, sizeof buf, byte_order); + this_id = frame_id_build (addr, get_frame_pc (this_frame)); trad_frame_set_id (cache, this_id); for (regnum = 0; regnum < frv_num_regs; regnum++) { - LONGEST reg_addr = frv_linux_sigcontext_reg_addr (next_frame, regnum, + LONGEST reg_addr = frv_linux_sigcontext_reg_addr (this_frame, regnum, &sc_addr_cache_val); if (reg_addr != -1) trad_frame_set_reg_addr (cache, regnum, reg_addr); @@ -290,48 +297,50 @@ frv_linux_sigtramp_frame_cache (struct frame_info *next_frame, void **this_cache } static void -frv_linux_sigtramp_frame_this_id (struct frame_info *next_frame, void **this_cache, - struct frame_id *this_id) +frv_linux_sigtramp_frame_this_id (struct frame_info *this_frame, + void **this_cache, + struct frame_id *this_id) { - struct trad_frame_cache *cache = - frv_linux_sigtramp_frame_cache (next_frame, this_cache); + struct trad_frame_cache *cache + = frv_linux_sigtramp_frame_cache (this_frame, this_cache); trad_frame_get_id (cache, this_id); } -static void -frv_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, gdb_byte *valuep) +static struct value * +frv_linux_sigtramp_frame_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum) { /* Make sure we've initialized the cache. */ - struct trad_frame_cache *cache = - frv_linux_sigtramp_frame_cache (next_frame, this_cache); - trad_frame_get_register (cache, next_frame, regnum, optimizedp, lvalp, - addrp, realnump, valuep); + struct trad_frame_cache *cache + = frv_linux_sigtramp_frame_cache (this_frame, this_cache); + return trad_frame_get_register (cache, this_frame, regnum); } -static const struct frame_unwind frv_linux_sigtramp_frame_unwind = -{ - SIGTRAMP_FRAME, - frv_linux_sigtramp_frame_this_id, - frv_linux_sigtramp_frame_prev_register -}; - -static const struct frame_unwind * -frv_linux_sigtramp_frame_sniffer (struct frame_info *next_frame) +static int +frv_linux_sigtramp_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_cache) { - CORE_ADDR pc = frame_pc_unwind (next_frame); - char *name; + struct gdbarch *gdbarch = get_frame_arch (this_frame); + CORE_ADDR pc = get_frame_pc (this_frame); + const char *name; find_pc_partial_function (pc, &name, NULL, NULL); - if (frv_linux_pc_in_sigtramp (pc, name)) - return &frv_linux_sigtramp_frame_unwind; + if (frv_linux_pc_in_sigtramp (gdbarch, pc, name)) + return 1; - return NULL; + return 0; } +static const struct frame_unwind frv_linux_sigtramp_frame_unwind = +{ + SIGTRAMP_FRAME, + default_frame_unwind_stop_reason, + frv_linux_sigtramp_frame_this_id, + frv_linux_sigtramp_frame_prev_register, + NULL, + frv_linux_sigtramp_frame_sniffer +}; /* The FRV kernel defines ELF_NGREG as 46. We add 2 in order to include the loadmap addresses in the register set. (See below for more info.) */ @@ -350,37 +359,52 @@ typedef struct frv_elf_fpreg_t fsr[1]; } frv_elf_fpregset_t; -/* Constants for accessing elements of frv_elf_gregset_t. */ - -#define FRV_PT_PSR 0 -#define FRV_PT_ISR 1 -#define FRV_PT_CCR 2 -#define FRV_PT_CCCR 3 -#define FRV_PT_LR 4 -#define FRV_PT_LCR 5 -#define FRV_PT_PC 6 -#define FRV_PT_GNER0 10 -#define FRV_PT_GNER1 11 -#define FRV_PT_IACC0H 12 -#define FRV_PT_IACC0L 13 - -/* Note: Only 32 of the GRs will be found in the corefile. */ -#define FRV_PT_GR(j) ( 14 + (j)) /* GRj for 0<=j<=63. */ - -#define FRV_PT_TBR FRV_PT_GR(0) /* gr0 is always 0, so TBR is stuffed - there. */ - -/* Technically, the loadmap addresses are not part of `pr_reg' as - found in the elf_prstatus struct. The fields which communicate the - loadmap address appear (by design) immediately after `pr_reg' - though, and the BFD function elf32_frv_grok_prstatus() has been - implemented to include these fields in the register section that it - extracts from the core file. So, for our purposes, they may be - viewed as registers. */ - -#define FRV_PT_EXEC_FDPIC_LOADMAP 46 -#define FRV_PT_INTERP_FDPIC_LOADMAP 47 - +/* Register maps. */ + +static const struct regcache_map_entry frv_linux_gregmap[] = + { + { 1, psr_regnum, 4 }, + { 1, REGCACHE_MAP_SKIP, 4 }, /* isr */ + { 1, ccr_regnum, 4 }, + { 1, cccr_regnum, 4 }, + { 1, lr_regnum, 4 }, + { 1, lcr_regnum, 4 }, + { 1, pc_regnum, 4 }, + { 1, REGCACHE_MAP_SKIP, 4 }, /* __status */ + { 1, REGCACHE_MAP_SKIP, 4 }, /* syscallno */ + { 1, REGCACHE_MAP_SKIP, 4 }, /* orig_gr8 */ + { 1, gner0_regnum, 4 }, + { 1, gner1_regnum, 4 }, + { 1, REGCACHE_MAP_SKIP, 8 }, /* iacc0 */ + { 1, tbr_regnum, 4 }, + { 31, first_gpr_regnum + 1, 4 }, /* gr1 ... gr31 */ + + /* Technically, the loadmap addresses are not part of `pr_reg' as + found in the elf_prstatus struct. The fields which communicate + the loadmap address appear (by design) immediately after + `pr_reg' though, and the BFD function elf32_frv_grok_prstatus() + has been implemented to include these fields in the register + section that it extracts from the core file. So, for our + purposes, they may be viewed as registers. */ + + { 1, fdpic_loadmap_exec_regnum, 4 }, + { 1, fdpic_loadmap_interp_regnum, 4 }, + { 0 } + }; + +static const struct regcache_map_entry frv_linux_fpregmap[] = + { + { 64, first_fpr_regnum, 4 }, /* fr0 ... fr63 */ + { 1, fner0_regnum, 4 }, + { 1, fner1_regnum, 4 }, + { 1, msr0_regnum, 4 }, + { 1, msr1_regnum, 4 }, + { 8, acc0_regnum, 4 }, /* acc0 ... acc7 */ + { 1, accg0123_regnum, 4 }, + { 1, accg4567_regnum, 4 }, + { 1, fsr0_regnum, 4 }, + { 0 } + }; /* Unpack an frv_elf_gregset_t into GDB's register cache. */ @@ -390,104 +414,55 @@ frv_linux_supply_gregset (const struct regset *regset, int regnum, const void *gregs, size_t len) { int regi; - char zerobuf[MAX_REGISTER_SIZE]; - const frv_elf_gregset_t *gregsetp = gregs; - - memset (zerobuf, 0, MAX_REGISTER_SIZE); /* gr0 always contains 0. Also, the kernel passes the TBR value in this slot. */ - regcache_raw_supply (regcache, first_gpr_regnum, zerobuf); - - for (regi = first_gpr_regnum + 1; regi <= last_gpr_regnum; regi++) - { - if (regi >= first_gpr_regnum + 32) - regcache_raw_supply (regcache, regi, zerobuf); - else - regcache_raw_supply (regcache, regi, - gregsetp->reg[FRV_PT_GR (regi - first_gpr_regnum)]); - } - - regcache_raw_supply (regcache, pc_regnum, gregsetp->reg[FRV_PT_PC]); - regcache_raw_supply (regcache, psr_regnum, gregsetp->reg[FRV_PT_PSR]); - regcache_raw_supply (regcache, ccr_regnum, gregsetp->reg[FRV_PT_CCR]); - regcache_raw_supply (regcache, cccr_regnum, gregsetp->reg[FRV_PT_CCCR]); - regcache_raw_supply (regcache, lr_regnum, gregsetp->reg[FRV_PT_LR]); - regcache_raw_supply (regcache, lcr_regnum, gregsetp->reg[FRV_PT_LCR]); - regcache_raw_supply (regcache, gner0_regnum, gregsetp->reg[FRV_PT_GNER0]); - regcache_raw_supply (regcache, gner1_regnum, gregsetp->reg[FRV_PT_GNER1]); - regcache_raw_supply (regcache, tbr_regnum, gregsetp->reg[FRV_PT_TBR]); - regcache_raw_supply (regcache, fdpic_loadmap_exec_regnum, - gregsetp->reg[FRV_PT_EXEC_FDPIC_LOADMAP]); - regcache_raw_supply (regcache, fdpic_loadmap_interp_regnum, - gregsetp->reg[FRV_PT_INTERP_FDPIC_LOADMAP]); -} - -/* Unpack an frv_elf_fpregset_t into GDB's register cache. */ - -static void -frv_linux_supply_fpregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *gregs, size_t len) -{ - int regi; - const frv_elf_fpregset_t *fpregsetp = gregs; - - for (regi = first_fpr_regnum; regi <= last_fpr_regnum; regi++) - regcache_raw_supply (regcache, regi, fpregsetp->fr[regi - first_fpr_regnum]); + regcache->raw_supply_zeroed (first_gpr_regnum); - regcache_raw_supply (regcache, fner0_regnum, fpregsetp->fner[0]); - regcache_raw_supply (regcache, fner1_regnum, fpregsetp->fner[1]); + /* Fill gr32, ..., gr63 with zeros. */ + for (regi = first_gpr_regnum + 32; regi <= last_gpr_regnum; regi++) + regcache->raw_supply_zeroed (regi); - regcache_raw_supply (regcache, msr0_regnum, fpregsetp->msr[0]); - regcache_raw_supply (regcache, msr1_regnum, fpregsetp->msr[1]); - - for (regi = acc0_regnum; regi <= acc7_regnum; regi++) - regcache_raw_supply (regcache, regi, fpregsetp->acc[regi - acc0_regnum]); - - regcache_raw_supply (regcache, accg0123_regnum, fpregsetp->accg); - regcache_raw_supply (regcache, accg4567_regnum, fpregsetp->accg + 4); - - regcache_raw_supply (regcache, fsr0_regnum, fpregsetp->fsr[0]); + regcache_supply_regset (regset, regcache, regnum, gregs, len); } /* FRV Linux kernel register sets. */ -static struct regset frv_linux_gregset = +static const struct regset frv_linux_gregset = { - NULL, - frv_linux_supply_gregset + frv_linux_gregmap, + frv_linux_supply_gregset, regcache_collect_regset }; -static struct regset frv_linux_fpregset = +static const struct regset frv_linux_fpregset = { - NULL, - frv_linux_supply_fpregset + frv_linux_fpregmap, + regcache_supply_regset, regcache_collect_regset }; -static const struct regset * -frv_linux_regset_from_core_section (struct gdbarch *gdbarch, - const char *sect_name, size_t sect_size) +static void +frv_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) { - if (strcmp (sect_name, ".reg") == 0 - && sect_size >= sizeof (frv_elf_gregset_t)) - return &frv_linux_gregset; - - if (strcmp (sect_name, ".reg2") == 0 - && sect_size >= sizeof (frv_elf_fpregset_t)) - return &frv_linux_fpregset; - - return NULL; + cb (".reg", sizeof (frv_elf_gregset_t), sizeof (frv_elf_gregset_t), + &frv_linux_gregset, NULL, cb_data); + cb (".reg2", sizeof (frv_elf_fpregset_t), sizeof (frv_elf_fpregset_t), + &frv_linux_fpregset, NULL, cb_data); } static void frv_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { + linux_init_abi (info, gdbarch); + /* Set the sigtramp frame sniffer. */ - frame_unwind_append_sniffer (gdbarch, frv_linux_sigtramp_frame_sniffer); - set_gdbarch_regset_from_core_section (gdbarch, - frv_linux_regset_from_core_section); + frame_unwind_append_unwinder (gdbarch, &frv_linux_sigtramp_frame_unwind); + + set_gdbarch_iterate_over_regset_sections + (gdbarch, frv_linux_iterate_over_regset_sections); } static enum gdb_osabi @@ -506,13 +481,11 @@ frv_linux_elf_osabi_sniffer (bfd *abfd) return GDB_OSABI_UNKNOWN; } -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_frv_linux_tdep (void); - void _initialize_frv_linux_tdep (void) { - gdbarch_register_osabi (bfd_arch_frv, 0, GDB_OSABI_LINUX, frv_linux_init_abi); + gdbarch_register_osabi (bfd_arch_frv, 0, GDB_OSABI_LINUX, + frv_linux_init_abi); gdbarch_register_osabi_sniffer (bfd_arch_frv, bfd_target_elf_flavour, frv_linux_elf_osabi_sniffer);