X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fmips-linux-tdep.c;h=002c5c51d96c7639dbb2ddb97f1bb2ecc0a55e17;hb=63ffd7c9131c0e9723016d33cf8d435cc508d02b;hp=0c41444ed9c9b618dc029d5f3014f1b08463c1c0;hpb=ecd75fc8eed3bde86036141228074a20e55dcfc9;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c index 0c41444ed9..002c5c51d9 100644 --- a/gdb/mips-linux-tdep.c +++ b/gdb/mips-linux-tdep.c @@ -1,6 +1,6 @@ /* Target-dependent code for GNU/Linux on MIPS processors. - Copyright (C) 2001-2014 Free Software Foundation, Inc. + Copyright (C) 2001-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -23,8 +23,6 @@ #include "solib-svr4.h" #include "osabi.h" #include "mips-tdep.h" -#include -#include "gdb_assert.h" #include "frame.h" #include "regcache.h" #include "trad-frame.h" @@ -32,7 +30,6 @@ #include "gdbtypes.h" #include "objfiles.h" #include "solib.h" -#include "solib-svr4.h" #include "solist.h" #include "symtab.h" #include "target-descriptions.h" @@ -41,7 +38,12 @@ #include "glibc-tdep.h" #include "linux-tdep.h" #include "xml-syscall.h" -#include "gdb_signals.h" +#include "gdbsupport/gdb_signals.h" + +#include "features/mips-linux.c" +#include "features/mips-dsp-linux.c" +#include "features/mips64-linux.c" +#include "features/mips64-dsp-linux.c" static struct target_so_ops mips_svr4_so_ops; @@ -119,12 +121,7 @@ mips_linux_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc) static void supply_32bit_reg (struct regcache *regcache, int regnum, const void *addr) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - gdb_byte buf[MAX_REGISTER_SIZE]; - store_signed_integer (buf, register_size (gdbarch, regnum), byte_order, - extract_signed_integer (addr, 4, byte_order)); - regcache_raw_supply (regcache, regnum, buf); + regcache->raw_supply_integer (regnum, (const gdb_byte *) addr, 4, true); } /* Unpack an elf_gregset_t into GDB's register cache. */ @@ -135,10 +132,7 @@ mips_supply_gregset (struct regcache *regcache, { int regi; const mips_elf_greg_t *regp = *gregsetp; - char zerobuf[MAX_REGISTER_SIZE]; - struct gdbarch *gdbarch = get_regcache_arch (regcache); - - memset (zerobuf, 0, MAX_REGISTER_SIZE); + struct gdbarch *gdbarch = regcache->arch (); for (regi = EF_REG0 + 1; regi <= EF_REG31; regi++) supply_32bit_reg (regcache, regi - EF_REG0, regp + regi); @@ -158,7 +152,7 @@ mips_supply_gregset (struct regcache *regcache, regp + EF_CP0_CAUSE); /* Fill the inaccessible zero register with zero. */ - regcache_raw_supply (regcache, MIPS_ZERO_REGNUM, zerobuf); + regcache->raw_supply_zeroed (MIPS_ZERO_REGNUM); } static void @@ -166,7 +160,7 @@ mips_supply_gregset_wrapper (const struct regset *regset, struct regcache *regcache, int regnum, const void *gregs, size_t len) { - gdb_assert (len == sizeof (mips_elf_gregset_t)); + gdb_assert (len >= sizeof (mips_elf_gregset_t)); mips_supply_gregset (regcache, (const mips_elf_gregset_t *)gregs); } @@ -177,7 +171,7 @@ void mips_fill_gregset (const struct regcache *regcache, mips_elf_gregset_t *gregsetp, int regno) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); int regaddr, regi; mips_elf_greg_t *regp = *gregsetp; void *dst; @@ -200,7 +194,7 @@ mips_fill_gregset (const struct regcache *regcache, if (regno > 0 && regno < 32) { dst = regp + regno + EF_REG0; - regcache_raw_collect (regcache, regno, dst); + regcache->raw_collect (regno, dst); return; } @@ -225,7 +219,7 @@ mips_fill_gregset (const struct regcache *regcache, if (regaddr != -1) { dst = regp + regaddr; - regcache_raw_collect (regcache, regno, dst); + regcache->raw_collect (regno, dst); } } @@ -234,91 +228,11 @@ mips_fill_gregset_wrapper (const struct regset *regset, const struct regcache *regcache, int regnum, void *gregs, size_t len) { - gdb_assert (len == sizeof (mips_elf_gregset_t)); + gdb_assert (len >= sizeof (mips_elf_gregset_t)); mips_fill_gregset (regcache, (mips_elf_gregset_t *)gregs, regnum); } -/* Likewise, unpack an elf_fpregset_t. */ - -void -mips_supply_fpregset (struct regcache *regcache, - const mips_elf_fpregset_t *fpregsetp) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - int regi; - char zerobuf[MAX_REGISTER_SIZE]; - - memset (zerobuf, 0, MAX_REGISTER_SIZE); - - for (regi = 0; regi < 32; regi++) - regcache_raw_supply (regcache, - gdbarch_fp0_regnum (gdbarch) + regi, - *fpregsetp + regi); - - regcache_raw_supply (regcache, - mips_regnum (gdbarch)->fp_control_status, - *fpregsetp + 32); - - /* FIXME: how can we supply FCRIR? The ABI doesn't tell us. */ - regcache_raw_supply (regcache, - mips_regnum (gdbarch)->fp_implementation_revision, - zerobuf); -} - -static void -mips_supply_fpregset_wrapper (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *gregs, size_t len) -{ - gdb_assert (len == sizeof (mips_elf_fpregset_t)); - - mips_supply_fpregset (regcache, (const mips_elf_fpregset_t *)gregs); -} - -/* Likewise, pack one or all floating point registers into an - elf_fpregset_t. */ - -void -mips_fill_fpregset (const struct regcache *regcache, - mips_elf_fpregset_t *fpregsetp, int regno) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - char *to; - - if ((regno >= gdbarch_fp0_regnum (gdbarch)) - && (regno < gdbarch_fp0_regnum (gdbarch) + 32)) - { - to = (char *) (*fpregsetp + regno - gdbarch_fp0_regnum (gdbarch)); - regcache_raw_collect (regcache, regno, to); - } - else if (regno == mips_regnum (gdbarch)->fp_control_status) - { - to = (char *) (*fpregsetp + 32); - regcache_raw_collect (regcache, regno, to); - } - else if (regno == -1) - { - int regi; - - for (regi = 0; regi < 32; regi++) - mips_fill_fpregset (regcache, fpregsetp, - gdbarch_fp0_regnum (gdbarch) + regi); - mips_fill_fpregset (regcache, fpregsetp, - mips_regnum (gdbarch)->fp_control_status); - } -} - -static void -mips_fill_fpregset_wrapper (const struct regset *regset, - const struct regcache *regcache, - int regnum, void *gregs, size_t len) -{ - gdb_assert (len == sizeof (mips_elf_fpregset_t)); - - mips_fill_fpregset (regcache, (mips_elf_fpregset_t *)gregs, regnum); -} - /* Support for 64-bit ABIs. */ /* Figure out where the longjmp will land. @@ -337,7 +251,8 @@ mips64_linux_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc) CORE_ADDR jb_addr; struct gdbarch *gdbarch = get_frame_arch (frame); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - void *buf = alloca (gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT); + gdb_byte *buf + = (gdb_byte *) alloca (gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT); int element_size = gdbarch_ptr_bit (gdbarch) == 32 ? 4 : 8; jb_addr = get_frame_register_unsigned (frame, MIPS_A0_REGNUM); @@ -364,12 +279,12 @@ static void supply_64bit_reg (struct regcache *regcache, int regnum, const gdb_byte *buf) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG && register_size (gdbarch, regnum) == 4) - regcache_raw_supply (regcache, regnum, buf + 4); + regcache->raw_supply (regnum, buf + 4); else - regcache_raw_supply (regcache, regnum, buf); + regcache->raw_supply (regnum, buf); } /* Unpack a 64-bit elf_gregset_t into GDB's register cache. */ @@ -380,10 +295,7 @@ mips64_supply_gregset (struct regcache *regcache, { int regi; const mips64_elf_greg_t *regp = *gregsetp; - gdb_byte zerobuf[MAX_REGISTER_SIZE]; - struct gdbarch *gdbarch = get_regcache_arch (regcache); - - memset (zerobuf, 0, MAX_REGISTER_SIZE); + struct gdbarch *gdbarch = regcache->arch (); for (regi = MIPS64_EF_REG0 + 1; regi <= MIPS64_EF_REG31; regi++) supply_64bit_reg (regcache, regi - MIPS64_EF_REG0, @@ -408,7 +320,7 @@ mips64_supply_gregset (struct regcache *regcache, (const gdb_byte *) (regp + MIPS64_EF_CP0_CAUSE)); /* Fill the inaccessible zero register with zero. */ - regcache_raw_supply (regcache, MIPS_ZERO_REGNUM, zerobuf); + regcache->raw_supply_zeroed (MIPS_ZERO_REGNUM); } static void @@ -416,7 +328,7 @@ mips64_supply_gregset_wrapper (const struct regset *regset, struct regcache *regcache, int regnum, const void *gregs, size_t len) { - gdb_assert (len == sizeof (mips64_elf_gregset_t)); + gdb_assert (len >= sizeof (mips64_elf_gregset_t)); mips64_supply_gregset (regcache, (const mips64_elf_gregset_t *)gregs); } @@ -427,8 +339,7 @@ void mips64_fill_gregset (const struct regcache *regcache, mips64_elf_gregset_t *gregsetp, int regno) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + struct gdbarch *gdbarch = regcache->arch (); int regaddr, regi; mips64_elf_greg_t *regp = *gregsetp; void *dst; @@ -471,14 +382,8 @@ mips64_fill_gregset (const struct regcache *regcache, if (regaddr != -1) { - gdb_byte buf[MAX_REGISTER_SIZE]; - LONGEST val; - - regcache_raw_collect (regcache, regno, buf); - val = extract_signed_integer (buf, register_size (gdbarch, regno), - byte_order); dst = regp + regaddr; - store_signed_integer (dst, 8, byte_order, val); + regcache->raw_collect_integer (regno, (gdb_byte *) dst, 8, true); } } @@ -487,22 +392,29 @@ mips64_fill_gregset_wrapper (const struct regset *regset, const struct regcache *regcache, int regnum, void *gregs, size_t len) { - gdb_assert (len == sizeof (mips64_elf_gregset_t)); + gdb_assert (len >= sizeof (mips64_elf_gregset_t)); mips64_fill_gregset (regcache, (mips64_elf_gregset_t *)gregs, regnum); } -/* Likewise, unpack an elf_fpregset_t. */ +/* Likewise, unpack an elf_fpregset_t. Linux only uses even-numbered + FPR slots in the Status.FR=0 mode, storing even-odd FPR pairs as the + SDC1 instruction would. When run on MIPS I architecture processors + all FPR slots used to be used, unusually, holding the respective FPRs + in the first 4 bytes, but that was corrected for consistency, with + `linux-mips.org' (LMO) commit 42533948caac ("Major pile of FP emulator + changes."), the fix corrected with LMO commit 849fa7a50dff ("R3k FPU + ptrace() handling fixes."), and then broken and fixed over and over + again, until last time fixed with commit 80cbfad79096 ("MIPS: Correct + MIPS I FP context layout"). */ void mips64_supply_fpregset (struct regcache *regcache, const mips64_elf_fpregset_t *fpregsetp) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); int regi; - /* See mips_linux_o32_sigframe_init for a description of the - peculiar FP register layout. */ if (register_size (gdbarch, gdbarch_fp0_regnum (gdbarch)) == 4) for (regi = 0; regi < 32; regi++) { @@ -510,15 +422,12 @@ mips64_supply_fpregset (struct regcache *regcache, = (const gdb_byte *) (*fpregsetp + (regi & ~1)); if ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) != (regi & 1)) reg_ptr += 4; - regcache_raw_supply (regcache, - gdbarch_fp0_regnum (gdbarch) + regi, - reg_ptr); + regcache->raw_supply (gdbarch_fp0_regnum (gdbarch) + regi, reg_ptr); } else for (regi = 0; regi < 32; regi++) - regcache_raw_supply (regcache, - gdbarch_fp0_regnum (gdbarch) + regi, - (const char *) (*fpregsetp + regi)); + regcache->raw_supply (gdbarch_fp0_regnum (gdbarch) + regi, + (const char *) (*fpregsetp + regi)); supply_32bit_reg (regcache, mips_regnum (gdbarch)->fp_control_status, (const gdb_byte *) (*fpregsetp + 32)); @@ -536,27 +445,25 @@ mips64_supply_fpregset_wrapper (const struct regset *regset, struct regcache *regcache, int regnum, const void *gregs, size_t len) { - gdb_assert (len == sizeof (mips64_elf_fpregset_t)); + gdb_assert (len >= sizeof (mips64_elf_fpregset_t)); mips64_supply_fpregset (regcache, (const mips64_elf_fpregset_t *)gregs); } /* Likewise, pack one or all floating point registers into an - elf_fpregset_t. */ + elf_fpregset_t. See `mips_supply_fpregset' for an explanation + of the layout. */ void mips64_fill_fpregset (const struct regcache *regcache, mips64_elf_fpregset_t *fpregsetp, int regno) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + struct gdbarch *gdbarch = regcache->arch (); gdb_byte *to; if ((regno >= gdbarch_fp0_regnum (gdbarch)) && (regno < gdbarch_fp0_regnum (gdbarch) + 32)) { - /* See mips_linux_o32_sigframe_init for a description of the - peculiar FP register layout. */ if (register_size (gdbarch, regno) == 4) { int regi = regno - gdbarch_fp0_regnum (gdbarch); @@ -564,36 +471,24 @@ mips64_fill_fpregset (const struct regcache *regcache, to = (gdb_byte *) (*fpregsetp + (regi & ~1)); if ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) != (regi & 1)) to += 4; - regcache_raw_collect (regcache, regno, to); + regcache->raw_collect (regno, to); } else { to = (gdb_byte *) (*fpregsetp + regno - gdbarch_fp0_regnum (gdbarch)); - regcache_raw_collect (regcache, regno, to); + regcache->raw_collect (regno, to); } } else if (regno == mips_regnum (gdbarch)->fp_control_status) { - gdb_byte buf[MAX_REGISTER_SIZE]; - LONGEST val; - - regcache_raw_collect (regcache, regno, buf); - val = extract_signed_integer (buf, register_size (gdbarch, regno), - byte_order); to = (gdb_byte *) (*fpregsetp + 32); - store_signed_integer (to, 4, byte_order, val); + regcache->raw_collect_integer (regno, to, 4, true); } else if (regno == mips_regnum (gdbarch)->fp_implementation_revision) { - gdb_byte buf[MAX_REGISTER_SIZE]; - LONGEST val; - - regcache_raw_collect (regcache, regno, buf); - val = extract_signed_integer (buf, register_size (gdbarch, regno), - byte_order); to = (gdb_byte *) (*fpregsetp + 32) + 4; - store_signed_integer (to, 4, byte_order, val); + regcache->raw_collect_integer (regno, to, 4, true); } else if (regno == -1) { @@ -614,69 +509,48 @@ mips64_fill_fpregset_wrapper (const struct regset *regset, const struct regcache *regcache, int regnum, void *gregs, size_t len) { - gdb_assert (len == sizeof (mips64_elf_fpregset_t)); + gdb_assert (len >= sizeof (mips64_elf_fpregset_t)); mips64_fill_fpregset (regcache, (mips64_elf_fpregset_t *)gregs, regnum); } -static const struct regset * -mips_linux_regset_from_core_section (struct gdbarch *gdbarch, - const char *sect_name, size_t sect_size) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - mips_elf_gregset_t gregset; - mips_elf_fpregset_t fpregset; - mips64_elf_gregset_t gregset64; - mips64_elf_fpregset_t fpregset64; +static const struct regset mips_linux_gregset = + { + NULL, mips_supply_gregset_wrapper, mips_fill_gregset_wrapper + }; + +static const struct regset mips64_linux_gregset = + { + NULL, mips64_supply_gregset_wrapper, mips64_fill_gregset_wrapper + }; + +static const struct regset mips64_linux_fpregset = + { + NULL, mips64_supply_fpregset_wrapper, mips64_fill_fpregset_wrapper + }; - if (strcmp (sect_name, ".reg") == 0) +static void +mips_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + if (register_size (gdbarch, MIPS_ZERO_REGNUM) == 4) { - if (sect_size == sizeof (gregset)) - { - if (tdep->gregset == NULL) - tdep->gregset = regset_alloc (gdbarch, - mips_supply_gregset_wrapper, - mips_fill_gregset_wrapper); - return tdep->gregset; - } - else if (sect_size == sizeof (gregset64)) - { - if (tdep->gregset64 == NULL) - tdep->gregset64 = regset_alloc (gdbarch, - mips64_supply_gregset_wrapper, - mips64_fill_gregset_wrapper); - return tdep->gregset64; - } - else - { - warning (_("wrong size gregset struct in core file")); - } + cb (".reg", sizeof (mips_elf_gregset_t), sizeof (mips_elf_gregset_t), + &mips_linux_gregset, NULL, cb_data); + cb (".reg2", sizeof (mips64_elf_fpregset_t), + sizeof (mips64_elf_fpregset_t), &mips64_linux_fpregset, + NULL, cb_data); } - else if (strcmp (sect_name, ".reg2") == 0) + else { - if (sect_size == sizeof (fpregset)) - { - if (tdep->fpregset == NULL) - tdep->fpregset = regset_alloc (gdbarch, - mips_supply_fpregset_wrapper, - mips_fill_fpregset_wrapper); - return tdep->fpregset; - } - else if (sect_size == sizeof (fpregset64)) - { - if (tdep->fpregset64 == NULL) - tdep->fpregset64 = regset_alloc (gdbarch, - mips64_supply_fpregset_wrapper, - mips64_fill_fpregset_wrapper); - return tdep->fpregset64; - } - else - { - warning (_("wrong size fpregset struct in core file")); - } + cb (".reg", sizeof (mips64_elf_gregset_t), sizeof (mips64_elf_gregset_t), + &mips64_linux_gregset, NULL, cb_data); + cb (".reg2", sizeof (mips64_elf_fpregset_t), + sizeof (mips64_elf_fpregset_t), &mips64_linux_fpregset, + NULL, cb_data); } - - return NULL; } static const struct target_desc * @@ -688,7 +562,7 @@ mips_linux_core_read_description (struct gdbarch *gdbarch, if (! section) return NULL; - switch (bfd_section_size (abfd, section)) + switch (bfd_section_size (section)) { case sizeof (mips_elf_gregset_t): return mips_tdesc_gp32; @@ -758,15 +632,17 @@ mips_linux_in_dynsym_stub (CORE_ADDR pc) insn = extract_unsigned_integer (p + 4, 4, byte_order); if (n64) { - /* daddu t7,ra */ - if (insn != 0x03e0782d) + /* 'daddu t7,ra' or 'or t7, ra, zero'*/ + if (insn != 0x03e0782d || insn != 0x03e07825) return 0; + } else { - /* addu t7,ra */ - if (insn != 0x03e07821) + /* 'addu t7,ra' or 'or t7, ra, zero'*/ + if (insn != 0x03e07821 || insn != 0x03e07825) return 0; + } insn = extract_unsigned_integer (p + 8, 4, byte_order); @@ -823,11 +699,11 @@ mips_linux_in_dynsym_resolve_code (CORE_ADDR pc) static CORE_ADDR mips_linux_skip_resolver (struct gdbarch *gdbarch, CORE_ADDR pc) { - struct minimal_symbol *resolver; + struct bound_minimal_symbol resolver; resolver = lookup_minimal_symbol ("__dl_runtime_resolve", NULL, NULL); - if (resolver && SYMBOL_VALUE_ADDRESS (resolver) == pc) + if (resolver.minsym && BMSYMBOL_VALUE_ADDRESS (resolver) == pc) return frame_unwind_caller_pc (get_current_frame ()); return glibc_skip_solib_resolver (gdbarch, pc); @@ -848,6 +724,14 @@ static void mips_linux_n32n64_sigframe_init (const struct tramp_frame *self, struct trad_frame_cache *this_cache, CORE_ADDR func); +static int mips_linux_sigframe_validate (const struct tramp_frame *self, + struct frame_info *this_frame, + CORE_ADDR *pc); + +static int micromips_linux_sigframe_validate (const struct tramp_frame *self, + struct frame_info *this_frame, + CORE_ADDR *pc); + #define MIPS_NR_LINUX 4000 #define MIPS_NR_N64_LINUX 5000 #define MIPS_NR_N32_LINUX 6000 @@ -863,47 +747,111 @@ static void mips_linux_n32n64_sigframe_init (const struct tramp_frame *self, #define MIPS_INST_LI_V0_N32_RT_SIGRETURN 0x24020000 + MIPS_NR_N32_rt_sigreturn #define MIPS_INST_SYSCALL 0x0000000c +#define MICROMIPS_INST_LI_V0 0x3040 +#define MICROMIPS_INST_POOL32A 0x0000 +#define MICROMIPS_INST_SYSCALL 0x8b7c + static const struct tramp_frame mips_linux_o32_sigframe = { SIGTRAMP_FRAME, 4, { - { MIPS_INST_LI_V0_SIGRETURN, -1 }, - { MIPS_INST_SYSCALL, -1 }, - { TRAMP_SENTINEL_INSN, -1 } + { MIPS_INST_LI_V0_SIGRETURN, ULONGEST_MAX }, + { MIPS_INST_SYSCALL, ULONGEST_MAX }, + { TRAMP_SENTINEL_INSN, ULONGEST_MAX } }, - mips_linux_o32_sigframe_init + mips_linux_o32_sigframe_init, + mips_linux_sigframe_validate }; static const struct tramp_frame mips_linux_o32_rt_sigframe = { SIGTRAMP_FRAME, 4, { - { MIPS_INST_LI_V0_RT_SIGRETURN, -1 }, - { MIPS_INST_SYSCALL, -1 }, - { TRAMP_SENTINEL_INSN, -1 } }, - mips_linux_o32_sigframe_init + { MIPS_INST_LI_V0_RT_SIGRETURN, ULONGEST_MAX }, + { MIPS_INST_SYSCALL, ULONGEST_MAX }, + { TRAMP_SENTINEL_INSN, ULONGEST_MAX } }, + mips_linux_o32_sigframe_init, + mips_linux_sigframe_validate }; static const struct tramp_frame mips_linux_n32_rt_sigframe = { SIGTRAMP_FRAME, 4, { - { MIPS_INST_LI_V0_N32_RT_SIGRETURN, -1 }, - { MIPS_INST_SYSCALL, -1 }, - { TRAMP_SENTINEL_INSN, -1 } + { MIPS_INST_LI_V0_N32_RT_SIGRETURN, ULONGEST_MAX }, + { MIPS_INST_SYSCALL, ULONGEST_MAX }, + { TRAMP_SENTINEL_INSN, ULONGEST_MAX } }, - mips_linux_n32n64_sigframe_init + mips_linux_n32n64_sigframe_init, + mips_linux_sigframe_validate }; static const struct tramp_frame mips_linux_n64_rt_sigframe = { SIGTRAMP_FRAME, 4, { - { MIPS_INST_LI_V0_N64_RT_SIGRETURN, -1 }, - { MIPS_INST_SYSCALL, -1 }, - { TRAMP_SENTINEL_INSN, -1 } + { MIPS_INST_LI_V0_N64_RT_SIGRETURN, ULONGEST_MAX }, + { MIPS_INST_SYSCALL, ULONGEST_MAX }, + { TRAMP_SENTINEL_INSN, ULONGEST_MAX } + }, + mips_linux_n32n64_sigframe_init, + mips_linux_sigframe_validate +}; + +static const struct tramp_frame micromips_linux_o32_sigframe = { + SIGTRAMP_FRAME, + 2, + { + { MICROMIPS_INST_LI_V0, ULONGEST_MAX }, + { MIPS_NR_sigreturn, ULONGEST_MAX }, + { MICROMIPS_INST_POOL32A, ULONGEST_MAX }, + { MICROMIPS_INST_SYSCALL, ULONGEST_MAX }, + { TRAMP_SENTINEL_INSN, ULONGEST_MAX } + }, + mips_linux_o32_sigframe_init, + micromips_linux_sigframe_validate +}; + +static const struct tramp_frame micromips_linux_o32_rt_sigframe = { + SIGTRAMP_FRAME, + 2, + { + { MICROMIPS_INST_LI_V0, ULONGEST_MAX }, + { MIPS_NR_rt_sigreturn, ULONGEST_MAX }, + { MICROMIPS_INST_POOL32A, ULONGEST_MAX }, + { MICROMIPS_INST_SYSCALL, ULONGEST_MAX }, + { TRAMP_SENTINEL_INSN, ULONGEST_MAX } + }, + mips_linux_o32_sigframe_init, + micromips_linux_sigframe_validate +}; + +static const struct tramp_frame micromips_linux_n32_rt_sigframe = { + SIGTRAMP_FRAME, + 2, + { + { MICROMIPS_INST_LI_V0, ULONGEST_MAX }, + { MIPS_NR_N32_rt_sigreturn, ULONGEST_MAX }, + { MICROMIPS_INST_POOL32A, ULONGEST_MAX }, + { MICROMIPS_INST_SYSCALL, ULONGEST_MAX }, + { TRAMP_SENTINEL_INSN, ULONGEST_MAX } }, - mips_linux_n32n64_sigframe_init + mips_linux_n32n64_sigframe_init, + micromips_linux_sigframe_validate +}; + +static const struct tramp_frame micromips_linux_n64_rt_sigframe = { + SIGTRAMP_FRAME, + 2, + { + { MICROMIPS_INST_LI_V0, ULONGEST_MAX }, + { MIPS_NR_N64_rt_sigreturn, ULONGEST_MAX }, + { MICROMIPS_INST_POOL32A, ULONGEST_MAX }, + { MICROMIPS_INST_SYSCALL, ULONGEST_MAX }, + { TRAMP_SENTINEL_INSN, ULONGEST_MAX } + }, + mips_linux_n32n64_sigframe_init, + micromips_linux_sigframe_validate }; /* *INDENT-OFF* */ @@ -1023,7 +971,8 @@ mips_linux_o32_sigframe_init (const struct tramp_frame *self, const struct mips_regnum *regs = mips_regnum (gdbarch); CORE_ADDR regs_base; - if (self == &mips_linux_o32_sigframe) + if (self == &mips_linux_o32_sigframe + || self == µmips_linux_o32_sigframe) sigcontext_base = frame_sp + SIGFRAME_SIGCONTEXT_OFFSET; else sigcontext_base = frame_sp + RTSIGFRAME_SIGCONTEXT_OFFSET; @@ -1051,14 +1000,6 @@ mips_linux_o32_sigframe_init (const struct tramp_frame *self, (regs_base + SIGCONTEXT_REGS + ireg * SIGCONTEXT_REG_SIZE)); - /* The way that floating point registers are saved, unfortunately, - depends on the architecture the kernel is built for. For the r3000 and - tx39, four bytes of each register are at the beginning of each of the - 32 eight byte slots. For everything else, the registers are saved - using double precision; only the even-numbered slots are initialized, - and the high bits are the odd-numbered register. Assume the latter - layout, since we can't tell, and it's much more common. Which bits are - the "high" bits depends on endianness. */ for (ireg = 0; ireg < 32; ireg++) if ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) != (ireg & 1)) trad_frame_set_reg_addr (this_cache, @@ -1224,7 +1165,8 @@ mips_linux_n32n64_sigframe_init (const struct tramp_frame *self, CORE_ADDR sigcontext_base; const struct mips_regnum *regs = mips_regnum (gdbarch); - if (self == &mips_linux_n32_rt_sigframe) + if (self == &mips_linux_n32_rt_sigframe + || self == µmips_linux_n32_rt_sigframe) sigcontext_base = frame_sp + N32_SIGFRAME_SIGCONTEXT_OFFSET; else sigcontext_base = frame_sp + N64_SIGFRAME_SIGCONTEXT_OFFSET; @@ -1294,12 +1236,38 @@ mips_linux_n32n64_sigframe_init (const struct tramp_frame *self, trad_frame_set_id (this_cache, frame_id_build (frame_sp, func)); } +/* Implement struct tramp_frame's "validate" method for standard MIPS code. */ + +static int +mips_linux_sigframe_validate (const struct tramp_frame *self, + struct frame_info *this_frame, + CORE_ADDR *pc) +{ + return mips_pc_is_mips (*pc); +} + +/* Implement struct tramp_frame's "validate" method for microMIPS code. */ + +static int +micromips_linux_sigframe_validate (const struct tramp_frame *self, + struct frame_info *this_frame, + CORE_ADDR *pc) +{ + if (mips_pc_is_micromips (get_frame_arch (this_frame), *pc)) + { + *pc = mips_unmake_compact_addr (*pc); + return 1; + } + else + return 0; +} + /* Implement the "write_pc" gdbarch method. */ static void mips_linux_write_pc (struct regcache *regcache, CORE_ADDR pc) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch *gdbarch = regcache->arch (); mips_write_pc (regcache, pc); @@ -1348,9 +1316,9 @@ mips_linux_syscall_next_pc (struct frame_info *frame) static LONGEST mips_linux_get_syscall_number (struct gdbarch *gdbarch, - ptid_t ptid) + thread_info *thread) { - struct regcache *regcache = get_thread_regcache (ptid); + struct regcache *regcache = get_thread_regcache (thread); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); int regsize = register_size (gdbarch, MIPS_V0_REGNUM); @@ -1368,7 +1336,7 @@ mips_linux_get_syscall_number (struct gdbarch *gdbarch, /* Getting the system call number from the register. syscall number is in v0 or $2. */ - regcache_cooked_read (regcache, MIPS_V0_REGNUM, buf); + regcache->cooked_read (MIPS_V0_REGNUM, buf); ret = extract_signed_integer (buf, regsize, byte_order); @@ -1469,7 +1437,7 @@ mips_gdb_signal_to_target (struct gdbarch *gdbarch, } /* Translate signals based on MIPS signal values. - Adapted from gdb/common/signals.c. */ + Adapted from gdb/gdbsupport/signals.c. */ static enum gdb_signal mips_gdb_signal_from_target (struct gdbarch *gdbarch, int signal) @@ -1563,7 +1531,7 @@ mips_linux_init_abi (struct gdbarch_info info, { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum mips_abi abi = mips_abi (gdbarch); - struct tdesc_arch_data *tdesc_data = (void *) info.tdep_info; + struct tdesc_arch_data *tdesc_data = info.tdesc_data; linux_init_abi (info, gdbarch); @@ -1577,9 +1545,12 @@ mips_linux_init_abi (struct gdbarch_info info, mips_linux_get_longjmp_target); set_solib_svr4_fetch_link_map_offsets (gdbarch, svr4_ilp32_fetch_link_map_offsets); + tramp_frame_prepend_unwinder (gdbarch, µmips_linux_o32_sigframe); + tramp_frame_prepend_unwinder (gdbarch, + µmips_linux_o32_rt_sigframe); tramp_frame_prepend_unwinder (gdbarch, &mips_linux_o32_sigframe); tramp_frame_prepend_unwinder (gdbarch, &mips_linux_o32_rt_sigframe); - set_xml_syscall_file_name ("syscalls/mips-o32-linux.xml"); + set_xml_syscall_file_name (gdbarch, "syscalls/mips-o32-linux.xml"); break; case MIPS_ABI_N32: set_gdbarch_get_longjmp_target (gdbarch, @@ -1592,8 +1563,10 @@ mips_linux_init_abi (struct gdbarch_info info, except that the quiet/signalling NaN bit is reversed (GDB does not distinguish between quiet and signalling NaNs). */ set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad); + tramp_frame_prepend_unwinder (gdbarch, + µmips_linux_n32_rt_sigframe); tramp_frame_prepend_unwinder (gdbarch, &mips_linux_n32_rt_sigframe); - set_xml_syscall_file_name ("syscalls/mips-n32-linux.xml"); + set_xml_syscall_file_name (gdbarch, "syscalls/mips-n32-linux.xml"); break; case MIPS_ABI_N64: set_gdbarch_get_longjmp_target (gdbarch, @@ -1606,8 +1579,10 @@ mips_linux_init_abi (struct gdbarch_info info, except that the quiet/signalling NaN bit is reversed (GDB does not distinguish between quiet and signalling NaNs). */ set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad); + tramp_frame_prepend_unwinder (gdbarch, + µmips_linux_n64_rt_sigframe); tramp_frame_prepend_unwinder (gdbarch, &mips_linux_n64_rt_sigframe); - set_xml_syscall_file_name ("syscalls/mips-n64-linux.xml"); + set_xml_syscall_file_name (gdbarch, "syscalls/mips-n64-linux.xml"); break; default: break; @@ -1636,8 +1611,8 @@ mips_linux_init_abi (struct gdbarch_info info, set_gdbarch_core_read_description (gdbarch, mips_linux_core_read_description); - set_gdbarch_regset_from_core_section (gdbarch, - mips_linux_regset_from_core_section); + set_gdbarch_iterate_over_regset_sections + (gdbarch, mips_linux_iterate_over_regset_sections); set_gdbarch_gdb_signal_from_target (gdbarch, mips_gdb_signal_from_target); @@ -1667,9 +1642,6 @@ mips_linux_init_abi (struct gdbarch_info info, } } -/* Provide a prototype to silence -Wmissing-prototypes. */ -extern initialize_file_ftype _initialize_mips_linux_tdep; - void _initialize_mips_linux_tdep (void) { @@ -1683,4 +1655,10 @@ _initialize_mips_linux_tdep (void) GDB_OSABI_LINUX, mips_linux_init_abi); } + + /* Initialize the standard target descriptions. */ + initialize_tdesc_mips_linux (); + initialize_tdesc_mips_dsp_linux (); + initialize_tdesc_mips64_linux (); + initialize_tdesc_mips64_dsp_linux (); }