From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 20846 invoked by alias); 10 Feb 2006 20:12:32 -0000 Received: (qmail 20829 invoked by uid 22791); 10 Feb 2006 20:12:28 -0000 X-Spam-Check-By: sourceware.org Received: from brmea-mail-2.Sun.COM (HELO brmea-mail-2.sun.com) (192.18.98.43) by sourceware.org (qpsmtpd/0.31) with ESMTP; Fri, 10 Feb 2006 20:12:25 +0000 Received: from phys-mpk-1 ([129.146.11.81]) by brmea-mail-2.sun.com (8.12.10/8.12.9) with ESMTP id k1AKCN8u016353 for ; Fri, 10 Feb 2006 13:12:23 -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 <0IUH00401MM23L@mpk-mail1.sfbay.sun.com> (original mail from Olatunji.Ruwase@Sun.COM) for gdb-patches@sources.redhat.com; Fri, 10 Feb 2006 12:12:23 -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 <0IUH000MEMSGOY@mpk-mail1.sfbay.sun.com> for gdb-patches@sources.redhat.com; Fri, 10 Feb 2006 12:12:17 -0800 (PST) Date: Fri, 10 Feb 2006 20:12:00 -0000 From: Olatunji Ruwase Subject: Re : Debugging v8plus binaries on solaris To: gdb-patches@sources.redhat.com Reply-to: Olatunji.Ruwase@Sun.COM Message-id: <43ECF3A0.6070203@Sun.COM> MIME-version: 1.0 Content-type: multipart/mixed; boundary="Boundary_(ID_u1JhyhdsivInf6qsRXBOVQ)" User-Agent: Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.4) Gecko/20041214 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/msg00254.txt.bz2 This is a multi-part message in MIME format. --Boundary_(ID_u1JhyhdsivInf6qsRXBOVQ) Content-type: text/plain; charset=us-ascii Content-transfer-encoding: 7BIT Content-length: 1178 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 --Boundary_(ID_u1JhyhdsivInf6qsRXBOVQ) Content-type: text/plain; name=v8plus_patch.txt Content-transfer-encoding: QUOTED-PRINTABLE Content-disposition: inline; filename=v8plus_patch.txt Content-length: 28552 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); =20 +#ifdef PCSXREG + +#ifndef GDB_XREGSET_T +#define GDB_XREGSET_T prxregset_t +#endif=20 + +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,=20 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 */ =20 +#ifdef PCSXREG + int xregs_fd; +#endif=20 + char pathname[MAX_PROC_NAME_SIZE]; /* Pathname to /proc entry */ =20 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 =20 +#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=20 + int xregs_valid : 1; +#endif + } procinfo; =20 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. */ =20 -enum { FD_CTL, FD_STATUS, FD_AS }; +enum { FD_CTL, FD_STATUS, FD_AS, FD_XREGS }; =20 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 =3D fd; break; + +#if PCSXREG + case FD_XREGS: + strcat (tmp, "/lwp/1/xregs"); + fd =3D open_with_retry (tmp, O_RDONLY); + if (fd <=3D 0) + return 0; /* fail */ + pi->xregs_fd =3D fd; + break; +#endif /* PCSXREG */ + default: return 0; /* unknown file descriptor */ } @@ -2597,6 +2627,71 @@ proc_get_gregs (procinfo *pi) #endif } =20 +#ifdef PCSXREG + +/* Return extra state registers for the process or LWP=20 + corresponding to PI. Upon failure return NULL. */ +gdb_prxregset_t * +proc_get_xregs (procinfo *pi) +{ + int size; +=20=20 + if (pi->xregs_fd =3D=3D 0 && + open_procinfo_files (pi, FD_XREGS) =3D=3D 0) + { + pi->xregs_valid =3D 0; + return NULL; + } + memset (&pi->xregset, 0, sizeof (gdb_prxregset_t)); + if (lseek (pi->xregs_fd, 0, SEEK_SET) < 0) + { + pi->xregs_valid =3D 0; + return NULL; + } + size =3D read (pi->xregs_fd, (char *) &pi->xregset, + sizeof (gdb_prxregset_t)) ; + pi->xregs_valid =3D (size =3D=3D sizeof (gdb_prxregset_t)); + if (pi->xregs_valid) + return &pi->xregset; + else=20 + return NULL; + +} + +/* Write extra state registers back to the process or LWP + corresponding to PI. Return non-zero for success, zero + for failure. */ +int=20 +proc_set_xregs (procinfo *pi) +{ + int win; + gdb_xregset_t *xregs; +=20=20 + xregs =3D proc_get_xregs (pi); + if (xregs =3D=3D NULL) + return 0; +=20=20 + if (pi->ctl_fd =3D=3D 0 && open_procinfo_files (pi, FD_CTL) =3D=3D 0) + { + return 0; + } + else + { + struct=20 + { + procfs_ctl_t cmd; + gdb_xregset_t xregs; + } arg; + arg.cmd =3D PCSXREG; + memcpy (&arg.xregs, xregs, sizeof (arg.xregs)); + win =3D (write (pi->ctl_fd, (void *) &arg, sizeof (arg)) =3D=3D size= of (arg)); + } + pi->xregs_valid =3D 0;=20=20 + + return win; +} +#endif /* PCSXREG */ + /* Return the general-purpose registers for the process or LWP corresponding to PI. Upon failure, return NULL. */ =20 @@ -3686,6 +3781,11 @@ procfs_fetch_registers (int regnum) procinfo *pi; int pid =3D PIDGET (inferior_ptid); int tid =3D TIDGET (inferior_ptid); + unsigned long mach =3D gdbarch_bfd_arch_info (current_gdbarch)->mach; + int sparc_v8plus =3D (bfd_mach_sparc_v9_p (mach) && !bfd_mach_sparc_64bi= t_p (mach)); +#ifdef PCSXREG + gdb_prxregset_t *xregs; +#endif =20 /* First look up procinfo for the main process. */ pi =3D find_procinfo_or_die (pid, 0); @@ -3706,6 +3806,15 @@ procfs_fetch_registers (int regnum) =20 supply_gregset (gregs); =20 + if (sparc_v8plus)=20=20 + { +#ifdef PCSXREG + xregs =3D proc_get_xregs (pi); + if (xregs !=3D NULL) + supply_xregset (xregs); +#endif + } +=20 if (FP0_REGNUM >=3D 0) /* Do we have an FPU? */ { gdb_fpregset_t *fpregs; @@ -3754,6 +3863,11 @@ procfs_store_registers (int regnum) procinfo *pi; int pid =3D PIDGET (inferior_ptid); int tid =3D TIDGET (inferior_ptid); + unsigned long mach =3D gdbarch_bfd_arch_info (current_gdbarch)->mach; + int sparc_v8plus =3D (bfd_mach_sparc_v9_p (mach) && !bfd_mach_sparc_64bi= t_p (mach)); +#ifdef PCSXREG + gdb_prxregset_t *xregs; +#endif =20 /* First find procinfo for main process. */ pi =3D 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__); =20 + if (sparc_v8plus) + { +#ifdef PCSXREG + xregs =3D proc_get_xregs (pi); + if (xregs !=3D NULL) + { + fill_xregset (xregs, regnum); + proc_set_xregs (pi); + } +#endif=20=20 + } +=20=20 + if (FP0_REGNUM >=3D 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 @@ =20 #include #include "gregset.h" +#include =20 #include "sparc-tdep.h" =20 @@ -70,9 +71,12 @@ =20 #define sparc_sol2_gregset sparc32_sol2_gregset #define sparc_sol2_fpregset sparc32_sol2_fpregset - #endif =20 +#define sparc_supply_xregset sparc32_supply_xregset=20 +#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, xr= egs); +} 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 =3D +{ + 148, /* xr_g1 */=20=20=20=20 +}; + =0C =20 /* 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") =3D=3D 0)); } =20 + +/* Extract and cache extra register state from uc_mcontext member of + ucontext_t instance if available. */ +void=20 +sparc32_sol2_frame_cache_xregs (CORE_ADDR mcontext_addr, + struct frame_info *next_frame,=20 + struct sparc_frame_cache *cache) +{ + CORE_ADDR addr; + int numregs =3D SPARC_O7_REGNUM + 1;=20 + int regnum, xrs_id; +=20=20 + xrs_id =3D get_frame_memory_unsigned (next_frame,=20 + (mcontext_addr + XRS_ID_OFFSET), 4); + if (xrs_id !=3D XRS_ID) + return; +=20=20 + addr =3D get_frame_memory_unsigned (next_frame,=20 + (mcontext_addr + XRS_ID_OFFSET + 4), 4= ); + addr +=3D sparc32_sol2_xregset.xr_g1_offset; + cache->saved_xregs =3D FRAME_OBSTACK_CALLOC (numregs, + struct trad_frame_saved_reg); + cache->saved_xregs[SPARC_G0_REGNUM].realreg =3D SPARC_G0_REGNUM; + cache->saved_xregs[SPARC_G0_REGNUM].addr =3D -1; + for (regnum =3D SPARC_G1_REGNUM; regnum < numregs; regnum++, addr +=3D4) + { + cache->saved_xregs[regnum].realreg =3D regnum; + cache->saved_xregs[regnum].addr =3D 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 =3D get_frame_arch (next_frame); + unsigned long mach =3D gdbarch_bfd_arch_info (current_gdbarch)->mach; +=20=20 if (*this_cache) return *this_cache; =20 @@ -121,6 +165,9 @@ sparc32_sol2_sigtramp_frame_cache (struc cache->saved_regs[regnum].addr =3D addr; } =20 + if (bfd_mach_sparc_v8plus_p (mach)) + sparc32_sol2_frame_cache_xregs (mcontext_addr, next_frame, cache); +=20=20 return cache; } =20 @@ -135,6 +182,40 @@ sparc32_sol2_sigtramp_frame_this_id (str (*this_id) =3D frame_id_build (cache->base, cache->pc); } =20 + +/* Read associate extra register state information. */ +static=20 +void sparc32_sol2_sigtramp_frame_prev_xregs (struct frame_info *next_frame, + struct sparc_frame_cache *cac= he, + int regnum, int *optimizedp, + enum lval_type *lvalp, CORE_A= DDR *addrp, + int *realregp, gdb_byte *buff= erp) +=20=20=20=20=20 +{ + struct gdbarch *gdbarch =3D 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 =3D 0; + *lvalp =3D lval_memory; + *addrp =3D cache->saved_regs[regnum].addr; + *realregp =3D -1; + if (bufferp !=3D NULL) + { + /* Read the value in from memory. */ + memset (bufferp, 0, register_size (gdbarch, regnum)); + get_frame_memory (next_frame, cache->saved_xregs[regnum].addr, buffe= rp, 4); + get_frame_memory (next_frame, cache->saved_regs[regnum].addr,=20 + bufferp + 4, 4); + }=20 + + 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 =20 trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum, optimizedp, lvalp, addrp, realnump, valuep); + if (cache->saved_xregs &&=20 + ((regnum >=3D SPARC_G0_REGNUM) && (regnum <=3D SPARC_O7_REGNUM)) + && trad_frame_addr_p (cache->saved_regs, regnum)) + { + sparc32_sol2_sigtramp_frame_prev_xregs (next_frame, cache, regnum,op= timizedp,=20 + lvalp, addrp, realnump, valu= ep); + } } =20 static const struct frame_unwind sparc32_sol2_sigtramp_frame_unwind =3D 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 =3D gdbarch_bfd_arch_info (current_gdbarch)->mach; +=20=20 if (regnum >=3D SPARC_F0_REGNUM && regnum <=3D SPARC_F31_REGNUM) return builtin_type_float; - +=20=20 if (regnum >=3D SPARC32_D0_REGNUM && regnum <=3D SPARC32_D30_REGNUM) return builtin_type_double; - +=20=20 + /* 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 >=3D SPARC_G0_REGNUM) && (regnum <=3D SPARC_O7_REGNUM)) + return builtin_type_int64; + } +=20=20 if (regnum =3D=3D SPARC_SP_REGNUM || regnum =3D=3D SPARC_FP_REGNUM) return builtin_type_void_data_ptr; =20 @@ -372,7 +382,11 @@ sparc32_store_arguments (struct regcache int num_elements =3D 0; int element =3D 0; int i; + gdb_byte buf[8]; + unsigned long mach =3D gdbarch_bfd_arch_info (current_gdbarch)->mach; + int sparc_v8plus =3D bfd_mach_sparc_v8plus_p (mach); =20 + memset (buf, 0, sizeof (buf)); for (i =3D 0; i < nargs; i++) { struct type *type =3D value_type (args[i]); @@ -421,21 +435,38 @@ sparc32_store_arguments (struct regcache aligned." */ sp &=3D ~0x7; =20 + for (i =3D 0; i < nargs; i++) { const bfd_byte *valbuf =3D value_contents (args[i]); struct type *type =3D value_type (args[i]); int len =3D TYPE_LENGTH (type); - +=20=20=20=20=20=20 gdb_assert (len =3D=3D 4 || len =3D=3D 8); - +=20=20=20=20=20=20 if (element < 6) { int regnum =3D SPARC_O0_REGNUM + element; - - regcache_cooked_write (regcache, regnum, valbuf); +=20=20=20=20=20=20=20=20=20=20 + 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=20 + 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); + } } =20 /* 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 =3D 0; struct sparc_frame_cache *cache =3D sparc32_frame_cache (next_frame, this_cache); =20 @@ -815,14 +847,26 @@ sparc32_frame_prev_register (struct fram current frame's `in' registers. */ if (!cache->frameless_p && regnum >=3D SPARC_O0_REGNUM && regnum <=3D SPARC_O7_REGNUM) - regnum +=3D (SPARC_I0_REGNUM - SPARC_O0_REGNUM); + { + regnum +=3D (SPARC_I0_REGNUM - SPARC_O0_REGNUM); + prev_out_reg =3D 1; + } =20 *optimizedp =3D 0; *lvalp =3D lval_register; *addrp =3D 0; *realnump =3D 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=20 + frame_unwind_register (next_frame, (*realnump), valuep); + } } =20 static const struct frame_unwind sparc32_frame_unwind =3D @@ -876,11 +920,12 @@ sparc32_extract_return_value (struct typ gdb_byte *valbuf) { int len =3D TYPE_LENGTH (type); - gdb_byte buf[8]; - + gdb_byte buf[MAX_REGISTER_SIZE]; +=20=20 gdb_assert (!sparc_structure_or_union_p (type)); gdb_assert (!(sparc_floating_p (type) && len =3D=3D 16)); =20 + 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 =3D gdbarch_bfd_arch_info (current_gdbarch)->mach; + int sparc_v8plus =3D bfd_mach_sparc_v8plus_p (mach); =20 + gdb_assert (sparc_integral_or_pointer_p (type)); +=20=20=20=20=20=20 + reg_size =3D 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 =3D=3D 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=20 + { + 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=20 const gdb_byte *valbuf) { int len =3D TYPE_LENGTH (type); - gdb_byte buf[8]; - + gdb_byte buf[MAX_REGISTER_SIZE]; +=20=20 gdb_assert (!sparc_structure_or_union_p (type)); gdb_assert (!(sparc_floating_p (type) && len =3D=3D 16)); =20 + memset (buf, 0, MAX_REGISTER_SIZE); + if (sparc_floating_p (type)) { /* Floating return values. */ @@ -934,20 +997,34 @@ sparc32_store_return_value (struct type=20 else { /* Integral and pointer return values. */ + int reg_size; + unsigned long mach =3D gdbarch_bfd_arch_info (current_gdbarch)->mach; + int sparc_v8plus =3D bfd_mach_sparc_v8plus_p (mach); + gdb_assert (sparc_integral_or_pointer_p (type)); =20 + reg_size =3D register_size (current_gdbarch, SPARC_O0_REGNUM); if (len > 4) { gdb_assert (len =3D=3D 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=20 + { + 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); } } =20 @@ -1395,6 +1472,8 @@ sparc32_supply_gregset (const struct spa { const gdb_byte *regs =3D gregs; int i; + gdb_byte buf[8]; + unsigned long mach =3D gdbarch_bfd_arch_info (current_gdbarch)->mach; =20 if (regnum =3D=3D SPARC32_PSR_REGNUM || regnum =3D=3D -1) regcache_raw_supply (regcache, SPARC32_PSR_REGNUM, @@ -1418,11 +1497,20 @@ sparc32_supply_gregset (const struct spa if ((regnum >=3D SPARC_G1_REGNUM && regnum <=3D SPARC_O7_REGNUM) || regn= um =3D=3D -1) { int offset =3D gregset->r_g1_offset; - +=20=20=20=20=20=20 + memset (buf, 0, sizeof (buf)); for (i =3D SPARC_G1_REGNUM; i <=3D SPARC_O7_REGNUM; i++) { if (regnum =3D=3D i || regnum =3D=3D -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 +=3D 4; } } @@ -1459,6 +1547,8 @@ sparc32_collect_gregset (const struct sp { gdb_byte *regs =3D gregs; int i; + gdb_byte buf[8]; + unsigned long mach =3D gdbarch_bfd_arch_info (current_gdbarch)->mach; =20 if (regnum =3D=3D SPARC32_PSR_REGNUM || regnum =3D=3D -1) regcache_raw_collect (regcache, SPARC32_PSR_REGNUM, @@ -1479,12 +1569,21 @@ sparc32_collect_gregset (const struct sp if ((regnum >=3D SPARC_G1_REGNUM && regnum <=3D SPARC_O7_REGNUM) || regn= um =3D=3D -1) { int offset =3D gregset->r_g1_offset; - +=20=20=20=20=20=20 + memset (buf, 0, sizeof (buf)); /* %g0 is always zero. */ for (i =3D SPARC_G1_REGNUM; i <=3D SPARC_O7_REGNUM; i++) { if (regnum =3D=3D i || regnum =3D=3D -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=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20 + regcache_raw_collect (regcache, i, regs + offset); + } offset +=3D 4; } } @@ -1507,6 +1606,71 @@ sparc32_collect_gregset (const struct sp } } =20 +void=20 +sparc32_supply_xregset (const struct sparc_xregset *xregset, + struct regcache *regcache, + int regnum, const void *xregs) +{ + const gdb_byte *regs =3D xregs; + int i; + gdb_byte buf[8]; + unsigned long mach =3D gdbarch_bfd_arch_info (current_gdbarch)->mach; + + if (bfd_mach_sparc_v8plus_p (mach)) + { + if ((regnum >=3D SPARC_G1_REGNUM && regnum <=3D SPARC_O7_REGNUM) || = regnum =3D=3D -1) + { + int offset =3D xregset->xr_g1_offset; +=20=20=20=20=20=20=20=20=20=20 + /* %g0 is always zero. */ + for (i =3D SPARC_G1_REGNUM; i <=3D SPARC_O7_REGNUM; i++) + { + if (regnum =3D=3D i || regnum =3D=3D -1) + { + memset (buf, 0, sizeof (buf)); + regcache_raw_collect (regcache, i, buf); + memcpy (buf, regs + offset, 4); + regcache_raw_supply (regcache, i, buf); + } + offset +=3D 4; + } + } + } + return; +} + +void=20 +sparc32_collect_xregset (const struct sparc_xregset *xregset, + struct regcache *regcache, + int regnum, void *xregs) +{ + gdb_byte *regs =3D xregs; + int i; + gdb_byte buf[8]; + unsigned long mach =3D gdbarch_bfd_arch_info (current_gdbarch)->mach; +=20=20 + if (bfd_mach_sparc_v8plus_p (mach)) + { + if ((regnum >=3D SPARC_G1_REGNUM && regnum <=3D SPARC_O7_REGNUM) || = regnum =3D=3D -1) + { + int offset =3D xregset->xr_g1_offset; +=20=20=20=20=20=20=20=20=20=20 + memset (buf, 0, sizeof (buf)); + /* %g0 is always zero. */ + for (i =3D SPARC_G1_REGNUM; i <=3D SPARC_O7_REGNUM; i++) + { + if (regnum =3D=3D i || regnum =3D=3D -1) + { + regcache_raw_collect (regcache, i, buf); + memcpy (regs + offset, buf, 4); + } + offset +=3D 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; =20 +#define bfd_mach_sparc_v8plus_p(mach) \ + (bfd_mach_sparc_v9_p (mach) && !bfd_mach_sparc_64bit_p (mach)) +=20 /* Register offsets for the general-purpose register set. */ =20 struct sparc_gregset @@ -43,6 +46,12 @@ struct sparc_gregset int r_y_size; }; =20 +struct sparc_xregset +{ + int xr_g1_offset; /* offset of G1 register. */=20 + /* Add other extra register state offsets as needed. */ +}; + /* SPARC architecture-specific information. */ =20 struct gdbarch_tdep @@ -142,6 +151,9 @@ struct sparc_frame_cache =20 /* Table of saved registers. */ struct trad_frame_saved_reg *saved_regs; + + /* Table of saved extra registers. */ + struct trad_frame_saved_reg *saved_xregs; }; =20 /* 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); =20 /* Functions and variables exported from sparc-sol2-tdep.c. */ =20 /* Register offsets for Solaris 2. */ extern const struct sparc_gregset sparc32_sol2_gregset; +extern const struct sparc_xregset sparc32_sol2_xregset; =20 extern int sparc_sol2_pc_in_sigtramp (CORE_ADDR pc, char *name); =20 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 >=3D SPARC_G1_REGNUM && regnum <=3D SPARC_O7_REGNUM) || regn= um =3D=3D -1) { int offset =3D gregset->r_g1_offset; - - if (sparc32) - offset +=3D 4; - +=20=20=20=20=20=20 + if (sparc32 &&=20 + !bfd_mach_sparc_v8plus_p (gdbarch_bfd_arch_info (current_gdbarch= )->mach)) + offset +=3D 4; +=20=20=20=20=20=20 for (i =3D SPARC_G1_REGNUM; i <=3D SPARC_O7_REGNUM; i++) { if (regnum =3D=3D i || regnum =3D=3D -1) - regcache_raw_supply (regcache, i, regs + offset); + regcache_raw_supply (regcache, i, regs + offset); offset +=3D 8; } } @@ -1376,8 +1377,9 @@ sparc64_collect_gregset (const struct sp { int offset =3D gregset->r_g1_offset; =20 - if (sparc32) - offset +=3D 4; + if (sparc32 &&=20 + !bfd_mach_sparc_v8plus_p (gdbarch_bfd_arch_info (current_gdbarch= )->mach)) + offset +=3D 4; =20 /* %g0 is always zero. */ for (i =3D SPARC_G1_REGNUM; i <=3D 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 !=3D 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, buff= erp, + register_size (gdbarch, regnum)); } } else if (trad_frame_realreg_p (this_saved_regs, regnum)) --Boundary_(ID_u1JhyhdsivInf6qsRXBOVQ)--