summaryrefslogtreecommitdiff
path: root/gdb/gdbserver/linux-low.c
diff options
context:
space:
mode:
authorDaniel Jacobowitz <drow@false.org>2002-02-27 07:07:49 +0000
committerDaniel Jacobowitz <drow@false.org>2002-02-27 07:07:49 +0000
commit58caa3dcdb43a5d66932182338f41df0bfd6cc98 (patch)
tree8932e0b600933a36f94b2668449ca3626bc0b5ac /gdb/gdbserver/linux-low.c
parent936521746ce912bf28fbeb3be2a006f6ffe23929 (diff)
downloadbinutils-gdb-58caa3dcdb43a5d66932182338f41df0bfd6cc98.tar.gz
2002-02-27 Daniel Jacobowitz <drow@mvista.com>
* gdbserver/acconfig.h: New file. * gdbserver/i387-fp.c: New file. * gdbserver/i387-fp.h: New file. * gdbserver/linux-x86-64.c: New file. * regformats/reg-x86-64.dat: New file. * configure.tgt: Add x86_64-*-linux* gdbserver support. & gdbserver/configure.srv: Add x86_64-*-linux* and regset support. * gdbserver/configure.in: Add support for regsets. * gdbserver/config.in: Regenerate. * gdbserver/configure: Regenerate. * gdbserver/Makefile.in: Likewise. Add $(linux_low_h). * gdbserver/linux-low.h: New file. * gdbserver/linux-low.c: Include "linux-low.h". Add support for regsets. * gdbserver/linux-arm-low.c: Include "linux-low.h". * gdbserver/linux-ia64-low.c: Include "linux-low.h". * gdbserver/linux-m68k-low.c: Include "linux-low.h". * gdbserver/linux-mips-low.c: Include "linux-low.h". * gdbserver/linux-ppc-low.c: Include "linux-low.h". * gdbserver/linux-sh-low.c: Include "linux-low.h". * gdbserver/linux-i386-low.c: Include "linux-low.h". Include "i387-fp.h". Add PTRACE_GETREGS and friends. * gdbserver/regcache.c (supply_register): New function. (supply_register_by_name): New function. (collect_register): New function. (collect_register_by_name): New function.
Diffstat (limited to 'gdb/gdbserver/linux-low.c')
-rw-r--r--gdb/gdbserver/linux-low.c155
1 files changed, 147 insertions, 8 deletions
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index f9152c7ea3c..b1e3d132980 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -20,8 +20,9 @@
Boston, MA 02111-1307, USA. */
#include "server.h"
-#include <sys/wait.h>
+#include "linux-low.h"
+#include <sys/wait.h>
#include <stdio.h>
#include <sys/param.h>
#include <sys/dir.h>
@@ -37,6 +38,10 @@
#define PTRACE_ARG3_TYPE long
#define PTRACE_XFER_TYPE int
+#ifdef HAVE_LINUX_REGSETS
+static int use_regsets_p = 1;
+#endif
+
extern int errno;
extern int num_regs;
extern int regmap[];
@@ -166,8 +171,11 @@ register_addr (int regnum)
return addr;
}
-/* Fetch one register. */
+
+#ifdef HAVE_LINUX_USRREGS
+
+/* Fetch one register. */
static void
fetch_register (int regno)
{
@@ -203,9 +211,8 @@ error_exit:;
}
/* Fetch all registers, or just one, from the child process. */
-
-void
-fetch_inferior_registers (int regno)
+static void
+usr_fetch_inferior_registers (int regno)
{
if (regno == -1 || regno == 0)
for (regno = 0; regno < num_regs; regno++)
@@ -217,9 +224,8 @@ fetch_inferior_registers (int regno)
/* Store our register values back into the inferior.
If REGNO is -1, do this for all registers.
Otherwise, REGNO specifies which register (so we can save time). */
-
-void
-store_inferior_registers (int regno)
+static void
+usr_store_inferior_registers (int regno)
{
CORE_ADDR regaddr;
int i;
@@ -259,6 +265,139 @@ store_inferior_registers (int regno)
for (regno = 0; regno < num_regs; regno++)
store_inferior_registers (regno);
}
+#endif /* HAVE_LINUX_USRREGS */
+
+
+
+#ifdef HAVE_LINUX_REGSETS
+
+static int
+regsets_fetch_inferior_registers (void)
+{
+ struct regset_info *regset;
+
+ regset = target_regsets;
+
+ while (regset->size >= 0)
+ {
+ void *buf;
+ int res;
+
+ if (regset->size == 0)
+ {
+ regset ++;
+ continue;
+ }
+
+ buf = malloc (regset->size);
+ res = ptrace (regset->get_request, inferior_pid, 0, (int) buf);
+ if (res < 0)
+ {
+ if (errno == EIO)
+ {
+ /* If we get EIO on the first regset, do not try regsets again.
+ If we get EIO on a later regset, disable that regset. */
+ if (regset == target_regsets)
+ {
+ use_regsets_p = 0;
+ return -1;
+ }
+ else
+ {
+ regset->size = 0;
+ continue;
+ }
+ }
+ else
+ {
+ perror ("Warning: ptrace(regsets_fetch_inferior_registers)");
+ }
+ }
+ regset->store_function (buf);
+ regset ++;
+ }
+}
+
+static int
+regsets_store_inferior_registers (void)
+{
+ struct regset_info *regset;
+
+ regset = target_regsets;
+
+ while (regset->size >= 0)
+ {
+ void *buf;
+ int res;
+
+ if (regset->size == 0)
+ {
+ regset ++;
+ continue;
+ }
+
+ buf = malloc (regset->size);
+ regset->fill_function (buf);
+ res = ptrace (regset->set_request, inferior_pid, 0, (int) buf);
+ if (res < 0)
+ {
+ if (errno == EIO)
+ {
+ /* If we get EIO on the first regset, do not try regsets again.
+ If we get EIO on a later regset, disable that regset. */
+ if (regset == target_regsets)
+ {
+ use_regsets_p = 0;
+ return -1;
+ }
+ else
+ {
+ regset->size = 0;
+ continue;
+ }
+ }
+ else
+ {
+ perror ("Warning: ptrace(regsets_fetch_inferior_registers)");
+ }
+ }
+ regset ++;
+ }
+}
+
+#endif /* HAVE_LINUX_REGSETS */
+
+
+void
+fetch_inferior_registers (int regno)
+{
+#ifdef HAVE_LINUX_REGSETS
+ if (use_regsets_p)
+ {
+ if (regsets_fetch_inferior_registers () == 0)
+ return;
+ }
+#endif
+#ifdef HAVE_LINUX_USRREGS
+ usr_fetch_inferior_registers (regno);
+#endif
+}
+
+void
+store_inferior_registers (int regno)
+{
+#ifdef HAVE_LINUX_REGSETS
+ if (use_regsets_p)
+ {
+ if (regsets_store_inferior_registers () == 0)
+ return;
+ }
+#endif
+#ifdef HAVE_LINUX_USRREGS
+ usr_store_inferior_registers (regno);
+#endif
+}
+
/* Copy LEN bytes from inferior's memory starting at MEMADDR
to debugger memory starting at MYADDR. */