aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/gdbserver/ChangeLog19
-rw-r--r--gdb/gdbserver/configure.srv2
-rw-r--r--gdb/gdbserver/linux-low.c19
-rw-r--r--gdb/gdbserver/linux-s390-low.c57
-rw-r--r--gdb/gdbserver/regcache.c12
5 files changed, 95 insertions, 14 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 80ea9f9..ae63d4e 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,5 +1,24 @@
2008-02-27 Ulrich Weigand <uweigand@de.ibm.com>
+ * configure.srv [s390x-*-linux*]: Set srv_regobj to include both
+ reg-s390.o and reg-s390x.o.
+
+ * linux-low.c (new_inferior): New global variable.
+ (linux_create_inferior, linux_attach): Set it.
+ (linux_wait_for_process): Call the_low_target.arch_setup after the
+ target has stopped for the first time.
+ (initialize_low): Do not call the_low_target.arch_setup.
+
+ * linux-s390-low.c (s390_get_pc): Support bi-arch operation.
+ (s390_set_pc): Likewise.
+ (s390_arch_setup): New function.
+ (the_low_target): Use s390_arch_setup as arch_setup routine.
+
+ * regcache.c (realloc_register_cache): New function.
+ (set_register_cache): Call it for each existing regcache.
+
+2008-02-27 Ulrich Weigand <uweigand@de.ibm.com>
+
* server.h (init_registers): Remove prototype.
* linux-low.h (struct linux_target_ops): Add arch_setup field.
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index 4f1c22b..b529c02 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -145,7 +145,7 @@ case "${target}" in
srv_linux_regsets=yes
srv_linux_thread_db=yes
;;
- s390x-*-linux*) srv_regobj=reg-s390x.o
+ s390x-*-linux*) srv_regobj="reg-s390.o reg-s390x.o"
srv_tgtobj="linux-low.o linux-s390-low.o"
srv_linux_usrregs=yes
srv_linux_regsets=yes
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index d5a8fb4..732aafb 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -107,6 +107,11 @@ static int thread_db_active;
static int must_set_ptrace_flags;
+/* This flag is true iff we've just created or attached to a new inferior
+ but it has not stopped yet. As soon as it does, we need to call the
+ low target's arch_setup callback. */
+static int new_inferior;
+
static void linux_resume_one_process (struct inferior_list_entry *entry,
int step, int signal, siginfo_t *info);
static void linux_resume (struct thread_resume *resume_info);
@@ -291,6 +296,7 @@ linux_create_inferior (char *program, char **allargs)
new_process = add_process (pid);
add_thread (pid, new_process, pid);
must_set_ptrace_flags = 1;
+ new_inferior = 1;
return pid;
}
@@ -350,6 +356,8 @@ linux_attach (unsigned long pid)
process = (struct process_info *) find_inferior_id (&all_processes, pid);
process->stop_expected = 0;
+ new_inferior = 1;
+
return 0;
}
@@ -616,6 +624,16 @@ retry:
(*childp)->last_status = *wstatp;
+ /* Architecture-specific setup after inferior is running.
+ This needs to happen after we have attached to the inferior
+ and it is stopped for the first time, but before we access
+ any inferior registers. */
+ if (new_inferior)
+ {
+ the_low_target.arch_setup ();
+ new_inferior = 0;
+ }
+
if (debug_threads
&& WIFSTOPPED (*wstatp))
{
@@ -2072,7 +2090,6 @@ initialize_low (void)
set_target_ops (&linux_target_ops);
set_breakpoint_data (the_low_target.breakpoint,
the_low_target.breakpoint_len);
- the_low_target.arch_setup ();
linux_init_signals ();
linux_test_for_tracefork ();
}
diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c
index 6ae1a23..d6739ab 100644
--- a/gdb/gdbserver/linux-s390-low.c
+++ b/gdb/gdbserver/linux-s390-low.c
@@ -102,24 +102,61 @@ static const unsigned char s390_breakpoint[] = { 0, 1 };
static CORE_ADDR
s390_get_pc ()
{
- unsigned long pc;
- collect_register_by_name ("pswa", &pc);
+ if (register_size (0) == 4)
+ {
+ unsigned int pc;
+ collect_register_by_name ("pswa", &pc);
#ifndef __s390x__
- pc &= 0x7fffffff;
+ pc &= 0x7fffffff;
#endif
- return pc;
+ return pc;
+ }
+ else
+ {
+ unsigned long pc;
+ collect_register_by_name ("pswa", &pc);
+ return pc;
+ }
}
static void
s390_set_pc (CORE_ADDR newpc)
{
- unsigned long pc = newpc;
+ if (register_size (0) == 4)
+ {
+ unsigned int pc = newpc;
#ifndef __s390x__
- pc |= 0x80000000;
+ pc |= 0x80000000;
#endif
- supply_register_by_name ("pswa", &pc);
+ supply_register_by_name ("pswa", &pc);
+ }
+ else
+ {
+ unsigned long pc = newpc;
+ supply_register_by_name ("pswa", &pc);
+ }
}
+
+static void
+s390_arch_setup (void)
+{
+ /* Assume 31-bit inferior process. */
+ init_registers_s390 ();
+
+ /* On a 64-bit host, check the low bit of the (31-bit) PSWM
+ -- if this is one, we actually have a 64-bit inferior. */
+#ifdef __s390x__
+ {
+ unsigned int pswm;
+ collect_register_by_name ("pswm", &pswm);
+ if (pswm & 1)
+ init_registers_s390x ();
+ }
+#endif
+}
+
+
static int
s390_breakpoint_at (CORE_ADDR pc)
{
@@ -130,11 +167,7 @@ s390_breakpoint_at (CORE_ADDR pc)
struct linux_target_ops the_low_target = {
-#ifndef __s390x__
- init_registers_s390,
-#else
- init_registers_s390x,
-#endif
+ s390_arch_setup,
s390_num_regs,
s390_regmap,
s390_cannot_fetch_register,
diff --git a/gdb/gdbserver/regcache.c b/gdb/gdbserver/regcache.c
index 7b2285a..a42d95b 100644
--- a/gdb/gdbserver/regcache.c
+++ b/gdb/gdbserver/regcache.c
@@ -121,6 +121,15 @@ free_register_cache (void *regcache_p)
free (regcache);
}
+static void
+realloc_register_cache (struct inferior_list_entry *thread_p)
+{
+ struct thread_info *thread = (struct thread_info *) thread_p;
+
+ free_register_cache (inferior_regcache_data (thread));
+ set_inferior_regcache_data (thread, new_register_cache ());
+}
+
void
set_register_cache (struct reg *regs, int n)
{
@@ -137,6 +146,9 @@ set_register_cache (struct reg *regs, int n)
}
register_bytes = offset / 8;
+
+ /* Re-allocate all pre-existing register caches. */
+ for_each_inferior (&all_threads, realloc_register_cache);
}
void