This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: fix assertions; handle endianness more directly


The assertions this patch deletes were meant to cover the use of
ppc_fp0_regnum later in the functions, but the assertions are simply
wrong: control can certainly reach that point in the function on
architectures that lack floating-point registers.

This patch removes the assertions, and then decides which end of the
bytes read from / written to the kernel the register's value really
occupies simply by considering endianness and the relative sizes,
rather than "knowing" how big various registers are relative to the
ptrace word size.  That cleanup removes all references to the
ppc_fp0_regnum, settling the original problem.

Tested with no regressions on powerpc-unknown-linux-gnu.

2004-06-02  Jim Blandy  <jimb@redhat.com>

	* 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).
 
Index: gdb/ppc-linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/ppc-linux-nat.c,v
retrieving revision 1.42
diff -c -p -r1.42 ppc-linux-nat.c
*** gdb/ppc-linux-nat.c	2 Jun 2004 18:24:35 -0000	1.42
--- gdb/ppc-linux-nat.c	2 Jun 2004 20:49:11 -0000
*************** fetch_register (int tid, int regno)
*** 209,215 ****
    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;
    unsigned int offset;         /* Offset of registers within the u area. */
    char buf[MAX_REGISTER_SIZE];
  
--- 209,215 ----
    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 bytes_transferred;
    unsigned int offset;         /* Offset of registers within the u area. */
    char buf[MAX_REGISTER_SIZE];
  
*************** fetch_register (int tid, int regno)
*** 236,254 ****
        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))
      {
        errno = 0;
!       *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid,
! 					       (PTRACE_ARG3_TYPE) regaddr, 0);
        regaddr += sizeof (PTRACE_XFER_TYPE);
        if (errno != 0)
  	{
--- 236,251 ----
        return;
      }
  
    /* 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 (bytes_transferred = 0;
!        bytes_transferred < DEPRECATED_REGISTER_RAW_SIZE (regno);
!        bytes_transferred += sizeof (PTRACE_XFER_TYPE))
      {
        errno = 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)
  	{
*************** fetch_register (int tid, int regno)
*** 259,279 ****
  	}
      }
  
!   /* 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)));
  }
  
  static void
  supply_vrregset (gdb_vrregset_t *vrregsetp)
  {
--- 256,283 ----
  	}
      }
  
!   /* 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
  supply_vrregset (gdb_vrregset_t *vrregsetp)
  {
*************** store_register (int tid, int regno)
*** 407,412 ****
--- 411,417 ----
    /* 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))
*************** store_register (int tid, int regno)
*** 418,445 ****
    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.  */
    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)));
  
!   for (i = 0; i < DEPRECATED_REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
      {
        errno = 0;
        ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr,
--- 423,448 ----
    if (regaddr == -1)
      return;
  
!   /* 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);
!   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 < bytes_to_transfer; i += sizeof (PTRACE_XFER_TYPE))
      {
        errno = 0;
        ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr,


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]