* Re : Debugging v8plus binaries on solaris
@ 2006-02-10 20:12 Olatunji Ruwase
2006-02-17 22:52 ` Olatunji Ruwase
0 siblings, 1 reply; 5+ messages in thread
From: Olatunji Ruwase @ 2006-02-10 20:12 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1178 bytes --]
Hi,
I would like a review of the following changes that I would like to
eventually submit as patch. The changes add support for debugging v8plus
binaries on solaris. Below is a description, please pardon the format
this is my first gdb contribution.
Problem : Out and Global registers in v8plus are 64 bits, but v8plus
follows the 32 bit abi.
/proc provides /proc/<proc-id>/lwp/<lwp-id>/xregs for storing
the upper 32 bits of these registers (and other extra
register state info that dont fit in the 32 bit abi).
Fix : * gdb should treat out/global registers as 64 bits for
v8plus binaries, while respecting the abi requirements that
only the low 32 bits are used at abi points.
* gdb should also read/write xregs as needed.
Feature : Users will be able to view correct values of out/global
registers when debugging v8plus binaries.
Note that only v8plus built gdb and above will be able to
debug v8plus binaries.
Testing : No regressions gdb-6.4 testsuite for v8plus and v9 gdb.
Testing done with gcc 4.0.2, solaris 2.9.
Thanks
tunji
[-- Attachment #2: v8plus_patch.txt --]
[-- Type: text/plain, Size: 28540 bytes --]
diff -upr old_src/gregset.h new_src/gregset.h
--- old_src/gregset.h 2002-05-08 16:29:11.000000000 -0700
+++ new_src/gregset.h 2006-02-09 11:18:26.166141000 -0800
@@ -45,6 +45,19 @@ typedef GDB_FPREGSET_T gdb_fpregset_t;
extern void supply_gregset (gdb_gregset_t *gregs);
extern void supply_fpregset (gdb_fpregset_t *fpregs);
+#ifdef PCSXREG
+
+#ifndef GDB_XREGSET_T
+#define GDB_XREGSET_T prxregset_t
+#endif
+
+typedef GDB_XREGSET_T gdb_xregset_t;
+
+extern void supply_xregset (gdb_xregset_t *);
+extern void fill_xregset (gdb_xregset_t *, int regno);
+
+#endif /* PCSXREG */
+
/* Copy register values from GDB's register cache into
the native target gregset/fpregset. If regno is -1,
copy all the registers. */
diff -upr old_src/procfs.c new_src/procfs.c
--- old_src/procfs.c 2005-02-15 07:49:14.000000000 -0800
+++ new_src/procfs.c 2006-02-09 17:34:37.112140000 -0800
@@ -328,6 +328,11 @@ typedef struct siginfo gdb_siginfo_t;
/* the name of the proc status struct depends on the implementation */
typedef pstatus_t gdb_prstatus_t;
typedef lwpstatus_t gdb_lwpstatus_t;
+
+#ifdef PCSXREG
+typedef prxregset_t gdb_prxregset_t;
+#endif /* PCSXREG */
+
#else /* ! NEW_PROC_API */
/* format strings for /proc paths */
# ifndef CTL_PROC_NAME_FMT
@@ -367,6 +372,10 @@ typedef struct procinfo {
int status_fd; /* File descriptor for /proc status file */
int as_fd; /* File descriptor for /proc as file */
+#ifdef PCSXREG
+ int xregs_fd;
+#endif
+
char pathname[MAX_PROC_NAME_SIZE]; /* Pathname to /proc entry */
fltset_t saved_fltset; /* Saved traced hardware fault set */
@@ -381,6 +390,10 @@ typedef struct procinfo {
gdb_fpregset_t fpregset; /* Current floating point registers */
#endif
+#ifdef PCSXREG
+ gdb_prxregset_t xregset;
+#endif
+
#ifdef DYNAMIC_SYSCALLS
int num_syscalls; /* Total number of syscalls */
char **syscall_names; /* Syscall number to name map */
@@ -392,6 +405,11 @@ typedef struct procinfo {
int gregs_valid : 1;
int fpregs_valid : 1;
int threads_valid: 1;
+
+#ifdef PCSXREG
+ int xregs_valid : 1;
+#endif
+
} procinfo;
static char errmsg[128]; /* shared error msg buffer */
@@ -521,7 +539,7 @@ open_with_retry (const char *pathname, i
* Return: file descriptor, or zero for failure.
*/
-enum { FD_CTL, FD_STATUS, FD_AS };
+enum { FD_CTL, FD_STATUS, FD_AS, FD_XREGS };
static int
open_procinfo_files (procinfo *pi, int which)
@@ -553,6 +571,7 @@ open_procinfo_files (procinfo *pi, int w
* Pathnames for an LWP (lwp-id):
* /proc/<proc-id>/lwp/<lwp-id>/lwpctl
* /proc/<proc-id>/lwp/<lwp-id>/lwpstatus
+ * /proc/<proc-id>/lwp/<lwp-id>/xregs
* An LWP has no map or address space file descriptor, since
* the memory map and address space are shared by all LWPs.
*
@@ -617,6 +636,17 @@ open_procinfo_files (procinfo *pi, int w
return 0; /* fail */
pi->status_fd = fd;
break;
+
+#if PCSXREG
+ case FD_XREGS:
+ strcat (tmp, "/lwp/1/xregs");
+ fd = open_with_retry (tmp, O_RDONLY);
+ if (fd <= 0)
+ return 0; /* fail */
+ pi->xregs_fd = fd;
+ break;
+#endif /* PCSXREG */
+
default:
return 0; /* unknown file descriptor */
}
@@ -2597,6 +2627,71 @@ proc_get_gregs (procinfo *pi)
#endif
}
+#ifdef PCSXREG
+
+/* Return extra state registers for the process or LWP
+ corresponding to PI. Upon failure return NULL. */
+gdb_prxregset_t *
+proc_get_xregs (procinfo *pi)
+{
+ int size;
+
+ if (pi->xregs_fd == 0 &&
+ open_procinfo_files (pi, FD_XREGS) == 0)
+ {
+ pi->xregs_valid = 0;
+ return NULL;
+ }
+ memset (&pi->xregset, 0, sizeof (gdb_prxregset_t));
+ if (lseek (pi->xregs_fd, 0, SEEK_SET) < 0)
+ {
+ pi->xregs_valid = 0;
+ return NULL;
+ }
+ size = read (pi->xregs_fd, (char *) &pi->xregset,
+ sizeof (gdb_prxregset_t)) ;
+ pi->xregs_valid = (size == sizeof (gdb_prxregset_t));
+ if (pi->xregs_valid)
+ return &pi->xregset;
+ else
+ return NULL;
+
+}
+
+/* Write extra state registers back to the process or LWP
+ corresponding to PI. Return non-zero for success, zero
+ for failure. */
+int
+proc_set_xregs (procinfo *pi)
+{
+ int win;
+ gdb_xregset_t *xregs;
+
+ xregs = proc_get_xregs (pi);
+ if (xregs == NULL)
+ return 0;
+
+ if (pi->ctl_fd == 0 && open_procinfo_files (pi, FD_CTL) == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ struct
+ {
+ procfs_ctl_t cmd;
+ gdb_xregset_t xregs;
+ } arg;
+ arg.cmd = PCSXREG;
+ memcpy (&arg.xregs, xregs, sizeof (arg.xregs));
+ win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg)) == sizeof (arg));
+ }
+ pi->xregs_valid = 0;
+
+ return win;
+}
+#endif /* PCSXREG */
+
/* Return the general-purpose registers for the process or LWP
corresponding to PI. Upon failure, return NULL. */
@@ -3686,6 +3781,11 @@ procfs_fetch_registers (int regnum)
procinfo *pi;
int pid = PIDGET (inferior_ptid);
int tid = TIDGET (inferior_ptid);
+ unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
+ int sparc_v8plus = (bfd_mach_sparc_v9_p (mach) && !bfd_mach_sparc_64bit_p (mach));
+#ifdef PCSXREG
+ gdb_prxregset_t *xregs;
+#endif
/* First look up procinfo for the main process. */
pi = find_procinfo_or_die (pid, 0);
@@ -3706,6 +3806,15 @@ procfs_fetch_registers (int regnum)
supply_gregset (gregs);
+ if (sparc_v8plus)
+ {
+#ifdef PCSXREG
+ xregs = proc_get_xregs (pi);
+ if (xregs != NULL)
+ supply_xregset (xregs);
+#endif
+ }
+
if (FP0_REGNUM >= 0) /* Do we have an FPU? */
{
gdb_fpregset_t *fpregs;
@@ -3754,6 +3863,11 @@ procfs_store_registers (int regnum)
procinfo *pi;
int pid = PIDGET (inferior_ptid);
int tid = TIDGET (inferior_ptid);
+ unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
+ int sparc_v8plus = (bfd_mach_sparc_v9_p (mach) && !bfd_mach_sparc_64bit_p (mach));
+#ifdef PCSXREG
+ gdb_prxregset_t *xregs;
+#endif
/* First find procinfo for main process. */
pi = find_procinfo_or_die (pid, 0);
@@ -3776,6 +3890,19 @@ procfs_store_registers (int regnum)
if (!proc_set_gregs (pi))
proc_error (pi, "store_registers, set_gregs", __LINE__);
+ if (sparc_v8plus)
+ {
+#ifdef PCSXREG
+ xregs = proc_get_xregs (pi);
+ if (xregs != NULL)
+ {
+ fill_xregset (xregs, regnum);
+ proc_set_xregs (pi);
+ }
+#endif
+ }
+
+
if (FP0_REGNUM >= 0) /* Do we have an FPU? */
{
gdb_fpregset_t *fpregs;
diff -upr old_src/sparc-sol2-nat.c new_src/sparc-sol2-nat.c
--- old_src/sparc-sol2-nat.c 2004-01-03 10:21:01.000000000 -0800
+++ new_src/sparc-sol2-nat.c 2006-02-09 15:21:38.093231000 -0800
@@ -24,6 +24,7 @@
#include <sys/procfs.h>
#include "gregset.h"
+#include <sys/ucontext.h>
#include "sparc-tdep.h"
@@ -70,9 +71,12 @@
#define sparc_sol2_gregset sparc32_sol2_gregset
#define sparc_sol2_fpregset sparc32_sol2_fpregset
-
#endif
+#define sparc_supply_xregset sparc32_supply_xregset
+#define sparc_collect_xregset sparc32_collect_xregset
+#define sparc_sol2_xregset sparc32_sol2_xregset
+
void
supply_gregset (prgregset_t *gregs)
{
@@ -96,3 +100,14 @@ fill_fpregset (prfpregset_t *fpregs, int
{
sparc_collect_fpregset (current_regcache, regnum, fpregs);
}
+
+void
+supply_xregset (prxregset_t *xregs)
+{
+ sparc_supply_xregset (&sparc_sol2_xregset, current_regcache, -1, xregs);
+}
+
+void fill_xregset (prxregset_t *xregs, int regnum)
+{
+ sparc_collect_xregset (&sparc_sol2_xregset, current_regcache, regnum, xregs);
+}
diff -upr old_src/sparc-sol2-tdep.c new_src/sparc-sol2-tdep.c
--- old_src/sparc-sol2-tdep.c 2005-08-13 15:09:06.000000000 -0700
+++ new_src/sparc-sol2-tdep.c 2006-02-09 17:28:50.748354000 -0800
@@ -48,6 +48,15 @@ const struct sparc_gregset sparc32_sol2_
1 * 4, /* %g1 */
16 * 4, /* %l0 */
};
+
+#define XRS_ID 0x78727300 /* the string "xrs" */
+#define XRS_ID_OFFSET 224 /* offset of xrs in mcontext_t*/
+
+const struct sparc_xregset sparc32_sol2_xregset =
+{
+ 148, /* xr_g1 */
+};
+
\f
/* The Solaris signal trampolines reside in libc. For normal signals,
@@ -74,6 +83,39 @@ sparc_sol2_pc_in_sigtramp (CORE_ADDR pc,
|| strcmp (name, "__sighndlr") == 0));
}
+
+/* Extract and cache extra register state from uc_mcontext member of
+ ucontext_t instance if available. */
+void
+sparc32_sol2_frame_cache_xregs (CORE_ADDR mcontext_addr,
+ struct frame_info *next_frame,
+ struct sparc_frame_cache *cache)
+{
+ CORE_ADDR addr;
+ int numregs = SPARC_O7_REGNUM + 1;
+ int regnum, xrs_id;
+
+ xrs_id = get_frame_memory_unsigned (next_frame,
+ (mcontext_addr + XRS_ID_OFFSET), 4);
+ if (xrs_id != XRS_ID)
+ return;
+
+ addr = get_frame_memory_unsigned (next_frame,
+ (mcontext_addr + XRS_ID_OFFSET + 4), 4);
+ addr += sparc32_sol2_xregset.xr_g1_offset;
+ cache->saved_xregs = FRAME_OBSTACK_CALLOC (numregs,
+ struct trad_frame_saved_reg);
+ cache->saved_xregs[SPARC_G0_REGNUM].realreg = SPARC_G0_REGNUM;
+ cache->saved_xregs[SPARC_G0_REGNUM].addr = -1;
+ for (regnum = SPARC_G1_REGNUM; regnum < numregs; regnum++, addr +=4)
+ {
+ cache->saved_xregs[regnum].realreg = regnum;
+ cache->saved_xregs[regnum].addr = addr;
+ }
+ return;
+}
+
+
static struct sparc_frame_cache *
sparc32_sol2_sigtramp_frame_cache (struct frame_info *next_frame,
void **this_cache)
@@ -81,7 +123,9 @@ sparc32_sol2_sigtramp_frame_cache (struc
struct sparc_frame_cache *cache;
CORE_ADDR mcontext_addr, addr;
int regnum;
-
+ struct gdbarch *gdbarch = get_frame_arch (next_frame);
+ unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
+
if (*this_cache)
return *this_cache;
@@ -121,6 +165,9 @@ sparc32_sol2_sigtramp_frame_cache (struc
cache->saved_regs[regnum].addr = addr;
}
+ if (bfd_mach_sparc_v8plus_p (mach))
+ sparc32_sol2_frame_cache_xregs (mcontext_addr, next_frame, cache);
+
return cache;
}
@@ -135,6 +182,40 @@ sparc32_sol2_sigtramp_frame_this_id (str
(*this_id) = frame_id_build (cache->base, cache->pc);
}
+
+/* Read associate extra register state information. */
+static
+void sparc32_sol2_sigtramp_frame_prev_xregs (struct frame_info *next_frame,
+ struct sparc_frame_cache *cache,
+ int regnum, int *optimizedp,
+ enum lval_type *lvalp, CORE_ADDR *addrp,
+ int *realregp, gdb_byte *bufferp)
+
+{
+ struct gdbarch *gdbarch = get_frame_arch (next_frame);
+
+ if (!trad_frame_addr_p (cache->saved_regs, regnum))
+ error (_("Register %s not saved in memory"),
+ gdbarch_register_name (gdbarch, regnum));
+
+ /* The register was saved in memory. */
+ *optimizedp = 0;
+ *lvalp = lval_memory;
+ *addrp = cache->saved_regs[regnum].addr;
+ *realregp = -1;
+ if (bufferp != NULL)
+ {
+ /* Read the value in from memory. */
+ memset (bufferp, 0, register_size (gdbarch, regnum));
+ get_frame_memory (next_frame, cache->saved_xregs[regnum].addr, bufferp, 4);
+ get_frame_memory (next_frame, cache->saved_regs[regnum].addr,
+ bufferp + 4, 4);
+ }
+
+ return;
+}
+
+
static void
sparc32_sol2_sigtramp_frame_prev_register (struct frame_info *next_frame,
void **this_cache,
@@ -148,6 +229,13 @@ sparc32_sol2_sigtramp_frame_prev_registe
trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum,
optimizedp, lvalp, addrp, realnump, valuep);
+ if (cache->saved_xregs &&
+ ((regnum >= SPARC_G0_REGNUM) && (regnum <= SPARC_O7_REGNUM))
+ && trad_frame_addr_p (cache->saved_regs, regnum))
+ {
+ sparc32_sol2_sigtramp_frame_prev_xregs (next_frame, cache, regnum,optimizedp,
+ lvalp, addrp, realnump, valuep);
+ }
}
static const struct frame_unwind sparc32_sol2_sigtramp_frame_unwind =
diff -upr old_src/sparc-tdep.c new_src/sparc-tdep.c
--- old_src/sparc-tdep.c 2005-08-13 15:12:24.000000000 -0700
+++ new_src/sparc-tdep.c 2006-02-09 17:38:00.553882000 -0800
@@ -300,12 +300,22 @@ sparc32_register_name (int regnum)
static struct type *
sparc32_register_type (struct gdbarch *gdbarch, int regnum)
{
+ unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
+
if (regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F31_REGNUM)
return builtin_type_float;
-
+
if (regnum >= SPARC32_D0_REGNUM && regnum <= SPARC32_D30_REGNUM)
return builtin_type_double;
-
+
+ /* sparc_v8plus support. v8plus is 32 bit abi, but with v9 ISA. This
+ allows software to use global and out registers as 64 bits registers. */
+ if (bfd_mach_sparc_v8plus_p (mach))
+ {
+ if ((regnum >= SPARC_G0_REGNUM) && (regnum <= SPARC_O7_REGNUM))
+ return builtin_type_int64;
+ }
+
if (regnum == SPARC_SP_REGNUM || regnum == SPARC_FP_REGNUM)
return builtin_type_void_data_ptr;
@@ -372,7 +382,11 @@ sparc32_store_arguments (struct regcache
int num_elements = 0;
int element = 0;
int i;
+ gdb_byte buf[8];
+ unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
+ int sparc_v8plus = bfd_mach_sparc_v8plus_p (mach);
+ memset (buf, 0, sizeof (buf));
for (i = 0; i < nargs; i++)
{
struct type *type = value_type (args[i]);
@@ -421,21 +435,38 @@ sparc32_store_arguments (struct regcache
aligned." */
sp &= ~0x7;
+
for (i = 0; i < nargs; i++)
{
const bfd_byte *valbuf = value_contents (args[i]);
struct type *type = value_type (args[i]);
int len = TYPE_LENGTH (type);
-
+
gdb_assert (len == 4 || len == 8);
-
+
if (element < 6)
{
int regnum = SPARC_O0_REGNUM + element;
-
- regcache_cooked_write (regcache, regnum, valbuf);
+
+ if (sparc_v8plus)
+ {
+ /* Although v8plus out registers are 64 bits,
+ only the lower 32 bits are used for argument passing. */
+ memcpy (buf + 4, valbuf, 4);
+ regcache_cooked_write (regcache, regnum, buf);
+ }
+ else
+ regcache_cooked_write (regcache, regnum, valbuf);
if (len > 4 && element < 5)
- regcache_cooked_write (regcache, regnum + 1, valbuf + 4);
+ {
+ if (sparc_v8plus)
+ {
+ memcpy (buf + 4, valbuf + 4, 4);
+ regcache_cooked_write (regcache, regnum + 1, buf);
+ }
+ else
+ regcache_cooked_write (regcache, regnum + 1, valbuf + 4);
+ }
}
/* Always store the argument in memory. */
@@ -743,6 +774,7 @@ sparc32_frame_prev_register (struct fram
enum lval_type *lvalp, CORE_ADDR *addrp,
int *realnump, gdb_byte *valuep)
{
+ int prev_out_reg = 0;
struct sparc_frame_cache *cache =
sparc32_frame_cache (next_frame, this_cache);
@@ -815,14 +847,26 @@ sparc32_frame_prev_register (struct fram
current frame's `in' registers. */
if (!cache->frameless_p
&& regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM)
- regnum += (SPARC_I0_REGNUM - SPARC_O0_REGNUM);
+ {
+ regnum += (SPARC_I0_REGNUM - SPARC_O0_REGNUM);
+ prev_out_reg = 1;
+ }
*optimizedp = 0;
*lvalp = lval_register;
*addrp = 0;
*realnump = regnum;
if (valuep)
- frame_unwind_register (next_frame, (*realnump), valuep);
+ {
+ if (bfd_mach_sparc_v8plus_p (gdbarch_bfd_arch_info (current_gdbarch)->mach)
+ && prev_out_reg)
+ {
+ memset (valuep, 0, 4);
+ frame_unwind_register (next_frame, (*realnump), valuep + 4);
+ }
+ else
+ frame_unwind_register (next_frame, (*realnump), valuep);
+ }
}
static const struct frame_unwind sparc32_frame_unwind =
@@ -876,11 +920,12 @@ sparc32_extract_return_value (struct typ
gdb_byte *valbuf)
{
int len = TYPE_LENGTH (type);
- gdb_byte buf[8];
-
+ gdb_byte buf[MAX_REGISTER_SIZE];
+
gdb_assert (!sparc_structure_or_union_p (type));
gdb_assert (!(sparc_floating_p (type) && len == 16));
+ memset (buf, 0, sizeof (buf));
if (sparc_floating_p (type))
{
/* Floating return values. */
@@ -892,20 +937,36 @@ sparc32_extract_return_value (struct typ
else
{
/* Integral and pointer return values. */
- gdb_assert (sparc_integral_or_pointer_p (type));
+ int reg_size;
+ unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
+ int sparc_v8plus = bfd_mach_sparc_v8plus_p (mach);
+ gdb_assert (sparc_integral_or_pointer_p (type));
+
+ reg_size = register_size (current_gdbarch, SPARC_O0_REGNUM);
regcache_cooked_read (regcache, SPARC_O0_REGNUM, buf);
if (len > 4)
{
- regcache_cooked_read (regcache, SPARC_O1_REGNUM, buf + 4);
gdb_assert (len == 8);
- memcpy (valbuf, buf, 8);
+
+ regcache_cooked_read (regcache, SPARC_O1_REGNUM, buf + reg_size);
+ if (sparc_v8plus)
+ {
+ /* The lower 4 bytes of v8plus %o0 and %o1 registers make up
+ the return value. */
+ memcpy (valbuf, buf + 4, 4);
+ memcpy (valbuf + 4, buf + 12, 4);
+ }
+ else
+ {
+ memcpy (valbuf, buf, 8);
+ }
}
else
{
/* Just stripping off any unused bytes should preserve the
signed-ness just fine. */
- memcpy (valbuf, buf + 4 - len, len);
+ memcpy (valbuf, buf + reg_size - len, len);
}
}
}
@@ -918,11 +979,13 @@ sparc32_store_return_value (struct type
const gdb_byte *valbuf)
{
int len = TYPE_LENGTH (type);
- gdb_byte buf[8];
-
+ gdb_byte buf[MAX_REGISTER_SIZE];
+
gdb_assert (!sparc_structure_or_union_p (type));
gdb_assert (!(sparc_floating_p (type) && len == 16));
+ memset (buf, 0, MAX_REGISTER_SIZE);
+
if (sparc_floating_p (type))
{
/* Floating return values. */
@@ -934,20 +997,34 @@ sparc32_store_return_value (struct type
else
{
/* Integral and pointer return values. */
+ int reg_size;
+ unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
+ int sparc_v8plus = bfd_mach_sparc_v8plus_p (mach);
+
gdb_assert (sparc_integral_or_pointer_p (type));
+ reg_size = register_size (current_gdbarch, SPARC_O0_REGNUM);
if (len > 4)
{
gdb_assert (len == 8);
- memcpy (buf, valbuf, 8);
- regcache_cooked_write (regcache, SPARC_O1_REGNUM, buf + 4);
+ if (sparc_v8plus)
+ {
+ memcpy (buf + 4, valbuf, 4);
+ memcpy (buf + 12, valbuf + 4, 4);
+ }
+ else
+ {
+ memcpy (buf, valbuf, 8);
+ }
+ regcache_cooked_write (regcache, SPARC_O1_REGNUM, buf + reg_size);
}
else
{
/* ??? Do we need to do any sign-extension here? */
- memcpy (buf + 4 - len, valbuf, len);
+ memcpy (buf + reg_size - len, valbuf, len);
}
- regcache_cooked_write (regcache, SPARC_O0_REGNUM, buf);
+
+ regcache_cooked_write (regcache, SPARC_O0_REGNUM, buf);
}
}
@@ -1395,6 +1472,8 @@ sparc32_supply_gregset (const struct spa
{
const gdb_byte *regs = gregs;
int i;
+ gdb_byte buf[8];
+ unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
regcache_raw_supply (regcache, SPARC32_PSR_REGNUM,
@@ -1418,11 +1497,20 @@ sparc32_supply_gregset (const struct spa
if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
{
int offset = gregset->r_g1_offset;
-
+
+ memset (buf, 0, sizeof (buf));
for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
{
if (regnum == i || regnum == -1)
- regcache_raw_supply (regcache, i, regs + offset);
+ {
+ if (bfd_mach_sparc_v8plus_p (mach))
+ {
+ memcpy (buf + 4, regs + offset, 4);
+ regcache_raw_supply (regcache, i, buf);
+ }
+ else
+ regcache_raw_supply (regcache, i, regs + offset);
+ }
offset += 4;
}
}
@@ -1459,6 +1547,8 @@ sparc32_collect_gregset (const struct sp
{
gdb_byte *regs = gregs;
int i;
+ gdb_byte buf[8];
+ unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
regcache_raw_collect (regcache, SPARC32_PSR_REGNUM,
@@ -1479,12 +1569,21 @@ sparc32_collect_gregset (const struct sp
if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
{
int offset = gregset->r_g1_offset;
-
+
+ memset (buf, 0, sizeof (buf));
/* %g0 is always zero. */
for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
{
if (regnum == i || regnum == -1)
- regcache_raw_collect (regcache, i, regs + offset);
+ {
+ if (bfd_mach_sparc_v8plus_p (mach))
+ {
+ regcache_raw_collect (regcache, i, buf);
+ memcpy (regs + offset, buf + 4, 4);
+ }
+ else
+ regcache_raw_collect (regcache, i, regs + offset);
+ }
offset += 4;
}
}
@@ -1507,6 +1606,71 @@ sparc32_collect_gregset (const struct sp
}
}
+void
+sparc32_supply_xregset (const struct sparc_xregset *xregset,
+ struct regcache *regcache,
+ int regnum, const void *xregs)
+{
+ const gdb_byte *regs = xregs;
+ int i;
+ gdb_byte buf[8];
+ unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
+
+ if (bfd_mach_sparc_v8plus_p (mach))
+ {
+ if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
+ {
+ int offset = xregset->xr_g1_offset;
+
+ /* %g0 is always zero. */
+ for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
+ {
+ if (regnum == i || regnum == -1)
+ {
+ memset (buf, 0, sizeof (buf));
+ regcache_raw_collect (regcache, i, buf);
+ memcpy (buf, regs + offset, 4);
+ regcache_raw_supply (regcache, i, buf);
+ }
+ offset += 4;
+ }
+ }
+ }
+ return;
+}
+
+void
+sparc32_collect_xregset (const struct sparc_xregset *xregset,
+ struct regcache *regcache,
+ int regnum, void *xregs)
+{
+ gdb_byte *regs = xregs;
+ int i;
+ gdb_byte buf[8];
+ unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
+
+ if (bfd_mach_sparc_v8plus_p (mach))
+ {
+ if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
+ {
+ int offset = xregset->xr_g1_offset;
+
+ memset (buf, 0, sizeof (buf));
+ /* %g0 is always zero. */
+ for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
+ {
+ if (regnum == i || regnum == -1)
+ {
+ regcache_raw_collect (regcache, i, buf);
+ memcpy (regs + offset, buf, 4);
+ }
+ offset += 4;
+ }
+ }
+ }
+ return;
+}
+
void
sparc32_supply_fpregset (struct regcache *regcache,
int regnum, const void *fpregs)
diff -upr old_src/sparc-tdep.h new_src/sparc-tdep.h
--- old_src/sparc-tdep.h 2004-11-29 07:20:27.000000000 -0800
+++ new_src/sparc-tdep.h 2006-02-09 17:28:41.454518000 -0800
@@ -28,6 +28,9 @@ struct regcache;
struct regset;
struct trad_frame_saved_reg;
+#define bfd_mach_sparc_v8plus_p(mach) \
+ (bfd_mach_sparc_v9_p (mach) && !bfd_mach_sparc_64bit_p (mach))
+
/* Register offsets for the general-purpose register set. */
struct sparc_gregset
@@ -43,6 +46,12 @@ struct sparc_gregset
int r_y_size;
};
+struct sparc_xregset
+{
+ int xr_g1_offset; /* offset of G1 register. */
+ /* Add other extra register state offsets as needed. */
+};
+
/* SPARC architecture-specific information. */
struct gdbarch_tdep
@@ -142,6 +151,9 @@ struct sparc_frame_cache
/* Table of saved registers. */
struct trad_frame_saved_reg *saved_regs;
+
+ /* Table of saved extra registers. */
+ struct trad_frame_saved_reg *saved_xregs;
};
/* Fetch the instruction at PC. */
@@ -182,11 +194,18 @@ extern void sparc32_supply_fpregset (str
int regnum, const void *fpregs);
extern void sparc32_collect_fpregset (const struct regcache *regcache,
int regnum, void *fpregs);
+extern void sparc32_supply_xregset (const struct sparc_xregset *xregset,
+ struct regcache *regcache,
+ int regnum, const void *xregs);
+extern void sparc32_collect_xregset (const struct sparc_xregset *xregset,
+ struct regcache *regcache,
+ int regnum, void *xregs);
/* Functions and variables exported from sparc-sol2-tdep.c. */
/* Register offsets for Solaris 2. */
extern const struct sparc_gregset sparc32_sol2_gregset;
+extern const struct sparc_xregset sparc32_sol2_xregset;
extern int sparc_sol2_pc_in_sigtramp (CORE_ADDR pc, char *name);
diff -upr old_src/sparc64-tdep.c new_src/sparc64-tdep.c
--- old_src/sparc64-tdep.c 2005-06-12 04:10:56.000000000 -0700
+++ new_src/sparc64-tdep.c 2006-02-09 09:47:02.765731000 -0800
@@ -1261,14 +1261,15 @@ sparc64_supply_gregset (const struct spa
if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
{
int offset = gregset->r_g1_offset;
-
- if (sparc32)
- offset += 4;
-
+
+ if (sparc32 &&
+ !bfd_mach_sparc_v8plus_p (gdbarch_bfd_arch_info (current_gdbarch)->mach))
+ offset += 4;
+
for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
{
if (regnum == i || regnum == -1)
- regcache_raw_supply (regcache, i, regs + offset);
+ regcache_raw_supply (regcache, i, regs + offset);
offset += 8;
}
}
@@ -1376,8 +1377,9 @@ sparc64_collect_gregset (const struct sp
{
int offset = gregset->r_g1_offset;
- if (sparc32)
- offset += 4;
+ if (sparc32 &&
+ !bfd_mach_sparc_v8plus_p (gdbarch_bfd_arch_info (current_gdbarch)->mach))
+ offset += 4;
/* %g0 is always zero. */
for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
diff -upr old_src/trad-frame.c new_src/trad-frame.c
--- old_src/trad-frame.c 2005-05-22 07:53:34.000000000 -0700
+++ new_src/trad-frame.c 2006-02-09 16:55:53.357073000 -0800
@@ -148,8 +148,8 @@ trad_frame_get_prev_register (struct fra
if (bufferp != NULL)
{
/* Read the value in from memory. */
- get_frame_memory (next_frame, this_saved_regs[regnum].addr, bufferp,
- register_size (gdbarch, regnum));
+ get_frame_memory (next_frame, this_saved_regs[regnum].addr, bufferp,
+ register_size (gdbarch, regnum));
}
}
else if (trad_frame_realreg_p (this_saved_regs, regnum))
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Re : Debugging v8plus binaries on solaris
2006-02-10 20:12 Re : Debugging v8plus binaries on solaris Olatunji Ruwase
@ 2006-02-17 22:52 ` Olatunji Ruwase
2006-02-17 23:31 ` Mark Kettenis
0 siblings, 1 reply; 5+ messages in thread
From: Olatunji Ruwase @ 2006-02-17 22:52 UTC (permalink / raw)
To: gdb-patches
Hi,
I wanted to find out if anyone was looking at this ?.
Thanks
tunji
Olatunji Ruwase wrote On 02/10/06 12:12,:
> Hi,
> I would like a review of the following changes that I would like to
> eventually submit as patch. The changes add support for debugging v8plus
> binaries on solaris. Below is a description, please pardon the format
> this is my first gdb contribution.
>
> Problem : Out and Global registers in v8plus are 64 bits, but v8plus
> follows the 32 bit abi.
> /proc provides /proc/<proc-id>/lwp/<lwp-id>/xregs for storing
> the upper 32 bits of these registers (and other extra
> register state info that dont fit in the 32 bit abi).
>
> Fix : * gdb should treat out/global registers as 64 bits for
> v8plus binaries, while respecting the abi requirements that
> only the low 32 bits are used at abi points.
>
> * gdb should also read/write xregs as needed.
>
>
> Feature : Users will be able to view correct values of out/global
> registers when debugging v8plus binaries.
> Note that only v8plus built gdb and above will be able to
> debug v8plus binaries.
>
> Testing : No regressions gdb-6.4 testsuite for v8plus and v9 gdb.
> Testing done with gcc 4.0.2, solaris 2.9.
>
> Thanks
>
> tunji
>
>
>
>
>
>
>
>
>
> ------------------------------------------------------------------------
>
> diff -upr old_src/gregset.h new_src/gregset.h
> --- old_src/gregset.h 2002-05-08 16:29:11.000000000 -0700
> +++ new_src/gregset.h 2006-02-09 11:18:26.166141000 -0800
> @@ -45,6 +45,19 @@ typedef GDB_FPREGSET_T gdb_fpregset_t;
> extern void supply_gregset (gdb_gregset_t *gregs);
> extern void supply_fpregset (gdb_fpregset_t *fpregs);
>
> +#ifdef PCSXREG
> +
> +#ifndef GDB_XREGSET_T
> +#define GDB_XREGSET_T prxregset_t
> +#endif
> +
> +typedef GDB_XREGSET_T gdb_xregset_t;
> +
> +extern void supply_xregset (gdb_xregset_t *);
> +extern void fill_xregset (gdb_xregset_t *, int regno);
> +
> +#endif /* PCSXREG */
> +
> /* Copy register values from GDB's register cache into
> the native target gregset/fpregset. If regno is -1,
> copy all the registers. */
> diff -upr old_src/procfs.c new_src/procfs.c
> --- old_src/procfs.c 2005-02-15 07:49:14.000000000 -0800
> +++ new_src/procfs.c 2006-02-09 17:34:37.112140000 -0800
> @@ -328,6 +328,11 @@ typedef struct siginfo gdb_siginfo_t;
> /* the name of the proc status struct depends on the implementation */
> typedef pstatus_t gdb_prstatus_t;
> typedef lwpstatus_t gdb_lwpstatus_t;
> +
> +#ifdef PCSXREG
> +typedef prxregset_t gdb_prxregset_t;
> +#endif /* PCSXREG */
> +
> #else /* ! NEW_PROC_API */
> /* format strings for /proc paths */
> # ifndef CTL_PROC_NAME_FMT
> @@ -367,6 +372,10 @@ typedef struct procinfo {
> int status_fd; /* File descriptor for /proc status file */
> int as_fd; /* File descriptor for /proc as file */
>
> +#ifdef PCSXREG
> + int xregs_fd;
> +#endif
> +
> char pathname[MAX_PROC_NAME_SIZE]; /* Pathname to /proc entry */
>
> fltset_t saved_fltset; /* Saved traced hardware fault set */
> @@ -381,6 +390,10 @@ typedef struct procinfo {
> gdb_fpregset_t fpregset; /* Current floating point registers */
> #endif
>
> +#ifdef PCSXREG
> + gdb_prxregset_t xregset;
> +#endif
> +
> #ifdef DYNAMIC_SYSCALLS
> int num_syscalls; /* Total number of syscalls */
> char **syscall_names; /* Syscall number to name map */
> @@ -392,6 +405,11 @@ typedef struct procinfo {
> int gregs_valid : 1;
> int fpregs_valid : 1;
> int threads_valid: 1;
> +
> +#ifdef PCSXREG
> + int xregs_valid : 1;
> +#endif
> +
> } procinfo;
>
> static char errmsg[128]; /* shared error msg buffer */
> @@ -521,7 +539,7 @@ open_with_retry (const char *pathname, i
> * Return: file descriptor, or zero for failure.
> */
>
> -enum { FD_CTL, FD_STATUS, FD_AS };
> +enum { FD_CTL, FD_STATUS, FD_AS, FD_XREGS };
>
> static int
> open_procinfo_files (procinfo *pi, int which)
> @@ -553,6 +571,7 @@ open_procinfo_files (procinfo *pi, int w
> * Pathnames for an LWP (lwp-id):
> * /proc/<proc-id>/lwp/<lwp-id>/lwpctl
> * /proc/<proc-id>/lwp/<lwp-id>/lwpstatus
> + * /proc/<proc-id>/lwp/<lwp-id>/xregs
> * An LWP has no map or address space file descriptor, since
> * the memory map and address space are shared by all LWPs.
> *
> @@ -617,6 +636,17 @@ open_procinfo_files (procinfo *pi, int w
> return 0; /* fail */
> pi->status_fd = fd;
> break;
> +
> +#if PCSXREG
> + case FD_XREGS:
> + strcat (tmp, "/lwp/1/xregs");
> + fd = open_with_retry (tmp, O_RDONLY);
> + if (fd <= 0)
> + return 0; /* fail */
> + pi->xregs_fd = fd;
> + break;
> +#endif /* PCSXREG */
> +
> default:
> return 0; /* unknown file descriptor */
> }
> @@ -2597,6 +2627,71 @@ proc_get_gregs (procinfo *pi)
> #endif
> }
>
> +#ifdef PCSXREG
> +
> +/* Return extra state registers for the process or LWP
> + corresponding to PI. Upon failure return NULL. */
> +gdb_prxregset_t *
> +proc_get_xregs (procinfo *pi)
> +{
> + int size;
> +
> + if (pi->xregs_fd == 0 &&
> + open_procinfo_files (pi, FD_XREGS) == 0)
> + {
> + pi->xregs_valid = 0;
> + return NULL;
> + }
> + memset (&pi->xregset, 0, sizeof (gdb_prxregset_t));
> + if (lseek (pi->xregs_fd, 0, SEEK_SET) < 0)
> + {
> + pi->xregs_valid = 0;
> + return NULL;
> + }
> + size = read (pi->xregs_fd, (char *) &pi->xregset,
> + sizeof (gdb_prxregset_t)) ;
> + pi->xregs_valid = (size == sizeof (gdb_prxregset_t));
> + if (pi->xregs_valid)
> + return &pi->xregset;
> + else
> + return NULL;
> +
> +}
> +
> +/* Write extra state registers back to the process or LWP
> + corresponding to PI. Return non-zero for success, zero
> + for failure. */
> +int
> +proc_set_xregs (procinfo *pi)
> +{
> + int win;
> + gdb_xregset_t *xregs;
> +
> + xregs = proc_get_xregs (pi);
> + if (xregs == NULL)
> + return 0;
> +
> + if (pi->ctl_fd == 0 && open_procinfo_files (pi, FD_CTL) == 0)
> + {
> + return 0;
> + }
> + else
> + {
> + struct
> + {
> + procfs_ctl_t cmd;
> + gdb_xregset_t xregs;
> + } arg;
> + arg.cmd = PCSXREG;
> + memcpy (&arg.xregs, xregs, sizeof (arg.xregs));
> + win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg)) == sizeof (arg));
> + }
> + pi->xregs_valid = 0;
> +
> + return win;
> +}
> +#endif /* PCSXREG */
> +
> /* Return the general-purpose registers for the process or LWP
> corresponding to PI. Upon failure, return NULL. */
>
> @@ -3686,6 +3781,11 @@ procfs_fetch_registers (int regnum)
> procinfo *pi;
> int pid = PIDGET (inferior_ptid);
> int tid = TIDGET (inferior_ptid);
> + unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
> + int sparc_v8plus = (bfd_mach_sparc_v9_p (mach) && !bfd_mach_sparc_64bit_p (mach));
> +#ifdef PCSXREG
> + gdb_prxregset_t *xregs;
> +#endif
>
> /* First look up procinfo for the main process. */
> pi = find_procinfo_or_die (pid, 0);
> @@ -3706,6 +3806,15 @@ procfs_fetch_registers (int regnum)
>
> supply_gregset (gregs);
>
> + if (sparc_v8plus)
> + {
> +#ifdef PCSXREG
> + xregs = proc_get_xregs (pi);
> + if (xregs != NULL)
> + supply_xregset (xregs);
> +#endif
> + }
> +
> if (FP0_REGNUM >= 0) /* Do we have an FPU? */
> {
> gdb_fpregset_t *fpregs;
> @@ -3754,6 +3863,11 @@ procfs_store_registers (int regnum)
> procinfo *pi;
> int pid = PIDGET (inferior_ptid);
> int tid = TIDGET (inferior_ptid);
> + unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
> + int sparc_v8plus = (bfd_mach_sparc_v9_p (mach) && !bfd_mach_sparc_64bit_p (mach));
> +#ifdef PCSXREG
> + gdb_prxregset_t *xregs;
> +#endif
>
> /* First find procinfo for main process. */
> pi = find_procinfo_or_die (pid, 0);
> @@ -3776,6 +3890,19 @@ procfs_store_registers (int regnum)
> if (!proc_set_gregs (pi))
> proc_error (pi, "store_registers, set_gregs", __LINE__);
>
> + if (sparc_v8plus)
> + {
> +#ifdef PCSXREG
> + xregs = proc_get_xregs (pi);
> + if (xregs != NULL)
> + {
> + fill_xregset (xregs, regnum);
> + proc_set_xregs (pi);
> + }
> +#endif
> + }
> +
> +
> if (FP0_REGNUM >= 0) /* Do we have an FPU? */
> {
> gdb_fpregset_t *fpregs;
> diff -upr old_src/sparc-sol2-nat.c new_src/sparc-sol2-nat.c
> --- old_src/sparc-sol2-nat.c 2004-01-03 10:21:01.000000000 -0800
> +++ new_src/sparc-sol2-nat.c 2006-02-09 15:21:38.093231000 -0800
> @@ -24,6 +24,7 @@
>
> #include <sys/procfs.h>
> #include "gregset.h"
> +#include <sys/ucontext.h>
>
> #include "sparc-tdep.h"
>
> @@ -70,9 +71,12 @@
>
> #define sparc_sol2_gregset sparc32_sol2_gregset
> #define sparc_sol2_fpregset sparc32_sol2_fpregset
> -
> #endif
>
> +#define sparc_supply_xregset sparc32_supply_xregset
> +#define sparc_collect_xregset sparc32_collect_xregset
> +#define sparc_sol2_xregset sparc32_sol2_xregset
> +
> void
> supply_gregset (prgregset_t *gregs)
> {
> @@ -96,3 +100,14 @@ fill_fpregset (prfpregset_t *fpregs, int
> {
> sparc_collect_fpregset (current_regcache, regnum, fpregs);
> }
> +
> +void
> +supply_xregset (prxregset_t *xregs)
> +{
> + sparc_supply_xregset (&sparc_sol2_xregset, current_regcache, -1, xregs);
> +}
> +
> +void fill_xregset (prxregset_t *xregs, int regnum)
> +{
> + sparc_collect_xregset (&sparc_sol2_xregset, current_regcache, regnum, xregs);
> +}
> diff -upr old_src/sparc-sol2-tdep.c new_src/sparc-sol2-tdep.c
> --- old_src/sparc-sol2-tdep.c 2005-08-13 15:09:06.000000000 -0700
> +++ new_src/sparc-sol2-tdep.c 2006-02-09 17:28:50.748354000 -0800
> @@ -48,6 +48,15 @@ const struct sparc_gregset sparc32_sol2_
> 1 * 4, /* %g1 */
> 16 * 4, /* %l0 */
> };
> +
> +#define XRS_ID 0x78727300 /* the string "xrs" */
> +#define XRS_ID_OFFSET 224 /* offset of xrs in mcontext_t*/
> +
> +const struct sparc_xregset sparc32_sol2_xregset =
> +{
> + 148, /* xr_g1 */
> +};
> +
> \f
>
> /* The Solaris signal trampolines reside in libc. For normal signals,
> @@ -74,6 +83,39 @@ sparc_sol2_pc_in_sigtramp (CORE_ADDR pc,
> || strcmp (name, "__sighndlr") == 0));
> }
>
> +
> +/* Extract and cache extra register state from uc_mcontext member of
> + ucontext_t instance if available. */
> +void
> +sparc32_sol2_frame_cache_xregs (CORE_ADDR mcontext_addr,
> + struct frame_info *next_frame,
> + struct sparc_frame_cache *cache)
> +{
> + CORE_ADDR addr;
> + int numregs = SPARC_O7_REGNUM + 1;
> + int regnum, xrs_id;
> +
> + xrs_id = get_frame_memory_unsigned (next_frame,
> + (mcontext_addr + XRS_ID_OFFSET), 4);
> + if (xrs_id != XRS_ID)
> + return;
> +
> + addr = get_frame_memory_unsigned (next_frame,
> + (mcontext_addr + XRS_ID_OFFSET + 4), 4);
> + addr += sparc32_sol2_xregset.xr_g1_offset;
> + cache->saved_xregs = FRAME_OBSTACK_CALLOC (numregs,
> + struct trad_frame_saved_reg);
> + cache->saved_xregs[SPARC_G0_REGNUM].realreg = SPARC_G0_REGNUM;
> + cache->saved_xregs[SPARC_G0_REGNUM].addr = -1;
> + for (regnum = SPARC_G1_REGNUM; regnum < numregs; regnum++, addr +=4)
> + {
> + cache->saved_xregs[regnum].realreg = regnum;
> + cache->saved_xregs[regnum].addr = addr;
> + }
> + return;
> +}
> +
> +
> static struct sparc_frame_cache *
> sparc32_sol2_sigtramp_frame_cache (struct frame_info *next_frame,
> void **this_cache)
> @@ -81,7 +123,9 @@ sparc32_sol2_sigtramp_frame_cache (struc
> struct sparc_frame_cache *cache;
> CORE_ADDR mcontext_addr, addr;
> int regnum;
> -
> + struct gdbarch *gdbarch = get_frame_arch (next_frame);
> + unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
> +
> if (*this_cache)
> return *this_cache;
>
> @@ -121,6 +165,9 @@ sparc32_sol2_sigtramp_frame_cache (struc
> cache->saved_regs[regnum].addr = addr;
> }
>
> + if (bfd_mach_sparc_v8plus_p (mach))
> + sparc32_sol2_frame_cache_xregs (mcontext_addr, next_frame, cache);
> +
> return cache;
> }
>
> @@ -135,6 +182,40 @@ sparc32_sol2_sigtramp_frame_this_id (str
> (*this_id) = frame_id_build (cache->base, cache->pc);
> }
>
> +
> +/* Read associate extra register state information. */
> +static
> +void sparc32_sol2_sigtramp_frame_prev_xregs (struct frame_info *next_frame,
> + struct sparc_frame_cache *cache,
> + int regnum, int *optimizedp,
> + enum lval_type *lvalp, CORE_ADDR *addrp,
> + int *realregp, gdb_byte *bufferp)
> +
> +{
> + struct gdbarch *gdbarch = get_frame_arch (next_frame);
> +
> + if (!trad_frame_addr_p (cache->saved_regs, regnum))
> + error (_("Register %s not saved in memory"),
> + gdbarch_register_name (gdbarch, regnum));
> +
> + /* The register was saved in memory. */
> + *optimizedp = 0;
> + *lvalp = lval_memory;
> + *addrp = cache->saved_regs[regnum].addr;
> + *realregp = -1;
> + if (bufferp != NULL)
> + {
> + /* Read the value in from memory. */
> + memset (bufferp, 0, register_size (gdbarch, regnum));
> + get_frame_memory (next_frame, cache->saved_xregs[regnum].addr, bufferp, 4);
> + get_frame_memory (next_frame, cache->saved_regs[regnum].addr,
> + bufferp + 4, 4);
> + }
> +
> + return;
> +}
> +
> +
> static void
> sparc32_sol2_sigtramp_frame_prev_register (struct frame_info *next_frame,
> void **this_cache,
> @@ -148,6 +229,13 @@ sparc32_sol2_sigtramp_frame_prev_registe
>
> trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum,
> optimizedp, lvalp, addrp, realnump, valuep);
> + if (cache->saved_xregs &&
> + ((regnum >= SPARC_G0_REGNUM) && (regnum <= SPARC_O7_REGNUM))
> + && trad_frame_addr_p (cache->saved_regs, regnum))
> + {
> + sparc32_sol2_sigtramp_frame_prev_xregs (next_frame, cache, regnum,optimizedp,
> + lvalp, addrp, realnump, valuep);
> + }
> }
>
> static const struct frame_unwind sparc32_sol2_sigtramp_frame_unwind =
> diff -upr old_src/sparc-tdep.c new_src/sparc-tdep.c
> --- old_src/sparc-tdep.c 2005-08-13 15:12:24.000000000 -0700
> +++ new_src/sparc-tdep.c 2006-02-09 17:38:00.553882000 -0800
> @@ -300,12 +300,22 @@ sparc32_register_name (int regnum)
> static struct type *
> sparc32_register_type (struct gdbarch *gdbarch, int regnum)
> {
> + unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
> +
> if (regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F31_REGNUM)
> return builtin_type_float;
> -
> +
> if (regnum >= SPARC32_D0_REGNUM && regnum <= SPARC32_D30_REGNUM)
> return builtin_type_double;
> -
> +
> + /* sparc_v8plus support. v8plus is 32 bit abi, but with v9 ISA. This
> + allows software to use global and out registers as 64 bits registers. */
> + if (bfd_mach_sparc_v8plus_p (mach))
> + {
> + if ((regnum >= SPARC_G0_REGNUM) && (regnum <= SPARC_O7_REGNUM))
> + return builtin_type_int64;
> + }
> +
> if (regnum == SPARC_SP_REGNUM || regnum == SPARC_FP_REGNUM)
> return builtin_type_void_data_ptr;
>
> @@ -372,7 +382,11 @@ sparc32_store_arguments (struct regcache
> int num_elements = 0;
> int element = 0;
> int i;
> + gdb_byte buf[8];
> + unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
> + int sparc_v8plus = bfd_mach_sparc_v8plus_p (mach);
>
> + memset (buf, 0, sizeof (buf));
> for (i = 0; i < nargs; i++)
> {
> struct type *type = value_type (args[i]);
> @@ -421,21 +435,38 @@ sparc32_store_arguments (struct regcache
> aligned." */
> sp &= ~0x7;
>
> +
> for (i = 0; i < nargs; i++)
> {
> const bfd_byte *valbuf = value_contents (args[i]);
> struct type *type = value_type (args[i]);
> int len = TYPE_LENGTH (type);
> -
> +
> gdb_assert (len == 4 || len == 8);
> -
> +
> if (element < 6)
> {
> int regnum = SPARC_O0_REGNUM + element;
> -
> - regcache_cooked_write (regcache, regnum, valbuf);
> +
> + if (sparc_v8plus)
> + {
> + /* Although v8plus out registers are 64 bits,
> + only the lower 32 bits are used for argument passing. */
> + memcpy (buf + 4, valbuf, 4);
> + regcache_cooked_write (regcache, regnum, buf);
> + }
> + else
> + regcache_cooked_write (regcache, regnum, valbuf);
> if (len > 4 && element < 5)
> - regcache_cooked_write (regcache, regnum + 1, valbuf + 4);
> + {
> + if (sparc_v8plus)
> + {
> + memcpy (buf + 4, valbuf + 4, 4);
> + regcache_cooked_write (regcache, regnum + 1, buf);
> + }
> + else
> + regcache_cooked_write (regcache, regnum + 1, valbuf + 4);
> + }
> }
>
> /* Always store the argument in memory. */
> @@ -743,6 +774,7 @@ sparc32_frame_prev_register (struct fram
> enum lval_type *lvalp, CORE_ADDR *addrp,
> int *realnump, gdb_byte *valuep)
> {
> + int prev_out_reg = 0;
> struct sparc_frame_cache *cache =
> sparc32_frame_cache (next_frame, this_cache);
>
> @@ -815,14 +847,26 @@ sparc32_frame_prev_register (struct fram
> current frame's `in' registers. */
> if (!cache->frameless_p
> && regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM)
> - regnum += (SPARC_I0_REGNUM - SPARC_O0_REGNUM);
> + {
> + regnum += (SPARC_I0_REGNUM - SPARC_O0_REGNUM);
> + prev_out_reg = 1;
> + }
>
> *optimizedp = 0;
> *lvalp = lval_register;
> *addrp = 0;
> *realnump = regnum;
> if (valuep)
> - frame_unwind_register (next_frame, (*realnump), valuep);
> + {
> + if (bfd_mach_sparc_v8plus_p (gdbarch_bfd_arch_info (current_gdbarch)->mach)
> + && prev_out_reg)
> + {
> + memset (valuep, 0, 4);
> + frame_unwind_register (next_frame, (*realnump), valuep + 4);
> + }
> + else
> + frame_unwind_register (next_frame, (*realnump), valuep);
> + }
> }
>
> static const struct frame_unwind sparc32_frame_unwind =
> @@ -876,11 +920,12 @@ sparc32_extract_return_value (struct typ
> gdb_byte *valbuf)
> {
> int len = TYPE_LENGTH (type);
> - gdb_byte buf[8];
> -
> + gdb_byte buf[MAX_REGISTER_SIZE];
> +
> gdb_assert (!sparc_structure_or_union_p (type));
> gdb_assert (!(sparc_floating_p (type) && len == 16));
>
> + memset (buf, 0, sizeof (buf));
> if (sparc_floating_p (type))
> {
> /* Floating return values. */
> @@ -892,20 +937,36 @@ sparc32_extract_return_value (struct typ
> else
> {
> /* Integral and pointer return values. */
> - gdb_assert (sparc_integral_or_pointer_p (type));
> + int reg_size;
> + unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
> + int sparc_v8plus = bfd_mach_sparc_v8plus_p (mach);
>
> + gdb_assert (sparc_integral_or_pointer_p (type));
> +
> + reg_size = register_size (current_gdbarch, SPARC_O0_REGNUM);
> regcache_cooked_read (regcache, SPARC_O0_REGNUM, buf);
> if (len > 4)
> {
> - regcache_cooked_read (regcache, SPARC_O1_REGNUM, buf + 4);
> gdb_assert (len == 8);
> - memcpy (valbuf, buf, 8);
> +
> + regcache_cooked_read (regcache, SPARC_O1_REGNUM, buf + reg_size);
> + if (sparc_v8plus)
> + {
> + /* The lower 4 bytes of v8plus %o0 and %o1 registers make up
> + the return value. */
> + memcpy (valbuf, buf + 4, 4);
> + memcpy (valbuf + 4, buf + 12, 4);
> + }
> + else
> + {
> + memcpy (valbuf, buf, 8);
> + }
> }
> else
> {
> /* Just stripping off any unused bytes should preserve the
> signed-ness just fine. */
> - memcpy (valbuf, buf + 4 - len, len);
> + memcpy (valbuf, buf + reg_size - len, len);
> }
> }
> }
> @@ -918,11 +979,13 @@ sparc32_store_return_value (struct type
> const gdb_byte *valbuf)
> {
> int len = TYPE_LENGTH (type);
> - gdb_byte buf[8];
> -
> + gdb_byte buf[MAX_REGISTER_SIZE];
> +
> gdb_assert (!sparc_structure_or_union_p (type));
> gdb_assert (!(sparc_floating_p (type) && len == 16));
>
> + memset (buf, 0, MAX_REGISTER_SIZE);
> +
> if (sparc_floating_p (type))
> {
> /* Floating return values. */
> @@ -934,20 +997,34 @@ sparc32_store_return_value (struct type
> else
> {
> /* Integral and pointer return values. */
> + int reg_size;
> + unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
> + int sparc_v8plus = bfd_mach_sparc_v8plus_p (mach);
> +
> gdb_assert (sparc_integral_or_pointer_p (type));
>
> + reg_size = register_size (current_gdbarch, SPARC_O0_REGNUM);
> if (len > 4)
> {
> gdb_assert (len == 8);
> - memcpy (buf, valbuf, 8);
> - regcache_cooked_write (regcache, SPARC_O1_REGNUM, buf + 4);
> + if (sparc_v8plus)
> + {
> + memcpy (buf + 4, valbuf, 4);
> + memcpy (buf + 12, valbuf + 4, 4);
> + }
> + else
> + {
> + memcpy (buf, valbuf, 8);
> + }
> + regcache_cooked_write (regcache, SPARC_O1_REGNUM, buf + reg_size);
> }
> else
> {
> /* ??? Do we need to do any sign-extension here? */
> - memcpy (buf + 4 - len, valbuf, len);
> + memcpy (buf + reg_size - len, valbuf, len);
> }
> - regcache_cooked_write (regcache, SPARC_O0_REGNUM, buf);
> +
> + regcache_cooked_write (regcache, SPARC_O0_REGNUM, buf);
> }
> }
>
> @@ -1395,6 +1472,8 @@ sparc32_supply_gregset (const struct spa
> {
> const gdb_byte *regs = gregs;
> int i;
> + gdb_byte buf[8];
> + unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
>
> if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
> regcache_raw_supply (regcache, SPARC32_PSR_REGNUM,
> @@ -1418,11 +1497,20 @@ sparc32_supply_gregset (const struct spa
> if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
> {
> int offset = gregset->r_g1_offset;
> -
> +
> + memset (buf, 0, sizeof (buf));
> for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
> {
> if (regnum == i || regnum == -1)
> - regcache_raw_supply (regcache, i, regs + offset);
> + {
> + if (bfd_mach_sparc_v8plus_p (mach))
> + {
> + memcpy (buf + 4, regs + offset, 4);
> + regcache_raw_supply (regcache, i, buf);
> + }
> + else
> + regcache_raw_supply (regcache, i, regs + offset);
> + }
> offset += 4;
> }
> }
> @@ -1459,6 +1547,8 @@ sparc32_collect_gregset (const struct sp
> {
> gdb_byte *regs = gregs;
> int i;
> + gdb_byte buf[8];
> + unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
>
> if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
> regcache_raw_collect (regcache, SPARC32_PSR_REGNUM,
> @@ -1479,12 +1569,21 @@ sparc32_collect_gregset (const struct sp
> if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
> {
> int offset = gregset->r_g1_offset;
> -
> +
> + memset (buf, 0, sizeof (buf));
> /* %g0 is always zero. */
> for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
> {
> if (regnum == i || regnum == -1)
> - regcache_raw_collect (regcache, i, regs + offset);
> + {
> + if (bfd_mach_sparc_v8plus_p (mach))
> + {
> + regcache_raw_collect (regcache, i, buf);
> + memcpy (regs + offset, buf + 4, 4);
> + }
> + else
> + regcache_raw_collect (regcache, i, regs + offset);
> + }
> offset += 4;
> }
> }
> @@ -1507,6 +1606,71 @@ sparc32_collect_gregset (const struct sp
> }
> }
>
> +void
> +sparc32_supply_xregset (const struct sparc_xregset *xregset,
> + struct regcache *regcache,
> + int regnum, const void *xregs)
> +{
> + const gdb_byte *regs = xregs;
> + int i;
> + gdb_byte buf[8];
> + unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
> +
> + if (bfd_mach_sparc_v8plus_p (mach))
> + {
> + if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
> + {
> + int offset = xregset->xr_g1_offset;
> +
> + /* %g0 is always zero. */
> + for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
> + {
> + if (regnum == i || regnum == -1)
> + {
> + memset (buf, 0, sizeof (buf));
> + regcache_raw_collect (regcache, i, buf);
> + memcpy (buf, regs + offset, 4);
> + regcache_raw_supply (regcache, i, buf);
> + }
> + offset += 4;
> + }
> + }
> + }
> + return;
> +}
> +
> +void
> +sparc32_collect_xregset (const struct sparc_xregset *xregset,
> + struct regcache *regcache,
> + int regnum, void *xregs)
> +{
> + gdb_byte *regs = xregs;
> + int i;
> + gdb_byte buf[8];
> + unsigned long mach = gdbarch_bfd_arch_info (current_gdbarch)->mach;
> +
> + if (bfd_mach_sparc_v8plus_p (mach))
> + {
> + if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
> + {
> + int offset = xregset->xr_g1_offset;
> +
> + memset (buf, 0, sizeof (buf));
> + /* %g0 is always zero. */
> + for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
> + {
> + if (regnum == i || regnum == -1)
> + {
> + regcache_raw_collect (regcache, i, buf);
> + memcpy (regs + offset, buf, 4);
> + }
> + offset += 4;
> + }
> + }
> + }
> + return;
> +}
> +
> void
> sparc32_supply_fpregset (struct regcache *regcache,
> int regnum, const void *fpregs)
> diff -upr old_src/sparc-tdep.h new_src/sparc-tdep.h
> --- old_src/sparc-tdep.h 2004-11-29 07:20:27.000000000 -0800
> +++ new_src/sparc-tdep.h 2006-02-09 17:28:41.454518000 -0800
> @@ -28,6 +28,9 @@ struct regcache;
> struct regset;
> struct trad_frame_saved_reg;
>
> +#define bfd_mach_sparc_v8plus_p(mach) \
> + (bfd_mach_sparc_v9_p (mach) && !bfd_mach_sparc_64bit_p (mach))
> +
> /* Register offsets for the general-purpose register set. */
>
> struct sparc_gregset
> @@ -43,6 +46,12 @@ struct sparc_gregset
> int r_y_size;
> };
>
> +struct sparc_xregset
> +{
> + int xr_g1_offset; /* offset of G1 register. */
> + /* Add other extra register state offsets as needed. */
> +};
> +
> /* SPARC architecture-specific information. */
>
> struct gdbarch_tdep
> @@ -142,6 +151,9 @@ struct sparc_frame_cache
>
> /* Table of saved registers. */
> struct trad_frame_saved_reg *saved_regs;
> +
> + /* Table of saved extra registers. */
> + struct trad_frame_saved_reg *saved_xregs;
> };
>
> /* Fetch the instruction at PC. */
> @@ -182,11 +194,18 @@ extern void sparc32_supply_fpregset (str
> int regnum, const void *fpregs);
> extern void sparc32_collect_fpregset (const struct regcache *regcache,
> int regnum, void *fpregs);
> +extern void sparc32_supply_xregset (const struct sparc_xregset *xregset,
> + struct regcache *regcache,
> + int regnum, const void *xregs);
> +extern void sparc32_collect_xregset (const struct sparc_xregset *xregset,
> + struct regcache *regcache,
> + int regnum, void *xregs);
>
> /* Functions and variables exported from sparc-sol2-tdep.c. */
>
> /* Register offsets for Solaris 2. */
> extern const struct sparc_gregset sparc32_sol2_gregset;
> +extern const struct sparc_xregset sparc32_sol2_xregset;
>
> extern int sparc_sol2_pc_in_sigtramp (CORE_ADDR pc, char *name);
>
> diff -upr old_src/sparc64-tdep.c new_src/sparc64-tdep.c
> --- old_src/sparc64-tdep.c 2005-06-12 04:10:56.000000000 -0700
> +++ new_src/sparc64-tdep.c 2006-02-09 09:47:02.765731000 -0800
> @@ -1261,14 +1261,15 @@ sparc64_supply_gregset (const struct spa
> if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
> {
> int offset = gregset->r_g1_offset;
> -
> - if (sparc32)
> - offset += 4;
> -
> +
> + if (sparc32 &&
> + !bfd_mach_sparc_v8plus_p (gdbarch_bfd_arch_info (current_gdbarch)->mach))
> + offset += 4;
> +
> for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
> {
> if (regnum == i || regnum == -1)
> - regcache_raw_supply (regcache, i, regs + offset);
> + regcache_raw_supply (regcache, i, regs + offset);
> offset += 8;
> }
> }
> @@ -1376,8 +1377,9 @@ sparc64_collect_gregset (const struct sp
> {
> int offset = gregset->r_g1_offset;
>
> - if (sparc32)
> - offset += 4;
> + if (sparc32 &&
> + !bfd_mach_sparc_v8plus_p (gdbarch_bfd_arch_info (current_gdbarch)->mach))
> + offset += 4;
>
> /* %g0 is always zero. */
> for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
> diff -upr old_src/trad-frame.c new_src/trad-frame.c
> --- old_src/trad-frame.c 2005-05-22 07:53:34.000000000 -0700
> +++ new_src/trad-frame.c 2006-02-09 16:55:53.357073000 -0800
> @@ -148,8 +148,8 @@ trad_frame_get_prev_register (struct fra
> if (bufferp != NULL)
> {
> /* Read the value in from memory. */
> - get_frame_memory (next_frame, this_saved_regs[regnum].addr, bufferp,
> - register_size (gdbarch, regnum));
> + get_frame_memory (next_frame, this_saved_regs[regnum].addr, bufferp,
> + register_size (gdbarch, regnum));
> }
> }
> else if (trad_frame_realreg_p (this_saved_regs, regnum))
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Re : Debugging v8plus binaries on solaris
2006-02-17 22:52 ` Olatunji Ruwase
@ 2006-02-17 23:31 ` Mark Kettenis
2006-02-22 18:24 ` Olatunji Ruwase
2006-03-03 19:46 ` Olatunji Ruwase
0 siblings, 2 replies; 5+ messages in thread
From: Mark Kettenis @ 2006-02-17 23:31 UTC (permalink / raw)
To: Olatunji.Ruwase; +Cc: gdb-patches
> Date: Fri, 17 Feb 2006 14:51:31 -0800
> From: Olatunji Ruwase <Olatunji.Ruwase@Sun.COM>
Sorry, I spent most of the week in bed/on the couch in front of the
telly with a bad flu :(. I had a first glance at it last week, but
I'm afraid it needs a bit more work.
For one thing, I think it's important to split the generic v8plus
target support out from the Solaris v8plus native support. And
concentrate on the target support first. The seperation is mostly
already there (*-tdep.c versus *-nat.c), but some of the Solaris
native "weirdness" (which I realize is necessary for backwards
compatibility) has crept into the target support.
Looking from an OS agnostic point onto the v8plus support code, I
really think v8plus should be a seperate architecture much in the same
way existing 64-bit support is seperate from the 32-bit support. Of
course this v8plus architecture should reuse as much code from the
existing 32-bit code as possible, and if the 32-bit code can be
generalized to work for v8plus as well, that's great, but I think
constructs like
if (sparc_v8plus)
{
...
}
else
{
...
}
should be avoided. I also think the xregset stuff should be moved
into Solaris-specific files, perhaps even into Solaris-specofic
*-nat.c files. This depends a bit on how v8plus core dumps look. If
they have the xregset stuff too, the code should probably be moved to
sparc-sol2-tdep.c or sparc64-sol2-tdep.c.
Is the v8plus ABI documented somewhere?
Mark
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Re : Debugging v8plus binaries on solaris
2006-02-17 23:31 ` Mark Kettenis
@ 2006-02-22 18:24 ` Olatunji Ruwase
2006-03-03 19:46 ` Olatunji Ruwase
1 sibling, 0 replies; 5+ messages in thread
From: Olatunji Ruwase @ 2006-02-22 18:24 UTC (permalink / raw)
To: Mark Kettenis; +Cc: gdb-patches
Mark Kettenis wrote On 02/17/06 15:31,:
>>Date: Fri, 17 Feb 2006 14:51:31 -0800
>>From: Olatunji Ruwase <Olatunji.Ruwase@Sun.COM>
>
>
> Sorry, I spent most of the week in bed/on the couch in front of the
> telly with a bad flu :(. I had a first glance at it last week, but
Nice to have you back :).
> I'm afraid it needs a bit more work.
I suspected it would, this is my first stab at gdb development, and
the architecture of the code is still a bit fuzzy to me.
>
> For one thing, I think it's important to split the generic v8plus
> target support out from the Solaris v8plus native support. And
> concentrate on the target support first. The seperation is mostly
> already there (*-tdep.c versus *-nat.c), but some of the Solaris
> native "weirdness" (which I realize is necessary for backwards
> compatibility) has crept into the target support.
>
> Looking from an OS agnostic point onto the v8plus support code, I
> really think v8plus should be a seperate architecture much in the same
> way existing 64-bit support is seperate from the 32-bit support. Of
> course this v8plus architecture should reuse as much code from the
> existing 32-bit code as possible, and if the 32-bit code can be
> generalized to work for v8plus as well, that's great, but I think
> constructs like
>
> if (sparc_v8plus)
> {
> ...
> }
> else
> {
> ...
> }
>
Most of my changes to the target support (sparc-tdep.c) are wrapped in
the above construct. sparc32 target support assumes that registers are
4 bytes. One way to eliminate the "if (sparc_v8plus)" is to rewrite
the code to also support 8 byte registers, while making sure that data
is only written and read from the low 4 bytes. However this proposed
change will not work for sparc32_register_type(), but should work for
all other cases. Will this be an acceptable complexity in the target
support code ?. If not I will start moving all the changes into
sparc32plus-* files.
> should be avoided. I also think the xregset stuff should be moved
> into Solaris-specific files, perhaps even into Solaris-specofic
> *-nat.c files. This depends a bit on how v8plus core dumps look. If
> they have the xregset stuff too, the code should probably be moved to
> sparc-sol2-tdep.c or sparc64-sol2-tdep.c.
Yes the v8plus core dump has xregset stuff in it. And I now see why
these changes need to be restricted to solaris specific files.
>
> Is the v8plus ABI documented somewhere?
Unfortunately I dont think it is, I cant find any :(.
Thanks
tunji
>
> Mark
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Re : Debugging v8plus binaries on solaris
2006-02-17 23:31 ` Mark Kettenis
2006-02-22 18:24 ` Olatunji Ruwase
@ 2006-03-03 19:46 ` Olatunji Ruwase
1 sibling, 0 replies; 5+ messages in thread
From: Olatunji Ruwase @ 2006-03-03 19:46 UTC (permalink / raw)
To: Mark Kettenis; +Cc: gdb-patches
Mark Kettenis wrote On 02/17/06 15:31,:
>>Date: Fri, 17 Feb 2006 14:51:31 -0800
> Is the v8plus ABI documented somewhere?
>
Location of is given the link below. I 'll work on making it easier to
access.
http://forum.sun.com/thread.jspa?threadID=29408&tstart=0
Thanks
tunji
> Mark
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2006-03-03 17:56 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-02-10 20:12 Re : Debugging v8plus binaries on solaris Olatunji Ruwase
2006-02-17 22:52 ` Olatunji Ruwase
2006-02-17 23:31 ` Mark Kettenis
2006-02-22 18:24 ` Olatunji Ruwase
2006-03-03 19:46 ` Olatunji Ruwase
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox