From 4a19ea356e67d4e693bf9d6d23a439716e434546 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Fri, 4 Jun 2004 23:07:28 +0000 Subject: [PATCH] * ppc-linux-nat.c (store_register, fetch_register): Remove incorrect assertions. Simplify and generalize handling of transfers whose sizes are not multiples of, or less than, sizeof (PTRACE_XFER_TYPE). --- gdb/ChangeLog | 7 ++++ gdb/ppc-linux-nat.c | 86 +++++++++++++++++++++++---------------------- 2 files changed, 51 insertions(+), 42 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 0e830f4be7c..01e5533aefc 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2004-06-04 Jim Blandy + + * ppc-linux-nat.c (store_register, fetch_register): Remove + incorrect assertions. Simplify and generalize handling of + transfers whose sizes are not multiples of, or less than, sizeof + (PTRACE_XFER_TYPE). + 2004-06-04 Jeff Johnston * infrun.c (handle_inferior_event): Don't treat an invalid ptid diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c index f532a58b15f..0700d84b40f 100644 --- a/gdb/ppc-linux-nat.c +++ b/gdb/ppc-linux-nat.c @@ -209,7 +209,7 @@ fetch_register (int tid, int regno) struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); /* This isn't really an address. But ptrace thinks of it as one. */ CORE_ADDR regaddr = ppc_register_u_addr (regno); - int i; + int bytes_transferred; unsigned int offset; /* Offset of registers within the u area. */ char buf[MAX_REGISTER_SIZE]; @@ -236,19 +236,16 @@ fetch_register (int tid, int regno) return; } - /* If the current architecture has no floating-point registers, we - should never reach this point: ppc_register_u_addr should have - returned -1, and we should have caught that above. */ - gdb_assert (ppc_floating_point_unit_p (current_gdbarch)); - /* Read the raw register using PTRACE_XFER_TYPE sized chunks. On a 32-bit platform, 64-bit floating-point registers will require two transfers. */ - for (i = 0; i < DEPRECATED_REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE)) + for (bytes_transferred = 0; + bytes_transferred < register_size (regno); + bytes_transferred += sizeof (PTRACE_XFER_TYPE)) { errno = 0; - *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid, - (PTRACE_ARG3_TYPE) regaddr, 0); + *(PTRACE_XFER_TYPE *) & buf[bytes_transferred] + = ptrace (PT_READ_U, tid, (PTRACE_ARG3_TYPE) regaddr, 0); regaddr += sizeof (PTRACE_XFER_TYPE); if (errno != 0) { @@ -259,19 +256,25 @@ fetch_register (int tid, int regno) } } - /* Now supply the register. Be careful to map between ptrace's and - the current_regcache's idea of the current wordsize. */ - if ((regno >= tdep->ppc_fp0_regnum - && regno < tdep->ppc_fp0_regnum + ppc_num_fprs) - || gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_LITTLE) - /* FPs are always 64 bits. Little endian values are always found - at the left-hand end of the register. */ - regcache_raw_supply (current_regcache, regno, buf); - else - /* Big endian register, need to fetch the right-hand end. */ - regcache_raw_supply (current_regcache, regno, - (buf + sizeof (PTRACE_XFER_TYPE) - - register_size (current_gdbarch, regno))); + /* Now supply the register. Keep in mind that the regcache's idea + of the register's size may not be a multiple of sizeof + (PTRACE_XFER_TYPE). */ + if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_LITTLE) + { + /* Little-endian values are always found at the left end of the + bytes transferred. */ + regcache_raw_supply (current_regcache, regno, buf); + } + else if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG) + { + /* Big-endian values are found at the right end of the bytes + transferred. */ + size_t padding = (bytes_transferred + - register_size (current_gdbarch, regno)); + regcache_raw_supply (current_regcache, regno, buf + padding); + } + else + gdb_assert (0); } static void @@ -407,6 +410,7 @@ store_register (int tid, int regno) /* This isn't really an address. But ptrace thinks of it as one. */ CORE_ADDR regaddr = ppc_register_u_addr (regno); int i; + size_t bytes_to_transfer; char buf[MAX_REGISTER_SIZE]; if (altivec_register_p (regno)) @@ -418,28 +422,26 @@ store_register (int tid, int regno) if (regaddr == -1) return; - /* If the current architecture has no floating-point registers, we - should never reach this point: ppc_register_u_addr should have - returned -1, and we should have caught that above. */ - gdb_assert (ppc_floating_point_unit_p (current_gdbarch)); - - /* First collect the register value from the regcache. Be careful - to to convert the regcache's wordsize into ptrace's wordsize. */ + /* First collect the register. Keep in mind that the regcache's + idea of the register's size may not be a multiple of sizeof + (PTRACE_XFER_TYPE). */ memset (buf, 0, sizeof buf); - if ((regno >= tdep->ppc_fp0_regnum - && regno < tdep->ppc_fp0_regnum + ppc_num_fprs) - || TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE) - /* Floats are always 64-bit. Little endian registers are always - at the left-hand end of the register cache. */ - regcache_raw_collect (current_regcache, regno, buf); - else - /* Big-endian registers belong at the right-hand end of the - buffer. */ - regcache_raw_collect (current_regcache, regno, - (buf + sizeof (PTRACE_XFER_TYPE) - - register_size (current_gdbarch, regno))); + bytes_to_transfer = align_up (register_size (current_gdbarch, regno), + sizeof (PTRACE_XFER_TYPE)); + if (TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE) + { + /* Little-endian values always sit at the left end of the buffer. */ + regcache_raw_collect (current_regcache, regno, buf); + } + else if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) + { + /* Big-endian values sit at the right end of the buffer. */ + size_t padding = (bytes_to_transfer + - register_size (current_gdbarch, regno)); + regcache_raw_collect (current_regcache, regno, buf + padding); + } - for (i = 0; i < DEPRECATED_REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE)) + for (i = 0; i < bytes_to_transfer; i += sizeof (PTRACE_XFER_TYPE)) { errno = 0; ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr, -- 2.30.2