aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/ChangeLog17
-rw-r--r--gdb/gdbserver/ChangeLog5
-rw-r--r--gdb/mips-linux-nat.c12
-rw-r--r--gdb/mips-linux-tdep.c109
-rw-r--r--gdb/mips-linux-tdep.h2
-rw-r--r--gdb/testsuite/gdb.arch/mips-fpregset-core.c82
-rw-r--r--gdb/testsuite/gdb.arch/mips-fpregset-core.exp154
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