* Re: [patch] multi-arch INIT_FRAME_PC*; Was: New gdb 31 & 64 bit patches for S/390
@ 2001-06-16 17:39 Michael Elizabeth Chastain
2001-06-17 8:51 ` Andrew Cagney
2001-06-17 9:58 ` Andrew Cagney
0 siblings, 2 replies; 8+ messages in thread
From: Michael Elizabeth Chastain @ 2001-06-16 17:39 UTC (permalink / raw)
To: ac131313; +Cc: gdb-patches
Backtrace is working again on native solaris 2.6 and native red hat linux 6.2.
But native solaris traces back past main without stopping. Native linux
does not have a problem.
Yesterday before the change:
[chastain@delta fsf]$ /horton/chastain/fsf/2001-06-15-16.00.00/delta/native/build/gdb/gdb ~/tmp/miscexprs.delta
GNU gdb 2001-06-15-cvs
Copyright 2001 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "sparc-sun-solaris2.6"...
(gdb) break marker1
Breakpoint 1 at 0x1057c: file /horton/chastain/fsf/2001-06-09/source/gdb/testsuite/gdb.base/miscexprs.c, line 5.
(gdb) run
Starting program: /home/chastain/tmp/miscexprs.delta
Breakpoint 1, marker1 ()
at /horton/chastain/fsf/2001-06-09/source/gdb/testsuite/gdb.base/miscexprs.c:5
5 }
(gdb) bt
#0 marker1 ()
at /horton/chastain/fsf/2001-06-09/source/gdb/testsuite/gdb.base/miscexprs.c:5
#1 0x00010628 in main ()
at /horton/chastain/fsf/2001-06-09/source/gdb/testsuite/gdb.base/miscexprs.c:47
(gdb) cont
Continuing.
Program exited normally.
(gdb) quit
Current gdb:
[chastain@delta fsf]$ /horton/chastain/fsf/2001-06-16/delta/native/build/gdb/gdb ~/tmp/miscexprs.delta
GNU gdb 2001-06-16-cvs
Copyright 2001 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "sparc-sun-solaris2.6"...
(gdb) break marker1
Breakpoint 1 at 0x1057c: file /horton/chastain/fsf/2001-06-09/source/gdb/testsuite/gdb.base/miscexprs.c, line 5.
(gdb) run
Starting program: /home/chastain/tmp/miscexprs.delta
Breakpoint 1, marker1 ()
at /horton/chastain/fsf/2001-06-09/source/gdb/testsuite/gdb.base/miscexprs.c:5
5 }
(gdb) bt
#0 marker1 ()
at /horton/chastain/fsf/2001-06-09/source/gdb/testsuite/gdb.base/miscexprs.c:5
#1 0x00010628 in main ()
at /horton/chastain/fsf/2001-06-09/source/gdb/testsuite/gdb.base/miscexprs.c:47
#2 0x00010414 in .nope ()
#3 0x00000008 in ?? ()
(gdb) cont
Continuing.
Program exited normally.
(gdb) quit
Michael
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [patch] multi-arch INIT_FRAME_PC*; Was: New gdb 31 & 64 bit patches for S/390
2001-06-16 17:39 Michael Elizabeth Chastain
@ 2001-06-17 8:51 ` Andrew Cagney
2001-06-17 9:26 ` Andrew Cagney
2001-06-17 9:58 ` Andrew Cagney
1 sibling, 1 reply; 8+ messages in thread
From: Andrew Cagney @ 2001-06-17 8:51 UTC (permalink / raw)
To: Michael Elizabeth Chastain; +Cc: gdb-patches
> Backtrace is working again on native solaris 2.6 and native red hat linux 6.2.
> But native solaris traces back past main without stopping. Native linux
> does not have a problem.
Michael, the sparc case has me stumped. tm-sparc.h defines both
INIT_FRAME_PC() and INIT_FRAME_PC_FIRST() so (as far as theories go :-)
shouldn't be affected by the change.
Andrew
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [patch] multi-arch INIT_FRAME_PC*; Was: New gdb 31 & 64 bit patches for S/390
2001-06-17 8:51 ` Andrew Cagney
@ 2001-06-17 9:26 ` Andrew Cagney
0 siblings, 0 replies; 8+ messages in thread
From: Andrew Cagney @ 2001-06-17 9:26 UTC (permalink / raw)
To: Andrew Cagney; +Cc: Michael Elizabeth Chastain, gdb-patches
>
> Michael, the sparc case has me stumped. tm-sparc.h defines both INIT_FRAME_PC() and INIT_FRAME_PC_FIRST() so (as far as theories go :-) shouldn't be affected by the change.
>
>
Found it. It needs to be native:
make[1]: Entering directory `/horton/cagney/GDB/native/gdb'
gcc -c -g -O -I/usr/include/v9 -I. -I/horton/cagney/GDB/src/gdb -I/horton/cagn
ey/GDB/src/gdb/config -DHAVE_CONFIG_H -I/horton/cagney/GDB/src/gdb/../include/op
code -I/horton/cagney/GDB/src/gdb/../readline/.. -I../bfd -I/horton/cagney/GDB/s
rc/gdb/../bfd -I/horton/cagney/GDB/src/gdb/../include -I../intl -I/horton/cagne
y/GDB/src/gdb/../intl -DUI_OUT=1 -Werror /horton/cagney/GDB/src/gdb/main.c
In file included from /horton/cagney/GDB/src/gdb/defs.h:1148,
from /horton/cagney/GDB/src/gdb/main.c:22:
/horton/cagney/GDB/src/gdb/gdbarch.h:691: warning: `CANNOT_STORE_REGISTER' redef
ined
/horton/cagney/GDB/src/gdb/config/sparc/tm-sparc.h:412: warning: this is the loc
ation of the previous definition
/horton/cagney/GDB/src/gdb/gdbarch.h:830: warning: `INIT_FRAME_PC_FIRST' redefin
ed
/horton/cagney/GDB/src/gdb/config/sparc/tm-sparc.h:538: warning: this is the loc
ation of the previous definition
/horton/cagney/GDB/src/gdb/gdbarch.h:844: warning: `INIT_FRAME_PC' redefined
/horton/cagney/GDB/src/gdb/config/sparc/tm-sparc.h:535: warning: this is the loc
ation of the previous definition
make[1]: *** [main.o] Error 1
make[1]: Leaving directory `/horton/cagney/GDB/native/gdb'
make: *** [all-gdb] Error 2
status=2
I'm going to tweek gdbarch.sh so that it is more pig-headed about this.
Andrew
PS: Michael, time to use -Werror.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [patch] multi-arch INIT_FRAME_PC*; Was: New gdb 31 & 64 bit patches for S/390
2001-06-16 17:39 Michael Elizabeth Chastain
2001-06-17 8:51 ` Andrew Cagney
@ 2001-06-17 9:58 ` Andrew Cagney
1 sibling, 0 replies; 8+ messages in thread
From: Andrew Cagney @ 2001-06-17 9:58 UTC (permalink / raw)
To: Michael Elizabeth Chastain; +Cc: gdb-patches
Michael,
I've checked in the attached as an obvious fix. I'll follow this up
with a more pig-headed gdbarch.sh (#error) so that the problem gets
detected earlier.
Andrew
From ac131313@cygnus.com Sun Jun 17 10:47:00 2001
From: Andrew Cagney <ac131313@cygnus.com>
To: gdb-patches@sources.redhat.com
Subject: [patch] treat conflicting multi-arch macros as an error
Date: Sun, 17 Jun 2001 10:47:00 -0000
Message-id: <3B2CED49.90809@cygnus.com>
X-SW-Source: 2001-06/msg00335.html
Content-length: 126
Per other e-mail. This should cause a compilation failure when there is
a conflicting multi-arch macro definition.
Andrew
From chastain@cygnus.com Sun Jun 17 11:15:00 2001
From: Michael Elizabeth Chastain <chastain@cygnus.com>
To: ac131313@cygnus.com
Cc: gdb-patches@sources.redhat.com
Subject: Re: [patch] multi-arch INIT_FRAME_PC*; Was: New gdb 31 & 64 bit patches for S/390
Date: Sun, 17 Jun 2001 11:15:00 -0000
Message-id: <200106171816.LAA21467@bosch.cygnus.com>
X-SW-Source: 2001-06/msg00336.html
Content-length: 252
> PS: Michael, time to use -Werror.
I'll try it. Is this the right incantation?
/.../.../configure ... --enable-build-warnings=-Wimplicit,-Wreturn-type,-Wcomment,-Wtrigraphs,-Wformat,-Wparentheses,-Wpointer-arith,-Wuninitialized,-Werror
Michael
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [patch] multi-arch INIT_FRAME_PC*; Was: New gdb 31 & 64 bit patches for S/390
@ 2001-06-16 16:14 Michael Elizabeth Chastain
0 siblings, 0 replies; 8+ messages in thread
From: Michael Elizabeth Chastain @ 2001-06-16 16:14 UTC (permalink / raw)
To: ac131313; +Cc: gdb-patches
> The attached should fix the problem. Michael, if it doesn't it may pay
> to revert this and the other patch (until I find a thinking cap that
> fits) :-/
Cool. I'll crank up some native linux and solaris builds and check
it out.
Michael
^ permalink raw reply [flat|nested] 8+ messages in thread
[parent not found: <200106161813.LAA20846@bosch.cygnus.com>]
* Re: [patch] multi-arch INIT_FRAME_PC*; Was: New gdb 31 & 64 bit patches for S/390
[not found] <200106161813.LAA20846@bosch.cygnus.com>
@ 2001-06-16 12:35 ` Andrew Cagney
0 siblings, 0 replies; 8+ messages in thread
From: Andrew Cagney @ 2001-06-16 12:35 UTC (permalink / raw)
To: Michael Elizabeth Chastain, gdb-patches
Oops,
As MichaelC just pointed out to me it might work fine for my target
(MIPS) but doesn't work fine for any other target :-(. Back traces fail
because blockframe.c no longer gets the default:
- #if !defined (INIT_FRAME_PC)
- #define INIT_FRAME_PC(fromleaf, prev) \
- prev->pc = (fromleaf ? SAVED_PC_AFTER_CALL (prev->next) : \
- prev->next ? FRAME_SAVED_PC (prev->next) : read_pc ());
- #endif
-
The attached should fix the problem. Michael, if it doesn't it may pay
to revert this and the other patch (until I find a thinking cap that
fits) :-/
Andrew
^ permalink raw reply [flat|nested] 8+ messages in thread
* New gdb 31 & 64 bit patches for S/390
@ 2001-02-27 12:39 DJBARROW
2001-06-15 16:09 ` [patch] multi-arch INIT_FRAME_PC*; Was: " Andrew Cagney
0 siblings, 1 reply; 8+ messages in thread
From: DJBARROW @ 2001-02-27 12:39 UTC (permalink / raw)
To: gdb-patches, s390-patches, Binutils Patches, bash_maintainers
Cc: schwidefsky, ARENZ
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1219 bytes --]
Hi All,
Here are the latest gdb patches for S/390, they are against yesterdays
repository ( Feb 26th )
I have spent a lot of time reworking the stuff to get it down to as few
files as possible,
& addressing issues brought up on previous submissions
( a hell of a lot more time than the 64 bit port took :-) ).
& hope it is accepted this time.
The only thing I'm aware of which isn't working properly
is gdb /boot/vmlinux /proc/kcore
when compiled for multiarch
This is because the bfd stuff returns
bfd_arch_unknown
& set_gdbarch_from_file complains because gdbarch_update_p can't fix up
this,
this however is quite normal for the /proc/kcore file even when compiled
without multi-arch,
the code works fine when compiled without multi-arch.
(See attached file: gdb.s390.270201.binutils.config.diff)(See attached
file: gdb.s390.270201.config.diff)(See attached file:
gdb.s390.270201.core.diff)(See attached file:
gdb.s390.270201.readline.config.diff)(See attached file: S390ChangeLog.gdb)
(See attached file: S390ChangeLog.Root)
D.J. Barrow Gnu/Linux for S/390 kernel developer
eMail: djbarrow@de.ibm.com,barrow_dj@yahoo.com
Phone: +49-(0)7031-16-2583
IBM Germany Lab, Schönaicherstr. 220, 71032 Böblingen
[-- Attachment #2: gdb.s390.270201.binutils.config.diff --]
[-- Type: text/x-diff, Size: 402 bytes --]
--- src.orig/bfd/configure.in Thu Feb 22 17:38:45 2001
+++ src.new/bfd/configure.in Mon Feb 26 19:03:16 2001
@@ -151,6 +151,7 @@
hppa*-*-mpeix*) COREFILE=hpux-core.lo ;;
hppa*-*-bsd*) COREFILE="hpux-core.lo hppabsd-core.lo"
COREFLAG="-DHPUX_CORE -DHPPABSD_CORE" ;;
+ s390*-*-*) COREFILE=trad-core.lo ;;
i370-*-*)
COREFILE=trad-core.lo
TRAD_HEADER='"hosts/i370linux.h"'
[-- Attachment #3: gdb.s390.270201.config.diff --]
[-- Type: text/x-diff, Size: 1302 bytes --]
--- src.orig/config.sub Sat Feb 10 01:55:46 2001
+++ src.new/config.sub Mon Feb 26 17:57:37 2001
@@ -740,6 +740,12 @@
rtpc | rtpc-*)
basic_machine=romp-ibm
;;
+ s390 | s390-* )
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-* )
+ basic_machine=s390x-ibm
+ ;;
sa29200)
basic_machine=a29k-amd
os=-udi
--- src.orig/gdb/configure.host Thu Feb 8 07:30:23 2001
+++ src.new/gdb/configure.host Mon Feb 26 17:57:37 2001
@@ -18,6 +18,7 @@
m88*) gdb_host_cpu=m88k ;;
powerpc*) gdb_host_cpu=powerpc ;;
sparc64) gdb_host_cpu=sparc ;;
+s390*) gdb_host_cpu=s390 ;;
*) gdb_host_cpu=$host_cpu ;;
esac
@@ -158,5 +159,10 @@
vax-*-bsd*) gdb_host=vaxbsd ;;
vax-*-ultrix2*) gdb_host=vaxult2 ;;
vax-*-ultrix*) gdb_host=vaxult ;;
-
+s390*-*-*) gdb_host=s390 ;;
esac
+
+
+
+
+
--- src.orig/gdb/configure.tgt Thu Feb 8 07:30:23 2001
+++ src.new/gdb/configure.tgt Mon Feb 26 17:57:37 2001
@@ -26,6 +26,7 @@
strongarm*) gdb_target_cpu=arm ;;
xscale*) gdb_target_cpu=arm ;;
v850*) gdb_target_cpu=v850 ;;
+s390*) gdb_target_cpu=s390 ;;
*) gdb_target_cpu=$target_cpu ;;
esac
@@ -305,6 +306,8 @@
z8k-*-coff*) gdb_target=z8k ;;
+s390-*-*) gdb_target=s390 ;;
+s390x-*-*) gdb_target=s390x ;;
esac
[-- Attachment #4: gdb.s390.270201.core.diff --]
[-- Type: text/x-diff, Size: 78499 bytes --]
diff -u -r -N src.orig/gdb/config/s390/nm-linux.h src.new/gdb/config/s390/nm-linux.h
--- src.orig/gdb/config/s390/nm-linux.h Thu Jan 1 01:00:00 1970
+++ src.new/gdb/config/s390/nm-linux.h Mon Feb 26 17:57:49 2001
@@ -0,0 +1,107 @@
+/* Native support for Linux for S390
+
+ Copyright 1986, 1987, 1989, 1992, 1996, 1998, 2000
+ Free Software Foundation, Inc.
+ Ported by D.J. Barrow for IBM Deutschland Entwicklung GmbH, IBM Corporation.
+ derived from i390-nmlinux.h
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef NM_LINUX_H
+#define NM_LINUX_H
+
+#include "config/nm-linux.h"
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ (addr) = s390_register_u_addr((blockend),(regno));
+extern int s390_register_u_addr (int, int);
+
+/* Return sizeof user struct to callers in less machine dependent routines */
+
+#define KERNEL_U_SIZE kernel_u_size()
+extern int kernel_u_size (void);
+
+#define U_REGS_OFFSET 0
+
+
+/* We define this if link.h is available, because with ELF we use SVR4 style
+ shared libraries. */
+
+#ifdef HAVE_LINK_H
+#define SVR4_SHARED_LIBS
+#include "solib.h" /* Support for shared libraries. */
+#endif
+
+
+/* WATCHPOINT SPECIFIC STUFF */
+
+#define TARGET_HAS_HARDWARE_WATCHPOINTS
+#define HAVE_CONTINUABLE_WATCHPOINT
+#define HAVE_STEPPABLE_WATCHPOINT
+#define target_insert_watchpoint(addr, len, type) \
+ s390_insert_watchpoint (inferior_pid, addr, len, type)
+
+#define target_remove_watchpoint(addr, len, type) \
+ s390_remove_watchpoint (inferior_pid, addr, len)
+
+extern int watch_area_cnt;
+/* gdb if really stupid & calls this all the time without a
+ watchpoint even being set */
+#define STOPPED_BY_WATCHPOINT(W) \
+ (watch_area_cnt&&s390_stopped_by_watchpoint (inferior_pid))
+
+extern CORE_ADDR s390_stopped_by_watchpoint (int);
+
+/*
+ Type can be 1 for a read_watchpoint or 2 for an access watchpoint.
+ */
+extern int s390_insert_watchpoint (int pid, CORE_ADDR addr, int len, int rw);
+extern int s390_remove_watchpoint (int pid, CORE_ADDR addr, int len);
+#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \
+ (((type) == bp_hardware_watchpoint)|| \
+ ((type) == bp_watchpoint)|| \
+ ((type) == bp_read_watchpoint) || \
+ ((type) == bp_access_watchpoint))
+
+
+/* FIXME: kettenis/2000-09-03: This should be moved to ../nm-linux.h
+ once we have converted all Linux targets to use the new threads
+ stuff (without the #undef of course). */
+#undef PREPARE_TO_PROCEED
+
+/* Set to 1 if post 5.0 */
+#if 1
+extern int lin_lwp_prepare_to_proceed (void);
+#define PREPARE_TO_PROCEED(select_it) lin_lwp_prepare_to_proceed ()
+#else
+extern int linuxthreads_prepare_to_proceed (int step);
+#define PREPARE_TO_PROCEED(select_it) linuxthreads_prepare_to_proceed (select_it)
+#endif
+
+
+extern void lin_lwp_attach_lwp (int pid, int verbose);
+#define ATTACH_LWP(pid, verbose) lin_lwp_attach_lwp ((pid), (verbose))
+
+#include <signal.h>
+
+extern void lin_thread_get_thread_signals (sigset_t * mask);
+#define GET_THREAD_SIGNALS(mask) lin_thread_get_thread_signals (mask)
+
+/* Needed for s390x */
+#define PTRACE_ARG3_TYPE long
+#define PTRACE_XFER_TYPE long
+#endif /* nm_linux.h */
diff -u -r -N src.orig/gdb/config/s390/s390.mh src.new/gdb/config/s390/s390.mh
--- src.orig/gdb/config/s390/s390.mh Thu Jan 1 01:00:00 1970
+++ src.new/gdb/config/s390/s390.mh Mon Feb 26 17:57:49 2001
@@ -0,0 +1,14 @@
+# Host: S390, running Linux
+
+XM_FILE= xm-linux.h
+XDEPFILES=
+XM_CLIBS=
+
+NAT_FILE= nm-linux.h
+#NATDEPFILES= infptrace.o solib.o inftarg.o fork-child.o corelow.o \
+# s390-nat.o linux-thread.o core-aout.o core-regset.o
+# post 5.0 natdepfiles.
+NATDEPFILES= infptrace.o solib.o inftarg.o fork-child.o corelow.o \
+ s390-nat.o thread-db.o lin-lwp.o proc-service.o \
+ core-aout.o core-regset.o solib-svr4.o
+LOADLIBES = -ldl -rdynamic
diff -u -r -N src.orig/gdb/config/s390/s390.mt src.new/gdb/config/s390/s390.mt
--- src.orig/gdb/config/s390/s390.mt Thu Jan 1 01:00:00 1970
+++ src.new/gdb/config/s390/s390.mt Mon Feb 26 17:57:49 2001
@@ -0,0 +1,4 @@
+# Target: S390 running Linux
+TM_FILE= tm-linux.h
+TDEPFILES=s390-tdep.o
+GDB_MULTI_ARCH=2
diff -u -r -N src.orig/gdb/config/s390/s390x.mt src.new/gdb/config/s390/s390x.mt
--- src.orig/gdb/config/s390/s390x.mt Thu Jan 1 01:00:00 1970
+++ src.new/gdb/config/s390/s390x.mt Mon Feb 26 17:57:49 2001
@@ -0,0 +1,5 @@
+# Target: S390x running Linux
+TM_FILE= tm-linux.h
+MT_CFLAGS= -DCONFIG_ARCH_S390X
+TDEPFILES=s390-tdep.o
+GDB_MULTI_ARCH=2
diff -u -r -N src.orig/gdb/config/s390/tm-linux.h src.new/gdb/config/s390/tm-linux.h
--- src.orig/gdb/config/s390/tm-linux.h Thu Jan 1 01:00:00 1970
+++ src.new/gdb/config/s390/tm-linux.h Mon Feb 26 17:57:49 2001
@@ -0,0 +1,66 @@
+/* Target definitions for GDB for a s390 running Linux.
+ Copyright (C) 1999-2001 Free Software Foundation, Inc.
+ Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ for IBM Deutschland Entwicklung GmbH, IBM Corporation.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifndef TM_LINUX_H
+#define TM_LINUX_H
+#include "config/tm-linux.h"
+#include "s390/tm-s390.h"
+
+
+#define S390_SIGNAL_FRAMESIZE (GDB_TARGET_IS_ESAME ? 160:96)
+#define s390_NR_sigreturn 119
+#define s390_NR_rt_sigreturn 173
+#define S390_SIGCONTEXT_NSIG 64
+#define S390_SIGCONTEXT_NSIG_BPW 32
+/* Size of stack frame allocated when calling signal handler. */
+#define S390_SIGCONTEXT_NSIG_WORDS (S390_SIGCONTEXT_NSIG / S390_SIGCONTEXT_NSIG_BPW)
+
+
+typedef struct
+{
+ __s390_regs_common regs;
+ __s390_fp_regs fpregs;
+}
+s390_sigregs;
+
+typedef struct
+{
+ __u32 oldmask[S390_SIGCONTEXT_NSIG_WORDS];
+ s390_sigregs *sregs;
+}
+s390_sigcontext;
+
+typedef struct
+{
+ __s390x_regs_common regs;
+ __s390_fp_regs fpregs;
+}
+s390x_sigregs;
+
+typedef struct
+{
+ __u32 oldmask[S390_SIGCONTEXT_NSIG_WORDS];
+ s390x_sigregs *sregs;
+}
+s390x_sigcontext;
+
+#endif /* TM_LINUX_H */
diff -u -r -N src.orig/gdb/config/s390/tm-s390.h src.new/gdb/config/s390/tm-s390.h
--- src.orig/gdb/config/s390/tm-s390.h Thu Jan 1 01:00:00 1970
+++ src.new/gdb/config/s390/tm-s390.h Tue Feb 27 16:47:03 2001
@@ -0,0 +1,390 @@
+/* Macro definitions for GDB on an S390.
+ Copyright (C) 1999-2001 Free Software Foundation, Inc.
+ Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ for IBM Deutschland Entwicklung GmbH, IBM Corporation.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#if !defined(TM_S390_H)
+#define TM_S390_H 1
+#include <asm/types.h>
+#if GDB_MULTI_ARCH
+#define GDB_TARGET_IS_ESAME (TARGET_ARCHITECTURE->mach == bfd_mach_s390_esame)
+#else
+#if CONFIG_ARCH_S390X
+#define GDB_TARGET_IS_ESAME (1)
+#else
+#define GDB_TARGET_IS_ESAME (0)
+#endif /* CONFIG_ARCH_S390X */
+#endif /* GDB_MULTI_ARCH */
+
+#if defined(S390_TDEP) && GDB_MULTI_ARCH
+#define S390_REGISTER_SIZE REGISTER_SIZE
+#else
+#if CONFIG_ARCH_S390X
+#define S390_REGISTER_SIZE (8)
+#else
+#define S390_REGISTER_SIZE (4)
+#endif /* CONFIG_ARCH_S390X */
+#endif /* defined(S390_TDEP) && GDB_MULTI_ARCH */
+
+
+#define S390_STACK_FRAME_OVERHEAD (GDB_TARGET_IS_ESAME ? 160:96)
+#define S390_NUM_GPRS (16)
+#define S390_GPR_SIZE S390_REGISTER_SIZE
+#define S390_PSW_MASK_SIZE S390_REGISTER_SIZE
+#define S390_PSW_ADDR_SIZE S390_REGISTER_SIZE
+#define S390_NUM_FPRS (16)
+#define S390_FPR_SIZE (8)
+#define S390_FPC_SIZE (4)
+#define S390_FPC_PAD_SIZE (4) /* gcc insists on aligning the fpregs */
+#define S390_NUM_CRS (16)
+#define S390_CR_SIZE S390_REGISTER_SIZE
+#define S390_NUM_ACRS (16)
+#define S390_ACR_SIZE (4)
+
+#define S390_ACR0_OFFSET ((S390_PSW_MASK_SIZE+S390_PSW_ADDR_SIZE)+(S390_GPR_SIZE*S390_NUM_GPRS))
+#define S390_CR0_OFFSET (S390_ACR0_OFFSET+(S390_ACR_SIZE+S390_NUM_ACRS))
+#define S390_FPC_OFFSET (S390_CR0_OFFSET+(S390_CR_SIZE*S390_NUM_CRS))
+#define S390_FP0_OFFSET (S390_FPC_OFFSET+(S390_FPC_SIZE+S390_FPC_PAD_SIZE))
+#define S390_GPR6_STACK_OFFSET (GDB_TARGET_IS_ESAME ? 48:24)
+
+typedef struct
+{
+ __u32 mask;
+ __u32 addr;
+} s390_psw_t __attribute__ ((aligned (8)));
+
+typedef struct
+{
+ __u64 mask;
+ __u64 addr;
+} s390x_psw_t __attribute__ ((aligned (8)));
+
+
+typedef union
+{
+ struct
+ {
+ __u32 hi;
+ __u32 lo;
+ }
+ fp;
+ __u32 f;
+} s390_freg_t;
+
+typedef struct
+{
+ /* The compiler appears to like aligning freg_t on an 8 byte boundary
+ so I always access fpregs, this was causing fun when I was doing
+ coersions. */
+ __u32 fpc;
+ s390_freg_t fprs[S390_NUM_FPRS];
+} __s390_fp_regs;
+
+/* gdb structures & the kernel have this much always in common */
+#define __S390_REGS_COMMON \
+s390_psw_t psw; \
+__u32 gprs[S390_NUM_GPRS]; \
+__u32 acrs[S390_NUM_ACRS];
+
+#define __S390X_REGS_COMMON \
+s390x_psw_t psw; \
+__u64 gprs[S390_NUM_GPRS]; \
+__u32 acrs[S390_NUM_ACRS];
+
+
+typedef struct
+{
+__S390_REGS_COMMON
+} __s390_regs_common;
+
+typedef struct
+{
+__S390X_REGS_COMMON
+} __s390x_regs_common;
+
+
+
+/* Sequence of bytes for breakpoint illegal instruction. */
+#define S390_BREAKPOINT {0x0,0x1}
+#define S390_BREAKPOINT_U16 ((__u16)0x0001)
+#define S390_SYSCALL_OPCODE ((__u16)0x0a00)
+#define S390_SYSCALL_SIZE 2
+
+#define S390_MAX_INSTR_SIZE 6
+#define S390_NUM_REGS (2+S390_NUM_GPRS+S390_NUM_ACRS+S390_NUM_CRS+1+S390_NUM_FPRS)
+#define S390_FIRST_ACR (2+S390_NUM_GPRS)
+#define S390_LAST_ACR (S390_FIRST_ACR+S390_NUM_ACRS-1)
+#define S390_FIRST_CR (S390_FIRST_ACR+S390_NUM_ACRS)
+#define S390_LAST_CR (S390_FIRST_CR+S390_NUM_CRS-1)
+
+#define S390_PSWM_REGNUM 0
+#define S390_PC_REGNUM 1
+#define S390_GP0_REGNUM 2 /* GPR register 0 */
+#define S390_GP_LAST_REGNUM (S390_GP0_REGNUM+S390_NUM_GPRS-1)
+/* Usually return address */
+#define S390_RETADDR_REGNUM (S390_GP0_REGNUM+14)
+/* Contains address of top of stack */
+#define S390_SP_REGNUM (S390_GP0_REGNUM+15)
+/* needed in findvar.c still */
+#define S390_FP_REGNUM S390_SP_REGNUM
+#define S390_FRAME_REGNUM (S390_GP0_REGNUM+11)
+#define S390_FPC_REGNUM (S390_GP0_REGNUM+S390_NUM_GPRS+S390_NUM_ACRS+S390_NUM_CRS)
+/* FPR (Floating point) register 0 */
+#define S390_FP0_REGNUM (S390_FPC_REGNUM+1)
+/* Last floating point register */
+#define S390_FPLAST_REGNUM (S390_FP0_REGNUM+S390_NUM_FPRS-1)
+#define S390_LAST_REGNUM S390_FPLAST_REGNUM
+
+/* The top of this structure is as similar as possible to a
+ pt_regs structure to simplify code */
+typedef struct
+{
+ __S390_REGS_COMMON
+ __u32 crs[S390_NUM_CRS];
+ __s390_fp_regs fp_regs;
+} s390_gdb_regs __attribute__ ((packed));
+
+typedef struct
+{
+ __S390X_REGS_COMMON
+ __u64 crs[S390_NUM_CRS];
+ __s390_fp_regs fp_regs;
+} s390x_gdb_regs __attribute__ ((packed));
+
+
+#define S390_REGISTER_NAMES \
+{ \
+"pswm","pswa", \
+"gpr0","gpr1","gpr2","gpr3","gpr4","gpr5","gpr6","gpr7", \
+"gpr8","gpr9","gpr10","gpr11","gpr12","gpr13","gpr14","gpr15", \
+"acr0","acr1","acr2","acr3","acr4","acr5","acr6","acr7", \
+"acr8","acr9","acr10","acr11","acr12","acr13","acr14","acr15", \
+"cr0","cr1","cr2","cr3","cr4","cr5","cr6","cr7", \
+"cr8","cr9","cr10","cr11","cr12","cr13","cr14","cr15", \
+"fpc", \
+"fpr0","fpr1","fpr2","fpr3","fpr4","fpr5","fpr6","fpr7", \
+"fpr8","fpr9","fpr10","fpr11","fpr12","fpr13","fpr14","fpr15" \
+}
+
+
+/* instruction sequence for call dummy is as follows
+ bras %r1,.+8 ; 0xA7150004
+ long basraddr ; 0x00000000
+ l %r1,0(%r1) ; 0x58101000
+ basr %r14,%r1 ; 0x0DE1
+ breakpoint ; 0x0001 */
+#define S390_CALL_DUMMY {0xA7150004,0x00000000,0x58101000,0x0DE10000|S390_BREAKPOINT_U16}
+#define S390_CALL_DUMMY_LENGTH 16
+#define S390_CALL_ADDR_OFFSET 4
+
+
+/* instruction sequence for call dummy is as follows
+ bras %r1,.+12 ; 0xA7150006
+ long basraddr ; 0x0000000000000000
+ lg %r1,0(%r1) ; 0xE31010000004
+ basr %r14,%r1 ; 0x0DE1
+ breakpoint ; 0x0001 */
+
+#define S390X_CALL_DUMMY {0xA715000600000000,0x00000000E3101000, \
+0x00040DE100000000|S390_BREAKPOINT_U16<<16}
+#define S390X_CALL_DUMMY_LENGTH 22
+
+#define S390_REGISTER_BYTES \
+((S390_FP0_OFFSET)+(S390_FPR_SIZE*S390_NUM_FPRS))
+
+
+#if !GDB_MULTI_ARCH
+#if CONFIG_ARCH_S390X
+#define CALL_DUMMY S390X_CALL_DUMMY
+#define CALL_DUMMY_LENGTH S390X_CALL_DUMMY_LENGTH
+int s390x_register_raw_size (int reg_nr);
+#define REGISTER_RAW_SIZE(reg_nr) s390x_register_raw_size(reg_nr)
+
+struct type *s390x_register_virtual_type (int regno);
+#define REGISTER_VIRTUAL_TYPE(regno) s390x_register_virtual_type(regno)
+
+#define TARGET_LONG_BIT (8 * TARGET_CHAR_BIT)
+#define TARGET_LONG_LONG_BIT (TARGET_LONG_BIT)
+#define TARGET_PTR_BIT (TARGET_LONG_BIT)
+#else
+#define CALL_DUMMY S390_CALL_DUMMY
+#define CALL_DUMMY_LENGTH S390_CALL_DUMMY_LENGTH
+int s390_register_raw_size (int reg_nr);
+#define REGISTER_RAW_SIZE(reg_nr) s390_register_raw_size(reg_nr)
+
+struct type *s390_register_virtual_type (int regno);
+#define REGISTER_VIRTUAL_TYPE(regno) s390_register_virtual_type(regno)
+#define ADDR_BITS_REMOVE(addr) ((addr)&0x7fffffff)
+
+#endif /* CONFIG_ARCH_S390X */
+#define BELIEVE_PCC_PROMOTION 0
+#define USE_GENERIC_DUMMY_FRAMES 0
+#define CALL_DUMMY_LOCATION ON_STACK
+#define CALL_DUMMY_START_OFFSET 0
+
+#define REGISTER_BYTES S390_REGISTER_BYTES
+#define PC_REGNUM S390_PC_REGNUM
+#define SP_REGNUM S390_SP_REGNUM
+#define FP_REGNUM S390_FP_REGNUM
+#define FP0_REGNUM S390_FP0_REGNUM
+#define NUM_REGS S390_NUM_REGS
+#define NUM_FPRS S390_NUM_FPRS
+#define FP0_OFFSET S390_FP0_OFFSET
+#define FPR_SIZE S390_FPR_SIZE
+#define REGISTER_SIZE S390_REGISTER_SIZE
+
+#define REGISTER_VIRTUAL_SIZE(reg_nr) REGISTER_RAW_SIZE(reg_nr)
+
+#define TARGET_BYTE_ORDER BIG_ENDIAN
+
+/* Used for example in valprint.c:print_floating() to enable checking
+ for NaN's */
+#define IEEE_FLOAT (1)
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+#define FUNCTION_START_OFFSET 0
+
+/* Stack grows downward. */
+#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+#define MAX_REGISTER_RAW_SIZE 8
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+#define BREAKPOINT S390_BREAKPOINT
+/* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+#define DECR_PC_AFTER_BREAK 2
+
+void s390_pop_frame (void);
+#define POP_FRAME s390_pop_frame()
+
+void s390_push_dummy_frame (void);
+#define PUSH_DUMMY_FRAME s390_push_dummy_frame()
+
+struct value;
+
+CORE_ADDR s390_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
+ int struct_return, CORE_ADDR struct_addr);
+#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
+ sp = s390_push_arguments((nargs), (args), (sp), (struct_return), (struct_addr))
+
+int s390_pc_in_call_dummy (CORE_ADDR pc, CORE_ADDR sp,
+ CORE_ADDR frame_address);
+#define PC_IN_CALL_DUMMY(pc, sp, frame_address) \
+s390_pc_in_call_dummy(pc,sp,frame_address)
+
+void s390_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun,
+ int nargs, struct value **args,
+ struct type *value_type, int using_gcc);
+#define FIX_CALL_DUMMY(dummy, pc, fun, nargs, args, value_type, using_gcc) \
+s390_fix_call_dummy(dummy,pc,fun,nargs,args,value_type,using_gcc);
+
+
+void s390_store_struct_return (CORE_ADDR addr, CORE_ADDR sp);
+#define STORE_STRUCT_RETURN(addr,sp) \
+s390_store_struct_return(addr,sp);
+
+/* Return number of bytes at start of arglist that are not really args. */
+#define FRAME_ARGS_SKIP 0
+
+CORE_ADDR s390_skip_prologue (CORE_ADDR pc);
+#define SKIP_PROLOGUE(pc) s390_skip_prologue(pc);
+
+CORE_ADDR s390_frame_args_address (struct frame_info *fi);
+#define FRAME_ARGS_ADDRESS(fi) s390_frame_args_address(fi)
+
+#define FRAME_LOCALS_ADDRESS(fi) FRAME_ARGS_ADDRESS(fi)
+#define FRAME_NUM_ARGS(fi) (-1) /* We can't do this */
+void s390_extract_return_value (struct type *valtype, char *regbuf,
+ char *valbuf);
+#define EXTRACT_RETURN_VALUE(valtype,regbuf,valbuf) \
+ s390_extract_return_value(valtype,regbuf,valbuf)
+
+void s390_store_return_value (struct type *valtype, char *valbuf);
+#define STORE_RETURN_VALUE(valtype,valbuf) \
+ s390_store_return_value(valtype,valbuf)
+
+/* Return saved PC from a frame */
+CORE_ADDR s390_frame_saved_pc (struct frame_info *fi);
+#define FRAME_SAVED_PC(fi) s390_frame_saved_pc(fi)
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer. */
+CORE_ADDR s390_frame_chain (struct frame_info *thisframe);
+#define FRAME_CHAIN(thisframe) s390_frame_chain(thisframe)
+
+/* Immediately after a function call, return the saved pc.
+ Can't go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+CORE_ADDR s390_saved_pc_after_call (struct frame_info *frame);
+#define SAVED_PC_AFTER_CALL(frame) s390_saved_pc_after_call(frame)
+
+void s390_write_fp (CORE_ADDR val);
+#define TARGET_WRITE_FP(val) s390_write_fp(val)
+
+CORE_ADDR s390_read_fp ();
+#define TARGET_READ_FP() s390_read_fp()
+
+void s390_frame_init_saved_regs (struct frame_info *fi);
+#define FRAME_INIT_SAVED_REGS(fi) s390_frame_init_saved_regs(fi);
+
+void s390_init_frame_pc_first (int next_fromleaf, struct frame_info *fi);
+#define INIT_FRAME_PC_FIRST(fromleaf, fi) s390_init_frame_pc_first((fromleaf),(fi))
+
+void s390_init_extra_frame_info (int fromleaf, struct frame_info *fi);
+#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) s390_init_extra_frame_info((fromleaf),(fi))
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+int s390_frameless_function_invocation (struct frame_info *fi);
+#define FRAMELESS_FUNCTION_INVOCATION(fi) \
+ s390_frameless_function_invocation(fi)
+
+/* Obviously ptrace for user program tracing cannot be allowed
+ mess with control registers (except per registers for hardware watchpoints),
+ when we add kernel debugging we may need to alter these macros. */
+int s390_cannot_fetch_register (int regno);
+#define CANNOT_FETCH_REGISTER(regno) s390_cannot_fetch_register(regno)
+#define CANNOT_STORE_REGISTER(regno) s390_cannot_fetch_register(regno)
+
+int s390_register_byte (int reg_nr);
+#define REGISTER_BYTE(reg_nr) s390_register_byte(reg_nr)
+
+
+char *s390_register_name (int reg_nr);
+#define REGISTER_NAME(reg_nr) s390_register_name(reg_nr)
+
+int s390_stab_reg_to_regnum (int regno);
+#define STAB_REG_TO_REGNUM(regno) \
+s390_stab_reg_to_regnum(regno)
+#define DWARF_REG_TO_REGNUM(regno) STAB_REG_TO_REGNUM(regno)
+#define DWARF2_REG_TO_REGNUM(regno) STAB_REG_TO_REGNUM(regno)
+#endif /* !GDB_MULTI_ARCH */
+#endif /* ifndef TM_S390_H */
+
+
+
diff -u -r -N src.orig/gdb/config/s390/xm-linux.h src.new/gdb/config/s390/xm-linux.h
--- src.orig/gdb/config/s390/xm-linux.h Thu Jan 1 01:00:00 1970
+++ src.new/gdb/config/s390/xm-linux.h Mon Feb 26 17:57:49 2001
@@ -0,0 +1,38 @@
+/* Native support for GNU/Linux, for GDB, the GNU debugger.
+ Copyright (C) 1999-2001 Free Software Foundation, Inc.
+ Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ for IBM Deutschland Entwicklung GmbH, IBM Corporation.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifndef XM_LINUX_H
+#define XM_LINUX_H
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+#define KERNEL_U_ADDR 0x0
+
+#define NEED_POSIX_SETPGID
+
+/* Need R_OK etc, but USG isn't defined. */
+#include <unistd.h>
+
+#endif /* #ifndef XM_LINUX_H */
--- /dev/null Tue Jun 1 11:25:19 1999
+++ src.new/gdb/s390-nat.c Tue Feb 27 16:46:54 2001
@@ -0,0 +1,292 @@
+/* S390 native-dependent code for GDB, the GNU debugger.
+ Copyright 1999-2001 Free Software Foundation, Inc
+ Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ for IBM Deutschland Entwicklung GmbH, IBM Corporation.
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#include "defs.h"
+#include "tm.h"
+#include <asm/ptrace.h>
+#include <sys/ptrace.h>
+#include <asm/processor.h>
+#include <sys/procfs.h>
+#include <sys/user.h>
+#include <value.h>
+
+int
+s390_register_u_addr (int blockend, int regnum)
+{
+ int retval;
+
+ if (regnum >= S390_GP0_REGNUM && regnum <= S390_GP_LAST_REGNUM)
+ retval = PT_GPR0 + ((regnum - S390_GP0_REGNUM) * S390_GPR_SIZE);
+ else if (regnum >= S390_PSWM_REGNUM && regnum <= S390_PC_REGNUM)
+ retval = PT_PSWMASK + ((regnum - S390_PSWM_REGNUM) * S390_PSW_MASK_SIZE);
+ else if (regnum == S390_FPC_REGNUM)
+ retval = PT_FPC;
+ else if (regnum >= S390_FP0_REGNUM && regnum <= S390_FPLAST_REGNUM)
+ retval =
+#if CONFIG_ARCH_S390X
+ PT_FPR0
+#else
+ PT_FPR0_HI
+#endif
+ + ((regnum - S390_FP0_REGNUM) * S390_FPR_SIZE);
+ else if (regnum >= S390_FIRST_ACR && regnum <= S390_LAST_ACR)
+ retval = PT_ACR0 + ((regnum - S390_FIRST_ACR) * S390_ACR_SIZE);
+ else if (regnum >= (S390_FIRST_CR + 9) && regnum <= (S390_FIRST_CR + 11))
+ retval = PT_CR_9 + ((regnum - (S390_FIRST_CR + 9)) * S390_CR_SIZE);
+ else
+ {
+ error ("s390_register_u_addr invalid regnum %s %d regnum=%d", __FILE__,
+ (int)__LINE__, regnum);
+ retval = 0;
+ }
+ return retval + blockend;
+}
+
+/* watch_areas are required if you put 2 or more watchpoints on the same
+ address or overlapping areas gdb will call us to delete the watchpoint
+ more than once when we try to delete them.
+ attempted reference counting to reduce the number of areas unfortunately
+ they didn't shrink when areas had to be split overlapping occurs. */
+struct watch_area;
+typedef struct watch_area watch_area;
+struct watch_area
+{
+ watch_area *next;
+ CORE_ADDR lo_addr;
+ CORE_ADDR hi_addr;
+};
+
+static watch_area *watch_base = NULL;
+int watch_area_cnt = 0;
+static CORE_ADDR watch_lo_addr = 0, watch_hi_addr = 0;
+
+
+
+CORE_ADDR s390_stopped_by_watchpoint (int pid)
+{
+ per_lowcore_bits per_lowcore;
+ ptrace_area parea;
+
+ parea.len = sizeof (per_lowcore);
+ parea.process_addr = (addr_t) & per_lowcore;
+ parea.kernel_addr = pt_off (per_info.lowcore);
+ ptrace (PTRACE_PEEKUSR_AREA, pid, &parea);
+ return ((per_lowcore.perc_storage_alteration == 1) &&
+ (per_lowcore.perc_store_real_address == 0));
+}
+
+
+void
+s390_fix_watch_points (int pid)
+{
+ per_struct per_info;
+ ptrace_area parea;
+
+ parea.len = sizeof (per_info);
+ parea.process_addr = (addr_t) & per_info;
+ parea.kernel_addr = PT_CR_9;
+ ptrace (PTRACE_PEEKUSR_AREA, pid, &parea);
+ /* The kernel automatically sets the psw for per depending */
+ /* on whether the per control registers are set for event recording */
+ /* & sets cr9 & cr10 appropriately also */
+ if (watch_area_cnt)
+ {
+ per_info.control_regs.bits.em_storage_alteration = 1;
+ per_info.control_regs.bits.storage_alt_space_ctl = 1;
+ }
+ else
+ {
+ per_info.control_regs.bits.em_storage_alteration = 0;
+ per_info.control_regs.bits.storage_alt_space_ctl = 0;
+ }
+ per_info.starting_addr = watch_lo_addr;
+ per_info.ending_addr = watch_hi_addr;
+ ptrace (PTRACE_POKEUSR_AREA, pid, &parea);
+}
+
+int
+s390_insert_watchpoint (int pid, CORE_ADDR addr, int len, int rw)
+{
+ CORE_ADDR hi_addr = addr + len - 1;
+ watch_area *newArea = (watch_area *) malloc (sizeof (watch_area));
+
+
+ if (newArea)
+ {
+ newArea->next = watch_base;
+ watch_base = newArea;
+ watch_lo_addr = min (watch_lo_addr, addr);
+ watch_hi_addr = max (watch_hi_addr, hi_addr);
+ newArea->lo_addr = addr;
+ newArea->hi_addr = hi_addr;
+ if (watch_area_cnt == 0)
+ {
+ watch_lo_addr = newArea->lo_addr;
+ watch_hi_addr = newArea->hi_addr;
+ }
+ watch_area_cnt++;
+ s390_fix_watch_points (pid);
+ }
+ return newArea ? 0 : -1 ;
+}
+
+
+int
+s390_remove_watchpoint (int pid, CORE_ADDR addr, int len)
+{
+ watch_area *curr = watch_base, *prev, *matchCurr;
+ CORE_ADDR hi_addr = addr + len - 1;
+ CORE_ADDR watch_second_lo_addr = 0xffffffffUL, watch_second_hi_addr = 0;
+ int lo_addr_ref_cnt, hi_addr_ref_cnt;
+ prev = matchCurr = NULL;
+ lo_addr_ref_cnt = (addr == watch_lo_addr);
+ hi_addr_ref_cnt = (addr == watch_hi_addr);
+ while (curr)
+ {
+ if (matchCurr == NULL)
+ {
+ if (curr->lo_addr == addr && curr->hi_addr == hi_addr)
+ {
+ matchCurr = curr;
+ if (prev)
+ prev->next = curr->next;
+ else
+ watch_base = curr->next;
+ }
+ prev = curr;
+ }
+ if (lo_addr_ref_cnt)
+ {
+ if (watch_lo_addr == curr->lo_addr)
+ lo_addr_ref_cnt++;
+ if (curr->lo_addr > watch_lo_addr &&
+ curr->lo_addr < watch_second_lo_addr)
+ watch_second_lo_addr = curr->lo_addr;
+ }
+ if (hi_addr_ref_cnt)
+ {
+ if (watch_hi_addr == curr->hi_addr)
+ hi_addr_ref_cnt++;
+ if (curr->hi_addr < watch_hi_addr &&
+ curr->hi_addr > watch_second_hi_addr)
+ watch_second_hi_addr = curr->hi_addr;
+ }
+ curr = curr->next;
+ }
+ if (matchCurr)
+ {
+ free (matchCurr);
+ watch_area_cnt--;
+ if (watch_area_cnt)
+ {
+ if (lo_addr_ref_cnt == 2)
+ watch_lo_addr = watch_second_lo_addr;
+ if (hi_addr_ref_cnt == 2)
+ watch_hi_addr = watch_second_hi_addr;
+ }
+ else
+ {
+ watch_lo_addr = watch_hi_addr = 0;
+ }
+ s390_fix_watch_points (pid);
+ return 0;
+ }
+ else
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Attempt to remove nonexistent watchpoint in s390_remove_watchpoint\n");
+ return -1;
+ }
+}
+
+int
+kernel_u_size (void)
+{
+ return sizeof(struct user);
+}
+
+
+#if (defined (S390_FP0_REGNUM) && defined (HAVE_FPREGSET_T) && defined(HAVE_SYS_PROCFS_H) && defined (HAVE_GREGSET_T))
+void
+supply_gregset (gregset_t * gregsetp)
+{
+ int regi;
+ s390_regs_common *s390regs = (s390_regs_common *) gregsetp;
+
+ for (regi = 0; regi < S390_NUM_GPRS; regi++)
+ supply_register (S390_GP0_REGNUM + regi, (char *) &s390regs->gprs[regi]);
+ supply_register (S390_PSWM_REGNUM, (char *) &s390regs->psw.mask);
+ supply_register (S390_PC_REGNUM, (char *) &s390regs->psw.addr);
+ for (regi = 0; regi < S390_NUM_ACRS; regi++)
+ supply_register (S390_FIRST_ACR + regi, (char *) &s390regs->acrs[regi]);
+ /* unfortunately this isn't in gregsetp */
+ for (regi = 0; regi < S390_NUM_CRS; regi++)
+ supply_register (S390_FIRST_CR + regi, NULL);
+}
+
+
+void
+supply_fpregset (fpregset_t * fpregsetp)
+{
+ int regi;
+
+ supply_register (S390_FPC_REGNUM, (char *) &fpregsetp->fpc);
+ for (regi = 0; regi < S390_NUM_FPRS; regi++)
+ supply_register (S390_FP0_REGNUM + regi, (char *) &fpregsetp->fprs[regi]);
+
+}
+
+void
+fill_gregset (gregset_t * gregsetp, int regno)
+{
+ if (regno >= S390_FIRST_CR && regno <= S390_LAST_CR)
+ memset (&((__u8 *) gregsetp)[REGISTER_BYTE (regno)], 0,
+ REGISTER_RAW_SIZE (regno));
+ if (regno != -1)
+ supply_register (regno, &((__u8 *) gregsetp)[REGISTER_BYTE (regno)]);
+ else
+ supply_gregset (gregsetp);
+}
+
+/* Given a pointer to a floating point register set in /proc format
+ (fpregset_t *), update the register specified by REGNO from gdb's idea
+ of the current floating point register set. If REGNO is -1, update
+ them all. */
+
+void
+fill_fpregset (fpregset_t * fpregsetp, int regno)
+{
+ if (regno == -1)
+ supply_fpregset (fpregsetp);
+ else
+ supply_register (regno,
+ &((__u8 *) fpregsetp)[REGISTER_BYTE (regno) -
+ REGISTER_BYTE (S390_FPC_REGNUM)]);
+}
+
+
+#else
+#error "There are a few possibilities here"
+#error "1) You aren't compiling for linux & don't need a core dumps to work."
+#error "2) The header files sys/elf.h sys/user.h sys/ptrace.h & sys/procfs.h"
+#error "libc files are inconsistent with linux/include/asm-s390/"
+#error "3) you didn't do a completely clean build & delete config.cache."
+#endif
--- /dev/null Tue Jun 1 11:25:19 1999
+++ src.new/gdb/s390-tdep.c Tue Feb 27 15:10:47 2001
@@ -0,0 +1,1308 @@
+/* Target-dependent code for GDB, the GNU debugger.
+ Copyright 1999 Free Software Foundation, Inc.
+ Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ for IBM Deutschland Entwicklung GmbH, IBM Corporation.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#define S390_TDEP /* for special macros in tm-s390.h */
+#include <defs.h>
+#include "arch-utils.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "gdbcmd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "tm.h"
+#include "../bfd/bfd.h"
+#include "floatformat.h"
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#undef offsetof
+#define offsetof(type, member) ((CORE_ADDR) & ((type*)0) -> member )
+
+#define s390_offsetof(esame_type,esa_type,member) \
+(GDB_TARGET_IS_ESAME ? offsetof(esame_type,member) : offsetof(esa_type,member))
+
+#define s390_sizeof(esame_type,esa_type) \
+(GDB_TARGET_IS_ESAME ? sizeof(esame_type) : sizeof(esa_type))
+
+#define SIZEOF_S390_GDB_REGS s390_sizeof(s390x_gdb_regs,s390_gdb_regs)
+
+
+struct frame_extra_info
+{
+ int initialised;
+ int good_prologue;
+ CORE_ADDR function_start;
+ CORE_ADDR skip_prologue_function_start;
+ CORE_ADDR saved_pc_valid;
+ CORE_ADDR saved_pc;
+ CORE_ADDR sig_fixed_saved_pc_valid;
+ CORE_ADDR sig_fixed_saved_pc;
+ __u32 stack_bought; /* amount we decrement the stack pointer by */
+ int has_frame_pointer; /* frame pointer needed for alloca */
+};
+
+
+static CORE_ADDR s390_frame_saved_pc_nofix (struct frame_info *fi);
+
+int
+s390_readinstruction (__u8 instr[], CORE_ADDR at,
+ struct disassemble_info *info)
+{
+ int instrlen;
+
+ static int s390_instrlen[] = {
+ 2,
+ 4,
+ 4,
+ 6
+ };
+ if ((*info->read_memory_func) (at, &instr[0], 2, info))
+ return -1;
+ instrlen = s390_instrlen[instr[0] >> 6];
+ if ((*info->read_memory_func) (at + 2, &instr[2], instrlen - 2, info))
+ return -1;
+ return instrlen;
+}
+
+static void
+s390_memset_extra_info (struct frame_extra_info *fextra_info)
+{
+ memset (fextra_info, 0, sizeof (struct frame_extra_info));
+}
+
+
+
+char *
+s390_register_name (int reg_nr)
+{
+ static char *register_names[] = S390_REGISTER_NAMES;
+
+ if (reg_nr >= S390_LAST_REGNUM)
+ return NULL;
+ return register_names[reg_nr];
+}
+
+
+
+int
+s390_cannot_fetch_register (int regno)
+{
+ return (regno >= S390_FIRST_CR && regno < (S390_FIRST_CR + 9)) ||
+ (regno >= (S390_FIRST_CR + 12) && regno <= S390_LAST_CR);
+}
+
+int
+s390_stab_reg_to_regnum (int regno)
+{
+ return regno >= 64 ? S390_PSWM_REGNUM - 64 :
+ regno >= 48 ? S390_FIRST_ACR - 48 :
+ regno >= 32 ? S390_FIRST_CR - 32 :
+ regno <= 15 ? (regno + 2) :
+ S390_FP0_REGNUM + ((regno - 16) & 8) + (((regno - 16) & 3) << 1) +
+ (((regno - 16) & 4) >> 2);
+}
+
+
+
+/* s390_get_frame_info based on Hartmuts
+ prologue definition in
+ gcc-2.8.1/config/l390/linux.c
+
+ It reads one instruction at a time & based on whether
+ it looks like prologue code or not it makes a decision on
+ whether the prologue is over, there are various state machines
+ in the code to determine if the prologue code is possilby valid.
+
+ This is done to hopefully allow the code survive minor revs of
+ calling conventions.
+
+ fextra_info must be already set up to come in with saved_regs not NULL */
+
+int
+s390_get_frame_info (CORE_ADDR pc, struct frame_extra_info *fextra_info,
+ struct frame_info *fi, int init_extra_info)
+{
+#define CONST_POOL_REGIDX 13
+#define GOT_REGIDX 12
+ __u8 instr[S390_MAX_INSTR_SIZE];
+ CORE_ADDR test_pc = pc, test_pc2;
+ CORE_ADDR orig_sp = 0, save_reg_addr = 0, *saved_regs = NULL;
+ int valid_prologue, good_prologue = FALSE;
+ int gprs_saved[S390_NUM_GPRS];
+ int fprs_saved[S390_NUM_FPRS];
+ int regidx, instrlen;
+ int save_link_regidx, subtract_sp_regidx;
+ int const_pool_state, save_link_state, got_state;
+ int frame_pointer_found, varargs_state;
+ int loop_cnt, gdb_gpr_store, gdb_fpr_store;
+ int frame_pointer_regidx = 0xf;
+ int offset, expected_offset;
+ int err = 0;
+ disassemble_info info;
+ const_pool_state = save_link_state = got_state = varargs_state = 0;
+ frame_pointer_found = FALSE;
+ memset (gprs_saved, 0, sizeof (gprs_saved));
+ memset (fprs_saved, 0, sizeof (fprs_saved));
+ info.read_memory_func = dis_asm_read_memory;
+
+ save_link_regidx = subtract_sp_regidx = 0;
+ if (fi)
+ {
+ saved_regs = fi->saved_regs;
+ orig_sp = fi->frame + fextra_info->stack_bought;
+ }
+ if (fextra_info)
+ {
+ if (init_extra_info || fextra_info->initialised == FALSE)
+ {
+ s390_memset_extra_info (fextra_info);
+ fextra_info->function_start = pc;
+ fextra_info->initialised = TRUE;
+ }
+ }
+ instrlen = 0;
+ do
+ {
+ valid_prologue = FALSE;
+ test_pc += instrlen;
+ /* add the previous instruction len */
+ instrlen = s390_readinstruction (instr, test_pc, &info);
+ if (instrlen < 0)
+ {
+ good_prologue = FALSE;
+ err = -1;
+ break;
+ }
+ if (save_link_state == 0)
+ {
+ /* check for a stack relative STMG or STM */
+ if (((GDB_TARGET_IS_ESAME &&
+ ((instr[0] == 0xeb) && (instr[5] == 0x24))) ||
+ (instr[0] == 0x90)) && ((instr[2] >> 4) == 0xf))
+ {
+ regidx = (instr[1] >> 4);
+ if (regidx < 6)
+ varargs_state = 1;
+ offset = ((*((__u16 *) & instr[2])) & 0xfff);
+ expected_offset =
+ S390_GPR6_STACK_OFFSET + (S390_GPR_SIZE * (regidx - 6));
+ if (offset != expected_offset)
+ {
+ good_prologue = FALSE;
+ break;
+ }
+ if (saved_regs)
+ save_reg_addr = orig_sp + offset;
+ for (; regidx <= (instr[1] & 0xf); regidx++)
+ {
+ if (gprs_saved[regidx])
+ {
+ good_prologue = FALSE;
+ break;
+ }
+ good_prologue = TRUE;
+ gprs_saved[regidx] = TRUE;
+ if (saved_regs)
+ {
+ saved_regs[S390_GP0_REGNUM + regidx] = save_reg_addr;
+ save_reg_addr += S390_GPR_SIZE;
+ }
+ }
+ valid_prologue = TRUE;
+ continue;
+ }
+ }
+ /* check for a stack relative STG or ST */
+ if ((save_link_state == 0 || save_link_state == 3) &&
+ ((GDB_TARGET_IS_ESAME &&
+ ((instr[0] == 0xe3) && (instr[5] == 0x24))) ||
+ (instr[0] == 0x50)) && ((instr[2] >> 4) == 0xf))
+ {
+ regidx = instr[1] >> 4;
+ offset = ((*((__u16 *) & instr[2])) & 0xfff);
+ if (offset == 0)
+ {
+ if (save_link_state == 3 && regidx == save_link_regidx)
+ {
+ save_link_state = 4;
+ valid_prologue = TRUE;
+ continue;
+ }
+ else
+ break;
+ }
+ if (regidx < 6)
+ varargs_state = 1;
+ expected_offset =
+ S390_GPR6_STACK_OFFSET + (S390_GPR_SIZE * (regidx - 6));
+ if (offset != expected_offset)
+ {
+ good_prologue = FALSE;
+ break;
+ }
+ if (gprs_saved[regidx])
+ {
+ good_prologue = FALSE;
+ break;
+ }
+ good_prologue = TRUE;
+ gprs_saved[regidx] = TRUE;
+ if (saved_regs)
+ {
+ save_reg_addr = orig_sp + offset;
+ saved_regs[S390_GP0_REGNUM + regidx] = save_reg_addr;
+ }
+ valid_prologue = TRUE;
+ continue;
+ }
+
+ /* check for STD */
+ if (instr[0] == 0x60 && (instr[2] >> 4) == 0xf)
+ {
+ regidx = instr[1] >> 4;
+ if (regidx == 0 || regidx == 2)
+ varargs_state = 1;
+ if (fprs_saved[regidx])
+ {
+ good_prologue = FALSE;
+ break;
+ }
+ fprs_saved[regidx] = TRUE;
+ if (saved_regs)
+ {
+ save_reg_addr = orig_sp + ((*((__u16 *) & instr[2])) & 0xfff);
+ saved_regs[S390_FP0_REGNUM + regidx] = save_reg_addr;
+ }
+ valid_prologue = TRUE;
+ continue;
+ }
+
+
+ if (const_pool_state == 0)
+ {
+ /* Check for BASR gpr13,gpr0 used to load constant pool pointer to r13 in old compiler */
+ if (GDB_TARGET_IS_ESAME && instr[0] == 0xd && (instr[1] & 0xf) == 0
+ && ((instr[1] >> 4) == CONST_POOL_REGIDX))
+ {
+ const_pool_state = 1;
+ valid_prologue = TRUE;
+ continue;
+ }
+ /* Check for new fangled bras %r13,newpc to load new constant pool */
+ /* embedded in code */
+ if ((instr[0] == 0xa7) && ((instr[1] & 0xf) == 0x5) &&
+ ((instr[1] >> 4) == CONST_POOL_REGIDX)
+ && ((instr[2] & 0x80) == 0))
+ {
+ const_pool_state = 2;
+ test_pc += ((*((__u16 *) & instr[2]) << 1) - instrlen);
+ valid_prologue = TRUE;
+ continue;
+ }
+ }
+ /* Check for AGHI or AHI CONST_POOL_REGIDX,val */
+ if (const_pool_state == 1 && (instr[0] == 0xa7) &&
+ ((GDB_TARGET_IS_ESAME &&
+ (instr[1] == ((CONST_POOL_REGIDX << 4) | 0xb))) ||
+ (instr[1] == ((CONST_POOL_REGIDX << 4) | 0xa))))
+ {
+ const_pool_state = 2;
+ valid_prologue = TRUE;
+ continue;
+ }
+ /* Check for LGR or LR gprx,15 */
+ if ((GDB_TARGET_IS_ESAME &&
+ instr[0] == 0xb9 && instr[1] == 0x04 && (instr[3] & 0xf) == 0xf) ||
+ (instr[0] == 0x18 && (instr[1] & 0xf) == 0xf))
+ {
+ if (GDB_TARGET_IS_ESAME)
+ regidx = instr[3] >> 4;
+ else
+ regidx = instr[1] >> 4;
+ if (save_link_state == 0 && regidx != 0xb)
+ {
+ /* Almost defintely code for
+ decrementing the stack pointer
+ ( i.e. a non leaf function
+ or else leaf with locals ) */
+ save_link_regidx = regidx;
+ save_link_state = 1;
+ valid_prologue = TRUE;
+ continue;
+ }
+ /* We use this frame pointer for alloca
+ unfortunately we need to assume its gpr11
+ otherwise we would need a smarter prologue
+ walker. */
+ if (frame_pointer_found == FALSE && regidx == 0xb)
+ {
+ frame_pointer_regidx = 0xb;
+ frame_pointer_found = TRUE;
+ if (fextra_info)
+ fextra_info->has_frame_pointer = TRUE;
+ valid_prologue = TRUE;
+ continue;
+ }
+ }
+ /* Check for AHI or AGHI gpr15,val */
+ if (save_link_state == 1 && (instr[0] == 0xa7) &&
+ ((GDB_TARGET_IS_ESAME && (instr[1] == 0xfb)) || (instr[1] == 0xfa)))
+ {
+ if (fextra_info)
+ fextra_info->stack_bought = -(*((__s16 *) & instr[2]));
+ save_link_state = 3;
+ valid_prologue = TRUE;
+ continue;
+ }
+ /* Alternatively check for the complex construction for
+ buying more than 32k of stack
+ BRAS gprx,.+8
+ long vals %r15,0(%gprx) gprx currently r1 */
+ if ((save_link_state == 1) && (instr[0] == 0xa7)
+ && ((instr[1] & 0xf) == 0x5) && (*((__u16 *) & instr[2]) == 0x4)
+ && ((instr[1] >> 4) != CONST_POOL_REGIDX))
+ {
+ subtract_sp_regidx = instr[1] >> 4;
+ save_link_state = 2;
+ if (fextra_info)
+ target_read_memory (test_pc + instrlen,
+ (char *) &fextra_info->stack_bought,
+ sizeof (fextra_info->stack_bought));
+ test_pc += 4;
+ valid_prologue = TRUE;
+ continue;
+ }
+ if (save_link_state == 2 && (*((__u16 *) & instr[0]) == 0x5bf0) &&
+ (*((__u16 *) & instr[2]) == subtract_sp_regidx << 12))
+ {
+ save_link_state = 3;
+ valid_prologue = TRUE;
+ continue;
+ }
+ /* check for LA gprx,offset(15) used for varargs */
+ if (varargs_state == 1 &&
+ instr[0] == 0x41 && ((instr[1] & 0xf) == 0)
+ && ((instr[2] >> 4) == 0xf))
+ {
+ varargs_state = 2;
+ valid_prologue = TRUE;
+ continue;
+ }
+ /*
+ Check for a GOT load
+ we might be able to get info like whether we
+ are compiled -fpic to check whether this is valid
+ prologue */
+ if (got_state == 0 && const_pool_state == 2 && instr[0] == 0x58
+ && (instr[2] == (CONST_POOL_REGIDX << 4))
+ && ((instr[1] >> 4) == GOT_REGIDX))
+ {
+ got_state == 1;
+ valid_prologue = TRUE;
+ continue;
+ }
+ /* Check for subsequent ar got_regidx,basr_regidx */
+ if (got_state == 1 && instr[0] == 0x1a &&
+ instr[1] == ((GOT_REGIDX << 4) | CONST_POOL_REGIDX))
+ {
+ got_state = 2;
+ valid_prologue = TRUE;
+ continue;
+ }
+ }
+ while (valid_prologue && good_prologue);
+ if (good_prologue == TRUE)
+ {
+ good_prologue = (((got_state == 0) || (got_state == 2)) &&
+ ((const_pool_state == 0) || (const_pool_state == 2)) &&
+ ((save_link_state == 0) || (save_link_state == 4)) &&
+ ((varargs_state == 0) || (varargs_state == 2)));
+ }
+ if (fextra_info)
+ {
+ fextra_info->good_prologue = good_prologue;
+ fextra_info->skip_prologue_function_start =
+ (good_prologue ? test_pc : pc);
+ }
+ return err;
+}
+
+
+static CORE_ADDR
+s390_sniff_pc_function_start (CORE_ADDR pc)
+{
+ CORE_ADDR function_start, test_function_start, ret_function_start, loop_dec;
+ int loop_cnt, err;
+ struct frame_extra_info fextra_info;
+ function_start = get_pc_function_start (pc);
+
+ if (function_start == 0)
+ {
+ test_function_start = pc;
+ if (test_function_start & 1)
+ loop_dec = 1; /* This is a suspicious address */
+ else
+ loop_dec = 2;
+ loop_cnt = 0;
+ do
+ {
+ err =
+ s390_get_frame_info (test_function_start, &fextra_info, NULL,
+ TRUE);
+ loop_cnt++;
+ test_function_start -= loop_dec;
+ }
+ while (err == 0 && loop_cnt < 4096
+ && fextra_info.good_prologue == FALSE);
+ if (fextra_info.good_prologue)
+ function_start = fextra_info.function_start;
+ }
+ return function_start;
+}
+
+
+
+CORE_ADDR s390_function_start (struct frame_info * fi)
+{
+ CORE_ADDR function_start = 0;
+
+ if (fi->extra_info && fi->extra_info->initialised)
+ function_start = fi->extra_info->function_start;
+ else if (fi->pc)
+ function_start = get_pc_function_start (fi->pc);
+ return function_start;
+}
+
+
+
+
+int
+s390_frameless_function_invocation (struct frame_info *fi)
+{
+ struct frame_extra_info fextra_info, *fextra_info_ptr;
+ int frameless = 0;
+
+ if (fi->next == NULL) /* no may be frameless */
+ {
+ if (fi->extra_info)
+ fextra_info_ptr = fi->extra_info;
+ else
+ {
+ fextra_info_ptr = &fextra_info;
+ s390_get_frame_info (s390_sniff_pc_function_start (fi->pc),
+ fextra_info_ptr, NULL, TRUE);
+ }
+ frameless = ((fextra_info_ptr->good_prologue)
+ && (fextra_info_ptr->stack_bought == 0));
+ }
+ return frameless;
+
+}
+
+
+static int
+s390_is_sigreturn (CORE_ADDR pc, struct frame_info *sighandler_fi,
+ CORE_ADDR * sregs, CORE_ADDR * sigcaller_pc)
+{
+ __u8 instr[S390_MAX_INSTR_SIZE];
+ disassemble_info info;
+ int instrlen;
+ CORE_ADDR scontext;
+ int retval = FALSE;
+ CORE_ADDR orig_sp;
+ CORE_ADDR temp_sregs;
+
+ scontext = temp_sregs = 0;
+
+ info.read_memory_func = dis_asm_read_memory;
+ instrlen = s390_readinstruction (instr, pc, &info);
+ if (sigcaller_pc)
+ *sigcaller_pc = 0;
+ if ((instrlen == S390_SYSCALL_SIZE) &&
+ ((((S390_SYSCALL_OPCODE | s390_NR_sigreturn)) == *(__u16 *) instr) ||
+ (((S390_SYSCALL_OPCODE | s390_NR_rt_sigreturn)) == *(__u16 *) instr)))
+ {
+ if (sighandler_fi)
+ {
+ if (s390_frameless_function_invocation (sighandler_fi))
+ orig_sp = sighandler_fi->frame;
+ else
+ orig_sp = ADDR_BITS_REMOVE ((CORE_ADDR)
+ read_memory_integer (sighandler_fi->frame,
+ S390_GPR_SIZE));
+ if (orig_sp && sigcaller_pc)
+ {
+ scontext = orig_sp + S390_SIGNAL_FRAMESIZE;
+ temp_sregs = ADDR_BITS_REMOVE((CORE_ADDR)
+ read_memory_integer (scontext +
+ s390_offsetof(s390x_sigcontext,s390_sigcontext,sregs),
+ S390_GPR_SIZE));
+ *sigcaller_pc =
+ ADDR_BITS_REMOVE ((CORE_ADDR)
+ read_memory_integer (temp_sregs +
+ s390_offsetof(s390x_sigregs,s390_sigregs,regs.psw.addr),
+ S390_PSW_ADDR_SIZE));
+ }
+ }
+ retval = TRUE;
+ }
+ if (sregs)
+ *sregs = temp_sregs;
+ return retval;
+}
+
+/*
+ We need to do something better here but this will keep us out of trouble
+ for the moment.
+ For some reason the blockframe.c calls us with fi->next->fromleaf
+ so this seems of little use to us. */
+void
+s390_init_frame_pc_first (int next_fromleaf, struct frame_info *fi)
+{
+ CORE_ADDR sigcaller_pc;
+
+ fi->pc = 0;
+ if (next_fromleaf)
+ {
+ fi->pc = ADDR_BITS_REMOVE (read_register (S390_RETADDR_REGNUM));
+ /* fix signal handlers */
+ }
+ else if (fi->next && fi->next->pc)
+ fi->pc = s390_frame_saved_pc_nofix (fi->next);
+ if (fi->pc && fi->next && fi->next->frame &&
+ s390_is_sigreturn (fi->pc, fi->next, NULL, &sigcaller_pc))
+ {
+ fi->pc = sigcaller_pc;
+ }
+
+}
+
+void
+s390_init_extra_frame_info (int fromleaf, struct frame_info *fi)
+{
+ fi->extra_info = frame_obstack_alloc (sizeof (struct frame_extra_info));
+ if (fi->pc)
+ s390_get_frame_info (s390_sniff_pc_function_start (fi->pc),
+ fi->extra_info, NULL, TRUE);
+ else
+ s390_memset_extra_info (fi->extra_info);
+}
+
+/* If saved registers of frame FI are not known yet, read and cache them.
+ &FEXTRA_INFOP contains struct frame_extra_info; TDATAP can be NULL,
+ in which case the framedata are read. */
+
+void
+s390_frame_init_saved_regs (struct frame_info *fi)
+{
+
+ if (fi->saved_regs == NULL)
+ {
+
+ frame_saved_regs_zalloc (fi);
+ if (fi->extra_info)
+ {
+ if (!fi->extra_info->initialised && fi->pc)
+ s390_get_frame_info (s390_sniff_pc_function_start (fi->pc),
+ fi->extra_info, fi, TRUE);
+ if (fi->extra_info->good_prologue)
+ s390_get_frame_info (fi->extra_info->function_start,
+ fi->extra_info, fi, FALSE);
+ }
+ }
+}
+
+
+
+CORE_ADDR s390_frame_args_address (struct frame_info *fi)
+{
+
+ /* Apparently gdb already knows gdb_args_offset itself */
+ return fi->frame;
+}
+
+
+static CORE_ADDR
+s390_frame_saved_pc_nofix (struct frame_info *fi)
+{
+ if (fi->extra_info && fi->extra_info->saved_pc_valid)
+ return fi->extra_info->saved_pc;
+ s390_frame_init_saved_regs (fi);
+ if (fi->extra_info)
+ {
+ fi->extra_info->saved_pc_valid = TRUE;
+ if (fi->extra_info->good_prologue)
+ {
+ return (fi->extra_info->saved_pc =
+ ADDR_BITS_REMOVE(read_memory_integer(fi->saved_regs[S390_RETADDR_REGNUM],
+ S390_GPR_SIZE)));
+ }
+ }
+ return 0;
+}
+
+CORE_ADDR s390_frame_saved_pc (struct frame_info * fi)
+{
+ CORE_ADDR saved_pc = 0, sig_pc;
+
+ if (fi->extra_info && fi->extra_info->sig_fixed_saved_pc_valid)
+ return fi->extra_info->sig_fixed_saved_pc;
+ saved_pc = s390_frame_saved_pc_nofix (fi);
+
+ if (fi->extra_info)
+ {
+ fi->extra_info->sig_fixed_saved_pc_valid = TRUE;
+ if (saved_pc)
+ {
+ if (s390_is_sigreturn (saved_pc, fi, NULL, &sig_pc))
+ saved_pc = sig_pc;
+ }
+ fi->extra_info->sig_fixed_saved_pc = saved_pc;
+ }
+ return saved_pc;
+}
+
+
+
+
+/* We want backtraces out of signal handlers so we don't
+ set thisframe->signal_handler_caller to 1 */
+
+CORE_ADDR s390_frame_chain (struct frame_info * thisframe)
+{
+
+ CORE_ADDR prev_fp = 0;
+ struct frame_extra_info fextra_info;
+ CORE_ADDR saved_pc, sig_pc;
+ int regno;
+ CORE_ADDR sregs;
+ int sigreturn;
+
+ if (thisframe->prev && thisframe->prev->frame)
+ prev_fp = thisframe->prev->frame;
+ else
+ {
+ /* We have to do some work */
+ if (!thisframe->pc)
+ return 0;
+ saved_pc = s390_frame_saved_pc_nofix (thisframe);
+ if (!saved_pc)
+ return 0;
+ if (
+ (sigreturn =
+ s390_is_sigreturn (saved_pc, thisframe, &sregs, &sig_pc)))
+ saved_pc = sig_pc;
+ s390_get_frame_info (s390_sniff_pc_function_start (saved_pc),
+ &fextra_info, NULL, TRUE);
+ if (!fextra_info.good_prologue)
+ return 0;
+ if (sigreturn)
+ prev_fp =
+ ADDR_BITS_REMOVE ((CORE_ADDR)
+ read_memory_integer (sregs +
+ s390_offsetof (s390x_sigregs,
+ s390_sigregs,
+ regs.
+ gprs
+ [fextra_info.
+ has_frame_pointer
+ ? 11 : 15]),
+ S390_GPR_SIZE));
+ else
+ {
+ regno =
+ (fextra_info.
+ has_frame_pointer ? S390_FRAME_REGNUM : S390_SP_REGNUM);
+ /* if it wasn't saved we must be in the innermost frame */
+ prev_fp = ADDR_BITS_REMOVE (thisframe->saved_regs[regno] ?
+ read_memory_integer (thisframe->
+ saved_regs[regno],
+ S390_GPR_SIZE) :
+ read_register (regno));
+ }
+
+
+ }
+ return prev_fp;
+}
+
+/*
+ Whether struct frame_extra_info is actually needed I'll have to figure
+ out as our frames are similar to rs6000 there is a possibility
+ i386 dosen't need it. */
+
+
+
+/* a given return value in `regbuf' with a type `valtype', extract and copy its
+ value into `valbuf' */
+void
+s390_extract_return_value (struct type *valtype, char *regbuf, char *valbuf)
+{
+ /* floats and doubles are returned in fpr0. fpr's have a size of 8 bytes.
+ We need to truncate the return value into float size (4 byte) if
+ necessary. */
+ int len = TYPE_LENGTH (valtype);
+
+ if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
+ {
+ if (len > (TARGET_FLOAT_BIT>>3))
+ memcpy (valbuf,®buf[REGISTER_BYTE (S390_FP0_REGNUM)],len);
+ else
+ {
+ /* float */
+ DOUBLEST val;
+
+ floatformat_to_doublest (&floatformat_ieee_double_big,
+ ®buf[REGISTER_BYTE (S390_FP0_REGNUM)], &val);
+ store_floating (valbuf,len, val);
+ }
+ }
+ else
+ {
+ int offset = 0;
+ /* return value is copied starting from r2. */
+ if (TYPE_LENGTH (valtype) < S390_GPR_SIZE)
+ offset = S390_GPR_SIZE - TYPE_LENGTH (valtype);
+ memcpy (valbuf,
+ regbuf + REGISTER_BYTE (S390_GP0_REGNUM + 2) + offset,
+ TYPE_LENGTH (valtype));
+ }
+}
+
+
+static char *
+s390_promote_integer_argument(struct type *valtype,char *valbuf,char *reg_buff,int *arglen)
+{
+ char *value=valbuf;
+ int len=TYPE_LENGTH (valtype);
+
+ if (len < S390_GPR_SIZE)
+ {
+ /* We need to upgrade this value to a register to pass it correctly */
+ int idx,diff=S390_GPR_SIZE-len,negative = (!TYPE_UNSIGNED (valtype)&&value[0]&0x80);
+ for(idx=0;idx<S390_GPR_SIZE;idx++)
+ {
+ reg_buff[idx] = (idx<diff ? (negative ? 0xff:0x0) :
+ value[idx-diff] );
+ }
+ value=reg_buff;
+ *arglen = S390_GPR_SIZE;
+ }
+ else
+ {
+ if (len & (S390_GPR_SIZE - 1))
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "s390_promote_integer_argument detected an argument not "
+ "a multiple of S390_GPR_SIZE & greater than S390_GPR_SIZE "
+ "we might not deal with this correctly.\n");
+ }
+ *arglen = len;
+ }
+
+ return(value);
+}
+
+void
+s390_store_return_value (struct type *valtype, char *valbuf)
+{
+ int arglen;
+ char *reg_buff=alloca(max(S390_FPR_SIZE,S390_REGISTER_SIZE)),*value;
+
+ if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
+ {
+ DOUBLEST tempfloat = extract_floating (valbuf,TYPE_LENGTH (valtype));
+
+ floatformat_from_doublest ( &floatformat_ieee_double_big,&tempfloat, reg_buff);
+ write_register_bytes (REGISTER_BYTE (S390_FP0_REGNUM),reg_buff,S390_FPR_SIZE);
+ }
+ else
+ {
+ value=s390_promote_integer_argument(valtype,valbuf,reg_buff,&arglen);
+ /* Everything else is returned in GPR2 and up. */
+ write_register_bytes (REGISTER_BYTE (S390_GP0_REGNUM + 2), value, arglen);
+ }
+}
+static int
+gdb_print_insn_s390 (bfd_vma memaddr, disassemble_info * info)
+{
+ __u8 instrbuff[S390_MAX_INSTR_SIZE];
+ int instrlen, cnt;
+
+ instrlen = s390_readinstruction (instrbuff, (CORE_ADDR) memaddr, info);
+ if (instrlen < 0)
+ {
+ (*info->memory_error_func) (instrlen, memaddr, info);
+ return -1;
+ }
+ for (cnt = 0; cnt < instrlen; cnt++)
+ info->fprintf_func (info->stream, "%02X ", instrbuff[cnt]);
+ for (cnt = instrlen; cnt < S390_MAX_INSTR_SIZE; cnt++)
+ info->fprintf_func (info->stream, " ");
+ instrlen = print_insn_s390 (memaddr, info);
+ return instrlen;
+}
+
+
+
+/* Not the most efficent code in the world */
+int
+s390_fp_regnum ()
+{
+ int regno = S390_SP_REGNUM;
+ struct frame_extra_info fextra_info;
+ s390_get_frame_info (s390_sniff_pc_function_start
+ (read_register (S390_PC_REGNUM)), &fextra_info, NULL,
+ TRUE);
+ if (fextra_info.good_prologue && fextra_info.has_frame_pointer)
+ regno = S390_FRAME_REGNUM;
+ return regno;
+}
+
+CORE_ADDR s390_read_fp ()
+{
+ return read_register (s390_fp_regnum ());
+}
+
+
+void
+s390_write_fp (CORE_ADDR val)
+{
+ write_register (s390_fp_regnum (), val);
+}
+
+
+void
+s390_push_dummy_frame ()
+{
+ CORE_ADDR orig_sp = read_register (S390_SP_REGNUM), new_sp;
+ void *saved_regs=alloca(SIZEOF_S390_GDB_REGS);
+
+ new_sp = (orig_sp - (SIZEOF_S390_GDB_REGS + S390_GPR_SIZE));
+ read_register_bytes (0, (char *)saved_regs,SIZEOF_S390_GDB_REGS);
+ /* Use saved copy instead of orig_sp as this will have the correct endianness */
+ write_memory (new_sp, (char *)saved_regs+
+ s390_offsetof(s390x_gdb_regs,s390_gdb_regs,gprs[S390_SP_REGNUM]),
+ S390_GPR_SIZE);
+ write_memory (new_sp + S390_GPR_SIZE, (char *) &saved_regs,
+ SIZEOF_S390_GDB_REGS);
+ write_register (S390_SP_REGNUM, new_sp);
+}
+
+/* pop the innermost frame, go back to the caller.
+ Used in `call_function_by_hand' to remove an artificial stack
+ frame. */
+void
+s390_pop_frame ()
+{
+ CORE_ADDR new_sp = read_register (S390_SP_REGNUM), orig_sp;
+ void *saved_regs=alloca(SIZEOF_S390_GDB_REGS);
+
+
+ read_memory (new_sp + S390_GPR_SIZE, (char *)saved_regs,
+ s390_sizeof(s390x_gdb_regs,s390_gdb_regs));
+ write_register_bytes (0, (char *) &saved_regs,SIZEOF_S390_GDB_REGS);
+}
+
+/* used by call function by hand
+ struct_return indicates that this function returns a structure &
+ therefore gpr2 stores a pointer to the structure to be returned as
+ opposed to the first argument.
+ Currently I haven't seen a TYPE_CODE_INT whose size wasn't 2^n or less
+ than S390_GPR_SIZE this is good because I don't seem to have to worry
+ about sign extending pushed arguments (i.e. a signed char currently
+ comes into this code with a size of 4 ). */
+
+CORE_ADDR
+s390_push_arguments (int nargs, value_ptr * args, CORE_ADDR sp,
+ int struct_return, CORE_ADDR struct_addr)
+{
+ int num_float_args, num_gpr_args, orig_num_gpr_args, argno;
+ int second_pass, len, arglen, gprs_required;
+ CORE_ADDR outgoing_args_ptr, outgoing_args_space;
+ value_ptr arg;
+ struct type *type;
+ int max_num_gpr_args = 5 - (struct_return ? 1 : 0);
+ int arg0_regnum = S390_GP0_REGNUM + 2 + (struct_return ? 1 : 0);
+ char *reg_buff=alloca(max(S390_FPR_SIZE,S390_REGISTER_SIZE)),*value;
+
+ for (second_pass = FALSE; second_pass <= TRUE; second_pass++)
+ {
+ if (second_pass)
+ outgoing_args_ptr = sp + S390_STACK_FRAME_OVERHEAD;
+ else
+ outgoing_args_ptr = 0;
+ num_float_args = 0;
+ num_gpr_args = 0;
+ for (argno = 0; argno < nargs; argno++)
+ {
+ arg = args[argno];
+ type = check_typedef (VALUE_TYPE (arg));
+ len = TYPE_LENGTH (type);
+ if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ {
+ int all_float_registers_used=num_float_args > (GDB_TARGET_IS_ESAME ? 3 : 1);
+
+ if(second_pass)
+ {
+ DOUBLEST tempfloat = extract_floating (VALUE_CONTENTS(arg),len);
+
+
+ floatformat_from_doublest ( all_float_registers_used &&
+ len == (TARGET_FLOAT_BIT>>3)
+ ? &floatformat_ieee_single_big
+ : &floatformat_ieee_double_big,
+ &tempfloat, reg_buff);
+ if(all_float_registers_used)
+ write_memory (outgoing_args_ptr,reg_buff, len);
+ else
+ write_register_bytes (REGISTER_BYTE((S390_FP0_REGNUM)
+ + (2 * num_float_args)),reg_buff,
+ S390_FPR_SIZE);
+ }
+ if(all_float_registers_used)
+ outgoing_args_ptr += len;
+ num_float_args++;
+ }
+ else
+ {
+ gprs_required = ((len + (S390_GPR_SIZE - 1)) / S390_GPR_SIZE);
+
+ value=s390_promote_integer_argument(type,VALUE_CONTENTS(arg),reg_buff,&arglen);
+
+ orig_num_gpr_args = num_gpr_args;
+ num_gpr_args += gprs_required;
+ if (num_gpr_args > max_num_gpr_args)
+ {
+ if (second_pass)
+ write_memory (outgoing_args_ptr, value, arglen);
+ outgoing_args_ptr += arglen;
+ }
+ else
+ {
+ if (second_pass)
+ write_register_bytes (REGISTER_BYTE (arg0_regnum)
+ + (orig_num_gpr_args * S390_GPR_SIZE),
+ value,arglen);
+ }
+ }
+ }
+ if (!second_pass)
+ {
+ outgoing_args_space = outgoing_args_ptr;
+ /* Align to 16 bytes because because I like alignment &
+ some of the kernel code requires 8 byte stack alignment at least. */
+ sp = (sp - (S390_STACK_FRAME_OVERHEAD + outgoing_args_ptr)) & (-16);
+ }
+
+ }
+ return sp;
+
+}
+
+
+#if defined(GDB_MULTI_ARCH) || !defined(CONFIG_ARCH_S390X)
+void
+s390_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
+ struct value **args, struct type *value_type,
+ int using_gcc)
+{
+ *(__u32 *) ((char *) &dummy[4]) = fun;
+}
+/* Number of bytes of storage in the actual machine representation
+ for register N.
+ Note that the unsigned cast here forces the result of the
+ subtraction to very high positive values if N < S390_FP0_REGNUM */
+int
+s390_register_raw_size (int reg_nr)
+{
+ return ((unsigned) reg_nr - S390_FP0_REGNUM) <
+ S390_NUM_FPRS ? S390_FPR_SIZE : 4;
+}
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+struct type *
+s390_register_virtual_type (int regno)
+{
+ return ((unsigned) regno - S390_FPC_REGNUM) <
+ S390_NUM_FPRS ? builtin_type_double : builtin_type_int;
+}
+
+#endif
+
+#if defined(GDB_MULTI_ARCH) || defined(CONFIG_ARCH_S390X)
+void
+s390x_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
+ struct value **args, struct type *value_type,
+ int using_gcc)
+{
+ *(__u64 *) ((char *) &dummy[4]) = fun;
+}
+
+int
+s390x_register_raw_size (int reg_nr)
+{
+ return (reg_nr == S390_FPC_REGNUM)
+ || (reg_nr >= S390_FIRST_ACR && reg_nr <= S390_LAST_ACR) ? 4 : 8 ;
+}
+
+struct type *
+s390x_register_virtual_type (int regno)
+{
+ return (regno == S390_FPC_REGNUM) ||
+ (regno >= S390_FIRST_ACR && regno <= S390_LAST_ACR) ? builtin_type_int :
+ (regno >= S390_FP0_REGNUM) ? builtin_type_double : builtin_type_long;
+}
+
+#endif
+
+
+void
+s390_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
+{
+ write_register (S390_GP0_REGNUM + 2, addr);
+}
+
+
+
+static unsigned char *
+s390_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
+{
+ static unsigned char breakpoint[] = S390_BREAKPOINT;
+
+ *lenptr = sizeof (breakpoint);
+ return breakpoint;
+}
+
+/* Advance PC across any function entry prologue instructions to reach some
+ "real" code. */
+CORE_ADDR
+s390_skip_prologue (CORE_ADDR pc)
+{
+ struct frame_extra_info fextra_info;
+
+ s390_get_frame_info (pc, &fextra_info, NULL, TRUE);
+ return fextra_info.skip_prologue_function_start;
+}
+
+/* pc_in_call_dummy_on stack may work for us must test this */
+int
+s390_pc_in_call_dummy (CORE_ADDR pc, CORE_ADDR sp, CORE_ADDR frame_address)
+{
+ return pc > sp && pc < (sp + 4096);
+}
+
+/* Immediately after a function call, return the saved pc.
+ Can't go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+CORE_ADDR s390_saved_pc_after_call (struct frame_info * frame)
+{
+ return ADDR_BITS_REMOVE (read_register (S390_RETADDR_REGNUM));
+}
+
+#if GDB_MULTI_ARCH
+static CORE_ADDR
+s390_addr_bits_remove (CORE_ADDR addr)
+{
+ return (addr) & 0x7fffffff;
+}
+#endif
+
+int
+s390_register_byte (int reg_nr)
+{
+ return (((reg_nr) <= S390_GP_LAST_REGNUM ? (reg_nr) * S390_GPR_SIZE :
+ (reg_nr) <=
+ S390_LAST_ACR ? (S390_ACR0_OFFSET +
+ (((reg_nr) - S390_FIRST_ACR) *
+ S390_ACR_SIZE)) : (reg_nr) <=
+ S390_LAST_CR ? (S390_CR0_OFFSET +
+ (((reg_nr) - S390_FIRST_CR) *
+ S390_CR_SIZE)) : (reg_nr) ==
+ S390_FPC_REGNUM ? S390_FPC_OFFSET : (S390_FP0_OFFSET +
+ (((reg_nr) - S390_FP0_REGNUM)
+ * S390_FPR_SIZE))));
+}
+
+#if GDB_MULTI_ARCH
+struct gdbarch *
+s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+{
+ static LONGEST s390_call_dummy_words[] = S390_CALL_DUMMY;
+ static LONGEST s390x_call_dummy_words[] = S390X_CALL_DUMMY;
+ struct gdbarch *gdbarch;
+ struct gdbarch_tdep *tdep;
+ int elf_flags;
+
+ /* First see if there is already a gdbarch that can satisfy the request. */
+ arches = gdbarch_list_lookup_by_info (arches, &info);
+ if (arches != NULL)
+ return arches->gdbarch;
+
+ /* None found: is the request for a s390 architecture? */
+ if (info.bfd_architecture != bfd_arch_s390)
+ return NULL; /* No; then it's not for us. */
+
+ /* Yes: create a new gdbarch for the specified machine type. */
+ gdbarch = gdbarch_alloc (&info, NULL);
+
+ set_gdbarch_believe_pcc_promotion (gdbarch, 0);
+
+ /* We don't define set_gdbarch_call_dummy_breakpoint_offset
+ as we already have a breakpoint inserted. */
+ set_gdbarch_use_generic_dummy_frames (gdbarch, 0);
+
+ set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
+ set_gdbarch_call_dummy_start_offset (gdbarch, 0);
+ set_gdbarch_pc_in_call_dummy (gdbarch, s390_pc_in_call_dummy);
+ set_gdbarch_frame_args_skip (gdbarch, 0);
+ set_gdbarch_frame_args_address (gdbarch, s390_frame_args_address);
+ set_gdbarch_frame_chain (gdbarch, s390_frame_chain);
+ set_gdbarch_frame_init_saved_regs (gdbarch, s390_frame_init_saved_regs);
+ set_gdbarch_frame_locals_address (gdbarch, s390_frame_args_address);
+ /* We can't do this */
+ set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
+ set_gdbarch_store_struct_return (gdbarch, s390_store_struct_return);
+ set_gdbarch_extract_return_value (gdbarch, s390_extract_return_value);
+ set_gdbarch_store_return_value (gdbarch, s390_store_return_value);
+ /* Amount PC must be decremented by after a breakpoint.
+ This is often the number of bytes in BREAKPOINT
+ but not always. */
+ set_gdbarch_decr_pc_after_break (gdbarch, 2);
+ set_gdbarch_pop_frame (gdbarch, s390_pop_frame);
+ set_gdbarch_push_dummy_frame (gdbarch, s390_push_dummy_frame);
+ set_gdbarch_push_arguments (gdbarch, s390_push_arguments);
+ set_gdbarch_ieee_float (gdbarch, 1);
+ /* Stack grows downward. */
+ set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+ /* Offset from address of function to start of its code.
+ Zero on most machines. */
+ set_gdbarch_function_start_offset (gdbarch, 0);
+ set_gdbarch_max_register_raw_size (gdbarch, 8);
+ set_gdbarch_max_register_virtual_size (gdbarch, 8);
+ set_gdbarch_breakpoint_from_pc (gdbarch, s390_breakpoint_from_pc);
+ set_gdbarch_skip_prologue (gdbarch, s390_skip_prologue);
+ set_gdbarch_init_extra_frame_info (gdbarch, s390_init_extra_frame_info);
+ set_gdbarch_init_frame_pc_first (gdbarch, s390_init_frame_pc_first);
+ set_gdbarch_read_fp (gdbarch, s390_read_fp);
+ set_gdbarch_write_fp (gdbarch, s390_write_fp);
+ /* This function that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+ set_gdbarch_frameless_function_invocation (gdbarch,
+ s390_frameless_function_invocation);
+ /* Return saved PC from a frame */
+ set_gdbarch_frame_saved_pc (gdbarch, s390_frame_saved_pc);
+ /* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer. */
+ set_gdbarch_frame_chain (gdbarch, s390_frame_chain);
+ set_gdbarch_saved_pc_after_call (gdbarch, s390_saved_pc_after_call);
+ set_gdbarch_register_byte (gdbarch, s390_register_byte);
+ set_gdbarch_pc_regnum (gdbarch, S390_PC_REGNUM);
+ set_gdbarch_sp_regnum (gdbarch, S390_SP_REGNUM);
+ set_gdbarch_fp_regnum (gdbarch, S390_FP_REGNUM);
+ set_gdbarch_fp0_regnum (gdbarch, S390_FP0_REGNUM);
+ set_gdbarch_num_regs (gdbarch, S390_NUM_REGS);
+ set_gdbarch_cannot_fetch_register (gdbarch, s390_cannot_fetch_register);
+ set_gdbarch_cannot_store_register (gdbarch, s390_cannot_fetch_register);
+ set_gdbarch_get_saved_register (gdbarch, generic_get_saved_register);
+ set_gdbarch_use_struct_convention (gdbarch, generic_use_struct_convention);
+ set_gdbarch_frame_chain_valid (gdbarch, file_frame_chain_valid);
+ set_gdbarch_register_name (gdbarch, s390_register_name);
+ set_gdbarch_stab_reg_to_regnum (gdbarch, s390_stab_reg_to_regnum);
+ set_gdbarch_dwarf_reg_to_regnum (gdbarch, s390_stab_reg_to_regnum);
+ set_gdbarch_dwarf2_reg_to_regnum (gdbarch, s390_stab_reg_to_regnum);
+
+
+ /* Stuff below here wouldn't be required if gdbarch.sh was a little */
+ /* more intelligent */
+ set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 0);
+ set_gdbarch_call_dummy_p (gdbarch, 1);
+ set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
+ set_gdbarch_extract_struct_value_address_p (gdbarch, 0);
+ switch (info.bfd_arch_info->mach)
+ {
+ case bfd_mach_s390_esa:
+ set_gdbarch_register_size (gdbarch, 4);
+ set_gdbarch_call_dummy_length (gdbarch, S390_CALL_DUMMY_LENGTH);
+ set_gdbarch_register_raw_size (gdbarch, s390_register_raw_size);
+ set_gdbarch_register_virtual_size (gdbarch, s390_register_raw_size);
+ set_gdbarch_register_virtual_type (gdbarch, s390_register_virtual_type);
+
+ set_gdbarch_addr_bits_remove (gdbarch, s390_addr_bits_remove);
+ set_gdbarch_fix_call_dummy (gdbarch, s390_fix_call_dummy);
+ set_gdbarch_sizeof_call_dummy_words (gdbarch,
+ sizeof (s390_call_dummy_words));
+ set_gdbarch_call_dummy_words (gdbarch, s390_call_dummy_words);
+ break;
+ case bfd_mach_s390_esame:
+ set_gdbarch_register_size (gdbarch, 8);
+ set_gdbarch_call_dummy_length (gdbarch, S390X_CALL_DUMMY_LENGTH);
+ set_gdbarch_register_raw_size (gdbarch, s390x_register_raw_size);
+ set_gdbarch_register_virtual_size (gdbarch, s390x_register_raw_size);
+ set_gdbarch_register_virtual_type (gdbarch,
+ s390x_register_virtual_type);
+
+ set_gdbarch_long_bit (gdbarch, 64);
+ set_gdbarch_long_long_bit (gdbarch, 64);
+ set_gdbarch_ptr_bit (gdbarch, 64);
+ set_gdbarch_fix_call_dummy (gdbarch, s390x_fix_call_dummy);
+ set_gdbarch_sizeof_call_dummy_words (gdbarch,
+ sizeof (s390x_call_dummy_words));
+ set_gdbarch_call_dummy_words (gdbarch, s390x_call_dummy_words);
+ break;
+ }
+ /* REGISTER_SIZE is set up so this is correct here */
+ set_gdbarch_register_bytes (gdbarch, S390_REGISTER_BYTES);
+ return gdbarch;
+}
+#endif
+
+
+void
+_initialize_s390_tdep ()
+{
+ const bfd_arch_info_type *s390_arch_ptr =
+ bfd_lookup_arch (bfd_arch_s390, 0);
+
+#if GDB_MULTI_ARCH
+ /* Hook us into the gdbarch mechanism. */
+ register_gdbarch_init (bfd_arch_s390, s390_gdbarch_init);
+#endif
+ if (!tm_print_insn) /* Someone may have already set it */
+ tm_print_insn = gdb_print_insn_s390;
+ if (s390_arch_ptr)
+ tm_print_insn_info.mach = s390_arch_ptr->mach;
+ else
+ internal_error (__FILE__, __LINE__,
+ "_initialize_s390_tdep: bfd_lookup_arch failed for bfd_arch_s390 recompile.\n");
+}
--- src.orig/gdb/gdbarch.sh Thu Feb 8 07:03:53 2001
+++ src.new/gdb/gdbarch.sh Tue Feb 27 20:12:37 2001
@@ -35,7 +35,7 @@
# Format of the input table
-read="class level macro returntype function formal actual attrib staticdefault predefault postdefault invalid_p fmt print print_p description"
+read="class level macro returntype function formal actual attrib staticdefault predefault postdefault invalid_p fmt print print_p description allow_null_function null_function_default_retval"
do_read ()
{
@@ -303,7 +303,14 @@
description ) : ;;
# Currently unused.
-
+ allow_null_function ) : ;;
+ # this definition is set to an
+ # non empty string if it is okay for the gdbarch function
+ # to be null.
+ null_function_default_retval ) : ;;
+ # this definiton is the
+ # default return value for a undefined function
+ # (i.e. allow_null_function is defined ).
*) exit 1;;
esac
done
@@ -401,7 +408,7 @@
v:2:CALL_DUMMY_LOCATION:int:call_dummy_location::::0:0
f:2:CALL_DUMMY_ADDRESS:CORE_ADDR:call_dummy_address:void:::0:0::gdbarch->call_dummy_location == AT_ENTRY_POINT && gdbarch->call_dummy_address == 0
v:2:CALL_DUMMY_START_OFFSET:CORE_ADDR:call_dummy_start_offset::::0:-1:::0x%08lx
-v:2:CALL_DUMMY_BREAKPOINT_OFFSET:CORE_ADDR:call_dummy_breakpoint_offset::::0:-1:::0x%08lx::CALL_DUMMY_BREAKPOINT_OFFSET_P
+v:2:CALL_DUMMY_BREAKPOINT_OFFSET:CORE_ADDR:call_dummy_breakpoint_offset::::0:-1::gdbarch->call_dummy_breakpoint_offset_p && gdbarch->call_dummy_breakpoint_offset == -1:0x%08lx::CALL_DUMMY_BREAKPOINT_OFFSET_P
v:1:CALL_DUMMY_BREAKPOINT_OFFSET_P:int:call_dummy_breakpoint_offset_p::::0:-1
v:2:CALL_DUMMY_LENGTH:int:call_dummy_length::::0:-1:::::CALL_DUMMY_LOCATION == BEFORE_TEXT_END || CALL_DUMMY_LOCATION == AFTER_TEXT_END
f:2:PC_IN_CALL_DUMMY:int:pc_in_call_dummy:CORE_ADDR pc, CORE_ADDR sp, CORE_ADDR frame_address:pc, sp, frame_address::0:0
@@ -436,7 +443,7 @@
f:2:EXTRACT_RETURN_VALUE:void:extract_return_value:struct type *type, char *regbuf, char *valbuf:type, regbuf, valbuf::0:0
f:1:PUSH_ARGUMENTS:CORE_ADDR:push_arguments:int nargs, struct value **args, CORE_ADDR sp, int struct_return, CORE_ADDR struct_addr:nargs, args, sp, struct_return, struct_addr::0:0
f:2:PUSH_DUMMY_FRAME:void:push_dummy_frame:void:-:::0
-f:1:PUSH_RETURN_ADDRESS:CORE_ADDR:push_return_address:CORE_ADDR pc, CORE_ADDR sp:pc, sp:::0
+f:1:PUSH_RETURN_ADDRESS:CORE_ADDR:push_return_address:CORE_ADDR pc, CORE_ADDR sp:pc, sp:::0::0:::::1:sp
f:2:POP_FRAME:void:pop_frame:void:-:::0
#
# I wish that these would just go away....
@@ -449,7 +456,8 @@
#
f:2:STORE_STRUCT_RETURN:void:store_struct_return:CORE_ADDR addr, CORE_ADDR sp:addr, sp:::0
f:2:STORE_RETURN_VALUE:void:store_return_value:struct type *type, char *valbuf:type, valbuf:::0
-f:2:EXTRACT_STRUCT_VALUE_ADDRESS:CORE_ADDR:extract_struct_value_address:char *regbuf:regbuf:::0
+f:2:EXTRACT_STRUCT_VALUE_ADDRESS:CORE_ADDR:extract_struct_value_address:char *regbuf:regbuf::0:0::gdbarch->extract_struct_value_address_p && gdbarch->extract_struct_value_address == 0
+v:2:EXTRACT_STRUCT_VALUE_ADDRESS_P:int:extract_struct_value_address_p::::0:-1
f:2:USE_STRUCT_CONVENTION:int:use_struct_convention:int gcc_p, struct type *value_type:gcc_p, value_type:::0
#
f:2:FRAME_INIT_SAVED_REGS:void:frame_init_saved_regs:struct frame_info *frame:frame::0:0
@@ -459,6 +467,10 @@
f:2:PROLOGUE_FRAMELESS_P:int:prologue_frameless_p:CORE_ADDR ip:ip::0:generic_prologue_frameless_p::0
f:2:INNER_THAN:int:inner_than:CORE_ADDR lhs, CORE_ADDR rhs:lhs, rhs::0:0
f:2:BREAKPOINT_FROM_PC:unsigned char *:breakpoint_from_pc:CORE_ADDR *pcptr, int *lenptr:pcptr, lenptr:::legacy_breakpoint_from_pc::0
+f:2:INIT_FRAME_PC_FIRST:void:init_frame_pc_first:int fromleaf,struct frame_info *fi:fromleaf,fi::::::::::1
+f:2:CANNOT_STORE_REGISTER:int:cannot_store_register:int regno:regno::::::::::1:0
+f:2:CANNOT_FETCH_REGISTER:int:cannot_fetch_register:int regno:regno::::::::::1:0
+f:2:ADDR_BITS_REMOVE:CORE_ADDR:addr_bits_remove:CORE_ADDR addr:addr::::::::::1:addr
f:2:MEMORY_INSERT_BREAKPOINT:int:memory_insert_breakpoint:CORE_ADDR addr, char *contents_cache:addr, contents_cache::0:default_memory_insert_breakpoint::0
f:2:MEMORY_REMOVE_BREAKPOINT:int:memory_remove_breakpoint:CORE_ADDR addr, char *contents_cache:addr, contents_cache::0:default_memory_remove_breakpoint::0
v:2:DECR_PC_AFTER_BREAK:CORE_ADDR:decr_pc_after_break::::0:-1
@@ -1440,12 +1452,25 @@
printf "gdbarch_${function} (struct gdbarch *gdbarch, ${formal})\n"
fi
printf "{\n"
- printf " if (gdbarch->${function} == 0)\n"
- printf " internal_error (__FILE__, __LINE__,\n"
- printf " \"gdbarch: gdbarch_${function} invalid\");\n"
+ if [ "${allow_null_function}" = "" ]
+ then
+ printf " if (gdbarch->${function} == 0)\n"
+ printf " internal_error (__FILE__, __LINE__,\n"
+ printf " \"gdbarch: gdbarch_${function} invalid\");\n"
+ fi
printf " if (gdbarch_debug >= 2)\n"
printf " fprintf_unfiltered (gdb_stdlog, \"gdbarch_${function} called\\\\n\");\n"
test "${actual}" = "-" && actual=""
+ if [ "${allow_null_function}" ]
+ then
+ printf " if (gdbarch->${function} == 0)\n"
+ if [ "${returntype}" = "void" ]
+ then
+ printf " return;\n"
+ else
+ printf " return ${null_function_default_retval};\n"
+ fi
+ fi
if [ "${returntype}" = "void" ]
then
printf " gdbarch->${function} (${actual});\n"
--- src.orig/gdb/core-aout.c Sun Jul 30 03:48:24 2000
+++ src.new/gdb/core-aout.c Tue Feb 27 17:36:35 2001
@@ -81,6 +81,7 @@
int bad_reg = -1;
CORE_ADDR reg_ptr = -reg_addr; /* Original u.u_ar0 is -reg_addr. */
int numregs = ARCH_NUM_REGS;
+ char *buf=alloca(MAX_REGISTER_RAW_SIZE);
/* If u.u_ar0 was an absolute address in the core file, relativize it now,
so we can use it as an offset into core_reg_sect. When we're done,
@@ -93,12 +94,20 @@
for (regno = 0; regno < numregs; regno++)
{
- addr = CORE_REGISTER_ADDR (regno, reg_ptr);
- if (addr >= core_reg_size
- && bad_reg < 0)
- bad_reg = regno;
+ if (CANNOT_FETCH_REGISTER (regno))
+ {
+ memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */
+ supply_register (regno, buf);
+ }
else
- supply_register (regno, core_reg_sect + addr);
+ {
+ addr = CORE_REGISTER_ADDR (regno, reg_ptr);
+ if (addr >= core_reg_size
+ && bad_reg < 0)
+ bad_reg = regno;
+ else
+ supply_register (regno, core_reg_sect + addr);
+ }
}
if (bad_reg >= 0)
[-- Attachment #5: gdb.s390.270201.readline.config.diff --]
[-- Type: text/x-diff, Size: 261 bytes --]
--- src.orig/readline/configure.in Sun Jul 9 19:19:56 2000
+++ src.new/readline/configure.in Mon Feb 26 17:58:04 2001
@@ -129,6 +129,7 @@
case "$host_cpu" in
*cray*) LOCAL_CFLAGS=-DCRAY ;;
+*s390*) LOCAL_CFLAGS=-fsigned-char ;;
esac
case "$host_os" in
[-- Attachment #6: S390ChangeLog.gdb --]
[-- Type: text/plain, Size: 1444 bytes --]
2001-02-26 D.J. Barrow <djbarrow@de.ibm.com,barrow_dj@yahoo.com>
* s390-nat.c New file Added for S/390 31 & 64 bit target.
* s390-tdep.c Likewise.
* config/s390/nm-linux.h Likewise.
* config/s390/s390x.mt Likewise.
* config/s390/tm-linux.h Likewise.
* config/s390/xm-linux.h Likewise
* config/s390/s390.mh Likewise.
* config/s390/s390.mt Likewise.
* config/s390/tm-s390.h Likewise.
* config.in Added definitions for S/390 31 & 64 bit target.
* configure.host Likewise.
* configure.in Likewise.
* configure.tgt Likewise.
* gdbarch.sh Added 2 definitions to the input table
allow_null_function, this definition is set to an
non empty string if it is okay for the gdbarch function
to be null.
null_function_default_retval, this definiton is the
default return value for a undefined function
(i.e. allow_null_function is defined ).
Added new macros required for S/390
INIT_FRAME_PC_FIRST
CANNOT_STORE_REGISTER
CANNOT_FETCH_REGISTER
ADDR_BITS_REMOVE
EXTRACT_STRUCT_VALUE_ADDRESS_P
Improved the behaviour of the following macros.
PUSH_RETURN_ADDRESS
added allow null function so default behaviour would be correct.
EXTRACT_STRUCT_VALUE_ADDRESS
added check for EXTRACT_STRUCT_VALUE_ADDRESS_P
CALL_DUMMY_BREAKPOINT_OFFSET
* core-aout.c added check for CANNOT_FETCH_REGISTER
in fetch_core_registers.
* arch-utils.c added check for BFD_ENDIAN_UNKNOWN
in set_endian_from_file.
[-- Attachment #7: S390ChangeLog.Root --]
[-- Type: text/plain, Size: 173 bytes --]
2001-02-26 D.J. Barrow <djbarrow@de.ibm.com,barrow_dj@yahoo.com>
* config.sub: Added S/390 31 & 64 bit target.
* configure.in: Likewise.
* config.guess: Likewise.
^ permalink raw reply [flat|nested] 8+ messages in thread* [patch] multi-arch INIT_FRAME_PC*; Was: New gdb 31 & 64 bit patches for S/390
2001-02-27 12:39 DJBARROW
@ 2001-06-15 16:09 ` Andrew Cagney
0 siblings, 0 replies; 8+ messages in thread
From: Andrew Cagney @ 2001-06-15 16:09 UTC (permalink / raw)
To: DJBARROW; +Cc: gdb-patches, schwidefsky, ARENZ
Hello,
I've checked in the attatched, it multi-arches INIT_FRAME_PC_FIRST. (I
also got a little carried away and multi-arched INIT_FRAME_PC as well :-)
Andrew
From msnyder@cygnus.com Fri Jun 15 16:22:00 2001
From: Michael Snyder <msnyder@cygnus.com>
To: "Peter.Schauer" <Peter.Schauer@Regent.E-Technik.TU-Muenchen.DE>, gdb-patches@sources.redhat.com
Subject: [RFC] if (INNER_THAN (read_sp(), step_sp - 16))
Date: Fri, 15 Jun 2001 16:22:00 -0000
Message-id: <3B2A97C7.52A839FD@cygnus.com>
X-SW-Source: 2001-06/msg00307.html
Content-length: 1134
Hellooooooo, Peter Schauer!
Back in April of 1998 a patch from you was checked in (you may have
submitted it some time earlier) for x86 Solaris. Among other things,
it contained a test in infrun.c (wait_for_inferior) that looked like:
[stuff...]
(CURRENTLY_STEPPING ()
&& prev_pc != stop_pc - DECR_PC_AFTER_BREAK
&& !(step_range_end
&& read_sp () INNER_THAN (step_sp - 16)));
A comment explains that the INNER_THAN expression is meant to detect
hitting a breakpoint in a signal handler without an intervening stop
in sigtramp.
The lines have metamorphosed since then, but the expression with
(step_sp - 16) is still in there, and I would really like to get
rid of it. Especially since I have now found that it can cause
serious bugs in debugging native Linux x86.
But I have no idea how to detect the situation that you are
trying to test for. So I'd like to toss it back to you.
Can you find a better way to test for this? Maybe with
(ugh) another state variable?
And if not, can you put those two lines into an ifdef,
so they won't affect targets for which they're not intended?
Thanks a lot,
Michael
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2001-06-18 5:52 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <200106171816.LAA21467@bosch.cygnus.com>
2001-06-18 5:52 ` [patch] multi-arch INIT_FRAME_PC*; Was: New gdb 31 & 64 bit patches for S/390 Andrew Cagney
2001-06-16 17:39 Michael Elizabeth Chastain
2001-06-17 8:51 ` Andrew Cagney
2001-06-17 9:26 ` Andrew Cagney
2001-06-17 9:58 ` Andrew Cagney
-- strict thread matches above, loose matches on Subject: below --
2001-06-16 16:14 Michael Elizabeth Chastain
[not found] <200106161813.LAA20846@bosch.cygnus.com>
2001-06-16 12:35 ` Andrew Cagney
2001-02-27 12:39 DJBARROW
2001-06-15 16:09 ` [patch] multi-arch INIT_FRAME_PC*; Was: " Andrew Cagney
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox