X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fhppa-linux-tdep.c;h=159f572d4898b7b5943fa3ffd370a2588c5079cd;hb=c17e02e1b55b5e9cbdc6581f05bfec96dc8436f4;hp=2c91441d1fa71418da6828deeb23cb211ff07b58;hpb=85c83e9940455e2c6ab318afa35a4a9d11b0a6cf;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/hppa-linux-tdep.c b/gdb/hppa-linux-tdep.c index 2c91441d1f..159f572d48 100644 --- a/gdb/hppa-linux-tdep.c +++ b/gdb/hppa-linux-tdep.c @@ -1,6 +1,6 @@ /* Target-dependent code for GNU/Linux running on PA-RISC, for GDB. - Copyright (C) 2004, 2006, 2007, 2008 Free Software Foundation, Inc. + Copyright (C) 2004-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -31,7 +31,7 @@ #include "regset.h" #include "regcache.h" #include "hppa-tdep.h" - +#include "linux-tdep.h" #include "elf/common.h" /* Map DWARF DBX register numbers to GDB register numbers. */ @@ -39,14 +39,13 @@ static int hppa_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg) { /* The general registers and the sar are the same in both sets. */ - if (reg <= 32) + if (reg >= 0 && reg <= 32) return reg; /* fr4-fr31 (left and right halves) are mapped from 72. */ if (reg >= 72 && reg <= 72 + 28 * 2) return HPPA_FP4_REGNUM + (reg - 72); - warning (_("Unmapped DWARF DBX Register #%d encountered."), reg); return -1; } @@ -55,7 +54,8 @@ hppa_linux_target_write_pc (struct regcache *regcache, CORE_ADDR v) { /* Probably this should be done by the kernel, but it isn't. */ regcache_cooked_write_unsigned (regcache, HPPA_PCOQ_HEAD_REGNUM, v | 0x3); - regcache_cooked_write_unsigned (regcache, HPPA_PCOQ_TAIL_REGNUM, (v + 4) | 0x3); + regcache_cooked_write_unsigned (regcache, + HPPA_PCOQ_TAIL_REGNUM, (v + 4) | 0x3); } /* An instruction to match. */ @@ -87,19 +87,20 @@ static struct insn_pattern hppa_sigtramp[] = { When the match is successful, fill INSN[i] with what PATTERN[i] matched. */ static int -insns_match_pattern (CORE_ADDR pc, +insns_match_pattern (struct gdbarch *gdbarch, CORE_ADDR pc, struct insn_pattern *pattern, unsigned int *insn) { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); int i; CORE_ADDR npc = pc; for (i = 0; pattern[i].mask; i++) { - char buf[4]; + gdb_byte buf[4]; target_read_memory (npc, buf, 4); - insn[i] = extract_unsigned_integer (buf, 4); + insn[i] = extract_unsigned_integer (buf, 4, byte_order); if ((insn[i] & pattern[i].mask) == pattern[i].data) npc += 4; else @@ -130,11 +131,11 @@ insns_match_pattern (CORE_ADDR pc, Note that with a 2.4 64-bit kernel, the signal context is not properly passed back to userspace so the unwind will not work correctly. */ static CORE_ADDR -hppa_linux_sigtramp_find_sigcontext (CORE_ADDR pc) +hppa_linux_sigtramp_find_sigcontext (struct gdbarch *gdbarch, CORE_ADDR pc) { unsigned int dummy[HPPA_MAX_INSN_PATTERN_LEN]; int offs = 0; - int try; + int attempt; /* offsets to try to find the trampoline */ static int pcoffs[] = { 0, 4*4, 5*4 }; /* offsets to the rt_sigframe structure */ @@ -152,24 +153,25 @@ hppa_linux_sigtramp_find_sigcontext (CORE_ADDR pc) e4008200 be,l 0x100(%sr2, %r0), %sr0, %r31 08000240 nop */ - for (try = 0; try < ARRAY_SIZE (pcoffs); try++) + for (attempt = 0; attempt < ARRAY_SIZE (pcoffs); attempt++) { - if (insns_match_pattern (sp + pcoffs[try], hppa_sigtramp, dummy)) + if (insns_match_pattern (gdbarch, sp + pcoffs[attempt], + hppa_sigtramp, dummy)) { - offs = sfoffs[try]; + offs = sfoffs[attempt]; break; } } if (offs == 0) { - if (insns_match_pattern (pc, hppa_sigtramp, dummy)) + if (insns_match_pattern (gdbarch, pc, hppa_sigtramp, dummy)) { /* sigaltstack case: we have no way of knowing which offset to - use in this case; default to new kernel handling. If this is + use in this case; default to new kernel handling. If this is wrong the unwinding will fail. */ - try = 2; - sp = pc - pcoffs[try]; + attempt = 2; + sp = pc - pcoffs[attempt]; } else { @@ -179,11 +181,11 @@ hppa_linux_sigtramp_find_sigcontext (CORE_ADDR pc) /* sp + sfoffs[try] points to a struct rt_sigframe, which contains a struct siginfo and a struct ucontext. struct ucontext contains - a struct sigcontext. Return an offset to this sigcontext here. Too - bad we cannot include system specific headers :-(. + a struct sigcontext. Return an offset to this sigcontext here. Too + bad we cannot include system specific headers :-(. sizeof(struct siginfo) == 128 offsetof(struct ucontext, uc_mcontext) == 24. */ - return sp + sfoffs[try] + 128 + 24; + return sp + sfoffs[attempt] + 128 + 24; } struct hppa_linux_sigtramp_unwind_cache @@ -202,14 +204,14 @@ hppa_linux_sigtramp_frame_unwind_cache (struct frame_info *this_frame, int i; if (*this_cache) - return *this_cache; + return (struct hppa_linux_sigtramp_unwind_cache *) *this_cache; info = FRAME_OBSTACK_ZALLOC (struct hppa_linux_sigtramp_unwind_cache); *this_cache = info; info->saved_regs = trad_frame_alloc_saved_regs (this_frame); pc = get_frame_pc (this_frame); - scptr = hppa_linux_sigtramp_find_sigcontext (pc); + scptr = hppa_linux_sigtramp_find_sigcontext (gdbarch, pc); /* structure of struct sigcontext: @@ -224,7 +226,8 @@ hppa_linux_sigtramp_frame_unwind_cache (struct frame_info *this_frame, /* Skip sc_flags. */ scptr += 4; - /* GR[0] is the psw, we don't restore that. */ + /* GR[0] is the psw. */ + info->saved_regs[HPPA_IPSW_REGNUM].addr = scptr; scptr += 4; /* General registers. */ @@ -234,7 +237,7 @@ hppa_linux_sigtramp_frame_unwind_cache (struct frame_info *this_frame, scptr += 4; } - /* Pad. */ + /* Pad to long long boundary. */ scptr += 4; /* FP regs; FP0-3 are not restored. */ @@ -248,7 +251,7 @@ hppa_linux_sigtramp_frame_unwind_cache (struct frame_info *this_frame, scptr += 4; } - /* IASQ/IAOQ. */ + /* IASQ/IAOQ. */ info->saved_regs[HPPA_PCSQ_HEAD_REGNUM].addr = scptr; scptr += 4; info->saved_regs[HPPA_PCSQ_TAIL_REGNUM].addr = scptr; @@ -259,6 +262,8 @@ hppa_linux_sigtramp_frame_unwind_cache (struct frame_info *this_frame, info->saved_regs[HPPA_PCOQ_TAIL_REGNUM].addr = scptr; scptr += 4; + info->saved_regs[HPPA_SAR_REGNUM].addr = scptr; + info->base = get_frame_register_unsigned (this_frame, HPPA_SP_REGNUM); return info; @@ -296,9 +301,10 @@ hppa_linux_sigtramp_frame_sniffer (const struct frame_unwind *self, struct frame_info *this_frame, void **this_prologue_cache) { + struct gdbarch *gdbarch = get_frame_arch (this_frame); CORE_ADDR pc = get_frame_pc (this_frame); - if (hppa_linux_sigtramp_find_sigcontext (pc)) + if (hppa_linux_sigtramp_find_sigcontext (gdbarch, pc)) return 1; return 0; @@ -306,6 +312,7 @@ hppa_linux_sigtramp_frame_sniffer (const struct frame_unwind *self, static const struct frame_unwind hppa_linux_sigtramp_frame_unwind = { SIGTRAMP_FRAME, + default_frame_unwind_stop_reason, hppa_linux_sigtramp_frame_this_id, hppa_linux_sigtramp_frame_prev_register, NULL, @@ -323,8 +330,10 @@ static const struct frame_unwind hppa_linux_sigtramp_frame_unwind = { d_un.d_ptr value is the global pointer. */ static CORE_ADDR -hppa_linux_find_global_pointer (struct gdbarch *gdbarch, struct value *function) +hppa_linux_find_global_pointer (struct gdbarch *gdbarch, + struct value *function) { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); struct obj_section *faddr_sect; CORE_ADDR faddr; @@ -334,19 +343,19 @@ hppa_linux_find_global_pointer (struct gdbarch *gdbarch, struct value *function) if (faddr & 2) { int status; - char buf[4]; + gdb_byte buf[4]; faddr &= ~3; status = target_read_memory (faddr + 4, buf, sizeof (buf)); if (status == 0) - return extract_unsigned_integer (buf, sizeof (buf)); + return extract_unsigned_integer (buf, sizeof (buf), byte_order); } /* If the address is in the plt section, then the real function hasn't yet been fixed up by the linker so we cannot determine the gp of that function. */ - if (in_plt_section (faddr, NULL)) + if (in_plt_section (faddr)) return 0; faddr_sect = find_pc_section (faddr); @@ -371,12 +380,12 @@ hppa_linux_find_global_pointer (struct gdbarch *gdbarch, struct value *function) { int status; LONGEST tag; - char buf[4]; + gdb_byte buf[4]; status = target_read_memory (addr, buf, sizeof (buf)); if (status != 0) break; - tag = extract_signed_integer (buf, sizeof (buf)); + tag = extract_signed_integer (buf, sizeof (buf), byte_order); if (tag == DT_PLTGOT) { @@ -385,9 +394,9 @@ hppa_linux_find_global_pointer (struct gdbarch *gdbarch, struct value *function) status = target_read_memory (addr + 4, buf, sizeof (buf)); if (status != 0) break; - global_pointer = extract_unsigned_integer (buf, sizeof (buf)); - - /* The payoff... */ + global_pointer = extract_unsigned_integer (buf, sizeof (buf), + byte_order); + /* The payoff... */ return global_pointer; } @@ -413,108 +422,75 @@ hppa_linux_find_global_pointer (struct gdbarch *gdbarch, struct value *function) * cr10, cr15 */ -#define GR_REGNUM(_n) (HPPA_R0_REGNUM+_n) -#define TR_REGNUM(_n) (HPPA_TR0_REGNUM+_n) -static const int greg_map[] = +static const struct regcache_map_entry hppa_linux_gregmap[] = { - GR_REGNUM(0), GR_REGNUM(1), GR_REGNUM(2), GR_REGNUM(3), - GR_REGNUM(4), GR_REGNUM(5), GR_REGNUM(6), GR_REGNUM(7), - GR_REGNUM(8), GR_REGNUM(9), GR_REGNUM(10), GR_REGNUM(11), - GR_REGNUM(12), GR_REGNUM(13), GR_REGNUM(14), GR_REGNUM(15), - GR_REGNUM(16), GR_REGNUM(17), GR_REGNUM(18), GR_REGNUM(19), - GR_REGNUM(20), GR_REGNUM(21), GR_REGNUM(22), GR_REGNUM(23), - GR_REGNUM(24), GR_REGNUM(25), GR_REGNUM(26), GR_REGNUM(27), - GR_REGNUM(28), GR_REGNUM(29), GR_REGNUM(30), GR_REGNUM(31), - - HPPA_SR4_REGNUM+1, HPPA_SR4_REGNUM+2, HPPA_SR4_REGNUM+3, HPPA_SR4_REGNUM+4, - HPPA_SR4_REGNUM, HPPA_SR4_REGNUM+5, HPPA_SR4_REGNUM+6, HPPA_SR4_REGNUM+7, - - HPPA_PCOQ_HEAD_REGNUM, HPPA_PCOQ_TAIL_REGNUM, - HPPA_PCSQ_HEAD_REGNUM, HPPA_PCSQ_TAIL_REGNUM, - - HPPA_SAR_REGNUM, HPPA_IIR_REGNUM, HPPA_ISR_REGNUM, HPPA_IOR_REGNUM, - HPPA_IPSW_REGNUM, HPPA_RCR_REGNUM, - - TR_REGNUM(0), TR_REGNUM(1), TR_REGNUM(2), TR_REGNUM(3), - TR_REGNUM(4), TR_REGNUM(5), TR_REGNUM(6), TR_REGNUM(7), - - HPPA_PID0_REGNUM, HPPA_PID1_REGNUM, HPPA_PID2_REGNUM, HPPA_PID3_REGNUM, - HPPA_CCR_REGNUM, HPPA_EIEM_REGNUM, + { 32, HPPA_R0_REGNUM }, + { 1, HPPA_SR4_REGNUM+1 }, + { 1, HPPA_SR4_REGNUM+2 }, + { 1, HPPA_SR4_REGNUM+3 }, + { 1, HPPA_SR4_REGNUM+4 }, + { 1, HPPA_SR4_REGNUM }, + { 1, HPPA_SR4_REGNUM+5 }, + { 1, HPPA_SR4_REGNUM+6 }, + { 1, HPPA_SR4_REGNUM+7 }, + { 1, HPPA_PCOQ_HEAD_REGNUM }, + { 1, HPPA_PCOQ_TAIL_REGNUM }, + { 1, HPPA_PCSQ_HEAD_REGNUM }, + { 1, HPPA_PCSQ_TAIL_REGNUM }, + { 1, HPPA_SAR_REGNUM }, + { 1, HPPA_IIR_REGNUM }, + { 1, HPPA_ISR_REGNUM }, + { 1, HPPA_IOR_REGNUM }, + { 1, HPPA_IPSW_REGNUM }, + { 1, HPPA_RCR_REGNUM }, + { 8, HPPA_TR0_REGNUM }, + { 4, HPPA_PID0_REGNUM }, + { 1, HPPA_CCR_REGNUM }, + { 1, HPPA_EIEM_REGNUM }, + { 0 } }; -static void -hppa_linux_supply_regset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *regs, size_t len) -{ - struct gdbarch *arch = get_regcache_arch (regcache); - struct gdbarch_tdep *tdep = gdbarch_tdep (arch); - const char *buf = regs; - int i, offset; - - offset = 0; - for (i = 0; i < ARRAY_SIZE (greg_map); i++) - { - if (regnum == greg_map[i] || regnum == -1) - regcache_raw_supply (regcache, greg_map[i], buf + offset); - - offset += tdep->bytes_per_address; - } -} - -static void -hppa_linux_supply_fpregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *regs, size_t len) -{ - const char *buf = regs; - int i, offset; - - offset = 0; - for (i = 0; i < 64; i++) - { - if (regnum == HPPA_FP0_REGNUM + i || regnum == -1) - regcache_raw_supply (regcache, HPPA_FP0_REGNUM + i, - buf + offset); - offset += 4; - } -} +static const struct regcache_map_entry hppa_linux_fpregmap[] = + { + /* FIXME: Only works for 32-bit mode. In 64-bit mode there should + be 32 fpregs, 8 bytes each. */ + { 64, HPPA_FP0_REGNUM, 4 }, + { 0 } + }; /* HPPA Linux kernel register set. */ -static struct regset hppa_linux_regset = +static const struct regset hppa_linux_regset = { - NULL, - hppa_linux_supply_regset + hppa_linux_gregmap, + regcache_supply_regset, regcache_collect_regset }; -static struct regset hppa_linux_fpregset = +static const struct regset hppa_linux_fpregset = { - NULL, - hppa_linux_supply_fpregset + hppa_linux_fpregmap, + regcache_supply_regset, regcache_collect_regset }; -static const struct regset * -hppa_linux_regset_from_core_section (struct gdbarch *gdbarch, - const char *sect_name, - size_t sect_size) +static void +hppa_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) - return &hppa_linux_regset; - else if (strcmp (sect_name, ".reg2") == 0) - return &hppa_linux_fpregset; + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - return NULL; + cb (".reg", 80 * tdep->bytes_per_address, 80 * tdep->bytes_per_address, + &hppa_linux_regset, NULL, cb_data); + cb (".reg2", 64 * 4, 64 * 4, &hppa_linux_fpregset, NULL, cb_data); } - - -/* Forward declarations. */ -extern initialize_file_ftype _initialize_hppa_linux_tdep; static void hppa_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + linux_init_abi (info, gdbarch); + /* GNU/Linux is always ELF. */ tdep->is_elf = 1; @@ -538,9 +514,10 @@ hppa_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) some discussions to support 128-bit long double, but it requires some more work in gcc and glibc first. */ set_gdbarch_long_double_bit (gdbarch, 64); + set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double); - set_gdbarch_regset_from_core_section - (gdbarch, hppa_linux_regset_from_core_section); + set_gdbarch_iterate_over_regset_sections + (gdbarch, hppa_linux_iterate_over_regset_sections); set_gdbarch_dwarf2_reg_to_regnum (gdbarch, hppa_dwarf_reg_to_regnum); @@ -552,6 +529,8 @@ hppa_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) void _initialize_hppa_linux_tdep (void) { - gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_LINUX, hppa_linux_init_abi); - gdbarch_register_osabi (bfd_arch_hppa, bfd_mach_hppa20w, GDB_OSABI_LINUX, hppa_linux_init_abi); + gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_LINUX, + hppa_linux_init_abi); + gdbarch_register_osabi (bfd_arch_hppa, bfd_mach_hppa20w, + GDB_OSABI_LINUX, hppa_linux_init_abi); }