From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31220 invoked by alias); 17 Feb 2006 22:52:27 -0000 Received: (qmail 31200 invoked by uid 22791); 17 Feb 2006 22:52:24 -0000 X-Spam-Check-By: sourceware.org Received: from brmea-mail-4.Sun.COM (HELO brmea-mail-4.sun.com) (192.18.98.36) by sourceware.org (qpsmtpd/0.31) with ESMTP; Fri, 17 Feb 2006 22:52:21 +0000 Received: from phys-mpk-1 ([129.146.11.81]) by brmea-mail-4.sun.com (8.12.10/8.12.9) with ESMTP id k1HMpHv3016768 for ; Fri, 17 Feb 2006 15:52:19 -0700 (MST) Received: from conversion-daemon.mpk-mail1.sfbay.sun.com by mpk-mail1.sfbay.sun.com (iPlanet Messaging Server 5.2 HotFix 1.24 (built Dec 19 2003)) id <0IUU00B01SKEWQ@mpk-mail1.sfbay.sun.com> (original mail from Olatunji.Ruwase@Sun.COM) for gdb-patches@sources.redhat.com; Fri, 17 Feb 2006 14:51:40 -0800 (PST) Received: from Sun.COM (ruwase.SFBay.Sun.COM [129.146.78.63]) by mpk-mail1.sfbay.sun.com (iPlanet Messaging Server 5.2 HotFix 1.24 (built Dec 19 2003)) with ESMTP id <0IUU00A9PSTV1N@mpk-mail1.sfbay.sun.com> for gdb-patches@sources.redhat.com; Fri, 17 Feb 2006 14:51:31 -0800 (PST) Date: Fri, 17 Feb 2006 22:52:00 -0000 From: Olatunji Ruwase Subject: Re: Re : Debugging v8plus binaries on solaris In-reply-to: <43ECF3A0.6070203@Sun.COM> To: gdb-patches@sources.redhat.com Reply-to: Olatunji.Ruwase@Sun.COM Message-id: <43F65373.5020805@Sun.COM> MIME-version: 1.0 Content-type: text/plain; charset=us-ascii Content-transfer-encoding: 7BIT User-Agent: Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.4) Gecko/20041214 References: <43ECF3A0.6070203@Sun.COM> Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2006-02/txt/msg00339.txt.bz2 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//lwp//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//lwp//lwpctl > * /proc//lwp//lwpstatus > + * /proc//lwp//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 > #include "gregset.h" > +#include > > #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 */ > +}; > + > > > /* 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))