From patchwork Thu Oct 16 22:00:28 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kratochvil X-Patchwork-Id: 3256 Received: (qmail 18037 invoked by alias); 16 Oct 2014 23:00:39 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 18013 invoked by uid 89); 16 Oct 2014 23:00:38 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.1 required=5.0 tests=AWL, BAYES_50, KAM_STOCKGEN, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD, URIBL_BLACK autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 16 Oct 2014 23:00:19 +0000 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s9GM0ske007693 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 16 Oct 2014 18:00:55 -0400 Received: from host2.jankratochvil.net (ovpn-116-79.ams2.redhat.com [10.36.116.79]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s9GM0Skv011970 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=NO); Thu, 16 Oct 2014 18:00:31 -0400 Date: Fri, 17 Oct 2014 00:00:28 +0200 From: Jan Kratochvil To: gdb-patches@sourceware.org Cc: Joel Brobecker Subject: [patch] Remove HPUX Message-ID: <20141016220028.GA25839@host2.jankratochvil.net> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) X-IsSubscribed: yes Hi, IIUC it is a pre-requisite for IPv6 support, some UNICes do not support getaddrinfo required for IPv6. But coincidentally such UNICes are no longer really supported by GDB. Therefore it was concluded we can remove all such UNICes and then we can implement IPv6 easily with getaddrinfo. In mail Re: getaddrinfo available on all GDB hosts? [Re: [PATCH v2] Add IPv6 support for remote TCP connections] Message-ID: <20140211034157.GG5485@adacore.com> https://sourceware.org/ml/gdb-patches/2014-02/msg00333.html Joel said: # [...] HP-UX [...] are probably de facto unmaintained, at this point. So I chose HP-UX first for this patch. # We should probably send an announcement if we ever implement a change # we know might be breaking some platforms, though. Not sure if anything should be really done for this part. I did not test it anyhow, not sure how, it still builds on Linux. I did not investigate too much which other parts of GDB could be removed along, there may be some dead code now (but it always has been). I am not sure if somread.c really can be removed or not, I have removed it. The same patch is also available as a GIT branch at: https://sourceware.org/git/?p=archer.git;a=shortlog;h=refs/heads/jankratochvil/nohpux 24 files changed, 47 insertions(+), 7384 deletions(-) Thanks, Jan 2014-10-16 Jan Kratochvil Remove HPUX. * Makefile.in (ALL_64_TARGET_OBS): Remove ia64-hpux-tdep.o. (ALL_TARGET_OBS): Remove hppa-hpux-tdep.o, solib-som.o and solib-pa64.o. (HFILES_NO_SRCDIR): Remove solib-som.h, inf-ttrace.h, solib-pa64.h and ia64-hpux-tdep.h, solib-ia64-hpux.h. (ALLDEPFILES): Remove hppa-hpux-tdep.c, hppa-hpux-nat.c, ia64-hpux-nat.c, ia64-hpux-tdep.c, somread.c and solib-som.c. * config/djgpp/fnchange.lst: Remove hppa-hpux-nat.c and hppa-hpux-tdep.c. * config/ia64/hpux.mh: Remove file. * config/pa/hpux.mh: Remove file. * configure: Rebuilt. * configure.ac (dlgetmodinfo, somread.o): Remove. * configure.host (hppa*-*-hpux*, ia64-*-hpux*): Make them obsolete. (ia64-*-hpux*): Remove its float format exception. * configure.tgt (hppa*-*-hpux*, ia64-*-hpux*): Make them obsolete. * hppa-hpux-nat.c: Remove file. * hppa-hpux-tdep.c: Remove file. * hppa-tdep.c (struct hppa_unwind_info, struct hppa_objfile_private): Move them here from hppa-tdep.h (hppa_objfile_priv_data, hppa_init_objfile_priv_data): Make it static. (hppa_frame_prev_register_helper): Remove HPPA_FLAGS_REGNUM exception. * hppa-tdep.h (struct hppa_unwind_info, struct hppa_objfile_private): Move them to hppa-tdep.c. (hppa_objfile_priv_data, hppa_init_objfile_priv_data): Remove declarations. * ia64-hpux-nat.c: Remove file. * ia64-hpux-tdep.c: Remove file. * ia64-hpux-tdep.h: Remove file. * inf-ttrace.c: Remove file. * inf-ttrace.h: Remove file. * solib-ia64-hpux.c: Remove file. * solib-ia64-hpux.h: Remove file. * solib-pa64.c: Remove file. * solib-pa64.h: Remove file. * solib-som.c: Remove file. * solib-som.h: Remove file. * somread.c: Remove file. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index a6cebd8..6e516e1 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -611,7 +611,7 @@ ALL_64_TARGET_OBS = \ amd64fbsd-tdep.o amd64-darwin-tdep.o amd64-dicos-tdep.o \ amd64-linux-tdep.o amd64nbsd-tdep.o \ amd64obsd-tdep.o amd64-sol2-tdep.o amd64-tdep.o amd64-windows-tdep.o \ - ia64-hpux-tdep.o ia64-linux-tdep.o ia64-vms-tdep.o ia64-tdep.o \ + ia64-linux-tdep.o ia64-vms-tdep.o ia64-tdep.o \ mips64obsd-tdep.o \ sparc64fbsd-tdep.o sparc64-linux-tdep.o sparc64nbsd-tdep.o \ sparc64obsd-tdep.o sparc64-sol2-tdep.o sparc64-tdep.o @@ -629,7 +629,7 @@ ALL_TARGET_OBS = \ frv-linux-tdep.o frv-tdep.o \ h8300-tdep.o \ hppabsd-tdep.o hppanbsd-tdep.o hppaobsd-tdep.o \ - hppa-hpux-tdep.o hppa-linux-tdep.o hppa-tdep.o \ + hppa-linux-tdep.o hppa-tdep.o \ i386bsd-tdep.o i386-cygwin-tdep.o i386fbsd-tdep.o i386gnu-tdep.o \ i386-linux-tdep.o i386nbsd-tdep.o i386-nto-tdep.o i386obsd-tdep.o \ i386-sol2-tdep.o i386-tdep.o i387-tdep.o \ @@ -674,7 +674,7 @@ ALL_TARGET_OBS = \ nbsd-tdep.o obsd-tdep.o \ sol2-tdep.o \ solib-frv.o solib-svr4.o \ - solib-som.o solib-pa64.o solib-darwin.o solib-dsbt.o \ + solib-darwin.o solib-dsbt.o \ dbug-rom.o dink32-rom.o ppcbug-rom.o m32r-rom.o dsrec.o monitor.o \ remote-m32r-sdi.o remote-mips.o \ xcoffread.o \ @@ -867,7 +867,7 @@ common/gdb_signals.h nat/gdb_thread_db.h common/gdb_vecs.h \ common/x86-xstate.h nat/linux-ptrace.h nat/mips-linux-watch.h \ proc-utils.h aarch64-tdep.h arm-tdep.h ax-gdb.h ppcfbsd-tdep.h \ ppcnbsd-tdep.h cli-out.h gdb_expat.h breakpoint.h infcall.h obsd-tdep.h \ -exec.h m32r-tdep.h osabi.h gdbcore.h solib-som.h amd64bsd-nat.h \ +exec.h m32r-tdep.h osabi.h gdbcore.h amd64bsd-nat.h \ i386bsd-nat.h xml-support.h xml-tdesc.h alphabsd-tdep.h gdb_obstack.h \ ia64-tdep.h ada-lang.h ada-varobj.h varobj.h varobj-iter.h frv-tdep.h \ nto-tdep.h serial.h \ @@ -884,7 +884,7 @@ ser-unix.h inf-ptrace.h terminal.h ui-out.h frame-base.h \ f-lang.h dwarf2loc.h value.h sparc-tdep.h defs.h target-descriptions.h \ objfiles.h common/vec.h disasm.h mips-tdep.h ser-base.h \ gdb_curses.h bfd-target.h memattr.h inferior.h ax.h dummy-frame.h \ -inflow.h fbsd-nat.h ia64-libunwind-tdep.h completer.h inf-ttrace.h \ +inflow.h fbsd-nat.h ia64-libunwind-tdep.h completer.h \ solib-target.h gdb_vfork.h alpha-tdep.h dwarf2expr.h \ m2-lang.h stack.h charset.h addrmap.h command.h solist.h source.h \ target.h target-dcache.h prologue-value.h cp-abi.h tui/tui-hooks.h tui/tui.h \ @@ -901,7 +901,7 @@ complaints.h gdb_proc_service.h gdb_regex.h xtensa-tdep.h inf-loop.h \ common/gdb_wait.h common/gdb_assert.h solib.h ppc-tdep.h cp-support.h glibc-tdep.h \ interps.h auxv.h gdbcmd.h tramp-frame.h mipsnbsd-tdep.h \ amd64-linux-tdep.h linespec.h i387-tdep.h mn10300-tdep.h \ -sparc64-tdep.h monitor.h ppcobsd-tdep.h srec.h solib-pa64.h \ +sparc64-tdep.h monitor.h ppcobsd-tdep.h srec.h \ coff-pe-read.h parser-defs.h gdb_ptrace.h mips-linux-tdep.h \ m68k-tdep.h spu-tdep.h jv-lang.h environ.h amd64-tdep.h \ doublest.h regset.h hppa-tdep.h ppc-linux-tdep.h ppc64-tdep.h \ @@ -918,7 +918,7 @@ annotate.h sim-regno.h dictionary.h dfp.h main.h frame-unwind.h \ remote-fileio.h i386-linux-tdep.h vax-tdep.h objc-lang.h \ sentinel-frame.h bcache.h symfile.h windows-tdep.h linux-tdep.h \ gdb_usleep.h jit.h xml-syscall.h microblaze-tdep.h \ -psymtab.h psympriv.h progspace.h bfin-tdep.h ia64-hpux-tdep.h \ +psymtab.h psympriv.h progspace.h bfin-tdep.h \ amd64-darwin-tdep.h charset-list.h \ config/djgpp/langinfo.h config/djgpp/nl_types.h darwin-nat.h \ dicos-tdep.h filesystem.h gcore.h gdb_wchar.h hppabsd-tdep.h \ @@ -926,7 +926,7 @@ i386-darwin-tdep.h x86-nat.h linux-record.h moxie-tdep.h nios2-tdep.h \ osdata.h procfs.h python/py-event.h python/py-events.h python/py-stopevent.h \ python/python-internal.h python/python.h ravenscar-thread.h record.h \ record-full.h solib-aix.h \ -solib-darwin.h solib-ia64-hpux.h solib-spu.h windows-nat.h xcoffread.h \ +solib-darwin.h solib-spu.h windows-nat.h xcoffread.h \ gnulib/import/extra/snippet/arg-nonnull.h gnulib/import/extra/snippet/c++defs.h \ gnulib/import/extra/snippet/warn-on-use.h \ gnulib/import/stddef.in.h gnulib/import/inttypes.in.h inline-frame.h skip.h \ @@ -1626,7 +1626,7 @@ ALLDEPFILES = \ fork-child.c \ glibc-tdep.c \ go32-nat.c h8300-tdep.c \ - hppa-tdep.c hppa-hpux-tdep.c hppa-hpux-nat.c \ + hppa-tdep.c \ hppa-linux-tdep.c hppa-linux-nat.c \ hppabsd-nat.c hppabsd-tdep.c \ hppaobsd-tdep.c \ @@ -1641,9 +1641,8 @@ ALLDEPFILES = \ i386-linux-tdep.c x86-nat.c \ i386-sol2-nat.c i386-sol2-tdep.c \ i386gnu-nat.c i386gnu-tdep.c \ - ia64-hpux-nat.c ia64-hpux-tdep.c \ ia64-linux-nat.c ia64-linux-tdep.c ia64-tdep.c ia64-vms-tdep.c \ - inf-ptrace.c inf-ttrace.c \ + inf-ptrace.c \ irix5-nat.c \ ia64-libunwind-tdep.c \ linux-fork.c \ @@ -1667,7 +1666,6 @@ ALLDEPFILES = \ nios2-tdep.c nios2-linux-tdep.c \ nbsd-nat.c nbsd-tdep.c obsd-nat.c obsd-tdep.c \ solib-osf.c \ - somread.c solib-som.c \ posix-hdep.c \ ppc-sysv-tdep.c ppc-linux-nat.c ppc-linux-tdep.c ppc64-tdep.c \ ppcfbsd-nat.c ppcfbsd-tdep.c \ diff --git a/gdb/config/djgpp/fnchange.lst b/gdb/config/djgpp/fnchange.lst index cbf11c6..e8fa0cc 100644 --- a/gdb/config/djgpp/fnchange.lst +++ b/gdb/config/djgpp/fnchange.lst @@ -512,8 +512,6 @@ @V@/gdb/amd64-linux-nat.c @V@/gdb/amd64-lnat.c @V@/gdb/hppa-linux-tdep.c @V@/gdb/palnxtdep.c @V@/gdb/hppa-linux-nat.c @V@/gdb/palnxnat.c -@V@/gdb/hppa-hpux-nat.c @V@/gdb/pahpuxnat.c -@V@/gdb/hppa-hpux-tdep.c @V@/gdb/pahpuxtdep.c @V@/gdb/hppanbsd-nat.c @V@/gdb/panbsd-nat.c @V@/gdb/hppanbsd-tdep.c @V@/gdb/panbsd-tdep.c @V@/gdb/amd64-windows-nat.c @V@/gdb/amd64-wnat.c diff --git a/gdb/config/ia64/hpux.mh b/gdb/config/ia64/hpux.mh deleted file mode 100644 index 7bbfab4..0000000 --- a/gdb/config/ia64/hpux.mh +++ /dev/null @@ -1,3 +0,0 @@ -# Host: ia64 running HP-UX -NATDEPFILES= fork-child.o inf-ttrace.o ia64-hpux-nat.o \ - solib-ia64-hpux.o diff --git a/gdb/config/pa/hpux.mh b/gdb/config/pa/hpux.mh deleted file mode 100644 index 3151120..0000000 --- a/gdb/config/pa/hpux.mh +++ /dev/null @@ -1,3 +0,0 @@ -# Host: PA-RISC HP-UX -NATDEPFILES= fork-child.o inf-ptrace.o inf-ttrace.o \ - hppa-hpux-nat.o diff --git a/gdb/configure b/gdb/configure index 889103c..c515ca2 100755 --- a/gdb/configure +++ b/gdb/configure @@ -6754,64 +6754,6 @@ fi fi -# On HP/UX we may need libxpdl for dlgetmodinfo (used by solib-pa64.c). -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlgetmodinfo" >&5 -$as_echo_n "checking for library containing dlgetmodinfo... " >&6; } -if test "${ac_cv_search_dlgetmodinfo+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char dlgetmodinfo (); -int -main () -{ -return dlgetmodinfo (); - ; - return 0; -} -_ACEOF -for ac_lib in '' dl xpdl; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_dlgetmodinfo=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if test "${ac_cv_search_dlgetmodinfo+set}" = set; then : - break -fi -done -if test "${ac_cv_search_dlgetmodinfo+set}" = set; then : - -else - ac_cv_search_dlgetmodinfo=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlgetmodinfo" >&5 -$as_echo "$ac_cv_search_dlgetmodinfo" >&6; } -ac_res=$ac_cv_search_dlgetmodinfo -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - -fi - - @@ -13381,54 +13323,6 @@ if test $gdb_cv_var_macho = yes; then CONFIG_OBS="$CONFIG_OBS machoread.o" fi -# Add SOM support to GDB, but only if BFD includes it. - - OLD_CFLAGS=$CFLAGS - OLD_LDFLAGS=$LDFLAGS - OLD_LIBS=$LIBS - # Put the old CFLAGS/LDFLAGS last, in case the user's (C|LD)FLAGS - # points somewhere with bfd, with -I/foo/lib and -L/foo/lib. We - # always want our bfd. - CFLAGS="-I${srcdir}/../include -I../bfd -I${srcdir}/../bfd $CFLAGS" - LDFLAGS="-L../bfd -L../libiberty $LDFLAGS" - intl=`echo $LIBINTL | sed 's,${top_builddir}/,,g'` - LIBS="-lbfd -liberty $intl $LIBS" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SOM support in BFD" >&5 -$as_echo_n "checking for SOM support in BFD... " >&6; } -if test "${gdb_cv_var_som+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - #include "bfd.h" - #include "som.h" - -int -main () -{ -return bfd_som_attach_aux_hdr (NULL, 0, NULL); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - gdb_cv_var_som=yes -else - gdb_cv_var_som=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_var_som" >&5 -$as_echo "$gdb_cv_var_som" >&6; } - CFLAGS=$OLD_CFLAGS - LDFLAGS=$OLD_LDFLAGS - LIBS=$OLD_LIBS -if test $gdb_cv_var_som = yes; then - CONFIG_OBS="$CONFIG_OBS somread.o" -fi - # Add any host-specific objects to GDB. CONFIG_OBS="${CONFIG_OBS} ${gdb_host_obs}" diff --git a/gdb/configure.ac b/gdb/configure.ac index 2b4f5b0..49dd68a 100644 --- a/gdb/configure.ac +++ b/gdb/configure.ac @@ -518,9 +518,6 @@ AC_SEARCH_LIBS(socketpair, socket) # Link in zlib if we can. This allows us to read compressed debug sections. AM_ZLIB -# On HP/UX we may need libxpdl for dlgetmodinfo (used by solib-pa64.c). -AC_SEARCH_LIBS(dlgetmodinfo, [dl xpdl]) - AM_ICONV # GDB may fork/exec the iconv program to get the list of supported character @@ -2106,13 +2103,6 @@ if test $gdb_cv_var_macho = yes; then CONFIG_OBS="$CONFIG_OBS machoread.o" fi -# Add SOM support to GDB, but only if BFD includes it. -GDB_AC_CHECK_BFD([for SOM support in BFD], gdb_cv_var_som, - [bfd_som_attach_aux_hdr (NULL, 0, NULL)], som.h) -if test $gdb_cv_var_som = yes; then - CONFIG_OBS="$CONFIG_OBS somread.o" -fi - # Add any host-specific objects to GDB. CONFIG_OBS="${CONFIG_OBS} ${gdb_host_obs}" diff --git a/gdb/configure.host b/gdb/configure.host index 5f77166..0d1a8d2 100644 --- a/gdb/configure.host +++ b/gdb/configure.host @@ -43,6 +43,8 @@ case $host in sparc-*-netbsd* | \ rs6000-*-lynxos* | \ vax-*-netbsd* | \ + hppa*-*-hpux* | \ + ia64-*-hpux* | \ null) echo "*** Configuration $host is obsolete." >&2 echo "*** Support has been REMOVED." >&2 @@ -93,8 +95,6 @@ arm*-*-netbsdelf* | arm*-*-knetbsd*-gnu) gdb_host=nbsdelf ;; arm*-*-openbsd*) gdb_host=nbsdelf ;; -hppa*-*-hpux*) - gdb_host=hpux ;; hppa*-*-linux*) gdb_host=linux ;; hppa*-*-netbsd*) gdb_host=nbsd ;; hppa*-*-openbsd*) gdb_host=obsd ;; @@ -117,7 +117,6 @@ i[34567]86-*-solaris2.1[0-9]* | x86_64-*-solaris2.1[0-9]*) i[34567]86-*-solaris*) gdb_host=i386sol2 ;; i[34567]86-*-cygwin*) gdb_host=cygwin ;; -ia64-*-hpux*) gdb_host=hpux ;; ia64-*-linux*) gdb_host=linux ;; m68*-*-linux*) gdb_host=linux ;; @@ -213,11 +212,6 @@ m68*-*-*) gdb_host_double_format="&floatformat_ieee_double_big" gdb_host_long_double_format="&floatformat_m68881_ext" ;; -ia64-*-hpux*) - gdb_host_float_format="&floatformat_ieee_single_big" - gdb_host_double_format="&floatformat_ieee_double_big" - gdb_host_long_double_format="&floatformat_ia64_quad_big" - ;; *) gdb_host_float_format=0 gdb_host_double_format=0 diff --git a/gdb/configure.tgt b/gdb/configure.tgt index d362cd9..8ff5300 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -23,6 +23,8 @@ case $targ in mips*-*-pe | \ rs6000-*-lynxos* | \ sh*-*-pe | \ + hppa*-*-hpux* | \ + ia64-*-hpux* | \ null) echo "*** Configuration $targ is obsolete." >&2 echo "*** Support has been REMOVED." >&2 @@ -152,10 +154,6 @@ h8300-*-*) gdb_sim=../sim/h8300/libsim.a ;; -hppa*-*-hpux*) - # Target: HP PA-RISC running hpux - gdb_target_obs="hppa-tdep.o hppa-hpux-tdep.o solib-som.o solib-pa64.o" - ;; hppa*-*-linux*) # Target: HP PA-RISC running Linux gdb_target_obs="hppa-tdep.o hppa-linux-tdep.o glibc-tdep.o \ @@ -250,10 +248,6 @@ i[34567]86-*-*) gdb_target_obs="i386-tdep.o i387-tdep.o" ;; -ia64-*-hpux*) - # Target: Intel IA-64 running HP-UX - gdb_target_obs="ia64-tdep.o ia64-hpux-tdep.o" - ;; ia64-*-linux*) # Target: Intel IA-64 running GNU/Linux gdb_target_obs="ia64-tdep.o ia64-linux-tdep.o linux-tdep.o \ diff --git a/gdb/hppa-hpux-nat.c b/gdb/hppa-hpux-nat.c deleted file mode 100644 index 65a2b85..0000000 --- a/gdb/hppa-hpux-nat.c +++ /dev/null @@ -1,273 +0,0 @@ -/* Native-dependent code for PA-RISC HP-UX. - - Copyright (C) 2004-2014 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 3 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, see . */ - -#include "defs.h" -#include "inferior.h" -#include "regcache.h" -#include "target.h" - -#include -#include -#include - -#ifdef HAVE_TTRACE -#include -#endif - -#include "hppa-tdep.h" -#include "solib-som.h" -#include "inf-ptrace.h" -#include "inf-ttrace.h" - -/* Return the offset of register REGNUM within `struct save_state'. - The offset returns depends on the flags in the "flags" register and - the register size (32-bit or 64-bit). These are taken from - REGCACHE. */ - -static LONGEST -hppa_hpux_save_state_offset (struct regcache *regcache, int regnum) -{ - LONGEST offset; - - if (regnum == HPPA_FLAGS_REGNUM) - return ssoff (ss_flags); - - if (HPPA_R0_REGNUM < regnum && regnum < HPPA_FP0_REGNUM) - { - struct gdbarch *arch = get_regcache_arch (regcache); - size_t size = register_size (arch, HPPA_R1_REGNUM); - ULONGEST flags; - - gdb_assert (size == 4 || size == 8); - - regcache_cooked_read_unsigned (regcache, HPPA_FLAGS_REGNUM, &flags); - if (flags & SS_WIDEREGS) - offset = ssoff (ss_wide) + (8 - size) + (regnum - HPPA_R0_REGNUM) * 8; - else - offset = ssoff (ss_narrow) + (regnum - HPPA_R1_REGNUM) * 4; - } - else - { - struct gdbarch *arch = get_regcache_arch (regcache); - size_t size = register_size (arch, HPPA_FP0_REGNUM); - - gdb_assert (size == 4 || size == 8); - gdb_assert (regnum >= HPPA_FP0_REGNUM); - offset = ssoff(ss_fpblock) + (regnum - HPPA_FP0_REGNUM) * size; - } - - gdb_assert (offset < sizeof (save_state_t)); - return offset; -} - -/* Just in case a future version of PA-RISC HP-UX won't have ptrace(2) - at all. */ -#ifndef PTRACE_TYPE_RET -#define PTRACE_TYPE_RET void -#endif - -static void -hppa_hpux_fetch_register (struct regcache *regcache, int regnum) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - CORE_ADDR addr; - size_t size; - PTRACE_TYPE_RET *buf; - pid_t pid; - int i; - - pid = ptid_get_pid (inferior_ptid); - - /* This isn't really an address, but ptrace thinks of it as one. */ - addr = hppa_hpux_save_state_offset (regcache, regnum); - size = register_size (gdbarch, regnum); - - gdb_assert (size == 4 || size == 8); - buf = alloca (size); - -#ifdef HAVE_TTRACE - { - lwpid_t lwp = ptid_get_lwp (inferior_ptid); - - if (ttrace (TT_LWP_RUREGS, pid, lwp, addr, size, (uintptr_t)buf) == -1) - error (_("Couldn't read register %s (#%d): %s"), - gdbarch_register_name (gdbarch, regnum), - regnum, safe_strerror (errno)); - } -#else - { - int i; - - /* Read the register contents from the inferior a chuck at the time. */ - for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++) - { - errno = 0; - buf[i] = ptrace (PT_RUREGS, pid, (PTRACE_TYPE_ARG3) addr, 0, 0); - if (errno != 0) - error (_("Couldn't read register %s (#%d): %s"), - gdbarch_register_name (gdbarch, regnum), - regnum, safe_strerror (errno)); - - addr += sizeof (PTRACE_TYPE_RET); - } - } -#endif - - /* Take care with the "flags" register. It's stored as an `int' in - `struct save_state', even for 64-bit code. */ - if (regnum == HPPA_FLAGS_REGNUM && size == 8) - { - ULONGEST flags; - flags = extract_unsigned_integer ((gdb_byte *)buf, 4, byte_order); - store_unsigned_integer ((gdb_byte *)buf, 8, byte_order, flags); - } - - regcache_raw_supply (regcache, regnum, buf); -} - -static void -hppa_hpux_fetch_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - if (regnum == -1) - for (regnum = 0; - regnum < gdbarch_num_regs (get_regcache_arch (regcache)); - regnum++) - hppa_hpux_fetch_register (regcache, regnum); - else - hppa_hpux_fetch_register (regcache, regnum); -} - -/* Store register REGNUM into the inferior. */ - -static void -hppa_hpux_store_register (struct regcache *regcache, int regnum) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - CORE_ADDR addr; - size_t size; - PTRACE_TYPE_RET *buf; - pid_t pid; - - pid = ptid_get_pid (inferior_ptid); - - /* This isn't really an address, but ptrace thinks of it as one. */ - addr = hppa_hpux_save_state_offset (regcache, regnum); - size = register_size (gdbarch, regnum); - - gdb_assert (size == 4 || size == 8); - buf = alloca (size); - - regcache_raw_collect (regcache, regnum, buf); - - /* Take care with the "flags" register. It's stored as an `int' in - `struct save_state', even for 64-bit code. */ - if (regnum == HPPA_FLAGS_REGNUM && size == 8) - { - ULONGEST flags; - flags = extract_unsigned_integer ((gdb_byte *)buf, 8, byte_order); - store_unsigned_integer ((gdb_byte *)buf, 4, byte_order, flags); - size = 4; - } - -#ifdef HAVE_TTRACE - { - lwpid_t lwp = ptid_get_lwp (inferior_ptid); - - if (ttrace (TT_LWP_WUREGS, pid, lwp, addr, size, (uintptr_t)buf) == -1) - error (_("Couldn't write register %s (#%d): %s"), - gdbarch_register_name (gdbarch, regnum), - regnum, safe_strerror (errno)); - } -#else - { - int i; - - /* Write the register contents into the inferior a chunk at the time. */ - for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++) - { - errno = 0; - ptrace (PT_WUREGS, pid, (PTRACE_TYPE_ARG3) addr, buf[i], 0); - if (errno != 0) - error (_("Couldn't write register %s (#%d): %s"), - gdbarch_register_name (gdbarch, regnum), - regnum, safe_strerror (errno)); - - addr += sizeof (PTRACE_TYPE_RET); - } - } -#endif -} - -/* Store register REGNUM back into the inferior. If REGNUM is -1, do - this for all registers (including the floating point registers). */ - -static void -hppa_hpux_store_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - if (regnum == -1) - for (regnum = 0; - regnum < gdbarch_num_regs (get_regcache_arch (regcache)); - regnum++) - hppa_hpux_store_register (regcache, regnum); - else - hppa_hpux_store_register (regcache, regnum); -} - -/* Set hpux_major_release variable to the value retrieved from a call to - uname function. */ - -static void -set_hpux_major_release (void) -{ - struct utsname x; - char *p; - - uname (&x); - p = strchr (x.release, '.'); - if (p) - hpux_major_release = atoi (p + 1); -} - - - -/* Prevent warning from -Wmissing-prototypes. */ -void _initialize_hppa_hpux_nat (void); - -void -_initialize_hppa_hpux_nat (void) -{ - struct target_ops *t; - - set_hpux_major_release (); - -#ifdef HAVE_TTRACE - t = inf_ttrace_target (); -#else - t = inf_ptrace_target (); -#endif - - t->to_fetch_registers = hppa_hpux_fetch_inferior_registers; - t->to_store_registers = hppa_hpux_store_inferior_registers; - - add_target (t); -} diff --git a/gdb/hppa-hpux-tdep.c b/gdb/hppa-hpux-tdep.c deleted file mode 100644 index 6ec2af9..0000000 --- a/gdb/hppa-hpux-tdep.c +++ /dev/null @@ -1,1570 +0,0 @@ -/* Target-dependent code for HP-UX on PA-RISC. - - Copyright (C) 2002-2014 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 3 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, see . */ - -#include "defs.h" -#include "arch-utils.h" -#include "gdbcore.h" -#include "osabi.h" -#include "frame.h" -#include "frame-unwind.h" -#include "trad-frame.h" -#include "symtab.h" -#include "objfiles.h" -#include "inferior.h" -#include "infcall.h" -#include "observer.h" -#include "hppa-tdep.h" -#include "solib-som.h" -#include "solib-pa64.h" -#include "regset.h" -#include "regcache.h" - -#define IS_32BIT_TARGET(_gdbarch) \ - ((gdbarch_tdep (_gdbarch))->bytes_per_address == 4) - -/* Bit in the `ss_flag' member of `struct save_state' that indicates - that the 64-bit register values are live. From - . */ -#define HPPA_HPUX_SS_WIDEREGS 0x40 - -/* Offsets of various parts of `struct save_state'. From - . */ -#define HPPA_HPUX_SS_FLAGS_OFFSET 0 -#define HPPA_HPUX_SS_NARROW_OFFSET 4 -#define HPPA_HPUX_SS_FPBLOCK_OFFSET 256 -#define HPPA_HPUX_SS_WIDE_OFFSET 640 - -/* The size of `struct save_state. */ -#define HPPA_HPUX_SAVE_STATE_SIZE 1152 - -/* The size of `struct pa89_save_state', which corresponds to PA-RISC - 1.1, the lowest common denominator that we support. */ -#define HPPA_HPUX_PA89_SAVE_STATE_SIZE 512 - - -/* Forward declarations. */ -extern void _initialize_hppa_hpux_tdep (void); -extern initialize_file_ftype _initialize_hppa_hpux_tdep; - -/* Return one if PC is in the call path of a trampoline, else return zero. - - Note we return one for *any* call trampoline (long-call, arg-reloc), not - just shared library trampolines (import, export). */ - -static int -hppa32_hpux_in_solib_call_trampoline (struct gdbarch *gdbarch, CORE_ADDR pc) -{ - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct bound_minimal_symbol minsym; - struct unwind_table_entry *u; - - /* First see if PC is in one of the two C-library trampolines. */ - if (pc == hppa_symbol_address("$$dyncall") - || pc == hppa_symbol_address("_sr4export")) - return 1; - - minsym = lookup_minimal_symbol_by_pc (pc); - if (minsym.minsym - && strcmp (MSYMBOL_LINKAGE_NAME (minsym.minsym), ".stub") == 0) - return 1; - - /* Get the unwind descriptor corresponding to PC, return zero - if no unwind was found. */ - u = find_unwind_entry (pc); - if (!u) - return 0; - - /* If this isn't a linker stub, then return now. */ - if (u->stub_unwind.stub_type == 0) - return 0; - - /* By definition a long-branch stub is a call stub. */ - if (u->stub_unwind.stub_type == LONG_BRANCH) - return 1; - - /* The call and return path execute the same instructions within - an IMPORT stub! So an IMPORT stub is both a call and return - trampoline. */ - if (u->stub_unwind.stub_type == IMPORT) - return 1; - - /* Parameter relocation stubs always have a call path and may have a - return path. */ - if (u->stub_unwind.stub_type == PARAMETER_RELOCATION - || u->stub_unwind.stub_type == EXPORT) - { - CORE_ADDR addr; - - /* Search forward from the current PC until we hit a branch - or the end of the stub. */ - for (addr = pc; addr <= u->region_end; addr += 4) - { - unsigned long insn; - - insn = read_memory_integer (addr, 4, byte_order); - - /* Does it look like a bl? If so then it's the call path, if - we find a bv or be first, then we're on the return path. */ - if ((insn & 0xfc00e000) == 0xe8000000) - return 1; - else if ((insn & 0xfc00e001) == 0xe800c000 - || (insn & 0xfc000000) == 0xe0000000) - return 0; - } - - /* Should never happen. */ - warning (_("Unable to find branch in parameter relocation stub.")); - return 0; - } - - /* Unknown stub type. For now, just return zero. */ - return 0; -} - -static int -hppa64_hpux_in_solib_call_trampoline (struct gdbarch *gdbarch, CORE_ADDR pc) -{ - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - - /* PA64 has a completely different stub/trampoline scheme. Is it - better? Maybe. It's certainly harder to determine with any - certainty that we are in a stub because we can not refer to the - unwinders to help. - - The heuristic is simple. Try to lookup the current PC value in th - minimal symbol table. If that fails, then assume we are not in a - stub and return. - - Then see if the PC value falls within the section bounds for the - section containing the minimal symbol we found in the first - step. If it does, then assume we are not in a stub and return. - - Finally peek at the instructions to see if they look like a stub. */ - struct bound_minimal_symbol minsym; - asection *sec; - CORE_ADDR addr; - int insn; - - minsym = lookup_minimal_symbol_by_pc (pc); - if (! minsym.minsym) - return 0; - - sec = MSYMBOL_OBJ_SECTION (minsym.objfile, minsym.minsym)->the_bfd_section; - - if (bfd_get_section_vma (sec->owner, sec) <= pc - && pc < (bfd_get_section_vma (sec->owner, sec) - + bfd_section_size (sec->owner, sec))) - return 0; - - /* We might be in a stub. Peek at the instructions. Stubs are 3 - instructions long. */ - insn = read_memory_integer (pc, 4, byte_order); - - /* Find out where we think we are within the stub. */ - if ((insn & 0xffffc00e) == 0x53610000) - addr = pc; - else if ((insn & 0xffffffff) == 0xe820d000) - addr = pc - 4; - else if ((insn & 0xffffc00e) == 0x537b0000) - addr = pc - 8; - else - return 0; - - /* Now verify each insn in the range looks like a stub instruction. */ - insn = read_memory_integer (addr, 4, byte_order); - if ((insn & 0xffffc00e) != 0x53610000) - return 0; - - /* Now verify each insn in the range looks like a stub instruction. */ - insn = read_memory_integer (addr + 4, 4, byte_order); - if ((insn & 0xffffffff) != 0xe820d000) - return 0; - - /* Now verify each insn in the range looks like a stub instruction. */ - insn = read_memory_integer (addr + 8, 4, byte_order); - if ((insn & 0xffffc00e) != 0x537b0000) - return 0; - - /* Looks like a stub. */ - return 1; -} - -/* Return one if PC is in the return path of a trampoline, else return zero. - - Note we return one for *any* call trampoline (long-call, arg-reloc), not - just shared library trampolines (import, export). */ - -static int -hppa_hpux_in_solib_return_trampoline (struct gdbarch *gdbarch, - CORE_ADDR pc, const char *name) -{ - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct unwind_table_entry *u; - - /* Get the unwind descriptor corresponding to PC, return zero - if no unwind was found. */ - u = find_unwind_entry (pc); - if (!u) - return 0; - - /* If this isn't a linker stub or it's just a long branch stub, then - return zero. */ - if (u->stub_unwind.stub_type == 0 || u->stub_unwind.stub_type == LONG_BRANCH) - return 0; - - /* The call and return path execute the same instructions within - an IMPORT stub! So an IMPORT stub is both a call and return - trampoline. */ - if (u->stub_unwind.stub_type == IMPORT) - return 1; - - /* Parameter relocation stubs always have a call path and may have a - return path. */ - if (u->stub_unwind.stub_type == PARAMETER_RELOCATION - || u->stub_unwind.stub_type == EXPORT) - { - CORE_ADDR addr; - - /* Search forward from the current PC until we hit a branch - or the end of the stub. */ - for (addr = pc; addr <= u->region_end; addr += 4) - { - unsigned long insn; - - insn = read_memory_integer (addr, 4, byte_order); - - /* Does it look like a bl? If so then it's the call path, if - we find a bv or be first, then we're on the return path. */ - if ((insn & 0xfc00e000) == 0xe8000000) - return 0; - else if ((insn & 0xfc00e001) == 0xe800c000 - || (insn & 0xfc000000) == 0xe0000000) - return 1; - } - - /* Should never happen. */ - warning (_("Unable to find branch in parameter relocation stub.")); - return 0; - } - - /* Unknown stub type. For now, just return zero. */ - return 0; - -} - -/* Figure out if PC is in a trampoline, and if so find out where - the trampoline will jump to. If not in a trampoline, return zero. - - Simple code examination probably is not a good idea since the code - sequences in trampolines can also appear in user code. - - We use unwinds and information from the minimal symbol table to - determine when we're in a trampoline. This won't work for ELF - (yet) since it doesn't create stub unwind entries. Whether or - not ELF will create stub unwinds or normal unwinds for linker - stubs is still being debated. - - This should handle simple calls through dyncall or sr4export, - long calls, argument relocation stubs, and dyncall/sr4export - calling an argument relocation stub. It even handles some stubs - used in dynamic executables. */ - -static CORE_ADDR -hppa_hpux_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc) -{ - struct gdbarch *gdbarch = get_frame_arch (frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - int word_size = gdbarch_ptr_bit (gdbarch) / 8; - long orig_pc = pc; - long prev_inst, curr_inst, loc; - struct bound_minimal_symbol msym; - struct unwind_table_entry *u; - - /* Addresses passed to dyncall may *NOT* be the actual address - of the function. So we may have to do something special. */ - if (pc == hppa_symbol_address("$$dyncall")) - { - pc = (CORE_ADDR) get_frame_register_unsigned (frame, 22); - - /* If bit 30 (counting from the left) is on, then pc is the address of - the PLT entry for this function, not the address of the function - itself. Bit 31 has meaning too, but only for MPE. */ - if (pc & 0x2) - pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, word_size, - byte_order); - } - if (pc == hppa_symbol_address("$$dyncall_external")) - { - pc = (CORE_ADDR) get_frame_register_unsigned (frame, 22); - pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, word_size, byte_order); - } - else if (pc == hppa_symbol_address("_sr4export")) - pc = (CORE_ADDR) get_frame_register_unsigned (frame, 22); - - /* Get the unwind descriptor corresponding to PC, return zero - if no unwind was found. */ - u = find_unwind_entry (pc); - if (!u) - return 0; - - /* If this isn't a linker stub, then return now. */ - /* elz: attention here! (FIXME) because of a compiler/linker - error, some stubs which should have a non zero stub_unwind.stub_type - have unfortunately a value of zero. So this function would return here - as if we were not in a trampoline. To fix this, we go look at the partial - symbol information, which reports this guy as a stub. - (FIXME): Unfortunately, we are not that lucky: it turns out that the - partial symbol information is also wrong sometimes. This is because - when it is entered (somread.c::som_symtab_read()) it can happen that - if the type of the symbol (from the som) is Entry, and the symbol is - in a shared library, then it can also be a trampoline. This would be OK, - except that I believe the way they decide if we are ina shared library - does not work. SOOOO..., even if we have a regular function w/o - trampolines its minimal symbol can be assigned type mst_solib_trampoline. - Also, if we find that the symbol is a real stub, then we fix the unwind - descriptor, and define the stub type to be EXPORT. - Hopefully this is correct most of the times. */ - if (u->stub_unwind.stub_type == 0) - { - -/* elz: NOTE (FIXME!) once the problem with the unwind information is fixed - we can delete all the code which appears between the lines. */ -/*--------------------------------------------------------------------------*/ - msym = lookup_minimal_symbol_by_pc (pc); - - if (msym.minsym == NULL - || MSYMBOL_TYPE (msym.minsym) != mst_solib_trampoline) - return orig_pc == pc ? 0 : pc & ~0x3; - - else if (msym.minsym != NULL - && MSYMBOL_TYPE (msym.minsym) == mst_solib_trampoline) - { - struct objfile *objfile; - struct minimal_symbol *msymbol; - int function_found = 0; - - /* Go look if there is another minimal symbol with the same name as - this one, but with type mst_text. This would happen if the msym - is an actual trampoline, in which case there would be another - symbol with the same name corresponding to the real function. */ - - ALL_MSYMBOLS (objfile, msymbol) - { - if (MSYMBOL_TYPE (msymbol) == mst_text - && strcmp (MSYMBOL_LINKAGE_NAME (msymbol), - MSYMBOL_LINKAGE_NAME (msym.minsym)) == 0) - { - function_found = 1; - break; - } - } - - if (function_found) - /* The type of msym is correct (mst_solib_trampoline), but - the unwind info is wrong, so set it to the correct value. */ - u->stub_unwind.stub_type = EXPORT; - else - /* The stub type info in the unwind is correct (this is not a - trampoline), but the msym type information is wrong, it - should be mst_text. So we need to fix the msym, and also - get out of this function. */ - { - MSYMBOL_TYPE (msym.minsym) = mst_text; - return orig_pc == pc ? 0 : pc & ~0x3; - } - } - -/*--------------------------------------------------------------------------*/ - } - - /* It's a stub. Search for a branch and figure out where it goes. - Note we have to handle multi insn branch sequences like ldil;ble. - Most (all?) other branches can be determined by examining the contents - of certain registers and the stack. */ - - loc = pc; - curr_inst = 0; - prev_inst = 0; - while (1) - { - /* Make sure we haven't walked outside the range of this stub. */ - if (u != find_unwind_entry (loc)) - { - warning (_("Unable to find branch in linker stub")); - return orig_pc == pc ? 0 : pc & ~0x3; - } - - prev_inst = curr_inst; - curr_inst = read_memory_integer (loc, 4, byte_order); - - /* Does it look like a branch external using %r1? Then it's the - branch from the stub to the actual function. */ - if ((curr_inst & 0xffe0e000) == 0xe0202000) - { - /* Yup. See if the previous instruction loaded - a value into %r1. If so compute and return the jump address. */ - if ((prev_inst & 0xffe00000) == 0x20200000) - return (hppa_extract_21 (prev_inst) - + hppa_extract_17 (curr_inst)) & ~0x3; - else - { - warning (_("Unable to find ldil X,%%r1 " - "before ble Y(%%sr4,%%r1).")); - return orig_pc == pc ? 0 : pc & ~0x3; - } - } - - /* Does it look like a be 0(sr0,%r21)? OR - Does it look like a be, n 0(sr0,%r21)? OR - Does it look like a bve (r21)? (this is on PA2.0) - Does it look like a bve, n(r21)? (this is also on PA2.0) - That's the branch from an - import stub to an export stub. - - It is impossible to determine the target of the branch via - simple examination of instructions and/or data (consider - that the address in the plabel may be the address of the - bind-on-reference routine in the dynamic loader). - - So we have try an alternative approach. - - Get the name of the symbol at our current location; it should - be a stub symbol with the same name as the symbol in the - shared library. - - Then lookup a minimal symbol with the same name; we should - get the minimal symbol for the target routine in the shared - library as those take precedence of import/export stubs. */ - if ((curr_inst == 0xe2a00000) || - (curr_inst == 0xe2a00002) || - (curr_inst == 0xeaa0d000) || - (curr_inst == 0xeaa0d002)) - { - struct bound_minimal_symbol stubsym; - struct bound_minimal_symbol libsym; - - stubsym = lookup_minimal_symbol_by_pc (loc); - if (stubsym.minsym == NULL) - { - warning (_("Unable to find symbol for 0x%lx"), loc); - return orig_pc == pc ? 0 : pc & ~0x3; - } - - libsym = lookup_minimal_symbol (MSYMBOL_LINKAGE_NAME (stubsym.minsym), - NULL, NULL); - if (libsym.minsym == NULL) - { - warning (_("Unable to find library symbol for %s."), - MSYMBOL_PRINT_NAME (stubsym.minsym)); - return orig_pc == pc ? 0 : pc & ~0x3; - } - - return MSYMBOL_VALUE (libsym.minsym); - } - - /* Does it look like bl X,%rp or bl X,%r0? Another way to do a - branch from the stub to the actual function. */ - /*elz */ - else if ((curr_inst & 0xffe0e000) == 0xe8400000 - || (curr_inst & 0xffe0e000) == 0xe8000000 - || (curr_inst & 0xffe0e000) == 0xe800A000) - return (loc + hppa_extract_17 (curr_inst) + 8) & ~0x3; - - /* Does it look like bv (rp)? Note this depends on the - current stack pointer being the same as the stack - pointer in the stub itself! This is a branch on from the - stub back to the original caller. */ - /*else if ((curr_inst & 0xffe0e000) == 0xe840c000) */ - else if ((curr_inst & 0xffe0f000) == 0xe840c000) - { - /* Yup. See if the previous instruction loaded - rp from sp - 8. */ - if (prev_inst == 0x4bc23ff1) - { - CORE_ADDR sp; - sp = get_frame_register_unsigned (frame, HPPA_SP_REGNUM); - return read_memory_integer (sp - 8, 4, byte_order) & ~0x3; - } - else - { - warning (_("Unable to find restore of %%rp before bv (%%rp).")); - return orig_pc == pc ? 0 : pc & ~0x3; - } - } - - /* elz: added this case to capture the new instruction - at the end of the return part of an export stub used by - the PA2.0: BVE, n (rp) */ - else if ((curr_inst & 0xffe0f000) == 0xe840d000) - { - return (read_memory_integer - (get_frame_register_unsigned (frame, HPPA_SP_REGNUM) - 24, - word_size, byte_order)) & ~0x3; - } - - /* What about be,n 0(sr0,%rp)? It's just another way we return to - the original caller from the stub. Used in dynamic executables. */ - else if (curr_inst == 0xe0400002) - { - /* The value we jump to is sitting in sp - 24. But that's - loaded several instructions before the be instruction. - I guess we could check for the previous instruction being - mtsp %r1,%sr0 if we want to do sanity checking. */ - return (read_memory_integer - (get_frame_register_unsigned (frame, HPPA_SP_REGNUM) - 24, - word_size, byte_order)) & ~0x3; - } - - /* Haven't found the branch yet, but we're still in the stub. - Keep looking. */ - loc += 4; - } -} - -static void -hppa_skip_permanent_breakpoint (struct regcache *regcache) -{ - /* To step over a breakpoint instruction on the PA takes some - fiddling with the instruction address queue. - - When we stop at a breakpoint, the IA queue front (the instruction - we're executing now) points at the breakpoint instruction, and - the IA queue back (the next instruction to execute) points to - whatever instruction we would execute after the breakpoint, if it - were an ordinary instruction. This is the case even if the - breakpoint is in the delay slot of a branch instruction. - - Clearly, to step past the breakpoint, we need to set the queue - front to the back. But what do we put in the back? What - instruction comes after that one? Because of the branch delay - slot, the next insn is always at the back + 4. */ - - ULONGEST pcoq_tail, pcsq_tail; - regcache_cooked_read_unsigned (regcache, HPPA_PCOQ_TAIL_REGNUM, &pcoq_tail); - regcache_cooked_read_unsigned (regcache, HPPA_PCSQ_TAIL_REGNUM, &pcsq_tail); - - regcache_cooked_write_unsigned (regcache, HPPA_PCOQ_HEAD_REGNUM, pcoq_tail); - regcache_cooked_write_unsigned (regcache, HPPA_PCSQ_HEAD_REGNUM, pcsq_tail); - - regcache_cooked_write_unsigned (regcache, - HPPA_PCOQ_TAIL_REGNUM, pcoq_tail + 4); - /* We can leave the tail's space the same, since there's no jump. */ -} - - -/* Signal frames. */ -struct hppa_hpux_sigtramp_unwind_cache -{ - CORE_ADDR base; - struct trad_frame_saved_reg *saved_regs; -}; - -static int hppa_hpux_tramp_reg[] = { - HPPA_SAR_REGNUM, - HPPA_PCOQ_HEAD_REGNUM, - HPPA_PCSQ_HEAD_REGNUM, - HPPA_PCOQ_TAIL_REGNUM, - HPPA_PCSQ_TAIL_REGNUM, - HPPA_EIEM_REGNUM, - HPPA_IIR_REGNUM, - HPPA_ISR_REGNUM, - HPPA_IOR_REGNUM, - HPPA_IPSW_REGNUM, - -1, - HPPA_SR4_REGNUM, - HPPA_SR4_REGNUM + 1, - HPPA_SR4_REGNUM + 2, - HPPA_SR4_REGNUM + 3, - HPPA_SR4_REGNUM + 4, - HPPA_SR4_REGNUM + 5, - HPPA_SR4_REGNUM + 6, - HPPA_SR4_REGNUM + 7, - HPPA_RCR_REGNUM, - HPPA_PID0_REGNUM, - HPPA_PID1_REGNUM, - HPPA_CCR_REGNUM, - HPPA_PID2_REGNUM, - HPPA_PID3_REGNUM, - HPPA_TR0_REGNUM, - HPPA_TR0_REGNUM + 1, - HPPA_TR0_REGNUM + 2, - HPPA_CR27_REGNUM -}; - -static struct hppa_hpux_sigtramp_unwind_cache * -hppa_hpux_sigtramp_frame_unwind_cache (struct frame_info *this_frame, - void **this_cache) - -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct hppa_hpux_sigtramp_unwind_cache *info; - unsigned int flag; - CORE_ADDR sp, scptr, off; - int i, incr, szoff; - - if (*this_cache) - return *this_cache; - - info = FRAME_OBSTACK_ZALLOC (struct hppa_hpux_sigtramp_unwind_cache); - *this_cache = info; - info->saved_regs = trad_frame_alloc_saved_regs (this_frame); - - sp = get_frame_register_unsigned (this_frame, HPPA_SP_REGNUM); - - if (IS_32BIT_TARGET (gdbarch)) - scptr = sp - 1352; - else - scptr = sp - 1520; - - off = scptr; - - /* See /usr/include/machine/save_state.h for the structure of the - save_state_t structure. */ - - flag = read_memory_unsigned_integer (scptr + HPPA_HPUX_SS_FLAGS_OFFSET, - 4, byte_order); - - if (!(flag & HPPA_HPUX_SS_WIDEREGS)) - { - /* Narrow registers. */ - off = scptr + HPPA_HPUX_SS_NARROW_OFFSET; - incr = 4; - szoff = 0; - } - else - { - /* Wide registers. */ - off = scptr + HPPA_HPUX_SS_WIDE_OFFSET + 8; - incr = 8; - szoff = (tdep->bytes_per_address == 4 ? 4 : 0); - } - - for (i = 1; i < 32; i++) - { - info->saved_regs[HPPA_R0_REGNUM + i].addr = off + szoff; - off += incr; - } - - for (i = 0; i < ARRAY_SIZE (hppa_hpux_tramp_reg); i++) - { - if (hppa_hpux_tramp_reg[i] > 0) - info->saved_regs[hppa_hpux_tramp_reg[i]].addr = off + szoff; - - off += incr; - } - - /* TODO: fp regs */ - - info->base = get_frame_register_unsigned (this_frame, HPPA_SP_REGNUM); - - return info; -} - -static void -hppa_hpux_sigtramp_frame_this_id (struct frame_info *this_frame, - void **this_prologue_cache, - struct frame_id *this_id) -{ - struct hppa_hpux_sigtramp_unwind_cache *info - = hppa_hpux_sigtramp_frame_unwind_cache (this_frame, this_prologue_cache); - - *this_id = frame_id_build (info->base, get_frame_pc (this_frame)); -} - -static struct value * -hppa_hpux_sigtramp_frame_prev_register (struct frame_info *this_frame, - void **this_prologue_cache, - int regnum) -{ - struct hppa_hpux_sigtramp_unwind_cache *info - = hppa_hpux_sigtramp_frame_unwind_cache (this_frame, this_prologue_cache); - - return hppa_frame_prev_register_helper (this_frame, - info->saved_regs, regnum); -} - -static int -hppa_hpux_sigtramp_unwind_sniffer (const struct frame_unwind *self, - struct frame_info *this_frame, - void **this_cache) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct unwind_table_entry *u; - CORE_ADDR pc = get_frame_pc (this_frame); - - u = find_unwind_entry (pc); - - /* If this is an export stub, try to get the unwind descriptor for - the actual function itself. */ - if (u && u->stub_unwind.stub_type == EXPORT) - { - gdb_byte buf[HPPA_INSN_SIZE]; - unsigned long insn; - - if (!safe_frame_unwind_memory (this_frame, u->region_start, - buf, sizeof buf)) - return 0; - - insn = extract_unsigned_integer (buf, sizeof buf, byte_order); - if ((insn & 0xffe0e000) == 0xe8400000) - u = find_unwind_entry(u->region_start + hppa_extract_17 (insn) + 8); - } - - if (u && u->HP_UX_interrupt_marker) - return 1; - - return 0; -} - -static const struct frame_unwind hppa_hpux_sigtramp_frame_unwind = { - SIGTRAMP_FRAME, - default_frame_unwind_stop_reason, - hppa_hpux_sigtramp_frame_this_id, - hppa_hpux_sigtramp_frame_prev_register, - NULL, - hppa_hpux_sigtramp_unwind_sniffer -}; - -static CORE_ADDR -hppa32_hpux_find_global_pointer (struct gdbarch *gdbarch, - struct value *function) -{ - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - CORE_ADDR faddr; - - faddr = value_as_address (function); - - /* Is this a plabel? If so, dereference it to get the gp value. */ - if (faddr & 2) - { - int status; - gdb_byte buf[4]; - - faddr &= ~3; - - status = target_read_memory (faddr + 4, buf, sizeof (buf)); - if (status == 0) - return extract_unsigned_integer (buf, sizeof (buf), byte_order); - } - - return gdbarch_tdep (gdbarch)->solib_get_got_by_pc (faddr); -} - -static CORE_ADDR -hppa64_hpux_find_global_pointer (struct gdbarch *gdbarch, - struct value *function) -{ - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - CORE_ADDR faddr; - gdb_byte buf[32]; - - faddr = value_as_address (function); - - if (pc_in_section (faddr, ".opd")) - { - target_read_memory (faddr, buf, sizeof (buf)); - return extract_unsigned_integer (&buf[24], 8, byte_order); - } - else - { - return gdbarch_tdep (gdbarch)->solib_get_got_by_pc (faddr); - } -} - -static unsigned int ldsid_pattern[] = { - 0x000010a0, /* ldsid (rX),rY */ - 0x00001820, /* mtsp rY,sr0 */ - 0xe0000000 /* be,n (sr0,rX) */ -}; - -static CORE_ADDR -hppa_hpux_search_pattern (struct gdbarch *gdbarch, - CORE_ADDR start, CORE_ADDR end, - unsigned int *patterns, int count) -{ - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - int num_insns = (end - start + HPPA_INSN_SIZE) / HPPA_INSN_SIZE; - unsigned int *insns; - gdb_byte *buf; - int offset, i; - - buf = alloca (num_insns * HPPA_INSN_SIZE); - insns = alloca (num_insns * sizeof (unsigned int)); - - read_memory (start, buf, num_insns * HPPA_INSN_SIZE); - for (i = 0; i < num_insns; i++, buf += HPPA_INSN_SIZE) - insns[i] = extract_unsigned_integer (buf, HPPA_INSN_SIZE, byte_order); - - for (offset = 0; offset <= num_insns - count; offset++) - { - for (i = 0; i < count; i++) - { - if ((insns[offset + i] & patterns[i]) != patterns[i]) - break; - } - if (i == count) - break; - } - - if (offset <= num_insns - count) - return start + offset * HPPA_INSN_SIZE; - else - return 0; -} - -static CORE_ADDR -hppa32_hpux_search_dummy_call_sequence (struct gdbarch *gdbarch, CORE_ADDR pc, - int *argreg) -{ - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct objfile *obj; - struct obj_section *sec; - struct hppa_objfile_private *priv; - struct frame_info *frame; - struct unwind_table_entry *u; - CORE_ADDR addr, rp; - gdb_byte buf[4]; - unsigned int insn; - - sec = find_pc_section (pc); - obj = sec->objfile; - priv = objfile_data (obj, hppa_objfile_priv_data); - - if (!priv) - priv = hppa_init_objfile_priv_data (obj); - if (!priv) - error (_("Internal error creating objfile private data.")); - - /* Use the cached value if we have one. */ - if (priv->dummy_call_sequence_addr != 0) - { - *argreg = priv->dummy_call_sequence_reg; - return priv->dummy_call_sequence_addr; - } - - /* First try a heuristic; if we are in a shared library call, our return - pointer is likely to point at an export stub. */ - frame = get_current_frame (); - rp = frame_unwind_register_unsigned (frame, 2); - u = find_unwind_entry (rp); - if (u && u->stub_unwind.stub_type == EXPORT) - { - addr = hppa_hpux_search_pattern (gdbarch, - u->region_start, u->region_end, - ldsid_pattern, - ARRAY_SIZE (ldsid_pattern)); - if (addr) - goto found_pattern; - } - - /* Next thing to try is to look for an export stub. */ - if (priv->unwind_info) - { - int i; - - for (i = 0; i < priv->unwind_info->last; i++) - { - struct unwind_table_entry *u; - u = &priv->unwind_info->table[i]; - if (u->stub_unwind.stub_type == EXPORT) - { - addr = hppa_hpux_search_pattern (gdbarch, - u->region_start, u->region_end, - ldsid_pattern, - ARRAY_SIZE (ldsid_pattern)); - if (addr) - { - goto found_pattern; - } - } - } - } - - /* Finally, if this is the main executable, try to locate a sequence - from noshlibs */ - addr = hppa_symbol_address ("noshlibs"); - sec = find_pc_section (addr); - - if (sec && sec->objfile == obj) - { - CORE_ADDR start, end; - - find_pc_partial_function (addr, NULL, &start, &end); - if (start != 0 && end != 0) - { - addr = hppa_hpux_search_pattern (gdbarch, start, end, ldsid_pattern, - ARRAY_SIZE (ldsid_pattern)); - if (addr) - goto found_pattern; - } - } - - /* Can't find a suitable sequence. */ - return 0; - -found_pattern: - target_read_memory (addr, buf, sizeof (buf)); - insn = extract_unsigned_integer (buf, sizeof (buf), byte_order); - priv->dummy_call_sequence_addr = addr; - priv->dummy_call_sequence_reg = (insn >> 21) & 0x1f; - - *argreg = priv->dummy_call_sequence_reg; - return priv->dummy_call_sequence_addr; -} - -static CORE_ADDR -hppa64_hpux_search_dummy_call_sequence (struct gdbarch *gdbarch, CORE_ADDR pc, - int *argreg) -{ - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct objfile *obj; - struct obj_section *sec; - struct hppa_objfile_private *priv; - CORE_ADDR addr; - struct minimal_symbol *msym; - - sec = find_pc_section (pc); - obj = sec->objfile; - priv = objfile_data (obj, hppa_objfile_priv_data); - - if (!priv) - priv = hppa_init_objfile_priv_data (obj); - if (!priv) - error (_("Internal error creating objfile private data.")); - - /* Use the cached value if we have one. */ - if (priv->dummy_call_sequence_addr != 0) - { - *argreg = priv->dummy_call_sequence_reg; - return priv->dummy_call_sequence_addr; - } - - /* FIXME: Without stub unwind information, locating a suitable sequence is - fairly difficult. For now, we implement a very naive and inefficient - scheme; try to read in blocks of code, and look for a "bve,n (rp)" - instruction. These are likely to occur at the end of functions, so - we only look at the last two instructions of each function. */ - ALL_OBJFILE_MSYMBOLS (obj, msym) - { - CORE_ADDR begin, end; - const char *name; - gdb_byte buf[2 * HPPA_INSN_SIZE]; - int offset; - - find_pc_partial_function (MSYMBOL_VALUE_ADDRESS (obj, msym), &name, - &begin, &end); - - if (name == NULL || begin == 0 || end == 0) - continue; - - if (target_read_memory (end - sizeof (buf), buf, sizeof (buf)) == 0) - { - for (offset = 0; offset < sizeof (buf); offset++) - { - unsigned int insn; - - insn = extract_unsigned_integer (buf + offset, - HPPA_INSN_SIZE, byte_order); - if (insn == 0xe840d002) /* bve,n (rp) */ - { - addr = (end - sizeof (buf)) + offset; - goto found_pattern; - } - } - } - } - - /* Can't find a suitable sequence. */ - return 0; - -found_pattern: - priv->dummy_call_sequence_addr = addr; - /* Right now we only look for a "bve,l (rp)" sequence, so the register is - always HPPA_RP_REGNUM. */ - priv->dummy_call_sequence_reg = HPPA_RP_REGNUM; - - *argreg = priv->dummy_call_sequence_reg; - return priv->dummy_call_sequence_addr; -} - -static CORE_ADDR -hppa_hpux_find_import_stub_for_addr (CORE_ADDR funcaddr) -{ - struct objfile *objfile; - struct bound_minimal_symbol funsym; - struct bound_minimal_symbol stubsym; - CORE_ADDR stubaddr; - - funsym = lookup_minimal_symbol_by_pc (funcaddr); - stubaddr = 0; - - ALL_OBJFILES (objfile) - { - stubsym = lookup_minimal_symbol_solib_trampoline - (MSYMBOL_LINKAGE_NAME (funsym.minsym), objfile); - - if (stubsym.minsym) - { - struct unwind_table_entry *u; - - u = find_unwind_entry (MSYMBOL_VALUE (stubsym.minsym)); - if (u == NULL - || (u->stub_unwind.stub_type != IMPORT - && u->stub_unwind.stub_type != IMPORT_SHLIB)) - continue; - - stubaddr = MSYMBOL_VALUE (stubsym.minsym); - - /* If we found an IMPORT stub, then we can stop searching; - if we found an IMPORT_SHLIB, we want to continue the search - in the hopes that we will find an IMPORT stub. */ - if (u->stub_unwind.stub_type == IMPORT) - break; - } - } - - return stubaddr; -} - -static int -hppa_hpux_sr_for_addr (struct gdbarch *gdbarch, CORE_ADDR addr) -{ - int sr; - /* The space register to use is encoded in the top 2 bits of the address. */ - sr = addr >> (gdbarch_tdep (gdbarch)->bytes_per_address * 8 - 2); - return sr + 4; -} - -static CORE_ADDR -hppa_hpux_find_dummy_bpaddr (CORE_ADDR addr) -{ - /* In order for us to restore the space register to its starting state, - we need the dummy trampoline to return to an instruction address in - the same space as where we started the call. We used to place the - breakpoint near the current pc, however, this breaks nested dummy calls - as the nested call will hit the breakpoint address and terminate - prematurely. Instead, we try to look for an address in the same space to - put the breakpoint. - - This is similar in spirit to putting the breakpoint at the "entry point" - of an executable. */ - - struct obj_section *sec; - struct unwind_table_entry *u; - struct minimal_symbol *msym; - CORE_ADDR func; - - sec = find_pc_section (addr); - if (sec) - { - /* First try the lowest address in the section; we can use it as long - as it is "regular" code (i.e. not a stub). */ - u = find_unwind_entry (obj_section_addr (sec)); - if (!u || u->stub_unwind.stub_type == 0) - return obj_section_addr (sec); - - /* Otherwise, we need to find a symbol for a regular function. We - do this by walking the list of msymbols in the objfile. The symbol - we find should not be the same as the function that was passed in. */ - - /* FIXME: this is broken, because we can find a function that will be - called by the dummy call target function, which will still not - work. */ - - find_pc_partial_function (addr, NULL, &func, NULL); - ALL_OBJFILE_MSYMBOLS (sec->objfile, msym) - { - u = find_unwind_entry (MSYMBOL_VALUE_ADDRESS (sec->objfile, msym)); - if (func != MSYMBOL_VALUE_ADDRESS (sec->objfile, msym) - && (!u || u->stub_unwind.stub_type == 0)) - return MSYMBOL_VALUE_ADDRESS (sec->objfile, msym); - } - } - - warning (_("Cannot find suitable address to place dummy breakpoint; nested " - "calls may fail.")); - return addr - 4; -} - -static CORE_ADDR -hppa_hpux_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp, - CORE_ADDR funcaddr, - struct value **args, int nargs, - struct type *value_type, - CORE_ADDR *real_pc, CORE_ADDR *bp_addr, - struct regcache *regcache) -{ - CORE_ADDR pc, stubaddr; - int argreg = 0; - - pc = regcache_read_pc (regcache); - - /* Note: we don't want to pass a function descriptor here; push_dummy_call - fills in the PIC register for us. */ - funcaddr = gdbarch_convert_from_func_ptr_addr (gdbarch, funcaddr, NULL); - - /* The simple case is where we call a function in the same space that we are - currently in; in that case we don't really need to do anything. */ - if (hppa_hpux_sr_for_addr (gdbarch, pc) - == hppa_hpux_sr_for_addr (gdbarch, funcaddr)) - { - /* Intraspace call. */ - *bp_addr = hppa_hpux_find_dummy_bpaddr (pc); - *real_pc = funcaddr; - regcache_cooked_write_unsigned (regcache, HPPA_RP_REGNUM, *bp_addr); - - return sp; - } - - /* In order to make an interspace call, we need to go through a stub. - gcc supplies an appropriate stub called "__gcc_plt_call", however, if - an application is compiled with HP compilers then this stub is not - available. We used to fallback to "__d_plt_call", however that stub - is not entirely useful for us because it doesn't do an interspace - return back to the caller. Also, on hppa64-hpux, there is no - __gcc_plt_call available. In order to keep the code uniform, we - instead don't use either of these stubs, but instead write our own - onto the stack. - - A problem arises since the stack is located in a different space than - code, so in order to branch to a stack stub, we will need to do an - interspace branch. Previous versions of gdb did this by modifying code - at the current pc and doing single-stepping to set the pcsq. Since this - is highly undesirable, we use a different scheme: - - All we really need to do the branch to the stub is a short instruction - sequence like this: - - PA1.1: - ldsid (rX),r1 - mtsp r1,sr0 - be,n (sr0,rX) - - PA2.0: - bve,n (sr0,rX) - - Instead of writing these sequences ourselves, we can find it in - the instruction stream that belongs to the current space. While this - seems difficult at first, we are actually guaranteed to find the sequences - in several places: - - For 32-bit code: - - in export stubs for shared libraries - - in the "noshlibs" routine in the main module - - For 64-bit code: - - at the end of each "regular" function - - We cache the address of these sequences in the objfile's private data - since these operations can potentially be quite expensive. - - So, what we do is: - - write a stack trampoline - - look for a suitable instruction sequence in the current space - - point the sequence at the trampoline - - set the return address of the trampoline to the current space - (see hppa_hpux_find_dummy_call_bpaddr) - - set the continuing address of the "dummy code" as the sequence. */ - - if (IS_32BIT_TARGET (gdbarch)) - { -#define INSN(I1, I2, I3, I4) 0x ## I1, 0x ## I2, 0x ## I3, 0x ## I4 - static const gdb_byte hppa32_tramp[] = { - INSN(0f,df,12,91), /* stw r31,-8(,sp) */ - INSN(02,c0,10,a1), /* ldsid (,r22),r1 */ - INSN(00,01,18,20), /* mtsp r1,sr0 */ - INSN(e6,c0,00,00), /* be,l 0(sr0,r22),%sr0,%r31 */ - INSN(08,1f,02,42), /* copy r31,rp */ - INSN(0f,d1,10,82), /* ldw -8(,sp),rp */ - INSN(00,40,10,a1), /* ldsid (,rp),r1 */ - INSN(00,01,18,20), /* mtsp r1,sr0 */ - INSN(e0,40,00,00), /* be 0(sr0,rp) */ - INSN(08,00,02,40) /* nop */ - }; - - /* for hppa32, we must call the function through a stub so that on - return it can return to the space of our trampoline. */ - stubaddr = hppa_hpux_find_import_stub_for_addr (funcaddr); - if (stubaddr == 0) - error (_("Cannot call external function not referenced by application " - "(no import stub).\n")); - regcache_cooked_write_unsigned (regcache, 22, stubaddr); - - write_memory (sp, hppa32_tramp, sizeof (hppa32_tramp)); - - *bp_addr = hppa_hpux_find_dummy_bpaddr (pc); - regcache_cooked_write_unsigned (regcache, 31, *bp_addr); - - *real_pc = hppa32_hpux_search_dummy_call_sequence (gdbarch, pc, &argreg); - if (*real_pc == 0) - error (_("Cannot make interspace call from here.")); - - regcache_cooked_write_unsigned (regcache, argreg, sp); - - sp += sizeof (hppa32_tramp); - } - else - { - static const gdb_byte hppa64_tramp[] = { - INSN(ea,c0,f0,00), /* bve,l (r22),%r2 */ - INSN(0f,df,12,d1), /* std r31,-8(,sp) */ - INSN(0f,d1,10,c2), /* ldd -8(,sp),rp */ - INSN(e8,40,d0,02), /* bve,n (rp) */ - INSN(08,00,02,40) /* nop */ - }; -#undef INSN - - /* for hppa64, we don't need to call through a stub; all functions - return via a bve. */ - regcache_cooked_write_unsigned (regcache, 22, funcaddr); - write_memory (sp, hppa64_tramp, sizeof (hppa64_tramp)); - - *bp_addr = pc - 4; - regcache_cooked_write_unsigned (regcache, 31, *bp_addr); - - *real_pc = hppa64_hpux_search_dummy_call_sequence (gdbarch, pc, &argreg); - if (*real_pc == 0) - error (_("Cannot make interspace call from here.")); - - regcache_cooked_write_unsigned (regcache, argreg, sp); - - sp += sizeof (hppa64_tramp); - } - - sp = gdbarch_frame_align (gdbarch, sp); - - return sp; -} - - - -static void -hppa_hpux_supply_ss_narrow (struct regcache *regcache, - int regnum, const gdb_byte *save_state) -{ - const gdb_byte *ss_narrow = save_state + HPPA_HPUX_SS_NARROW_OFFSET; - int i, offset = 0; - - for (i = HPPA_R1_REGNUM; i < HPPA_FP0_REGNUM; i++) - { - if (regnum == i || regnum == -1) - regcache_raw_supply (regcache, i, ss_narrow + offset); - - offset += 4; - } -} - -static void -hppa_hpux_supply_ss_fpblock (struct regcache *regcache, - int regnum, const gdb_byte *save_state) -{ - const gdb_byte *ss_fpblock = save_state + HPPA_HPUX_SS_FPBLOCK_OFFSET; - int i, offset = 0; - - /* FIXME: We view the floating-point state as 64 single-precision - registers for 32-bit code, and 32 double-precision register for - 64-bit code. This distinction is artificial and should be - eliminated. If that ever happens, we should remove the if-clause - below. */ - - if (register_size (get_regcache_arch (regcache), HPPA_FP0_REGNUM) == 4) - { - for (i = HPPA_FP0_REGNUM; i < HPPA_FP0_REGNUM + 64; i++) - { - if (regnum == i || regnum == -1) - regcache_raw_supply (regcache, i, ss_fpblock + offset); - - offset += 4; - } - } - else - { - for (i = HPPA_FP0_REGNUM; i < HPPA_FP0_REGNUM + 32; i++) - { - if (regnum == i || regnum == -1) - regcache_raw_supply (regcache, i, ss_fpblock + offset); - - offset += 8; - } - } -} - -static void -hppa_hpux_supply_ss_wide (struct regcache *regcache, - int regnum, const gdb_byte *save_state) -{ - const gdb_byte *ss_wide = save_state + HPPA_HPUX_SS_WIDE_OFFSET; - int i, offset = 8; - - if (register_size (get_regcache_arch (regcache), HPPA_R1_REGNUM) == 4) - offset += 4; - - for (i = HPPA_R1_REGNUM; i < HPPA_FP0_REGNUM; i++) - { - if (regnum == i || regnum == -1) - regcache_raw_supply (regcache, i, ss_wide + offset); - - offset += 8; - } -} - -static void -hppa_hpux_supply_save_state (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *regs, size_t len) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - const gdb_byte *proc_info = regs; - const gdb_byte *save_state = proc_info + 8; - ULONGEST flags; - - flags = extract_unsigned_integer (save_state + HPPA_HPUX_SS_FLAGS_OFFSET, - 4, byte_order); - if (regnum == -1 || regnum == HPPA_FLAGS_REGNUM) - { - size_t size = register_size (gdbarch, HPPA_FLAGS_REGNUM); - gdb_byte buf[8]; - - store_unsigned_integer (buf, size, byte_order, flags); - regcache_raw_supply (regcache, HPPA_FLAGS_REGNUM, buf); - } - - /* If the SS_WIDEREGS flag is set, we really do need the full - `struct save_state'. */ - if (flags & HPPA_HPUX_SS_WIDEREGS && len < HPPA_HPUX_SAVE_STATE_SIZE) - error (_("Register set contents too small")); - - if (flags & HPPA_HPUX_SS_WIDEREGS) - hppa_hpux_supply_ss_wide (regcache, regnum, save_state); - else - hppa_hpux_supply_ss_narrow (regcache, regnum, save_state); - - hppa_hpux_supply_ss_fpblock (regcache, regnum, save_state); -} - -/* HP-UX register set. */ - -static const struct regset hppa_hpux_regset = -{ - NULL, - hppa_hpux_supply_save_state -}; - -static void -hppa_hpux_iterate_over_regset_sections (struct gdbarch *gdbarch, - iterate_over_regset_sections_cb *cb, - void *cb_data, - const struct regcache *regcache) -{ - cb (".reg", HPPA_HPUX_PA89_SAVE_STATE_SIZE + 8, &hppa_hpux_regset, - NULL, cb_data); -} - - -/* Bit in the `ss_flag' member of `struct save_state' that indicates - the state was saved from a system call. From - . */ -#define HPPA_HPUX_SS_INSYSCALL 0x02 - -static CORE_ADDR -hppa_hpux_read_pc (struct regcache *regcache) -{ - ULONGEST flags; - - /* If we're currently in a system call return the contents of %r31. */ - regcache_cooked_read_unsigned (regcache, HPPA_FLAGS_REGNUM, &flags); - if (flags & HPPA_HPUX_SS_INSYSCALL) - { - ULONGEST pc; - regcache_cooked_read_unsigned (regcache, HPPA_R31_REGNUM, &pc); - return pc & ~0x3; - } - - return hppa_read_pc (regcache); -} - -static void -hppa_hpux_write_pc (struct regcache *regcache, CORE_ADDR pc) -{ - ULONGEST flags; - - /* If we're currently in a system call also write PC into %r31. */ - regcache_cooked_read_unsigned (regcache, HPPA_FLAGS_REGNUM, &flags); - if (flags & HPPA_HPUX_SS_INSYSCALL) - regcache_cooked_write_unsigned (regcache, HPPA_R31_REGNUM, pc | 0x3); - - hppa_write_pc (regcache, pc); -} - -static CORE_ADDR -hppa_hpux_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) -{ - ULONGEST flags; - - /* If we're currently in a system call return the contents of %r31. */ - flags = frame_unwind_register_unsigned (next_frame, HPPA_FLAGS_REGNUM); - if (flags & HPPA_HPUX_SS_INSYSCALL) - return frame_unwind_register_unsigned (next_frame, HPPA_R31_REGNUM) & ~0x3; - - return hppa_unwind_pc (gdbarch, next_frame); -} - - -/* Given the current value of the pc, check to see if it is inside a stub, and - if so, change the value of the pc to point to the caller of the stub. - THIS_FRAME is the current frame in the current list of frames. - BASE contains to stack frame base of the current frame. - SAVE_REGS is the register file stored in the frame cache. */ -static void -hppa_hpux_unwind_adjust_stub (struct frame_info *this_frame, CORE_ADDR base, - struct trad_frame_saved_reg *saved_regs) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - int word_size = gdbarch_ptr_bit (gdbarch) / 8; - struct value *pcoq_head_val; - ULONGEST pcoq_head; - CORE_ADDR stubpc; - struct unwind_table_entry *u; - - pcoq_head_val = trad_frame_get_prev_register (this_frame, saved_regs, - HPPA_PCOQ_HEAD_REGNUM); - pcoq_head = - extract_unsigned_integer (value_contents_all (pcoq_head_val), - register_size (gdbarch, HPPA_PCOQ_HEAD_REGNUM), - byte_order); - - u = find_unwind_entry (pcoq_head); - if (u && u->stub_unwind.stub_type == EXPORT) - { - stubpc = read_memory_integer (base - 24, word_size, byte_order); - trad_frame_set_value (saved_regs, HPPA_PCOQ_HEAD_REGNUM, stubpc); - } - else if (hppa_symbol_address ("__gcc_plt_call") - == get_pc_function_start (pcoq_head)) - { - stubpc = read_memory_integer (base - 8, word_size, byte_order); - trad_frame_set_value (saved_regs, HPPA_PCOQ_HEAD_REGNUM, stubpc); - } -} - -static void -hppa_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - if (IS_32BIT_TARGET (gdbarch)) - tdep->in_solib_call_trampoline = hppa32_hpux_in_solib_call_trampoline; - else - tdep->in_solib_call_trampoline = hppa64_hpux_in_solib_call_trampoline; - - tdep->unwind_adjust_stub = hppa_hpux_unwind_adjust_stub; - - set_gdbarch_in_solib_return_trampoline - (gdbarch, hppa_hpux_in_solib_return_trampoline); - set_gdbarch_skip_trampoline_code (gdbarch, hppa_hpux_skip_trampoline_code); - - set_gdbarch_push_dummy_code (gdbarch, hppa_hpux_push_dummy_code); - set_gdbarch_call_dummy_location (gdbarch, ON_STACK); - - set_gdbarch_read_pc (gdbarch, hppa_hpux_read_pc); - set_gdbarch_write_pc (gdbarch, hppa_hpux_write_pc); - set_gdbarch_unwind_pc (gdbarch, hppa_hpux_unwind_pc); - set_gdbarch_skip_permanent_breakpoint - (gdbarch, hppa_skip_permanent_breakpoint); - - set_gdbarch_iterate_over_regset_sections - (gdbarch, hppa_hpux_iterate_over_regset_sections); - - frame_unwind_append_unwinder (gdbarch, &hppa_hpux_sigtramp_frame_unwind); -} - -static void -hppa_hpux_som_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - tdep->is_elf = 0; - - tdep->find_global_pointer = hppa32_hpux_find_global_pointer; - - hppa_hpux_init_abi (info, gdbarch); - som_solib_select (gdbarch); -} - -static void -hppa_hpux_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - tdep->is_elf = 1; - tdep->find_global_pointer = hppa64_hpux_find_global_pointer; - - hppa_hpux_init_abi (info, gdbarch); - pa64_solib_select (gdbarch); -} - -static enum gdb_osabi -hppa_hpux_core_osabi_sniffer (bfd *abfd) -{ - if (strcmp (bfd_get_target (abfd), "hpux-core") == 0) - return GDB_OSABI_HPUX_SOM; - else if (strcmp (bfd_get_target (abfd), "elf64-hppa") == 0) - { - asection *section; - - section = bfd_get_section_by_name (abfd, ".kernel"); - if (section) - { - bfd_size_type size; - char *contents; - - size = bfd_section_size (abfd, section); - contents = alloca (size); - if (bfd_get_section_contents (abfd, section, contents, - (file_ptr) 0, size) - && strcmp (contents, "HP-UX") == 0) - return GDB_OSABI_HPUX_ELF; - } - } - - return GDB_OSABI_UNKNOWN; -} - -void -_initialize_hppa_hpux_tdep (void) -{ - /* BFD doesn't set a flavour for HP-UX style core files. It doesn't - set the architecture either. */ - gdbarch_register_osabi_sniffer (bfd_arch_unknown, - bfd_target_unknown_flavour, - hppa_hpux_core_osabi_sniffer); - gdbarch_register_osabi_sniffer (bfd_arch_hppa, - bfd_target_elf_flavour, - hppa_hpux_core_osabi_sniffer); - - gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_HPUX_SOM, - hppa_hpux_som_init_abi); - gdbarch_register_osabi (bfd_arch_hppa, bfd_mach_hppa20w, GDB_OSABI_HPUX_ELF, - hppa_hpux_elf_init_abi); -} diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c index 627f31a..0217755 100644 --- a/gdb/hppa-tdep.c +++ b/gdb/hppa-tdep.c @@ -46,13 +46,44 @@ static int hppa_debug = 0; static const int hppa32_num_regs = 128; static const int hppa64_num_regs = 96; +/* We use the objfile->obj_private pointer for two things: + * 1. An unwind table; + * + * 2. A pointer to any associated shared library object. + * + * #defines are used to help refer to these objects. + */ + +/* Info about the unwind table associated with an object file. + * This is hung off of the "objfile->obj_private" pointer, and + * is allocated in the objfile's psymbol obstack. This allows + * us to have unique unwind info for each executable and shared + * library that we are debugging. + */ +struct hppa_unwind_info + { + struct unwind_table_entry *table; /* Pointer to unwind info */ + struct unwind_table_entry *cache; /* Pointer to last entry we found */ + int last; /* Index of last entry */ + }; + +struct hppa_objfile_private + { + struct hppa_unwind_info *unwind_info; /* a pointer */ + struct so_list *so_info; /* a pointer */ + CORE_ADDR dp; + + int dummy_call_sequence_reg; + CORE_ADDR dummy_call_sequence_addr; + }; + /* hppa-specific object data -- unwind and solib info. TODO/maybe: think about splitting this into two parts; the unwind data is common to all hppa targets, but is only used in this file; we can register that separately and make this static. The solib data is probably hpux- specific, so we can create a separate extern objfile_data that is registered by hppa-hpux-tdep.c and shared with pa64solib.c and somsolib.c. */ -const struct objfile_data *hppa_objfile_priv_data = NULL; +static const struct objfile_data *hppa_objfile_priv_data = NULL; /* Get at various relevent fields of an instruction word. */ #define MASK_5 0x1f @@ -170,7 +201,7 @@ hppa_symbol_address(const char *sym) return (CORE_ADDR)-1; } -struct hppa_objfile_private * +static struct hppa_objfile_private * hppa_init_objfile_priv_data (struct objfile *objfile) { struct hppa_objfile_private *priv; @@ -2709,14 +2740,6 @@ hppa_frame_prev_register_helper (struct frame_info *this_frame, return frame_unwind_got_constant (this_frame, regnum, pc + 4); } - /* Make sure the "flags" register is zero in all unwound frames. - The "flags" registers is a HP-UX specific wart, and only the code - in hppa-hpux-tdep.c depends on it. However, it is easier to deal - with it here. This shouldn't affect other systems since those - should provide zero for the "flags" register anyway. */ - if (regnum == HPPA_FLAGS_REGNUM) - return frame_unwind_got_constant (this_frame, regnum, 0); - return trad_frame_get_prev_register (this_frame, saved_regs, regnum); } diff --git a/gdb/hppa-tdep.h b/gdb/hppa-tdep.h index 0669ce3..048677b 100644 --- a/gdb/hppa-tdep.h +++ b/gdb/hppa-tdep.h @@ -188,39 +188,6 @@ enum unwind_stub_types struct unwind_table_entry *find_unwind_entry (CORE_ADDR); -/* We use the objfile->obj_private pointer for two things: - * 1. An unwind table; - * - * 2. A pointer to any associated shared library object. - * - * #defines are used to help refer to these objects. - */ - -/* Info about the unwind table associated with an object file. - * This is hung off of the "objfile->obj_private" pointer, and - * is allocated in the objfile's psymbol obstack. This allows - * us to have unique unwind info for each executable and shared - * library that we are debugging. - */ -struct hppa_unwind_info - { - struct unwind_table_entry *table; /* Pointer to unwind info */ - struct unwind_table_entry *cache; /* Pointer to last entry we found */ - int last; /* Index of last entry */ - }; - -struct hppa_objfile_private - { - struct hppa_unwind_info *unwind_info; /* a pointer */ - struct so_list *so_info; /* a pointer */ - CORE_ADDR dp; - - int dummy_call_sequence_reg; - CORE_ADDR dummy_call_sequence_addr; - }; - -extern const struct objfile_data *hppa_objfile_priv_data; - int hppa_get_field (unsigned word, int from, int to); int hppa_extract_5_load (unsigned int); unsigned hppa_extract_5R_store (unsigned int); @@ -244,8 +211,6 @@ extern struct bound_minimal_symbol hppa_lookup_stub_minimal_symbol (const char *name, enum unwind_stub_types stub_type); -extern struct hppa_objfile_private *hppa_init_objfile_priv_data (struct objfile *objfile); - extern int hppa_in_solib_call_trampoline (struct gdbarch *gdbarch, CORE_ADDR pc); extern CORE_ADDR hppa_skip_trampoline_code (struct frame_info *, CORE_ADDR pc); diff --git a/gdb/ia64-hpux-nat.c b/gdb/ia64-hpux-nat.c deleted file mode 100644 index 6a4e088..0000000 --- a/gdb/ia64-hpux-nat.c +++ /dev/null @@ -1,756 +0,0 @@ -/* Copyright (C) 2010-2014 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 3 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, see . */ - -#include "defs.h" -#include "ia64-tdep.h" -#include "inferior.h" -#include "inf-ttrace.h" -#include "regcache.h" -#include "solib-ia64-hpux.h" - -#include -#include - -/* The offsets used with ttrace to read the value of the raw registers. */ - -static int u_offsets[] = -{ /* Static General Registers. */ - -1, __r1, __r2, __r3, __r4, __r5, __r6, __r7, - __r8, __r9, __r10, __r11, __r12, __r13, __r14, __r15, - __r16, __r17, __r18, __r19, __r20, __r21, __r22, __r23, - __r24, __r25, __r26, __r27, __r28, __r29, __r30, __r31, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - - /* Static Floating-Point Registers. */ - -1, -1, __f2, __f3, __f4, __f5, __f6, __f7, - __f8, __f9, __f10, __f11, __f12, __f13, __f14, __f15, - __f16, __f17, __f18, __f19, __f20, __f21, __f22, __f23, - __f24, __f25, __f26, __f27, __f28, __f29, __f30, __f31, - __f32, __f33, __f34, __f35, __f36, __f37, __f38, __f39, - __f40, __f41, __f42, __f43, __f44, __f45, __f46, __f47, - __f48, __f49, __f50, __f51, __f52, __f53, __f54, __f55, - __f56, __f57, __f58, __f59, __f60, __f61, __f62, __f63, - __f64, __f65, __f66, __f67, __f68, __f69, __f70, __f71, - __f72, __f73, __f74, __f75, __f76, __f77, __f78, __f79, - __f80, __f81, __f82, __f83, __f84, __f85, __f86, __f87, - __f88, __f89, __f90, __f91, __f92, __f93, __f94, __f95, - __f96, __f97, __f98, __f99, __f100, __f101, __f102, __f103, - __f104, __f105, __f106, __f107, __f108, __f109, __f110, __f111, - __f112, __f113, __f114, __f115, __f116, __f117, __f118, __f119, - __f120, __f121, __f122, __f123, __f124, __f125, __f126, __f127, - - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - - /* Branch Registers. */ - __b0, __b1, __b2, __b3, __b4, __b5, __b6, __b7, - - /* Virtual frame pointer and virtual return address pointer. */ - -1, -1, - - /* Other registers. */ - __pr, __ip, __cr_ipsr, __cfm, - - /* Kernel registers. */ - -1, -1, -1, -1, - -1, -1, -1, -1, - - -1, -1, -1, -1, -1, -1, -1, -1, - - /* Some application registers. */ - __ar_rsc, __ar_bsp, __ar_bspstore, __ar_rnat, - - -1, - -1, /* Not available: FCR, IA32 floating control register. */ - -1, -1, - - -1, /* Not available: EFLAG. */ - -1, /* Not available: CSD. */ - -1, /* Not available: SSD. */ - -1, /* Not available: CFLG. */ - -1, /* Not available: FSR. */ - -1, /* Not available: FIR. */ - -1, /* Not available: FDR. */ - -1, - __ar_ccv, -1, -1, -1, __ar_unat, -1, -1, -1, - __ar_fpsr, -1, -1, -1, - -1, /* Not available: ITC. */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, - __ar_pfs, __ar_lc, __ar_ec, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1 - /* All following registers, starting with nat0, are handled as - pseudo registers, and hence are handled separately. */ -}; - -/* Some register have a fixed value and can not be modified. - Store their value in static constant buffers that can be used - later to fill the register cache. */ -static const char r0_value[8] = {0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}; -static const char f0_value[16] = {0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}; -static const char f1_value[16] = {0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, - 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}; - -/* The "to_wait" routine from the "inf-ttrace" layer. */ - -static ptid_t (*super_to_wait) (struct target_ops *, ptid_t, - struct target_waitstatus *, int); - -/* The "to_wait" target_ops routine routine for ia64-hpux. */ - -static ptid_t -ia64_hpux_wait (struct target_ops *ops, ptid_t ptid, - struct target_waitstatus *ourstatus, int options) -{ - ptid_t new_ptid; - - new_ptid = super_to_wait (ops, ptid, ourstatus, options); - - /* If this is a DLD event (hard-coded breakpoint instruction - that was activated by the solib-ia64-hpux module), we need to - process it, and then resume the execution as if the event did - not happen. */ - if (ourstatus->kind == TARGET_WAITKIND_STOPPED - && ourstatus->value.sig == GDB_SIGNAL_TRAP - && ia64_hpux_at_dld_breakpoint_p (new_ptid)) - { - ia64_hpux_handle_dld_breakpoint (new_ptid); - - target_resume (new_ptid, 0, GDB_SIGNAL_0); - ourstatus->kind = TARGET_WAITKIND_IGNORE; - } - - return new_ptid; -} - -/* Fetch the RNAT register and supply it to the REGCACHE. */ - -static void -ia64_hpux_fetch_rnat_register (struct regcache *regcache) -{ - CORE_ADDR addr; - gdb_byte buf[8]; - int status; - - /* The value of RNAT is stored at bsp|0x1f8, and must be read using - TT_LWP_RDRSEBS. */ - - regcache_raw_read_unsigned (regcache, IA64_BSP_REGNUM, &addr); - addr |= 0x1f8; - - status = ttrace (TT_LWP_RDRSEBS, ptid_get_pid (inferior_ptid), - ptid_get_lwp (inferior_ptid), addr, sizeof (buf), - (uintptr_t) buf); - if (status < 0) - error (_("failed to read RNAT register at %s"), - paddress (get_regcache_arch(regcache), addr)); - - regcache_raw_supply (regcache, IA64_RNAT_REGNUM, buf); -} - -/* Read the value of the register saved at OFFSET in the save_state_t - structure, and store its value in BUF. LEN is the size of the register - to be read. */ - -static int -ia64_hpux_read_register_from_save_state_t (int offset, gdb_byte *buf, int len) -{ - int status; - - status = ttrace (TT_LWP_RUREGS, ptid_get_pid (inferior_ptid), - ptid_get_lwp (inferior_ptid), offset, len, (uintptr_t) buf); - - return status; -} - -/* Fetch register REGNUM from the inferior. */ - -static void -ia64_hpux_fetch_register (struct regcache *regcache, int regnum) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - int offset, len, status; - gdb_byte *buf; - - if (regnum == IA64_GR0_REGNUM) - { - /* r0 is always 0. */ - regcache_raw_supply (regcache, regnum, r0_value); - return; - } - - if (regnum == IA64_FR0_REGNUM) - { - /* f0 is always 0.0. */ - regcache_raw_supply (regcache, regnum, f0_value); - return; - } - - if (regnum == IA64_FR1_REGNUM) - { - /* f1 is always 1.0. */ - regcache_raw_supply (regcache, regnum, f1_value); - return; - } - - if (regnum == IA64_RNAT_REGNUM) - { - ia64_hpux_fetch_rnat_register (regcache); - return; - } - - /* Get the register location. If the register can not be fetched, - then return now. */ - offset = u_offsets[regnum]; - if (offset == -1) - return; - - len = register_size (gdbarch, regnum); - buf = alloca (len * sizeof (gdb_byte)); - status = ia64_hpux_read_register_from_save_state_t (offset, buf, len); - if (status < 0) - warning (_("Failed to read register value for %s."), - gdbarch_register_name (gdbarch, regnum)); - - regcache_raw_supply (regcache, regnum, buf); -} - -/* The "to_fetch_registers" target_ops routine for ia64-hpux. */ - -static void -ia64_hpux_fetch_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - if (regnum == -1) - for (regnum = 0; - regnum < gdbarch_num_regs (get_regcache_arch (regcache)); - regnum++) - ia64_hpux_fetch_register (regcache, regnum); - else - ia64_hpux_fetch_register (regcache, regnum); -} - -/* Save register REGNUM (stored in BUF) in the save_state_t structure. - LEN is the size of the register in bytes. - - Return the value from the corresponding ttrace call (a negative value - means that the operation failed). */ - -static int -ia64_hpux_write_register_to_saved_state_t (int offset, gdb_byte *buf, int len) -{ - return ttrace (TT_LWP_WUREGS, ptid_get_pid (inferior_ptid), - ptid_get_lwp (inferior_ptid), offset, len, (uintptr_t) buf); -} - -/* Store register REGNUM into the inferior. */ - -static void -ia64_hpux_store_register (const struct regcache *regcache, int regnum) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - int offset = u_offsets[regnum]; - gdb_byte *buf; - int len, status; - - /* If the register can not be stored, then return now. */ - if (offset == -1) - return; - - /* I don't know how to store that register for now. So just ignore any - request to store it, to avoid an internal error. */ - if (regnum == IA64_PSR_REGNUM) - return; - - len = register_size (gdbarch, regnum); - buf = alloca (len * sizeof (gdb_byte)); - regcache_raw_collect (regcache, regnum, buf); - - status = ia64_hpux_write_register_to_saved_state_t (offset, buf, len); - - if (status < 0) - error (_("failed to write register value for %s."), - gdbarch_register_name (gdbarch, regnum)); -} - -/* The "to_store_registers" target_ops routine for ia64-hpux. */ - -static void -ia64_hpux_store_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - if (regnum == -1) - for (regnum = 0; - regnum < gdbarch_num_regs (get_regcache_arch (regcache)); - regnum++) - ia64_hpux_store_register (regcache, regnum); - else - ia64_hpux_store_register (regcache, regnum); -} - -/* The "xfer_partial" routine from the "inf-ttrace" target layer. - Ideally, we would like to use this routine for all transfer - requests, but this platforms has a lot of special cases that - need to be handled manually. So we override this routine and - delegate back if we detect that we are not in a special case. */ - -static target_xfer_partial_ftype *super_xfer_partial; - -/* The "xfer_partial" routine for a memory region that is completely - outside of the backing-store region. */ - -static enum target_xfer_status -ia64_hpux_xfer_memory_no_bs (struct target_ops *ops, const char *annex, - gdb_byte *readbuf, const gdb_byte *writebuf, - CORE_ADDR addr, LONGEST len, - ULONGEST *xfered_len) -{ - /* Memory writes need to be aligned on 16byte boundaries, at least - when writing in the text section. On the other hand, the size - of the buffer does not need to be a multiple of 16bytes. - - No such restriction when performing memory reads. */ - - if (writebuf && addr & 0x0f) - { - const CORE_ADDR aligned_addr = addr & ~0x0f; - const int aligned_len = len + (addr - aligned_addr); - gdb_byte *aligned_buf = alloca (aligned_len * sizeof (gdb_byte)); - LONGEST status; - - /* Read the portion of memory between ALIGNED_ADDR and ADDR, so - that we can write it back during our aligned memory write. */ - status = super_xfer_partial (ops, TARGET_OBJECT_MEMORY, annex, - aligned_buf /* read */, - NULL /* write */, - aligned_addr, addr - aligned_addr); - if (status <= 0) - return TARGET_XFER_EOF; - memcpy (aligned_buf + (addr - aligned_addr), writebuf, len); - - return super_xfer_partial (ops, TARGET_OBJECT_MEMORY, annex, - NULL /* read */, aligned_buf /* write */, - aligned_addr, aligned_len, xfered_len); - } - else - /* Memory read or properly aligned memory write. */ - return super_xfer_partial (ops, TARGET_OBJECT_MEMORY, annex, readbuf, - writebuf, addr, len, xfered_len); -} - -/* Read LEN bytes at ADDR from memory, and store it in BUF. This memory - region is assumed to be inside the backing store. - - Return zero if the operation failed. */ - -static int -ia64_hpux_read_memory_bs (gdb_byte *buf, CORE_ADDR addr, int len) -{ - gdb_byte tmp_buf[8]; - CORE_ADDR tmp_addr = addr & ~0x7; - - while (tmp_addr < addr + len) - { - int status; - int skip_lo = 0; - int skip_hi = 0; - - status = ttrace (TT_LWP_RDRSEBS, ptid_get_pid (inferior_ptid), - ptid_get_lwp (inferior_ptid), tmp_addr, - sizeof (tmp_buf), (uintptr_t) tmp_buf); - if (status < 0) - return 0; - - if (tmp_addr < addr) - skip_lo = addr - tmp_addr; - - if (tmp_addr + sizeof (tmp_buf) > addr + len) - skip_hi = (tmp_addr + sizeof (tmp_buf)) - (addr + len); - - memcpy (buf + (tmp_addr + skip_lo - addr), - tmp_buf + skip_lo, - sizeof (tmp_buf) - skip_lo - skip_hi); - - tmp_addr += sizeof (tmp_buf); - } - - return 1; -} - -/* Write LEN bytes from BUF in memory at ADDR. This memory region is assumed - to be inside the backing store. - - Return zero if the operation failed. */ - -static int -ia64_hpux_write_memory_bs (const gdb_byte *buf, CORE_ADDR addr, int len) -{ - gdb_byte tmp_buf[8]; - CORE_ADDR tmp_addr = addr & ~0x7; - - while (tmp_addr < addr + len) - { - int status; - int lo = 0; - int hi = 7; - - if (tmp_addr < addr || tmp_addr + sizeof (tmp_buf) > addr + len) - /* Part of the 8byte region pointed by tmp_addr needs to be preserved. - So read it in before we copy the data that needs to be changed. */ - if (!ia64_hpux_read_memory_bs (tmp_buf, tmp_addr, sizeof (tmp_buf))) - return 0; - - if (tmp_addr < addr) - lo = addr - tmp_addr; - - if (tmp_addr + sizeof (tmp_buf) > addr + len) - hi = addr - tmp_addr + len - 1; - - memcpy (tmp_buf + lo, buf + tmp_addr - addr + lo, hi - lo + 1); - - status = ttrace (TT_LWP_WRRSEBS, ptid_get_pid (inferior_ptid), - ptid_get_lwp (inferior_ptid), tmp_addr, - sizeof (tmp_buf), (uintptr_t) tmp_buf); - if (status < 0) - return 0; - - tmp_addr += sizeof (tmp_buf); - } - - return 1; -} - -/* The "xfer_partial" routine for a memory region that is completely - inside of the backing-store region. */ - -static LONGEST -ia64_hpux_xfer_memory_bs (struct target_ops *ops, const char *annex, - gdb_byte *readbuf, const gdb_byte *writebuf, - CORE_ADDR addr, LONGEST len) -{ - int success; - - if (readbuf) - success = ia64_hpux_read_memory_bs (readbuf, addr, len); - else - success = ia64_hpux_write_memory_bs (writebuf, addr, len); - - if (success) - return len; - else - return 0; -} - -/* Get a register value as a unsigned value directly from the system, - instead of going through the regcache. - - This function is meant to be used when inferior_ptid is not - a thread/process known to GDB. */ - -static ULONGEST -ia64_hpux_get_register_from_save_state_t (int regnum, int reg_size) -{ - gdb_byte *buf = alloca (reg_size); - int offset = u_offsets[regnum]; - int status; - - /* The register is assumed to be available for fetching. */ - gdb_assert (offset != -1); - - status = ia64_hpux_read_register_from_save_state_t (offset, buf, reg_size); - if (status < 0) - { - /* This really should not happen. If it does, emit a warning - and pretend the register value is zero. Not exactly the best - error recovery mechanism, but better than nothing. We will - try to do better if we can demonstrate that this can happen - under normal circumstances. */ - warning (_("Failed to read value of register number %d."), regnum); - return 0; - } - - return extract_unsigned_integer (buf, reg_size, BFD_ENDIAN_BIG); -} - -/* The "xfer_partial" target_ops routine for ia64-hpux, in the case - where the requested object is TARGET_OBJECT_MEMORY. */ - -static enum target_xfer_status -ia64_hpux_xfer_memory (struct target_ops *ops, const char *annex, - gdb_byte *readbuf, const gdb_byte *writebuf, - CORE_ADDR addr, ULONGEST len, ULONGEST *xfered_len) -{ - CORE_ADDR bsp, bspstore; - CORE_ADDR start_addr, short_len; - int status = 0; - - /* The back-store region cannot be read/written by the standard memory - read/write operations. So we handle the memory region piecemeal: - (1) and (2) The regions before and after the backing-store region, - which can be treated as normal memory; - (3) The region inside the backing-store, which needs to be - read/written specially. */ - - if (in_inferior_list (ptid_get_pid (inferior_ptid))) - { - struct regcache *regcache = get_current_regcache (); - - regcache_raw_read_unsigned (regcache, IA64_BSP_REGNUM, &bsp); - regcache_raw_read_unsigned (regcache, IA64_BSPSTORE_REGNUM, &bspstore); - } - else - { - /* This is probably a child of our inferior created by a fork. - Because this process has not been added to our inferior list - (we are probably in the process of handling that child - process), we do not have a regcache to read the registers - from. So get those values directly from the kernel. */ - bsp = ia64_hpux_get_register_from_save_state_t (IA64_BSP_REGNUM, 8); - bspstore = - ia64_hpux_get_register_from_save_state_t (IA64_BSPSTORE_REGNUM, 8); - } - - /* 1. Memory region before BSPSTORE. */ - - if (addr < bspstore) - { - short_len = len; - if (addr + len > bspstore) - short_len = bspstore - addr; - - status = ia64_hpux_xfer_memory_no_bs (ops, annex, readbuf, writebuf, - addr, short_len); - if (status <= 0) - return TARGET_XFER_EOF; - } - - /* 2. Memory region after BSP. */ - - if (addr + len > bsp) - { - start_addr = addr; - if (start_addr < bsp) - start_addr = bsp; - short_len = len + addr - start_addr; - - status = ia64_hpux_xfer_memory_no_bs - (ops, annex, - readbuf ? readbuf + (start_addr - addr) : NULL, - writebuf ? writebuf + (start_addr - addr) : NULL, - start_addr, short_len); - if (status <= 0) - return TARGET_XFER_EOF; - } - - /* 3. Memory region between BSPSTORE and BSP. */ - - if (bspstore != bsp - && ((addr < bspstore && addr + len > bspstore) - || (addr + len <= bsp && addr + len > bsp))) - { - start_addr = addr; - if (addr < bspstore) - start_addr = bspstore; - short_len = len + addr - start_addr; - - if (start_addr + short_len > bsp) - short_len = bsp - start_addr; - - gdb_assert (short_len > 0); - - status = ia64_hpux_xfer_memory_bs - (ops, annex, - readbuf ? readbuf + (start_addr - addr) : NULL, - writebuf ? writebuf + (start_addr - addr) : NULL, - start_addr, short_len); - if (status < 0) - return TARGET_XFER_EOF; - } - - *xfered_len = len; - return TARGET_XFER_OK; -} - -/* Handle the transfer of TARGET_OBJECT_HPUX_UREGS objects on ia64-hpux. - ANNEX is currently ignored. - - The current implementation does not support write transfers (because - we do not currently do not need these transfers), and will raise - a failed assertion if WRITEBUF is not NULL. */ - -static enum target_xfer_status -ia64_hpux_xfer_uregs (struct target_ops *ops, const char *annex, - gdb_byte *readbuf, const gdb_byte *writebuf, - ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) -{ - int status; - - gdb_assert (writebuf == NULL); - - status = ia64_hpux_read_register_from_save_state_t (offset, readbuf, len); - if (status < 0) - return TARGET_XFER_E_IO; - - *xfered_len = (ULONGEST) len; - return TARGET_XFER_OK; -} - -/* Handle the transfer of TARGET_OBJECT_HPUX_SOLIB_GOT objects on ia64-hpux. - - The current implementation does not support write transfers (because - we do not currently do not need these transfers), and will raise - a failed assertion if WRITEBUF is not NULL. */ - -static enum target_xfer_status -ia64_hpux_xfer_solib_got (struct target_ops *ops, const char *annex, - gdb_byte *readbuf, const gdb_byte *writebuf, - ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) -{ - CORE_ADDR fun_addr; - /* The linkage pointer. We use a uint64_t to make sure that the size - of the object we are returning is always 64 bits long, as explained - in the description of the TARGET_OBJECT_HPUX_SOLIB_GOT object. - This is probably paranoia, but we do not use a CORE_ADDR because - it could conceivably be larger than uint64_t. */ - uint64_t got; - - gdb_assert (writebuf == NULL); - - if (offset > sizeof (got)) - return TARGET_XFER_EOF; - - fun_addr = string_to_core_addr (annex); - got = ia64_hpux_get_solib_linkage_addr (fun_addr); - - if (len > sizeof (got) - offset) - len = sizeof (got) - offset; - memcpy (readbuf, &got + offset, len); - - *xfered_len = (ULONGEST) len; - return TARGET_XFER_OK; -} - -/* The "to_xfer_partial" target_ops routine for ia64-hpux. */ - -static enum target_xfer_status -ia64_hpux_xfer_partial (struct target_ops *ops, enum target_object object, - const char *annex, gdb_byte *readbuf, - const gdb_byte *writebuf, ULONGEST offset, ULONGEST len, - ULONGEST *xfered_len) -{ - enum target_xfer_status val; - - if (object == TARGET_OBJECT_MEMORY) - val = ia64_hpux_xfer_memory (ops, annex, readbuf, writebuf, offset, len, - xfered_len); - else if (object == TARGET_OBJECT_HPUX_UREGS) - val = ia64_hpux_xfer_uregs (ops, annex, readbuf, writebuf, offset, len, - xfered_len); - else if (object == TARGET_OBJECT_HPUX_SOLIB_GOT) - val = ia64_hpux_xfer_solib_got (ops, annex, readbuf, writebuf, offset, - len, xfered_len); - else - val = super_xfer_partial (ops, object, annex, readbuf, writebuf, offset, - len, xfered_len); - - return val; -} - -/* The "to_can_use_hw_breakpoint" target_ops routine for ia64-hpux. */ - -static int -ia64_hpux_can_use_hw_breakpoint (struct target_ops *self, - int type, int cnt, int othertype) -{ - /* No hardware watchpoint/breakpoint support yet. */ - return 0; -} - -/* The "to_mourn_inferior" routine from the "inf-ttrace" target_ops layer. */ - -static void (*super_mourn_inferior) (struct target_ops *); - -/* The "to_mourn_inferior" target_ops routine for ia64-hpux. */ - -static void -ia64_hpux_mourn_inferior (struct target_ops *ops) -{ - const int pid = ptid_get_pid (inferior_ptid); - int status; - - super_mourn_inferior (ops); - - /* On this platform, the process still exists even after we received - an exit event. Detaching from the process isn't sufficient either, - as it only turns the process into a zombie. So the only solution - we found is to kill it. */ - ttrace (TT_PROC_EXIT, pid, 0, 0, 0, 0); - wait (&status); -} - -/* Prevent warning from -Wmissing-prototypes. */ -void _initialize_ia64_hpux_nat (void); - -void -_initialize_ia64_hpux_nat (void) -{ - struct target_ops *t; - - t = inf_ttrace_target (); - super_to_wait = t->to_wait; - super_xfer_partial = t->to_xfer_partial; - super_mourn_inferior = t->to_mourn_inferior; - - t->to_wait = ia64_hpux_wait; - t->to_fetch_registers = ia64_hpux_fetch_registers; - t->to_store_registers = ia64_hpux_store_registers; - t->to_xfer_partial = ia64_hpux_xfer_partial; - t->to_can_use_hw_breakpoint = ia64_hpux_can_use_hw_breakpoint; - t->to_mourn_inferior = ia64_hpux_mourn_inferior; - t->to_attach_no_wait = 1; - - add_target (t); -} diff --git a/gdb/ia64-hpux-tdep.c b/gdb/ia64-hpux-tdep.c deleted file mode 100644 index da51518..0000000 --- a/gdb/ia64-hpux-tdep.c +++ /dev/null @@ -1,434 +0,0 @@ -/* Target-dependent code for the IA-64 for GDB, the GNU debugger. - - Copyright (C) 2010-2014 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 3 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, see . */ - -#include "defs.h" -#include "ia64-tdep.h" -#include "ia64-hpux-tdep.h" -#include "osabi.h" -#include "gdbtypes.h" -#include "solib.h" -#include "target.h" -#include "frame.h" -#include "regcache.h" -#include "gdbcore.h" -#include "inferior.h" - -/* A sequence of instructions pushed on the stack when we want to perform - an inferior function call. The main purpose of this code is to save - the output region of the register frame belonging to the function - from which we are making the call. Normally, all registers are saved - prior to the call, but this does not include stacked registers because - they are seen by GDB as pseudo registers. - - With Linux kernels, these stacked registers can be saved by simply - creating a new register frame, or in other words by moving the BSP. - But the HP/UX kernel does not allow this. So we rely on this code - instead, that makes functions calls whose only purpose is to create - new register frames. - - The array below is the result obtained after assembling the code - shown below. It's an array of bytes in order to make it independent - of the host endianess, in case it ends up being used on more than - one target. - - start: - // Save b0 before using it (into preserved reg: r4). - mov r4 = b0 - ;; - - br.call.dptk.few b0 = stub# - ;; - - // Add a nop bundle where we can insert our dummy breakpoint. - nop.m 0 - nop.i 0 - nop.i 0 - ;; - - stub: - // Alloc a new register stack frame. Here, we set the size - // of all regions to zero. Eventually, GDB will manually - // change the instruction to set the size of the local region - // to match size of the output region of the function from - // which we are making the function call. This is to protect - // the value of the output registers of the function from - // which we are making the call. - alloc r6 = ar.pfs, 0, 0, 0, 0 - - // Save b0 before using it again (into preserved reg: r5). - mov r5 = b0 - ;; - - // Now that we have protected the entire output region of the - // register stack frame, we can call our function that will - // setup the arguments, and call our target function. - br.call.dptk.few b0 = call_dummy# - ;; - - // Restore b0, ar.pfs, and return - mov b0 = r5 - mov.i ar.pfs = r6 - ;; - br.ret.dptk.few b0 - ;; - - call_dummy: - // Alloc a new frame, with 2 local registers, and 8 output registers - // (8 output registers for the maximum of 8 slots passed by register). - alloc r32 = ar.pfs, 2, 0, 8, 0 - - // Save b0 before using it to call our target function. - mov r33 = b0 - - // Load the argument values placed by GDB inside r14-r21 in their - // proper registers. - or r34 = r14, r0 - or r35 = r15, r0 - or r36 = r16, r0 - or r37 = r17, r0 - or r38 = r18, r0 - or r39 = r19, r0 - or r40 = r20, r0 - or r41 = r21, r0 - ;; - - // actual call - br.call.dptk.few b0 = b1 - ;; - - mov.i ar.pfs=r32 - mov b0=r33 - ;; - - br.ret.dptk.few b0 - ;; - -*/ - -static const gdb_byte ia64_hpux_dummy_code[] = -{ - 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, - 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, - 0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x52, - 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, - 0x02, 0x30, 0x00, 0x00, 0x80, 0x05, 0x50, 0x00, - 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, - 0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x30, 0x00, 0x00, 0x52, - 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x28, - 0x04, 0x80, 0x03, 0x00, 0x60, 0x00, 0xaa, 0x00, - 0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x84, 0x02, - 0x00, 0x00, 0x29, 0x04, 0x80, 0x05, 0x10, 0x02, - 0x00, 0x62, 0x00, 0x40, 0xe4, 0x00, 0x38, 0x80, - 0x00, 0x18, 0x3d, 0x00, 0x0e, 0x20, 0x40, 0x82, - 0x00, 0x1c, 0x40, 0xa0, 0x14, 0x01, 0x38, 0x80, - 0x00, 0x30, 0x49, 0x00, 0x0e, 0x20, 0x70, 0x9a, - 0x00, 0x1c, 0x40, 0x00, 0x45, 0x01, 0x38, 0x80, - 0x0a, 0x48, 0x55, 0x00, 0x0e, 0x20, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, - 0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x10, 0x00, 0x80, 0x12, - 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x55, 0x00, 0x00, 0x10, 0x0a, 0x00, 0x07, - 0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x84, 0x02 -}; - -/* The offset to be used in order to get the __reason pseudo-register - when using one of the *UREGS ttrace requests (see system header file - /usr/include/ia64/sys/uregs.h for more details). - - The documentation for this pseudo-register says that a nonzero value - indicates that the thread stopped due to a fault, trap, or interrupt. - A null value indicates a stop inside a syscall. */ -#define IA64_HPUX_UREG_REASON 0x00070000 - -/* Return nonzero if the value of the register identified by REGNUM - can be modified. */ - -static int -ia64_hpux_can_store_ar_register (int regnum) -{ - switch (regnum) - { - case IA64_RSC_REGNUM: - case IA64_RNAT_REGNUM: - case IA64_CSD_REGNUM: - case IA64_SSD_REGNUM: - case IA64_CCV_REGNUM: - case IA64_UNAT_REGNUM: - case IA64_FPSR_REGNUM: - case IA64_PFS_REGNUM: - case IA64_LC_REGNUM: - case IA64_EC_REGNUM: - return 1; - break; - - default: - return 0; - break; - } -} - -/* The "cannot_store_register" target_ops method. */ - -static int -ia64_hpux_cannot_store_register (struct gdbarch *gdbarch, int regnum) -{ - /* General registers. */ - - if (regnum == IA64_GR0_REGNUM) - return 1; - - /* FP register. */ - - if (regnum == IA64_FR0_REGNUM || regnum == IA64_FR1_REGNUM) - return 1; - - /* Application registers. */ - if (regnum >= IA64_AR0_REGNUM && regnum <= IA64_AR0_REGNUM + 127) - return (!ia64_hpux_can_store_ar_register (regnum)); - - /* We can store all other registers. */ - return 0; -} - -/* Return nonzero if the inferior is stopped inside a system call. */ - -static int -ia64_hpux_stopped_in_syscall (struct gdbarch *gdbarch) -{ - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct target_ops *ops = ¤t_target; - gdb_byte buf[8]; - int len; - - len = target_read (ops, TARGET_OBJECT_HPUX_UREGS, NULL, - buf, IA64_HPUX_UREG_REASON, sizeof (buf)); - if (len == -1) - /* The target wasn't able to tell us. Assume we are not stopped - in a system call, which is the normal situation. */ - return 0; - gdb_assert (len == 8); - - return (extract_unsigned_integer (buf, len, byte_order) == 0); -} - -/* The "size_of_register_frame" gdbarch_tdep routine for ia64-hpux. */ - -static int -ia64_hpux_size_of_register_frame (struct frame_info *this_frame, - ULONGEST cfm) -{ - int sof; - - if (frame_relative_level (this_frame) == 0 - && ia64_hpux_stopped_in_syscall (get_frame_arch (this_frame))) - /* If the inferior stopped in a system call, the base address - of the register frame is at BSP - SOL instead of BSP - SOF. - This is an HP-UX exception. */ - sof = (cfm & 0x3f80) >> 7; - else - sof = (cfm & 0x7f); - - return sof; -} - -/* Implement the push_dummy_code gdbarch method. - - This function assumes that the SP is already 16-byte-aligned. */ - -static CORE_ADDR -ia64_hpux_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp, - CORE_ADDR funaddr, struct value **args, int nargs, - struct type *value_type, CORE_ADDR *real_pc, - CORE_ADDR *bp_addr, struct regcache *regcache) -{ - ULONGEST cfm; - int sof, sol, sor, soo; - gdb_byte buf[16]; - - regcache_cooked_read_unsigned (regcache, IA64_CFM_REGNUM, &cfm); - sof = cfm & 0x7f; - sol = (cfm >> 7) & 0x7f; - sor = (cfm >> 14) & 0xf; - soo = sof - sol - sor; - - /* Reserve some space on the stack to hold the dummy code. */ - sp = sp - sizeof (ia64_hpux_dummy_code); - - /* Set the breakpoint address at the first instruction of the bundle - in the dummy code that has only nops. This is where the dummy code - expects us to break. */ - *bp_addr = sp + 0x20; - - /* Start the inferior function call from the dummy code. The dummy - code will then call our function. */ - *real_pc = sp; - - /* Transfer the dummy code to the inferior. */ - write_memory (sp, ia64_hpux_dummy_code, sizeof (ia64_hpux_dummy_code)); - - /* Update the size of the local portion of the register frame allocated - by ``stub'' to match the size of the output region of the current - register frame. This allows us to save the stacked registers. - - The "alloc" instruction is located at slot 0 of the bundle at +0x30. - Update the "sof" and "sol" portion of that instruction which are - respectively at bits 18-24 and 25-31 of the bundle. */ - memcpy (buf, ia64_hpux_dummy_code + 0x30, sizeof (buf)); - - buf[2] |= ((soo & 0x3f) << 2); - buf[3] |= (soo << 1); - if (soo > 63) - buf[3] |= 1; - - write_memory (sp + 0x30, buf, sizeof (buf)); - - /* Return the new (already properly aligned) SP. */ - return sp; -} - -/* The "allocate_new_rse_frame" ia64_infcall_ops routine for ia64-hpux. */ - -static void -ia64_hpux_allocate_new_rse_frame (struct regcache *regcache, ULONGEST bsp, - int sof) -{ - /* We cannot change the value of the BSP register on HP-UX, - so we can't allocate a new RSE frame. */ -} - -/* The "store_argument_in_slot" ia64_infcall_ops routine for ia64-hpux. */ - -static void -ia64_hpux_store_argument_in_slot (struct regcache *regcache, CORE_ADDR bsp, - int slotnum, gdb_byte *buf) -{ - /* The call sequence on this target expects us to place the arguments - inside r14 - r21. */ - regcache_cooked_write (regcache, IA64_GR0_REGNUM + 14 + slotnum, buf); -} - -/* The "set_function_addr" ia64_infcall_ops routine for ia64-hpux. */ - -static void -ia64_hpux_set_function_addr (struct regcache *regcache, CORE_ADDR func_addr) -{ - /* The calling sequence calls the function whose address is placed - in register b1. */ - regcache_cooked_write_unsigned (regcache, IA64_BR1_REGNUM, func_addr); -} - -/* The ia64_infcall_ops structure for ia64-hpux. */ - -static const struct ia64_infcall_ops ia64_hpux_infcall_ops = -{ - ia64_hpux_allocate_new_rse_frame, - ia64_hpux_store_argument_in_slot, - ia64_hpux_set_function_addr -}; - -/* The "dummy_id" gdbarch routine for ia64-hpux. */ - -static struct frame_id -ia64_hpux_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame) -{ - CORE_ADDR sp, pc, bp_addr, bsp; - - sp = get_frame_register_unsigned (this_frame, IA64_GR12_REGNUM); - - /* Just double-check that the frame PC is within a certain region - of the stack that would be plausible for our dummy code (the dummy - code was pushed at SP + 16). If not, then return a null frame ID. - This is necessary in our case, because it is possible to produce - the same frame ID for a normal frame, if that frame corresponds - to the function called by our dummy code, and the function has not - modified the registers that we use to build the dummy frame ID. */ - pc = get_frame_pc (this_frame); - if (pc < sp + 16 || pc >= sp + 16 + sizeof (ia64_hpux_dummy_code)) - return null_frame_id; - - /* The call sequence is such that the address of the dummy breakpoint - we inserted is stored in r5. */ - bp_addr = get_frame_register_unsigned (this_frame, IA64_GR5_REGNUM); - - bsp = get_frame_register_unsigned (this_frame, IA64_BSP_REGNUM); - - return frame_id_build_special (sp, bp_addr, bsp); -} - -/* Should be set to non-NULL if the ia64-hpux solib module is linked in. - This may not be the case because the shared library support code can - only be compiled on ia64-hpux. */ - -struct target_so_ops *ia64_hpux_so_ops = NULL; - -/* The "find_global_pointer_from_solib" gdbarch_tdep routine for - ia64-hpux. */ - -static CORE_ADDR -ia64_hpux_find_global_pointer_from_solib (struct gdbarch *gdbarch, - CORE_ADDR faddr) -{ - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct target_ops *ops = ¤t_target; - gdb_byte buf[8]; - LONGEST len; - - len = target_read (ops, TARGET_OBJECT_HPUX_SOLIB_GOT, - paddress (gdbarch, faddr), buf, 0, sizeof (buf)); - - return extract_unsigned_integer (buf, len, byte_order); -} - -static void -ia64_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - tdep->size_of_register_frame = ia64_hpux_size_of_register_frame; - - set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad); - set_gdbarch_cannot_store_register (gdbarch, ia64_hpux_cannot_store_register); - - /* Inferior functions must be called from stack. */ - set_gdbarch_call_dummy_location (gdbarch, ON_STACK); - set_gdbarch_push_dummy_code (gdbarch, ia64_hpux_push_dummy_code); - tdep->infcall_ops = ia64_hpux_infcall_ops; - tdep->find_global_pointer_from_solib - = ia64_hpux_find_global_pointer_from_solib; - set_gdbarch_dummy_id (gdbarch, ia64_hpux_dummy_id); - - if (ia64_hpux_so_ops) - set_solib_ops (gdbarch, ia64_hpux_so_ops); -} - -/* Provide a prototype to silence -Wmissing-prototypes. */ -extern initialize_file_ftype _initialize_ia64_hpux_tdep; - -void -_initialize_ia64_hpux_tdep (void) -{ - gdbarch_register_osabi (bfd_arch_ia64, 0, GDB_OSABI_HPUX_ELF, - ia64_hpux_init_abi); -} diff --git a/gdb/ia64-hpux-tdep.h b/gdb/ia64-hpux-tdep.h deleted file mode 100644 index a82215e..0000000 --- a/gdb/ia64-hpux-tdep.h +++ /dev/null @@ -1,24 +0,0 @@ -/* Copyright (C) 2010-2014 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 3 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, see . */ - -#ifndef IA64_HPUX_TDEP_H -#define IA64_HPUX_TDEP_H - -struct target_so_ops; -extern struct target_so_ops *ia64_hpux_so_ops; - -#endif diff --git a/gdb/inf-ttrace.c b/gdb/inf-ttrace.c deleted file mode 100644 index dceea42..0000000 --- a/gdb/inf-ttrace.c +++ /dev/null @@ -1,1224 +0,0 @@ -/* Low-level child interface to ttrace. - - Copyright (C) 2004-2014 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 3 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, see . */ - -#include "defs.h" - -/* The ttrace(2) system call didn't exist before HP-UX 10.30. Don't - try to compile this code unless we have it. */ -#ifdef HAVE_TTRACE - -#include "command.h" -#include "gdbcore.h" -#include "gdbthread.h" -#include "inferior.h" -#include "terminal.h" -#include "target.h" -#include -#include -#include - -#include "inf-child.h" -#include "inf-ttrace.h" -#include "common/filestuff.h" - - - -/* HP-UX uses a threading model where each user-space thread - corresponds to a kernel thread. These kernel threads are called - lwps. The ttrace(2) interface gives us almost full control over - the threads, which makes it very easy to support them in GDB. We - identify the threads by process ID and lwp ID. The ttrace(2) also - provides us with a thread's user ID (in the `tts_user_tid' member - of `ttstate_t') but we don't use that (yet) as it isn't necessary - to uniquely label the thread. */ - -/* Number of active lwps. */ -static int inf_ttrace_num_lwps; - - -/* On HP-UX versions that have the ttrace(2) system call, we can - implement "hardware" watchpoints by fiddling with the protection of - pages in the address space that contain the variable being watched. - In order to implement this, we keep a dictionary of pages for which - we have changed the protection. */ - -struct inf_ttrace_page -{ - CORE_ADDR addr; /* Page address. */ - int prot; /* Protection. */ - int refcount; /* Reference count. */ - struct inf_ttrace_page *next; - struct inf_ttrace_page *prev; -}; - -struct inf_ttrace_page_dict -{ - struct inf_ttrace_page buckets[128]; - int pagesize; /* Page size. */ - int count; /* Number of pages in this dictionary. */ -} inf_ttrace_page_dict; - -struct inf_ttrace_private_thread_info -{ - int dying; -}; - -/* Number of lwps that are currently in a system call. */ -static int inf_ttrace_num_lwps_in_syscall; - -/* Flag to indicate whether we should re-enable page protections after - the next wait. */ -static int inf_ttrace_reenable_page_protections; - -/* Enable system call events for process PID. */ - -static void -inf_ttrace_enable_syscall_events (pid_t pid) -{ - ttevent_t tte; - ttstate_t tts; - - gdb_assert (inf_ttrace_num_lwps_in_syscall == 0); - - if (ttrace (TT_PROC_GET_EVENT_MASK, pid, 0, - (uintptr_t)&tte, sizeof tte, 0) == -1) - perror_with_name (("ttrace")); - - tte.tte_events |= (TTEVT_SYSCALL_ENTRY | TTEVT_SYSCALL_RETURN); - - if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0, - (uintptr_t)&tte, sizeof tte, 0) == -1) - perror_with_name (("ttrace")); - - if (ttrace (TT_PROC_GET_FIRST_LWP_STATE, pid, 0, - (uintptr_t)&tts, sizeof tts, 0) == -1) - perror_with_name (("ttrace")); - - if (tts.tts_flags & TTS_INSYSCALL) - inf_ttrace_num_lwps_in_syscall++; - - /* FIXME: Handle multiple threads. */ -} - -/* Disable system call events for process PID. */ - -static void -inf_ttrace_disable_syscall_events (pid_t pid) -{ - ttevent_t tte; - - gdb_assert (inf_ttrace_page_dict.count == 0); - - if (ttrace (TT_PROC_GET_EVENT_MASK, pid, 0, - (uintptr_t)&tte, sizeof tte, 0) == -1) - perror_with_name (("ttrace")); - - tte.tte_events &= ~(TTEVT_SYSCALL_ENTRY | TTEVT_SYSCALL_RETURN); - - if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0, - (uintptr_t)&tte, sizeof tte, 0) == -1) - perror_with_name (("ttrace")); - - inf_ttrace_num_lwps_in_syscall = 0; -} - -/* Get information about the page at address ADDR for process PID from - the dictionary. */ - -static struct inf_ttrace_page * -inf_ttrace_get_page (pid_t pid, CORE_ADDR addr) -{ - const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets); - const int pagesize = inf_ttrace_page_dict.pagesize; - int bucket; - struct inf_ttrace_page *page; - - bucket = (addr / pagesize) % num_buckets; - page = &inf_ttrace_page_dict.buckets[bucket]; - while (page) - { - if (page->addr == addr) - break; - - page = page->next; - } - - return page; -} - -/* Add the page at address ADDR for process PID to the dictionary. */ - -static struct inf_ttrace_page * -inf_ttrace_add_page (pid_t pid, CORE_ADDR addr) -{ - const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets); - const int pagesize = inf_ttrace_page_dict.pagesize; - int bucket; - struct inf_ttrace_page *page; - struct inf_ttrace_page *prev = NULL; - - bucket = (addr / pagesize) % num_buckets; - page = &inf_ttrace_page_dict.buckets[bucket]; - while (page) - { - if (page->addr == addr) - break; - - prev = page; - page = page->next; - } - - if (!page) - { - int prot; - - if (ttrace (TT_PROC_GET_MPROTECT, pid, 0, - addr, 0, (uintptr_t)&prot) == -1) - perror_with_name (("ttrace")); - - page = XNEW (struct inf_ttrace_page); - page->addr = addr; - page->prot = prot; - page->refcount = 0; - page->next = NULL; - - page->prev = prev; - prev->next = page; - - inf_ttrace_page_dict.count++; - if (inf_ttrace_page_dict.count == 1) - inf_ttrace_enable_syscall_events (pid); - - if (inf_ttrace_num_lwps_in_syscall == 0) - { - if (ttrace (TT_PROC_SET_MPROTECT, pid, 0, - addr, pagesize, prot & ~PROT_WRITE) == -1) - perror_with_name (("ttrace")); - } - } - - return page; -} - -/* Insert the page at address ADDR of process PID to the dictionary. */ - -static void -inf_ttrace_insert_page (pid_t pid, CORE_ADDR addr) -{ - struct inf_ttrace_page *page; - - page = inf_ttrace_get_page (pid, addr); - if (!page) - page = inf_ttrace_add_page (pid, addr); - - page->refcount++; -} - -/* Remove the page at address ADDR of process PID from the dictionary. */ - -static void -inf_ttrace_remove_page (pid_t pid, CORE_ADDR addr) -{ - const int pagesize = inf_ttrace_page_dict.pagesize; - struct inf_ttrace_page *page; - - page = inf_ttrace_get_page (pid, addr); - page->refcount--; - - gdb_assert (page->refcount >= 0); - - if (page->refcount == 0) - { - if (inf_ttrace_num_lwps_in_syscall == 0) - { - if (ttrace (TT_PROC_SET_MPROTECT, pid, 0, - addr, pagesize, page->prot) == -1) - perror_with_name (("ttrace")); - } - - inf_ttrace_page_dict.count--; - if (inf_ttrace_page_dict.count == 0) - inf_ttrace_disable_syscall_events (pid); - - page->prev->next = page->next; - if (page->next) - page->next->prev = page->prev; - - xfree (page); - } -} - -/* Mask the bits in PROT from the page protections that are currently - in the dictionary for process PID. */ - -static void -inf_ttrace_mask_page_protections (pid_t pid, int prot) -{ - const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets); - const int pagesize = inf_ttrace_page_dict.pagesize; - int bucket; - - for (bucket = 0; bucket < num_buckets; bucket++) - { - struct inf_ttrace_page *page; - - page = inf_ttrace_page_dict.buckets[bucket].next; - while (page) - { - if (ttrace (TT_PROC_SET_MPROTECT, pid, 0, - page->addr, pagesize, page->prot & ~prot) == -1) - perror_with_name (("ttrace")); - - page = page->next; - } - } -} - -/* Write-protect the pages in the dictionary for process PID. */ - -static void -inf_ttrace_enable_page_protections (pid_t pid) -{ - inf_ttrace_mask_page_protections (pid, PROT_WRITE); -} - -/* Restore the protection of the pages in the dictionary for process - PID. */ - -static void -inf_ttrace_disable_page_protections (pid_t pid) -{ - inf_ttrace_mask_page_protections (pid, 0); -} - -/* Insert a "hardware" watchpoint for LEN bytes at address ADDR of - type TYPE. */ - -static int -inf_ttrace_insert_watchpoint (struct target_ops *self, - CORE_ADDR addr, int len, int type, - struct expression *cond) -{ - const int pagesize = inf_ttrace_page_dict.pagesize; - pid_t pid = ptid_get_pid (inferior_ptid); - CORE_ADDR page_addr; - int num_pages; - int page; - - gdb_assert (type == hw_write); - - page_addr = (addr / pagesize) * pagesize; - num_pages = (len + pagesize - 1) / pagesize; - - for (page = 0; page < num_pages; page++, page_addr += pagesize) - inf_ttrace_insert_page (pid, page_addr); - - return 1; -} - -/* Remove a "hardware" watchpoint for LEN bytes at address ADDR of - type TYPE. */ - -static int -inf_ttrace_remove_watchpoint (struct target_ops *self, - CORE_ADDR addr, int len, int type, - struct expression *cond) -{ - const int pagesize = inf_ttrace_page_dict.pagesize; - pid_t pid = ptid_get_pid (inferior_ptid); - CORE_ADDR page_addr; - int num_pages; - int page; - - gdb_assert (type == hw_write); - - page_addr = (addr / pagesize) * pagesize; - num_pages = (len + pagesize - 1) / pagesize; - - for (page = 0; page < num_pages; page++, page_addr += pagesize) - inf_ttrace_remove_page (pid, page_addr); - - return 1; -} - -static int -inf_ttrace_can_use_hw_breakpoint (struct target_ops *self, - int type, int len, int ot) -{ - return (type == bp_hardware_watchpoint); -} - -static int -inf_ttrace_region_ok_for_hw_watchpoint (struct target_ops *self, - CORE_ADDR addr, int len) -{ - return 1; -} - -/* Return non-zero if the current inferior was (potentially) stopped - by hitting a "hardware" watchpoint. */ - -static int -inf_ttrace_stopped_by_watchpoint (struct target_ops *ops) -{ - pid_t pid = ptid_get_pid (inferior_ptid); - lwpid_t lwpid = ptid_get_lwp (inferior_ptid); - ttstate_t tts; - - if (inf_ttrace_page_dict.count > 0) - { - if (ttrace (TT_LWP_GET_STATE, pid, lwpid, - (uintptr_t)&tts, sizeof tts, 0) == -1) - perror_with_name (("ttrace")); - - if (tts.tts_event == TTEVT_SIGNAL - && tts.tts_u.tts_signal.tts_signo == SIGBUS) - { - const int pagesize = inf_ttrace_page_dict.pagesize; - void *addr = tts.tts_u.tts_signal.tts_siginfo.si_addr; - CORE_ADDR page_addr = ((uintptr_t)addr / pagesize) * pagesize; - - if (inf_ttrace_get_page (pid, page_addr)) - return 1; - } - } - - return 0; -} - - -/* Target hook for follow_fork. On entry and at return inferior_ptid - is the ptid of the followed inferior. */ - -static int -inf_ttrace_follow_fork (struct target_ops *ops, int follow_child, - int detach_fork) -{ - struct thread_info *tp = inferior_thread (); - - gdb_assert (tp->pending_follow.kind == TARGET_WAITKIND_FORKED - || tp->pending_follow.kind == TARGET_WAITKIND_VFORKED); - - if (follow_child) - { - struct thread_info *ti; - - /* The child will start out single-threaded. */ - inf_ttrace_num_lwps = 1; - inf_ttrace_num_lwps_in_syscall = 0; - - ti = inferior_thread (); - ti->private = - xmalloc (sizeof (struct inf_ttrace_private_thread_info)); - memset (ti->private, 0, - sizeof (struct inf_ttrace_private_thread_info)); - } - else - { - pid_t child_pid; - - /* Following parent. Detach child now. */ - child_pid = ptid_get_pid (tp->pending_follow.value.related_pid); - if (ttrace (TT_PROC_DETACH, child_pid, 0, 0, 0, 0) == -1) - perror_with_name (("ttrace")); - } - - return 0; -} - - -/* File descriptors for pipes used as semaphores during initial - startup of an inferior. */ -static int inf_ttrace_pfd1[2]; -static int inf_ttrace_pfd2[2]; - -static void -do_cleanup_pfds (void *dummy) -{ - close (inf_ttrace_pfd1[0]); - close (inf_ttrace_pfd1[1]); - close (inf_ttrace_pfd2[0]); - close (inf_ttrace_pfd2[1]); - - unmark_fd_no_cloexec (inf_ttrace_pfd1[0]); - unmark_fd_no_cloexec (inf_ttrace_pfd1[1]); - unmark_fd_no_cloexec (inf_ttrace_pfd2[0]); - unmark_fd_no_cloexec (inf_ttrace_pfd2[1]); -} - -static void -inf_ttrace_prepare (void) -{ - if (pipe (inf_ttrace_pfd1) == -1) - perror_with_name (("pipe")); - - if (pipe (inf_ttrace_pfd2) == -1) - { - close (inf_ttrace_pfd1[0]); - close (inf_ttrace_pfd2[0]); - perror_with_name (("pipe")); - } - - mark_fd_no_cloexec (inf_ttrace_pfd1[0]); - mark_fd_no_cloexec (inf_ttrace_pfd1[1]); - mark_fd_no_cloexec (inf_ttrace_pfd2[0]); - mark_fd_no_cloexec (inf_ttrace_pfd2[1]); -} - -/* Prepare to be traced. */ - -static void -inf_ttrace_me (void) -{ - struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0); - char c; - - /* "Trace me, Dr. Memory!" */ - if (ttrace (TT_PROC_SETTRC, 0, 0, 0, TT_VERSION, 0) == -1) - perror_with_name (("ttrace")); - - /* Tell our parent that we are ready to be traced. */ - if (write (inf_ttrace_pfd1[1], &c, sizeof c) != sizeof c) - perror_with_name (("write")); - - /* Wait until our parent has set the initial event mask. */ - if (read (inf_ttrace_pfd2[0], &c, sizeof c) != sizeof c) - perror_with_name (("read")); - - do_cleanups (old_chain); -} - -/* Start tracing PID. */ - -static void -inf_ttrace_him (struct target_ops *ops, int pid) -{ - struct cleanup *old_chain = make_cleanup (do_cleanup_pfds, 0); - ttevent_t tte; - char c; - - /* Wait until our child is ready to be traced. */ - if (read (inf_ttrace_pfd1[0], &c, sizeof c) != sizeof c) - perror_with_name (("read")); - - /* Set the initial event mask. */ - memset (&tte, 0, sizeof (tte)); - tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK; - tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE; -#ifdef TTEVT_BPT_SSTEP - tte.tte_events |= TTEVT_BPT_SSTEP; -#endif - tte.tte_opts |= TTEO_PROC_INHERIT; - if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0, - (uintptr_t)&tte, sizeof tte, 0) == -1) - perror_with_name (("ttrace")); - - /* Tell our child that we have set the initial event mask. */ - if (write (inf_ttrace_pfd2[1], &c, sizeof c) != sizeof c) - perror_with_name (("write")); - - do_cleanups (old_chain); - - if (!target_is_pushed (ops)) - push_target (ops); - - startup_inferior (START_INFERIOR_TRAPS_EXPECTED); - - /* On some targets, there must be some explicit actions taken after - the inferior has been started up. */ - target_post_startup_inferior (pid_to_ptid (pid)); -} - -static void -inf_ttrace_create_inferior (struct target_ops *ops, char *exec_file, - char *allargs, char **env, int from_tty) -{ - int pid; - - gdb_assert (inf_ttrace_num_lwps == 0); - gdb_assert (inf_ttrace_num_lwps_in_syscall == 0); - gdb_assert (inf_ttrace_page_dict.count == 0); - gdb_assert (inf_ttrace_reenable_page_protections == 0); - - pid = fork_inferior (exec_file, allargs, env, inf_ttrace_me, NULL, - inf_ttrace_prepare, NULL, NULL); - - inf_ttrace_him (ops, pid); -} - -static void -inf_ttrace_mourn_inferior (struct target_ops *ops) -{ - const int num_buckets = ARRAY_SIZE (inf_ttrace_page_dict.buckets); - int bucket; - - inf_ttrace_num_lwps = 0; - inf_ttrace_num_lwps_in_syscall = 0; - - for (bucket = 0; bucket < num_buckets; bucket++) - { - struct inf_ttrace_page *page; - struct inf_ttrace_page *next; - - page = inf_ttrace_page_dict.buckets[bucket].next; - while (page) - { - next = page->next; - xfree (page); - page = next; - } - } - inf_ttrace_page_dict.count = 0; - - inf_child_mourn_inferior (ops); -} - -/* Assuming we just attached the debugger to a new inferior, create - a new thread_info structure for each thread, and add it to our - list of threads. */ - -static void -inf_ttrace_create_threads_after_attach (int pid) -{ - int status; - ptid_t ptid; - ttstate_t tts; - struct thread_info *ti; - - status = ttrace (TT_PROC_GET_FIRST_LWP_STATE, pid, 0, - (uintptr_t) &tts, sizeof (ttstate_t), 0); - if (status < 0) - perror_with_name (_("TT_PROC_GET_FIRST_LWP_STATE ttrace call failed")); - gdb_assert (tts.tts_pid == pid); - - /* Add the stopped thread. */ - ptid = ptid_build (pid, tts.tts_lwpid, 0); - ti = add_thread (ptid); - ti->private = xzalloc (sizeof (struct inf_ttrace_private_thread_info)); - inf_ttrace_num_lwps++; - - /* We use the "first stopped thread" as the currently active thread. */ - inferior_ptid = ptid; - - /* Iterative over all the remaining threads. */ - - for (;;) - { - ptid_t ptid; - - status = ttrace (TT_PROC_GET_NEXT_LWP_STATE, pid, 0, - (uintptr_t) &tts, sizeof (ttstate_t), 0); - if (status < 0) - perror_with_name (_("TT_PROC_GET_NEXT_LWP_STATE ttrace call failed")); - if (status == 0) - break; /* End of list. */ - - ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0); - ti = add_thread (ptid); - ti->private = xzalloc (sizeof (struct inf_ttrace_private_thread_info)); - inf_ttrace_num_lwps++; - } -} - -static void -inf_ttrace_attach (struct target_ops *ops, const char *args, int from_tty) -{ - char *exec_file; - pid_t pid; - ttevent_t tte; - struct inferior *inf; - - pid = parse_pid_to_attach (args); - - if (pid == getpid ()) /* Trying to masturbate? */ - error (_("I refuse to debug myself!")); - - if (from_tty) - { - exec_file = get_exec_file (0); - - if (exec_file) - printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file, - target_pid_to_str (pid_to_ptid (pid))); - else - printf_unfiltered (_("Attaching to %s\n"), - target_pid_to_str (pid_to_ptid (pid))); - - gdb_flush (gdb_stdout); - } - - gdb_assert (inf_ttrace_num_lwps == 0); - gdb_assert (inf_ttrace_num_lwps_in_syscall == 0); - - if (ttrace (TT_PROC_ATTACH, pid, 0, TT_KILL_ON_EXIT, TT_VERSION, 0) == -1) - perror_with_name (("ttrace")); - - inf = current_inferior (); - inferior_appeared (inf, pid); - inf->attach_flag = 1; - - /* Set the initial event mask. */ - memset (&tte, 0, sizeof (tte)); - tte.tte_events |= TTEVT_EXEC | TTEVT_EXIT | TTEVT_FORK | TTEVT_VFORK; - tte.tte_events |= TTEVT_LWP_CREATE | TTEVT_LWP_EXIT | TTEVT_LWP_TERMINATE; -#ifdef TTEVT_BPT_SSTEP - tte.tte_events |= TTEVT_BPT_SSTEP; -#endif - tte.tte_opts |= TTEO_PROC_INHERIT; - if (ttrace (TT_PROC_SET_EVENT_MASK, pid, 0, - (uintptr_t)&tte, sizeof tte, 0) == -1) - perror_with_name (("ttrace")); - - if (!target_is_pushed (ops)) - push_target (ops); - - inf_ttrace_create_threads_after_attach (pid); -} - -static void -inf_ttrace_detach (struct target_ops *ops, const char *args, int from_tty) -{ - pid_t pid = ptid_get_pid (inferior_ptid); - int sig = 0; - - if (from_tty) - { - char *exec_file = get_exec_file (0); - if (exec_file == 0) - exec_file = ""; - printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file, - target_pid_to_str (pid_to_ptid (pid))); - gdb_flush (gdb_stdout); - } - if (args) - sig = atoi (args); - - /* ??? The HP-UX 11.0 ttrace(2) manual page doesn't mention that we - can pass a signal number here. Does this really work? */ - if (ttrace (TT_PROC_DETACH, pid, 0, 0, sig, 0) == -1) - perror_with_name (("ttrace")); - - inf_ttrace_num_lwps = 0; - inf_ttrace_num_lwps_in_syscall = 0; - - inferior_ptid = null_ptid; - detach_inferior (pid); - - inf_child_maybe_unpush_target (ops); -} - -static void -inf_ttrace_kill (struct target_ops *ops) -{ - pid_t pid = ptid_get_pid (inferior_ptid); - - if (pid == 0) - return; - - if (ttrace (TT_PROC_EXIT, pid, 0, 0, 0, 0) == -1) - perror_with_name (("ttrace")); - /* ??? Is it necessary to call ttrace_wait() here? */ - - target_mourn_inferior (); -} - -/* Check is a dying thread is dead by now, and delete it from GDBs - thread list if so. */ -static int -inf_ttrace_delete_dead_threads_callback (struct thread_info *info, void *arg) -{ - lwpid_t lwpid; - struct inf_ttrace_private_thread_info *p; - - if (is_exited (info->ptid)) - return 0; - - lwpid = ptid_get_lwp (info->ptid); - p = (struct inf_ttrace_private_thread_info *) info->private; - - /* Check if an lwp that was dying is still there or not. */ - if (p->dying && (kill (lwpid, 0) == -1)) - /* It's gone now. */ - delete_thread (info->ptid); - - return 0; -} - -/* Resume the lwp pointed to by INFO, with REQUEST, and pass it signal - SIG. */ - -static void -inf_ttrace_resume_lwp (struct thread_info *info, ttreq_t request, int sig) -{ - pid_t pid = ptid_get_pid (info->ptid); - lwpid_t lwpid = ptid_get_lwp (info->ptid); - - if (ttrace (request, pid, lwpid, TT_NOPC, sig, 0) == -1) - { - struct inf_ttrace_private_thread_info *p - = (struct inf_ttrace_private_thread_info *) info->private; - if (p->dying && errno == EPROTO) - /* This is expected, it means the dying lwp is really gone - by now. If ttrace had an event to inform the debugger - the lwp is really gone, this wouldn't be needed. */ - delete_thread (info->ptid); - else - /* This was really unexpected. */ - perror_with_name (("ttrace")); - } -} - -/* Callback for iterate_over_threads. */ - -static int -inf_ttrace_resume_callback (struct thread_info *info, void *arg) -{ - if (!ptid_equal (info->ptid, inferior_ptid) && !is_exited (info->ptid)) - inf_ttrace_resume_lwp (info, TT_LWP_CONTINUE, 0); - - return 0; -} - -static void -inf_ttrace_resume (struct target_ops *ops, - ptid_t ptid, int step, enum gdb_signal signal) -{ - int resume_all; - ttreq_t request = step ? TT_LWP_SINGLE : TT_LWP_CONTINUE; - int sig = gdb_signal_to_host (signal); - struct thread_info *info; - - /* A specific PTID means `step only this process id'. */ - resume_all = (ptid_equal (ptid, minus_one_ptid)); - - /* If resuming all threads, it's the current thread that should be - handled specially. */ - if (resume_all) - ptid = inferior_ptid; - - info = find_thread_ptid (ptid); - inf_ttrace_resume_lwp (info, request, sig); - - if (resume_all) - /* Let all the other threads run too. */ - iterate_over_threads (inf_ttrace_resume_callback, NULL); -} - -static ptid_t -inf_ttrace_wait (struct target_ops *ops, - ptid_t ptid, struct target_waitstatus *ourstatus, int options) -{ - pid_t pid = ptid_get_pid (ptid); - lwpid_t lwpid = ptid_get_lwp (ptid); - ttstate_t tts; - struct thread_info *ti; - ptid_t related_ptid; - - /* Until proven otherwise. */ - ourstatus->kind = TARGET_WAITKIND_SPURIOUS; - - if (pid == -1) - pid = lwpid = 0; - - gdb_assert (pid != 0 || lwpid == 0); - - do - { - set_sigint_trap (); - - if (ttrace_wait (pid, lwpid, TTRACE_WAITOK, &tts, sizeof tts) == -1) - perror_with_name (("ttrace_wait")); - - clear_sigint_trap (); - } - while (tts.tts_event == TTEVT_NONE); - - /* Now that we've waited, we can re-enable the page protections. */ - if (inf_ttrace_reenable_page_protections) - { - gdb_assert (inf_ttrace_num_lwps_in_syscall == 0); - inf_ttrace_enable_page_protections (tts.tts_pid); - inf_ttrace_reenable_page_protections = 0; - } - - ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0); - - if (inf_ttrace_num_lwps == 0) - { - struct thread_info *ti; - - inf_ttrace_num_lwps = 1; - - /* This is the earliest we hear about the lwp member of - INFERIOR_PTID, after an attach or fork_inferior. */ - gdb_assert (ptid_get_lwp (inferior_ptid) == 0); - - /* We haven't set the private member on the main thread yet. Do - it now. */ - ti = find_thread_ptid (inferior_ptid); - gdb_assert (ti != NULL && ti->private == NULL); - ti->private = - xmalloc (sizeof (struct inf_ttrace_private_thread_info)); - memset (ti->private, 0, - sizeof (struct inf_ttrace_private_thread_info)); - - /* Notify the core that this ptid changed. This changes - inferior_ptid as well. */ - thread_change_ptid (inferior_ptid, ptid); - } - - switch (tts.tts_event) - { -#ifdef TTEVT_BPT_SSTEP - case TTEVT_BPT_SSTEP: - /* Make it look like a breakpoint. */ - ourstatus->kind = TARGET_WAITKIND_STOPPED; - ourstatus->value.sig = GDB_SIGNAL_TRAP; - break; -#endif - - case TTEVT_EXEC: - ourstatus->kind = TARGET_WAITKIND_EXECD; - ourstatus->value.execd_pathname = - xmalloc (tts.tts_u.tts_exec.tts_pathlen + 1); - if (ttrace (TT_PROC_GET_PATHNAME, tts.tts_pid, 0, - (uintptr_t)ourstatus->value.execd_pathname, - tts.tts_u.tts_exec.tts_pathlen, 0) == -1) - perror_with_name (("ttrace")); - ourstatus->value.execd_pathname[tts.tts_u.tts_exec.tts_pathlen] = 0; - - /* At this point, all inserted breakpoints are gone. Doing this - as soon as we detect an exec prevents the badness of deleting - a breakpoint writing the current "shadow contents" to lift - the bp. That shadow is NOT valid after an exec. */ - mark_breakpoints_out (); - break; - - case TTEVT_EXIT: - store_waitstatus (ourstatus, tts.tts_u.tts_exit.tts_exitcode); - inf_ttrace_num_lwps = 0; - break; - - case TTEVT_FORK: - related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid, - tts.tts_u.tts_fork.tts_flwpid, 0); - - ourstatus->kind = TARGET_WAITKIND_FORKED; - ourstatus->value.related_pid = related_ptid; - - /* Make sure the other end of the fork is stopped too. */ - if (ttrace_wait (tts.tts_u.tts_fork.tts_fpid, - tts.tts_u.tts_fork.tts_flwpid, - TTRACE_WAITOK, &tts, sizeof tts) == -1) - perror_with_name (("ttrace_wait")); - - gdb_assert (tts.tts_event == TTEVT_FORK); - if (tts.tts_u.tts_fork.tts_isparent) - { - related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid, - tts.tts_u.tts_fork.tts_flwpid, 0); - ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0); - ourstatus->value.related_pid = related_ptid; - } - break; - - case TTEVT_VFORK: - if (tts.tts_u.tts_fork.tts_isparent) - ourstatus->kind = TARGET_WAITKIND_VFORK_DONE; - else - { - related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid, - tts.tts_u.tts_fork.tts_flwpid, 0); - - ourstatus->kind = TARGET_WAITKIND_VFORKED; - ourstatus->value.related_pid = related_ptid; - } - break; - - case TTEVT_LWP_CREATE: - lwpid = tts.tts_u.tts_thread.tts_target_lwpid; - ptid = ptid_build (tts.tts_pid, lwpid, 0); - ti = add_thread (ptid); - ti->private = - xmalloc (sizeof (struct inf_ttrace_private_thread_info)); - memset (ti->private, 0, - sizeof (struct inf_ttrace_private_thread_info)); - inf_ttrace_num_lwps++; - ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0); - /* Let the lwp_create-caller thread continue. */ - ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid), - ptid_get_lwp (ptid), TT_NOPC, 0, 0); - /* Return without stopping the whole process. */ - ourstatus->kind = TARGET_WAITKIND_IGNORE; - return ptid; - - case TTEVT_LWP_EXIT: - if (print_thread_events) - printf_unfiltered (_("[%s exited]\n"), target_pid_to_str (ptid)); - ti = find_thread_ptid (ptid); - gdb_assert (ti != NULL); - ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1; - inf_ttrace_num_lwps--; - /* Let the thread really exit. */ - ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid), - ptid_get_lwp (ptid), TT_NOPC, 0, 0); - /* Return without stopping the whole process. */ - ourstatus->kind = TARGET_WAITKIND_IGNORE; - return ptid; - - case TTEVT_LWP_TERMINATE: - lwpid = tts.tts_u.tts_thread.tts_target_lwpid; - ptid = ptid_build (tts.tts_pid, lwpid, 0); - if (print_thread_events) - printf_unfiltered(_("[%s has been terminated]\n"), - target_pid_to_str (ptid)); - ti = find_thread_ptid (ptid); - gdb_assert (ti != NULL); - ((struct inf_ttrace_private_thread_info *)ti->private)->dying = 1; - inf_ttrace_num_lwps--; - - /* Resume the lwp_terminate-caller thread. */ - ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0); - ttrace (TT_LWP_CONTINUE, ptid_get_pid (ptid), - ptid_get_lwp (ptid), TT_NOPC, 0, 0); - /* Return without stopping the whole process. */ - ourstatus->kind = TARGET_WAITKIND_IGNORE; - return ptid; - - case TTEVT_SIGNAL: - ourstatus->kind = TARGET_WAITKIND_STOPPED; - ourstatus->value.sig = - gdb_signal_from_host (tts.tts_u.tts_signal.tts_signo); - break; - - case TTEVT_SYSCALL_ENTRY: - gdb_assert (inf_ttrace_reenable_page_protections == 0); - inf_ttrace_num_lwps_in_syscall++; - if (inf_ttrace_num_lwps_in_syscall == 1) - { - /* A thread has just entered a system call. Disable any - page protections as the kernel can't deal with them. */ - inf_ttrace_disable_page_protections (tts.tts_pid); - } - ourstatus->kind = TARGET_WAITKIND_SYSCALL_ENTRY; - ourstatus->value.syscall_number = tts.tts_scno; - break; - - case TTEVT_SYSCALL_RETURN: - if (inf_ttrace_num_lwps_in_syscall > 0) - { - /* If the last thread has just left the system call, this - would be a logical place to re-enable the page - protections, but that doesn't work. We can't re-enable - them until we've done another wait. */ - inf_ttrace_reenable_page_protections = - (inf_ttrace_num_lwps_in_syscall == 1); - inf_ttrace_num_lwps_in_syscall--; - } - ourstatus->kind = TARGET_WAITKIND_SYSCALL_RETURN; - ourstatus->value.syscall_number = tts.tts_scno; - break; - - default: - gdb_assert (!"Unexpected ttrace event"); - break; - } - - /* Make sure all threads within the process are stopped. */ - if (ttrace (TT_PROC_STOP, tts.tts_pid, 0, 0, 0, 0) == -1) - perror_with_name (("ttrace")); - - /* Now that the whole process is stopped, check if any dying thread - is really dead by now. If a dying thread is still alive, it will - be stopped too, and will still show up in `info threads', tagged - with "(Exiting)". We could make `info threads' prune dead - threads instead via inf_ttrace_thread_alive, but doing this here - has the advantage that a frontend is notificed sooner of thread - exits. Note that a dying lwp is still alive, it still has to be - resumed, like any other lwp. */ - iterate_over_threads (inf_ttrace_delete_dead_threads_callback, NULL); - - return ptid; -} - -/* Transfer LEN bytes from ADDR in the inferior's memory into READBUF, - and transfer LEN bytes from WRITEBUF into the inferior's memory at - ADDR. Either READBUF or WRITEBUF may be null, in which case the - corresponding transfer doesn't happen. Return the number of bytes - actually transferred (which may be zero if an error occurs). */ - -static LONGEST -inf_ttrace_xfer_memory (CORE_ADDR addr, ULONGEST len, - void *readbuf, const void *writebuf) -{ - pid_t pid = ptid_get_pid (inferior_ptid); - - /* HP-UX treats text space and data space differently. GDB however, - doesn't really know the difference. Therefore we try both. Try - text space before data space though because when we're writing - into text space the instruction cache might need to be flushed. */ - - if (readbuf - && ttrace (TT_PROC_RDTEXT, pid, 0, addr, len, (uintptr_t)readbuf) == -1 - && ttrace (TT_PROC_RDDATA, pid, 0, addr, len, (uintptr_t)readbuf) == -1) - return 0; - - if (writebuf - && ttrace (TT_PROC_WRTEXT, pid, 0, addr, len, (uintptr_t)writebuf) == -1 - && ttrace (TT_PROC_WRDATA, pid, 0, addr, len, (uintptr_t)writebuf) == -1) - return 0; - - return len; -} - -static enum target_xfer_status -inf_ttrace_xfer_partial (struct target_ops *ops, enum target_object object, - const char *annex, gdb_byte *readbuf, - const gdb_byte *writebuf, - ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) -{ - switch (object) - { - case TARGET_OBJECT_MEMORY: - { - LONGEST val = inf_ttrace_xfer_memory (offset, len, readbuf, writebuf); - - if (val == 0) - return TARGET_XFER_EOF; - else - { - *xfered_len = (ULONGEST) val; - return TARGET_XFER_OK; - } - } - - case TARGET_OBJECT_UNWIND_TABLE: - return TARGET_XFER_E_IO; - - case TARGET_OBJECT_AUXV: - return TARGET_XFER_E_IO; - - case TARGET_OBJECT_WCOOKIE: - return TARGET_XFER_E_IO; - - default: - return TARGET_XFER_E_IO; - } -} - -/* Print status information about what we're accessing. */ - -static void -inf_ttrace_files_info (struct target_ops *ignore) -{ - struct inferior *inf = current_inferior (); - printf_filtered (_("\tUsing the running image of %s %s.\n"), - inf->attach_flag ? "attached" : "child", - target_pid_to_str (inferior_ptid)); -} - -static int -inf_ttrace_thread_alive (struct target_ops *ops, ptid_t ptid) -{ - return 1; -} - -/* Return a string describing the state of the thread specified by - INFO. */ - -static char * -inf_ttrace_extra_thread_info (struct target_ops *self, - struct thread_info *info) -{ - struct inf_ttrace_private_thread_info* private = - (struct inf_ttrace_private_thread_info *) info->private; - - if (private != NULL && private->dying) - return "Exiting"; - - return NULL; -} - -static char * -inf_ttrace_pid_to_str (struct target_ops *ops, ptid_t ptid) -{ - pid_t pid = ptid_get_pid (ptid); - lwpid_t lwpid = ptid_get_lwp (ptid); - static char buf[128]; - - if (lwpid == 0) - xsnprintf (buf, sizeof buf, "process %ld", - (long) pid); - else - xsnprintf (buf, sizeof buf, "process %ld, lwp %ld", - (long) pid, (long) lwpid); - return buf; -} - - -/* Implement the get_ada_task_ptid target_ops method. */ - -static ptid_t -inf_ttrace_get_ada_task_ptid (struct target_ops *self, long lwp, long thread) -{ - return ptid_build (ptid_get_pid (inferior_ptid), lwp, 0); -} - - -struct target_ops * -inf_ttrace_target (void) -{ - struct target_ops *t = inf_child_target (); - - t->to_attach = inf_ttrace_attach; - t->to_detach = inf_ttrace_detach; - t->to_resume = inf_ttrace_resume; - t->to_wait = inf_ttrace_wait; - t->to_files_info = inf_ttrace_files_info; - t->to_can_use_hw_breakpoint = inf_ttrace_can_use_hw_breakpoint; - t->to_insert_watchpoint = inf_ttrace_insert_watchpoint; - t->to_remove_watchpoint = inf_ttrace_remove_watchpoint; - t->to_stopped_by_watchpoint = inf_ttrace_stopped_by_watchpoint; - t->to_region_ok_for_hw_watchpoint = - inf_ttrace_region_ok_for_hw_watchpoint; - t->to_kill = inf_ttrace_kill; - t->to_create_inferior = inf_ttrace_create_inferior; - t->to_follow_fork = inf_ttrace_follow_fork; - t->to_mourn_inferior = inf_ttrace_mourn_inferior; - t->to_thread_alive = inf_ttrace_thread_alive; - t->to_extra_thread_info = inf_ttrace_extra_thread_info; - t->to_pid_to_str = inf_ttrace_pid_to_str; - t->to_xfer_partial = inf_ttrace_xfer_partial; - t->to_get_ada_task_ptid = inf_ttrace_get_ada_task_ptid; - - return t; -} -#endif - - -/* Prevent warning from -Wmissing-prototypes. */ -void _initialize_inf_ttrace (void); - -void -_initialize_inf_ttrace (void) -{ -#ifdef HAVE_TTRACE - inf_ttrace_page_dict.pagesize = getpagesize(); -#endif -} diff --git a/gdb/inf-ttrace.h b/gdb/inf-ttrace.h deleted file mode 100644 index 5090298..0000000 --- a/gdb/inf-ttrace.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Low-level child interface to ttrace. - - Copyright (C) 2004-2014 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 3 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, see . */ - -#ifndef INF_TTRACE_H -#define INF_TTRACE_H - -/* Create a prototype ttrace target. The client can override it with - local methods. */ - -extern struct target_ops *inf_ttrace_target (void); - -#endif diff --git a/gdb/solib-ia64-hpux.c b/gdb/solib-ia64-hpux.c deleted file mode 100644 index a718f14..0000000 --- a/gdb/solib-ia64-hpux.c +++ /dev/null @@ -1,701 +0,0 @@ -/* Copyright (C) 2010-2014 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 3 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, see . */ - -#include "defs.h" -#include "ia64-tdep.h" -#include "ia64-hpux-tdep.h" -#include "solib-ia64-hpux.h" -#include "solist.h" -#include "solib.h" -#include "target.h" -#include "gdbtypes.h" -#include "inferior.h" -#include "gdbcore.h" -#include "regcache.h" -#include "opcode/ia64.h" -#include "symfile.h" -#include "objfiles.h" -#include "elf-bfd.h" - -/* Need to define the following macro in order to get the complete - load_module_desc struct definition in dlfcn.h Otherwise, it doesn't - match the size of the struct the loader is providing us during load - events. */ -#define _LOAD_MODULE_DESC_EXT - -#include -#include -#include -#include - -/* The following is to have access to the definition of type load_info_t. */ -#include - -/* The r32 pseudo-register number. - - Like all stacked registers, r32 is treated as a pseudo-register, - because it is not always available for read/write via the ttrace - interface. */ -/* This is a bit of a hack, as we duplicate something hidden inside - ia64-tdep.c, but oh well... */ -#define IA64_R32_PSEUDO_REGNUM (IA64_NAT127_REGNUM + 2) - -/* Our struct so_list private data structure. */ - -struct lm_info -{ - /* The shared library module descriptor. We extract this structure - from the loader at the time the shared library gets mapped. */ - struct load_module_desc module_desc; - - /* The text segment address as defined in the shared library object - (this is not the address where this segment got loaded). This - field is initially set to zero, and computed lazily. */ - CORE_ADDR text_start; - - /* The data segment address as defined in the shared library object - (this is not the address where this segment got loaded). This - field is initially set to zero, and computed lazily. */ - CORE_ADDR data_start; -}; - -/* The list of shared libraries currently mapped by the inferior. */ - -static struct so_list *so_list_head = NULL; - -/* Create a new so_list element. The result should be deallocated - when no longer in use. */ - -static struct so_list * -new_so_list (char *so_name, struct load_module_desc module_desc) -{ - struct so_list *new_so; - - new_so = (struct so_list *) XCNEW (struct so_list); - new_so->lm_info = (struct lm_info *) XCNEW (struct lm_info); - new_so->lm_info->module_desc = module_desc; - - strncpy (new_so->so_name, so_name, SO_NAME_MAX_PATH_SIZE - 1); - new_so->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; - strcpy (new_so->so_original_name, new_so->so_name); - - return new_so; -} - -/* Return non-zero if the instruction at the current PC is a breakpoint - part of the dynamic loading process. - - We identify such instructions by checking that the instruction at - the current pc is a break insn where no software breakpoint has been - inserted by us. We also verify that the operands have specific - known values, to be extra certain. - - PTID is the ptid of the thread that should be checked, but this - function also assumes that inferior_ptid is already equal to PTID. - Ideally, we would like to avoid the requirement on inferior_ptid, - but many routines still use the inferior_ptid global to access - the relevant thread's register and memory. We still have the ptid - as parameter to be able to pass it to the routines that do take a ptid - - that way we avoid increasing explicit uses of the inferior_ptid - global. */ - -static int -ia64_hpux_at_dld_breakpoint_1_p (ptid_t ptid) -{ - struct regcache *regcache = get_thread_regcache (ptid); - CORE_ADDR pc = regcache_read_pc (regcache); - struct address_space *aspace = get_regcache_aspace (regcache); - ia64_insn t0, t1, slot[3], template, insn; - int slotnum; - bfd_byte bundle[16]; - - /* If this is a regular breakpoint, then it can not be a dld one. */ - if (breakpoint_inserted_here_p (aspace, pc)) - return 0; - - slotnum = ((long) pc) & 0xf; - if (slotnum > 2) - internal_error (__FILE__, __LINE__, - "invalid slot (%d) for address %s", slotnum, - paddress (get_regcache_arch (regcache), pc)); - - pc -= (pc & 0xf); - read_memory (pc, bundle, sizeof (bundle)); - - /* bundles are always in little-endian byte order */ - t0 = bfd_getl64 (bundle); - t1 = bfd_getl64 (bundle + 8); - template = (t0 >> 1) & 0xf; - slot[0] = (t0 >> 5) & 0x1ffffffffffLL; - slot[1] = ((t0 >> 46) & 0x3ffff) | ((t1 & 0x7fffff) << 18); - slot[2] = (t1 >> 23) & 0x1ffffffffffLL; - - if (template == 2 && slotnum == 1) - { - /* skip L slot in MLI template: */ - slotnum = 2; - } - - insn = slot[slotnum]; - - return (insn == 0x1c0c9c0 /* break.i 0x070327 */ - || insn == 0x3c0c9c0); /* break.i 0x0f0327 */ -} - -/* Same as ia64_hpux_at_dld_breakpoint_1_p above, with the following - differences: It temporarily sets inferior_ptid to PTID, and also - contains any exception being raised. */ - -int -ia64_hpux_at_dld_breakpoint_p (ptid_t ptid) -{ - volatile struct gdb_exception e; - ptid_t saved_ptid = inferior_ptid; - int result = 0; - - inferior_ptid = ptid; - TRY_CATCH (e, RETURN_MASK_ALL) - { - result = ia64_hpux_at_dld_breakpoint_1_p (ptid); - } - inferior_ptid = saved_ptid; - if (e.reason < 0) - warning (_("error while checking for dld breakpoint: %s"), e.message); - - return result; -} - -/* Handler for library load event: Read the information provided by - the loader, and then use it to read the shared library symbols. */ - -static void -ia64_hpux_handle_load_event (struct regcache *regcache) -{ - CORE_ADDR module_desc_addr; - ULONGEST module_desc_size; - CORE_ADDR so_path_addr; - char so_path[PATH_MAX]; - struct load_module_desc module_desc; - struct so_list *new_so; - - /* Extract the data provided by the loader as follow: - - r33: Address of load_module_desc structure - - r34: size of struct load_module_desc - - r35: Address of string holding shared library path - */ - regcache_cooked_read_unsigned (regcache, IA64_R32_PSEUDO_REGNUM + 1, - &module_desc_addr); - regcache_cooked_read_unsigned (regcache, IA64_R32_PSEUDO_REGNUM + 2, - &module_desc_size); - regcache_cooked_read_unsigned (regcache, IA64_R32_PSEUDO_REGNUM + 3, - &so_path_addr); - - if (module_desc_size != sizeof (struct load_module_desc)) - warning (_("load_module_desc size (%ld) != size returned by kernel (%s)"), - sizeof (struct load_module_desc), - pulongest (module_desc_size)); - - read_memory_string (so_path_addr, so_path, PATH_MAX); - read_memory (module_desc_addr, (gdb_byte *) &module_desc, - sizeof (module_desc)); - - /* Create a new so_list element and insert it at the start of our - so_list_head (we insert at the start of the list only because - it is less work compared to inserting it elsewhere). */ - new_so = new_so_list (so_path, module_desc); - new_so->next = so_list_head; - so_list_head = new_so; -} - -/* Update the value of the PC to point to the begining of the next - instruction bundle. */ - -static void -ia64_hpux_move_pc_to_next_bundle (struct regcache *regcache) -{ - CORE_ADDR pc = regcache_read_pc (regcache); - - pc -= pc & 0xf; - pc += 16; - ia64_write_pc (regcache, pc); -} - -/* Handle loader events. - - PTID is the ptid of the thread corresponding to the event being - handled. Similarly to ia64_hpux_at_dld_breakpoint_1_p, this - function assumes that inferior_ptid is set to PTID. */ - -static void -ia64_hpux_handle_dld_breakpoint_1 (ptid_t ptid) -{ - struct regcache *regcache = get_thread_regcache (ptid); - ULONGEST arg0; - - /* The type of event is provided by the loaded via r32. */ - regcache_cooked_read_unsigned (regcache, IA64_R32_PSEUDO_REGNUM, &arg0); - switch (arg0) - { - case BREAK_DE_SVC_LOADED: - /* Currently, the only service loads are uld and dld, - so we shouldn't need to do anything. Just ignore. */ - break; - case BREAK_DE_LIB_LOADED: - ia64_hpux_handle_load_event (regcache); - solib_add (NULL, 0, ¤t_target, auto_solib_add); - break; - case BREAK_DE_LIB_UNLOADED: - case BREAK_DE_LOAD_COMPLETE: - case BREAK_DE_BOR: - /* Ignore for now. */ - break; - } - - /* Now that we have handled the event, we can move the PC to - the next instruction bundle, past the break instruction. */ - ia64_hpux_move_pc_to_next_bundle (regcache); -} - -/* Same as ia64_hpux_handle_dld_breakpoint_1 above, with the following - differences: This function temporarily sets inferior_ptid to PTID, - and also contains any exception. */ - -void -ia64_hpux_handle_dld_breakpoint (ptid_t ptid) -{ - volatile struct gdb_exception e; - ptid_t saved_ptid = inferior_ptid; - - inferior_ptid = ptid; - TRY_CATCH (e, RETURN_MASK_ALL) - { - ia64_hpux_handle_dld_breakpoint_1 (ptid); - } - inferior_ptid = saved_ptid; - if (e.reason < 0) - warning (_("error detected while handling dld breakpoint: %s"), e.message); -} - -/* Find the address of the code and data segments in ABFD, and update - TEXT_START and DATA_START accordingly. */ - -static void -ia64_hpux_find_start_vma (bfd *abfd, CORE_ADDR *text_start, - CORE_ADDR *data_start) -{ - Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd); - Elf64_Phdr phdr; - int i; - - *text_start = 0; - *data_start = 0; - - if (bfd_seek (abfd, i_ehdrp->e_phoff, SEEK_SET) == -1) - error (_("invalid program header offset in %s"), abfd->filename); - - for (i = 0; i < i_ehdrp->e_phnum; i++) - { - if (bfd_bread (&phdr, sizeof (phdr), abfd) != sizeof (phdr)) - error (_("failed to read segment %d in %s"), i, abfd->filename); - - if (phdr.p_flags & PF_X - && (*text_start == 0 || phdr.p_vaddr < *text_start)) - *text_start = phdr.p_vaddr; - - if (phdr.p_flags & PF_W - && (*data_start == 0 || phdr.p_vaddr < *data_start)) - *data_start = phdr.p_vaddr; - } -} - -/* The "relocate_section_addresses" target_so_ops routine for ia64-hpux. */ - -static void -ia64_hpux_relocate_section_addresses (struct so_list *so, - struct target_section *sec) -{ - CORE_ADDR offset = 0; - - /* If we haven't computed the text & data segment addresses, do so now. - We do this here, because we now have direct access to the associated - bfd, whereas we would have had to open our own if we wanted to do it - while processing the library-load event. */ - if (so->lm_info->text_start == 0 && so->lm_info->data_start == 0) - ia64_hpux_find_start_vma (sec->the_bfd_section->owner, - &so->lm_info->text_start, - &so->lm_info->data_start); - - /* Determine the relocation offset based on which segment - the section belongs to. */ - if ((so->lm_info->text_start < so->lm_info->data_start - && sec->addr < so->lm_info->data_start) - || (so->lm_info->text_start > so->lm_info->data_start - && sec->addr >= so->lm_info->text_start)) - offset = so->lm_info->module_desc.text_base - so->lm_info->text_start; - else if ((so->lm_info->text_start < so->lm_info->data_start - && sec->addr >= so->lm_info->data_start) - || (so->lm_info->text_start > so->lm_info->data_start - && sec->addr < so->lm_info->text_start)) - offset = so->lm_info->module_desc.data_base - so->lm_info->data_start; - - /* And now apply the relocation. */ - sec->addr += offset; - sec->endaddr += offset; - - /* Best effort to set addr_high/addr_low. This is used only by - 'info sharedlibrary'. */ - if (so->addr_low == 0 || sec->addr < so->addr_low) - so->addr_low = sec->addr; - - if (so->addr_high == 0 || sec->endaddr > so->addr_high) - so->addr_high = sec->endaddr; -} - -/* The "free_so" target_so_ops routine for ia64-hpux. */ - -static void -ia64_hpux_free_so (struct so_list *so) -{ - xfree (so->lm_info); -} - -/* The "clear_solib" target_so_ops routine for ia64-hpux. */ - -static void -ia64_hpux_clear_solib (void) -{ - struct so_list *so; - - while (so_list_head != NULL) - { - so = so_list_head; - so_list_head = so_list_head->next; - - ia64_hpux_free_so (so); - xfree (so); - } -} - -/* Assuming the inferior just stopped on an EXEC event, return - the address of the load_info_t structure. */ - -static CORE_ADDR -ia64_hpux_get_load_info_addr (void) -{ - struct type *data_ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr; - CORE_ADDR addr; - int status; - - /* The address of the load_info_t structure is stored in the 4th - argument passed to the initial thread of the process (in other - words, in argv[3]). So get the address of these arguments, - and extract the 4th one. */ - status = ttrace (TT_PROC_GET_ARGS, ptid_get_pid (inferior_ptid), - 0, (uintptr_t) &addr, sizeof (CORE_ADDR), 0); - if (status == -1 && errno) - perror_with_name (_("Unable to get argument list")); - return (read_memory_typed_address (addr + 3 * 8, data_ptr_type)); -} - -/* A structure used to aggregate some information extracted from - the dynamic section of the main executable. */ - -struct dld_info -{ - ULONGEST dld_flags; - CORE_ADDR load_map; -}; - -/* Scan the ".dynamic" section referenced by ABFD and DYN_SECT, - and extract the information needed to fill in INFO. */ - -static void -ia64_hpux_read_dynamic_info (struct gdbarch *gdbarch, bfd *abfd, - asection *dyn_sect, struct dld_info *info) -{ - int sect_size; - char *buf; - char *buf_end; - - /* Make sure that info always has initialized data, even if we fail - to read the syn_sect section. */ - memset (info, 0, sizeof (struct dld_info)); - - sect_size = bfd_section_size (abfd, dyn_sect); - buf = alloca (sect_size); - buf_end = buf + sect_size; - - if (bfd_seek (abfd, dyn_sect->filepos, SEEK_SET) != 0 - || bfd_bread (buf, sect_size, abfd) != sect_size) - error (_("failed to read contents of .dynamic section")); - - for (; buf < buf_end; buf += sizeof (Elf64_Dyn)) - { - Elf64_Dyn *dynp = (Elf64_Dyn *) buf; - Elf64_Sxword d_tag; - - d_tag = bfd_h_get_64 (abfd, &dynp->d_tag); - switch (d_tag) - { - case DT_HP_DLD_FLAGS: - info->dld_flags = bfd_h_get_64 (abfd, &dynp->d_un); - break; - - case DT_HP_LOAD_MAP: - { - CORE_ADDR load_map_addr = bfd_h_get_64 (abfd, &dynp->d_un.d_ptr); - - if (target_read_memory (load_map_addr, - (gdb_byte *) &info->load_map, - sizeof (info->load_map)) != 0) - error (_("failed to read load map at %s"), - paddress (gdbarch, load_map_addr)); - } - break; - } - } -} - -/* Wrapper around target_read_memory used with libdl. */ - -static void * -ia64_hpux_read_tgt_mem (void *buffer, uint64_t ptr, size_t bufsiz, int ident) -{ - if (target_read_memory (ptr, (gdb_byte *) buffer, bufsiz) != 0) - return 0; - else - return buffer; -} - -/* Create a new so_list object for a shared library, and store that - new so_list object in our SO_LIST_HEAD list. - - SO_INDEX is an index specifying the placement of the loaded shared - library in the dynamic loader's search list. Normally, this index - is strictly positive, but an index of -1 refers to the loader itself. - - Return nonzero if the so_list object could be created. A null - return value with a positive SO_INDEX normally means that there are - no more entries in the dynamic loader's search list at SO_INDEX or - beyond. */ - -static int -ia64_hpux_add_so_from_dld_info (struct dld_info info, int so_index) -{ - struct load_module_desc module_desc; - uint64_t so_handle; - char *so_path; - struct so_list *so; - - so_handle = dlgetmodinfo (so_index, &module_desc, sizeof (module_desc), - ia64_hpux_read_tgt_mem, 0, info.load_map); - - if (so_handle == 0) - /* No such entry. We probably reached the end of the list. */ - return 0; - - so_path = dlgetname (&module_desc, sizeof (module_desc), - ia64_hpux_read_tgt_mem, 0, info.load_map); - if (so_path == NULL) - { - /* Should never happen, but let's not crash if it does. */ - warning (_("unable to get shared library name, symbols not loaded")); - return 0; - } - - /* Create a new so_list and insert it at the start of our list. - The order is not extremely important, but it's less work to do so - at the end of the list. */ - so = new_so_list (so_path, module_desc); - so->next = so_list_head; - so_list_head = so; - - return 1; -} - -/* Assuming we just attached to a process, update our list of shared - libraries (SO_LIST_HEAD) as well as GDB's list. */ - -static void -ia64_hpux_solib_add_after_attach (void) -{ - bfd *abfd; - asection *dyn_sect; - struct dld_info info; - int i; - - if (symfile_objfile == NULL) - return; - - abfd = symfile_objfile->obfd; - dyn_sect = bfd_get_section_by_name (abfd, ".dynamic"); - - if (dyn_sect == NULL || bfd_section_size (abfd, dyn_sect) == 0) - return; - - ia64_hpux_read_dynamic_info (get_objfile_arch (symfile_objfile), abfd, - dyn_sect, &info); - - if ((info.dld_flags & DT_HP_DEBUG_PRIVATE) == 0) - { - warning (_( -"The shared libraries were not privately mapped; setting a breakpoint\n\ -in a shared library will not work until you rerun the program.\n\ -Use the following command to enable debugging of shared libraries.\n\ -chatr +dbg enable a.out")); - } - - /* Read the symbols of the dynamic loader (dld.so). */ - ia64_hpux_add_so_from_dld_info (info, -1); - - /* Read the symbols of all the other shared libraries. */ - for (i = 1; ; i++) - if (!ia64_hpux_add_so_from_dld_info (info, i)) - break; /* End of list. */ - - /* Resync the library list at the core level. */ - solib_add (NULL, 1, ¤t_target, auto_solib_add); -} - -/* The "create_inferior_hook" target_so_ops routine for ia64-hpux. */ - -static void -ia64_hpux_solib_create_inferior_hook (int from_tty) -{ - CORE_ADDR load_info_addr; - load_info_t load_info; - - /* Initially, we were thinking about adding a check that the program - (accessible through symfile_objfile) was linked against some shared - libraries, by searching for a ".dynamic" section. However, could - this break in the case of a statically linked program that later - uses dlopen? Programs that are fully statically linked are very - rare, and we will worry about them when we encounter one that - causes trouble. */ - - /* Set the LI_TRACE flag in the load_info_t structure. This enables - notifications when shared libraries are being mapped. */ - load_info_addr = ia64_hpux_get_load_info_addr (); - read_memory (load_info_addr, (gdb_byte *) &load_info, sizeof (load_info)); - load_info.li_flags |= LI_TRACE; - write_memory (load_info_addr, (gdb_byte *) &load_info, sizeof (load_info)); - - /* If we just attached to our process, some shard libraries have - already been mapped. Find which ones they are... */ - if (current_inferior ()->attach_flag) - ia64_hpux_solib_add_after_attach (); -} - -/* The "special_symbol_handling" target_so_ops routine for ia64-hpux. */ - -static void -ia64_hpux_special_symbol_handling (void) -{ - /* Nothing to do. */ -} - -/* The "current_sos" target_so_ops routine for ia64-hpux. */ - -static struct so_list * -ia64_hpux_current_sos (void) -{ - /* Return a deep copy of our own list. */ - struct so_list *new_head = NULL, *prev_new_so = NULL; - struct so_list *our_so; - - for (our_so = so_list_head; our_so != NULL; our_so = our_so->next) - { - struct so_list *new_so; - - new_so = new_so_list (our_so->so_name, our_so->lm_info->module_desc); - if (prev_new_so != NULL) - prev_new_so->next = new_so; - prev_new_so = new_so; - if (new_head == NULL) - new_head = new_so; - } - - return new_head; -} - -/* The "open_symbol_file_object" target_so_ops routine for ia64-hpux. */ - -static int -ia64_hpux_open_symbol_file_object (void *from_ttyp) -{ - return 0; -} - -/* The "in_dynsym_resolve_code" target_so_ops routine for ia64-hpux. */ - -static int -ia64_hpux_in_dynsym_resolve_code (CORE_ADDR pc) -{ - return 0; -} - -/* If FADDR is the address of a function inside one of the shared - libraries, return the shared library linkage address. */ - -CORE_ADDR -ia64_hpux_get_solib_linkage_addr (CORE_ADDR faddr) -{ - struct so_list *so = so_list_head; - - while (so != NULL) - { - struct load_module_desc module_desc = so->lm_info->module_desc; - - if (module_desc.text_base <= faddr - && (module_desc.text_base + module_desc.text_size) > faddr) - return module_desc.linkage_ptr; - - so = so->next; - } - - return 0; -} - -/* Create a new target_so_ops structure suitable for ia64-hpux, and - return its address. */ - -static struct target_so_ops * -ia64_hpux_target_so_ops (void) -{ - struct target_so_ops *ops = XCNEW (struct target_so_ops); - - ops->relocate_section_addresses = ia64_hpux_relocate_section_addresses; - ops->free_so = ia64_hpux_free_so; - ops->clear_solib = ia64_hpux_clear_solib; - ops->solib_create_inferior_hook = ia64_hpux_solib_create_inferior_hook; - ops->special_symbol_handling = ia64_hpux_special_symbol_handling; - ops->current_sos = ia64_hpux_current_sos; - ops->open_symbol_file_object = ia64_hpux_open_symbol_file_object; - ops->in_dynsym_resolve_code = ia64_hpux_in_dynsym_resolve_code; - ops->bfd_open = solib_bfd_open; - - return ops; -} - -/* Prevent warning from -Wmissing-prototypes. */ -void _initialize_solib_ia64_hpux (void); - -void -_initialize_solib_ia64_hpux (void) -{ - ia64_hpux_so_ops = ia64_hpux_target_so_ops (); -} diff --git a/gdb/solib-ia64-hpux.h b/gdb/solib-ia64-hpux.h deleted file mode 100644 index 544d924..0000000 --- a/gdb/solib-ia64-hpux.h +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright (C) 2010-2014 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 3 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, see . */ - -#ifndef SOLIB_IA64_HPUX_H -#define SOLIB_IA64_HPUX_H - -int ia64_hpux_at_dld_breakpoint_p (ptid_t ptid); -void ia64_hpux_handle_dld_breakpoint (ptid_t ptid); -CORE_ADDR ia64_hpux_get_solib_linkage_addr (CORE_ADDR faddr); - -#endif diff --git a/gdb/solib-pa64.c b/gdb/solib-pa64.c deleted file mode 100644 index 099e1e7..0000000 --- a/gdb/solib-pa64.c +++ /dev/null @@ -1,654 +0,0 @@ -/* Handle PA64 shared libraries for GDB, the GNU Debugger. - - Copyright (C) 2004-2014 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 3 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, see . */ - -/* HP in their infinite stupidity choose not to use standard ELF dynamic - linker interfaces. They also choose not to make their ELF dymamic - linker interfaces compatible with the SOM dynamic linker. The - net result is we can not use either of the existing somsolib.c or - solib.c. What a crock. - - Even more disgusting. This file depends on functions provided only - in certain PA64 libraries. Thus this file is supposed to only be - used native. When will HP ever learn that they need to provide the - same functionality in all their libraries! */ - -#include "defs.h" -#include "symtab.h" -#include "bfd.h" -#include "symfile.h" -#include "objfiles.h" -#include "gdbcore.h" -#include "target.h" -#include "inferior.h" -#include "regcache.h" -#include "gdb_bfd.h" - -#include "hppa-tdep.h" -#include "solist.h" -#include "solib.h" -#include "solib-pa64.h" - -#undef SOLIB_PA64_DBG - -/* We can build this file only when running natively on 64-bit HP/UX. - We check for that by checking for the elf_hp.h header file. */ -#if defined(HAVE_ELF_HP_H) && defined(__LP64__) - -/* FIXME: kettenis/20041213: These includes should be eliminated. */ -#include -#include -#include - -struct lm_info { - struct load_module_desc desc; - CORE_ADDR desc_addr; -}; - -/* When adding fields, be sure to clear them in _initialize_pa64_solib. */ -typedef struct - { - CORE_ADDR dld_flags_addr; - LONGEST dld_flags; - struct bfd_section *dyninfo_sect; - int have_read_dld_descriptor; - int is_valid; - CORE_ADDR load_map; - CORE_ADDR load_map_addr; - struct load_module_desc dld_desc; - } -dld_cache_t; - -static dld_cache_t dld_cache; - -static int read_dynamic_info (asection *dyninfo_sect, - dld_cache_t *dld_cache_p); - -static void -pa64_relocate_section_addresses (struct so_list *so, - struct target_section *sec) -{ - asection *asec = sec->the_bfd_section; - CORE_ADDR load_offset; - - /* Relocate all the sections based on where they got loaded. */ - - load_offset = bfd_section_vma (so->abfd, asec) - asec->filepos; - - if (asec->flags & SEC_CODE) - { - sec->addr += so->lm_info->desc.text_base - load_offset; - sec->endaddr += so->lm_info->desc.text_base - load_offset; - } - else if (asec->flags & SEC_DATA) - { - sec->addr += so->lm_info->desc.data_base - load_offset; - sec->endaddr += so->lm_info->desc.data_base - load_offset; - } -} - -static void -pa64_free_so (struct so_list *so) -{ - xfree (so->lm_info); -} - -static void -pa64_clear_solib (void) -{ -} - -/* Wrapper for target_read_memory for dlgetmodinfo. */ - -static void * -pa64_target_read_memory (void *buffer, CORE_ADDR ptr, size_t bufsiz, int ident) -{ - if (target_read_memory (ptr, buffer, bufsiz) != 0) - return 0; - return buffer; -} - -/* Read the dynamic linker's internal shared library descriptor. - - This must happen after dld starts running, so we can't do it in - read_dynamic_info. Record the fact that we have loaded the - descriptor. If the library is archive bound or the load map - hasn't been setup, then return zero; else return nonzero. */ - -static int -read_dld_descriptor (void) -{ - char *dll_path; - asection *dyninfo_sect; - - /* If necessary call read_dynamic_info to extract the contents of the - .dynamic section from the shared library. */ - if (!dld_cache.is_valid) - { - if (symfile_objfile == NULL) - error (_("No object file symbols.")); - - dyninfo_sect = bfd_get_section_by_name (symfile_objfile->obfd, - ".dynamic"); - if (!dyninfo_sect) - { - return 0; - } - - if (!read_dynamic_info (dyninfo_sect, &dld_cache)) - error (_("Unable to read in .dynamic section information.")); - } - - /* Read the load map pointer. */ - if (target_read_memory (dld_cache.load_map_addr, - (char *) &dld_cache.load_map, - sizeof (dld_cache.load_map)) - != 0) - { - error (_("Error while reading in load map pointer.")); - } - - if (!dld_cache.load_map) - return 0; - - /* Read in the dld load module descriptor. */ - if (dlgetmodinfo (-1, - &dld_cache.dld_desc, - sizeof (dld_cache.dld_desc), - pa64_target_read_memory, - 0, - dld_cache.load_map) - == 0) - { - error (_("Error trying to get information about dynamic linker.")); - } - - /* Indicate that we have loaded the dld descriptor. */ - dld_cache.have_read_dld_descriptor = 1; - - return 1; -} - - -/* Read the .dynamic section and extract the information of interest, - which is stored in dld_cache. The routine elf_locate_base in solib.c - was used as a model for this. */ - -static int -read_dynamic_info (asection *dyninfo_sect, dld_cache_t *dld_cache_p) -{ - char *buf; - char *bufend; - CORE_ADDR dyninfo_addr; - int dyninfo_sect_size; - CORE_ADDR entry_addr; - - /* Read in .dynamic section, silently ignore errors. */ - dyninfo_addr = bfd_section_vma (symfile_objfile->obfd, dyninfo_sect); - dyninfo_sect_size = bfd_section_size (exec_bfd, dyninfo_sect); - buf = alloca (dyninfo_sect_size); - if (target_read_memory (dyninfo_addr, buf, dyninfo_sect_size)) - return 0; - - /* Scan the .dynamic section and record the items of interest. - In particular, DT_HP_DLD_FLAGS. */ - for (bufend = buf + dyninfo_sect_size, entry_addr = dyninfo_addr; - buf < bufend; - buf += sizeof (Elf64_Dyn), entry_addr += sizeof (Elf64_Dyn)) - { - Elf64_Dyn *x_dynp = (Elf64_Dyn*)buf; - Elf64_Sxword dyn_tag; - CORE_ADDR dyn_ptr; - - dyn_tag = bfd_h_get_64 (symfile_objfile->obfd, - (bfd_byte*) &x_dynp->d_tag); - - /* We can't use a switch here because dyn_tag is 64 bits and HP's - lame comiler does not handle 64bit items in switch statements. */ - if (dyn_tag == DT_NULL) - break; - else if (dyn_tag == DT_HP_DLD_FLAGS) - { - /* Set dld_flags_addr and dld_flags in *dld_cache_p. */ - dld_cache_p->dld_flags_addr = entry_addr + offsetof(Elf64_Dyn, d_un); - if (target_read_memory (dld_cache_p->dld_flags_addr, - (char*) &dld_cache_p->dld_flags, - sizeof (dld_cache_p->dld_flags)) - != 0) - { - error (_("Error while reading in " - ".dynamic section of the program.")); - } - } - else if (dyn_tag == DT_HP_LOAD_MAP) - { - /* Dld will place the address of the load map at load_map_addr - after it starts running. */ - if (target_read_memory (entry_addr + offsetof(Elf64_Dyn, - d_un.d_ptr), - (char*) &dld_cache_p->load_map_addr, - sizeof (dld_cache_p->load_map_addr)) - != 0) - { - error (_("Error while reading in " - ".dynamic section of the program.")); - } - } - else - { - /* Tag is not of interest. */ - } - } - - /* Record other information and set is_valid to 1. */ - dld_cache_p->dyninfo_sect = dyninfo_sect; - - /* Verify that we read in required info. These fields are re-set to zero - in pa64_solib_restart. */ - - if (dld_cache_p->dld_flags_addr != 0 && dld_cache_p->load_map_addr != 0) - dld_cache_p->is_valid = 1; - else - return 0; - - return 1; -} - -/* Helper function for gdb_bfd_lookup_symbol_from_symtab. */ - -static int -cmp_name (asymbol *sym, void *data) -{ - return (strcmp (sym->name, (const char *) data) == 0); -} - -/* This hook gets called just before the first instruction in the - inferior process is executed. - - This is our opportunity to set magic flags in the inferior so - that GDB can be notified when a shared library is mapped in and - to tell the dynamic linker that a private copy of the library is - needed (so GDB can set breakpoints in the library). - - We need to set DT_HP_DEBUG_CALLBACK to indicate that we want the - dynamic linker to call the breakpoint routine for significant events. - We used to set DT_HP_DEBUG_PRIVATE to indicate that shared libraries - should be mapped private. However, this flag can be set using - "chatr +dbg enable". Not setting DT_HP_DEBUG_PRIVATE allows debugging - with shared libraries mapped shareable. */ - -static void -pa64_solib_create_inferior_hook (int from_tty) -{ - struct minimal_symbol *msymbol; - unsigned int dld_flags, status; - asection *shlib_info, *interp_sect; - struct objfile *objfile; - CORE_ADDR anaddr; - - if (symfile_objfile == NULL) - return; - - /* First see if the objfile was dynamically linked. */ - shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, ".dynamic"); - if (!shlib_info) - return; - - /* It's got a .dynamic section, make sure it's not empty. */ - if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0) - return; - - /* Read in the .dynamic section. */ - if (! read_dynamic_info (shlib_info, &dld_cache)) - error (_("Unable to read the .dynamic section.")); - - /* If the libraries were not mapped private, warn the user. */ - if ((dld_cache.dld_flags & DT_HP_DEBUG_PRIVATE) == 0) - warning - (_("\ -Private mapping of shared library text was not specified\n\ -by the executable; setting a breakpoint in a shared library which\n\ -is not privately mapped will not work. See the HP-UX 11i v3 chatr\n\ -manpage for methods to privately map shared library text.")); - - /* Turn on the flags we care about. */ - dld_cache.dld_flags |= DT_HP_DEBUG_CALLBACK; - status = target_write_memory (dld_cache.dld_flags_addr, - (char *) &dld_cache.dld_flags, - sizeof (dld_cache.dld_flags)); - if (status != 0) - error (_("Unable to modify dynamic linker flags.")); - - /* Now we have to create a shared library breakpoint in the dynamic - linker. This can be somewhat tricky since the symbol is inside - the dynamic linker (for which we do not have symbols or a base - load address! Luckily I wrote this code for solib.c years ago. */ - interp_sect = bfd_get_section_by_name (exec_bfd, ".interp"); - if (interp_sect) - { - unsigned int interp_sect_size; - char *buf; - CORE_ADDR load_addr; - bfd *tmp_bfd; - CORE_ADDR sym_addr = 0; - - /* Read the contents of the .interp section into a local buffer; - the contents specify the dynamic linker this program uses. */ - interp_sect_size = bfd_section_size (exec_bfd, interp_sect); - buf = alloca (interp_sect_size); - bfd_get_section_contents (exec_bfd, interp_sect, - buf, 0, interp_sect_size); - - /* Now we need to figure out where the dynamic linker was - loaded so that we can load its symbols and place a breakpoint - in the dynamic linker itself. - - This address is stored on the stack. However, I've been unable - to find any magic formula to find it for Solaris (appears to - be trivial on GNU/Linux). Therefore, we have to try an alternate - mechanism to find the dynamic linker's base address. */ - tmp_bfd = gdb_bfd_open (buf, gnutarget, -1); - if (tmp_bfd == NULL) - return; - - /* Make sure the dynamic linker's really a useful object. */ - if (!bfd_check_format (tmp_bfd, bfd_object)) - { - warning (_("Unable to grok dynamic linker %s as an object file"), - buf); - gdb_bfd_unref (tmp_bfd); - return; - } - - /* We find the dynamic linker's base address by examining the - current pc (which point at the entry point for the dynamic - linker) and subtracting the offset of the entry point. - - Also note the breakpoint is the second instruction in the - routine. */ - load_addr = regcache_read_pc (get_current_regcache ()) - - tmp_bfd->start_address; - sym_addr = gdb_bfd_lookup_symbol_from_symtab (tmp_bfd, cmp_name, - "__dld_break"); - sym_addr = load_addr + sym_addr + 4; - - /* Create the shared library breakpoint. */ - { - struct breakpoint *b - = create_solib_event_breakpoint (target_gdbarch (), sym_addr); - - /* The breakpoint is actually hard-coded into the dynamic linker, - so we don't need to actually insert a breakpoint instruction - there. In fact, the dynamic linker's code is immutable, even to - ttrace, so we shouldn't even try to do that. For cases like - this, we have "permanent" breakpoints. */ - make_breakpoint_permanent (b); - } - - /* We're done with the temporary bfd. */ - gdb_bfd_unref (tmp_bfd); - } -} - -static void -pa64_special_symbol_handling (void) -{ -} - -static struct so_list * -pa64_current_sos (void) -{ - struct so_list *head = 0; - struct so_list **link_ptr = &head; - int dll_index; - - /* Read in the load map pointer if we have not done so already. */ - if (! dld_cache.have_read_dld_descriptor) - if (! read_dld_descriptor ()) - return NULL; - - for (dll_index = -1; ; dll_index++) - { - struct load_module_desc dll_desc; - char *dll_path; - struct so_list *new; - struct cleanup *old_chain; - - if (dll_index == 0) - continue; - - /* Read in the load module descriptor. */ - if (dlgetmodinfo (dll_index, &dll_desc, sizeof (dll_desc), - pa64_target_read_memory, 0, dld_cache.load_map) - == 0) - break; - - /* Get the name of the shared library. */ - dll_path = (char *)dlgetname (&dll_desc, sizeof (dll_desc), - pa64_target_read_memory, - 0, dld_cache.load_map); - - new = (struct so_list *) xmalloc (sizeof (struct so_list)); - memset (new, 0, sizeof (struct so_list)); - new->lm_info = (struct lm_info *) xmalloc (sizeof (struct lm_info)); - memset (new->lm_info, 0, sizeof (struct lm_info)); - - strncpy (new->so_name, dll_path, SO_NAME_MAX_PATH_SIZE - 1); - new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; - strcpy (new->so_original_name, new->so_name); - - memcpy (&new->lm_info->desc, &dll_desc, sizeof (dll_desc)); - -#ifdef SOLIB_PA64_DBG - { - struct load_module_desc *d = &new->lm_info->desc; - - printf ("\n+ library \"%s\" is described at index %d\n", new->so_name, - dll_index); - printf (" text_base = %s\n", hex_string (d->text_base)); - printf (" text_size = %s\n", hex_string (d->text_size)); - printf (" data_base = %s\n", hex_string (d->data_base)); - printf (" data_size = %s\n", hex_string (d->data_size)); - printf (" unwind_base = %s\n", hex_string (d->unwind_base)); - printf (" linkage_ptr = %s\n", hex_string (d->linkage_ptr)); - printf (" phdr_base = %s\n", hex_string (d->phdr_base)); - printf (" tls_size = %s\n", hex_string (d->tls_size)); - printf (" tls_start_addr = %s\n", hex_string (d->tls_start_addr)); - printf (" unwind_size = %s\n", hex_string (d->unwind_size)); - printf (" tls_index = %s\n", hex_string (d->tls_index)); - } -#endif - - /* Link the new object onto the list. */ - new->next = NULL; - *link_ptr = new; - link_ptr = &new->next; - } - - return head; -} - -static int -pa64_open_symbol_file_object (void *from_ttyp) -{ - int from_tty = *(int *)from_ttyp; - struct load_module_desc dll_desc; - char *dll_path; - - if (symfile_objfile) - if (!query (_("Attempt to reload symbols from process? "))) - return 0; - - /* Read in the load map pointer if we have not done so already. */ - if (! dld_cache.have_read_dld_descriptor) - if (! read_dld_descriptor ()) - return 0; - - /* Read in the load module descriptor. */ - if (dlgetmodinfo (0, &dll_desc, sizeof (dll_desc), - pa64_target_read_memory, 0, dld_cache.load_map) == 0) - return 0; - - /* Get the name of the shared library. */ - dll_path = (char *)dlgetname (&dll_desc, sizeof (dll_desc), - pa64_target_read_memory, - 0, dld_cache.load_map); - - /* Have a pathname: read the symbol file. */ - symbol_file_add_main (dll_path, from_tty); - - return 1; -} - -/* Return nonzero if PC is an address inside the dynamic linker. */ -static int -pa64_in_dynsym_resolve_code (CORE_ADDR pc) -{ - asection *shlib_info; - - if (symfile_objfile == NULL) - return 0; - - if (!dld_cache.have_read_dld_descriptor) - if (!read_dld_descriptor ()) - return 0; - - return (pc >= dld_cache.dld_desc.text_base - && pc < dld_cache.dld_desc.text_base + dld_cache.dld_desc.text_size); -} - - -/* Return the GOT value for the shared library in which ADDR belongs. If - ADDR isn't in any known shared library, return zero. */ - -static CORE_ADDR -pa64_solib_get_got_by_pc (CORE_ADDR addr) -{ - struct so_list *so_list = master_so_list (); - CORE_ADDR got_value = 0; - - while (so_list) - { - if (so_list->lm_info->desc.text_base <= addr - && ((so_list->lm_info->desc.text_base - + so_list->lm_info->desc.text_size) - > addr)) - { - got_value = so_list->lm_info->desc.linkage_ptr; - break; - } - so_list = so_list->next; - } - return got_value; -} - -/* Get some HPUX-specific data from a shared lib. */ -static CORE_ADDR -pa64_solib_thread_start_addr (struct so_list *so) -{ - return so->lm_info->desc.tls_start_addr; -} - - -/* Return the address of the handle of the shared library in which ADDR - belongs. If ADDR isn't in any known shared library, return zero. */ - -static CORE_ADDR -pa64_solib_get_solib_by_pc (CORE_ADDR addr) -{ - struct so_list *so_list = master_so_list (); - CORE_ADDR retval = 0; - - while (so_list) - { - if (so_list->lm_info->desc.text_base <= addr - && ((so_list->lm_info->desc.text_base - + so_list->lm_info->desc.text_size) - > addr)) - { - retval = so_list->lm_info->desc_addr; - break; - } - so_list = so_list->next; - } - return retval; -} - -/* pa64 libraries do not seem to set the section offsets in a standard (i.e. - SVr4) way; the text section offset stored in the file doesn't correspond - to the place where the library is actually loaded into memory. Instead, - we rely on the dll descriptor to tell us where things were loaded. */ -static CORE_ADDR -pa64_solib_get_text_base (struct objfile *objfile) -{ - struct so_list *so; - - for (so = master_so_list (); so; so = so->next) - if (so->objfile == objfile) - return so->lm_info->desc.text_base; - - return 0; -} - -static struct target_so_ops pa64_so_ops; - -extern initialize_file_ftype _initialize_pa64_solib; /* -Wmissing-prototypes */ - -void -_initialize_pa64_solib (void) -{ - pa64_so_ops.relocate_section_addresses = pa64_relocate_section_addresses; - pa64_so_ops.free_so = pa64_free_so; - pa64_so_ops.clear_solib = pa64_clear_solib; - pa64_so_ops.solib_create_inferior_hook = pa64_solib_create_inferior_hook; - pa64_so_ops.special_symbol_handling = pa64_special_symbol_handling; - pa64_so_ops.current_sos = pa64_current_sos; - pa64_so_ops.open_symbol_file_object = pa64_open_symbol_file_object; - pa64_so_ops.in_dynsym_resolve_code = pa64_in_dynsym_resolve_code; - pa64_so_ops.bfd_open = solib_bfd_open; - - memset (&dld_cache, 0, sizeof (dld_cache)); -} - -void pa64_solib_select (struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - set_solib_ops (gdbarch, &pa64_so_ops); - tdep->solib_thread_start_addr = pa64_solib_thread_start_addr; - tdep->solib_get_got_by_pc = pa64_solib_get_got_by_pc; - tdep->solib_get_solib_by_pc = pa64_solib_get_solib_by_pc; - tdep->solib_get_text_base = pa64_solib_get_text_base; -} - -#else /* HAVE_ELF_HP_H */ - -extern initialize_file_ftype _initialize_pa64_solib; /* -Wmissing-prototypes */ - -void -_initialize_pa64_solib (void) -{ -} - -void pa64_solib_select (struct gdbarch *gdbarch) -{ - /* For a SOM-only target, there is no pa64 solib support. This is needed - for hppa-hpux-tdep.c to build. */ - error (_("Cannot select pa64 solib support for this configuration.")); -} -#endif diff --git a/gdb/solib-pa64.h b/gdb/solib-pa64.h deleted file mode 100644 index f085af5..0000000 --- a/gdb/solib-pa64.h +++ /dev/null @@ -1,25 +0,0 @@ -/* Handle PA64 shared libraries for GDB, the GNU Debugger. - - Copyright (C) 2004-2014 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 3 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, see . */ - -#ifndef SOLIB_PA64_H -#define SOLIB_PA64_H - -void pa64_solib_select (struct gdbarch *gdbarch); - -#endif diff --git a/gdb/solib-som.c b/gdb/solib-som.c deleted file mode 100644 index 83f2065..0000000 --- a/gdb/solib-som.c +++ /dev/null @@ -1,891 +0,0 @@ -/* Handle SOM shared libraries. - - Copyright (C) 2004-2014 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 3 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, see . */ - -#include "defs.h" -#include "symtab.h" -#include "bfd.h" -#include "symfile.h" -#include "objfiles.h" -#include "gdbcore.h" -#include "target.h" -#include "inferior.h" - -#include "hppa-tdep.h" -#include "solist.h" -#include "solib.h" -#include "solib-som.h" - -#undef SOLIB_SOM_DBG - -/* These ought to be defined in some public interface, but aren't. They - define the meaning of the various bits in the distinguished __dld_flags - variable that is declared in every debuggable a.out on HP-UX, and that - is shared between the debugger and the dynamic linker. */ - -#define DLD_FLAGS_MAPPRIVATE 0x1 -#define DLD_FLAGS_HOOKVALID 0x2 -#define DLD_FLAGS_LISTVALID 0x4 -#define DLD_FLAGS_BOR_ENABLE 0x8 - -struct lm_info - { - /* Version of this structure (it is expected to change again in - hpux10). */ - unsigned char struct_version; - - /* Binding mode for this library. */ - unsigned char bind_mode; - - /* Version of this library. */ - short library_version; - - /* Start of text address, - link-time text location (length of text area), - end of text address. */ - CORE_ADDR text_addr; - CORE_ADDR text_link_addr; - CORE_ADDR text_end; - - /* Start of data, start of bss and end of data. */ - CORE_ADDR data_start; - CORE_ADDR bss_start; - CORE_ADDR data_end; - - /* Value of linkage pointer (%r19). */ - CORE_ADDR got_value; - - /* Address in target of offset from thread-local register of - start of this thread's data. I.e., the first thread-local - variable in this shared library starts at *(tsd_start_addr) - from that area pointed to by cr27 (mpsfu_hi). - - We do the indirection as soon as we read it, so from then - on it's the offset itself. */ - CORE_ADDR tsd_start_addr; - - /* Address of the link map entry in the loader. */ - CORE_ADDR lm_addr; - }; - -/* These addresses should be filled in by som_solib_create_inferior_hook. - They are also used elsewhere in this module. */ - -typedef struct - { - CORE_ADDR address; - struct unwind_table_entry *unwind; - } -addr_and_unwind_t; - -/* When adding fields, be sure to clear them in _initialize_som_solib. */ -static struct - { - int is_valid; - addr_and_unwind_t hook; - addr_and_unwind_t hook_stub; - addr_and_unwind_t load; - addr_and_unwind_t load_stub; - addr_and_unwind_t unload; - addr_and_unwind_t unload2; - addr_and_unwind_t unload_stub; - } -dld_cache; - -static void -som_relocate_section_addresses (struct so_list *so, - struct target_section *sec) -{ - flagword aflag = bfd_get_section_flags(so->abfd, sec->the_bfd_section); - - if (aflag & SEC_CODE) - { - sec->addr += so->lm_info->text_addr - so->lm_info->text_link_addr; - sec->endaddr += so->lm_info->text_addr - so->lm_info->text_link_addr; - } - else if (aflag & SEC_DATA) - { - sec->addr += so->lm_info->data_start; - sec->endaddr += so->lm_info->data_start; - } - else - { - /* Nothing. */ - } -} - - -/* Variable storing HP-UX major release number. - - On non-native system, simply assume that the major release number - is 11. On native systems, hppa-hpux-nat.c initialization code - sets this number to the real one on startup. - - We cannot compute this value here, because we need to make a native - call to "uname". We are are not allowed to do that from here, as - this file is used for both native and cross debugging. */ - -#define DEFAULT_HPUX_MAJOR_RELEASE 11 -int hpux_major_release = DEFAULT_HPUX_MAJOR_RELEASE; - -static int -get_hpux_major_release (void) -{ - return hpux_major_release; -} - -/* DL header flag defines. */ -#define SHLIB_TEXT_PRIVATE_ENABLE 0x4000 - -/* The DL header is documented in . We are only interested - in the flags field to determine whether the executable wants shared - libraries mapped private. */ -struct { - short junk[37]; - short flags; -} dl_header; - -/* This hook gets called just before the first instruction in the - inferior process is executed. - - This is our opportunity to set magic flags in the inferior so - that GDB can be notified when a shared library is mapped in and - to tell the dynamic linker that a private copy of the library is - needed (so GDB can set breakpoints in the library). - - __dld_flags is the location of the magic flags; as of this implementation - there are 3 flags of interest: - - bit 0 when set indicates that private copies of the libraries are needed - bit 1 when set indicates that the callback hook routine is valid - bit 2 when set indicates that the dynamic linker should maintain the - __dld_list structure when loading/unloading libraries. - - Note that shared libraries are not mapped in at this time, so we have - run the inferior until the libraries are mapped in. Typically this - means running until the "_start" is called. */ - -static void -som_solib_create_inferior_hook (int from_tty) -{ - enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); - struct bound_minimal_symbol msymbol; - unsigned int dld_flags, status, have_endo; - asection *shlib_info; - gdb_byte buf[4]; - CORE_ADDR anaddr; - - if (symfile_objfile == NULL) - return; - - /* First see if the objfile was dynamically linked. */ - shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$"); - if (!shlib_info) - return; - - /* It's got a $SHLIB_INFO$ section, make sure it's not empty. */ - if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0) - return; - - /* Read the DL header. */ - bfd_get_section_contents (symfile_objfile->obfd, shlib_info, - (char *) &dl_header, 0, sizeof (dl_header)); - - have_endo = 0; - /* Slam the pid of the process into __d_pid. - - We used to warn when this failed, but that warning is only useful - on very old HP systems (hpux9 and older). The warnings are an - annoyance to users of modern systems and foul up the testsuite as - well. As a result, the warnings have been disabled. */ - msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile); - if (msymbol.minsym == NULL) - goto keep_going; - - anaddr = BMSYMBOL_VALUE_ADDRESS (msymbol); - store_unsigned_integer (buf, 4, byte_order, ptid_get_pid (inferior_ptid)); - status = target_write_memory (anaddr, buf, 4); - if (status != 0) - { - warning (_("\ -Unable to write __d_pid.\n\ -Suggest linking with /opt/langtools/lib/end.o.\n\ -GDB will be unable to track shl_load/shl_unload calls")); - goto keep_going; - } - - /* Get the value of _DLD_HOOK (an export stub) and put it in __dld_hook; - This will force the dynamic linker to call __d_trap when significant - events occur. - - Note that the above is the pre-HP-UX 9.0 behaviour. At 9.0 and above, - the dld provides an export stub named "__d_trap" as well as the - function named "__d_trap" itself, but doesn't provide "_DLD_HOOK". - We'll look first for the old flavor and then the new. */ - - msymbol = lookup_minimal_symbol ("_DLD_HOOK", NULL, symfile_objfile); - if (msymbol.minsym == NULL) - msymbol = lookup_minimal_symbol ("__d_trap", NULL, symfile_objfile); - if (msymbol.minsym == NULL) - { - warning (_("\ -Unable to find _DLD_HOOK symbol in object file.\n\ -Suggest linking with /opt/langtools/lib/end.o.\n\ -GDB will be unable to track shl_load/shl_unload calls")); - goto keep_going; - } - anaddr = BMSYMBOL_VALUE_ADDRESS (msymbol); - dld_cache.hook.address = anaddr; - - /* Grrr, this might not be an export symbol! We have to find the - export stub. */ - msymbol - = hppa_lookup_stub_minimal_symbol (MSYMBOL_LINKAGE_NAME (msymbol.minsym), - EXPORT); - if (msymbol.minsym != NULL) - { - anaddr = MSYMBOL_VALUE (msymbol.minsym); - dld_cache.hook_stub.address = anaddr; - } - store_unsigned_integer (buf, 4, byte_order, anaddr); - - msymbol = lookup_minimal_symbol ("__dld_hook", NULL, symfile_objfile); - if (msymbol.minsym == NULL) - { - warning (_("\ -Unable to find __dld_hook symbol in object file.\n\ -Suggest linking with /opt/langtools/lib/end.o.\n\ -GDB will be unable to track shl_load/shl_unload calls")); - goto keep_going; - } - anaddr = BMSYMBOL_VALUE_ADDRESS (msymbol); - status = target_write_memory (anaddr, buf, 4); - - /* Now set a shlib_event breakpoint at __d_trap so we can track - significant shared library events. */ - msymbol = lookup_minimal_symbol ("__d_trap", NULL, symfile_objfile); - if (msymbol.minsym == NULL) - { - warning (_("\ -Unable to find __dld_d_trap symbol in object file.\n\ -Suggest linking with /opt/langtools/lib/end.o.\n\ -GDB will be unable to track shl_load/shl_unload calls")); - goto keep_going; - } - create_solib_event_breakpoint (target_gdbarch (), - BMSYMBOL_VALUE_ADDRESS (msymbol)); - - /* We have all the support usually found in end.o, so we can track - shl_load and shl_unload calls. */ - have_endo = 1; - -keep_going: - - /* Get the address of __dld_flags, if no such symbol exists, then we can - not debug the shared code. */ - msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL); - if (msymbol.minsym == NULL) - { - error (_("Unable to find __dld_flags symbol in object file.")); - } - - anaddr = BMSYMBOL_VALUE_ADDRESS (msymbol); - - /* Read the current contents. */ - status = target_read_memory (anaddr, buf, 4); - if (status != 0) - error (_("Unable to read __dld_flags.")); - dld_flags = extract_unsigned_integer (buf, 4, byte_order); - - /* If the libraries were not mapped private on HP-UX 11 and later, warn - the user. On HP-UX 10 and earlier, there is no easy way to specify - that shared libraries should be privately mapped. So, we just force - private mapping. */ - if (get_hpux_major_release () >= 11 - && (dl_header.flags & SHLIB_TEXT_PRIVATE_ENABLE) == 0 - && (dld_flags & DLD_FLAGS_MAPPRIVATE) == 0) - warning - (_("\ -Private mapping of shared library text was not specified\n\ -by the executable; setting a breakpoint in a shared library which\n\ -is not privately mapped will not work. See the HP-UX 11i v3 chatr\n\ -manpage for methods to privately map shared library text.")); - - /* Turn on the flags we care about. */ - if (get_hpux_major_release () < 11) - dld_flags |= DLD_FLAGS_MAPPRIVATE; - if (have_endo) - dld_flags |= DLD_FLAGS_HOOKVALID; - store_unsigned_integer (buf, 4, byte_order, dld_flags); - status = target_write_memory (anaddr, buf, 4); - if (status != 0) - error (_("Unable to write __dld_flags.")); - - /* Now find the address of _start and set a breakpoint there. - We still need this code for two reasons: - - * Not all sites have /opt/langtools/lib/end.o, so it's not always - possible to track the dynamic linker's events. - - * At this time no events are triggered for shared libraries - loaded at startup time (what a crock). */ - - msymbol = lookup_minimal_symbol ("_start", NULL, symfile_objfile); - if (msymbol.minsym == NULL) - error (_("Unable to find _start symbol in object file.")); - - anaddr = BMSYMBOL_VALUE_ADDRESS (msymbol); - - /* Make the breakpoint at "_start" a shared library event breakpoint. */ - create_solib_event_breakpoint (target_gdbarch (), anaddr); - - clear_symtab_users (0); -} - -static void -som_special_symbol_handling (void) -{ -} - -static void -som_solib_desire_dynamic_linker_symbols (void) -{ - struct objfile *objfile; - struct unwind_table_entry *u; - struct bound_minimal_symbol dld_msymbol; - - /* Do we already know the value of these symbols? If so, then - we've no work to do. - - (If you add clauses to this test, be sure to likewise update the - test within the loop.) */ - - if (dld_cache.is_valid) - return; - - ALL_OBJFILES (objfile) - { - dld_msymbol = lookup_minimal_symbol ("shl_load", NULL, objfile); - if (dld_msymbol.minsym != NULL) - { - dld_cache.load.address = MSYMBOL_VALUE (dld_msymbol.minsym); - dld_cache.load.unwind = find_unwind_entry (dld_cache.load.address); - } - - dld_msymbol = lookup_minimal_symbol_solib_trampoline ("shl_load", - objfile); - if (dld_msymbol.minsym != NULL) - { - if (MSYMBOL_TYPE (dld_msymbol.minsym) == mst_solib_trampoline) - { - u = find_unwind_entry (MSYMBOL_VALUE (dld_msymbol.minsym)); - if ((u != NULL) && (u->stub_unwind.stub_type == EXPORT)) - { - dld_cache.load_stub.address - = MSYMBOL_VALUE (dld_msymbol.minsym); - dld_cache.load_stub.unwind = u; - } - } - } - - dld_msymbol = lookup_minimal_symbol ("shl_unload", NULL, objfile); - if (dld_msymbol.minsym != NULL) - { - dld_cache.unload.address = MSYMBOL_VALUE (dld_msymbol.minsym); - dld_cache.unload.unwind = find_unwind_entry (dld_cache.unload.address); - - /* ??rehrauer: I'm not sure exactly what this is, but it appears - that on some HPUX 10.x versions, there's two unwind regions to - cover the body of "shl_unload", the second being 4 bytes past - the end of the first. This is a large hack to handle that - case, but since I don't seem to have any legitimate way to - look for this thing via the symbol table... */ - - if (dld_cache.unload.unwind != NULL) - { - u = find_unwind_entry (dld_cache.unload.unwind->region_end + 4); - if (u != NULL) - { - dld_cache.unload2.address = u->region_start; - dld_cache.unload2.unwind = u; - } - } - } - - dld_msymbol = lookup_minimal_symbol_solib_trampoline ("shl_unload", - objfile); - if (dld_msymbol.minsym != NULL) - { - if (MSYMBOL_TYPE (dld_msymbol.minsym) == mst_solib_trampoline) - { - u = find_unwind_entry (MSYMBOL_VALUE (dld_msymbol.minsym)); - if ((u != NULL) && (u->stub_unwind.stub_type == EXPORT)) - { - dld_cache.unload_stub.address - = MSYMBOL_VALUE (dld_msymbol.minsym); - dld_cache.unload_stub.unwind = u; - } - } - } - - /* Did we find everything we were looking for? If so, stop. */ - if ((dld_cache.load.address != 0) - && (dld_cache.load_stub.address != 0) - && (dld_cache.unload.address != 0) - && (dld_cache.unload_stub.address != 0)) - { - dld_cache.is_valid = 1; - break; - } - } - - dld_cache.hook.unwind = find_unwind_entry (dld_cache.hook.address); - dld_cache.hook_stub.unwind = find_unwind_entry (dld_cache.hook_stub.address); - - /* We're prepared not to find some of these symbols, which is why - this function is a "desire" operation, and not a "require". */ -} - -static int -som_in_dynsym_resolve_code (CORE_ADDR pc) -{ - struct unwind_table_entry *u_pc; - - /* Are we in the dld itself? - - ??rehrauer: Large hack -- We'll assume that any address in a - shared text region is the dld's text. This would obviously - fall down if the user attached to a process, whose shlibs - weren't mapped to a (writeable) private region. However, in - that case the debugger probably isn't able to set the fundamental - breakpoint in the dld callback anyways, so this hack should be - safe. */ - - if ((pc & (CORE_ADDR) 0xc0000000) == (CORE_ADDR) 0xc0000000) - return 1; - - /* Cache the address of some symbols that are part of the dynamic - linker, if not already known. */ - - som_solib_desire_dynamic_linker_symbols (); - - /* Are we in the dld callback? Or its export stub? */ - u_pc = find_unwind_entry (pc); - if (u_pc == NULL) - return 0; - - if ((u_pc == dld_cache.hook.unwind) || (u_pc == dld_cache.hook_stub.unwind)) - return 1; - - /* Or the interface of the dld (i.e., "shl_load" or friends)? */ - if ((u_pc == dld_cache.load.unwind) - || (u_pc == dld_cache.unload.unwind) - || (u_pc == dld_cache.unload2.unwind) - || (u_pc == dld_cache.load_stub.unwind) - || (u_pc == dld_cache.unload_stub.unwind)) - return 1; - - /* Apparently this address isn't part of the dld's text. */ - return 0; -} - -static void -som_clear_solib (void) -{ -} - -struct dld_list { - char name[4]; - char info[4]; - char text_addr[4]; - char text_link_addr[4]; - char text_end[4]; - char data_start[4]; - char bss_start[4]; - char data_end[4]; - char got_value[4]; - char next[4]; - char tsd_start_addr_ptr[4]; -}; - -static CORE_ADDR -link_map_start (void) -{ - enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); - struct bound_minimal_symbol sym; - CORE_ADDR addr; - gdb_byte buf[4]; - unsigned int dld_flags; - - sym = lookup_minimal_symbol ("__dld_flags", NULL, NULL); - if (!sym.minsym) - error (_("Unable to find __dld_flags symbol in object file.")); - addr = BMSYMBOL_VALUE_ADDRESS (sym); - read_memory (addr, buf, 4); - dld_flags = extract_unsigned_integer (buf, 4, byte_order); - if ((dld_flags & DLD_FLAGS_LISTVALID) == 0) - error (_("__dld_list is not valid according to __dld_flags.")); - - sym = lookup_minimal_symbol ("__dld_list", NULL, NULL); - if (!sym.minsym) - { - /* Older crt0.o files (hpux8) don't have __dld_list as a symbol, - but the data is still available if you know where to look. */ - sym = lookup_minimal_symbol ("__dld_flags", NULL, NULL); - if (!sym.minsym) - { - error (_("Unable to find dynamic library list.")); - return 0; - } - addr = BMSYMBOL_VALUE_ADDRESS (sym) - 8; - } - else - addr = BMSYMBOL_VALUE_ADDRESS (sym); - - read_memory (addr, buf, 4); - addr = extract_unsigned_integer (buf, 4, byte_order); - if (addr == 0) - return 0; - - read_memory (addr, buf, 4); - return extract_unsigned_integer (buf, 4, byte_order); -} - -/* Does this so's name match the main binary? */ -static int -match_main (const char *name) -{ - return strcmp (name, objfile_name (symfile_objfile)) == 0; -} - -static struct so_list * -som_current_sos (void) -{ - enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); - CORE_ADDR lm; - struct so_list *head = 0; - struct so_list **link_ptr = &head; - - for (lm = link_map_start (); lm; ) - { - char *namebuf; - CORE_ADDR addr; - struct so_list *new; - struct cleanup *old_chain; - int errcode; - struct dld_list dbuf; - gdb_byte tsdbuf[4]; - - new = (struct so_list *) xmalloc (sizeof (struct so_list)); - old_chain = make_cleanup (xfree, new); - - memset (new, 0, sizeof (*new)); - new->lm_info = xmalloc (sizeof (struct lm_info)); - make_cleanup (xfree, new->lm_info); - - read_memory (lm, (gdb_byte *)&dbuf, sizeof (struct dld_list)); - - addr = extract_unsigned_integer ((gdb_byte *)&dbuf.name, - sizeof (dbuf.name), byte_order); - target_read_string (addr, &namebuf, SO_NAME_MAX_PATH_SIZE - 1, &errcode); - if (errcode != 0) - warning (_("Can't read pathname for load map: %s."), - safe_strerror (errcode)); - else - { - strncpy (new->so_name, namebuf, SO_NAME_MAX_PATH_SIZE - 1); - new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; - xfree (namebuf); - strcpy (new->so_original_name, new->so_name); - } - - if (new->so_name[0] && !match_main (new->so_name)) - { - struct lm_info *lmi = new->lm_info; - unsigned int tmp; - - lmi->lm_addr = lm; - -#define EXTRACT(_fld) \ - extract_unsigned_integer ((gdb_byte *)&dbuf._fld, \ - sizeof (dbuf._fld), byte_order); - - lmi->text_addr = EXTRACT (text_addr); - tmp = EXTRACT (info); - lmi->library_version = (tmp >> 16) & 0xffff; - lmi->bind_mode = (tmp >> 8) & 0xff; - lmi->struct_version = tmp & 0xff; - lmi->text_link_addr = EXTRACT (text_link_addr); - lmi->text_end = EXTRACT (text_end); - lmi->data_start = EXTRACT (data_start); - lmi->bss_start = EXTRACT (bss_start); - lmi->data_end = EXTRACT (data_end); - lmi->got_value = EXTRACT (got_value); - tmp = EXTRACT (tsd_start_addr_ptr); - read_memory (tmp, tsdbuf, 4); - lmi->tsd_start_addr - = extract_unsigned_integer (tsdbuf, 4, byte_order); - -#ifdef SOLIB_SOM_DBG - printf ("\n+ library \"%s\" is described at %s\n", new->so_name, - paddress (target_gdbarch (), lm)); - printf (" 'version' is %d\n", new->lm_info->struct_version); - printf (" 'bind_mode' is %d\n", new->lm_info->bind_mode); - printf (" 'library_version' is %d\n", - new->lm_info->library_version); - printf (" 'text_addr' is %s\n", - paddress (target_gdbarch (), new->lm_info->text_addr)); - printf (" 'text_link_addr' is %s\n", - paddress (target_gdbarch (), new->lm_info->text_link_addr)); - printf (" 'text_end' is %s\n", - paddress (target_gdbarch (), new->lm_info->text_end)); - printf (" 'data_start' is %s\n", - paddress (target_gdbarch (), new->lm_info->data_start)); - printf (" 'bss_start' is %s\n", - paddress (target_gdbarch (), new->lm_info->bss_start)); - printf (" 'data_end' is %s\n", - paddress (target_gdbarch (), new->lm_info->data_end)); - printf (" 'got_value' is %s\n", - paddress (target_gdbarch (), new->lm_info->got_value)); - printf (" 'tsd_start_addr' is %s\n", - paddress (target_gdbarch (), new->lm_info->tsd_start_addr)); -#endif - - new->addr_low = lmi->text_addr; - new->addr_high = lmi->text_end; - - /* Link the new object onto the list. */ - new->next = NULL; - *link_ptr = new; - link_ptr = &new->next; - } - else - { - free_so (new); - } - - lm = EXTRACT (next); - discard_cleanups (old_chain); -#undef EXTRACT - } - - /* TODO: The original somsolib code has logic to detect and eliminate - duplicate entries. Do we need that? */ - - return head; -} - -static int -som_open_symbol_file_object (void *from_ttyp) -{ - enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); - CORE_ADDR lm, l_name; - char *filename; - int errcode; - int from_tty = *(int *)from_ttyp; - gdb_byte buf[4]; - struct cleanup *cleanup; - - if (symfile_objfile) - if (!query (_("Attempt to reload symbols from process? "))) - return 0; - - /* First link map member should be the executable. */ - if ((lm = link_map_start ()) == 0) - return 0; /* failed somehow... */ - - /* Read address of name from target memory to GDB. */ - read_memory (lm + offsetof (struct dld_list, name), buf, 4); - - /* Convert the address to host format. Assume that the address is - unsigned. */ - l_name = extract_unsigned_integer (buf, 4, byte_order); - - if (l_name == 0) - return 0; /* No filename. */ - - /* Now fetch the filename from target memory. */ - target_read_string (l_name, &filename, SO_NAME_MAX_PATH_SIZE - 1, &errcode); - - if (errcode) - { - warning (_("failed to read exec filename from attached file: %s"), - safe_strerror (errcode)); - return 0; - } - - cleanup = make_cleanup (xfree, filename); - /* Have a pathname: read the symbol file. */ - symbol_file_add_main (filename, from_tty); - - do_cleanups (cleanup); - return 1; -} - -static void -som_free_so (struct so_list *so) -{ - xfree (so->lm_info); -} - -static CORE_ADDR -som_solib_thread_start_addr (struct so_list *so) -{ - return so->lm_info->tsd_start_addr; -} - -/* Return the GOT value for the shared library in which ADDR belongs. If - ADDR isn't in any known shared library, return zero. */ - -static CORE_ADDR -som_solib_get_got_by_pc (CORE_ADDR addr) -{ - struct so_list *so_list = master_so_list (); - CORE_ADDR got_value = 0; - - while (so_list) - { - if (so_list->lm_info->text_addr <= addr - && so_list->lm_info->text_end > addr) - { - got_value = so_list->lm_info->got_value; - break; - } - so_list = so_list->next; - } - return got_value; -} - -/* Return the address of the handle of the shared library in which - ADDR belongs. If ADDR isn't in any known shared library, return - zero. */ -/* This function is used in initialize_hp_cxx_exception_support in - hppa-hpux-tdep.c. */ - -static CORE_ADDR -som_solib_get_solib_by_pc (CORE_ADDR addr) -{ - struct so_list *so_list = master_so_list (); - - while (so_list) - { - if (so_list->lm_info->text_addr <= addr - && so_list->lm_info->text_end > addr) - { - break; - } - so_list = so_list->next; - } - if (so_list) - return so_list->lm_info->lm_addr; - else - return 0; -} - - -static struct target_so_ops som_so_ops; - -extern initialize_file_ftype _initialize_som_solib; /* -Wmissing-prototypes */ - -void -_initialize_som_solib (void) -{ - som_so_ops.relocate_section_addresses = som_relocate_section_addresses; - som_so_ops.free_so = som_free_so; - som_so_ops.clear_solib = som_clear_solib; - som_so_ops.solib_create_inferior_hook = som_solib_create_inferior_hook; - som_so_ops.special_symbol_handling = som_special_symbol_handling; - som_so_ops.current_sos = som_current_sos; - som_so_ops.open_symbol_file_object = som_open_symbol_file_object; - som_so_ops.in_dynsym_resolve_code = som_in_dynsym_resolve_code; - som_so_ops.bfd_open = solib_bfd_open; -} - -void -som_solib_select (struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - set_solib_ops (gdbarch, &som_so_ops); - tdep->solib_thread_start_addr = som_solib_thread_start_addr; - tdep->solib_get_got_by_pc = som_solib_get_got_by_pc; - tdep->solib_get_solib_by_pc = som_solib_get_solib_by_pc; -} - -/* The rest of these functions are not part of the solib interface; they - are used by somread.c or hppa-hpux-tdep.c. */ - -int -som_solib_section_offsets (struct objfile *objfile, - struct section_offsets *offsets) -{ - struct so_list *so_list = master_so_list (); - - while (so_list) - { - /* Oh what a pain! We need the offsets before so_list->objfile - is valid. The BFDs will never match. Make a best guess. */ - if (strstr (objfile_name (objfile), so_list->so_name)) - { - asection *private_section; - struct obj_section *sect; - - /* The text offset is easy. */ - offsets->offsets[SECT_OFF_TEXT (objfile)] - = (so_list->lm_info->text_addr - - so_list->lm_info->text_link_addr); - - /* We should look at presumed_dp in the SOM header, but - that's not easily available. This should be OK though. */ - private_section = bfd_get_section_by_name (objfile->obfd, - "$PRIVATE$"); - if (!private_section) - { - warning (_("Unable to find $PRIVATE$ in shared library!")); - offsets->offsets[SECT_OFF_DATA (objfile)] = 0; - offsets->offsets[SECT_OFF_BSS (objfile)] = 0; - return 1; - } - if (objfile->sect_index_data != -1) - { - offsets->offsets[SECT_OFF_DATA (objfile)] - = (so_list->lm_info->data_start - private_section->vma); - if (objfile->sect_index_bss != -1) - offsets->offsets[SECT_OFF_BSS (objfile)] - = ANOFFSET (offsets, SECT_OFF_DATA (objfile)); - } - - ALL_OBJFILE_OSECTIONS (objfile, sect) - { - flagword flags = bfd_get_section_flags (objfile->obfd, - sect->the_bfd_section); - - if ((flags & SEC_CODE) != 0) - offsets->offsets[sect->the_bfd_section->index] - = offsets->offsets[SECT_OFF_TEXT (objfile)]; - else - offsets->offsets[sect->the_bfd_section->index] - = offsets->offsets[SECT_OFF_DATA (objfile)]; - } - - return 1; - } - so_list = so_list->next; - } - return 0; -} diff --git a/gdb/solib-som.h b/gdb/solib-som.h deleted file mode 100644 index aa10fe0..0000000 --- a/gdb/solib-som.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Handle SOM shared libraries for GDB, the GNU Debugger. - - Copyright (C) 2004-2014 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 3 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, see . */ - -#ifndef SOLIB_SOM_H -#define SOLIB_SOM_H - -struct objfile; -struct section_offsets; -struct gdbarch; - -extern int hpux_major_release; - -void som_solib_select (struct gdbarch *gdbarch); - -int som_solib_section_offsets (struct objfile *objfile, - struct section_offsets *offsets); - -#endif - diff --git a/gdb/somread.c b/gdb/somread.c deleted file mode 100644 index fcd02bd..0000000 --- a/gdb/somread.c +++ /dev/null @@ -1,547 +0,0 @@ -/* Read HP PA/Risc object files for GDB. - Copyright (C) 1991-2014 Free Software Foundation, Inc. - Written by Fred Fish at Cygnus Support. - - 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 3 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, see . */ - -#include "defs.h" -#include "bfd.h" -#include "som/aout.h" -#include "symtab.h" -#include "symfile.h" -#include "objfiles.h" -#include "buildsym.h" -#include "stabsread.h" -#include "gdb-stabs.h" -#include "complaints.h" -#include "demangle.h" -#include "som.h" -#include "libhppa.h" -#include "psymtab.h" - -#include "solib-som.h" - -/* Read the symbol table of a SOM file. - - Given an open bfd, a base address to relocate symbols to, and a - flag that specifies whether or not this bfd is for an executable - or not (may be shared library for example), add all the global - function and data symbols to the minimal symbol table. */ - -static void -som_symtab_read (bfd *abfd, struct objfile *objfile, - struct section_offsets *section_offsets) -{ - struct cleanup *cleanup; - struct gdbarch *gdbarch = get_objfile_arch (objfile); - unsigned int number_of_symbols; - int val, dynamic; - char *stringtab; - asection *shlib_info; - struct som_external_symbol_dictionary_record *buf, *bufp, *endbufp; - char *symname; - const int symsize = sizeof (struct som_external_symbol_dictionary_record); - - - number_of_symbols = bfd_get_symcount (abfd); - - /* Allocate a buffer to read in the debug info. - We avoid using alloca because the memory size could be so large - that we could hit the stack size limit. */ - buf = xmalloc (symsize * number_of_symbols); - cleanup = make_cleanup (xfree, buf); - bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET); - val = bfd_bread (buf, symsize * number_of_symbols, abfd); - if (val != symsize * number_of_symbols) - error (_("Couldn't read symbol dictionary!")); - - /* Allocate a buffer to read in the som stringtab section of - the debugging info. Again, we avoid using alloca because - the data could be so large that we could potentially hit - the stack size limitat. */ - stringtab = xmalloc (obj_som_stringtab_size (abfd)); - make_cleanup (xfree, stringtab); - bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET); - val = bfd_bread (stringtab, obj_som_stringtab_size (abfd), abfd); - if (val != obj_som_stringtab_size (abfd)) - error (_("Can't read in HP string table.")); - - /* We need to determine if objfile is a dynamic executable (so we - can do the right thing for ST_ENTRY vs ST_CODE symbols). - - There's nothing in the header which easily allows us to do - this. - - This code used to rely upon the existence of a $SHLIB_INFO$ - section to make this determination. HP claims that it is - more accurate to check for a nonzero text offset, but they - have not provided any information about why that test is - more accurate. */ - dynamic = (ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile)) != 0); - - endbufp = buf + number_of_symbols; - for (bufp = buf; bufp < endbufp; ++bufp) - { - enum minimal_symbol_type ms_type; - unsigned int flags = bfd_getb32 (bufp->flags); - unsigned int symbol_type - = (flags >> SOM_SYMBOL_TYPE_SH) & SOM_SYMBOL_TYPE_MASK; - unsigned int symbol_scope - = (flags >> SOM_SYMBOL_SCOPE_SH) & SOM_SYMBOL_SCOPE_MASK; - CORE_ADDR symbol_value = bfd_getb32 (bufp->symbol_value); - asection *section = NULL; - - QUIT; - - /* Compute the section. */ - switch (symbol_scope) - { - case SS_EXTERNAL: - if (symbol_type != ST_STORAGE) - section = bfd_und_section_ptr; - else - section = bfd_com_section_ptr; - break; - - case SS_UNSAT: - if (symbol_type != ST_STORAGE) - section = bfd_und_section_ptr; - else - section = bfd_com_section_ptr; - break; - - case SS_UNIVERSAL: - section = bfd_section_from_som_symbol (abfd, bufp); - break; - - case SS_LOCAL: - section = bfd_section_from_som_symbol (abfd, bufp); - break; - } - - switch (symbol_scope) - { - case SS_UNIVERSAL: - case SS_EXTERNAL: - switch (symbol_type) - { - case ST_SYM_EXT: - case ST_ARG_EXT: - continue; - - case ST_CODE: - case ST_PRI_PROG: - case ST_SEC_PROG: - case ST_MILLICODE: - symname = bfd_getb32 (bufp->name) + stringtab; - ms_type = mst_text; - symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); - break; - - case ST_ENTRY: - symname = bfd_getb32 (bufp->name) + stringtab; - /* For a dynamic executable, ST_ENTRY symbols are - the stubs, while the ST_CODE symbol is the real - function. */ - if (dynamic) - ms_type = mst_solib_trampoline; - else - ms_type = mst_text; - symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); - break; - - case ST_STUB: - symname = bfd_getb32 (bufp->name) + stringtab; - ms_type = mst_solib_trampoline; - symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); - break; - - case ST_DATA: - symname = bfd_getb32 (bufp->name) + stringtab; - ms_type = mst_data; - break; - default: - continue; - } - break; - -#if 0 - /* SS_GLOBAL and SS_LOCAL are two names for the same thing (!). */ - case SS_GLOBAL: -#endif - case SS_LOCAL: - switch (symbol_type) - { - case ST_SYM_EXT: - case ST_ARG_EXT: - continue; - - case ST_CODE: - symname = bfd_getb32 (bufp->name) + stringtab; - ms_type = mst_file_text; - symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); - - check_strange_names: - /* Utah GCC 2.5, FSF GCC 2.6 and later generate correct local - label prefixes for stabs, constant data, etc. So we need - only filter out L$ symbols which are left in due to - limitations in how GAS generates SOM relocations. - - When linking in the HPUX C-library the HP linker has - the nasty habit of placing section symbols from the literal - subspaces in the middle of the program's text. Filter - those out as best we can. Check for first and last character - being '$'. - - And finally, the newer HP compilers emit crud like $PIC_foo$N - in some circumstance (PIC code I guess). It's also claimed - that they emit D$ symbols too. What stupidity. */ - if ((symname[0] == 'L' && symname[1] == '$') - || (symname[0] == '$' && symname[strlen (symname) - 1] == '$') - || (symname[0] == 'D' && symname[1] == '$') - || (strncmp (symname, "L0\001", 3) == 0) - || (strncmp (symname, "$PIC", 4) == 0)) - continue; - break; - - case ST_PRI_PROG: - case ST_SEC_PROG: - case ST_MILLICODE: - symname = bfd_getb32 (bufp->name) + stringtab; - ms_type = mst_file_text; - symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); - break; - - case ST_ENTRY: - symname = bfd_getb32 (bufp->name) + stringtab; - /* SS_LOCAL symbols in a shared library do not have - export stubs, so we do not have to worry about - using mst_file_text vs mst_solib_trampoline here like - we do for SS_UNIVERSAL and SS_EXTERNAL symbols above. */ - ms_type = mst_file_text; - symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); - break; - - case ST_STUB: - symname = bfd_getb32 (bufp->name) + stringtab; - ms_type = mst_solib_trampoline; - symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); - break; - - - case ST_DATA: - symname = bfd_getb32 (bufp->name) + stringtab; - ms_type = mst_file_data; - goto check_strange_names; - - default: - continue; - } - break; - - /* This can happen for common symbols when -E is passed to the - final link. No idea _why_ that would make the linker force - common symbols to have an SS_UNSAT scope, but it does. - - This also happens for weak symbols, but their type is - ST_DATA. */ - case SS_UNSAT: - switch (symbol_type) - { - case ST_STORAGE: - case ST_DATA: - symname = bfd_getb32 (bufp->name) + stringtab; - ms_type = mst_data; - break; - - default: - continue; - } - break; - - default: - continue; - } - - if (bfd_getb32 (bufp->name) > obj_som_stringtab_size (abfd)) - error (_("Invalid symbol data; bad HP string table offset: %s"), - plongest (bfd_getb32 (bufp->name))); - - if (bfd_is_const_section (section)) - { - struct obj_section *iter; - - ALL_OBJFILE_OSECTIONS (objfile, iter) - { - CORE_ADDR start; - CORE_ADDR len; - - if (bfd_is_const_section (iter->the_bfd_section)) - continue; - - start = bfd_get_section_vma (iter->objfile->obfd, - iter->the_bfd_section); - len = bfd_get_section_size (iter->the_bfd_section); - if (start <= symbol_value && symbol_value < start + len) - { - section = iter->the_bfd_section; - break; - } - } - } - - prim_record_minimal_symbol_and_info (symname, symbol_value, ms_type, - gdb_bfd_section_index (objfile->obfd, - section), - objfile); - } - - do_cleanups (cleanup); -} - -/* Scan and build partial symbols for a symbol file. - We have been initialized by a call to som_symfile_init, which - currently does nothing. - - SECTION_OFFSETS is a set of offsets to apply to relocate the symbols - in each section. This is ignored, as it isn't needed for SOM. - - This function only does the minimum work necessary for letting the - user "name" things symbolically; it does not read the entire symtab. - Instead, it reads the external and static symbols and puts them in partial - symbol tables. When more extensive information is requested of a - file, the corresponding partial symbol table is mutated into a full - fledged symbol table by going back and reading the symbols - for real. - - We look for sections with specific names, to tell us what debug - format to look for. - - somstab_build_psymtabs() handles STABS symbols. - - Note that SOM files have a "minimal" symbol table, which is vaguely - reminiscent of a COFF symbol table, but has only the minimal information - necessary for linking. We process this also, and use the information to - build gdb's minimal symbol table. This gives us some minimal debugging - capability even for files compiled without -g. */ - -static void -som_symfile_read (struct objfile *objfile, int symfile_flags) -{ - bfd *abfd = objfile->obfd; - struct cleanup *back_to; - - init_minimal_symbol_collection (); - back_to = make_cleanup_discard_minimal_symbols (); - - /* Process the normal SOM symbol table first. - This reads in the DNTT and string table, but doesn't - actually scan the DNTT. It does scan the linker symbol - table and thus build up a "minimal symbol table". */ - - som_symtab_read (abfd, objfile, objfile->section_offsets); - - /* Install any minimal symbols that have been collected as the current - minimal symbols for this objfile. - Further symbol-reading is done incrementally, file-by-file, - in a step known as "psymtab-to-symtab" expansion. hp-symtab-read.c - contains the code to do the actual DNTT scanning and symtab building. */ - install_minimal_symbols (objfile); - do_cleanups (back_to); - - /* Now read information from the stabs debug sections. - This is emitted by gcc. */ - stabsect_build_psymtabs (objfile, - "$GDB_SYMBOLS$", "$GDB_STRINGS$", "$TEXT$"); -} - -/* Initialize anything that needs initializing when a completely new symbol - file is specified (not just adding some symbols from another file, e.g. a - shared library). - - We reinitialize buildsym, since we may be reading stabs from a SOM file. */ - -static void -som_new_init (struct objfile *ignore) -{ - stabsread_new_init (); - buildsym_new_init (); -} - -/* Perform any local cleanups required when we are done with a particular - objfile. I.e, we are in the process of discarding all symbol information - for an objfile, freeing up all memory held for it, and unlinking the - objfile struct from the global list of known objfiles. */ - -static void -som_symfile_finish (struct objfile *objfile) -{ -} - -/* SOM specific initialization routine for reading symbols. */ - -static void -som_symfile_init (struct objfile *objfile) -{ - /* SOM objects may be reordered, so set OBJF_REORDERED. If we - find this causes a significant slowdown in gdb then we could - set it in the debug symbol readers only when necessary. */ - objfile->flags |= OBJF_REORDERED; -} - -/* An object of this type is passed to find_section_offset. */ - -struct find_section_offset_arg -{ - /* The objfile. */ - - struct objfile *objfile; - - /* Flags to invert. */ - - flagword invert; - - /* Flags to look for. */ - - flagword flags; - - /* A text section with non-zero size, if any. */ - - asection *best_section; - - /* An empty text section, if any. */ - - asection *empty_section; -}; - -/* A callback for bfd_map_over_sections that tries to find a section - with particular flags in an objfile. */ - -static void -find_section_offset (bfd *abfd, asection *sect, void *arg) -{ - struct find_section_offset_arg *info = arg; - flagword aflag; - - aflag = bfd_get_section_flags (abfd, sect); - - aflag ^= info->invert; - - if ((aflag & info->flags) == info->flags) - { - if (bfd_section_size (abfd, sect) > 0) - { - if (info->best_section == NULL) - info->best_section = sect; - } - else - { - if (info->empty_section == NULL) - info->empty_section = sect; - } - } -} - -/* Set a section index from a BFD. */ - -static void -set_section_index (struct objfile *objfile, flagword invert, flagword flags, - int *index_ptr) -{ - struct find_section_offset_arg info; - - info.objfile = objfile; - info.best_section = NULL; - info.empty_section = NULL; - info.invert = invert; - info.flags = flags; - bfd_map_over_sections (objfile->obfd, find_section_offset, &info); - - if (info.best_section) - *index_ptr = info.best_section->index; - else if (info.empty_section) - *index_ptr = info.empty_section->index; -} - -/* SOM specific parsing routine for section offsets. - - Plain and simple for now. */ - -static void -som_symfile_offsets (struct objfile *objfile, - const struct section_addr_info *addrs) -{ - int i; - CORE_ADDR text_addr; - asection *sect; - - objfile->num_sections = bfd_count_sections (objfile->obfd); - objfile->section_offsets = (struct section_offsets *) - obstack_alloc (&objfile->objfile_obstack, - SIZEOF_N_SECTION_OFFSETS (objfile->num_sections)); - - set_section_index (objfile, 0, SEC_ALLOC | SEC_CODE, - &objfile->sect_index_text); - set_section_index (objfile, 0, SEC_ALLOC | SEC_DATA, - &objfile->sect_index_data); - set_section_index (objfile, SEC_LOAD, SEC_ALLOC | SEC_LOAD, - &objfile->sect_index_bss); - set_section_index (objfile, 0, SEC_ALLOC | SEC_READONLY, - &objfile->sect_index_rodata); - - /* First see if we're a shared library. If so, get the section - offsets from the library, else get them from addrs. */ - if (!som_solib_section_offsets (objfile, objfile->section_offsets)) - { - /* Note: Here is OK to compare with ".text" because this is the - name that gdb itself gives to that section, not the SOM - name. */ - for (i = 0; i < addrs->num_sections; i++) - if (strcmp (addrs->other[i].name, ".text") == 0) - break; - text_addr = addrs->other[i].addr; - - for (i = 0; i < objfile->num_sections; i++) - (objfile->section_offsets)->offsets[i] = text_addr; - } -} - - - -/* Register that we are able to handle SOM object file formats. */ - -static const struct sym_fns som_sym_fns = -{ - som_new_init, /* init anything gbl to entire symtab */ - som_symfile_init, /* read initial info, setup for sym_read() */ - som_symfile_read, /* read a symbol file into symtab */ - NULL, /* sym_read_psymbols */ - som_symfile_finish, /* finished with file, cleanup */ - som_symfile_offsets, /* Translate ext. to int. relocation */ - default_symfile_segments, /* Get segment information from a file. */ - NULL, - default_symfile_relocate, /* Relocate a debug section. */ - NULL, /* sym_get_probes */ - &psym_functions -}; - -initialize_file_ftype _initialize_somread; - -void -_initialize_somread (void) -{ - add_symtab_fns (bfd_target_som_flavour, &som_sym_fns); -}