diff options
-rw-r--r-- | gdb/gdbserver/ChangeLog | 19 | ||||
-rw-r--r-- | gdb/gdbserver/configure.srv | 2 | ||||
-rw-r--r-- | gdb/gdbserver/linux-low.c | 19 | ||||
-rw-r--r-- | gdb/gdbserver/linux-s390-low.c | 57 | ||||
-rw-r--r-- | gdb/gdbserver/regcache.c | 12 |
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 |