From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10079 invoked by alias); 21 Jan 2008 17:46:20 -0000 Received: (qmail 10066 invoked by uid 22791); 21 Jan 2008 17:46:19 -0000 X-Spam-Check-By: sourceware.org Received: from mtagate6.de.ibm.com (HELO mtagate6.de.ibm.com) (195.212.29.155) by sourceware.org (qpsmtpd/0.31) with ESMTP; Mon, 21 Jan 2008 17:45:57 +0000 Received: from d12nrmr1607.megacenter.de.ibm.com (d12nrmr1607.megacenter.de.ibm.com [9.149.167.49]) by mtagate6.de.ibm.com (8.13.8/8.13.8) with ESMTP id m0LHjq6d159794 for ; Mon, 21 Jan 2008 17:45:52 GMT Received: from d12av02.megacenter.de.ibm.com (d12av02.megacenter.de.ibm.com [9.149.165.228]) by d12nrmr1607.megacenter.de.ibm.com (8.13.8/8.13.8/NCO v8.7) with ESMTP id m0LHjq8k1294532 for ; Mon, 21 Jan 2008 18:45:52 +0100 Received: from d12av02.megacenter.de.ibm.com (loopback [127.0.0.1]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id m0LHjqfa002479 for ; Mon, 21 Jan 2008 18:45:52 +0100 Received: from tuxmaker.boeblingen.de.ibm.com (tuxmaker.boeblingen.de.ibm.com [9.152.85.9]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.12.11) with SMTP id m0LHjqHo002475 for ; Mon, 21 Jan 2008 18:45:52 +0100 Message-Id: <200801211745.m0LHjqHo002475@d12av02.megacenter.de.ibm.com> Received: by tuxmaker.boeblingen.de.ibm.com (sSMTP sendmail emulation); Mon, 21 Jan 2008 18:45:52 +0100 Subject: [rfc][2/3] gdbserver bi-arch support: core s390x part To: gdb-patches@sourceware.org Date: Mon, 21 Jan 2008 17:46:00 -0000 From: "Ulrich Weigand" X-Mailer: ELM [version 2.5 PL2] MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-01/txt/msg00511.txt.bz2 Hello, this patch makes gdbserver on s390x bi-arch capabable: it will now detect whether the target is 31-bit or 64-bit and select the appropriate register format definition. The basic idea is to simply link gdbserver with both reg-s390.o and reg-s390x.o (which no longer conflict), and change the compile-time selection of the linux-s390-low version of the_low_target.arch_setup into a run-time selection. However, this isn't really sufficient: at the time the arch_setup routine is currently called, there is no target attached, and thus there is no way of detecting whether to use the 31-bit or 64-bit register set. Thus the patch also changes the call location of arch_setup in linux-low.c to just after the inferior is attached (but before any register access). This point happens to be in linux_wait_for_process (when called for the first time). This exposes another problem: at this time, common code has already set up a register cache for the initial thread, which may now turn out to be of the wrong size. To fix this, the set_register_cache routine (which is called by the generated init_register_... routine) now goes through all register caches that may already have been allocated and re-sizes them to the new size. (As a nice side-effect, this now also allows to call init_register_... multiple times.) Finally, the patch adapted s390_get_pc and s390_set_pc to properly work in the bi-arch configuration. (Note that even so there are a couple of problems that need to be fixed in a follow-on patch.) Tested (together with the follow-on patch) on s390-linux and s390x-linux. Bye, Ulrich ChangeLog: * configure.srv [s390x-*-linux*]: Set srv_regobj to include both reg-s390.o and reg-s390x.o. * linux-low.c (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. diff -urNp gdb-orig/gdb/gdbserver/configure.srv gdb-head/gdb/gdbserver/configure.srv --- gdb-orig/gdb/gdbserver/configure.srv 2008-01-18 00:57:40.000000000 +0100 +++ gdb-head/gdb/gdbserver/configure.srv 2008-01-17 22:29:26.000000000 +0100 @@ -138,7 +138,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 -urNp gdb-orig/gdb/gdbserver/linux-low.c gdb-head/gdb/gdbserver/linux-low.c --- gdb-orig/gdb/gdbserver/linux-low.c 2008-01-18 00:57:40.000000000 +0100 +++ gdb-head/gdb/gdbserver/linux-low.c 2008-01-18 00:57:34.000000000 +0100 @@ -548,6 +548,7 @@ status_pending_p (struct inferior_list_e static void linux_wait_for_process (struct process_info **childp, int *wstatp) { + static int arch_setup_done = 0; int ret; int to_wait_for = -1; @@ -606,6 +607,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 (!arch_setup_done) + { + the_low_target.arch_setup (); + arch_setup_done = 1; + } + if (debug_threads && WIFSTOPPED (*wstatp)) { @@ -2060,7 +2071,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 -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-18 00:57:40.000000000 +0100 +++ gdb-head/gdb/gdbserver/linux-s390-low.c 2008-01-18 01:00:18.000000000 +0100 @@ -102,24 +102,61 @@ static const unsigned char s390_breakpoi 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 -urNp gdb-orig/gdb/gdbserver/regcache.c gdb-head/gdb/gdbserver/regcache.c --- gdb-orig/gdb/gdbserver/regcache.c 2008-01-18 00:57:40.000000000 +0100 +++ gdb-head/gdb/gdbserver/regcache.c 2008-01-17 22:29:26.000000000 +0100 @@ -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, in } register_bytes = offset / 8; + + /* Re-allocate all pre-existing register caches. */ + for_each_inferior (&all_threads, realloc_register_cache); } void -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE Ulrich.Weigand@de.ibm.com