summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@gnu.org>2003-11-02 20:26:32 +0000
committerMark Kettenis <kettenis@gnu.org>2003-11-02 20:26:32 +0000
commit123ebd3f4266580b61135584f1edb0e81b52cfe3 (patch)
tree2c3349fca920953ad9c2e6108dfaac4431c7e2bf
parent71738b04c5b4be766affeb5ab003f1ef7ce19544 (diff)
downloadgdb-123ebd3f4266580b61135584f1edb0e81b52cfe3.tar.gz
* sparc64-tdep.h (r_tstate_offset): New define.
(sparc64_supply_gregset, sparc64_collect_gregset, sparc64_supply_fpregset, sparc64_collect_fpregset): New prototypes. (sparc64_sol2_gregset): New extern declaration. (sparc64_sol2_init_abi): New prototype. * sparc64-tdep.c: Include "symtab.h" and "objfiles.h". Don't include "sparc-tdep.h". (X_RD, X_I): New macros. (sparc64_analyze_prologue): Sync with implementation in sparc-tdep.c. (TSTATE_CWP, TSTATE_ICC, TSTATE_XCC): New macros. (PSR_S, PSR_ICC, PSR_VERS, PSR_IMPL, PSR_V8PLUS, PSR_XCC): New macros. (sparc64_supply_gregset, sparc64_collect_gregset, sparc64_supply_fpregset, sparc64_collect_fpregset): New functions. * sparc64-nat.c: New file. * sparc64-sol2-nat.c: New file. * sparc64-sol2-tdep.c: New file. * sparc64-linux-nat.c: New file. * sparc64-linux-tdep.c: New file. * Makefile.in (sparc_tdep_h): New variable. (ALLDEPFILES): Add sparc64-sol2-tdep.c, sparc64-linux-tdep.c, sparc64-nat.c sparc64-sol2-nat.c and sparc64-linux-nat.c (sparc-nat.o, sparc-linux-tdep.o, sparc64-tdep.o): Update dependencies. (sparc64-nat.o, sparc64-linux-nat.o, sparc64-linux-tdep.o, sparc64-sol2-nat.o, sparc64-sol2-tdep.o): New dependencies. * configure.tgt: Add sparc64-*-linux*. * configure.host: Add sparc64-*-linux*. * config/sparc/linux64.mt: New file. * config/sparc/linux64.mh: New file.
-rw-r--r--gdb/ChangeLog33
-rw-r--r--gdb/Makefile.in25
-rw-r--r--gdb/config/sparc/linux64.mh11
-rw-r--r--gdb/config/sparc/linux64.mt5
-rw-r--r--gdb/configure.host1
-rw-r--r--gdb/configure.tgt1
-rw-r--r--gdb/sparc64-linux-nat.c48
-rw-r--r--gdb/sparc64-linux-tdep.c82
-rw-r--r--gdb/sparc64-nat.c86
-rw-r--r--gdb/sparc64-sol2-nat.c57
-rw-r--r--gdb/sparc64-sol2-tdep.c73
-rw-r--r--gdb/sparc64-tdep.c339
-rw-r--r--gdb/sparc64-tdep.h24
13 files changed, 776 insertions, 9 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a0b79e692dd..daa6fef8c9e 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,38 @@
2003-11-02 Mark Kettenis <kettenis@gnu.org>
+ * sparc64-tdep.h (r_tstate_offset): New define.
+ (sparc64_supply_gregset, sparc64_collect_gregset,
+ sparc64_supply_fpregset, sparc64_collect_fpregset): New
+ prototypes.
+ (sparc64_sol2_gregset): New extern declaration.
+ (sparc64_sol2_init_abi): New prototype.
+ * sparc64-tdep.c: Include "symtab.h" and "objfiles.h". Don't
+ include "sparc-tdep.h".
+ (X_RD, X_I): New macros.
+ (sparc64_analyze_prologue): Sync with implementation in
+ sparc-tdep.c.
+ (TSTATE_CWP, TSTATE_ICC, TSTATE_XCC): New macros.
+ (PSR_S, PSR_ICC, PSR_VERS, PSR_IMPL, PSR_V8PLUS, PSR_XCC): New
+ macros.
+ (sparc64_supply_gregset, sparc64_collect_gregset,
+ sparc64_supply_fpregset, sparc64_collect_fpregset): New functions.
+ * sparc64-nat.c: New file.
+ * sparc64-sol2-nat.c: New file.
+ * sparc64-sol2-tdep.c: New file.
+ * sparc64-linux-nat.c: New file.
+ * sparc64-linux-tdep.c: New file.
+ * Makefile.in (sparc_tdep_h): New variable.
+ (ALLDEPFILES): Add sparc64-sol2-tdep.c, sparc64-linux-tdep.c,
+ sparc64-nat.c sparc64-sol2-nat.c and sparc64-linux-nat.c
+ (sparc-nat.o, sparc-linux-tdep.o, sparc64-tdep.o): Update
+ dependencies.
+ (sparc64-nat.o, sparc64-linux-nat.o, sparc64-linux-tdep.o,
+ sparc64-sol2-nat.o, sparc64-sol2-tdep.o): New dependencies.
+ * configure.tgt: Add sparc64-*-linux*.
+ * configure.host: Add sparc64-*-linux*.
+ * config/sparc/linux64.mt: New file.
+ * config/sparc/linux64.mh: New file.
+
* sparc-tdep.h (struct sparc_gregset): Add r_y_size member.
(sparc32_supply_gregset): Renamed from sparc_supply_gregset.
(sparc32_collect_gregset): Renamed from sparc_collect_gregset.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 22eb5508ee2..1552bfb8a8b 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -748,6 +748,7 @@ somsolib_h = somsolib.h
source_h = source.h
sparc_tdep_h = sparc-tdep.h
sparc64_tdep_h = sparc64-tdep.h $(sparc_tdep_h)
+sparc_nat_h = sparc-nat.h
srec_h = srec.h
stabsread_h = stabsread.h
stack_h = stack.h
@@ -1295,7 +1296,9 @@ ALLDEPFILES = \
solib.c solib-irix.c solib-svr4.c solib-sunos.c \
sparc-tdep.c sparc-linux-tdep.c sparc-sol2-tdep.c \
sparc-nat.c sparc-sol2-nat.c sparcbsd-nat.c \
- sparc64-tdep.c sparc64fbsd-tdep.c \
+ sparc64-tdep.c sparc64-sol2-tdep.c sparc64-linux-tdep.c \
+ sparc64fbsd-tdep.c \
+ sparc64-nat.c sparc64-sol2-nat.c sparc64-linux-nat.c \
sparc64fbsd-nat.c \
sun3-nat.c \
symm-tdep.c symm-nat.c \
@@ -2302,15 +2305,15 @@ source.o: source.c $(defs_h) $(symtab_h) $(expression_h) $(language_h) \
$(gdb_string_h) $(gdb_stat_h) $(gdbcore_h) $(gdb_regex_h) \
$(symfile_h) $(objfiles_h) $(annotate_h) $(gdbtypes_h) $(linespec_h) \
$(filenames_h) $(completer_h) $(ui_out_h)
-sparc-nat.o: sparc-nat.c $(defs_h) $(inferior_h) $(regcache_h) $(gdb_wait_h) \
- $(sparc_tdep_h)
+sparc-nat.o: sparc-nat.c $(defs_h) $(inferior_h) $(regcache_h) \
+ $(gdb_string_h) $(gdb_wait_h) $(sparc_tdep_h) $(sparc_nat_h)
sparc-tdep.o: sparc-tdep.c $(defs_h) $(arch_utils_h) $(dis_asm_h) $(frame_h) \
$(frame_base_h) $(frame_unwind_h) $(gdbcore_h) $(gdbtypes_h) \
$(inferior_h) $(symtab_h) $(objfiles_h) $(osabi_h) $(regcache_h) \
$(target_h) $(value_h) $(gdb_assert_h) $(gdb_string_h) \
$(sparc_tdep_h)
sparc-linux-tdep.o: sparc-linux-tdep.c $(defs_h) $(gdbarch_h) $(osabi_h) \
- $(sparc_tdep_h)
+ $(solib_svr4_h) $(sparc_tdep_h)
sparc-sol2-nat.o: sparc-sol2-nat.c $(defs_h) $(gregset_h) $(regcache_h) \
$(sparc_tdep_h)
sparc-sol2-tdep.o: sparc-sol2-tdep.c $(defs_h) $(frame_h) $(frame_base_h) \
@@ -2319,11 +2322,21 @@ sparc-sol2-tdep.o: sparc-sol2-tdep.c $(defs_h) $(frame_h) $(frame_base_h) \
$(gdb_string_h) $(sparc_tdep_h)
sparcbsd-nat.o: sparcbsd-nat.c $(defs_h) $(inferior_h) $(regcache_h) \
$(sparc64_tdep_h) $(sparcbsd_nat_h)
+sparc64-nat.o: sparc-nat.c $(defs_h) $(gdbarch_h) \
+ $(sparc64_tdep_h) $(sparc_nat_h)
sparc64-tdep.o: sparc64-tdep.c $(defs_h) $(arch_utils_h) $(floatformat_h) \
$(frame_h) $(frame_base_h) $(frame_unwind_h) $(gdbcore_h) \
- $(gdbtypes_h) $(inferior_h) $(osabi_h) $(regcache_h) $(target_h) \
- $(value_h) $(gdb_assert_h) $(gdb_string_h) $(sparc_tdep_h) \
+ $(gdbtypes_h) $(inferior_h) $(symtab_h) $(objfiles_h) $(osabi_h) \
+ $(regcache_h) $(target_h) $(value_h) $(gdb_assert_h) $(gdb_string_h) \
+ $(sparc64_tdep_h)
+sparc64-linux-nat.o: sparc64-linux-nat.c $(defs_h) \
+ $(sparc64_tdep_h) $(sparc_nat_h)
+sparc64-linux-tdep.o: sparc64-linux-tdep.c $(defs_h) $(gdbarch_h) \
+ $(osabi_h) $(solib_svr4_h) $(sparc64_tdep_h)
+sparc64-sol2-nat.o: sparc64-sol2-nat.o $(defs_h) $(gregset_h) $(regcache_h) \
$(sparc64_tdep_h)
+sparc64-sol2-tdep.c: sparc64-sol2-tdep.o $(defs_h) $(gdbarch_h) $(symtab_h) \
+ $(objfiles_h) $(osabi_h) $(sparc64_tdep_h)
sparc64fbsd-tdep.o: sparc64fbsd-tdep.c $(defs_h) $(gdbcore_h) $(osabi_h) \
$(regcache_h) $(target_h) $(gdb_string_h) $(sparc64_tdep_h)
sparc64fbsd-nat.o: sparc64fbsd-nat.c $(defs_h) $(sparc64_tdep_h) \
diff --git a/gdb/config/sparc/linux64.mh b/gdb/config/sparc/linux64.mh
new file mode 100644
index 00000000000..c0a98546a7c
--- /dev/null
+++ b/gdb/config/sparc/linux64.mh
@@ -0,0 +1,11 @@
+# Host: GNU/Linux UltraSPARC
+NAT_FILE= nm-linux.h
+NATDEPFILES= sparc-nat.o sparc64-nat.o sparc64-sol2-nat.o sparc64-linux-nat.o \
+ corelow.o core-regset.o \
+ fork-child.o infptrace.o inftarg.o \
+ proc-service.o thread-db.o lin-lwp.o \
+ linux-proc.o gcore.o linux-nat.o
+
+# The dynamically loaded libthread_db needs access to symbols in the
+# gdb executable.
+LOADLIBES = -ldl -rdynamic
diff --git a/gdb/config/sparc/linux64.mt b/gdb/config/sparc/linux64.mt
new file mode 100644
index 00000000000..4121314318b
--- /dev/null
+++ b/gdb/config/sparc/linux64.mt
@@ -0,0 +1,5 @@
+# Target: GNU/Linux UltraSPARC
+TDEPFILES= sparc64-tdep.o sparc64-sol2-tdep.o sparc64-linux-tdep.o \
+ sparc-tdep.o sparc-sol2-tdep.o sparc-linux-tdep.o \
+ solib.o solib-svr4.o solib-legacy.o
+TM_FILE= tm-linux.h
diff --git a/gdb/configure.host b/gdb/configure.host
index 6622803f183..4def0bc87fb 100644
--- a/gdb/configure.host
+++ b/gdb/configure.host
@@ -133,6 +133,7 @@ sh*-*-netbsdelf*) gdb_host=nbsd ;;
sparc-*-solaris2*) gdb_host=sol2 ;;
sparc-*-linux*) gdb_host=linux ;;
sparc64-*-freebsd*) gdb_host=fbsd ;;
+sparc64-*-linux*) gdb_host=linux64 ;;
vax-*-bsd*) gdb_host=vaxbsd ;;
vax-*-ultrix2*) gdb_host=vaxult2 ;;
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index b36ecc69678..2b2a2efde0b 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -205,6 +205,7 @@ sh*) gdb_target=embed ;;
sparc-*-solaris2*) gdb_target=sol2 ;;
sparc-*-linux*) gdb_target=linux ;;
sparc-*-*) gdb_target=sparc ;;
+sparc64-*-linux*) gdb_target=linux64 ;;
xstormy16-*-*) gdb_target=xstormy16 ;;
diff --git a/gdb/sparc64-linux-nat.c b/gdb/sparc64-linux-nat.c
new file mode 100644
index 00000000000..56ee2936938
--- /dev/null
+++ b/gdb/sparc64-linux-nat.c
@@ -0,0 +1,48 @@
+/* Native-dependent code for GNU/Linux UltraSPARC.
+
+ Copyright 2003 Free Software Foundation, Inc.
+
+ 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 "sparc64-tdep.h"
+#include "sparc-nat.h"
+
+static const struct sparc_gregset sparc64_linux_ptrace_gregset =
+{
+ 16 * 8, /* "tstate" */
+ 17 * 8, /* %pc */
+ 18 * 8, /* %npc */
+ 19 * 8, /* %y */
+ -1, /* %wim */
+ -1, /* %tbr */
+ 0 * 8, /* %g1 */
+ -1, /* %l0 */
+ 4 /* sizeof (%y) */
+};
+
+
+/* Provide a prototype to silence -Wmissing-prototypes. */
+void _initialize_sparc64_linux_nat (void);
+
+void
+_initialize_sparc64_linux_nat (void)
+{
+ sparc_gregset = &sparc64_linux_ptrace_gregset;
+}
diff --git a/gdb/sparc64-linux-tdep.c b/gdb/sparc64-linux-tdep.c
new file mode 100644
index 00000000000..cd785571d58
--- /dev/null
+++ b/gdb/sparc64-linux-tdep.c
@@ -0,0 +1,82 @@
+/* Target-dependent code for GNU/Linux UltraSPARC.
+
+ Copyright 2003 Free Software Foundation, Inc.
+
+ 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 "gdbarch.h"
+#include "osabi.h"
+#include "solib-svr4.h"
+
+#include "sparc64-tdep.h"
+
+static struct link_map_offsets *
+sparc64_linux_svr4_fetch_link_map_offsets (void)
+{
+ static struct link_map_offsets lmo;
+ static struct link_map_offsets *lmp = NULL;
+
+ if (lmp == NULL)
+ {
+ lmp = &lmo;
+
+ /* Everything we need is in the first 16 bytes. */
+ lmo.r_debug_size = 16;
+ lmo.r_map_offset = 8;
+ lmo.r_map_size = 8;
+
+ /* Everything we need is in the first 40 bytes. */
+ lmo.link_map_size = 40;
+ lmo.l_addr_offset = 0;
+ lmo.l_addr_size = 8;
+ lmo.l_name_offset = 8;
+ lmo.l_name_size = 8;
+ lmo.l_next_offset = 24;
+ lmo.l_next_size = 8;
+ lmo.l_prev_offset = 32;
+ lmo.l_prev_size = 8;
+ }
+
+ return lmp;
+}
+
+static void
+sparc64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ /* GNU/Linux is very similar to Solaris ... */
+ sparc64_sol2_init_abi (info, gdbarch);
+
+ /* ... but doesn't have kernel-assisted single-stepping support. */
+ set_gdbarch_software_single_step (gdbarch, sparc_software_single_step);
+
+ set_solib_svr4_fetch_link_map_offsets
+ (gdbarch, sparc64_linux_svr4_fetch_link_map_offsets);
+}
+
+/* Provide a prototype to silence -Wmissing-prototypes. */
+extern void _initialize_sparc64_linux_tdep (void);
+
+void
+_initialize_sparc64_linux_tdep (void)
+{
+ gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
+ GDB_OSABI_LINUX, sparc64_linux_init_abi);
+}
diff --git a/gdb/sparc64-nat.c b/gdb/sparc64-nat.c
new file mode 100644
index 00000000000..70ad7c089d4
--- /dev/null
+++ b/gdb/sparc64-nat.c
@@ -0,0 +1,86 @@
+/* Native-dependent code for GNU/Linux UltraSPARC.
+
+ Copyright 2003 Free Software Foundation, Inc.
+
+ 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 "gdbarch.h"
+
+#include "sparc64-tdep.h"
+#include "sparc-nat.h"
+
+/* Determine whether `gregset_t' contains register REGNUM. */
+
+static int
+sparc64_gregset_supplies_p (int regnum)
+{
+ if (gdbarch_ptr_bit (current_gdbarch) == 32)
+ return sparc32_gregset_supplies_p (regnum);
+
+ /* Integer registers. */
+ if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_G7_REGNUM)
+ || (regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM)
+ || (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_L7_REGNUM)
+ || (regnum >= SPARC_I0_REGNUM && regnum <= SPARC_I7_REGNUM))
+ return 1;
+
+ /* Control registers. */
+ if (regnum == SPARC64_PC_REGNUM
+ || regnum == SPARC64_NPC_REGNUM
+ || regnum == SPARC64_STATE_REGNUM
+ || regnum == SPARC64_Y_REGNUM)
+ return 1;
+
+ return 0;
+}
+
+/* Determine whether `fpregset_t' contains register REGNUM. */
+
+static int
+sparc64_fpregset_supplies_p (int regnum)
+{
+ if (gdbarch_ptr_bit (current_gdbarch) == 32)
+ return sparc32_fpregset_supplies_p (regnum);
+
+ /* Floating-point registers. */
+ if ((regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F31_REGNUM)
+ || (regnum >= SPARC64_F32_REGNUM && regnum <= SPARC64_F62_REGNUM))
+ return 1;
+
+ /* Control registers. */
+ if (regnum == SPARC64_FSR_REGNUM)
+ return 1;
+
+ return 0;
+}
+
+
+/* Provide a prototype to silence -Wmissing-prototypes. */
+void _initialize_sparc64_nat (void);
+
+void
+_initialize_sparc64_nat (void)
+{
+ sparc_supply_gregset = sparc64_supply_gregset;
+ sparc_collect_gregset = sparc64_collect_gregset;
+ sparc_supply_fpregset = sparc64_supply_fpregset;
+ sparc_collect_fpregset = sparc64_collect_fpregset;
+ sparc_gregset_supplies_p = sparc64_gregset_supplies_p;
+ sparc_fpregset_supplies_p = sparc64_fpregset_supplies_p;
+}
diff --git a/gdb/sparc64-sol2-nat.c b/gdb/sparc64-sol2-nat.c
new file mode 100644
index 00000000000..2af009df57f
--- /dev/null
+++ b/gdb/sparc64-sol2-nat.c
@@ -0,0 +1,57 @@
+/* Native-dependent code for Solaris UltraSPARC.
+
+ Copyright 2003 Free Software Foundation, Inc.
+
+ 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 "regcache.h"
+
+#include <sys/procfs.h>
+#include "gregset.h"
+
+#include "sparc64-tdep.h"
+
+/* These functions provide the (temporary) glue between the Solaris
+ SPARC target dependent code and the machine independent SVR4 /proc
+ support. */
+
+void
+supply_gregset (prgregset_t *gregs)
+{
+ sparc64_supply_gregset (&sparc64_sol2_gregset, current_regcache, -1, gregs);
+}
+
+void
+supply_fpregset (prfpregset_t *fpregs)
+{
+ sparc64_supply_fpregset (current_regcache, -1, fpregs);
+}
+
+void
+fill_gregset (prgregset_t *gregs, int regnum)
+{
+ sparc64_collect_gregset (&sparc64_sol2_gregset,
+ current_regcache, regnum, gregs);
+}
+
+void
+fill_fpregset (prfpregset_t *fpregs, int regnum)
+{
+ sparc64_collect_fpregset (current_regcache, regnum, fpregs);
+}
diff --git a/gdb/sparc64-sol2-tdep.c b/gdb/sparc64-sol2-tdep.c
new file mode 100644
index 00000000000..c8305080d14
--- /dev/null
+++ b/gdb/sparc64-sol2-tdep.c
@@ -0,0 +1,73 @@
+/* Target-dependent code for Solaris UltraSPARC.
+
+ Copyright 2003 Free Software Foundation, Inc.
+
+ 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 "gdbarch.h"
+#include "symtab.h"
+#include "objfiles.h"
+#include "osabi.h"
+
+#include "sparc64-tdep.h"
+
+/* From <sys/regset.h>. */
+const struct sparc_gregset sparc64_sol2_gregset =
+{
+ 32 * 8, /* "tstate" */
+ 33 * 8, /* %pc */
+ 34 * 8, /* %npc */
+ 35 * 8, /* %y */
+ -1, /* %wim */
+ -1, /* %tbr */
+ 1 * 8, /* %g1 */
+ 16 * 8, /* %l0 */
+ 8 /* sizeof (%y) */
+};
+
+
+void
+sparc64_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ sparc64_init_abi (info, gdbarch);
+
+ /* Solaris has SVR4-style shared libraries... */
+ set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section);
+ set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
+
+ /* ...which means that we need some special handling when doing
+ prologue analysis. */
+ tdep->plt_entry_size = 16;
+
+ /* Solaris has kernel-assisted single-stepping support. */
+ set_gdbarch_software_single_step (gdbarch, NULL);
+}
+
+
+/* Provide a prototype to silence -Wmissing-prototypes. */
+void _initialize_sparc64_sol2_tdep (void);
+
+void
+_initialize_sparc64_sol2_tdep (void)
+{
+ gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
+ GDB_OSABI_SOLARIS, sparc64_sol2_init_abi);
+}
diff --git a/gdb/sparc64-tdep.c b/gdb/sparc64-tdep.c
index 08ea7d740ab..6054f0c80c7 100644
--- a/gdb/sparc64-tdep.c
+++ b/gdb/sparc64-tdep.c
@@ -28,6 +28,8 @@
#include "gdbcore.h"
#include "gdbtypes.h"
#include "inferior.h"
+#include "symtab.h"
+#include "objfiles.h"
#include "osabi.h"
#include "regcache.h"
#include "target.h"
@@ -36,7 +38,6 @@
#include "gdb_assert.h"
#include "gdb_string.h"
-#include "sparc-tdep.h"
#include "sparc64-tdep.h"
/* This file implements the The SPARC 64-bit ABI as defined by the
@@ -56,11 +57,13 @@
/* Macros to extract fields from SPARC instructions. */
#define X_OP(i) (((i) >> 30) & 0x3)
+#define X_RD(i) (((i) >> 25) & 0x1f)
#define X_A(i) (((i) >> 29) & 1)
#define X_COND(i) (((i) >> 25) & 0xf)
#define X_OP2(i) (((i) >> 22) & 0x7)
#define X_IMM22(i) ((i) & 0x3fffff)
#define X_OP3(i) (((i) >> 19) & 0x3f)
+#define X_I(i) (((i) >> 13) & 1)
/* Sign extension macros. */
#define X_DISP22(i) ((X_IMM22 (i) ^ 0x200000) - 0x200000)
#define X_DISP19(i) ((((i) & 0x7ffff) ^ 0x40000) - 0x40000)
@@ -526,17 +529,52 @@ static CORE_ADDR
sparc64_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
struct sparc64_frame_cache *cache)
{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
unsigned long insn;
+ int offset = 0;
+ int dest = -1;
if (current_pc <= pc)
return current_pc;
- /* Check whether the function starts with a SAVE instruction. */
+ /* We have to handle to "Procedure Linkage Table" (PLT) special. On
+ SPARC the linker usually defines a symbol (typically
+ _PROCEDURE_LINKAGE_TABLE_) at the start of the .plt section.
+ This symbol makes us end up here with PC pointing at the start of
+ the PLT and CURRENT_PC probably pointing at a PLT entry. If we
+ would do our normal prologue analysis, we would probably conclude
+ that we've got a frame when in reality we don't, since the
+ dynamic linker patches up the first PLT with some code that
+ starts with a SAVE instruction. Patch up PC such that it points
+ at the start of our PLT entry. */
+ if (tdep->plt_entry_size > 0 && in_plt_section (current_pc, NULL))
+ pc = current_pc - ((current_pc - pc) % tdep->plt_entry_size);
+
insn = sparc_fetch_instruction (pc);
+
+ /* Recognize a SETHI insn and record its destination. */
+ if (X_OP (insn) == 0 && X_OP2 (insn) == 0x04)
+ {
+ dest = X_RD (insn);
+ offset += 4;
+
+ insn = sparc_fetch_instruction (pc + 4);
+ }
+
+ /* Allow for an arithmetic operation on DEST or %g1. */
+ if (X_OP (insn) == 2 && X_I (insn)
+ && (X_RD (insn) == 1 || X_RD (insn) == dest))
+ {
+ offset += 4;
+
+ insn = sparc_fetch_instruction (pc + 8);
+ }
+
+ /* Check for the SAVE instruction that sets up the frame. */
if (X_OP (insn) == 2 && X_OP3 (insn) == 0x3c)
{
cache->frameless_p = 0;
- return pc + 4;
+ return pc + offset + 4;
}
return pc;
@@ -1204,3 +1242,298 @@ sparc64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
frame_unwind_append_sniffer (gdbarch, sparc64_frame_sniffer);
frame_base_set_default (gdbarch, &sparc64_frame_base);
}
+
+
+/* Helper functions for dealing with register sets. */
+
+#define TSTATE_CWP 0x000000000000001f
+#define TSTATE_ICC 0x0000000f00000000
+#define TSTATE_XCC 0x000000f000000000
+
+#define PSR_S 0x00000080
+#define PSR_ICC 0x00f00000
+#define PSR_VERS 0x0f000000
+#define PSR_IMPL 0xf0000000
+#define PSR_V8PLUS 0xff000000
+#define PSR_XCC 0x000f0000
+
+void
+sparc64_supply_gregset (const struct sparc_gregset *gregset,
+ struct regcache *regcache,
+ int regnum, const void *gregs)
+{
+ int sparc32 = (gdbarch_ptr_bit (current_gdbarch) == 32);
+ const char *regs = gregs;
+ int i;
+
+ if (sparc32)
+ {
+ if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
+ {
+ int offset = gregset->r_tstate_offset;
+ ULONGEST tstate, psr;
+ char buf[4];
+
+ tstate = extract_unsigned_integer (regs + offset, 8);
+ psr = ((tstate & TSTATE_CWP) | PSR_S | ((tstate & TSTATE_ICC) >> 12)
+ | ((tstate & TSTATE_XCC) >> 20) | PSR_V8PLUS);
+ store_unsigned_integer (buf, 4, psr);
+ regcache_raw_supply (regcache, SPARC32_PSR_REGNUM, buf);
+ }
+
+ if (regnum == SPARC32_PC_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, SPARC32_PC_REGNUM,
+ regs + gregset->r_pc_offset + 4);
+
+ if (regnum == SPARC32_NPC_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, SPARC32_NPC_REGNUM,
+ regs + gregset->r_npc_offset + 4);
+
+ if (regnum == SPARC32_Y_REGNUM || regnum == -1)
+ {
+ int offset = gregset->r_y_offset + 8 - gregset->r_y_size;
+ regcache_raw_supply (regcache, SPARC32_Y_REGNUM, regs + offset);
+ }
+ }
+ else
+ {
+ if (regnum == SPARC64_STATE_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, SPARC64_STATE_REGNUM,
+ regs + gregset->r_tstate_offset);
+
+ if (regnum == SPARC64_PC_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, SPARC64_PC_REGNUM,
+ regs + gregset->r_pc_offset);
+
+ if (regnum == SPARC64_NPC_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, SPARC64_NPC_REGNUM,
+ regs + gregset->r_npc_offset);
+
+ if (regnum == SPARC64_Y_REGNUM || regnum == -1)
+ {
+ char buf[8];
+
+ memset (buf, 0, 8);
+ memcpy (buf + 8 - gregset->r_y_size,
+ regs + gregset->r_y_offset, gregset->r_y_size);
+ regcache_raw_supply (regcache, SPARC64_Y_REGNUM, buf);
+ }
+ }
+
+ if (regnum == SPARC_G0_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, SPARC_G0_REGNUM, NULL);
+
+ if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
+ {
+ int offset = gregset->r_g1_offset;
+
+ if (sparc32)
+ offset += 4;
+
+ for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
+ {
+ if (regnum == i || regnum == -1)
+ regcache_raw_supply (regcache, i, regs + offset);
+ offset += 8;
+ }
+ }
+
+ if ((regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM) || regnum == -1)
+ {
+ /* Not all of the register set variants include Locals and
+ Inputs. For those that don't, we read them off the stack. */
+ if (gregset->r_l0_offset == -1)
+ {
+ ULONGEST sp;
+
+ regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
+ sparc_supply_rwindow (regcache, sp, regnum);
+ }
+ else
+ {
+ int offset = gregset->r_l0_offset;
+
+ if (sparc32)
+ offset += 4;
+
+ for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++)
+ {
+ if (regnum == i || regnum == -1)
+ regcache_raw_supply (regcache, i, regs + offset);
+ offset += 8;
+ }
+ }
+ }
+}
+
+void
+sparc64_collect_gregset (const struct sparc_gregset *gregset,
+ const struct regcache *regcache,
+ int regnum, void *gregs)
+{
+ int sparc32 = (gdbarch_ptr_bit (current_gdbarch) == 32);
+ char *regs = gregs;
+ int i;
+
+ if (sparc32)
+ {
+ if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
+ {
+ int offset = gregset->r_tstate_offset;
+ ULONGEST tstate, psr;
+ char buf[8];
+
+ tstate = extract_unsigned_integer (regs + offset, 8);
+ regcache_raw_collect (regcache, SPARC32_PSR_REGNUM, buf);
+ psr = extract_unsigned_integer (buf, 4);
+ tstate |= (psr & PSR_ICC) << 12;
+ if ((psr & (PSR_VERS | PSR_IMPL)) == PSR_V8PLUS)
+ tstate |= (psr & PSR_XCC) << 20;
+ store_unsigned_integer (buf, 8, tstate);
+ memcpy (regs + offset, buf, 8);
+ }
+
+ if (regnum == SPARC32_PC_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, SPARC32_PC_REGNUM,
+ regs + gregset->r_pc_offset + 4);
+
+ if (regnum == SPARC32_NPC_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, SPARC32_NPC_REGNUM,
+ regs + gregset->r_npc_offset + 4);
+
+ if (regnum == SPARC32_Y_REGNUM || regnum == -1)
+ {
+ int offset = gregset->r_y_offset + 8 - gregset->r_y_size;
+ regcache_raw_collect (regcache, SPARC32_Y_REGNUM, regs + offset);
+ }
+ }
+ else
+ {
+ if (regnum == SPARC64_STATE_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, SPARC64_STATE_REGNUM,
+ regs + gregset->r_tstate_offset);
+
+ if (regnum == SPARC64_PC_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, SPARC64_PC_REGNUM,
+ regs + gregset->r_pc_offset);
+
+ if (regnum == SPARC64_NPC_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, SPARC64_NPC_REGNUM,
+ regs + gregset->r_npc_offset);
+
+ if (regnum == SPARC64_Y_REGNUM || regnum == -1)
+ {
+ char buf[8];
+
+ regcache_raw_collect (regcache, SPARC64_Y_REGNUM, buf);
+ memcpy (regs + gregset->r_y_offset,
+ buf + 8 - gregset->r_y_size, gregset->r_y_size);
+ }
+ }
+
+ if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
+ {
+ int offset = gregset->r_g1_offset;
+
+ if (sparc32)
+ offset += 4;
+
+ /* %g0 is always zero. */
+ for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
+ {
+ if (regnum == i || regnum == -1)
+ regcache_raw_collect (regcache, i, regs + offset);
+ offset += 8;
+ }
+ }
+
+ if ((regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM) || regnum == -1)
+ {
+ /* Not all of the register set variants include Locals and
+ Inputs. For those that don't, we read them off the stack. */
+ if (gregset->r_l0_offset != -1)
+ {
+ int offset = gregset->r_l0_offset;
+
+ if (sparc32)
+ offset += 4;
+
+ for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++)
+ {
+ if (regnum == i || regnum == -1)
+ regcache_raw_collect (regcache, i, regs + offset);
+ offset += 8;
+ }
+ }
+ }
+}
+
+void
+sparc64_supply_fpregset (struct regcache *regcache,
+ int regnum, const void *fpregs)
+{
+ int sparc32 = (gdbarch_ptr_bit (current_gdbarch) == 32);
+ const char *regs = fpregs;
+ int i;
+
+ for (i = 0; i < 32; i++)
+ {
+ if (regnum == (SPARC_F0_REGNUM + i) || regnum == -1)
+ regcache_raw_supply (regcache, SPARC_F0_REGNUM + i, regs + (i * 4));
+ }
+
+ if (sparc32)
+ {
+ if (regnum == SPARC32_FSR_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, SPARC32_FSR_REGNUM,
+ regs + (32 * 4) + (16 * 8) + 4);
+ }
+ else
+ {
+ for (i = 0; i < 16; i++)
+ {
+ if (regnum == (SPARC64_F32_REGNUM + i) || regnum == -1)
+ regcache_raw_supply (regcache, SPARC64_F32_REGNUM + i,
+ regs + (32 * 4) + (i * 8));
+ }
+
+ if (regnum == SPARC64_FSR_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, SPARC64_FSR_REGNUM,
+ regs + (32 * 4) + (16 * 8));
+ }
+}
+
+void
+sparc64_collect_fpregset (const struct regcache *regcache,
+ int regnum, void *fpregs)
+{
+ int sparc32 = (gdbarch_ptr_bit (current_gdbarch) == 32);
+ char *regs = fpregs;
+ int i;
+
+ for (i = 0; i < 32; i++)
+ {
+ if (regnum == (SPARC_F0_REGNUM + i) || regnum == -1)
+ regcache_raw_collect (regcache, SPARC_F0_REGNUM + i, regs + (i * 4));
+ }
+
+ if (sparc32)
+ {
+ if (regnum == SPARC32_FSR_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, SPARC32_FSR_REGNUM,
+ regs + (32 * 4) + (16 * 8) + 4);
+ }
+ else
+ {
+ for (i = 0; i < 16; i++)
+ {
+ if (regnum == (SPARC64_F32_REGNUM + i) || regnum == -1)
+ regcache_raw_collect (regcache, SPARC64_F32_REGNUM + i,
+ regs + (32 * 4) + (i * 8));
+ }
+
+ if (regnum == SPARC64_FSR_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, SPARC64_FSR_REGNUM,
+ regs + (32 * 4) + (16 * 8));
+ }
+}
diff --git a/gdb/sparc64-tdep.h b/gdb/sparc64-tdep.h
index 4320a68af3d..5995f42fb6c 100644
--- a/gdb/sparc64-tdep.h
+++ b/gdb/sparc64-tdep.h
@@ -24,6 +24,11 @@
#include "sparc-tdep.h"
+/* Register offsets for the general-purpose register set. */
+
+/* UltraSPARC doesn't have %psr. */
+#define r_tstate_offset r_psr_offset
+
/* Register numbers of various important registers. */
enum sparc64_regnum
@@ -67,6 +72,25 @@ enum sparc64_regnum
extern void sparc64_init_abi (struct gdbarch_info info,
struct gdbarch *gdbarch);
+extern void sparc64_supply_gregset (const struct sparc_gregset *gregset,
+ struct regcache *regcache,
+ int regnum, const void *gregs);
+extern void sparc64_collect_gregset (const struct sparc_gregset *gregset,
+ const struct regcache *regcache,
+ int regnum, void *gregs);
+extern void sparc64_supply_fpregset (struct regcache *regcache,
+ int regnum, const void *fpregs);
+extern void sparc64_collect_fpregset (const struct regcache *regcache,
+ int regnum, void *fpregs);
+
+/* Functions and variables exported from sparc64-sol2-tdep.c. */
+
+/* Register offsets for Solaris 2. */
+extern const struct sparc_gregset sparc64_sol2_gregset;
+
+extern void sparc64_sol2_init_abi (struct gdbarch_info info,
+ struct gdbarch *gdbarch);
+
/* Functions exported from sparc64fbsd-tdep.c. */
extern void sparc64fbsd_supply_reg (const char *regs, int regnum);