This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[RFA] gdbserver fetch/store registers problem on s390x
- From: Ulrich Weigand <uweigand at de dot ibm dot com>
- To: gdb-patches at sources dot redhat dot com
- Date: Tue, 10 May 2005 18:54:28 +0200 (CEST)
- Subject: [RFA] gdbserver fetch/store registers problem on s390x
Hello,
this patch fixes another problem with gdbserver on s390x occurring
on recent kernels. The problem is that some registers accessed by
ptrace (notably the access registers and the floating-point status
register) are still 32 bits wide, even though the PTRACE_PEEKUSER
and PTRACE_POKEUSER commands always transfer 64 bits.
This is a problem for two reasons: when fetching those registers,
a 4-byte buffer is allocated via alloca, but then 8 bytes are
written to that buffer (which just happens to work because alloca
rounds the size up to the next multiple of 8 anyway). The same
holds for storing the register; but in this case the second 4 bytes
have just random contents, and recent kernels won't allow the POKEUSER
command to succeed unless those extra bytes are zero.
The following patch fixes this problem by always allocating a buffer
that has multiple of sizeof (PTRACE_XFER_TYPE) as size, and by
zeroing out the excess bytes of the buffer when storing the register.
Tested on s390-ibm-linux and s390x-ibm-linux.
OK?
Bye,
Ulrich
ChangeLog:
* linux-low.c (fetch_register): Ensure buffer size is a multiple
of sizeof (PTRACE_XFER_TYPE).
(usr_store_inferior_registers): Likewise. Zero out excess bytes.
Index: gdb/gdbserver/linux-low.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/linux-low.c,v
retrieving revision 1.34
diff -c -p -r1.34 linux-low.c
*** gdb/gdbserver/linux-low.c 3 Mar 2005 16:56:53 -0000 1.34
--- gdb/gdbserver/linux-low.c 10 May 2005 11:53:40 -0000
*************** static void
*** 1095,1101 ****
fetch_register (int regno)
{
CORE_ADDR regaddr;
! register int i;
char *buf;
if (regno >= the_low_target.num_regs)
--- 1095,1101 ----
fetch_register (int regno)
{
CORE_ADDR regaddr;
! int i, size;
char *buf;
if (regno >= the_low_target.num_regs)
*************** fetch_register (int regno)
*** 1106,1113 ****
regaddr = register_addr (regno);
if (regaddr == -1)
return;
! buf = alloca (register_size (regno));
! for (i = 0; i < register_size (regno); i += sizeof (PTRACE_XFER_TYPE))
{
errno = 0;
*(PTRACE_XFER_TYPE *) (buf + i) =
--- 1106,1115 ----
regaddr = register_addr (regno);
if (regaddr == -1)
return;
! size = (register_size (regno) + sizeof (PTRACE_XFER_TYPE) - 1)
! & - sizeof (PTRACE_XFER_TYPE);
! buf = alloca (size);
! for (i = 0; i < size; i += sizeof (PTRACE_XFER_TYPE))
{
errno = 0;
*(PTRACE_XFER_TYPE *) (buf + i) =
*************** static void
*** 1147,1153 ****
usr_store_inferior_registers (int regno)
{
CORE_ADDR regaddr;
! int i;
char *buf;
if (regno >= 0)
--- 1149,1155 ----
usr_store_inferior_registers (int regno)
{
CORE_ADDR regaddr;
! int i, size;
char *buf;
if (regno >= 0)
*************** usr_store_inferior_registers (int regno)
*** 1162,1170 ****
if (regaddr == -1)
return;
errno = 0;
! buf = alloca (register_size (regno));
collect_register (regno, buf);
! for (i = 0; i < register_size (regno); i += sizeof (PTRACE_XFER_TYPE))
{
errno = 0;
ptrace (PTRACE_POKEUSER, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
--- 1164,1175 ----
if (regaddr == -1)
return;
errno = 0;
! size = (register_size (regno) + sizeof (PTRACE_XFER_TYPE) - 1)
! & - sizeof (PTRACE_XFER_TYPE);
! buf = alloca (size);
! memset (buf, 0, size);
collect_register (regno, buf);
! for (i = 0; i < size; i += sizeof (PTRACE_XFER_TYPE))
{
errno = 0;
ptrace (PTRACE_POKEUSER, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
--
Dr. Ulrich Weigand
Linux on zSeries Development
Ulrich.Weigand@de.ibm.com