summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@gnu.org>2003-11-02 17:05:07 +0000
committerMark Kettenis <kettenis@gnu.org>2003-11-02 17:05:07 +0000
commit71738b04c5b4be766affeb5ab003f1ef7ce19544 (patch)
tree4917ccb614e0290b10a495dff83337533b910382
parentf7396b9ed86c4c37dd46ea68bea01836035329d5 (diff)
downloadgdb-71738b04c5b4be766affeb5ab003f1ef7ce19544.tar.gz
* sparc-tdep.h (struct sparc_gregset): Add r_y_size member.
(sparc32_supply_gregset): Renamed from sparc_supply_gregset. (sparc32_collect_gregset): Renamed from sparc_collect_gregset. (sparc32_supply_fpregset): Renamed from sparc_supply_fpregset. (sparc32_collect_fpregset): Renamed from sparc_collect_fpregset. * sparc-tdep.c (sparc32_supply_gregset): Renamed from sparc_supply_gregset. (sparc32_collect_gregset): Renamed from sparc_collect_gregset. (sparc32_supply_fpregset): Renamed from sparc_supply_fpregset. (sparc32_collect_fpregset): Renamed from sparc_collect_fpregset. * sparc-linux-tdep.c: Include "solib-svr4.h". (sparc32_linux_svr4_fetch_link_map_offsets): New function. (sparc32_linux_init_abi): Set solib_svr4_fetch_link_map_offsets. * sparc-nat.h: New file. * sparc-nat.c: Add some more comments. Include "sparc-nat.h". (PTRACE_GETREGS): Define to PT_GETREGS if not already defined. (PTRACE_SETREGS, PTRACE_GETFPREGS, PTRACE_SETFPREGS): Likewise. (sparc_supply_gregset, sparc_collect_gregset, sparc_supply_fpregset, sparc_collect_fpregset, sparc_gregset_supplies_p, sparc_fpregset_supplies_p): New function variables. (sparc32_gregset_supplies_p): Rename from sparc_gregset_supplies_p. (sparc32_fpregset_supplies_p): Rename from sparc_fpregset_supplies_p. (fetch_inferior_registers): Deal with GNU/Linux LWPs. (store_inferior_registers): Likewise. Work around peculiarity in NetBSD when writing the floating-point registers. (_initialize_sparc_nat): Initialize sparc_supply_gregset, sparc_collect_gregset, sparc_supply_fpregset, sparc_collect_fpregset, sparc_gregset_supplies_p and sparc_fpregset_supplies_p if necessary. * sparc-sol2-nat.c (supply_gregset): Call sparc32_supply_gregset instead of sparc_supply_gregset. (supply_fpregset, fill_gregset, fill_fpregset): Likewise.
-rw-r--r--gdb/ChangeLog36
-rw-r--r--gdb/sparc-linux-tdep.c34
-rw-r--r--gdb/sparc-nat.c122
-rw-r--r--gdb/sparc-nat.h40
-rw-r--r--gdb/sparc-sol2-nat.c10
-rw-r--r--gdb/sparc-tdep.c22
-rw-r--r--gdb/sparc-tdep.h23
7 files changed, 236 insertions, 51 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 56ea4484497..a0b79e692dd 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,41 @@
2003-11-02 Mark Kettenis <kettenis@gnu.org>
+ * sparc-tdep.h (struct sparc_gregset): Add r_y_size member.
+ (sparc32_supply_gregset): Renamed from sparc_supply_gregset.
+ (sparc32_collect_gregset): Renamed from sparc_collect_gregset.
+ (sparc32_supply_fpregset): Renamed from sparc_supply_fpregset.
+ (sparc32_collect_fpregset): Renamed from sparc_collect_fpregset.
+ * sparc-tdep.c (sparc32_supply_gregset): Renamed from
+ sparc_supply_gregset.
+ (sparc32_collect_gregset): Renamed from sparc_collect_gregset.
+ (sparc32_supply_fpregset): Renamed from sparc_supply_fpregset.
+ (sparc32_collect_fpregset): Renamed from sparc_collect_fpregset.
+ * sparc-linux-tdep.c: Include "solib-svr4.h".
+ (sparc32_linux_svr4_fetch_link_map_offsets): New function.
+ (sparc32_linux_init_abi): Set solib_svr4_fetch_link_map_offsets.
+ * sparc-nat.h: New file.
+ * sparc-nat.c: Add some more comments. Include "sparc-nat.h".
+ (PTRACE_GETREGS): Define to PT_GETREGS if not already defined.
+ (PTRACE_SETREGS, PTRACE_GETFPREGS, PTRACE_SETFPREGS): Likewise.
+ (sparc_supply_gregset, sparc_collect_gregset,
+ sparc_supply_fpregset, sparc_collect_fpregset,
+ sparc_gregset_supplies_p, sparc_fpregset_supplies_p): New function
+ variables.
+ (sparc32_gregset_supplies_p): Rename from
+ sparc_gregset_supplies_p.
+ (sparc32_fpregset_supplies_p): Rename from
+ sparc_fpregset_supplies_p.
+ (fetch_inferior_registers): Deal with GNU/Linux LWPs.
+ (store_inferior_registers): Likewise. Work around peculiarity in
+ NetBSD when writing the floating-point registers.
+ (_initialize_sparc_nat): Initialize sparc_supply_gregset,
+ sparc_collect_gregset, sparc_supply_fpregset,
+ sparc_collect_fpregset, sparc_gregset_supplies_p and
+ sparc_fpregset_supplies_p if necessary.
+ * sparc-sol2-nat.c (supply_gregset): Call sparc32_supply_gregset
+ instead of sparc_supply_gregset.
+ (supply_fpregset, fill_gregset, fill_fpregset): Likewise.
+
* config/sparc/nm-linux.h (PTRACE_ARG3_TYPE, PTRACE_XFER_TYPE):
Define.
diff --git a/gdb/sparc-linux-tdep.c b/gdb/sparc-linux-tdep.c
index 3ba72f68908..e3643f82a91 100644
--- a/gdb/sparc-linux-tdep.c
+++ b/gdb/sparc-linux-tdep.c
@@ -22,9 +22,40 @@
#include "defs.h"
#include "gdbarch.h"
#include "osabi.h"
+#include "solib-svr4.h"
#include "sparc-tdep.h"
+static struct link_map_offsets *
+sparc32_linux_svr4_fetch_link_map_offsets (void)
+{
+ static struct link_map_offsets lmo;
+ static struct link_map_offsets *lmp = NULL;
+
+ if (lmp == NULL)
+ {
+ lmp = &lmo;
+
+ /* Everything we need is in the first 8 bytes. */
+ lmo.r_debug_size = 8;
+ lmo.r_map_offset = 4;
+ lmo.r_map_size = 4;
+
+ /* Everything we need is in the first 20 bytes. */
+ lmo.link_map_size = 20;
+ lmo.l_addr_offset = 0;
+ lmo.l_addr_size = 4;
+ lmo.l_name_offset = 4;
+ lmo.l_name_size = 4;
+ lmo.l_next_offset = 12;
+ lmo.l_next_size = 4;
+ lmo.l_prev_offset = 16;
+ lmo.l_prev_size = 4;
+ }
+
+ return lmp;
+}
+
static void
sparc32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
@@ -33,6 +64,9 @@ sparc32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* ... but doesn't have kernel-assisted single-stepping support. */
set_gdbarch_software_single_step (gdbarch, sparc_software_single_step);
+
+ set_solib_svr4_fetch_link_map_offsets
+ (gdbarch, sparc32_linux_svr4_fetch_link_map_offsets);
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff --git a/gdb/sparc-nat.c b/gdb/sparc-nat.c
index bbf2b4e5b07..09ee7c6471b 100644
--- a/gdb/sparc-nat.c
+++ b/gdb/sparc-nat.c
@@ -23,7 +23,22 @@
#include "inferior.h"
#include "regcache.h"
-/* We need a data structure for use with ptrace(2). SunOS 4 has
+#include <signal.h>
+#include "gdb_string.h"
+#include <sys/ptrace.h>
+#include "gdb_wait.h"
+#ifdef HAVE_MACHINE_REG_H
+#include <machine/reg.h>
+#endif
+
+#include "sparc-tdep.h"
+#include "sparc-nat.h"
+
+/* With some trickery we can use the code in this file for most (if
+ not all) ptrace(2) based SPARC systems, which includes SunOS 4,
+ Linux and the various SPARC BSD's.
+
+ First, we need a data structure for use with ptrace(2). SunOS has
`struct regs' and `struct fp_status' in <machine/reg.h>. BSD's
have `struct reg' and `struct fpreg' in <machine/reg.h>. GNU/Linux
has the same structures as SunOS 4, but they're in <asm/reg.h>,
@@ -35,11 +50,7 @@
typedefs, providing them for the other systems, therefore solves
the puzzle. */
-#include <signal.h>
-#include <sys/ptrace.h>
-#include "gdb_wait.h"
#ifdef HAVE_MACHINE_REG_H
-#include <machine/reg.h>
#ifdef HAVE_STRUCT_REG
typedef struct reg gregset_t;
typedef struct fpreg fpregset_t;
@@ -49,15 +60,40 @@ typedef struct fp_status fpregset_t;
#endif
#endif
-#include "sparc-tdep.h"
+/* Second, we need to remap the BSD ptrace(2) requests to their SunOS
+ equivalents. GNU/Linux already follows SunOS here. */
+
+#ifndef PTRACE_GETREGS
+#define PTRACE_GETREGS PT_GETREGS
+#endif
+
+#ifndef PTRACE_SETREGS
+#define PTRACE_SETREGS PT_SETREGS
+#endif
+
+#ifndef PTRACE_GETFPREGS
+#define PTRACE_GETFPREGS PT_GETFPREGS
+#endif
+
+#ifndef PTRACE_SETFPREGS
+#define PTRACE_SETFPREGS PT_SETFPREGS
+#endif
/* Register set description. */
const struct sparc_gregset *sparc_gregset;
+void (*sparc_supply_gregset) (const struct sparc_gregset *,
+ struct regcache *, int , const void *);
+void (*sparc_collect_gregset) (const struct sparc_gregset *,
+ const struct regcache *, int, void *);
+void (*sparc_supply_fpregset) (struct regcache *, int , const void *);
+void (*sparc_collect_fpregset) (const struct regcache *, int , void *);
+int (*sparc_gregset_supplies_p) (int);
+int (*sparc_fpregset_supplies_p) (int);
/* Determine whether `gregset_t' contains register REGNUM. */
int
-sparc_gregset_supplies_p (int regnum)
+sparc32_gregset_supplies_p (int regnum)
{
/* Integer registers. */
if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_G7_REGNUM)
@@ -78,8 +114,8 @@ sparc_gregset_supplies_p (int regnum)
/* Determine whether `fpregset_t' contains register REGNUM. */
-static int
-sparc_fpregset_supplies_p (int regnum)
+int
+sparc32_fpregset_supplies_p (int regnum)
{
/* Floating-point registers. */
if (regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F31_REGNUM)
@@ -99,6 +135,24 @@ void
fetch_inferior_registers (int regnum)
{
struct regcache *regcache = current_regcache;
+ int pid;
+
+ /* NOTE: cagney/2002-12-03: This code assumes that the currently
+ selected light weight processes' registers can be written
+ directly into the selected thread's register cache. This works
+ fine when given an 1:1 LWP:thread model (such as found on
+ GNU/Linux) but will, likely, have problems when used on an N:1
+ (userland threads) or N:M (userland multiple LWP) model. In the
+ case of the latter two, the LWP's registers do not necessarily
+ belong to the selected thread (the LWP could be in the middle of
+ executing the thread switch code).
+
+ These functions should instead be paramaterized with an explicit
+ object (struct regcache, struct thread_info?) into which the LWPs
+ registers can be written. */
+ pid = TIDGET (inferior_ptid);
+ if (pid == 0)
+ pid = PIDGET (inferior_ptid);
if (regnum == SPARC_G0_REGNUM)
{
@@ -110,8 +164,7 @@ fetch_inferior_registers (int regnum)
{
gregset_t regs;
- if (ptrace (PTRACE_GETREGS, PIDGET (inferior_ptid),
- (PTRACE_ARG3_TYPE) &regs, 0) == -1)
+ if (ptrace (PTRACE_GETREGS, pid, (PTRACE_ARG3_TYPE) &regs, 0) == -1)
perror_with_name ("Couldn't get registers");
sparc_supply_gregset (sparc_gregset, regcache, -1, &regs);
@@ -123,8 +176,7 @@ fetch_inferior_registers (int regnum)
{
fpregset_t fpregs;
- if (ptrace (PTRACE_GETFPREGS, PIDGET (inferior_ptid),
- (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
+ if (ptrace (PTRACE_GETFPREGS, pid, (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
perror_with_name ("Couldn't get floating point status");
sparc_supply_fpregset (regcache, -1, &fpregs);
@@ -135,19 +187,24 @@ void
store_inferior_registers (int regnum)
{
struct regcache *regcache = current_regcache;
+ int pid;
+
+ /* NOTE: cagney/2002-12-02: See comment in fetch_inferior_registers
+ about threaded assumptions. */
+ pid = TIDGET (inferior_ptid);
+ if (pid == 0)
+ pid = PIDGET (inferior_ptid);
if (regnum == -1 || sparc_gregset_supplies_p (regnum))
{
gregset_t regs;
- if (ptrace (PTRACE_GETREGS, PIDGET (inferior_ptid),
- (PTRACE_ARG3_TYPE) &regs, 0) == -1)
+ if (ptrace (PTRACE_GETREGS, pid, (PTRACE_ARG3_TYPE) &regs, 0) == -1)
perror_with_name ("Couldn't get registers");
sparc_collect_gregset (sparc_gregset, regcache, regnum, &regs);
- if (ptrace (PTRACE_SETREGS, PIDGET (inferior_ptid),
- (PTRACE_ARG3_TYPE) &regs, 0) == -1)
+ if (ptrace (PTRACE_SETREGS, pid, (PTRACE_ARG3_TYPE) &regs, 0) == -1)
perror_with_name ("Couldn't write registers");
/* Deal with the stack regs. */
@@ -166,17 +223,24 @@ store_inferior_registers (int regnum)
if (regnum == -1 || sparc_fpregset_supplies_p (regnum))
{
- fpregset_t fpregs;
+ fpregset_t fpregs, saved_fpregs;
- if (ptrace (PTRACE_GETFPREGS, PIDGET (inferior_ptid),
- (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
+ if (ptrace (PTRACE_GETFPREGS, pid, (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
perror_with_name ("Couldn't get floating-point registers");
+ memcpy (&saved_fpregs, &fpregs, sizeof (fpregs));
sparc_collect_fpregset (regcache, regnum, &fpregs);
- if (ptrace (PTRACE_SETFPREGS, PIDGET (inferior_ptid),
- (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
- perror_with_name ("Couldn't write floating-point registers");
+ /* Writing the floating-point registers will fail on NetBSD with
+ EINVAL if the inferior process doesn't have an FPU state
+ (i.e. if it didn't use the FPU yet). Therefore we don't try
+ to write the registers if nothing changed. */
+ if (memcmp (&saved_fpregs, &fpregs, sizeof (fpregs)) != 0)
+ {
+ if (ptrace (PTRACE_SETFPREGS, pid,
+ (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
+ perror_with_name ("Couldn't write floating-point registers");
+ }
if (regnum != -1)
return;
@@ -193,4 +257,16 @@ _initialize_sparc_nat (void)
/* Deafult to using SunOS 4 register sets. */
if (sparc_gregset == NULL)
sparc_gregset = &sparc32_sunos4_gregset;
+ if (sparc_supply_gregset == NULL)
+ sparc_supply_gregset = sparc32_supply_gregset;
+ if (sparc_collect_gregset == NULL)
+ sparc_collect_gregset = sparc32_collect_gregset;
+ if (sparc_supply_fpregset == NULL)
+ sparc_supply_fpregset = sparc32_supply_fpregset;
+ if (sparc_collect_fpregset == NULL)
+ sparc_collect_fpregset = sparc32_collect_fpregset;
+ if (sparc_gregset_supplies_p == NULL)
+ sparc_gregset_supplies_p = sparc32_gregset_supplies_p;
+ if (sparc_fpregset_supplies_p == NULL)
+ sparc_fpregset_supplies_p = sparc32_fpregset_supplies_p;
}
diff --git a/gdb/sparc-nat.h b/gdb/sparc-nat.h
new file mode 100644
index 00000000000..8f99b1eea11
--- /dev/null
+++ b/gdb/sparc-nat.h
@@ -0,0 +1,40 @@
+/* Native-dependent code for SPARC.
+
+ Copyright 2003 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef SPARC_NAT_H
+#define SPARC_NAT_H 1
+
+struct sparc_gregset;
+
+extern const struct sparc_gregset *sparc_gregset;
+extern void (*sparc_supply_gregset) (const struct sparc_gregset *,
+ struct regcache *, int , const void *);
+extern void (*sparc_collect_gregset) (const struct sparc_gregset *,
+ const struct regcache *, int, void *);
+extern void (*sparc_supply_fpregset) (struct regcache *, int , const void *);
+extern void (*sparc_collect_fpregset) (const struct regcache *, int , void *);
+extern int (*sparc_gregset_supplies_p) (int);
+extern int (*sparc_fpregset_supplies_p) (int);
+
+extern int sparc32_gregset_supplies_p (int regnum);
+extern int sparc32_fpregset_supplies_p (int regnum);
+
+#endif /* sparc-nat.h */
diff --git a/gdb/sparc-sol2-nat.c b/gdb/sparc-sol2-nat.c
index 5b3113a372c..e42e3c84b18 100644
--- a/gdb/sparc-sol2-nat.c
+++ b/gdb/sparc-sol2-nat.c
@@ -34,24 +34,24 @@
void
supply_gregset (prgregset_t *gregs)
{
- sparc_supply_gregset (&sparc32_sol2_gregset, current_regcache, -1, gregs);
+ sparc32_supply_gregset (&sparc32_sol2_gregset, current_regcache, -1, gregs);
}
void
supply_fpregset (prfpregset_t *fpregs)
{
- sparc_supply_fpregset (current_regcache, -1, fpregs);
+ sparc32_supply_fpregset (current_regcache, -1, fpregs);
}
void
fill_gregset (prgregset_t *gregs, int regnum)
{
- sparc_collect_gregset (&sparc32_sol2_gregset,
- current_regcache, regnum, gregs);
+ sparc32_collect_gregset (&sparc32_sol2_gregset,
+ current_regcache, regnum, gregs);
}
void
fill_fpregset (prfpregset_t *fpregs, int regnum)
{
- sparc_collect_fpregset (current_regcache, regnum, fpregs);
+ sparc32_collect_fpregset (current_regcache, regnum, fpregs);
}
diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c
index ecefb8fb295..d7f24baed08 100644
--- a/gdb/sparc-tdep.c
+++ b/gdb/sparc-tdep.c
@@ -1079,12 +1079,10 @@ sparc_collect_rwindow (const struct regcache *regcache,
/* Helper functions for dealing with register sets. */
-/* FIXME: kettenis/20031125: Make these handle 64-bit register sets. */
-
void
-sparc_supply_gregset (const struct sparc_gregset *gregset,
- struct regcache *regcache,
- int regnum, const void *gregs)
+sparc32_supply_gregset (const struct sparc_gregset *gregset,
+ struct regcache *regcache,
+ int regnum, const void *gregs)
{
const char *regs = gregs;
int i;
@@ -1146,9 +1144,9 @@ sparc_supply_gregset (const struct sparc_gregset *gregset,
}
void
-sparc_collect_gregset (const struct sparc_gregset *gregset,
- const struct regcache *regcache,
- int regnum, void *gregs)
+sparc32_collect_gregset (const struct sparc_gregset *gregset,
+ const struct regcache *regcache,
+ int regnum, void *gregs)
{
char *regs = gregs;
int i;
@@ -1201,8 +1199,8 @@ sparc_collect_gregset (const struct sparc_gregset *gregset,
}
void
-sparc_supply_fpregset (struct regcache *regcache,
- int regnum, const void *fpregs)
+sparc32_supply_fpregset (struct regcache *regcache,
+ int regnum, const void *fpregs)
{
const char *regs = fpregs;
int i;
@@ -1218,8 +1216,8 @@ sparc_supply_fpregset (struct regcache *regcache,
}
void
-sparc_collect_fpregset (const struct regcache *regcache,
- int regnum, void *fpregs)
+sparc32_collect_fpregset (const struct regcache *regcache,
+ int regnum, void *fpregs)
{
char *regs = fpregs;
int i;
diff --git a/gdb/sparc-tdep.h b/gdb/sparc-tdep.h
index bf081a01cc5..a683092f113 100644
--- a/gdb/sparc-tdep.h
+++ b/gdb/sparc-tdep.h
@@ -38,6 +38,7 @@ struct sparc_gregset
int r_tbr_offset;
int r_g1_offset;
int r_l0_offset;
+ int r_y_size;
};
/* SPARC architecture-specific information. */
@@ -146,16 +147,16 @@ extern void sparc_collect_rwindow (const struct regcache *regcache,
/* Register offsets for SunOS 4. */
extern const struct sparc_gregset sparc32_sunos4_gregset;
-extern void sparc_supply_gregset (const struct sparc_gregset *gregset,
- struct regcache *regcache,
- int regnum, const void *gregs);
-extern void sparc_collect_gregset (const struct sparc_gregset *gregset,
- const struct regcache *regcache,
- int regnum, void *gregs);
-extern void sparc_supply_fpregset (struct regcache *regcache,
- int regnum, const void *fpregs);
-extern void sparc_collect_fpregset (const struct regcache *regcache,
- int regnum, void *fpregs);
+extern void sparc32_supply_gregset (const struct sparc_gregset *gregset,
+ struct regcache *regcache,
+ int regnum, const void *gregs);
+extern void sparc32_collect_gregset (const struct sparc_gregset *gregset,
+ const struct regcache *regcache,
+ int regnum, void *gregs);
+extern void sparc32_supply_fpregset (struct regcache *regcache,
+ int regnum, const void *fpregs);
+extern void sparc32_collect_fpregset (const struct regcache *regcache,
+ int regnum, void *fpregs);
/* Functions and variables exported from sparc-sol2-tdep.c. */
@@ -163,6 +164,6 @@ extern void sparc_collect_fpregset (const struct regcache *regcache,
extern const struct sparc_gregset sparc32_sol2_gregset;
extern void sparc32_sol2_init_abi (struct gdbarch_info info,
- struct gdbarch *gdbarch);
+ struct gdbarch *gdbarch);
#endif /* sparc-tdep.h */