diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 17 | ||||
-rw-r--r-- | gdb/gdbserver/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/mips-linux-nat.c | 12 | ||||
-rw-r--r-- | gdb/mips-linux-tdep.c | 109 | ||||
-rw-r--r-- | gdb/mips-linux-tdep.h | 2 | ||||
-rw-r--r-- | gdb/testsuite/gdb.arch/mips-fpregset-core.c | 82 | ||||
-rw-r--r-- | gdb/testsuite/gdb.arch/mips-fpregset-core.exp | 154 |
7 files changed, 273 insertions, 108 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 4f42528..070c991 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,20 @@ +2018-05-25 Maciej W. Rozycki <macro@mips.com> + + * mips-linux-tdep.h (mips_supply_fpregset, mips_fill_fpregset): + Remove prototypes. + * mips-linux-nat.c (supply_fpregset): Always call + `mips64_supply_fpregset' rather than `mips_supply_fpregset'. + (fill_fpregset): Always call `mips64_fill_fpregset' rather than + `mips_fill_fpregset'. + * mips-linux-tdep.c (mips_supply_fpregset) + (mips_supply_fpregset_wrapper, mips_fill_fpregset) + (mips_fill_fpregset_wrapper): Remove functions. + (mips64_supply_fpregset, mips64_fill_fpregset): Update comments. + (mips_linux_fpregset): Remove variable. + (mips_linux_iterate_over_regset_sections): Use + `mips64_linux_fpregset' in place of `mips_linux_fpregset'. + (mips_linux_o32_sigframe_init): Remove comment. + 2018-05-25 Pedro Alves <palves@redhat.com> * remote.c (struct vCont_action_support, MAXTHREADLISTRESULTS) diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 7aa5946..0224818 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,8 @@ +2018-05-25 Maciej W. Rozycki <macro@mips.com> + + * gdb.arch/mips-fpregset-core.exp: New test. + * gdb.arch/mips-fpregset-core.c: New test source. + 2018-05-23 Erik Kurzinger <ekurzinger@nvidia.com> PR server/23198 diff --git a/gdb/mips-linux-nat.c b/gdb/mips-linux-nat.c index a9f0b79..3683107 100644 --- a/gdb/mips-linux-nat.c +++ b/gdb/mips-linux-nat.c @@ -224,22 +224,14 @@ fill_gregset (const struct regcache *regcache, void supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp) { - if (mips_isa_regsize (regcache->arch ()) == 4) - mips_supply_fpregset (regcache, (const mips_elf_fpregset_t *) fpregsetp); - else - mips64_supply_fpregset (regcache, - (const mips64_elf_fpregset_t *) fpregsetp); + mips64_supply_fpregset (regcache, (const mips64_elf_fpregset_t *) fpregsetp); } void fill_fpregset (const struct regcache *regcache, gdb_fpregset_t *fpregsetp, int regno) { - if (mips_isa_regsize (regcache->arch ()) == 4) - mips_fill_fpregset (regcache, (mips_elf_fpregset_t *) fpregsetp, regno); - else - mips64_fill_fpregset (regcache, - (mips64_elf_fpregset_t *) fpregsetp, regno); + mips64_fill_fpregset (regcache, (mips64_elf_fpregset_t *) fpregsetp, regno); } diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c index 175b402..e580424 100644 --- a/gdb/mips-linux-tdep.c +++ b/gdb/mips-linux-tdep.c @@ -233,82 +233,6 @@ mips_fill_gregset_wrapper (const struct regset *regset, 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 = regcache->arch (); - int regi; - - 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_zeroed - (mips_regnum (gdbarch)->fp_implementation_revision); -} - -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 = regcache->arch (); - 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. @@ -473,7 +397,16 @@ mips64_fill_gregset_wrapper (const struct regset *regset, 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, @@ -482,8 +415,6 @@ mips64_supply_fpregset (struct regcache *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++) { @@ -523,7 +454,8 @@ mips64_supply_fpregset_wrapper (const struct regset *regset, } /* 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, @@ -535,8 +467,6 @@ mips64_fill_fpregset (const struct regcache *regcache, 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); @@ -597,11 +527,6 @@ static const struct regset mips64_linux_gregset = NULL, mips64_supply_gregset_wrapper, mips64_fill_gregset_wrapper }; -static const struct regset mips_linux_fpregset = - { - NULL, mips_supply_fpregset_wrapper, mips_fill_fpregset_wrapper - }; - static const struct regset mips64_linux_fpregset = { NULL, mips64_supply_fpregset_wrapper, mips64_fill_fpregset_wrapper @@ -617,7 +542,7 @@ mips_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, { cb (".reg", sizeof (mips_elf_gregset_t), &mips_linux_gregset, NULL, cb_data); - cb (".reg2", sizeof (mips_elf_fpregset_t), &mips_linux_fpregset, + cb (".reg2", sizeof (mips64_elf_fpregset_t), &mips64_linux_fpregset, NULL, cb_data); } else @@ -1076,14 +1001,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, diff --git a/gdb/mips-linux-tdep.h b/gdb/mips-linux-tdep.h index 83636fa..a87d555 100644 --- a/gdb/mips-linux-tdep.h +++ b/gdb/mips-linux-tdep.h @@ -52,8 +52,6 @@ typedef mips_elf_fpreg_t mips_elf_fpregset_t[ELF_NFPREG]; void mips_supply_gregset (struct regcache *, const mips_elf_gregset_t *); void mips_fill_gregset (const struct regcache *, mips_elf_gregset_t *, int); -void mips_supply_fpregset (struct regcache *, const mips_elf_fpregset_t *); -void mips_fill_fpregset (const struct regcache *, mips_elf_fpregset_t *, int); /* 64-bit support. */ diff --git a/gdb/testsuite/gdb.arch/mips-fpregset-core.c b/gdb/testsuite/gdb.arch/mips-fpregset-core.c new file mode 100644 index 0000000..f0ac31b --- /dev/null +++ b/gdb/testsuite/gdb.arch/mips-fpregset-core.c @@ -0,0 +1,82 @@ +/* This test is part of GDB, the GNU debugger. + + Copyright 2018 Free Software Foundation, Inc. + + 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 <stdint.h> + +int __attribute__ ((nomips16)) +main (void) +{ + /* We need to use a complex type to avoid hitting GCC's limit of + the number of `asm' operands: + + mips-fpregset-core.f: In function 'main': + mips-fpregset-core.f:66:3: error: more than 30 operands in 'asm' + asm ( + ^~~ + + and still have complete 32 FGR coverage with FP64 ABIs. Using + a complex type breaks o32 GCC though, so use plain `double' with + FP32. */ +#if _MIPS_FPSET == 32 + typedef double _Complex float_t; +#else + typedef double float_t; +#endif + union + { + uint64_t i[32]; + float_t f[256 / sizeof (float_t)]; + } + u = + { .i = + { + 0x0112233445566778, 0x899aabbccddeeff0, + 0x0213243546576879, 0x8a9bacbdcedfe0f1, + 0x031425364758697a, 0x8b9cadbecfd0e1f2, + 0x0415263748596a7b, 0x8c9daebfc0d1e2f3, + 0x05162738495a6b7c, 0x8d9eafb0c1d2e3f4, + 0x061728394a5b6c7d, 0x8e9fa0b1c2d3e4f5, + 0x0718293a4b5c6d7e, 0x8f90a1b2c3d4e5f6, + 0x08192a3b4c5d6e7f, 0x8091a2b3c4d5e6f7, + 0x091a2b3c4d5e6f70, 0x8192a3b4c5d6e7f8, + 0x0a1b2c3d4e5f6071, 0x8293a4b5c6d7e8f9, + 0x0b1c2d3e4f506172, 0x8394a5b6c7d8e9fa, + 0x0c1d2e3f40516273, 0x8495a6b7c8d9eafb, + 0x0d1e2f3041526374, 0x8596a7b8c9daebfc, + 0x0e1f203142536475, 0x8697a8b9cadbecfd, + 0x0f10213243546576, 0x8798a9bacbdcedfe, + 0x0011223344556677, 0x8899aabbccddeeff + } + }; + + asm ( + ".globl\tbreak_here\n\t" + ".aent\tbreak_here\n" + "break_here:\n\t" + "lb\t$0,0($0)\n" + : + : [f0] "f" (u.f[0]), [f2] "f" (u.f[1]), + [f4] "f" (u.f[2]), [f6] "f" (u.f[3]), + [f8] "f" (u.f[4]), [f10] "f" (u.f[5]), + [f12] "f" (u.f[6]), [f14] "f" (u.f[7]), + [f16] "f" (u.f[8]), [f18] "f" (u.f[9]), + [f20] "f" (u.f[10]), [f22] "f" (u.f[11]), + [f24] "f" (u.f[12]), [f26] "f" (u.f[13]), + [f28] "f" (u.f[14]), [f30] "f" (u.f[15])); + + return 0; +} diff --git a/gdb/testsuite/gdb.arch/mips-fpregset-core.exp b/gdb/testsuite/gdb.arch/mips-fpregset-core.exp new file mode 100644 index 0000000..49fcb79 --- /dev/null +++ b/gdb/testsuite/gdb.arch/mips-fpregset-core.exp @@ -0,0 +1,154 @@ +# Copyright 2018 Free Software Foundation, Inc. + +# 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/>. + +# Test MIPS Floating Point General Register handling in core files. + +if { ![istarget "mips*-*-*"] } then { + verbose "Skipping MIPS Floating Point General Register tests." + return +} + +standard_testfile + +if { [prepare_for_testing "failed to prepare" ${testfile}] } { + return +} + +# Procedure to get current content of all floating-point registers. +proc mips_fpregset_core_fetch_float_registers { test } { + global gdb_prompt + + set all_registers_lines {} + set bad -1 + # Former trailing `\[\r\n\]+' may eat just \r leaving \n in the buffer + # corrupting the next matches. + if { [gdb_test_multiple "info registers float" $test { + -re "info registers float\r\n" { + exp_continue + } + -ex "The program has no registers now" { + set bad 1 + exp_continue + } + -re "^\(?:fcsr\|fir\):\[ \t\]+\[^\r\n\]+\r\n" { + # Filter out control registers. They may or may not be a part + # of the float group depending on whether XML descriptions are + # used or not. + exp_continue + } + -re "^\[^ \t\]+\[ \t\]+\[^\r\n\]+\r\n" { + lappend all_registers_lines $expect_out(0,string) + exp_continue + } + -re "$gdb_prompt $" { + incr bad + } + -re "^\[^\r\n\]+\r\n" { + if { !$bad } { + warning "Unrecognized output: $expect_out(0,string)" + set bad 1 + } + exp_continue + } + }] != 0 } { + return {} + } + + if { $bad } { + fail $test + return {} + } + + pass $test + return $all_registers_lines +} + +# Generate a native core file. + +set corefile [core_find $binfile] +set core_supported [expr {$corefile != ""}] + +# Generate a core file with "gcore". + +clean_restart ${binfile} + +runto break_here + +# Check if we have an FPU available. +gdb_test_multiple "show mipsfpu" "check for MIPS floating-point coprocessor" { + -re "The MIPS floating-point coprocessor\ + .*\(absent\|unknown\).*$gdb_prompt $" { + unsupported "no MIPS floating-point coprocessor in the processor" + return + } + -re "The MIPS floating-point coprocessor .*$gdb_prompt $" { + verbose "MIPS floating-point coprocessor check successful." + } + default { + fail + return + } +} + +# Save live FGR register contents. +set live_fgr_contents [mips_fpregset_core_fetch_float_registers \ + "retrieve live FGR register contents"] + +set gcorefile [standard_output_file gcore.test] +set gcore_supported [gdb_gcore_cmd "$gcorefile" "gcore"] + +# Restart gdb and load COREFILE as a core file. SUPPORTED is true iff +# the core was generated successfully; otherwise, the tests are marked +# unsupported. +# +proc mips_fpregset_core_test { supported corefile } { + upvar live_fgr_contents live_fgr_contents + upvar target_triplet target_triplet + upvar host_triplet host_triplet + upvar binfile binfile + + clean_restart ${binfile} + + set test "load core file" + if { $supported } { + set core_loaded [gdb_core_cmd $corefile $test] + } else { + set core_loaded 0 + unsupported $test + } + + if { $core_loaded == 1 } { + set test "core file FGR register contents" + set core_fgr_contents \ + [mips_fpregset_core_fetch_float_registers "retrieve $test"] + if { $core_fgr_contents == $live_fgr_contents } then { + pass $test + } else { + fail $test + } + } else { + unsupported $test + } +} + +with_test_prefix "native" { + mips_fpregset_core_test $core_supported $corefile +} + +with_test_prefix "gcore" { + mips_fpregset_core_test $gcore_supported $gcorefile +} + +gdb_exit |