* powerpc-linux biarch corefile support
@ 2007-01-22 16:43 Alan Modra
2007-01-22 17:12 ` Mark Kettenis
0 siblings, 1 reply; 12+ messages in thread
From: Alan Modra @ 2007-01-22 16:43 UTC (permalink / raw)
To: gdb-patches
This patch updates the powerpc-linux backend to use the newer struct
regset collect_regset facility. Along with the BFD change in
http://sources.redhat.com/ml/binutils/2006-12/msg00205.html, this
gives better support for debugging 32-bit powerpc programs under a
64-bit gdb. A powerpc64-linux gdb running the gdb testsuite with -m32
shows the following improvements without any regressions. No
regressions on powerpc-linux either.
-FAIL: gdb.base/gcore.exp: where in corefile (pattern 1)
-FAIL: gdb.base/gcore.exp: corefile restored general registers
-FAIL: gdb.base/gcore.exp: capture_command_output failed on print array_func::local_array.
-FAIL: gdb.base/gcore.exp: corefile restored stack array
-FAIL: gdb.base/gcore.exp: corefile restored backtrace
-FAIL: gdb.base/multi-forks.exp: follow parent, print pids (timeout)
-FAIL: gdb.base/readline.exp: print 42
-FAIL: gdb.threads/gcore-thread.exp: a corefile thread is executing thread2
-FAIL: gdb.threads/gcore-thread.exp: thread2 is current thread in corefile
We do lose one feature of the old code, which took some pains to write
the whole register field in a gregset_t when gdb's idea of the
register size was smaller than space in the gregset_t. I figure this
is unimportant since the current gdb code doesn't make use of writing
a single field as far as I can tell. Even if it did, it would
presumably be writing into a buffer that had been initialised at some
point with a full gregset. When writing the full regset, we now clear
the buffer beforehand.
OK to apply?
* ppc-linux-nat.c (supply_gregset): Use ppc_supply_gregset.
(right_fill_reg): Delete.
(fill_gregset): Use ppc_collect_gregset.
(supply_fpregset): Use ppc_supply_fpregset.
(fill_fpregset): Use ppc_collect_fpregset.
* ppc-linux-tdep.c (PPC_LINUX_PT_*): Don't define.
(right_supply_register, ppc_linux_supply_gregset): Delete.
(ppc32_linux_supply_gregset, ppc64_linux_supply_gregset): Delete.
(ppc_linux_supply_fpregset): Delete.
(ppc32_linux_reg_offsets, ppc64_linux_reg_offsets): New.
(ppc64_32_linux_reg_offsets): New.
(ppc32_linux_gregset, ppc64_linux_gregset): Update to use reg offsets,
ppc_supply_gregset, and ppc_collect_gregset.
(ppc64_32_linux_gregset): New.
(ppc_linux_fpregset): Rename to ppc32_linux_fpregset and update.
(ppc_linux_gregset, ppc_linux_fpregset): New functions.
(ppc_linux_regset_from_core_section): Update.
* ppc-tdep.h (ppc_linux_gregset, ppc_linux_fpregset): Declare.
(ppc_linux_supply_gregset, ppc_linux_supply_fpregset): Delete.
(struct ppc_reg_offsets): Add "gpr_step" field.
* ppcnbsd-tdep.c (_initialize_ppcnbsd_tdep): Init gpr_step.
* ppcobsd-tdep.c (_initialize_ppcobsd_tdep): Likewise.
* rs6000-tdep.c (ppc_supply_gregset): Heed gpr_step. Fix xer reg
offset typo.
(ppc_collect_gregset): Heed gpr_step. Clear entire gregset before
filling if transferring all regs.
(ppc_collect_fpregset): Clear entire fpregset before filling if
transferring all regs.
Index: gdb/ppc-linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/ppc-linux-nat.c,v
retrieving revision 1.62
diff -c -3 -p -r1.62 ppc-linux-nat.c
*** gdb/ppc-linux-nat.c 9 Jan 2007 17:58:55 -0000 1.62
--- gdb/ppc-linux-nat.c 22 Jan 2007 12:33:00 -0000
*************** ppc_linux_store_inferior_registers (int
*** 909,1005 ****
store_ppc_registers (tid);
}
void
supply_gregset (gdb_gregset_t *gregsetp)
{
! /* NOTE: cagney/2003-11-25: This is the word size used by the ptrace
! interface, and not the wordsize of the program's ABI. */
! int wordsize = sizeof (long);
! ppc_linux_supply_gregset (current_regcache, -1, gregsetp,
! sizeof (gdb_gregset_t), wordsize);
! }
! static void
! right_fill_reg (int regnum, void *reg)
! {
! /* NOTE: cagney/2003-11-25: This is the word size used by the ptrace
! interface, and not the wordsize of the program's ABI. */
! int wordsize = sizeof (long);
! /* Right fill the register. */
! regcache_raw_collect (current_regcache, regnum,
! ((bfd_byte *) reg
! + wordsize
! - register_size (current_gdbarch, regnum)));
}
void
fill_gregset (gdb_gregset_t *gregsetp, int regno)
{
! int regi;
! elf_greg_t *regp = (elf_greg_t *) gregsetp;
! struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
! const int elf_ngreg = 48;
!
!
! /* Start with zeros. */
! memset (regp, 0, elf_ngreg * sizeof (*regp));
!
! for (regi = 0; regi < ppc_num_gprs; regi++)
! {
! if ((regno == -1) || regno == tdep->ppc_gp0_regnum + regi)
! right_fill_reg (tdep->ppc_gp0_regnum + regi, (regp + PT_R0 + regi));
! }
!
! if ((regno == -1) || regno == PC_REGNUM)
! right_fill_reg (PC_REGNUM, regp + PT_NIP);
! if ((regno == -1) || regno == tdep->ppc_lr_regnum)
! right_fill_reg (tdep->ppc_lr_regnum, regp + PT_LNK);
! if ((regno == -1) || regno == tdep->ppc_cr_regnum)
! regcache_raw_collect (current_regcache, tdep->ppc_cr_regnum,
! regp + PT_CCR);
! if ((regno == -1) || regno == tdep->ppc_xer_regnum)
! regcache_raw_collect (current_regcache, tdep->ppc_xer_regnum,
! regp + PT_XER);
! if ((regno == -1) || regno == tdep->ppc_ctr_regnum)
! right_fill_reg (tdep->ppc_ctr_regnum, regp + PT_CTR);
! #ifdef PT_MQ
! if (((regno == -1) || regno == tdep->ppc_mq_regnum)
! && (tdep->ppc_mq_regnum != -1))
! right_fill_reg (tdep->ppc_mq_regnum, regp + PT_MQ);
! #endif
! if ((regno == -1) || regno == tdep->ppc_ps_regnum)
! right_fill_reg (tdep->ppc_ps_regnum, regp + PT_MSR);
}
void
! supply_fpregset (gdb_fpregset_t * fpregsetp)
{
! ppc_linux_supply_fpregset (NULL, current_regcache, -1, fpregsetp,
! sizeof (gdb_fpregset_t));
}
- /* Given a pointer to a floating point register set in /proc format
- (fpregset_t *), update the register specified by REGNO from gdb's
- idea of the current floating point register set. If REGNO is -1,
- update them all. */
void
fill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
{
! int regi;
! struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
! bfd_byte *fpp = (void *) fpregsetp;
!
! if (ppc_floating_point_unit_p (current_gdbarch))
! {
! for (regi = 0; regi < ppc_num_fprs; regi++)
! {
! if ((regno == -1) || (regno == tdep->ppc_fp0_regnum + regi))
! regcache_raw_collect (current_regcache, tdep->ppc_fp0_regnum + regi,
! fpp + 8 * regi);
! }
! if (regno == -1 || regno == tdep->ppc_fpscr_regnum)
! right_fill_reg (tdep->ppc_fpscr_regnum, (fpp + 8 * 32));
! }
}
void _initialize_ppc_linux_nat (void);
--- 909,960 ----
store_ppc_registers (tid);
}
+ /* Functions for transferring registers between a gregset_t or fpregset_t
+ (see sys/ucontext.h) and gdb's regcache. The word size is that used
+ by the ptrace interface, not the current program's ABI. eg. If a
+ powerpc64-linux gdb is being used to debug a powerpc32-linux app, we
+ read or write 64-bit gregsets. This is to suit the host libthread_db.
+
+ Note that the fill_gregset and fill_fpregset functions allow for
+ writing just one register into a gregset_t or fpregset_t buffer.
+ If it so happens that the field in the buffer is larger than gdb's
+ idea of the register size, then the high order bits of the field
+ will not be written. */
+
void
supply_gregset (gdb_gregset_t *gregsetp)
{
! const struct regset *regset = ppc_linux_gregset (current_gdbarch);
! ppc_supply_gregset (regset, current_regcache, -1,
! gregsetp, sizeof (*gregsetp));
}
void
fill_gregset (gdb_gregset_t *gregsetp, int regno)
{
! const struct regset *regset = ppc_linux_gregset (current_gdbarch);
!
! ppc_collect_gregset (regset, current_regcache, regno,
! gregsetp, sizeof (*gregsetp));
}
void
! supply_fpregset (gdb_fpregset_t *fpregsetp)
{
! const struct regset *regset = ppc_linux_fpregset (current_gdbarch);
!
! ppc_supply_fpregset (regset, current_regcache, -1,
! fpregsetp, sizeof (*fpregsetp));
}
void
fill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
{
! const struct regset *regset = ppc_linux_fpregset (current_gdbarch);
!
! ppc_collect_fpregset (regset, current_regcache, regno,
! fpregsetp, sizeof (*fpregsetp));
}
void _initialize_ppc_linux_nat (void);
Index: gdb/ppc-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ppc-linux-tdep.c,v
retrieving revision 1.81
diff -c -3 -p -r1.81 ppc-linux-tdep.c
*** gdb/ppc-linux-tdep.c 9 Jan 2007 17:58:55 -0000 1.81
--- gdb/ppc-linux-tdep.c 22 Jan 2007 12:33:00 -0000
***************
*** 67,116 ****
offsetof(struct sigcontext_struct, handler) == 0x14 */
#define PPC_LINUX_HANDLER_PTR_OFFSET (PPC_LINUX_SIGNAL_FRAMESIZE + 0x14)
- /* From <asm/ptrace.h>, values for PT_NIP, PT_R1, and PT_LNK */
- #define PPC_LINUX_PT_R0 0
- #define PPC_LINUX_PT_R1 1
- #define PPC_LINUX_PT_R2 2
- #define PPC_LINUX_PT_R3 3
- #define PPC_LINUX_PT_R4 4
- #define PPC_LINUX_PT_R5 5
- #define PPC_LINUX_PT_R6 6
- #define PPC_LINUX_PT_R7 7
- #define PPC_LINUX_PT_R8 8
- #define PPC_LINUX_PT_R9 9
- #define PPC_LINUX_PT_R10 10
- #define PPC_LINUX_PT_R11 11
- #define PPC_LINUX_PT_R12 12
- #define PPC_LINUX_PT_R13 13
- #define PPC_LINUX_PT_R14 14
- #define PPC_LINUX_PT_R15 15
- #define PPC_LINUX_PT_R16 16
- #define PPC_LINUX_PT_R17 17
- #define PPC_LINUX_PT_R18 18
- #define PPC_LINUX_PT_R19 19
- #define PPC_LINUX_PT_R20 20
- #define PPC_LINUX_PT_R21 21
- #define PPC_LINUX_PT_R22 22
- #define PPC_LINUX_PT_R23 23
- #define PPC_LINUX_PT_R24 24
- #define PPC_LINUX_PT_R25 25
- #define PPC_LINUX_PT_R26 26
- #define PPC_LINUX_PT_R27 27
- #define PPC_LINUX_PT_R28 28
- #define PPC_LINUX_PT_R29 29
- #define PPC_LINUX_PT_R30 30
- #define PPC_LINUX_PT_R31 31
- #define PPC_LINUX_PT_NIP 32
- #define PPC_LINUX_PT_MSR 33
- #define PPC_LINUX_PT_CTR 35
- #define PPC_LINUX_PT_LNK 36
- #define PPC_LINUX_PT_XER 37
- #define PPC_LINUX_PT_CCR 38
- #define PPC_LINUX_PT_MQ 39
- #define PPC_LINUX_PT_FPR0 48 /* each FP reg occupies 2 slots in this space */
- #define PPC_LINUX_PT_FPR31 (PPC_LINUX_PT_FPR0 + 2*31)
- #define PPC_LINUX_PT_FPSCR (PPC_LINUX_PT_FPR0 + 2*32 + 1)
-
static int ppc_linux_at_sigtramp_return_path (CORE_ADDR pc);
/* Determine if pc is in a signal trampoline...
--- 67,72 ----
*************** ppc64_linux_convert_from_func_ptr_addr (
*** 762,860 ****
return addr;
}
! static void
! right_supply_register (struct regcache *regcache, int wordsize, int regnum,
! const bfd_byte *buf)
! {
! regcache_raw_supply (regcache, regnum,
! (buf + wordsize - register_size (current_gdbarch, regnum)));
! }
!
! /* Extract the register values found in the WORDSIZED ABI GREGSET,
! storing their values in REGCACHE. Note that some are left-aligned,
! while others are right aligned. */
! void
! ppc_linux_supply_gregset (struct regcache *regcache,
! int regnum, const void *gregs, size_t size,
! int wordsize)
! {
! int regi;
! struct gdbarch *regcache_arch = get_regcache_arch (regcache);
! struct gdbarch_tdep *regcache_tdep = gdbarch_tdep (regcache_arch);
! const bfd_byte *buf = gregs;
!
! for (regi = 0; regi < ppc_num_gprs; regi++)
! right_supply_register (regcache, wordsize,
! regcache_tdep->ppc_gp0_regnum + regi,
! buf + wordsize * regi);
!
! right_supply_register (regcache, wordsize, gdbarch_pc_regnum (regcache_arch),
! buf + wordsize * PPC_LINUX_PT_NIP);
! right_supply_register (regcache, wordsize, regcache_tdep->ppc_lr_regnum,
! buf + wordsize * PPC_LINUX_PT_LNK);
! regcache_raw_supply (regcache, regcache_tdep->ppc_cr_regnum,
! buf + wordsize * PPC_LINUX_PT_CCR);
! regcache_raw_supply (regcache, regcache_tdep->ppc_xer_regnum,
! buf + wordsize * PPC_LINUX_PT_XER);
! regcache_raw_supply (regcache, regcache_tdep->ppc_ctr_regnum,
! buf + wordsize * PPC_LINUX_PT_CTR);
! if (regcache_tdep->ppc_mq_regnum != -1)
! right_supply_register (regcache, wordsize, regcache_tdep->ppc_mq_regnum,
! buf + wordsize * PPC_LINUX_PT_MQ);
! right_supply_register (regcache, wordsize, regcache_tdep->ppc_ps_regnum,
! buf + wordsize * PPC_LINUX_PT_MSR);
! }
! static void
! ppc32_linux_supply_gregset (const struct regset *regset,
! struct regcache *regcache,
! int regnum, const void *gregs, size_t size)
! {
! ppc_linux_supply_gregset (regcache, regnum, gregs, size, 4);
! }
static struct regset ppc32_linux_gregset = {
! NULL, ppc32_linux_supply_gregset
};
- static void
- ppc64_linux_supply_gregset (const struct regset *regset,
- struct regcache * regcache,
- int regnum, const void *gregs, size_t size)
- {
- ppc_linux_supply_gregset (regcache, regnum, gregs, size, 8);
- }
-
static struct regset ppc64_linux_gregset = {
! NULL, ppc64_linux_supply_gregset
};
! void
! ppc_linux_supply_fpregset (const struct regset *regset,
! struct regcache * regcache,
! int regnum, const void *fpset, size_t size)
! {
! int regi;
! struct gdbarch *regcache_arch = get_regcache_arch (regcache);
! struct gdbarch_tdep *regcache_tdep = gdbarch_tdep (regcache_arch);
! const bfd_byte *buf = fpset;
!
! if (! ppc_floating_point_unit_p (regcache_arch))
! return;
!
! for (regi = 0; regi < ppc_num_fprs; regi++)
! regcache_raw_supply (regcache,
! regcache_tdep->ppc_fp0_regnum + regi,
! buf + 8 * regi);
!
! /* The FPSCR is stored in the low order word of the last
! doubleword in the fpregset. */
! regcache_raw_supply (regcache, regcache_tdep->ppc_fpscr_regnum,
! buf + 8 * 32 + 4);
}
! static struct regset ppc_linux_fpregset = { NULL, ppc_linux_supply_fpregset };
static const struct regset *
ppc_linux_regset_from_core_section (struct gdbarch *core_arch,
--- 718,833 ----
return addr;
}
! /* Regset descriptions. */
! static const struct ppc_reg_offsets ppc32_linux_reg_offsets =
! {
! /* General-purpose registers. */
! .r0_offset = 0,
! .gpr_step = 4,
! .pc_offset = 128,
! .ps_offset = 132,
! .cr_offset = 152,
! .lr_offset = 144,
! .ctr_offset = 140,
! .xer_offset = 148,
! .mq_offset = 156,
!
! /* Floating-point registers. */
! .f0_offset = 0,
! .fpscr_offset = 256 + 4,
!
! /* AltiVec registers. */
! .vr0_offset = 0,
! .vrsave_offset = 512,
! .vscr_offset = 512 + 12
! };
! static const struct ppc_reg_offsets ppc64_linux_reg_offsets =
! {
! /* General-purpose registers. */
! .r0_offset = 0,
! .gpr_step = 8,
! .pc_offset = 256,
! .ps_offset = 264,
! .cr_offset = 304 + 4,
! .lr_offset = 288,
! .ctr_offset = 280,
! .xer_offset = 296 + 4,
! .mq_offset = 312 + 4,
!
! /* Floating-point registers. */
! .f0_offset = 0,
! .fpscr_offset = 256 + 4,
!
! /* AltiVec registers. */
! .vr0_offset = 0,
! .vrsave_offset = 528,
! .vscr_offset = 512 + 12
! };
! static const struct ppc_reg_offsets ppc64_32_linux_reg_offsets =
! {
! /* General-purpose registers. */
! .r0_offset = 0 + 4,
! .gpr_step = 8,
! .pc_offset = 256 + 4,
! .ps_offset = 264 + 4,
! .cr_offset = 304 + 4,
! .lr_offset = 288 + 4,
! .ctr_offset = 280 + 4,
! .xer_offset = 296 + 4,
! .mq_offset = 312 + 4,
!
! /* Floating-point registers. */
! .f0_offset = 0,
! .fpscr_offset = 256 + 4,
!
! /* AltiVec registers. */
! .vr0_offset = 0,
! .vrsave_offset = 528,
! .vscr_offset = 512 + 12
! };
static struct regset ppc32_linux_gregset = {
! &ppc32_linux_reg_offsets,
! ppc_supply_gregset,
! ppc_collect_gregset
};
static struct regset ppc64_linux_gregset = {
! &ppc64_linux_reg_offsets,
! ppc_supply_gregset,
! ppc_collect_gregset
};
! static struct regset ppc64_32_linux_gregset = {
! &ppc64_32_linux_reg_offsets,
! ppc_supply_gregset,
! ppc_collect_gregset
! };
!
! static struct regset ppc32_linux_fpregset = {
! &ppc32_linux_reg_offsets,
! ppc_supply_fpregset,
! ppc_collect_fpregset
! };
!
! const struct regset *
! ppc_linux_gregset (struct gdbarch *gdbarch)
! {
! struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
! if (tdep->wordsize == 8)
! return &ppc64_linux_gregset;
! if (sizeof (long) == 8)
! return &ppc64_32_linux_gregset;
! return &ppc32_linux_gregset;
}
! const struct regset *
! ppc_linux_fpregset (struct gdbarch *gdbarch)
! {
! return &ppc32_linux_fpregset;
! }
static const struct regset *
ppc_linux_regset_from_core_section (struct gdbarch *core_arch,
*************** ppc_linux_regset_from_core_section (stru
*** 869,875 ****
return &ppc64_linux_gregset;
}
if (strcmp (sect_name, ".reg2") == 0)
! return &ppc_linux_fpregset;
return NULL;
}
--- 842,848 ----
return &ppc64_linux_gregset;
}
if (strcmp (sect_name, ".reg2") == 0)
! return &ppc32_linux_fpregset;
return NULL;
}
Index: gdb/ppc-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/ppc-tdep.h,v
retrieving revision 1.52
diff -c -3 -p -r1.52 ppc-tdep.h
*** gdb/ppc-tdep.h 9 Jan 2007 17:58:55 -0000 1.52
--- gdb/ppc-tdep.h 22 Jan 2007 12:33:00 -0000
*************** CORE_ADDR ppc64_sysv_abi_adjust_breakpoi
*** 58,69 ****
CORE_ADDR bpaddr);
int ppc_linux_memory_remove_breakpoint (struct bp_target_info *bp_tgt);
struct link_map_offsets *ppc_linux_svr4_fetch_link_map_offsets (void);
! void ppc_linux_supply_gregset (struct regcache *regcache,
! int regnum, const void *gregs, size_t size,
! int wordsize);
! void ppc_linux_supply_fpregset (const struct regset *regset,
! struct regcache *regcache,
! int regnum, const void *gregs, size_t size);
enum return_value_convention ppc64_sysv_abi_return_value (struct gdbarch *gdbarch,
struct type *valtype,
--- 58,65 ----
CORE_ADDR bpaddr);
int ppc_linux_memory_remove_breakpoint (struct bp_target_info *bp_tgt);
struct link_map_offsets *ppc_linux_svr4_fetch_link_map_offsets (void);
! const struct regset *ppc_linux_gregset (struct gdbarch *);
! const struct regset *ppc_linux_fpregset (struct gdbarch *);
enum return_value_convention ppc64_sysv_abi_return_value (struct gdbarch *gdbarch,
struct type *valtype,
*************** struct ppc_reg_offsets
*** 85,90 ****
--- 81,87 ----
{
/* General-purpose registers. */
int r0_offset;
+ int gpr_step;
int pc_offset;
int ps_offset;
int cr_offset;
Index: gdb/ppcnbsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ppcnbsd-tdep.c,v
retrieving revision 1.31
diff -c -3 -p -r1.31 ppcnbsd-tdep.c
*** gdb/ppcnbsd-tdep.c 9 Jan 2007 17:58:55 -0000 1.31
--- gdb/ppcnbsd-tdep.c 22 Jan 2007 12:33:01 -0000
*************** _initialize_ppcnbsd_tdep (void)
*** 212,217 ****
--- 212,218 ----
{
/* General-purpose registers. */
ppcnbsd_reg_offsets.r0_offset = 0;
+ ppcnbsd_reg_offsets.gpr_step = 4;
ppcnbsd_reg_offsets.lr_offset = 128;
ppcnbsd_reg_offsets.cr_offset = 132;
ppcnbsd_reg_offsets.xer_offset = 136;
Index: gdb/ppcobsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ppcobsd-tdep.c,v
retrieving revision 1.13
diff -c -3 -p -r1.13 ppcobsd-tdep.c
*** gdb/ppcobsd-tdep.c 9 Jan 2007 17:58:55 -0000 1.13
--- gdb/ppcobsd-tdep.c 22 Jan 2007 12:33:01 -0000
*************** _initialize_ppcobsd_tdep (void)
*** 331,336 ****
--- 331,337 ----
{
/* General-purpose registers. */
ppcobsd_reg_offsets.r0_offset = 0;
+ ppcobsd_reg_offsets.gpr_step = 4;
ppcobsd_reg_offsets.pc_offset = 384;
ppcobsd_reg_offsets.ps_offset = 388;
ppcobsd_reg_offsets.cr_offset = 392;
Index: gdb/rs6000-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v
retrieving revision 1.260
diff -c -3 -p -r1.260 rs6000-tdep.c
*** gdb/rs6000-tdep.c 9 Jan 2007 17:58:57 -0000 1.260
--- gdb/rs6000-tdep.c 22 Jan 2007 12:33:03 -0000
*************** ppc_supply_gregset (const struct regset
*** 338,344 ****
for (i = tdep->ppc_gp0_regnum, offset = offsets->r0_offset;
i < tdep->ppc_gp0_regnum + ppc_num_gprs;
! i++, offset += 4)
{
if (regnum == -1 || regnum == i)
ppc_supply_reg (regcache, i, gregs, offset);
--- 338,344 ----
for (i = tdep->ppc_gp0_regnum, offset = offsets->r0_offset;
i < tdep->ppc_gp0_regnum + ppc_num_gprs;
! i++, offset += offsets->gpr_step)
{
if (regnum == -1 || regnum == i)
ppc_supply_reg (regcache, i, gregs, offset);
*************** ppc_supply_gregset (const struct regset
*** 360,366 ****
gregs, offsets->ctr_offset);
if (regnum == -1 || regnum == tdep->ppc_xer_regnum)
ppc_supply_reg (regcache, tdep->ppc_xer_regnum,
! gregs, offsets->cr_offset);
if (regnum == -1 || regnum == tdep->ppc_mq_regnum)
ppc_supply_reg (regcache, tdep->ppc_mq_regnum, gregs, offsets->mq_offset);
}
--- 360,366 ----
gregs, offsets->ctr_offset);
if (regnum == -1 || regnum == tdep->ppc_xer_regnum)
ppc_supply_reg (regcache, tdep->ppc_xer_regnum,
! gregs, offsets->xer_offset);
if (regnum == -1 || regnum == tdep->ppc_mq_regnum)
ppc_supply_reg (regcache, tdep->ppc_mq_regnum, gregs, offsets->mq_offset);
}
*************** ppc_supply_fpregset (const struct regset
*** 396,402 ****
}
/* Collect register REGNUM in the general-purpose register set
! REGSET. from register cache REGCACHE into the buffer specified by
GREGS and LEN. If REGNUM is -1, do this for all registers in
REGSET. */
--- 396,402 ----
}
/* Collect register REGNUM in the general-purpose register set
! REGSET from register cache REGCACHE into the buffer specified by
GREGS and LEN. If REGNUM is -1, do this for all registers in
REGSET. */
*************** ppc_collect_gregset (const struct regset
*** 411,420 ****
size_t offset;
int i;
offset = offsets->r0_offset;
for (i = tdep->ppc_gp0_regnum;
i < tdep->ppc_gp0_regnum + ppc_num_gprs;
! i++, offset += 4)
{
if (regnum == -1 || regnum == i)
ppc_collect_reg (regcache, i, gregs, offset);
--- 411,423 ----
size_t offset;
int i;
+ if (regnum == -1)
+ memset (gregs, 0, len);
+
offset = offsets->r0_offset;
for (i = tdep->ppc_gp0_regnum;
i < tdep->ppc_gp0_regnum + ppc_num_gprs;
! i++, offset += offsets->gpr_step)
{
if (regnum == -1 || regnum == i)
ppc_collect_reg (regcache, i, gregs, offset);
*************** ppc_collect_gregset (const struct regset
*** 443,449 ****
}
/* Collect register REGNUM in the floating-point register set
! REGSET. from register cache REGCACHE into the buffer specified by
FPREGS and LEN. If REGNUM is -1, do this for all registers in
REGSET. */
--- 446,452 ----
}
/* Collect register REGNUM in the floating-point register set
! REGSET from register cache REGCACHE into the buffer specified by
FPREGS and LEN. If REGNUM is -1, do this for all registers in
REGSET. */
*************** ppc_collect_fpregset (const struct regse
*** 460,465 ****
--- 463,471 ----
gdb_assert (ppc_floating_point_unit_p (gdbarch));
+ if (regnum == -1)
+ memset (fpregs, 0, len);
+
offset = offsets->f0_offset;
for (i = tdep->ppc_fp0_regnum;
i <= tdep->ppc_fp0_regnum + ppc_num_fprs;
--
Alan Modra
IBM OzLabs - Linux Technology Centre
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: powerpc-linux biarch corefile support 2007-01-22 16:43 powerpc-linux biarch corefile support Alan Modra @ 2007-01-22 17:12 ` Mark Kettenis 2007-01-23 6:57 ` Alan Modra 0 siblings, 1 reply; 12+ messages in thread From: Mark Kettenis @ 2007-01-22 17:12 UTC (permalink / raw) To: amodra; +Cc: gdb-patches > Date: Tue, 23 Jan 2007 03:13:08 +1030 > From: Alan Modra <amodra@bigpond.net.au> > > This patch updates the powerpc-linux backend to use the newer struct > regset collect_regset facility. Along with the BFD change in > http://sources.redhat.com/ml/binutils/2006-12/msg00205.html, this > gives better support for debugging 32-bit powerpc programs under a > 64-bit gdb. A powerpc64-linux gdb running the gdb testsuite with -m32 > shows the following improvements without any regressions. No > regressions on powerpc-linux either. > > -FAIL: gdb.base/gcore.exp: where in corefile (pattern 1) > -FAIL: gdb.base/gcore.exp: corefile restored general registers > -FAIL: gdb.base/gcore.exp: capture_command_output failed on print array_func::local_array. > -FAIL: gdb.base/gcore.exp: corefile restored stack array > -FAIL: gdb.base/gcore.exp: corefile restored backtrace > -FAIL: gdb.base/multi-forks.exp: follow parent, print pids (timeout) > -FAIL: gdb.base/readline.exp: print 42 > -FAIL: gdb.threads/gcore-thread.exp: a corefile thread is executing thread2 > -FAIL: gdb.threads/gcore-thread.exp: thread2 is current thread in corefile > > We do lose one feature of the old code, which took some pains to write > the whole register field in a gregset_t when gdb's idea of the > register size was smaller than space in the gregset_t. I figure this > is unimportant since the current gdb code doesn't make use of writing > a single field as far as I can tell. Even if it did, it would > presumably be writing into a buffer that had been initialised at some > point with a full gregset. When writing the full regset, we now clear > the buffer beforehand. > > OK to apply? Unfortunately not: 1. You use C99 structure initialization syntax; GDB still uses C90. 2. The use of memset() in ppc_collect_gregset()/ppc_collect_fpregset() is wrong. These functions should leave the contents of the buffer you're collecting the registers in alone, except for the registers that are actually being collected. The special value -1, means "all registers GDB supports" not "all registers the operating system supports". In some cases the OS will store some additional bits in the data structure used by ptrace(PT_GETREGS, ...) and we want to pass those back unchanged in the matching ptrace(PT_SETREGS, ...). I guess you need this for zero-extending the GPR's to 64-bits, but I think you should do that explicitly for each register, even if REGNUM isn't -1. Also, I'd probably use gpr_size instead of gpr_step, since that expresses more clearly that the registers in the set are really that size. Mark P.S. Could you do me a favour and send unified diffs? That's seems to be what everybody does these days, and I really have lost the ability to read context diffs :(. > * ppc-linux-nat.c (supply_gregset): Use ppc_supply_gregset. > (right_fill_reg): Delete. > (fill_gregset): Use ppc_collect_gregset. > (supply_fpregset): Use ppc_supply_fpregset. > (fill_fpregset): Use ppc_collect_fpregset. > * ppc-linux-tdep.c (PPC_LINUX_PT_*): Don't define. > (right_supply_register, ppc_linux_supply_gregset): Delete. > (ppc32_linux_supply_gregset, ppc64_linux_supply_gregset): Delete. > (ppc_linux_supply_fpregset): Delete. > (ppc32_linux_reg_offsets, ppc64_linux_reg_offsets): New. > (ppc64_32_linux_reg_offsets): New. > (ppc32_linux_gregset, ppc64_linux_gregset): Update to use reg offsets, > ppc_supply_gregset, and ppc_collect_gregset. > (ppc64_32_linux_gregset): New. > (ppc_linux_fpregset): Rename to ppc32_linux_fpregset and update. > (ppc_linux_gregset, ppc_linux_fpregset): New functions. > (ppc_linux_regset_from_core_section): Update. > * ppc-tdep.h (ppc_linux_gregset, ppc_linux_fpregset): Declare. > (ppc_linux_supply_gregset, ppc_linux_supply_fpregset): Delete. > (struct ppc_reg_offsets): Add "gpr_step" field. > * ppcnbsd-tdep.c (_initialize_ppcnbsd_tdep): Init gpr_step. > * ppcobsd-tdep.c (_initialize_ppcobsd_tdep): Likewise. > * rs6000-tdep.c (ppc_supply_gregset): Heed gpr_step. Fix xer reg > offset typo. > (ppc_collect_gregset): Heed gpr_step. Clear entire gregset before > filling if transferring all regs. > (ppc_collect_fpregset): Clear entire fpregset before filling if > transferring all regs. ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: powerpc-linux biarch corefile support 2007-01-22 17:12 ` Mark Kettenis @ 2007-01-23 6:57 ` Alan Modra 2007-02-08 14:40 ` Daniel Jacobowitz 2007-04-28 16:24 ` Ulrich Weigand 0 siblings, 2 replies; 12+ messages in thread From: Alan Modra @ 2007-01-23 6:57 UTC (permalink / raw) To: Mark Kettenis; +Cc: gdb-patches On Mon, Jan 22, 2007 at 06:11:54PM +0100, Mark Kettenis wrote: > 1. You use C99 structure initialization syntax; GDB still uses C90. OK. > 2. The use of memset() in ppc_collect_gregset()/ppc_collect_fpregset() > is wrong. These functions should leave the contents of the buffer > you're collecting the registers in alone, except for the registers > that are actually being collected. The special value -1, means > "all registers GDB supports" not "all registers the operating > system supports". In some cases the OS will store some additional > bits in the data structure used by ptrace(PT_GETREGS, ...) and we > want to pass those back unchanged in the matching I see. My patch might have broken bsd.. > ptrace(PT_SETREGS, ...). I guess you need this for zero-extending > the GPR's to 64-bits, but I think you should do that explicitly for > each register, even if REGNUM isn't -1. Yes, it is for zero extending, and also for initializing unused fields. Random values in unused fields (eg. orig_gpr3) look odd in core dumps. I could cure that particular problem by clearing the buffer in linux-nat.c:linux_nat_do_thread_registers, but that doesn't help ps_lgetregs. I'm sure we'll need to clear the high word of regs for libthread_db when the inferior is 32-bit and gdb is 64-bit. So that would seem to mean we need the rather messy business of clearing individual registers, except that fill_gregset and fill_fpregset are always called with regno == -1 and are not used in the powerpc linux store_inferior_registers. (That code needs cleaning up to use ppc_collect_gregset et al too. Maybe for my next gdb patch..) ie. fill_gregset and fill_fpregset are always storing into an uninitialised buffer. How about we just clear the buffers in fill_gregset and fill_fpregset? > Also, I'd probably use gpr_size instead of gpr_step, since that > expresses more clearly that the registers in the set are really that > size. OK, and thanks for the review. How does this look? * ppc-linux-nat.c (supply_gregset): Use ppc_supply_gregset. (right_fill_reg): Delete. (fill_gregset): Use ppc_collect_gregset and clear buffer. (supply_fpregset): Use ppc_supply_fpregset. (fill_fpregset): Use ppc_collect_fpregset and clear buffer. * ppc-linux-tdep.c (PPC_LINUX_PT_*): Don't define. (right_supply_register, ppc_linux_supply_gregset): Delete. (ppc32_linux_supply_gregset, ppc64_linux_supply_gregset): Delete. (ppc_linux_supply_fpregset): Delete. (ppc32_linux_reg_offsets, ppc64_linux_reg_offsets): New. (ppc64_32_linux_reg_offsets): New. (ppc32_linux_gregset, ppc64_linux_gregset): Update to use reg offsets, ppc_supply_gregset, and ppc_collect_gregset. (ppc64_32_linux_gregset): New. (ppc_linux_fpregset): Rename to ppc32_linux_fpregset and update. (ppc_linux_gregset, ppc_linux_fpregset): New functions. (ppc_linux_regset_from_core_section): Update. * ppc-tdep.h (ppc_linux_gregset, ppc_linux_fpregset): Declare. (ppc_linux_supply_gregset, ppc_linux_supply_fpregset): Delete. (struct ppc_reg_offsets): Add "gpr_size" field. * ppcnbsd-tdep.c (_initialize_ppcnbsd_tdep): Init gpr_size. * ppcobsd-tdep.c (_initialize_ppcobsd_tdep): Likewise. * rs6000-tdep.c (ppc_collect_gregset): Heed gpr_size. (ppc_supply_gregset): Likewise. Fix xer reg offset typo. Index: gdb/ppc-linux-nat.c =================================================================== RCS file: /cvs/src/src/gdb/ppc-linux-nat.c,v retrieving revision 1.62 diff -u -p -r1.62 ppc-linux-nat.c --- gdb/ppc-linux-nat.c 9 Jan 2007 17:58:55 -0000 1.62 +++ gdb/ppc-linux-nat.c 23 Jan 2007 05:57:32 -0000 @@ -909,97 +909,60 @@ ppc_linux_store_inferior_registers (int store_ppc_registers (tid); } +/* Functions for transferring registers between a gregset_t or fpregset_t + (see sys/ucontext.h) and gdb's regcache. The word size is that used + by the ptrace interface, not the current program's ABI. eg. If a + powerpc64-linux gdb is being used to debug a powerpc32-linux app, we + read or write 64-bit gregsets. This is to suit the host libthread_db. + + Note that the fill_gregset and fill_fpregset functions allow for + writing just one register into a gregset_t or fpregset_t buffer. + If it so happens that the field in the buffer is larger than gdb's + idea of the register size, then the high order bits of the field + will not be written. Currently, we always write the whole regset. */ + void supply_gregset (gdb_gregset_t *gregsetp) { - /* NOTE: cagney/2003-11-25: This is the word size used by the ptrace - interface, and not the wordsize of the program's ABI. */ - int wordsize = sizeof (long); - ppc_linux_supply_gregset (current_regcache, -1, gregsetp, - sizeof (gdb_gregset_t), wordsize); -} + const struct regset *regset = ppc_linux_gregset (current_gdbarch); -static void -right_fill_reg (int regnum, void *reg) -{ - /* NOTE: cagney/2003-11-25: This is the word size used by the ptrace - interface, and not the wordsize of the program's ABI. */ - int wordsize = sizeof (long); - /* Right fill the register. */ - regcache_raw_collect (current_regcache, regnum, - ((bfd_byte *) reg - + wordsize - - register_size (current_gdbarch, regnum))); + ppc_supply_gregset (regset, current_regcache, -1, + gregsetp, sizeof (*gregsetp)); } void fill_gregset (gdb_gregset_t *gregsetp, int regno) { - int regi; - elf_greg_t *regp = (elf_greg_t *) gregsetp; - struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); - const int elf_ngreg = 48; - - - /* Start with zeros. */ - memset (regp, 0, elf_ngreg * sizeof (*regp)); - - for (regi = 0; regi < ppc_num_gprs; regi++) - { - if ((regno == -1) || regno == tdep->ppc_gp0_regnum + regi) - right_fill_reg (tdep->ppc_gp0_regnum + regi, (regp + PT_R0 + regi)); - } - - if ((regno == -1) || regno == PC_REGNUM) - right_fill_reg (PC_REGNUM, regp + PT_NIP); - if ((regno == -1) || regno == tdep->ppc_lr_regnum) - right_fill_reg (tdep->ppc_lr_regnum, regp + PT_LNK); - if ((regno == -1) || regno == tdep->ppc_cr_regnum) - regcache_raw_collect (current_regcache, tdep->ppc_cr_regnum, - regp + PT_CCR); - if ((regno == -1) || regno == tdep->ppc_xer_regnum) - regcache_raw_collect (current_regcache, tdep->ppc_xer_regnum, - regp + PT_XER); - if ((regno == -1) || regno == tdep->ppc_ctr_regnum) - right_fill_reg (tdep->ppc_ctr_regnum, regp + PT_CTR); -#ifdef PT_MQ - if (((regno == -1) || regno == tdep->ppc_mq_regnum) - && (tdep->ppc_mq_regnum != -1)) - right_fill_reg (tdep->ppc_mq_regnum, regp + PT_MQ); -#endif - if ((regno == -1) || regno == tdep->ppc_ps_regnum) - right_fill_reg (tdep->ppc_ps_regnum, regp + PT_MSR); + const struct regset *regset = ppc_linux_gregset (current_gdbarch); + + gdb_assert (regno == -1); + if (regno == -1) + memset (gregsetp, 0, sizeof (*gregsetp)); + + ppc_collect_gregset (regset, current_regcache, regno, + gregsetp, sizeof (*gregsetp)); } void -supply_fpregset (gdb_fpregset_t * fpregsetp) +supply_fpregset (gdb_fpregset_t *fpregsetp) { - ppc_linux_supply_fpregset (NULL, current_regcache, -1, fpregsetp, - sizeof (gdb_fpregset_t)); + const struct regset *regset = ppc_linux_fpregset (current_gdbarch); + + ppc_supply_fpregset (regset, current_regcache, -1, + fpregsetp, sizeof (*fpregsetp)); } -/* Given a pointer to a floating point register set in /proc format - (fpregset_t *), update the register specified by REGNO from gdb's - idea of the current floating point register set. If REGNO is -1, - update them all. */ void fill_fpregset (gdb_fpregset_t *fpregsetp, int regno) { - int regi; - struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); - bfd_byte *fpp = (void *) fpregsetp; - - if (ppc_floating_point_unit_p (current_gdbarch)) - { - for (regi = 0; regi < ppc_num_fprs; regi++) - { - if ((regno == -1) || (regno == tdep->ppc_fp0_regnum + regi)) - regcache_raw_collect (current_regcache, tdep->ppc_fp0_regnum + regi, - fpp + 8 * regi); - } - if (regno == -1 || regno == tdep->ppc_fpscr_regnum) - right_fill_reg (tdep->ppc_fpscr_regnum, (fpp + 8 * 32)); - } + const struct regset *regset = ppc_linux_fpregset (current_gdbarch); + + gdb_assert (regno == -1); + if (regno == -1) + memset (fpregsetp, 0, sizeof (*fpregsetp)); + + ppc_collect_fpregset (regset, current_regcache, regno, + fpregsetp, sizeof (*fpregsetp)); } void _initialize_ppc_linux_nat (void); Index: gdb/ppc-linux-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/ppc-linux-tdep.c,v retrieving revision 1.81 diff -u -p -r1.81 ppc-linux-tdep.c --- gdb/ppc-linux-tdep.c 9 Jan 2007 17:58:55 -0000 1.81 +++ gdb/ppc-linux-tdep.c 23 Jan 2007 05:57:32 -0000 @@ -67,50 +67,6 @@ offsetof(struct sigcontext_struct, handler) == 0x14 */ #define PPC_LINUX_HANDLER_PTR_OFFSET (PPC_LINUX_SIGNAL_FRAMESIZE + 0x14) -/* From <asm/ptrace.h>, values for PT_NIP, PT_R1, and PT_LNK */ -#define PPC_LINUX_PT_R0 0 -#define PPC_LINUX_PT_R1 1 -#define PPC_LINUX_PT_R2 2 -#define PPC_LINUX_PT_R3 3 -#define PPC_LINUX_PT_R4 4 -#define PPC_LINUX_PT_R5 5 -#define PPC_LINUX_PT_R6 6 -#define PPC_LINUX_PT_R7 7 -#define PPC_LINUX_PT_R8 8 -#define PPC_LINUX_PT_R9 9 -#define PPC_LINUX_PT_R10 10 -#define PPC_LINUX_PT_R11 11 -#define PPC_LINUX_PT_R12 12 -#define PPC_LINUX_PT_R13 13 -#define PPC_LINUX_PT_R14 14 -#define PPC_LINUX_PT_R15 15 -#define PPC_LINUX_PT_R16 16 -#define PPC_LINUX_PT_R17 17 -#define PPC_LINUX_PT_R18 18 -#define PPC_LINUX_PT_R19 19 -#define PPC_LINUX_PT_R20 20 -#define PPC_LINUX_PT_R21 21 -#define PPC_LINUX_PT_R22 22 -#define PPC_LINUX_PT_R23 23 -#define PPC_LINUX_PT_R24 24 -#define PPC_LINUX_PT_R25 25 -#define PPC_LINUX_PT_R26 26 -#define PPC_LINUX_PT_R27 27 -#define PPC_LINUX_PT_R28 28 -#define PPC_LINUX_PT_R29 29 -#define PPC_LINUX_PT_R30 30 -#define PPC_LINUX_PT_R31 31 -#define PPC_LINUX_PT_NIP 32 -#define PPC_LINUX_PT_MSR 33 -#define PPC_LINUX_PT_CTR 35 -#define PPC_LINUX_PT_LNK 36 -#define PPC_LINUX_PT_XER 37 -#define PPC_LINUX_PT_CCR 38 -#define PPC_LINUX_PT_MQ 39 -#define PPC_LINUX_PT_FPR0 48 /* each FP reg occupies 2 slots in this space */ -#define PPC_LINUX_PT_FPR31 (PPC_LINUX_PT_FPR0 + 2*31) -#define PPC_LINUX_PT_FPSCR (PPC_LINUX_PT_FPR0 + 2*32 + 1) - static int ppc_linux_at_sigtramp_return_path (CORE_ADDR pc); /* Determine if pc is in a signal trampoline... @@ -762,99 +718,120 @@ ppc64_linux_convert_from_func_ptr_addr ( return addr; } -static void -right_supply_register (struct regcache *regcache, int wordsize, int regnum, - const bfd_byte *buf) -{ - regcache_raw_supply (regcache, regnum, - (buf + wordsize - register_size (current_gdbarch, regnum))); -} - -/* Extract the register values found in the WORDSIZED ABI GREGSET, - storing their values in REGCACHE. Note that some are left-aligned, - while others are right aligned. */ +/* Regset descriptions. */ +static const struct ppc_reg_offsets ppc32_linux_reg_offsets = + { + /* General-purpose registers. */ + /* .r0_offset = */ 0, + /* .gpr_size = */ 4, + /* .pc_offset = */ 128, + /* .ps_offset = */ 132, + /* .cr_offset = */ 152, + /* .lr_offset = */ 144, + /* .ctr_offset = */ 140, + /* .xer_offset = */ 148, + /* .mq_offset = */ 156, + + /* Floating-point registers. */ + /* .f0_offset = */ 0, + /* .fpscr_offset = */ 256 + 4, + + /* AltiVec registers. */ + /* .vr0_offset = */ 0, + /* .vrsave_offset = */ 512, + /* .vscr_offset = */ 512 + 12 + }; -void -ppc_linux_supply_gregset (struct regcache *regcache, - int regnum, const void *gregs, size_t size, - int wordsize) -{ - int regi; - struct gdbarch *regcache_arch = get_regcache_arch (regcache); - struct gdbarch_tdep *regcache_tdep = gdbarch_tdep (regcache_arch); - const bfd_byte *buf = gregs; - - for (regi = 0; regi < ppc_num_gprs; regi++) - right_supply_register (regcache, wordsize, - regcache_tdep->ppc_gp0_regnum + regi, - buf + wordsize * regi); - - right_supply_register (regcache, wordsize, gdbarch_pc_regnum (regcache_arch), - buf + wordsize * PPC_LINUX_PT_NIP); - right_supply_register (regcache, wordsize, regcache_tdep->ppc_lr_regnum, - buf + wordsize * PPC_LINUX_PT_LNK); - regcache_raw_supply (regcache, regcache_tdep->ppc_cr_regnum, - buf + wordsize * PPC_LINUX_PT_CCR); - regcache_raw_supply (regcache, regcache_tdep->ppc_xer_regnum, - buf + wordsize * PPC_LINUX_PT_XER); - regcache_raw_supply (regcache, regcache_tdep->ppc_ctr_regnum, - buf + wordsize * PPC_LINUX_PT_CTR); - if (regcache_tdep->ppc_mq_regnum != -1) - right_supply_register (regcache, wordsize, regcache_tdep->ppc_mq_regnum, - buf + wordsize * PPC_LINUX_PT_MQ); - right_supply_register (regcache, wordsize, regcache_tdep->ppc_ps_regnum, - buf + wordsize * PPC_LINUX_PT_MSR); -} +static const struct ppc_reg_offsets ppc64_linux_reg_offsets = + { + /* General-purpose registers. */ + /* .r0_offset = */ 0, + /* .gpr_size = */ 8, + /* .pc_offset = */ 256, + /* .ps_offset = */ 264, + /* .cr_offset = */ 304 + 4, + /* .lr_offset = */ 288, + /* .ctr_offset = */ 280, + /* .xer_offset = */ 296 + 4, + /* .mq_offset = */ 312 + 4, + + /* Floating-point registers. */ + /* .f0_offset = */ 0, + /* .fpscr_offset = */ 256 + 4, + + /* AltiVec registers. */ + /* .vr0_offset = */ 0, + /* .vrsave_offset = */ 528, + /* .vscr_offset = */ 512 + 12 + }; -static void -ppc32_linux_supply_gregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *gregs, size_t size) -{ - ppc_linux_supply_gregset (regcache, regnum, gregs, size, 4); -} +static const struct ppc_reg_offsets ppc64_32_linux_reg_offsets = + { + /* General-purpose registers. */ + /* .r0_offset = */ 0 + 4, + /* .gpr_size = */ 8, + /* .pc_offset = */ 256 + 4, + /* .ps_offset = */ 264 + 4, + /* .cr_offset = */ 304 + 4, + /* .lr_offset = */ 288 + 4, + /* .ctr_offset = */ 280 + 4, + /* .xer_offset = */ 296 + 4, + /* .mq_offset = */ 312 + 4, + + /* Floating-point registers. */ + /* .f0_offset = */ 0, + /* .fpscr_offset = */ 256 + 4, + + /* AltiVec registers. */ + /* .vr0_offset = */ 0, + /* .vrsave_offset = */ 528, + /* .vscr_offset = */ 512 + 12 + }; static struct regset ppc32_linux_gregset = { - NULL, ppc32_linux_supply_gregset + &ppc32_linux_reg_offsets, + ppc_supply_gregset, + ppc_collect_gregset, + NULL }; -static void -ppc64_linux_supply_gregset (const struct regset *regset, - struct regcache * regcache, - int regnum, const void *gregs, size_t size) -{ - ppc_linux_supply_gregset (regcache, regnum, gregs, size, 8); -} - static struct regset ppc64_linux_gregset = { - NULL, ppc64_linux_supply_gregset + &ppc64_linux_reg_offsets, + ppc_supply_gregset, + ppc_collect_gregset, + NULL }; -void -ppc_linux_supply_fpregset (const struct regset *regset, - struct regcache * regcache, - int regnum, const void *fpset, size_t size) -{ - int regi; - struct gdbarch *regcache_arch = get_regcache_arch (regcache); - struct gdbarch_tdep *regcache_tdep = gdbarch_tdep (regcache_arch); - const bfd_byte *buf = fpset; - - if (! ppc_floating_point_unit_p (regcache_arch)) - return; - - for (regi = 0; regi < ppc_num_fprs; regi++) - regcache_raw_supply (regcache, - regcache_tdep->ppc_fp0_regnum + regi, - buf + 8 * regi); - - /* The FPSCR is stored in the low order word of the last - doubleword in the fpregset. */ - regcache_raw_supply (regcache, regcache_tdep->ppc_fpscr_regnum, - buf + 8 * 32 + 4); +static struct regset ppc64_32_linux_gregset = { + &ppc64_32_linux_reg_offsets, + ppc_supply_gregset, + ppc_collect_gregset, + NULL +}; + +static struct regset ppc32_linux_fpregset = { + &ppc32_linux_reg_offsets, + ppc_supply_fpregset, + ppc_collect_fpregset, + NULL +}; + +const struct regset * +ppc_linux_gregset (struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + if (tdep->wordsize == 8) + return &ppc64_linux_gregset; + if (sizeof (long) == 8) + return &ppc64_32_linux_gregset; + return &ppc32_linux_gregset; } -static struct regset ppc_linux_fpregset = { NULL, ppc_linux_supply_fpregset }; +const struct regset * +ppc_linux_fpregset (struct gdbarch *gdbarch) +{ + return &ppc32_linux_fpregset; +} static const struct regset * ppc_linux_regset_from_core_section (struct gdbarch *core_arch, @@ -869,7 +846,7 @@ ppc_linux_regset_from_core_section (stru return &ppc64_linux_gregset; } if (strcmp (sect_name, ".reg2") == 0) - return &ppc_linux_fpregset; + return &ppc32_linux_fpregset; return NULL; } Index: gdb/ppc-tdep.h =================================================================== RCS file: /cvs/src/src/gdb/ppc-tdep.h,v retrieving revision 1.52 diff -u -p -r1.52 ppc-tdep.h --- gdb/ppc-tdep.h 9 Jan 2007 17:58:55 -0000 1.52 +++ gdb/ppc-tdep.h 23 Jan 2007 05:57:32 -0000 @@ -58,12 +58,8 @@ CORE_ADDR ppc64_sysv_abi_adjust_breakpoi CORE_ADDR bpaddr); int ppc_linux_memory_remove_breakpoint (struct bp_target_info *bp_tgt); struct link_map_offsets *ppc_linux_svr4_fetch_link_map_offsets (void); -void ppc_linux_supply_gregset (struct regcache *regcache, - int regnum, const void *gregs, size_t size, - int wordsize); -void ppc_linux_supply_fpregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *gregs, size_t size); +const struct regset *ppc_linux_gregset (struct gdbarch *); +const struct regset *ppc_linux_fpregset (struct gdbarch *); enum return_value_convention ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *valtype, @@ -85,6 +81,7 @@ struct ppc_reg_offsets { /* General-purpose registers. */ int r0_offset; + int gpr_size; int pc_offset; int ps_offset; int cr_offset; Index: gdb/ppcnbsd-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/ppcnbsd-tdep.c,v retrieving revision 1.31 diff -u -p -r1.31 ppcnbsd-tdep.c --- gdb/ppcnbsd-tdep.c 9 Jan 2007 17:58:55 -0000 1.31 +++ gdb/ppcnbsd-tdep.c 23 Jan 2007 05:57:33 -0000 @@ -212,6 +212,7 @@ _initialize_ppcnbsd_tdep (void) { /* General-purpose registers. */ ppcnbsd_reg_offsets.r0_offset = 0; + ppcnbsd_reg_offsets.gpr_size = 4; ppcnbsd_reg_offsets.lr_offset = 128; ppcnbsd_reg_offsets.cr_offset = 132; ppcnbsd_reg_offsets.xer_offset = 136; Index: gdb/ppcobsd-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/ppcobsd-tdep.c,v retrieving revision 1.13 diff -u -p -r1.13 ppcobsd-tdep.c --- gdb/ppcobsd-tdep.c 9 Jan 2007 17:58:55 -0000 1.13 +++ gdb/ppcobsd-tdep.c 23 Jan 2007 05:57:33 -0000 @@ -331,6 +331,7 @@ _initialize_ppcobsd_tdep (void) { /* General-purpose registers. */ ppcobsd_reg_offsets.r0_offset = 0; + ppcobsd_reg_offsets.gpr_size = 4; ppcobsd_reg_offsets.pc_offset = 384; ppcobsd_reg_offsets.ps_offset = 388; ppcobsd_reg_offsets.cr_offset = 392; Index: gdb/rs6000-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v retrieving revision 1.260 diff -u -p -r1.260 rs6000-tdep.c --- gdb/rs6000-tdep.c 9 Jan 2007 17:58:57 -0000 1.260 +++ gdb/rs6000-tdep.c 23 Jan 2007 05:57:35 -0000 @@ -338,7 +338,7 @@ ppc_supply_gregset (const struct regset for (i = tdep->ppc_gp0_regnum, offset = offsets->r0_offset; i < tdep->ppc_gp0_regnum + ppc_num_gprs; - i++, offset += 4) + i++, offset += offsets->gpr_size) { if (regnum == -1 || regnum == i) ppc_supply_reg (regcache, i, gregs, offset); @@ -360,7 +360,7 @@ ppc_supply_gregset (const struct regset gregs, offsets->ctr_offset); if (regnum == -1 || regnum == tdep->ppc_xer_regnum) ppc_supply_reg (regcache, tdep->ppc_xer_regnum, - gregs, offsets->cr_offset); + gregs, offsets->xer_offset); if (regnum == -1 || regnum == tdep->ppc_mq_regnum) ppc_supply_reg (regcache, tdep->ppc_mq_regnum, gregs, offsets->mq_offset); } @@ -396,7 +396,7 @@ ppc_supply_fpregset (const struct regset } /* Collect register REGNUM in the general-purpose register set - REGSET. from register cache REGCACHE into the buffer specified by + REGSET from register cache REGCACHE into the buffer specified by GREGS and LEN. If REGNUM is -1, do this for all registers in REGSET. */ @@ -414,7 +414,7 @@ ppc_collect_gregset (const struct regset offset = offsets->r0_offset; for (i = tdep->ppc_gp0_regnum; i < tdep->ppc_gp0_regnum + ppc_num_gprs; - i++, offset += 4) + i++, offset += offsets->gpr_size) { if (regnum == -1 || regnum == i) ppc_collect_reg (regcache, i, gregs, offset); @@ -443,7 +443,7 @@ ppc_collect_gregset (const struct regset } /* Collect register REGNUM in the floating-point register set - REGSET. from register cache REGCACHE into the buffer specified by + REGSET from register cache REGCACHE into the buffer specified by FPREGS and LEN. If REGNUM is -1, do this for all registers in REGSET. */ -- Alan Modra IBM OzLabs - Linux Technology Centre ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: powerpc-linux biarch corefile support 2007-01-23 6:57 ` Alan Modra @ 2007-02-08 14:40 ` Daniel Jacobowitz 2007-04-28 16:24 ` Ulrich Weigand 1 sibling, 0 replies; 12+ messages in thread From: Daniel Jacobowitz @ 2007-02-08 14:40 UTC (permalink / raw) To: Alan Modra; +Cc: Mark Kettenis, gdb-patches On Tue, Jan 23, 2007 at 05:27:26PM +1030, Alan Modra wrote: > Yes, it is for zero extending, and also for initializing unused > fields. Random values in unused fields (eg. orig_gpr3) look odd in > core dumps. I could cure that particular problem by clearing the > buffer in linux-nat.c:linux_nat_do_thread_registers, but that doesn't > help ps_lgetregs. Note, we use this very rarely now - libthread_db may call it internally to get at the thread pointer, but we no longer use it to get at registers for our own purposes. > OK, and thanks for the review. How does this look? FWIW, it looks fine to me, but it's hard to read a complete rewrite. Mark, did you want to take a look at this revised patch? -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: powerpc-linux biarch corefile support 2007-01-23 6:57 ` Alan Modra 2007-02-08 14:40 ` Daniel Jacobowitz @ 2007-04-28 16:24 ` Ulrich Weigand 2007-08-25 1:23 ` Alan Modra 1 sibling, 1 reply; 12+ messages in thread From: Ulrich Weigand @ 2007-04-28 16:24 UTC (permalink / raw) To: Alan Modra; +Cc: Mark Kettenis, gdb-patches Alan Modra wrote: > Yes, it is for zero extending, and also for initializing unused > fields. Random values in unused fields (eg. orig_gpr3) look odd in > core dumps. I could cure that particular problem by clearing the > buffer in linux-nat.c:linux_nat_do_thread_registers, but that doesn't > help ps_lgetregs. I'm sure we'll need to clear the high word of regs > for libthread_db when the inferior is 32-bit and gdb is 64-bit. So > that would seem to mean we need the rather messy business of clearing > individual registers, except that fill_gregset and fill_fpregset > are always called with regno == -1 and are not used in the powerpc > linux store_inferior_registers. (That code needs cleaning up to use > ppc_collect_gregset et al too. Maybe for my next gdb patch..) > ie. fill_gregset and fill_fpregset are always storing into an > uninitialised buffer. How about we just clear the buffers in > fill_gregset and fill_fpregset? I'm not sure I'm happy with this, it will cause problems if at some time in the future fill_gregset is indeed called with regno != -1. Why don't we push the task of clearing individual registers down to ppc_supply_reg and ppc_collect_reg in rs6000-nat.c? Have their callers always provide them with an "offset" value pointing to the start of the full field in REGS, and provide an extra "size" value denoting the length of the field in REGS. The helper functions can compare that size with GDB's notion of the register_size, and if it is bigger (it cannot be smaller), supply only the right part of the field, and zero out the left part of the field when collecting. The callers of ppc_supply_reg and ppc_collect_reg should be able to provide that new size value using offsets->gpr_size or fixed values. Note that this should make ppc64_32_linux_reg_offsets unnecessary, you'll need to always use ppc64_linux_reg_offsets on a 64-bit host. Mark, would this be OK with you as well? Another minor issue: > +const struct regset * > +ppc_linux_gregset (struct gdbarch *gdbarch) > +{ > + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); > + if (tdep->wordsize == 8) > + return &ppc64_linux_gregset; > + if (sizeof (long) == 8) > + return &ppc64_32_linux_gregset; > + return &ppc32_linux_gregset; > } While you'll indeed have to check sizeof (long), you should not do so in ppc-linux-tdep.c (which is built on many different hosts when building a cross-debugger), but rather in ppc-linux-nat.c (which is only built on the native system). Pass the value in as argument similar to what the old code did ... Bye, Ulrich -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE Ulrich.Weigand@de.ibm.com ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: powerpc-linux biarch corefile support 2007-04-28 16:24 ` Ulrich Weigand @ 2007-08-25 1:23 ` Alan Modra 2007-08-28 23:03 ` Ulrich Weigand 0 siblings, 1 reply; 12+ messages in thread From: Alan Modra @ 2007-08-25 1:23 UTC (permalink / raw) To: Ulrich Weigand; +Cc: gdb-patches On Sat, Apr 28, 2007 at 06:19:36PM +0200, Ulrich Weigand wrote: > Why don't we push the task of clearing individual registers down > to ppc_supply_reg and ppc_collect_reg in rs6000-nat.c? Have their > callers always provide them with an "offset" value pointing to the > start of the full field in REGS, and provide an extra "size" value > denoting the length of the field in REGS. > > The helper functions can compare that size with GDB's notion of > the register_size, and if it is bigger (it cannot be smaller), > supply only the right part of the field, and zero out the left > part of the field when collecting. > > The callers of ppc_supply_reg and ppc_collect_reg should be able > to provide that new size value using offsets->gpr_size or fixed > values. > > Note that this should make ppc64_32_linux_reg_offsets unnecessary, > you'll need to always use ppc64_linux_reg_offsets on a 64-bit host. OK, that's what I've done in the following patch. Looking first at the generic rs6000 changes, these are: 1) Add a "gpr_size" field to "struct ppc_reg_offsets" so that the collect_regset and supply_regset functions will work with both 32-bit and 64-bit regsets. We can't simply use tdep->wordsize to deduce the size of registers, because in some cases (eg. supply_gregset and fill_gregset in ppc-linux-nat.c) the size we want is "sizeof (long)" rather than the target wordsize. 2) The low level ppc_supply_reg and ppc_collect_reg functions are changed as per Ulrich's suggestion, to zero pad a larger register field as necessary. 3) I reorganized ppc_supply_gregset et al to be a little more efficient. It seemed silly to run around a loop to find a gpr/fpr offset when transferring one register. This particular change also fixes a bug in one of the register offsets, and removes uses of current_gdbarch where the gdbarch is available from the regcache. 4) ppc_supply_fpregset and ppc_collect_fpregset had an assert that the target had a fp unit, and callers generally tested the same. I changed the assert to instead return if !ppc_floating_point_unit_p and removed the caller tests. It seems silly to duplicate the tests, and I believe it is correct for ppc_supply_fpregset and ppc_collect_fpregset to do nothing when the target has no fp unit. It is certainly consistent with other cases where one or more registers are not present in a target. With these changes in place quite a lot of ppc-linux-nat.c and ppc-linux-tdep.c can disappear, and we get biarch core file capability. Note that without (4) above, we need a wrapper for ppc_supply_fpregset and ppc_collect_fpregset so that these functions aren't called for e500. I removed the FIXMEs in ppcobsd-tdep.c because that seems appropriate in line with removing the asserts in (4). I left the other two similar FIXMEs (in ppcobsd-nat.c and ppcnbsd-nat.c) as code there (and in the callers of getfpregs_supplies) will need updating to handle e500. * ppc-linux-nat.c (right_fill_reg): Delete. (supply_gregset): Use ppc_supply_gregset. (supply_fpregset): Use ppc_supply_fpregset. (fill_gregset): Use ppc_collect_gregset. (fill_fpregset): Use ppc_collect_fpregset. * ppc-linux-tdep.c (PPC_LINUX_PT_*): Don't define. (right_supply_register, ppc_linux_supply_gregset): Delete. (ppc32_linux_supply_gregset, ppc64_linux_supply_gregset): Delete. (ppc_linux_supply_fpregset): Delete. (ppc32_linux_reg_offsets, ppc64_linux_reg_offsets): New. (ppc32_linux_gregset, ppc64_linux_gregset): Update to use reg offsets, ppc_supply_gregset, and ppc_collect_gregset. (ppc_linux_fpregset): Rename to ppc32_linux_fpregset and update. (ppc_linux_gregset, ppc_linux_fpregset): New functions. (ppc_linux_regset_from_core_section): Update. * ppc-tdep.h (ppc_linux_gregset, ppc_linux_fpregset): Declare. (ppc_linux_supply_gregset, ppc_linux_supply_fpregset): Delete. (struct ppc_reg_offsets): Add "gpr_size" field. * ppcobsd-tdep.c (ppcobsd_supply_gregset): Delete FIXME and assert. (ppcobsd_collect_gregset): Likewise. (_initialize_ppcnbsd_tdep): Init gpr_size. * ppcnbsd-tdep.c (_initialize_ppcobsd_tdep): Likewise. * rs6000-aix-tdep.c (rs6000_aix_supply_regset): Call ppc_supply_fpregset without testing ppc_floating_point_unit_p. (rs6000_aix_collect_regset): Similarly. * rs6000-tdep.c (ppc_supply_reg): Add regsize param. Adjust offset when regsize is larger than regcache register size. (ppc_collect_reg): Similarly zero pad when regsize is larger than regcache register size. (ppc_greg_offset): New function, split out from.. (ppc_supply_gregset): ..here. Separate code handling all regs from single reg case. Correct xer offset. (ppc_fpreg_offset): New function, split out from.. (ppc_supply_fpregset): ..here. Separate code handling all regs from single reg case. (ppc_collect_gregset, ppc_collect_fpregset): Likewise. (ppc_supply_fpregset, ppc_collect_fpregset): Don't assert we have a fp unit, instead return if no fp. Index: gdb/ppc-linux-nat.c =================================================================== RCS file: /cvs/src/src/gdb/ppc-linux-nat.c,v retrieving revision 1.69 diff -u -p -r1.69 ppc-linux-nat.c --- gdb/ppc-linux-nat.c 23 Aug 2007 18:08:36 -0000 1.69 +++ gdb/ppc-linux-nat.c 24 Aug 2007 13:08:20 -0000 @@ -901,101 +901,46 @@ ppc_linux_store_inferior_registers (stru store_ppc_registers (regcache, tid); } +/* Functions for transferring registers between a gregset_t or fpregset_t + (see sys/ucontext.h) and gdb's regcache. The word size is that used + by the ptrace interface, not the current program's ABI. eg. If a + powerpc64-linux gdb is being used to debug a powerpc32-linux app, we + read or write 64-bit gregsets. This is to suit the host libthread_db. */ + void supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp) { - /* NOTE: cagney/2003-11-25: This is the word size used by the ptrace - interface, and not the wordsize of the program's ABI. */ - int wordsize = sizeof (long); - ppc_linux_supply_gregset (regcache, -1, gregsetp, - sizeof (gdb_gregset_t), wordsize); -} + const struct regset *regset = ppc_linux_gregset (sizeof (long)); -static void -right_fill_reg (const struct regcache *regcache, int regnum, void *reg) -{ - /* NOTE: cagney/2003-11-25: This is the word size used by the ptrace - interface, and not the wordsize of the program's ABI. */ - int wordsize = sizeof (long); - /* Right fill the register. */ - regcache_raw_collect (regcache, regnum, - ((bfd_byte *) reg - + wordsize - - register_size (current_gdbarch, regnum))); + ppc_supply_gregset (regset, regcache, -1, gregsetp, sizeof (*gregsetp)); } void fill_gregset (const struct regcache *regcache, gdb_gregset_t *gregsetp, int regno) { - int regi; - elf_greg_t *regp = (elf_greg_t *) gregsetp; - struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); - const int elf_ngreg = 48; - - - /* Start with zeros. */ - memset (regp, 0, elf_ngreg * sizeof (*regp)); - - for (regi = 0; regi < ppc_num_gprs; regi++) - { - if ((regno == -1) || regno == tdep->ppc_gp0_regnum + regi) - right_fill_reg (regcache, tdep->ppc_gp0_regnum + regi, - (regp + PT_R0 + regi)); - } - - if ((regno == -1) || regno == gdbarch_pc_regnum (current_gdbarch)) - right_fill_reg (regcache, gdbarch_pc_regnum (current_gdbarch), - regp + PT_NIP); - if ((regno == -1) || regno == tdep->ppc_lr_regnum) - right_fill_reg (regcache, tdep->ppc_lr_regnum, regp + PT_LNK); - if ((regno == -1) || regno == tdep->ppc_cr_regnum) - regcache_raw_collect (regcache, tdep->ppc_cr_regnum, - regp + PT_CCR); - if ((regno == -1) || regno == tdep->ppc_xer_regnum) - regcache_raw_collect (regcache, tdep->ppc_xer_regnum, - regp + PT_XER); - if ((regno == -1) || regno == tdep->ppc_ctr_regnum) - right_fill_reg (regcache, tdep->ppc_ctr_regnum, regp + PT_CTR); -#ifdef PT_MQ - if (((regno == -1) || regno == tdep->ppc_mq_regnum) - && (tdep->ppc_mq_regnum != -1)) - right_fill_reg (regcache, tdep->ppc_mq_regnum, regp + PT_MQ); -#endif - if ((regno == -1) || regno == tdep->ppc_ps_regnum) - right_fill_reg (regcache, tdep->ppc_ps_regnum, regp + PT_MSR); + const struct regset *regset = ppc_linux_gregset (sizeof (long)); + + ppc_collect_gregset (regset, regcache, regno, gregsetp, sizeof (*gregsetp)); } void supply_fpregset (struct regcache *regcache, const gdb_fpregset_t * fpregsetp) { - ppc_linux_supply_fpregset (NULL, regcache, -1, fpregsetp, - sizeof (gdb_fpregset_t)); + const struct regset *regset = ppc_linux_fpregset (); + + ppc_supply_fpregset (regset, regcache, -1, + fpregsetp, sizeof (*fpregsetp)); } -/* Given a pointer to a floating point register set in /proc format - (fpregset_t *), update the register specified by REGNO from gdb's - idea of the current floating point register set. If REGNO is -1, - update them all. */ void fill_fpregset (const struct regcache *regcache, gdb_fpregset_t *fpregsetp, int regno) { - int regi; - struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); - bfd_byte *fpp = (void *) fpregsetp; - - if (ppc_floating_point_unit_p (current_gdbarch)) - { - for (regi = 0; regi < ppc_num_fprs; regi++) - { - if ((regno == -1) || (regno == tdep->ppc_fp0_regnum + regi)) - regcache_raw_collect (regcache, tdep->ppc_fp0_regnum + regi, - fpp + 8 * regi); - } - if (regno == -1 || regno == tdep->ppc_fpscr_regnum) - right_fill_reg (regcache, tdep->ppc_fpscr_regnum, (fpp + 8 * 32)); - } + const struct regset *regset = ppc_linux_fpregset (); + + ppc_collect_fpregset (regset, regcache, regno, + fpregsetp, sizeof (*fpregsetp)); } void _initialize_ppc_linux_nat (void); Index: gdb/ppc-linux-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/ppc-linux-tdep.c,v retrieving revision 1.87 diff -u -p -r1.87 ppc-linux-tdep.c --- gdb/ppc-linux-tdep.c 23 Aug 2007 18:08:36 -0000 1.87 +++ gdb/ppc-linux-tdep.c 24 Aug 2007 13:08:21 -0000 @@ -38,51 +38,6 @@ #include "frame-unwind.h" #include "tramp-frame.h" -/* From <asm/ptrace.h>, values for PT_NIP, PT_R1, and PT_LNK */ -#define PPC_LINUX_PT_R0 0 -#define PPC_LINUX_PT_R1 1 -#define PPC_LINUX_PT_R2 2 -#define PPC_LINUX_PT_R3 3 -#define PPC_LINUX_PT_R4 4 -#define PPC_LINUX_PT_R5 5 -#define PPC_LINUX_PT_R6 6 -#define PPC_LINUX_PT_R7 7 -#define PPC_LINUX_PT_R8 8 -#define PPC_LINUX_PT_R9 9 -#define PPC_LINUX_PT_R10 10 -#define PPC_LINUX_PT_R11 11 -#define PPC_LINUX_PT_R12 12 -#define PPC_LINUX_PT_R13 13 -#define PPC_LINUX_PT_R14 14 -#define PPC_LINUX_PT_R15 15 -#define PPC_LINUX_PT_R16 16 -#define PPC_LINUX_PT_R17 17 -#define PPC_LINUX_PT_R18 18 -#define PPC_LINUX_PT_R19 19 -#define PPC_LINUX_PT_R20 20 -#define PPC_LINUX_PT_R21 21 -#define PPC_LINUX_PT_R22 22 -#define PPC_LINUX_PT_R23 23 -#define PPC_LINUX_PT_R24 24 -#define PPC_LINUX_PT_R25 25 -#define PPC_LINUX_PT_R26 26 -#define PPC_LINUX_PT_R27 27 -#define PPC_LINUX_PT_R28 28 -#define PPC_LINUX_PT_R29 29 -#define PPC_LINUX_PT_R30 30 -#define PPC_LINUX_PT_R31 31 -#define PPC_LINUX_PT_NIP 32 -#define PPC_LINUX_PT_MSR 33 -#define PPC_LINUX_PT_CTR 35 -#define PPC_LINUX_PT_LNK 36 -#define PPC_LINUX_PT_XER 37 -#define PPC_LINUX_PT_CCR 38 -#define PPC_LINUX_PT_MQ 39 -#define PPC_LINUX_PT_FPR0 48 /* each FP reg occupies 2 slots in this space */ -#define PPC_LINUX_PT_FPR31 (PPC_LINUX_PT_FPR0 + 2*31) -#define PPC_LINUX_PT_FPSCR (PPC_LINUX_PT_FPR0 + 2*32 + 1) - - static CORE_ADDR ppc_linux_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc) { @@ -660,99 +615,85 @@ ppc_linux_convert_from_func_ptr_addr (st return addr; } -static void -right_supply_register (struct regcache *regcache, int wordsize, int regnum, - const bfd_byte *buf) -{ - regcache_raw_supply (regcache, regnum, - (buf + wordsize - register_size (current_gdbarch, regnum))); -} - -/* Extract the register values found in the WORDSIZED ABI GREGSET, - storing their values in REGCACHE. Note that some are left-aligned, - while others are right aligned. */ - -void -ppc_linux_supply_gregset (struct regcache *regcache, - int regnum, const void *gregs, size_t size, - int wordsize) -{ - int regi; - struct gdbarch *regcache_arch = get_regcache_arch (regcache); - struct gdbarch_tdep *regcache_tdep = gdbarch_tdep (regcache_arch); - const bfd_byte *buf = gregs; - - for (regi = 0; regi < ppc_num_gprs; regi++) - right_supply_register (regcache, wordsize, - regcache_tdep->ppc_gp0_regnum + regi, - buf + wordsize * regi); - - right_supply_register (regcache, wordsize, gdbarch_pc_regnum (regcache_arch), - buf + wordsize * PPC_LINUX_PT_NIP); - right_supply_register (regcache, wordsize, regcache_tdep->ppc_lr_regnum, - buf + wordsize * PPC_LINUX_PT_LNK); - regcache_raw_supply (regcache, regcache_tdep->ppc_cr_regnum, - buf + wordsize * PPC_LINUX_PT_CCR); - regcache_raw_supply (regcache, regcache_tdep->ppc_xer_regnum, - buf + wordsize * PPC_LINUX_PT_XER); - regcache_raw_supply (regcache, regcache_tdep->ppc_ctr_regnum, - buf + wordsize * PPC_LINUX_PT_CTR); - if (regcache_tdep->ppc_mq_regnum != -1) - right_supply_register (regcache, wordsize, regcache_tdep->ppc_mq_regnum, - buf + wordsize * PPC_LINUX_PT_MQ); - right_supply_register (regcache, wordsize, regcache_tdep->ppc_ps_regnum, - buf + wordsize * PPC_LINUX_PT_MSR); -} +/* Regset descriptions. */ +static const struct ppc_reg_offsets ppc32_linux_reg_offsets = + { + /* General-purpose registers. */ + /* .r0_offset = */ 0, + /* .gpr_size = */ 4, + /* .pc_offset = */ 128, + /* .ps_offset = */ 132, + /* .cr_offset = */ 152, + /* .lr_offset = */ 144, + /* .ctr_offset = */ 140, + /* .xer_offset = */ 148, + /* .mq_offset = */ 156, + + /* Floating-point registers. */ + /* .f0_offset = */ 0, + /* .fpscr_offset = */ 256 + 4, + + /* AltiVec registers. */ + /* .vr0_offset = */ 0, + /* .vrsave_offset = */ 512, + /* .vscr_offset = */ 512 + 12 + }; -static void -ppc32_linux_supply_gregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *gregs, size_t size) -{ - ppc_linux_supply_gregset (regcache, regnum, gregs, size, 4); -} +static const struct ppc_reg_offsets ppc64_linux_reg_offsets = + { + /* General-purpose registers. */ + /* .r0_offset = */ 0, + /* .gpr_size = */ 8, + /* .pc_offset = */ 256, + /* .ps_offset = */ 264, + /* .cr_offset = */ 304, + /* .lr_offset = */ 288, + /* .ctr_offset = */ 280, + /* .xer_offset = */ 296, + /* .mq_offset = */ 312, + + /* Floating-point registers. */ + /* .f0_offset = */ 0, + /* .fpscr_offset = */ 256, + + /* AltiVec registers. */ + /* .vr0_offset = */ 0, + /* .vrsave_offset = */ 528, + /* .vscr_offset = */ 512 + 12 + }; static struct regset ppc32_linux_gregset = { - NULL, ppc32_linux_supply_gregset + &ppc32_linux_reg_offsets, + ppc_supply_gregset, + ppc_collect_gregset, + NULL }; -static void -ppc64_linux_supply_gregset (const struct regset *regset, - struct regcache * regcache, - int regnum, const void *gregs, size_t size) -{ - ppc_linux_supply_gregset (regcache, regnum, gregs, size, 8); -} - static struct regset ppc64_linux_gregset = { - NULL, ppc64_linux_supply_gregset + &ppc64_linux_reg_offsets, + ppc_supply_gregset, + ppc_collect_gregset, + NULL }; -void -ppc_linux_supply_fpregset (const struct regset *regset, - struct regcache * regcache, - int regnum, const void *fpset, size_t size) -{ - int regi; - struct gdbarch *regcache_arch = get_regcache_arch (regcache); - struct gdbarch_tdep *regcache_tdep = gdbarch_tdep (regcache_arch); - const bfd_byte *buf = fpset; - - if (! ppc_floating_point_unit_p (regcache_arch)) - return; - - for (regi = 0; regi < ppc_num_fprs; regi++) - regcache_raw_supply (regcache, - regcache_tdep->ppc_fp0_regnum + regi, - buf + 8 * regi); - - /* The FPSCR is stored in the low order word of the last - doubleword in the fpregset. */ - regcache_raw_supply (regcache, regcache_tdep->ppc_fpscr_regnum, - buf + 8 * 32 + 4); +static struct regset ppc32_linux_fpregset = { + &ppc32_linux_reg_offsets, + ppc_supply_fpregset, + ppc_collect_fpregset, + NULL +}; + +const struct regset * +ppc_linux_gregset (int wordsize) +{ + return wordsize == 8 ? &ppc64_linux_gregset : &ppc32_linux_gregset; } -static struct regset ppc_linux_fpregset = { NULL, ppc_linux_supply_fpregset }; +const struct regset * +ppc_linux_fpregset (void) +{ + return &ppc32_linux_fpregset; +} static const struct regset * ppc_linux_regset_from_core_section (struct gdbarch *core_arch, @@ -767,7 +708,7 @@ ppc_linux_regset_from_core_section (stru return &ppc64_linux_gregset; } if (strcmp (sect_name, ".reg2") == 0) - return &ppc_linux_fpregset; + return &ppc32_linux_fpregset; return NULL; } Index: gdb/ppc-tdep.h =================================================================== RCS file: /cvs/src/src/gdb/ppc-tdep.h,v retrieving revision 1.55 diff -u -p -r1.55 ppc-tdep.h --- gdb/ppc-tdep.h 23 Aug 2007 18:08:36 -0000 1.55 +++ gdb/ppc-tdep.h 24 Aug 2007 13:08:21 -0000 @@ -56,12 +56,8 @@ CORE_ADDR ppc64_sysv_abi_adjust_breakpoi CORE_ADDR bpaddr); int ppc_linux_memory_remove_breakpoint (struct bp_target_info *bp_tgt); struct link_map_offsets *ppc_linux_svr4_fetch_link_map_offsets (void); -void ppc_linux_supply_gregset (struct regcache *regcache, - int regnum, const void *gregs, size_t size, - int wordsize); -void ppc_linux_supply_fpregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *gregs, size_t size); +const struct regset *ppc_linux_gregset (int); +const struct regset *ppc_linux_fpregset (void); enum return_value_convention ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *valtype, @@ -83,6 +79,7 @@ struct ppc_reg_offsets { /* General-purpose registers. */ int r0_offset; + int gpr_size; int pc_offset; int ps_offset; int cr_offset; Index: gdb/ppcnbsd-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/ppcnbsd-tdep.c,v retrieving revision 1.33 diff -u -p -r1.33 ppcnbsd-tdep.c --- gdb/ppcnbsd-tdep.c 23 Aug 2007 18:08:36 -0000 1.33 +++ gdb/ppcnbsd-tdep.c 24 Aug 2007 13:08:21 -0000 @@ -213,6 +213,7 @@ _initialize_ppcnbsd_tdep (void) { /* General-purpose registers. */ ppcnbsd_reg_offsets.r0_offset = 0; + ppcnbsd_reg_offsets.gpr_size = 4; ppcnbsd_reg_offsets.lr_offset = 128; ppcnbsd_reg_offsets.cr_offset = 132; ppcnbsd_reg_offsets.xer_offset = 136; Index: gdb/ppcobsd-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/ppcobsd-tdep.c,v retrieving revision 1.17 diff -u -p -r1.17 ppcobsd-tdep.c --- gdb/ppcobsd-tdep.c 23 Aug 2007 18:08:36 -0000 1.17 +++ gdb/ppcobsd-tdep.c 24 Aug 2007 13:08:21 -0000 @@ -51,18 +51,6 @@ ppcobsd_supply_gregset (const struct reg struct regcache *regcache, int regnum, const void *gregs, size_t len) { - /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating - point registers. Traditionally, GDB's register set has still - listed the floating point registers for such machines, so this - code is harmless. However, the new E500 port actually omits the - floating point registers entirely from the register set --- they - don't even have register numbers assigned to them. - - It's not clear to me how best to update this code, so this assert - will alert the first person to encounter the OpenBSD/E500 - combination to the problem. */ - gdb_assert (ppc_floating_point_unit_p (current_gdbarch)); - ppc_supply_gregset (regset, regcache, regnum, gregs, len); ppc_supply_fpregset (regset, regcache, regnum, gregs, len); } @@ -77,18 +65,6 @@ ppcobsd_collect_gregset (const struct re const struct regcache *regcache, int regnum, void *gregs, size_t len) { - /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating - point registers. Traditionally, GDB's register set has still - listed the floating point registers for such machines, so this - code is harmless. However, the new E500 port actually omits the - floating point registers entirely from the register set --- they - don't even have register numbers assigned to them. - - It's not clear to me how best to update this code, so this assert - will alert the first person to encounter the OpenBSD/E500 - combination to the problem. */ - gdb_assert (ppc_floating_point_unit_p (current_gdbarch)); - ppc_collect_gregset (regset, regcache, regnum, gregs, len); ppc_collect_fpregset (regset, regcache, regnum, gregs, len); } @@ -331,6 +307,7 @@ _initialize_ppcobsd_tdep (void) { /* General-purpose registers. */ ppcobsd_reg_offsets.r0_offset = 0; + ppcobsd_reg_offsets.gpr_size = 4; ppcobsd_reg_offsets.pc_offset = 384; ppcobsd_reg_offsets.ps_offset = 388; ppcobsd_reg_offsets.cr_offset = 392; Index: gdb/rs6000-aix-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/rs6000-aix-tdep.c,v retrieving revision 1.5 diff -u -p -r1.5 rs6000-aix-tdep.c --- gdb/rs6000-aix-tdep.c 23 Aug 2007 18:08:37 -0000 1.5 +++ gdb/rs6000-aix-tdep.c 24 Aug 2007 13:08:21 -0000 @@ -85,9 +85,7 @@ rs6000_aix_supply_regset (const struct r const void *gregs, size_t len) { ppc_supply_gregset (regset, regcache, regnum, gregs, len); - - if (ppc_floating_point_unit_p (get_regcache_arch (regcache))) - ppc_supply_fpregset (regset, regcache, regnum, gregs, len); + ppc_supply_fpregset (regset, regcache, regnum, gregs, len); } /* Collect register REGNUM in the general-purpose register set @@ -101,9 +99,7 @@ rs6000_aix_collect_regset (const struct void *gregs, size_t len) { ppc_collect_gregset (regset, regcache, regnum, gregs, len); - - if (ppc_floating_point_unit_p (get_regcache_arch (regcache))) - ppc_collect_fpregset (regset, regcache, regnum, gregs, len); + ppc_collect_fpregset (regset, regcache, regnum, gregs, len); } /* AIX register set. */ Index: gdb/rs6000-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v retrieving revision 1.287 diff -u -p -r1.287 rs6000-tdep.c --- gdb/rs6000-tdep.c 23 Aug 2007 18:08:37 -0000 1.287 +++ gdb/rs6000-tdep.c 24 Aug 2007 13:08:24 -0000 @@ -302,22 +302,106 @@ rs6000_register_sim_regno (int reg) /* Register set support functions. */ +/* REGS + OFFSET contains register REGNUM in a field REGSIZE wide. + Write the register to REGCACHE. */ + static void ppc_supply_reg (struct regcache *regcache, int regnum, - const gdb_byte *regs, size_t offset) + const gdb_byte *regs, size_t offset, int regsize) { if (regnum != -1 && offset != -1) - regcache_raw_supply (regcache, regnum, regs + offset); + { + if (regsize > 4) + { + struct gdbarch *gdbarch = get_regcache_arch (regcache); + int gdb_regsize = register_size (gdbarch, regnum); + if (gdb_regsize < regsize + && gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + offset += regsize - gdb_regsize; + } + regcache_raw_supply (regcache, regnum, regs + offset); + } } +/* Read register REGNUM from REGCACHE and store to REGS + OFFSET + in a field REGSIZE wide. Zero pad as necessary. */ + static void ppc_collect_reg (const struct regcache *regcache, int regnum, - gdb_byte *regs, size_t offset) + gdb_byte *regs, size_t offset, int regsize) { if (regnum != -1 && offset != -1) - regcache_raw_collect (regcache, regnum, regs + offset); + { + if (regsize > 4) + { + struct gdbarch *gdbarch = get_regcache_arch (regcache); + int gdb_regsize = register_size (gdbarch, regnum); + if (gdb_regsize < regsize) + { + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + { + memset (regs + offset, 0, regsize - gdb_regsize); + offset += regsize - gdb_regsize; + } + else + memset (regs + offset + regsize - gdb_regsize, 0, + regsize - gdb_regsize); + } + } + regcache_raw_collect (regcache, regnum, regs + offset); + } } +static int +ppc_greg_offset (struct gdbarch *gdbarch, + struct gdbarch_tdep *tdep, + const struct ppc_reg_offsets *offsets, + int regnum) +{ + if (regnum >= tdep->ppc_gp0_regnum + && regnum < tdep->ppc_gp0_regnum + ppc_num_gprs) + return (offsets->r0_offset + + (regnum - tdep->ppc_gp0_regnum) * offsets->gpr_size); + + if (regnum == gdbarch_pc_regnum (gdbarch)) + return offsets->pc_offset; + + if (regnum == tdep->ppc_ps_regnum) + return offsets->ps_offset; + + if (regnum == tdep->ppc_cr_regnum) + return offsets->cr_offset; + + if (regnum == tdep->ppc_lr_regnum) + return offsets->lr_offset; + + if (regnum == tdep->ppc_ctr_regnum) + return offsets->ctr_offset; + + if (regnum == tdep->ppc_xer_regnum) + return offsets->xer_offset; + + if (regnum == tdep->ppc_mq_regnum) + return offsets->mq_offset; + + return -1; +} + +static int +ppc_fpreg_offset (struct gdbarch_tdep *tdep, + const struct ppc_reg_offsets *offsets, + int regnum) +{ + if (regnum >= tdep->ppc_fp0_regnum + && regnum < tdep->ppc_fp0_regnum + ppc_num_fprs) + return offsets->f0_offset + (regnum - tdep->ppc_fp0_regnum) * 8; + + if (regnum == tdep->ppc_fpscr_regnum) + return offsets->fpscr_offset; + + return -1; +} + /* Supply register REGNUM in the general-purpose register set REGSET from the buffer specified by GREGS and LEN to register cache REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ @@ -330,36 +414,36 @@ ppc_supply_gregset (const struct regset struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); const struct ppc_reg_offsets *offsets = regset->descr; size_t offset; - int i; + int gpr_size = offsets->gpr_size; + + if (regnum == -1) + { + int i; + + for (i = tdep->ppc_gp0_regnum, offset = offsets->r0_offset; + i < tdep->ppc_gp0_regnum + ppc_num_gprs; + i++, offset += gpr_size) + ppc_supply_reg (regcache, i, gregs, offset, gpr_size); + + ppc_supply_reg (regcache, gdbarch_pc_regnum (gdbarch), + gregs, offsets->pc_offset, gpr_size); + ppc_supply_reg (regcache, tdep->ppc_ps_regnum, + gregs, offsets->ps_offset, gpr_size); + ppc_supply_reg (regcache, tdep->ppc_cr_regnum, + gregs, offsets->cr_offset, gpr_size); + ppc_supply_reg (regcache, tdep->ppc_lr_regnum, + gregs, offsets->lr_offset, gpr_size); + ppc_supply_reg (regcache, tdep->ppc_ctr_regnum, + gregs, offsets->ctr_offset, gpr_size); + ppc_supply_reg (regcache, tdep->ppc_xer_regnum, + gregs, offsets->xer_offset, gpr_size); + ppc_supply_reg (regcache, tdep->ppc_mq_regnum, + gregs, offsets->mq_offset, gpr_size); + return; + } - for (i = tdep->ppc_gp0_regnum, offset = offsets->r0_offset; - i < tdep->ppc_gp0_regnum + ppc_num_gprs; - i++, offset += 4) - { - if (regnum == -1 || regnum == i) - ppc_supply_reg (regcache, i, gregs, offset); - } - - if (regnum == -1 || regnum == gdbarch_pc_regnum (current_gdbarch)) - ppc_supply_reg (regcache, gdbarch_pc_regnum (current_gdbarch), - gregs, offsets->pc_offset); - if (regnum == -1 || regnum == tdep->ppc_ps_regnum) - ppc_supply_reg (regcache, tdep->ppc_ps_regnum, - gregs, offsets->ps_offset); - if (regnum == -1 || regnum == tdep->ppc_cr_regnum) - ppc_supply_reg (regcache, tdep->ppc_cr_regnum, - gregs, offsets->cr_offset); - if (regnum == -1 || regnum == tdep->ppc_lr_regnum) - ppc_supply_reg (regcache, tdep->ppc_lr_regnum, - gregs, offsets->lr_offset); - if (regnum == -1 || regnum == tdep->ppc_ctr_regnum) - ppc_supply_reg (regcache, tdep->ppc_ctr_regnum, - gregs, offsets->ctr_offset); - if (regnum == -1 || regnum == tdep->ppc_xer_regnum) - ppc_supply_reg (regcache, tdep->ppc_xer_regnum, - gregs, offsets->cr_offset); - if (regnum == -1 || regnum == tdep->ppc_mq_regnum) - ppc_supply_reg (regcache, tdep->ppc_mq_regnum, gregs, offsets->mq_offset); + offset = ppc_greg_offset (gdbarch, tdep, offsets, regnum); + ppc_supply_reg (regcache, regnum, gregs, offset, gpr_size); } /* Supply register REGNUM in the floating-point register set REGSET @@ -371,29 +455,36 @@ ppc_supply_fpregset (const struct regset int regnum, const void *fpregs, size_t len) { struct gdbarch *gdbarch = get_regcache_arch (regcache); - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - const struct ppc_reg_offsets *offsets = regset->descr; + struct gdbarch_tdep *tdep; + const struct ppc_reg_offsets *offsets; size_t offset; - int i; - gdb_assert (ppc_floating_point_unit_p (gdbarch)); + if (!ppc_floating_point_unit_p (gdbarch)) + return; - offset = offsets->f0_offset; - for (i = tdep->ppc_fp0_regnum; - i < tdep->ppc_fp0_regnum + ppc_num_fprs; - i++, offset += 8) + tdep = gdbarch_tdep (gdbarch); + offsets = regset->descr; + if (regnum == -1) { - if (regnum == -1 || regnum == i) - ppc_supply_reg (regcache, i, fpregs, offset); + int i; + + for (i = tdep->ppc_fp0_regnum, offset = offsets->f0_offset; + i < tdep->ppc_fp0_regnum + ppc_num_fprs; + i++, offset += 8) + ppc_supply_reg (regcache, i, fpregs, offset, 8); + + ppc_supply_reg (regcache, tdep->ppc_fpscr_regnum, + fpregs, offsets->fpscr_offset, offsets->gpr_size); + return; } - if (regnum == -1 || regnum == tdep->ppc_fpscr_regnum) - ppc_supply_reg (regcache, tdep->ppc_fpscr_regnum, - fpregs, offsets->fpscr_offset); + offset = ppc_fpreg_offset (tdep, offsets, regnum); + ppc_supply_reg (regcache, regnum, fpregs, offset, + regnum == tdep->ppc_fpscr_regnum ? offsets->gpr_size : 8); } /* Collect register REGNUM in the general-purpose register set - REGSET. from register cache REGCACHE into the buffer specified by + REGSET from register cache REGCACHE into the buffer specified by GREGS and LEN. If REGNUM is -1, do this for all registers in REGSET. */ @@ -406,42 +497,40 @@ ppc_collect_gregset (const struct regset struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); const struct ppc_reg_offsets *offsets = regset->descr; size_t offset; - int i; + int gpr_size = offsets->gpr_size; + + if (regnum == -1) + { + int i; + + for (i = tdep->ppc_gp0_regnum, offset = offsets->r0_offset; + i < tdep->ppc_gp0_regnum + ppc_num_gprs; + i++, offset += gpr_size) + ppc_collect_reg (regcache, i, gregs, offset, gpr_size); + + ppc_collect_reg (regcache, gdbarch_pc_regnum (gdbarch), + gregs, offsets->pc_offset, gpr_size); + ppc_collect_reg (regcache, tdep->ppc_ps_regnum, + gregs, offsets->ps_offset, gpr_size); + ppc_collect_reg (regcache, tdep->ppc_cr_regnum, + gregs, offsets->cr_offset, gpr_size); + ppc_collect_reg (regcache, tdep->ppc_lr_regnum, + gregs, offsets->lr_offset, gpr_size); + ppc_collect_reg (regcache, tdep->ppc_ctr_regnum, + gregs, offsets->ctr_offset, gpr_size); + ppc_collect_reg (regcache, tdep->ppc_xer_regnum, + gregs, offsets->xer_offset, gpr_size); + ppc_collect_reg (regcache, tdep->ppc_mq_regnum, + gregs, offsets->mq_offset, gpr_size); + return; + } - offset = offsets->r0_offset; - for (i = tdep->ppc_gp0_regnum; - i < tdep->ppc_gp0_regnum + ppc_num_gprs; - i++, offset += 4) - { - if (regnum == -1 || regnum == i) - ppc_collect_reg (regcache, i, gregs, offset); - } - - if (regnum == -1 || regnum == gdbarch_pc_regnum (current_gdbarch)) - ppc_collect_reg (regcache, gdbarch_pc_regnum (current_gdbarch), - gregs, offsets->pc_offset); - if (regnum == -1 || regnum == tdep->ppc_ps_regnum) - ppc_collect_reg (regcache, tdep->ppc_ps_regnum, - gregs, offsets->ps_offset); - if (regnum == -1 || regnum == tdep->ppc_cr_regnum) - ppc_collect_reg (regcache, tdep->ppc_cr_regnum, - gregs, offsets->cr_offset); - if (regnum == -1 || regnum == tdep->ppc_lr_regnum) - ppc_collect_reg (regcache, tdep->ppc_lr_regnum, - gregs, offsets->lr_offset); - if (regnum == -1 || regnum == tdep->ppc_ctr_regnum) - ppc_collect_reg (regcache, tdep->ppc_ctr_regnum, - gregs, offsets->ctr_offset); - if (regnum == -1 || regnum == tdep->ppc_xer_regnum) - ppc_collect_reg (regcache, tdep->ppc_xer_regnum, - gregs, offsets->xer_offset); - if (regnum == -1 || regnum == tdep->ppc_mq_regnum) - ppc_collect_reg (regcache, tdep->ppc_mq_regnum, - gregs, offsets->mq_offset); + offset = ppc_greg_offset (gdbarch, tdep, offsets, regnum); + ppc_collect_reg (regcache, regnum, gregs, offset, gpr_size); } /* Collect register REGNUM in the floating-point register set - REGSET. from register cache REGCACHE into the buffer specified by + REGSET from register cache REGCACHE into the buffer specified by FPREGS and LEN. If REGNUM is -1, do this for all registers in REGSET. */ @@ -451,25 +540,32 @@ ppc_collect_fpregset (const struct regse int regnum, void *fpregs, size_t len) { struct gdbarch *gdbarch = get_regcache_arch (regcache); - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - const struct ppc_reg_offsets *offsets = regset->descr; + struct gdbarch_tdep *tdep; + const struct ppc_reg_offsets *offsets; size_t offset; - int i; - gdb_assert (ppc_floating_point_unit_p (gdbarch)); + if (!ppc_floating_point_unit_p (gdbarch)) + return; - offset = offsets->f0_offset; - for (i = tdep->ppc_fp0_regnum; - i <= tdep->ppc_fp0_regnum + ppc_num_fprs; - i++, offset += 8) + tdep = gdbarch_tdep (gdbarch); + offsets = regset->descr; + if (regnum == -1) { - if (regnum == -1 || regnum == i) - ppc_collect_reg (regcache, i, fpregs, offset); + int i; + + for (i = tdep->ppc_fp0_regnum, offset = offsets->f0_offset; + i < tdep->ppc_fp0_regnum + ppc_num_fprs; + i++, offset += 8) + ppc_collect_reg (regcache, i, fpregs, offset, 8); + + ppc_collect_reg (regcache, tdep->ppc_fpscr_regnum, + fpregs, offsets->fpscr_offset, offsets->gpr_size); + return; } - if (regnum == -1 || regnum == tdep->ppc_fpscr_regnum) - ppc_collect_reg (regcache, tdep->ppc_fpscr_regnum, - fpregs, offsets->fpscr_offset); + offset = ppc_fpreg_offset (tdep, offsets, regnum); + ppc_collect_reg (regcache, regnum, fpregs, offset, + regnum == tdep->ppc_fpscr_regnum ? offsets->gpr_size : 8); } \f -- Alan Modra Australia Development Lab, IBM ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: powerpc-linux biarch corefile support 2007-08-25 1:23 ` Alan Modra @ 2007-08-28 23:03 ` Ulrich Weigand 2007-08-29 7:26 ` Alan Modra 0 siblings, 1 reply; 12+ messages in thread From: Ulrich Weigand @ 2007-08-28 23:03 UTC (permalink / raw) To: Alan Modra; +Cc: gdb-patches Alan Modra wrote: > Looking first at the generic rs6000 changes, these are: > 1) Add a "gpr_size" field to "struct ppc_reg_offsets" so that the > collect_regset and supply_regset functions will work with both > 32-bit and 64-bit regsets. We can't simply use tdep->wordsize to > deduce the size of registers, because in some cases > (eg. supply_gregset and fill_gregset in ppc-linux-nat.c) the size > we want is "sizeof (long)" rather than the target wordsize. > 2) The low level ppc_supply_reg and ppc_collect_reg functions are > changed as per Ulrich's suggestion, to zero pad a larger register > field as necessary. > 3) I reorganized ppc_supply_gregset et al to be a little more > efficient. It seemed silly to run around a loop to find a gpr/fpr > offset when transferring one register. This particular change also > fixes a bug in one of the register offsets, and removes uses of > current_gdbarch where the gdbarch is available from the regcache. > 4) ppc_supply_fpregset and ppc_collect_fpregset had an assert that > the target had a fp unit, and callers generally tested the same. > I changed the assert to instead return if !ppc_floating_point_unit_p > and removed the caller tests. It seems silly to duplicate the > tests, and I believe it is correct for ppc_supply_fpregset and > ppc_collect_fpregset to do nothing when the target has no fp unit. > It is certainly consistent with other cases where one or more > registers are not present in a target. Thanks for working on this! The patch looks fine to me, however I wonder about one change: > -/* Extract the register values found in the WORDSIZED ABI GREGSET, > - storing their values in REGCACHE. Note that some are left-aligned, > - while others are right aligned. */ In particular, the original code appears to treat CCR, XER, and CTR as left-aligned, and the others as right-aligned: > -void > -ppc_linux_supply_gregset (struct regcache *regcache, > - int regnum, const void *gregs, size_t size, > - int wordsize) > -{ > - int regi; > - struct gdbarch *regcache_arch = get_regcache_arch (regcache); > - struct gdbarch_tdep *regcache_tdep = gdbarch_tdep (regcache_arch); > - const bfd_byte *buf = gregs; > - > - for (regi = 0; regi < ppc_num_gprs; regi++) > - right_supply_register (regcache, wordsize, > - regcache_tdep->ppc_gp0_regnum + regi, > - buf + wordsize * regi); > - > - right_supply_register (regcache, wordsize, gdbarch_pc_regnum (regcache_arch), > - buf + wordsize * PPC_LINUX_PT_NIP); > - right_supply_register (regcache, wordsize, regcache_tdep->ppc_lr_regnum, > - buf + wordsize * PPC_LINUX_PT_LNK); > - regcache_raw_supply (regcache, regcache_tdep->ppc_cr_regnum, > - buf + wordsize * PPC_LINUX_PT_CCR); > - regcache_raw_supply (regcache, regcache_tdep->ppc_xer_regnum, > - buf + wordsize * PPC_LINUX_PT_XER); > - regcache_raw_supply (regcache, regcache_tdep->ppc_ctr_regnum, > - buf + wordsize * PPC_LINUX_PT_CTR); > - if (regcache_tdep->ppc_mq_regnum != -1) > - right_supply_register (regcache, wordsize, regcache_tdep->ppc_mq_regnum, > - buf + wordsize * PPC_LINUX_PT_MQ); > - right_supply_register (regcache, wordsize, regcache_tdep->ppc_ps_regnum, > - buf + wordsize * PPC_LINUX_PT_MSR); > -} Your new code makes no such distinction, they're all treated as right-aligned. I wonder whether this change was deliberate? It does appear the original code is actually wrong; the kernel stores CCR, XER, and CRT just the same as e.g. NIP and LNK, as far as I can see. Did you verify that those registers are now handled correctly in both 64x64 and 32x64 cases (native and core)? Also, you missed setting the gpr_size field in a couple of cases: rs6000-aix-tdep.c:rs6000_aix32_reg_offsets rs6000-aix-tdep.c:rs6000_aix64_reg_offsets ppcobsd-nat.c:ppcobsd_reg_offsets And, since you're now using gpr_size in the _fpregset routines as well, I guess ppcobsd_fpreg_offsets would need to set gpr_size too. However, I think it would be preferable to not use gpr_size in those routines in the first place; the size of this register is in fact always 4. Bye, Ulrich -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE Ulrich.Weigand@de.ibm.com ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: powerpc-linux biarch corefile support 2007-08-28 23:03 ` Ulrich Weigand @ 2007-08-29 7:26 ` Alan Modra 2007-08-29 8:28 ` Alan Modra 0 siblings, 1 reply; 12+ messages in thread From: Alan Modra @ 2007-08-29 7:26 UTC (permalink / raw) To: Ulrich Weigand; +Cc: gdb-patches On Wed, Aug 29, 2007 at 01:03:05AM +0200, Ulrich Weigand wrote: > In particular, the original code appears to treat CCR, XER, and CTR > as left-aligned, and the others as right-aligned: [snip] > > Your new code makes no such distinction, they're all treated as > right-aligned. > > I wonder whether this change was deliberate? It does appear the > original code is actually wrong; the kernel stores CCR, XER, and > CRT just the same as e.g. NIP and LNK, as far as I can see. I should have mentioned this change. It was deliberate. The old code was just plain wrong (and the reason why "info reg" on a 64-bit core file always showed zero for CR and XER). It was inconsistent too. CTR used right fill in ppc-linux-nat.c:fill_gregset but left fill in ppc-linux-tdep.c:ppc_linux_supply_gregset. I suspect that using left fill for CTR was just a copy and paste error, but the comment Andrew Cagney added seems to indicate he meant to use left-fill for CR and XER. Perhaps the ppc64 linux kernel stored them that way at some stage? I'll ask some kernel experts. > Did you verify that those registers are now handled correctly in > both 64x64 and 32x64 cases (native and core)? Yes. > Also, you missed setting the gpr_size field in a couple of cases: > rs6000-aix-tdep.c:rs6000_aix32_reg_offsets > rs6000-aix-tdep.c:rs6000_aix64_reg_offsets > ppcobsd-nat.c:ppcobsd_reg_offsets Oops, shame on me. I'll fix that. > And, since you're now using gpr_size in the _fpregset routines as > well, I guess ppcobsd_fpreg_offsets would need to set gpr_size too. > However, I think it would be preferable to not use gpr_size in > those routines in the first place; the size of this register is in > fact always 4. However, the fpscr field is 64 bits in struct ucontext on both powerpc64-linux and powerpc-linux, and the definition of PT_FPSCR points to the low 32 bits on powerpc-linux and the full 64-bit word on powerpc64-linux. Since the size passed to ppc_supply_reg and ppc_collect_reg is that of the field, I figured that it ought to be 8 bytes on powerpc64-linux. I could make the size 4 and adjust the offset in ppc64_linux_reg_offsets, but I had ideas of using ppc_greg_offset and ppc_fpreg_offset in place of ppc-linux-nat.c:ppc_register_u_addr, which provides an offset into ucontext. PTRACE_PEEKUSER and PTRACE_POKEUSER bomb on ppc64 if the offset isn't a multiple of 8... -- Alan Modra Australia Development Lab, IBM ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: powerpc-linux biarch corefile support 2007-08-29 7:26 ` Alan Modra @ 2007-08-29 8:28 ` Alan Modra [not found] ` <OFA57C40FB.23E13286-ON42257346.004A0E7C-42257346.004A56D1@de.ibm.com> 0 siblings, 1 reply; 12+ messages in thread From: Alan Modra @ 2007-08-29 8:28 UTC (permalink / raw) To: Ulrich Weigand; +Cc: gdb-patches On Wed, Aug 29, 2007 at 04:55:56PM +0930, Alan Modra wrote: > On Wed, Aug 29, 2007 at 01:03:05AM +0200, Ulrich Weigand wrote: > > Also, you missed setting the gpr_size field in a couple of cases: > > rs6000-aix-tdep.c:rs6000_aix32_reg_offsets > > rs6000-aix-tdep.c:rs6000_aix64_reg_offsets > > ppcobsd-nat.c:ppcobsd_reg_offsets > > Oops, shame on me. I'll fix that. On looking at rs6000_aix64_reg_offsets, I noticed that xer_offset is not a multiple of 8. Apparently, AIX uses a 32-bit field for cr, xer, and fpscr. So it looks like I can't use gpr_size for any of these registers in ppc_{supply,collect}_gregset. Mind you, aix 64-bit gdb is broken anyway due to these functions assuming the gprs were 32-bit. -- Alan Modra Australia Development Lab, IBM ^ permalink raw reply [flat|nested] 12+ messages in thread
[parent not found: <OFA57C40FB.23E13286-ON42257346.004A0E7C-42257346.004A56D1@de.ibm.com>]
* Re: powerpc-linux biarch corefile support [not found] ` <OFA57C40FB.23E13286-ON42257346.004A0E7C-42257346.004A56D1@de.ibm.com> @ 2007-08-30 12:14 ` Alan Modra 2007-08-30 12:50 ` Ulrich Weigand 0 siblings, 1 reply; 12+ messages in thread From: Alan Modra @ 2007-08-30 12:14 UTC (permalink / raw) To: Ulrich Weigand; +Cc: gdb-patches Differences from last patch: - All struct ppc_reg_offsets instances set new fields if they will be used. - Added xr_size and fpscr_size to struct ppc_reg_offsets, and used these sizes in rs6000-tdep.c collect and supply regset functions. - Adjusted ppc32_linux_reg_offsets.fpscr_offset to reflect actual field size in ucontext struct. - Reinstated clearing of gregset in ppc-linux-nat.c:fill_gregset, but only when regnum is -1. I double checked that the simpler "sizeof (*gregsetp)" is correct. - Created a wrapper for ppc_collect_gregset that clears similarly to fill_gregset. Without this, gcore writes rubbish in the unused areas. * ppc-linux-nat.c (right_fill_reg): Delete. (supply_gregset): Use ppc_supply_gregset. (supply_fpregset): Use ppc_supply_fpregset. (fill_gregset): Use ppc_collect_gregset. (fill_fpregset): Use ppc_collect_fpregset. * ppc-linux-tdep.c (PPC_LINUX_PT_*): Don't define. (right_supply_register, ppc_linux_supply_gregset): Delete. (ppc32_linux_supply_gregset, ppc64_linux_supply_gregset): Delete. (ppc_linux_supply_fpregset): Delete. (ppc_linux_collect_gregset): New function. (ppc32_linux_reg_offsets, ppc64_linux_reg_offsets): New. (ppc32_linux_gregset, ppc64_linux_gregset): Update to use reg offsets, ppc_linux_supply_gregset, and ppc_collect_gregset. (ppc_linux_fpregset): Rename to ppc32_linux_fpregset and update. (ppc_linux_gregset, ppc_linux_fpregset): New functions. (ppc_linux_regset_from_core_section): Update. * ppc-tdep.h (ppc_linux_gregset, ppc_linux_fpregset): Declare. (ppc_linux_supply_gregset, ppc_linux_supply_fpregset): Delete. (struct ppc_reg_offsets): Add gpr_size, xr_size, fpscr_size fields. * ppcobsd-tdep.c (ppcobsd_supply_gregset): Delete FIXME and assert. (ppcobsd_collect_gregset): Likewise. (_initialize_ppcnbsd_tdep): Init gpr_size, xr_size, fpscr_size. * ppcnbsd-tdep.c (_initialize_ppcobsd_tdep): Likewise. * ppcobsd-nat.c (_initialize_ppcobsd_nat): Init fpscr_size. * rs6000-aix-tdep.c (rs6000_aix32_reg_offsets): Init new fields. (rs6000_aix64_reg_offsets): Likewise. (rs6000_aix_supply_regset): Call ppc_supply_fpregset without testing ppc_floating_point_unit_p. (rs6000_aix_collect_regset): Similarly. * rs6000-tdep.c (ppc_supply_reg): Add regsize param. Adjust offset when regsize is larger than regcache register size. (ppc_collect_reg): Similarly zero pad when regsize is larger than regcache register size. (ppc_greg_offset): New function, split out from.. (ppc_supply_gregset): ..here. Separate code handling all regs from single reg case. Correct xer offset. (ppc_fpreg_offset): New function, split out from.. (ppc_supply_fpregset): ..here. Separate code handling all regs from single reg case. (ppc_collect_gregset, ppc_collect_fpregset): Likewise. (ppc_supply_fpregset, ppc_collect_fpregset): Don't assert we have a fp unit, instead return if no fp. Index: gdb/ppc-linux-nat.c =================================================================== RCS file: /cvs/src/src/gdb/ppc-linux-nat.c,v retrieving revision 1.69 diff -u -p -r1.69 ppc-linux-nat.c --- gdb/ppc-linux-nat.c 23 Aug 2007 18:08:36 -0000 1.69 +++ gdb/ppc-linux-nat.c 30 Aug 2007 02:15:02 -0000 @@ -901,101 +901,48 @@ ppc_linux_store_inferior_registers (stru store_ppc_registers (regcache, tid); } +/* Functions for transferring registers between a gregset_t or fpregset_t + (see sys/ucontext.h) and gdb's regcache. The word size is that used + by the ptrace interface, not the current program's ABI. eg. If a + powerpc64-linux gdb is being used to debug a powerpc32-linux app, we + read or write 64-bit gregsets. This is to suit the host libthread_db. */ + void supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp) { - /* NOTE: cagney/2003-11-25: This is the word size used by the ptrace - interface, and not the wordsize of the program's ABI. */ - int wordsize = sizeof (long); - ppc_linux_supply_gregset (regcache, -1, gregsetp, - sizeof (gdb_gregset_t), wordsize); -} + const struct regset *regset = ppc_linux_gregset (sizeof (long)); -static void -right_fill_reg (const struct regcache *regcache, int regnum, void *reg) -{ - /* NOTE: cagney/2003-11-25: This is the word size used by the ptrace - interface, and not the wordsize of the program's ABI. */ - int wordsize = sizeof (long); - /* Right fill the register. */ - regcache_raw_collect (regcache, regnum, - ((bfd_byte *) reg - + wordsize - - register_size (current_gdbarch, regnum))); + ppc_supply_gregset (regset, regcache, -1, gregsetp, sizeof (*gregsetp)); } void fill_gregset (const struct regcache *regcache, gdb_gregset_t *gregsetp, int regno) { - int regi; - elf_greg_t *regp = (elf_greg_t *) gregsetp; - struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); - const int elf_ngreg = 48; - - - /* Start with zeros. */ - memset (regp, 0, elf_ngreg * sizeof (*regp)); - - for (regi = 0; regi < ppc_num_gprs; regi++) - { - if ((regno == -1) || regno == tdep->ppc_gp0_regnum + regi) - right_fill_reg (regcache, tdep->ppc_gp0_regnum + regi, - (regp + PT_R0 + regi)); - } - - if ((regno == -1) || regno == gdbarch_pc_regnum (current_gdbarch)) - right_fill_reg (regcache, gdbarch_pc_regnum (current_gdbarch), - regp + PT_NIP); - if ((regno == -1) || regno == tdep->ppc_lr_regnum) - right_fill_reg (regcache, tdep->ppc_lr_regnum, regp + PT_LNK); - if ((regno == -1) || regno == tdep->ppc_cr_regnum) - regcache_raw_collect (regcache, tdep->ppc_cr_regnum, - regp + PT_CCR); - if ((regno == -1) || regno == tdep->ppc_xer_regnum) - regcache_raw_collect (regcache, tdep->ppc_xer_regnum, - regp + PT_XER); - if ((regno == -1) || regno == tdep->ppc_ctr_regnum) - right_fill_reg (regcache, tdep->ppc_ctr_regnum, regp + PT_CTR); -#ifdef PT_MQ - if (((regno == -1) || regno == tdep->ppc_mq_regnum) - && (tdep->ppc_mq_regnum != -1)) - right_fill_reg (regcache, tdep->ppc_mq_regnum, regp + PT_MQ); -#endif - if ((regno == -1) || regno == tdep->ppc_ps_regnum) - right_fill_reg (regcache, tdep->ppc_ps_regnum, regp + PT_MSR); + const struct regset *regset = ppc_linux_gregset (sizeof (long)); + + if (regno == -1) + memset (gregsetp, 0, sizeof (*gregsetp)); + ppc_collect_gregset (regset, regcache, regno, gregsetp, sizeof (*gregsetp)); } void supply_fpregset (struct regcache *regcache, const gdb_fpregset_t * fpregsetp) { - ppc_linux_supply_fpregset (NULL, regcache, -1, fpregsetp, - sizeof (gdb_fpregset_t)); + const struct regset *regset = ppc_linux_fpregset (); + + ppc_supply_fpregset (regset, regcache, -1, + fpregsetp, sizeof (*fpregsetp)); } -/* Given a pointer to a floating point register set in /proc format - (fpregset_t *), update the register specified by REGNO from gdb's - idea of the current floating point register set. If REGNO is -1, - update them all. */ void fill_fpregset (const struct regcache *regcache, gdb_fpregset_t *fpregsetp, int regno) { - int regi; - struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); - bfd_byte *fpp = (void *) fpregsetp; - - if (ppc_floating_point_unit_p (current_gdbarch)) - { - for (regi = 0; regi < ppc_num_fprs; regi++) - { - if ((regno == -1) || (regno == tdep->ppc_fp0_regnum + regi)) - regcache_raw_collect (regcache, tdep->ppc_fp0_regnum + regi, - fpp + 8 * regi); - } - if (regno == -1 || regno == tdep->ppc_fpscr_regnum) - right_fill_reg (regcache, tdep->ppc_fpscr_regnum, (fpp + 8 * 32)); - } + const struct regset *regset = ppc_linux_fpregset (); + + ppc_collect_fpregset (regset, regcache, regno, + fpregsetp, sizeof (*fpregsetp)); } void _initialize_ppc_linux_nat (void); Index: gdb/ppc-linux-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/ppc-linux-tdep.c,v retrieving revision 1.87 diff -u -p -r1.87 ppc-linux-tdep.c --- gdb/ppc-linux-tdep.c 23 Aug 2007 18:08:36 -0000 1.87 +++ gdb/ppc-linux-tdep.c 30 Aug 2007 02:15:02 -0000 @@ -38,51 +38,6 @@ #include "frame-unwind.h" #include "tramp-frame.h" -/* From <asm/ptrace.h>, values for PT_NIP, PT_R1, and PT_LNK */ -#define PPC_LINUX_PT_R0 0 -#define PPC_LINUX_PT_R1 1 -#define PPC_LINUX_PT_R2 2 -#define PPC_LINUX_PT_R3 3 -#define PPC_LINUX_PT_R4 4 -#define PPC_LINUX_PT_R5 5 -#define PPC_LINUX_PT_R6 6 -#define PPC_LINUX_PT_R7 7 -#define PPC_LINUX_PT_R8 8 -#define PPC_LINUX_PT_R9 9 -#define PPC_LINUX_PT_R10 10 -#define PPC_LINUX_PT_R11 11 -#define PPC_LINUX_PT_R12 12 -#define PPC_LINUX_PT_R13 13 -#define PPC_LINUX_PT_R14 14 -#define PPC_LINUX_PT_R15 15 -#define PPC_LINUX_PT_R16 16 -#define PPC_LINUX_PT_R17 17 -#define PPC_LINUX_PT_R18 18 -#define PPC_LINUX_PT_R19 19 -#define PPC_LINUX_PT_R20 20 -#define PPC_LINUX_PT_R21 21 -#define PPC_LINUX_PT_R22 22 -#define PPC_LINUX_PT_R23 23 -#define PPC_LINUX_PT_R24 24 -#define PPC_LINUX_PT_R25 25 -#define PPC_LINUX_PT_R26 26 -#define PPC_LINUX_PT_R27 27 -#define PPC_LINUX_PT_R28 28 -#define PPC_LINUX_PT_R29 29 -#define PPC_LINUX_PT_R30 30 -#define PPC_LINUX_PT_R31 31 -#define PPC_LINUX_PT_NIP 32 -#define PPC_LINUX_PT_MSR 33 -#define PPC_LINUX_PT_CTR 35 -#define PPC_LINUX_PT_LNK 36 -#define PPC_LINUX_PT_XER 37 -#define PPC_LINUX_PT_CCR 38 -#define PPC_LINUX_PT_MQ 39 -#define PPC_LINUX_PT_FPR0 48 /* each FP reg occupies 2 slots in this space */ -#define PPC_LINUX_PT_FPR31 (PPC_LINUX_PT_FPR0 + 2*31) -#define PPC_LINUX_PT_FPSCR (PPC_LINUX_PT_FPR0 + 2*32 + 1) - - static CORE_ADDR ppc_linux_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc) { @@ -660,99 +615,102 @@ ppc_linux_convert_from_func_ptr_addr (st return addr; } +/* This wrapper clears areas in the linux gregset not written by + ppc_collect_gregset. */ + static void -right_supply_register (struct regcache *regcache, int wordsize, int regnum, - const bfd_byte *buf) +ppc_linux_collect_gregset (const struct regset *regset, + const struct regcache *regcache, + int regnum, void *gregs, size_t len) { - regcache_raw_supply (regcache, regnum, - (buf + wordsize - register_size (current_gdbarch, regnum))); + if (regnum == -1) + memset (gregs, 0, len); + ppc_collect_gregset (regset, regcache, regnum, gregs, len); } -/* Extract the register values found in the WORDSIZED ABI GREGSET, - storing their values in REGCACHE. Note that some are left-aligned, - while others are right aligned. */ - -void -ppc_linux_supply_gregset (struct regcache *regcache, - int regnum, const void *gregs, size_t size, - int wordsize) -{ - int regi; - struct gdbarch *regcache_arch = get_regcache_arch (regcache); - struct gdbarch_tdep *regcache_tdep = gdbarch_tdep (regcache_arch); - const bfd_byte *buf = gregs; - - for (regi = 0; regi < ppc_num_gprs; regi++) - right_supply_register (regcache, wordsize, - regcache_tdep->ppc_gp0_regnum + regi, - buf + wordsize * regi); - - right_supply_register (regcache, wordsize, gdbarch_pc_regnum (regcache_arch), - buf + wordsize * PPC_LINUX_PT_NIP); - right_supply_register (regcache, wordsize, regcache_tdep->ppc_lr_regnum, - buf + wordsize * PPC_LINUX_PT_LNK); - regcache_raw_supply (regcache, regcache_tdep->ppc_cr_regnum, - buf + wordsize * PPC_LINUX_PT_CCR); - regcache_raw_supply (regcache, regcache_tdep->ppc_xer_regnum, - buf + wordsize * PPC_LINUX_PT_XER); - regcache_raw_supply (regcache, regcache_tdep->ppc_ctr_regnum, - buf + wordsize * PPC_LINUX_PT_CTR); - if (regcache_tdep->ppc_mq_regnum != -1) - right_supply_register (regcache, wordsize, regcache_tdep->ppc_mq_regnum, - buf + wordsize * PPC_LINUX_PT_MQ); - right_supply_register (regcache, wordsize, regcache_tdep->ppc_ps_regnum, - buf + wordsize * PPC_LINUX_PT_MSR); -} +/* Regset descriptions. */ +static const struct ppc_reg_offsets ppc32_linux_reg_offsets = + { + /* General-purpose registers. */ + /* .r0_offset = */ 0, + /* .gpr_size = */ 4, + /* .xr_size = */ 4, + /* .pc_offset = */ 128, + /* .ps_offset = */ 132, + /* .cr_offset = */ 152, + /* .lr_offset = */ 144, + /* .ctr_offset = */ 140, + /* .xer_offset = */ 148, + /* .mq_offset = */ 156, + + /* Floating-point registers. */ + /* .f0_offset = */ 0, + /* .fpscr_offset = */ 256, + /* .fpscr_size = */ 8, + + /* AltiVec registers. */ + /* .vr0_offset = */ 0, + /* .vrsave_offset = */ 512, + /* .vscr_offset = */ 512 + 12 + }; -static void -ppc32_linux_supply_gregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *gregs, size_t size) -{ - ppc_linux_supply_gregset (regcache, regnum, gregs, size, 4); -} +static const struct ppc_reg_offsets ppc64_linux_reg_offsets = + { + /* General-purpose registers. */ + /* .r0_offset = */ 0, + /* .gpr_size = */ 8, + /* .xr_size = */ 8, + /* .pc_offset = */ 256, + /* .ps_offset = */ 264, + /* .cr_offset = */ 304, + /* .lr_offset = */ 288, + /* .ctr_offset = */ 280, + /* .xer_offset = */ 296, + /* .mq_offset = */ 312, + + /* Floating-point registers. */ + /* .f0_offset = */ 0, + /* .fpscr_offset = */ 256, + /* .fpscr_size = */ 8, + + /* AltiVec registers. */ + /* .vr0_offset = */ 0, + /* .vrsave_offset = */ 528, + /* .vscr_offset = */ 512 + 12 + }; static struct regset ppc32_linux_gregset = { - NULL, ppc32_linux_supply_gregset + &ppc32_linux_reg_offsets, + ppc_supply_gregset, + ppc_linux_collect_gregset, + NULL }; -static void -ppc64_linux_supply_gregset (const struct regset *regset, - struct regcache * regcache, - int regnum, const void *gregs, size_t size) -{ - ppc_linux_supply_gregset (regcache, regnum, gregs, size, 8); -} - static struct regset ppc64_linux_gregset = { - NULL, ppc64_linux_supply_gregset + &ppc64_linux_reg_offsets, + ppc_supply_gregset, + ppc_linux_collect_gregset, + NULL }; -void -ppc_linux_supply_fpregset (const struct regset *regset, - struct regcache * regcache, - int regnum, const void *fpset, size_t size) -{ - int regi; - struct gdbarch *regcache_arch = get_regcache_arch (regcache); - struct gdbarch_tdep *regcache_tdep = gdbarch_tdep (regcache_arch); - const bfd_byte *buf = fpset; - - if (! ppc_floating_point_unit_p (regcache_arch)) - return; - - for (regi = 0; regi < ppc_num_fprs; regi++) - regcache_raw_supply (regcache, - regcache_tdep->ppc_fp0_regnum + regi, - buf + 8 * regi); - - /* The FPSCR is stored in the low order word of the last - doubleword in the fpregset. */ - regcache_raw_supply (regcache, regcache_tdep->ppc_fpscr_regnum, - buf + 8 * 32 + 4); +static struct regset ppc32_linux_fpregset = { + &ppc32_linux_reg_offsets, + ppc_supply_fpregset, + ppc_collect_fpregset, + NULL +}; + +const struct regset * +ppc_linux_gregset (int wordsize) +{ + return wordsize == 8 ? &ppc64_linux_gregset : &ppc32_linux_gregset; } -static struct regset ppc_linux_fpregset = { NULL, ppc_linux_supply_fpregset }; +const struct regset * +ppc_linux_fpregset (void) +{ + return &ppc32_linux_fpregset; +} static const struct regset * ppc_linux_regset_from_core_section (struct gdbarch *core_arch, @@ -767,7 +725,7 @@ ppc_linux_regset_from_core_section (stru return &ppc64_linux_gregset; } if (strcmp (sect_name, ".reg2") == 0) - return &ppc_linux_fpregset; + return &ppc32_linux_fpregset; return NULL; } Index: gdb/ppc-tdep.h =================================================================== RCS file: /cvs/src/src/gdb/ppc-tdep.h,v retrieving revision 1.55 diff -u -p -r1.55 ppc-tdep.h --- gdb/ppc-tdep.h 23 Aug 2007 18:08:36 -0000 1.55 +++ gdb/ppc-tdep.h 30 Aug 2007 02:15:03 -0000 @@ -56,12 +56,8 @@ CORE_ADDR ppc64_sysv_abi_adjust_breakpoi CORE_ADDR bpaddr); int ppc_linux_memory_remove_breakpoint (struct bp_target_info *bp_tgt); struct link_map_offsets *ppc_linux_svr4_fetch_link_map_offsets (void); -void ppc_linux_supply_gregset (struct regcache *regcache, - int regnum, const void *gregs, size_t size, - int wordsize); -void ppc_linux_supply_fpregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *gregs, size_t size); +const struct regset *ppc_linux_gregset (int); +const struct regset *ppc_linux_fpregset (void); enum return_value_convention ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *valtype, @@ -83,6 +79,8 @@ struct ppc_reg_offsets { /* General-purpose registers. */ int r0_offset; + int gpr_size; /* size for r0-31, pc, ps, lr, ctr. */ + int xr_size; /* size for cr, xer, mq. */ int pc_offset; int ps_offset; int cr_offset; @@ -94,6 +92,7 @@ struct ppc_reg_offsets /* Floating-point registers. */ int f0_offset; int fpscr_offset; + int fpscr_size; /* AltiVec registers. */ int vr0_offset; Index: gdb/ppcobsd-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/ppcobsd-tdep.c,v retrieving revision 1.17 diff -u -p -r1.17 ppcobsd-tdep.c --- gdb/ppcobsd-tdep.c 23 Aug 2007 18:08:36 -0000 1.17 +++ gdb/ppcobsd-tdep.c 30 Aug 2007 02:15:03 -0000 @@ -51,18 +51,6 @@ ppcobsd_supply_gregset (const struct reg struct regcache *regcache, int regnum, const void *gregs, size_t len) { - /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating - point registers. Traditionally, GDB's register set has still - listed the floating point registers for such machines, so this - code is harmless. However, the new E500 port actually omits the - floating point registers entirely from the register set --- they - don't even have register numbers assigned to them. - - It's not clear to me how best to update this code, so this assert - will alert the first person to encounter the OpenBSD/E500 - combination to the problem. */ - gdb_assert (ppc_floating_point_unit_p (current_gdbarch)); - ppc_supply_gregset (regset, regcache, regnum, gregs, len); ppc_supply_fpregset (regset, regcache, regnum, gregs, len); } @@ -77,18 +65,6 @@ ppcobsd_collect_gregset (const struct re const struct regcache *regcache, int regnum, void *gregs, size_t len) { - /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating - point registers. Traditionally, GDB's register set has still - listed the floating point registers for such machines, so this - code is harmless. However, the new E500 port actually omits the - floating point registers entirely from the register set --- they - don't even have register numbers assigned to them. - - It's not clear to me how best to update this code, so this assert - will alert the first person to encounter the OpenBSD/E500 - combination to the problem. */ - gdb_assert (ppc_floating_point_unit_p (current_gdbarch)); - ppc_collect_gregset (regset, regcache, regnum, gregs, len); ppc_collect_fpregset (regset, regcache, regnum, gregs, len); } @@ -331,6 +307,8 @@ _initialize_ppcobsd_tdep (void) { /* General-purpose registers. */ ppcobsd_reg_offsets.r0_offset = 0; + ppcobsd_reg_offsets.gpr_size = 4; + ppcobsd_reg_offsets.xr_size = 4; ppcobsd_reg_offsets.pc_offset = 384; ppcobsd_reg_offsets.ps_offset = 388; ppcobsd_reg_offsets.cr_offset = 392; @@ -354,5 +332,6 @@ _initialize_ppcobsd_tdep (void) /* Floating-point registers. */ ppcobsd_reg_offsets.f0_offset = 0; ppcobsd_reg_offsets.fpscr_offset = 256; + ppcobsd_reg_offsets.fpscr_size = 4; } } Index: gdb/ppcnbsd-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/ppcnbsd-tdep.c,v retrieving revision 1.33 diff -u -p -r1.33 ppcnbsd-tdep.c --- gdb/ppcnbsd-tdep.c 23 Aug 2007 18:08:36 -0000 1.33 +++ gdb/ppcnbsd-tdep.c 30 Aug 2007 02:15:03 -0000 @@ -213,6 +213,8 @@ _initialize_ppcnbsd_tdep (void) { /* General-purpose registers. */ ppcnbsd_reg_offsets.r0_offset = 0; + ppcnbsd_reg_offsets.gpr_size = 4; + ppcnbsd_reg_offsets.xr_size = 4; ppcnbsd_reg_offsets.lr_offset = 128; ppcnbsd_reg_offsets.cr_offset = 132; ppcnbsd_reg_offsets.xer_offset = 136; @@ -224,6 +226,7 @@ _initialize_ppcnbsd_tdep (void) /* Floating-point registers. */ ppcnbsd_reg_offsets.f0_offset = 0; ppcnbsd_reg_offsets.fpscr_offset = 256; + ppcnbsd_reg_offsets.fpscr_size = 4; /* AltiVec registers. */ ppcnbsd_reg_offsets.vr0_offset = 0; Index: gdb/ppcobsd-nat.c =================================================================== RCS file: /cvs/src/src/gdb/ppcobsd-nat.c,v retrieving revision 1.12 diff -u -p -r1.12 ppcobsd-nat.c --- gdb/ppcobsd-nat.c 23 Aug 2007 18:08:36 -0000 1.12 +++ gdb/ppcobsd-nat.c 30 Aug 2007 02:15:03 -0000 @@ -212,6 +212,7 @@ _initialize_ppcobsd_nat (void) #ifdef PT_GETFPREGS ppcobsd_fpreg_offsets.f0_offset = offsetof (struct fpreg, fpr); ppcobsd_fpreg_offsets.fpscr_offset = offsetof (struct fpreg, fpscr); + ppcobsd_fpreg_offsets.fpscr_size = 4; #endif /* AltiVec registers. */ Index: gdb/rs6000-aix-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/rs6000-aix-tdep.c,v retrieving revision 1.5 diff -u -p -r1.5 rs6000-aix-tdep.c --- gdb/rs6000-aix-tdep.c 23 Aug 2007 18:08:37 -0000 1.5 +++ gdb/rs6000-aix-tdep.c 30 Aug 2007 02:15:06 -0000 @@ -34,6 +34,8 @@ static struct ppc_reg_offsets rs6000_aix { /* General-purpose registers. */ 208, /* r0_offset */ + 4, /* gpr_size */ + 4, /* xr_size */ 24, /* pc_offset */ 28, /* ps_offset */ 32, /* cr_offset */ @@ -45,6 +47,7 @@ static struct ppc_reg_offsets rs6000_aix /* Floating-point registers. */ 336, /* f0_offset */ 56, /* fpscr_offset */ + 4, /* fpscr_size */ /* AltiVec registers. */ -1, /* vr0_offset */ @@ -56,6 +59,8 @@ static struct ppc_reg_offsets rs6000_aix { /* General-purpose registers. */ 0, /* r0_offset */ + 8, /* gpr_size */ + 4, /* xr_size */ 264, /* pc_offset */ 256, /* ps_offset */ 288, /* cr_offset */ @@ -67,6 +72,7 @@ static struct ppc_reg_offsets rs6000_aix /* Floating-point registers. */ 312, /* f0_offset */ 296, /* fpscr_offset */ + 4, /* fpscr_size */ /* AltiVec registers. */ -1, /* vr0_offset */ @@ -85,9 +91,7 @@ rs6000_aix_supply_regset (const struct r const void *gregs, size_t len) { ppc_supply_gregset (regset, regcache, regnum, gregs, len); - - if (ppc_floating_point_unit_p (get_regcache_arch (regcache))) - ppc_supply_fpregset (regset, regcache, regnum, gregs, len); + ppc_supply_fpregset (regset, regcache, regnum, gregs, len); } /* Collect register REGNUM in the general-purpose register set @@ -101,9 +105,7 @@ rs6000_aix_collect_regset (const struct void *gregs, size_t len) { ppc_collect_gregset (regset, regcache, regnum, gregs, len); - - if (ppc_floating_point_unit_p (get_regcache_arch (regcache))) - ppc_collect_fpregset (regset, regcache, regnum, gregs, len); + ppc_collect_fpregset (regset, regcache, regnum, gregs, len); } /* AIX register set. */ Index: gdb/rs6000-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v retrieving revision 1.287 diff -u -p -r1.287 rs6000-tdep.c --- gdb/rs6000-tdep.c 23 Aug 2007 18:08:37 -0000 1.287 +++ gdb/rs6000-tdep.c 30 Aug 2007 02:15:06 -0000 @@ -302,22 +302,109 @@ rs6000_register_sim_regno (int reg) /* Register set support functions. */ +/* REGS + OFFSET contains register REGNUM in a field REGSIZE wide. + Write the register to REGCACHE. */ + static void ppc_supply_reg (struct regcache *regcache, int regnum, - const gdb_byte *regs, size_t offset) + const gdb_byte *regs, size_t offset, int regsize) { if (regnum != -1 && offset != -1) - regcache_raw_supply (regcache, regnum, regs + offset); + { + if (regsize > 4) + { + struct gdbarch *gdbarch = get_regcache_arch (regcache); + int gdb_regsize = register_size (gdbarch, regnum); + if (gdb_regsize < regsize + && gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + offset += regsize - gdb_regsize; + } + regcache_raw_supply (regcache, regnum, regs + offset); + } } +/* Read register REGNUM from REGCACHE and store to REGS + OFFSET + in a field REGSIZE wide. Zero pad as necessary. */ + static void ppc_collect_reg (const struct regcache *regcache, int regnum, - gdb_byte *regs, size_t offset) + gdb_byte *regs, size_t offset, int regsize) { if (regnum != -1 && offset != -1) - regcache_raw_collect (regcache, regnum, regs + offset); + { + if (regsize > 4) + { + struct gdbarch *gdbarch = get_regcache_arch (regcache); + int gdb_regsize = register_size (gdbarch, regnum); + if (gdb_regsize < regsize) + { + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + { + memset (regs + offset, 0, regsize - gdb_regsize); + offset += regsize - gdb_regsize; + } + else + memset (regs + offset + regsize - gdb_regsize, 0, + regsize - gdb_regsize); + } + } + regcache_raw_collect (regcache, regnum, regs + offset); + } } +static int +ppc_greg_offset (struct gdbarch *gdbarch, + struct gdbarch_tdep *tdep, + const struct ppc_reg_offsets *offsets, + int regnum, + int *regsize) +{ + *regsize = offsets->gpr_size; + if (regnum >= tdep->ppc_gp0_regnum + && regnum < tdep->ppc_gp0_regnum + ppc_num_gprs) + return (offsets->r0_offset + + (regnum - tdep->ppc_gp0_regnum) * offsets->gpr_size); + + if (regnum == gdbarch_pc_regnum (gdbarch)) + return offsets->pc_offset; + + if (regnum == tdep->ppc_ps_regnum) + return offsets->ps_offset; + + if (regnum == tdep->ppc_lr_regnum) + return offsets->lr_offset; + + if (regnum == tdep->ppc_ctr_regnum) + return offsets->ctr_offset; + + *regsize = offsets->xr_size; + if (regnum == tdep->ppc_cr_regnum) + return offsets->cr_offset; + + if (regnum == tdep->ppc_xer_regnum) + return offsets->xer_offset; + + if (regnum == tdep->ppc_mq_regnum) + return offsets->mq_offset; + + return -1; +} + +static int +ppc_fpreg_offset (struct gdbarch_tdep *tdep, + const struct ppc_reg_offsets *offsets, + int regnum) +{ + if (regnum >= tdep->ppc_fp0_regnum + && regnum < tdep->ppc_fp0_regnum + ppc_num_fprs) + return offsets->f0_offset + (regnum - tdep->ppc_fp0_regnum) * 8; + + if (regnum == tdep->ppc_fpscr_regnum) + return offsets->fpscr_offset; + + return -1; +} + /* Supply register REGNUM in the general-purpose register set REGSET from the buffer specified by GREGS and LEN to register cache REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ @@ -330,36 +417,37 @@ ppc_supply_gregset (const struct regset struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); const struct ppc_reg_offsets *offsets = regset->descr; size_t offset; - int i; + int regsize; + + if (regnum == -1) + { + int i; + int gpr_size = offsets->gpr_size; + + for (i = tdep->ppc_gp0_regnum, offset = offsets->r0_offset; + i < tdep->ppc_gp0_regnum + ppc_num_gprs; + i++, offset += gpr_size) + ppc_supply_reg (regcache, i, gregs, offset, gpr_size); + + ppc_supply_reg (regcache, gdbarch_pc_regnum (gdbarch), + gregs, offsets->pc_offset, gpr_size); + ppc_supply_reg (regcache, tdep->ppc_ps_regnum, + gregs, offsets->ps_offset, gpr_size); + ppc_supply_reg (regcache, tdep->ppc_lr_regnum, + gregs, offsets->lr_offset, gpr_size); + ppc_supply_reg (regcache, tdep->ppc_ctr_regnum, + gregs, offsets->ctr_offset, gpr_size); + ppc_supply_reg (regcache, tdep->ppc_cr_regnum, + gregs, offsets->cr_offset, offsets->xr_size); + ppc_supply_reg (regcache, tdep->ppc_xer_regnum, + gregs, offsets->xer_offset, offsets->xr_size); + ppc_supply_reg (regcache, tdep->ppc_mq_regnum, + gregs, offsets->mq_offset, offsets->xr_size); + return; + } - for (i = tdep->ppc_gp0_regnum, offset = offsets->r0_offset; - i < tdep->ppc_gp0_regnum + ppc_num_gprs; - i++, offset += 4) - { - if (regnum == -1 || regnum == i) - ppc_supply_reg (regcache, i, gregs, offset); - } - - if (regnum == -1 || regnum == gdbarch_pc_regnum (current_gdbarch)) - ppc_supply_reg (regcache, gdbarch_pc_regnum (current_gdbarch), - gregs, offsets->pc_offset); - if (regnum == -1 || regnum == tdep->ppc_ps_regnum) - ppc_supply_reg (regcache, tdep->ppc_ps_regnum, - gregs, offsets->ps_offset); - if (regnum == -1 || regnum == tdep->ppc_cr_regnum) - ppc_supply_reg (regcache, tdep->ppc_cr_regnum, - gregs, offsets->cr_offset); - if (regnum == -1 || regnum == tdep->ppc_lr_regnum) - ppc_supply_reg (regcache, tdep->ppc_lr_regnum, - gregs, offsets->lr_offset); - if (regnum == -1 || regnum == tdep->ppc_ctr_regnum) - ppc_supply_reg (regcache, tdep->ppc_ctr_regnum, - gregs, offsets->ctr_offset); - if (regnum == -1 || regnum == tdep->ppc_xer_regnum) - ppc_supply_reg (regcache, tdep->ppc_xer_regnum, - gregs, offsets->cr_offset); - if (regnum == -1 || regnum == tdep->ppc_mq_regnum) - ppc_supply_reg (regcache, tdep->ppc_mq_regnum, gregs, offsets->mq_offset); + offset = ppc_greg_offset (gdbarch, tdep, offsets, regnum, ®size); + ppc_supply_reg (regcache, regnum, gregs, offset, regsize); } /* Supply register REGNUM in the floating-point register set REGSET @@ -371,29 +459,36 @@ ppc_supply_fpregset (const struct regset int regnum, const void *fpregs, size_t len) { struct gdbarch *gdbarch = get_regcache_arch (regcache); - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - const struct ppc_reg_offsets *offsets = regset->descr; + struct gdbarch_tdep *tdep; + const struct ppc_reg_offsets *offsets; size_t offset; - int i; - gdb_assert (ppc_floating_point_unit_p (gdbarch)); + if (!ppc_floating_point_unit_p (gdbarch)) + return; - offset = offsets->f0_offset; - for (i = tdep->ppc_fp0_regnum; - i < tdep->ppc_fp0_regnum + ppc_num_fprs; - i++, offset += 8) + tdep = gdbarch_tdep (gdbarch); + offsets = regset->descr; + if (regnum == -1) { - if (regnum == -1 || regnum == i) - ppc_supply_reg (regcache, i, fpregs, offset); + int i; + + for (i = tdep->ppc_fp0_regnum, offset = offsets->f0_offset; + i < tdep->ppc_fp0_regnum + ppc_num_fprs; + i++, offset += 8) + ppc_supply_reg (regcache, i, fpregs, offset, 8); + + ppc_supply_reg (regcache, tdep->ppc_fpscr_regnum, + fpregs, offsets->fpscr_offset, offsets->fpscr_size); + return; } - if (regnum == -1 || regnum == tdep->ppc_fpscr_regnum) - ppc_supply_reg (regcache, tdep->ppc_fpscr_regnum, - fpregs, offsets->fpscr_offset); + offset = ppc_fpreg_offset (tdep, offsets, regnum); + ppc_supply_reg (regcache, regnum, fpregs, offset, + regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8); } /* Collect register REGNUM in the general-purpose register set - REGSET. from register cache REGCACHE into the buffer specified by + REGSET from register cache REGCACHE into the buffer specified by GREGS and LEN. If REGNUM is -1, do this for all registers in REGSET. */ @@ -406,42 +501,41 @@ ppc_collect_gregset (const struct regset struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); const struct ppc_reg_offsets *offsets = regset->descr; size_t offset; - int i; + int regsize; + + if (regnum == -1) + { + int i; + int gpr_size = offsets->gpr_size; + + for (i = tdep->ppc_gp0_regnum, offset = offsets->r0_offset; + i < tdep->ppc_gp0_regnum + ppc_num_gprs; + i++, offset += gpr_size) + ppc_collect_reg (regcache, i, gregs, offset, gpr_size); + + ppc_collect_reg (regcache, gdbarch_pc_regnum (gdbarch), + gregs, offsets->pc_offset, gpr_size); + ppc_collect_reg (regcache, tdep->ppc_ps_regnum, + gregs, offsets->ps_offset, gpr_size); + ppc_collect_reg (regcache, tdep->ppc_lr_regnum, + gregs, offsets->lr_offset, gpr_size); + ppc_collect_reg (regcache, tdep->ppc_ctr_regnum, + gregs, offsets->ctr_offset, gpr_size); + ppc_collect_reg (regcache, tdep->ppc_cr_regnum, + gregs, offsets->cr_offset, offsets->xr_size); + ppc_collect_reg (regcache, tdep->ppc_xer_regnum, + gregs, offsets->xer_offset, offsets->xr_size); + ppc_collect_reg (regcache, tdep->ppc_mq_regnum, + gregs, offsets->mq_offset, offsets->xr_size); + return; + } - offset = offsets->r0_offset; - for (i = tdep->ppc_gp0_regnum; - i < tdep->ppc_gp0_regnum + ppc_num_gprs; - i++, offset += 4) - { - if (regnum == -1 || regnum == i) - ppc_collect_reg (regcache, i, gregs, offset); - } - - if (regnum == -1 || regnum == gdbarch_pc_regnum (current_gdbarch)) - ppc_collect_reg (regcache, gdbarch_pc_regnum (current_gdbarch), - gregs, offsets->pc_offset); - if (regnum == -1 || regnum == tdep->ppc_ps_regnum) - ppc_collect_reg (regcache, tdep->ppc_ps_regnum, - gregs, offsets->ps_offset); - if (regnum == -1 || regnum == tdep->ppc_cr_regnum) - ppc_collect_reg (regcache, tdep->ppc_cr_regnum, - gregs, offsets->cr_offset); - if (regnum == -1 || regnum == tdep->ppc_lr_regnum) - ppc_collect_reg (regcache, tdep->ppc_lr_regnum, - gregs, offsets->lr_offset); - if (regnum == -1 || regnum == tdep->ppc_ctr_regnum) - ppc_collect_reg (regcache, tdep->ppc_ctr_regnum, - gregs, offsets->ctr_offset); - if (regnum == -1 || regnum == tdep->ppc_xer_regnum) - ppc_collect_reg (regcache, tdep->ppc_xer_regnum, - gregs, offsets->xer_offset); - if (regnum == -1 || regnum == tdep->ppc_mq_regnum) - ppc_collect_reg (regcache, tdep->ppc_mq_regnum, - gregs, offsets->mq_offset); + offset = ppc_greg_offset (gdbarch, tdep, offsets, regnum, ®size); + ppc_collect_reg (regcache, regnum, gregs, offset, regsize); } /* Collect register REGNUM in the floating-point register set - REGSET. from register cache REGCACHE into the buffer specified by + REGSET from register cache REGCACHE into the buffer specified by FPREGS and LEN. If REGNUM is -1, do this for all registers in REGSET. */ @@ -451,25 +545,32 @@ ppc_collect_fpregset (const struct regse int regnum, void *fpregs, size_t len) { struct gdbarch *gdbarch = get_regcache_arch (regcache); - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - const struct ppc_reg_offsets *offsets = regset->descr; + struct gdbarch_tdep *tdep; + const struct ppc_reg_offsets *offsets; size_t offset; - int i; - gdb_assert (ppc_floating_point_unit_p (gdbarch)); + if (!ppc_floating_point_unit_p (gdbarch)) + return; - offset = offsets->f0_offset; - for (i = tdep->ppc_fp0_regnum; - i <= tdep->ppc_fp0_regnum + ppc_num_fprs; - i++, offset += 8) + tdep = gdbarch_tdep (gdbarch); + offsets = regset->descr; + if (regnum == -1) { - if (regnum == -1 || regnum == i) - ppc_collect_reg (regcache, i, fpregs, offset); + int i; + + for (i = tdep->ppc_fp0_regnum, offset = offsets->f0_offset; + i < tdep->ppc_fp0_regnum + ppc_num_fprs; + i++, offset += 8) + ppc_collect_reg (regcache, i, fpregs, offset, 8); + + ppc_collect_reg (regcache, tdep->ppc_fpscr_regnum, + fpregs, offsets->fpscr_offset, offsets->fpscr_size); + return; } - if (regnum == -1 || regnum == tdep->ppc_fpscr_regnum) - ppc_collect_reg (regcache, tdep->ppc_fpscr_regnum, - fpregs, offsets->fpscr_offset); + offset = ppc_fpreg_offset (tdep, offsets, regnum); + ppc_collect_reg (regcache, regnum, fpregs, offset, + regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8); } \f -- Alan Modra Australia Development Lab, IBM ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: powerpc-linux biarch corefile support 2007-08-30 12:14 ` Alan Modra @ 2007-08-30 12:50 ` Ulrich Weigand 2007-08-30 13:14 ` Alan Modra 0 siblings, 1 reply; 12+ messages in thread From: Ulrich Weigand @ 2007-08-30 12:50 UTC (permalink / raw) To: Alan Modra; +Cc: Ulrich Weigand, gdb-patches Alan Modra wrote: > Differences from last patch: > - All struct ppc_reg_offsets instances set new fields if they will be > used. It looks like setting of gpr_size and xr_size in ppcobsd_reg_offsets is still missing in ppcobsd-nat.c:_initialize_ppcobsd_nat. Otherwise, this version is OK. Thanks, Ulrich -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE Ulrich.Weigand@de.ibm.com ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: powerpc-linux biarch corefile support 2007-08-30 12:50 ` Ulrich Weigand @ 2007-08-30 13:14 ` Alan Modra 0 siblings, 0 replies; 12+ messages in thread From: Alan Modra @ 2007-08-30 13:14 UTC (permalink / raw) To: Ulrich Weigand; +Cc: Ulrich Weigand, gdb-patches On Thu, Aug 30, 2007 at 02:50:20PM +0200, Ulrich Weigand wrote: > It looks like setting of gpr_size and xr_size in ppcobsd_reg_offsets > is still missing in ppcobsd-nat.c:_initialize_ppcobsd_nat. > > Otherwise, this version is OK. Fixed and applied. Thanks! -- Alan Modra Australia Development Lab, IBM ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2007-08-30 13:14 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-01-22 16:43 powerpc-linux biarch corefile support Alan Modra
2007-01-22 17:12 ` Mark Kettenis
2007-01-23 6:57 ` Alan Modra
2007-02-08 14:40 ` Daniel Jacobowitz
2007-04-28 16:24 ` Ulrich Weigand
2007-08-25 1:23 ` Alan Modra
2007-08-28 23:03 ` Ulrich Weigand
2007-08-29 7:26 ` Alan Modra
2007-08-29 8:28 ` Alan Modra
[not found] ` <OFA57C40FB.23E13286-ON42257346.004A0E7C-42257346.004A56D1@de.ibm.com>
2007-08-30 12:14 ` Alan Modra
2007-08-30 12:50 ` Ulrich Weigand
2007-08-30 13:14 ` Alan Modra
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox