This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [rfc][3/3] gdbserver bi-arch support: fix s390x partial register access
- From: "Ulrich Weigand" <uweigand at de dot ibm dot com>
- To: drow at false dot org (Daniel Jacobowitz)
- Cc: gdb-patches at sourceware dot org
- Date: Wed, 30 Jan 2008 00:35:17 +0100 (CET)
- Subject: Re: [rfc][3/3] gdbserver bi-arch support: fix s390x partial register access
Daniel Jacobowitz wrote:
> What do you think about passing data to the low target in this case?
> For MIPS the right bits will be value-dependent - registers must be
> sign extended.
Hmm, what about the version below? This should allow the low target
whatever flexibility it requires ...
Bye,
Ulrich
ChangeLog:
* linux-low.h (struct linux_target_ops): Replace left_pad_xfer field
by collect_ptrace_register and supply_ptrace_register hooks.
* linux-low.c (fetch_register): Use supply_ptrace_register callback
instead of checking for the_low_target.left_pad_xfer.
(usr_store_inferior_registers): Use collect_ptrace_register callback
instead of checking for the_low_target.left_pad_xfer.
* linux-s390-low.c (s390_collect_ptrace_register): New function.
(s390_supply_ptrace_register): Likewise.
(s390_fill_gregset): Call s390_collect_ptrace_register.
(the_low_target): Update.
* linux-ppc64-low.c (ppc_collect_ptrace_register): New function.
(ppc_supply_ptrace_register): Likewise.
(the_low_target): Update.
* linux-i386-low.c (the_low_target): Update.
* linux-x86-64-low.c (the_low_target): Update.
diff -urNp gdb-orig/gdb/gdbserver/linux-i386-low.c gdb-head/gdb/gdbserver/linux-i386-low.c
--- gdb-orig/gdb/gdbserver/linux-i386-low.c 2008-01-29 23:21:45.000000000 +0100
+++ gdb-head/gdb/gdbserver/linux-i386-low.c 2008-01-30 00:18:49.000000000 +0100
@@ -205,6 +205,7 @@ struct linux_target_ops the_low_target =
NULL,
NULL,
NULL,
- 0,
+ NULL,
+ NULL,
"i386"
};
diff -urNp gdb-orig/gdb/gdbserver/linux-low.c gdb-head/gdb/gdbserver/linux-low.c
--- gdb-orig/gdb/gdbserver/linux-low.c 2008-01-29 23:34:20.000000000 +0100
+++ gdb-head/gdb/gdbserver/linux-low.c 2008-01-30 00:12:02.000000000 +0100
@@ -1391,10 +1391,9 @@ fetch_register (int regno)
goto error_exit;
}
}
- if (the_low_target.left_pad_xfer
- && register_size (regno) < sizeof (PTRACE_XFER_TYPE))
- supply_register (regno, (buf + sizeof (PTRACE_XFER_TYPE)
- - register_size (regno)));
+
+ if (the_low_target.supply_ptrace_register)
+ the_low_target.supply_ptrace_register (regno, buf);
else
supply_register (regno, buf);
@@ -1438,12 +1437,12 @@ usr_store_inferior_registers (int regno)
& - sizeof (PTRACE_XFER_TYPE);
buf = alloca (size);
memset (buf, 0, size);
- if (the_low_target.left_pad_xfer
- && register_size (regno) < sizeof (PTRACE_XFER_TYPE))
- collect_register (regno, (buf + sizeof (PTRACE_XFER_TYPE)
- - register_size (regno)));
+
+ if (the_low_target.collect_ptrace_register)
+ the_low_target.collect_ptrace_register (regno, buf);
else
collect_register (regno, buf);
+
for (i = 0; i < size; i += sizeof (PTRACE_XFER_TYPE))
{
errno = 0;
diff -urNp gdb-orig/gdb/gdbserver/linux-low.h gdb-head/gdb/gdbserver/linux-low.h
--- gdb-orig/gdb/gdbserver/linux-low.h 2008-01-29 23:21:45.000000000 +0100
+++ gdb-head/gdb/gdbserver/linux-low.h 2008-01-29 23:55:41.000000000 +0100
@@ -69,9 +69,10 @@ struct linux_target_ops
int (*stopped_by_watchpoint) (void);
CORE_ADDR (*stopped_data_address) (void);
- /* Whether to left-pad registers for PEEKUSR/POKEUSR if they are smaller
- than an xfer unit. */
- int left_pad_xfer;
+ /* Hooks to reformat register data for PEEKUSR/POKEUSR (in particular
+ for registers smaller than an xfer unit). */
+ void (*collect_ptrace_register) (int regno, char *buf);
+ void (*supply_ptrace_register) (int regno, const char *buf);
/* What string to report to GDB when it asks for the architecture,
or NULL not to answer. */
diff -urNp gdb-orig/gdb/gdbserver/linux-ppc64-low.c gdb-head/gdb/gdbserver/linux-ppc64-low.c
--- gdb-orig/gdb/gdbserver/linux-ppc64-low.c 2008-01-29 23:21:45.000000000 +0100
+++ gdb-head/gdb/gdbserver/linux-ppc64-low.c 2008-01-30 00:11:13.000000000 +0100
@@ -64,6 +64,26 @@ ppc_cannot_fetch_register (int regno)
return 0;
}
+static void
+ppc_collect_ptrace_register (int regno, char *buf)
+{
+ int size = register_size (regno);
+ if (size < sizeof (long))
+ collect_register (regno, buf + sizeof (long) - size);
+ else
+ collect_register (regno, buf);
+}
+
+static void
+ppc_supply_ptrace_register (int regno, const char *buf)
+{
+ int size = register_size (regno);
+ if (size < sizeof (long))
+ supply_register (regno, buf + sizeof (long) - size);
+ else
+ supply_register (regno, buf);
+}
+
static CORE_ADDR
ppc_get_pc (void)
{
@@ -187,5 +207,6 @@ struct linux_target_ops the_low_target =
NULL,
NULL,
NULL,
- 1
+ ppc_collect_ptrace_register,
+ ppc_supply_ptrace_register,
};
diff -urNp gdb-orig/gdb/gdbserver/linux-s390-low.c gdb-head/gdb/gdbserver/linux-s390-low.c
--- gdb-orig/gdb/gdbserver/linux-s390-low.c 2008-01-29 23:34:20.000000000 +0100
+++ gdb-head/gdb/gdbserver/linux-s390-low.c 2008-01-30 00:13:19.000000000 +0100
@@ -79,6 +79,45 @@ s390_cannot_store_register (int regno)
return 0;
}
+static void
+s390_collect_ptrace_register (int regno, char *buf)
+{
+ int size = register_size (regno);
+ if (size < sizeof (long))
+ {
+ memset (buf, 0, sizeof (long));
+
+ if (regno == find_regno ("pswa")
+ || (regno >= find_regno ("r0") && regno <= find_regno ("r15")))
+ collect_register (regno, buf + sizeof (long) - size);
+ else
+ collect_register (regno, buf);
+
+ /* When debugging a 32-bit inferior on a 64-bit host, make sure
+ the 31-bit addressing mode bit is set in the PSW mask. */
+ if (regno == find_regno ("pswm"))
+ buf[size] |= 0x80;
+ }
+ else
+ collect_register (regno, buf);
+}
+
+static void
+s390_supply_ptrace_register (int regno, const char *buf)
+{
+ int size = register_size (regno);
+ if (size < sizeof (long))
+ {
+ if (regno == find_regno ("pswa")
+ || (regno >= find_regno ("r0") && regno <= find_regno ("r15")))
+ supply_register (regno, buf + sizeof (long) - size);
+ else
+ supply_register (regno, buf);
+ }
+ else
+ supply_register (regno, buf);
+}
+
/* Provide only a fill function for the general register set. ps_lgetregs
will use this for NPTL support. */
@@ -87,7 +126,7 @@ static void s390_fill_gregset (void *buf
int i;
for (i = 0; i < 34; i++)
- collect_register (i, (char *) buf + s390_regmap[i]);
+ s390_collect_ptrace_register (i, (char *) buf + s390_regmap[i]);
}
struct regset_info target_regsets[] = {
@@ -179,5 +218,11 @@ struct linux_target_ops the_low_target =
NULL,
s390_breakpoint_len,
s390_breakpoint_at,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ s390_collect_ptrace_register,
+ s390_supply_ptrace_register,
};
diff -urNp gdb-orig/gdb/gdbserver/linux-x86-64-low.c gdb-head/gdb/gdbserver/linux-x86-64-low.c
--- gdb-orig/gdb/gdbserver/linux-x86-64-low.c 2008-01-29 23:21:45.000000000 +0100
+++ gdb-head/gdb/gdbserver/linux-x86-64-low.c 2008-01-30 00:19:33.000000000 +0100
@@ -179,6 +179,7 @@ struct linux_target_ops the_low_target =
NULL,
NULL,
NULL,
- 0,
+ NULL,
+ NULL,
"i386:x86-64",
};
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com