diff options
author | Mark Kettenis <kettenis@gnu.org> | 2003-11-02 20:26:32 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@gnu.org> | 2003-11-02 20:26:32 +0000 |
commit | 123ebd3f4266580b61135584f1edb0e81b52cfe3 (patch) | |
tree | 2c3349fca920953ad9c2e6108dfaac4431c7e2bf | |
parent | 71738b04c5b4be766affeb5ab003f1ef7ce19544 (diff) | |
download | gdb-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/ChangeLog | 33 | ||||
-rw-r--r-- | gdb/Makefile.in | 25 | ||||
-rw-r--r-- | gdb/config/sparc/linux64.mh | 11 | ||||
-rw-r--r-- | gdb/config/sparc/linux64.mt | 5 | ||||
-rw-r--r-- | gdb/configure.host | 1 | ||||
-rw-r--r-- | gdb/configure.tgt | 1 | ||||
-rw-r--r-- | gdb/sparc64-linux-nat.c | 48 | ||||
-rw-r--r-- | gdb/sparc64-linux-tdep.c | 82 | ||||
-rw-r--r-- | gdb/sparc64-nat.c | 86 | ||||
-rw-r--r-- | gdb/sparc64-sol2-nat.c | 57 | ||||
-rw-r--r-- | gdb/sparc64-sol2-tdep.c | 73 | ||||
-rw-r--r-- | gdb/sparc64-tdep.c | 339 | ||||
-rw-r--r-- | gdb/sparc64-tdep.h | 24 |
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); |