aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Schauer <Peter.Schauer@mytum.de>2000-04-13 18:11:41 +0000
committerPeter Schauer <Peter.Schauer@mytum.de>2000-04-13 18:11:41 +0000
commit14164c30b6b5ae623fd1cd75384179d9fef368d6 (patch)
tree0175426db93d3a1413cf09e375d8799bce41c2e6
parentdb348f274580cbf2c07ab62ea3ff2a710709e076 (diff)
downloadgdb-14164c30b6b5ae623fd1cd75384179d9fef368d6.zip
gdb-14164c30b6b5ae623fd1cd75384179d9fef368d6.tar.gz
gdb-14164c30b6b5ae623fd1cd75384179d9fef368d6.tar.bz2
* config/i386/nm-i386sol2.h (CANNOT_STEP_HW_WATCHPOINTS): Define.
* config/i386/tm-i386sol2.h (HAVE_I387_REGS): Define. * i386v4-nat.c (supply_fpregset, fill_fpregset): Add code to handle floating point registers if NUM_FREGS is not zero.
-rw-r--r--gdb/ChangeLog7
-rw-r--r--gdb/config/i386/nm-i386sol2.h10
-rw-r--r--gdb/config/i386/tm-i386sol2.h1
-rw-r--r--gdb/i386v4-nat.c88
4 files changed, 102 insertions, 4 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a5a7685..318c1d3 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,10 @@
+2000-04-13 Peter Schauer <pes@regent.e-technik.tu-muenchen.de>
+
+ * config/i386/nm-i386sol2.h (CANNOT_STEP_HW_WATCHPOINTS): Define.
+ * config/i386/tm-i386sol2.h (HAVE_I387_REGS): Define.
+ * i386v4-nat.c (supply_fpregset, fill_fpregset): Add code
+ to handle floating point registers if NUM_FREGS is not zero.
+
2000-04-13 Nick Duffek <nsd@cygnus.com>
* sol-thread.c (init_sol_core_ops): Initialize to_thread_alive
diff --git a/gdb/config/i386/nm-i386sol2.h b/gdb/config/i386/nm-i386sol2.h
index 2c4b4d4..8f29711 100644
--- a/gdb/config/i386/nm-i386sol2.h
+++ b/gdb/config/i386/nm-i386sol2.h
@@ -34,6 +34,16 @@
It will *NOT* be necessary for GDB to step over the watchpoint. */
#define HAVE_CONTINUABLE_WATCHPOINT
+/* Solaris x86 2.6 and 2.7 targets have a kernel bug when stepping
+ over an instruction that causes a page fault without triggering
+ a hardware watchpoint. The kernel properly notices that it shouldn't
+ stop, because the hardware watchpoint is not triggered, but it forgets
+ the step request and continues the program normally.
+ Work around the problem by removing hardware watchpoints if a step is
+ requested, GDB will check for a hardware watchpoint trigger after the
+ step anyway. */
+#define CANNOT_STEP_HW_WATCHPOINTS
+
extern int procfs_stopped_by_watchpoint PARAMS ((int));
#define STOPPED_BY_WATCHPOINT(W) \
procfs_stopped_by_watchpoint(inferior_pid)
diff --git a/gdb/config/i386/tm-i386sol2.h b/gdb/config/i386/tm-i386sol2.h
index da231eb..a15d812 100644
--- a/gdb/config/i386/tm-i386sol2.h
+++ b/gdb/config/i386/tm-i386sol2.h
@@ -21,6 +21,7 @@
#ifndef TM_I386SOL2_H
#define TM_I386SOL2_H 1
+#define HAVE_I387_REGS
#include "i386/tm-i386v4.h"
/* Signal handler frames under Solaris 2 are recognized by a return address
diff --git a/gdb/i386v4-nat.c b/gdb/i386v4-nat.c
index 10802cb..056ea7f 100644
--- a/gdb/i386v4-nat.c
+++ b/gdb/i386v4-nat.c
@@ -142,17 +142,65 @@ fill_gregset (gregsetp, regno)
#endif /* HAVE_GREGSET_T */
-#if defined (FP0_REGNUM) && defined (HAVE_FPREGSET_T)
+#if defined (HAVE_FPREGSET_T)
/* Given a pointer to a floating point register set in /proc format
(fpregset_t *), unpack the register contents and supply them as gdb's
idea of the current floating point register values. */
+/* FIXME: Assumes that fpregsetp contains an i387 FSAVE area. */
+static const int freg_offset_map[] =
+{
+#if !defined(FPREGSET_FSAVE_OFFSET)
+#define FPREGSET_FSAVE_OFFSET 0
+#endif
+ FPREGSET_FSAVE_OFFSET + 28 + 0 * 10,
+ FPREGSET_FSAVE_OFFSET + 28 + 1 * 10,
+ FPREGSET_FSAVE_OFFSET + 28 + 2 * 10,
+ FPREGSET_FSAVE_OFFSET + 28 + 3 * 10,
+ FPREGSET_FSAVE_OFFSET + 28 + 4 * 10,
+ FPREGSET_FSAVE_OFFSET + 28 + 5 * 10,
+ FPREGSET_FSAVE_OFFSET + 28 + 6 * 10,
+ FPREGSET_FSAVE_OFFSET + 28 + 7 * 10,
+ FPREGSET_FSAVE_OFFSET + 0,
+ FPREGSET_FSAVE_OFFSET + 4,
+ FPREGSET_FSAVE_OFFSET + 8,
+ FPREGSET_FSAVE_OFFSET + 16,
+ FPREGSET_FSAVE_OFFSET + 12,
+ FPREGSET_FSAVE_OFFSET + 24,
+ FPREGSET_FSAVE_OFFSET + 20,
+ FPREGSET_FSAVE_OFFSET + 16
+};
+
void
supply_fpregset (fpregsetp)
fpregset_t *fpregsetp;
{
- /* FIXME: see m68k-tdep.c for an example, for the m68k. */
+ int regi;
+
+ if (NUM_FREGS == 0)
+ return;
+ for (regi = FP0_REGNUM; regi <= LAST_FPU_CTRL_REGNUM; regi++)
+ {
+ char tbuf[4];
+ ULONGEST tval;
+ char *from = (char *) fpregsetp + freg_offset_map[regi - FP0_REGNUM];
+
+ if (regi == FCS_REGNUM)
+ {
+ tval = extract_unsigned_integer (from, 4) & 0xffff;
+ store_unsigned_integer (tbuf, 4, tval);
+ supply_register (regi, tbuf);
+ }
+ else if (regi == FOP_REGNUM)
+ {
+ tval = (extract_unsigned_integer (from, 4) >> 16) & ((1 << 11) - 1);
+ store_unsigned_integer (tbuf, 4, tval);
+ supply_register (regi, tbuf);
+ }
+ else
+ supply_register (regi, from);
+ }
}
/* Given a pointer to a floating point register set in /proc format
@@ -165,9 +213,41 @@ fill_fpregset (fpregsetp, regno)
fpregset_t *fpregsetp;
int regno;
{
- /* FIXME: see m68k-tdep.c for an example, for the m68k. */
+ int regi;
+
+ if (NUM_FREGS == 0)
+ return;
+ for (regi = FP0_REGNUM; regi <= LAST_FPU_CTRL_REGNUM; regi++)
+ {
+ if ((regno == -1) || (regno == regi))
+ {
+ char *to = (char *) fpregsetp + freg_offset_map[regi - FP0_REGNUM];
+ char *from = (char *) &registers[REGISTER_BYTE (regi)];
+ ULONGEST valto;
+ ULONGEST valfrom;
+
+ if (regi == FCS_REGNUM)
+ {
+ valto = extract_unsigned_integer (to, 4);
+ valfrom = extract_unsigned_integer (from, 4);
+ valto = (valto & ~0xffff) | (valfrom & 0xffff);
+ store_unsigned_integer (to, 4, valto);
+ }
+ else if (regi == FOP_REGNUM)
+ {
+ valto = extract_unsigned_integer (to, 4);
+ valfrom = extract_unsigned_integer (from, 4);
+ valto = (valto & 0xffff) | ((valfrom & ((1 << 11) - 1)) << 16);
+ store_unsigned_integer (to, 4, valto);
+ }
+ else
+ {
+ memcpy (to, from, REGISTER_RAW_SIZE (regi));
+ }
+ }
+ }
}
-#endif /* defined (FP0_REGNUM) && defined (HAVE_FPREGSET_T) */
+#endif /* defined (HAVE_FPREGSET_T) */
#endif /* HAVE_SYS_PROCFS_H */