This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] preliminary support for hppa-linux


Hi, this is part 1 of my attempt to get gdb support for hppa-linux
upstream. There have been several failed attempts in the past... let's
see if we can fix it for real this time :)

Attached is a "minimal" patch to get gdb building on hppa-linux and have
some basic functionality. There are still many bugs which we will try to
fix in subsequent patches. The bulk of this patch moves some
hpux-specific code from hppa-tdep.c into hppa-hpux-tdep.c. This allows
hppa-linux to share most of the code in hppa-tdep.c.

This patch contains a bit of code that has been floating around in
Debian for a number of years. As far as I know, it was mostly 
contributed by Alan Modra and David Huggin-Daines as part of LinuxCare's
contract with HP for the initial hppa-linux work. In any case, there
have been many changes to gdb since then and the patch has been changed
many times by various people. As far as I know all the contributors have
copyright assignment with the FSF.

Tested on hppa2.0w-hp-hpux11.11 (with gcc) and hppa-unknown-linux-gnu. 
Comments appreciated.

randolph
-- 
Randolph Chung
Debian GNU/Linux Developer, hppa/ia64 ports
http://www.tausq.org/


2004-04-03  Randolph Chung  <tausq@debian.org>

	* hppa-tdep.c: (args_for_find_stub): Move to hppa-hpux-tdep.c
	(hp_som_som_object_present): Likewise.
	(exception_catchpoints_are_fragile): Likewise.
	(find_stub_with_shl_get): Likewise.
	(cover_find_stub_with_shl_get): Likewise.
	(initialize_hp_cxx_exception_support): Likewise.
	(child_enable_exception_callback): Likewise.
	(current_ex_event): Likewise.
	(null_symtab_and_line): Likewise.
	(child_get_current_exception_event): Likewise.
	(HP_ACC_EH_notify_hook): Likewise.
	(HP_ACC_EH_set_hook_value): Likewise.
	(HP_ACC_EH_notify_callback): Likewise.
	(HP_ACC_EH_break): Likewise.
	(HP_ACC_EH_catch_throw): Likewise.
	(HP_ACC_EH_catch_catch): Likewise.
	(__eh_notification): Likewise.
	(hp_cxx_exception_support): Likewise.
	(hp_cxx_exception_support_initialized): Likewise.
	(eh_notify_hook_addr): Likewise.
	(eh_notify_callback_addr): Likewise.
	(eh_break_addr): Likewise.
	(eh_catch_catch_addr): Likewise.
	(eh_catch_throw_addr): Likewise.
	(break_callback_sal): Likewise.
	(setup_d_pid_in_inferior): Likewise.
	* hppa-hpux-tdep.c: Moved hpux-specific definitions above here.

	* configure.host: Add hppa*-*-linux* target.
	* configure.tgt: Likewise.
	* config/pa/linux.mh: New file.
	* config/pa/linux.mt: New file.
	* config/pa/nm-linux.h: New file.
	* config/pa/tm-linux.h: New file.
	* config/pa/xm-linux.h: New file.
	* hppa-linux-nat.c: New file.
	* hppa-linux-tdep.c: New file.
	* hppa-linux-tdep.h: New file.

diff -uNrp gdb-cvs/gdb/config/pa/linux.mh gdb-work/gdb/config/pa/linux.mh
--- gdb-cvs/gdb/config/pa/linux.mh	1969-12-31 16:00:00.000000000 -0800
+++ gdb-work/gdb/config/pa/linux.mh	2004-04-03 16:26:14.763847816 -0800
@@ -0,0 +1,11 @@
+# Host: Hewlett-Packard PA-RISC machine, running Linux
+XDEPFILES=
+XM_FILE= xm-linux.h
+NAT_FILE= nm-linux.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o gcore.o \
+	core-aout.o core-regset.o hppa-linux-nat.o linux-proc.o \
+	proc-service.o thread-db.o lin-lwp.o linux-nat.o
+
+#GDBSERVER_DEPFILES= low-hppalinux.o
+
+XM_CLIBS= -ldl
diff -uNrp gdb-cvs/gdb/config/pa/linux.mt gdb-work/gdb/config/pa/linux.mt
--- gdb-cvs/gdb/config/pa/linux.mt	1969-12-31 16:00:00.000000000 -0800
+++ gdb-work/gdb/config/pa/linux.mt	2004-04-03 20:02:48.106559480 -0800
@@ -0,0 +1,3 @@
+# Target: HP PA-RISC running Linux
+TDEPFILES= hppa-tdep.o hppa-linux-tdep.o glibc-tdep.o solib.o solib-svr4.o
+TM_FILE= tm-linux.h
diff -uNrp gdb-cvs/gdb/config/pa/nm-linux.h gdb-work/gdb/config/pa/nm-linux.h
--- gdb-cvs/gdb/config/pa/nm-linux.h	1969-12-31 16:00:00.000000000 -0800
+++ gdb-work/gdb/config/pa/nm-linux.h	2004-04-03 16:26:54.240846400 -0800
@@ -0,0 +1,67 @@
+/* Native support for GNU/Linux, for GDB, the GNU debugger.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef PA_NM_LINUX_H
+#define PA_NM_LINUX_H
+
+#include "nm-linux.h"
+
+#define CANNOT_FETCH_REGISTER(regno) pa_cannot_fetch_register(regno)
+extern int pa_cannot_fetch_register (int regno);
+
+#define CANNOT_STORE_REGISTER(regno) pa_cannot_store_register(regno)
+extern int pa_cannot_store_register (int regno);
+
+#ifdef GDBSERVER
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+	(addr) = pa_register_u_addr ((blockend),(regno));
+
+extern int pa_register_u_addr(int, int);
+#endif /* GDBSERVER */
+
+#define U_REGS_OFFSET 0
+
+#define PTRACE_ARG3_TYPE long
+#define PTRACE_XFER_TYPE long
+
+/* Hardware watchpoints */
+
+#define TARGET_HAS_HARDWARE_WATCHPOINTS
+
+#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \
+  (type == bp_hardware_watchpoint) 
+
+#define HAVE_STEPPABLE_WATCHPOINT 1
+
+#define STOPPED_BY_WATCHPOINT(W) \
+  pa_linux_stopped_by_watchpoint (PIDGET(inferior_ptid))
+extern CORE_ADDR pa_linux_stopped_by_watchpoint (int);
+
+#define target_insert_watchpoint(addr, len, type) \
+  pa_linux_insert_watchpoint (PIDGET(inferior_ptid), addr, len, type)
+extern int pa_linux_insert_watchpoint (int pid, CORE_ADDR addr,
+                                         int len, int rw);
+
+#define target_remove_watchpoint(addr, len, type) \
+  pa_linux_remove_watchpoint (PIDGET(inferior_ptid), addr, len)
+extern int pa_linux_remove_watchpoint (int pid, CORE_ADDR addr, int len);
+
+#endif
+
diff -uNrp gdb-cvs/gdb/config/pa/tm-linux.h gdb-work/gdb/config/pa/tm-linux.h
--- gdb-cvs/gdb/config/pa/tm-linux.h	1969-12-31 16:00:00.000000000 -0800
+++ gdb-work/gdb/config/pa/tm-linux.h	2004-04-03 16:27:17.813262848 -0800
@@ -0,0 +1,9 @@
+#ifndef TM_LINUX_H
+#define TM_LINUX_H
+
+/* Include common stuff */
+#include "pa/tm-hppa.h"
+
+#define GDB_TARGET_IS_PA_ELF
+
+#endif
diff -uNrp gdb-cvs/gdb/config/pa/xm-linux.h gdb-work/gdb/config/pa/xm-linux.h
--- gdb-cvs/gdb/config/pa/xm-linux.h	1969-12-31 16:00:00.000000000 -0800
+++ gdb-work/gdb/config/pa/xm-linux.h	2004-04-03 16:27:34.680698608 -0800
@@ -0,0 +1,37 @@
+/* Native support for GNU/Linux, for GDB, the GNU debugger.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef PA_XM_LINUX_H
+#define PA_XM_LINUX_H
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+#define HAVE_TERMIOS
+
+/* This is the amount to subtract from u.u_ar0
+   to get the offset in the core file of the register values.  */
+#define KERNEL_U_ADDR 0x0
+
+#define NEED_POSIX_SETPGID
+
+/* Need R_OK etc, but USG isn't defined.  */
+#include <unistd.h>
+
+#endif
diff -uNrp gdb-cvs/gdb/configure.host gdb-work/gdb/configure.host
--- gdb-cvs/gdb/configure.host	2004-02-25 12:45:30.000000000 -0800
+++ gdb-work/gdb/configure.host	2004-04-03 16:29:22.028379280 -0800
@@ -48,6 +48,7 @@ hppa*-*-hpux10.20)	gdb_host=hpux1020 ;;
 hppa*64*-*-hpux11*)	gdb_host=hpux11w ;;
 hppa*-*-hpux11*)	gdb_host=hpux11 ;;
 hppa*-*-hpux*)		gdb_host=hppahpux ;;
+hppa*-*-linux*)		gdb_host=linux ;;
 
 i[34567]86-ncr-*)	gdb_host=ncr3000 ;;
 i[34567]86-*-dgux*)	gdb_host=i386v4 ;;
diff -uNrp gdb-cvs/gdb/configure.tgt gdb-work/gdb/configure.tgt
--- gdb-cvs/gdb/configure.tgt	2004-02-25 12:45:30.000000000 -0800
+++ gdb-work/gdb/configure.tgt	2004-04-03 16:29:43.663090304 -0800
@@ -74,6 +74,7 @@ frv-*-*)		gdb_target=frv ;;
 hppa*64*-*-hpux11*)	gdb_target=hppa64 ;;
 hppa*-*-hpux*)		gdb_target=hppahpux ;;
 hppa*-*-hiux*)		gdb_target=hppahpux ;;
+hppa*-*-linux*)		gdb_target=linux ;;
 hppa*-*-*)		gdb_target=hppa ;;
 
 i[34567]86-ncr-*)	gdb_target=ncr3000 ;;
diff -uNrp gdb-cvs/gdb/hppa-hpux-tdep.c gdb-work/gdb/hppa-hpux-tdep.c
--- gdb-cvs/gdb/hppa-hpux-tdep.c	2004-03-23 06:47:56.000000000 -0800
+++ gdb-work/gdb/hppa-hpux-tdep.c	2004-04-03 20:33:15.798708040 -0800
@@ -24,11 +24,32 @@ Foundation, Inc., 59 Temple Place - Suit
 #include "osabi.h"
 #include "gdb_string.h"
 #include "frame.h"
+#include "symtab.h"
+#include "objfiles.h"
+#include "inferior.h"
+#include "infcall.h"
+
+#include <dl.h>
+#include <machine/save_state.h>
 
 /* Forward declarations.  */
 extern void _initialize_hppa_hpux_tdep (void);
 extern initialize_file_ftype _initialize_hppa_hpux_tdep;
 
+typedef struct
+  {
+    struct minimal_symbol *msym;
+    CORE_ADDR solib_handle;
+    CORE_ADDR return_val;
+  }
+args_for_find_stub;
+
+/* This is declared in symtab.c; set to 1 in hp-symtab-read.c */
+extern int hp_som_som_object_present;
+
+/* In breakpoint.c */
+extern int exception_catchpoints_are_fragile;
+
 /* FIXME: brobecker 2002-12-25.  The following functions will eventually
    become static, after the multiarching conversion is done.  */
 int hppa_hpux_pc_in_sigtramp (CORE_ADDR pc, char *name);
@@ -148,6 +169,556 @@ hppa64_hpux_frame_find_saved_regs_in_sig
     }
 }
 
+/* Exception handling support for the HP-UX ANSI C++ compiler.
+   The compiler (aCC) provides a callback for exception events;
+   GDB can set a breakpoint on this callback and find out what
+   exception event has occurred. */
+
+/* The name of the hook to be set to point to the callback function */
+static char HP_ACC_EH_notify_hook[] = "__eh_notify_hook";
+/* The name of the function to be used to set the hook value */
+static char HP_ACC_EH_set_hook_value[] = "__eh_set_hook_value";
+/* The name of the callback function in end.o */
+static char HP_ACC_EH_notify_callback[] = "__d_eh_notify_callback";
+/* Name of function in end.o on which a break is set (called by above) */
+static char HP_ACC_EH_break[] = "__d_eh_break";
+/* Name of flag (in end.o) that enables catching throws */
+static char HP_ACC_EH_catch_throw[] = "__d_eh_catch_throw";
+/* Name of flag (in end.o) that enables catching catching */
+static char HP_ACC_EH_catch_catch[] = "__d_eh_catch_catch";
+/* The enum used by aCC */
+typedef enum
+  {
+    __EH_NOTIFY_THROW,
+    __EH_NOTIFY_CATCH
+  }
+__eh_notification;
+
+/* Is exception-handling support available with this executable? */
+static int hp_cxx_exception_support = 0;
+/* Has the initialize function been run? */
+int hp_cxx_exception_support_initialized = 0;
+/* Similar to above, but imported from breakpoint.c -- non-target-specific */
+extern int exception_support_initialized;
+/* Address of __eh_notify_hook */
+static CORE_ADDR eh_notify_hook_addr = 0;
+/* Address of __d_eh_notify_callback */
+static CORE_ADDR eh_notify_callback_addr = 0;
+/* Address of __d_eh_break */
+static CORE_ADDR eh_break_addr = 0;
+/* Address of __d_eh_catch_catch */
+static CORE_ADDR eh_catch_catch_addr = 0;
+/* Address of __d_eh_catch_throw */
+static CORE_ADDR eh_catch_throw_addr = 0;
+/* Sal for __d_eh_break */
+static struct symtab_and_line *break_callback_sal = 0;
+
+/* Code in end.c expects __d_pid to be set in the inferior,
+   otherwise __d_eh_notify_callback doesn't bother to call
+   __d_eh_break!  So we poke the pid into this symbol
+   ourselves.
+   0 => success
+   1 => failure  */
+int
+setup_d_pid_in_inferior (void)
+{
+  CORE_ADDR anaddr;
+  struct minimal_symbol *msymbol;
+  char buf[4];			/* FIXME 32x64? */
+
+  /* Slam the pid of the process into __d_pid; failing is only a warning!  */
+  msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile);
+  if (msymbol == NULL)
+    {
+      warning ("Unable to find __d_pid symbol in object file.");
+      warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
+      return 1;
+    }
+
+  anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
+  store_unsigned_integer (buf, 4, PIDGET (inferior_ptid)); /* FIXME 32x64? */
+  if (target_write_memory (anaddr, buf, 4))	/* FIXME 32x64? */
+    {
+      warning ("Unable to write __d_pid");
+      warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
+      return 1;
+    }
+  return 0;
+}
+
+/* elz: Used to lookup a symbol in the shared libraries.
+   This function calls shl_findsym, indirectly through a
+   call to __d_shl_get. __d_shl_get is in end.c, which is always
+   linked in by the hp compilers/linkers. 
+   The call to shl_findsym cannot be made directly because it needs
+   to be active in target address space. 
+   inputs: - minimal symbol pointer for the function we want to look up
+   - address in target space of the descriptor for the library
+   where we want to look the symbol up.
+   This address is retrieved using the 
+   som_solib_get_solib_by_pc function (somsolib.c). 
+   output: - real address in the library of the function.          
+   note: the handle can be null, in which case shl_findsym will look for
+   the symbol in all the loaded shared libraries.
+   files to look at if you need reference on this stuff:
+   dld.c, dld_shl_findsym.c
+   end.c
+   man entry for shl_findsym */
+
+CORE_ADDR
+find_stub_with_shl_get (struct minimal_symbol *function, CORE_ADDR handle)
+{
+  struct symbol *get_sym, *symbol2;
+  struct minimal_symbol *buff_minsym, *msymbol;
+  struct type *ftype;
+  struct value **args;
+  struct value *funcval;
+  struct value *val;
+
+  int x, namelen, err_value, tmp = -1;
+  CORE_ADDR endo_buff_addr, value_return_addr, errno_return_addr;
+  CORE_ADDR stub_addr;
+
+
+  args = alloca (sizeof (struct value *) * 8);		/* 6 for the arguments and one null one??? */
+  funcval = find_function_in_inferior ("__d_shl_get");
+  get_sym = lookup_symbol ("__d_shl_get", NULL, VAR_DOMAIN, NULL, NULL);
+  buff_minsym = lookup_minimal_symbol ("__buffer", NULL, NULL);
+  msymbol = lookup_minimal_symbol ("__shldp", NULL, NULL);
+  symbol2 = lookup_symbol ("__shldp", NULL, VAR_DOMAIN, NULL, NULL);
+  endo_buff_addr = SYMBOL_VALUE_ADDRESS (buff_minsym);
+  namelen = strlen (DEPRECATED_SYMBOL_NAME (function));
+  value_return_addr = endo_buff_addr + namelen;
+  ftype = check_typedef (SYMBOL_TYPE (get_sym));
+
+  /* do alignment */
+  if ((x = value_return_addr % 64) != 0)
+    value_return_addr = value_return_addr + 64 - x;
+
+  errno_return_addr = value_return_addr + 64;
+
+
+  /* set up stuff needed by __d_shl_get in buffer in end.o */
+
+  target_write_memory (endo_buff_addr, DEPRECATED_SYMBOL_NAME (function), namelen);
+
+  target_write_memory (value_return_addr, (char *) &tmp, 4);
+
+  target_write_memory (errno_return_addr, (char *) &tmp, 4);
+
+  target_write_memory (SYMBOL_VALUE_ADDRESS (msymbol),
+		       (char *) &handle, 4);
+
+  /* now prepare the arguments for the call */
+
+  args[0] = value_from_longest (TYPE_FIELD_TYPE (ftype, 0), 12);
+  args[1] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 1), SYMBOL_VALUE_ADDRESS (msymbol));
+  args[2] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 2), endo_buff_addr);
+  args[3] = value_from_longest (TYPE_FIELD_TYPE (ftype, 3), TYPE_PROCEDURE);
+  args[4] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 4), value_return_addr);
+  args[5] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 5), errno_return_addr);
+
+  /* now call the function */
+
+  val = call_function_by_hand (funcval, 6, args);
+
+  /* now get the results */
+
+  target_read_memory (errno_return_addr, (char *) &err_value, sizeof (err_value));
+
+  target_read_memory (value_return_addr, (char *) &stub_addr, sizeof (stub_addr));
+  if (stub_addr <= 0)
+    error ("call to __d_shl_get failed, error code is %d", err_value);
+
+  return (stub_addr);
+}
+
+/* Cover routine for find_stub_with_shl_get to pass to catch_errors */
+static int
+cover_find_stub_with_shl_get (void *args_untyped)
+{
+  args_for_find_stub *args = args_untyped;
+  args->return_val = find_stub_with_shl_get (args->msym, args->solib_handle);
+  return 0;
+}
+
+/* Initialize exception catchpoint support by looking for the
+   necessary hooks/callbacks in end.o, etc., and set the hook value to
+   point to the required debug function
+
+   Return 0 => failure
+   1 => success          */
+
+static int
+initialize_hp_cxx_exception_support (void)
+{
+  struct symtabs_and_lines sals;
+  struct cleanup *old_chain;
+  struct cleanup *canonical_strings_chain = NULL;
+  int i;
+  char *addr_start;
+  char *addr_end = NULL;
+  char **canonical = (char **) NULL;
+  int thread = -1;
+  struct symbol *sym = NULL;
+  struct minimal_symbol *msym = NULL;
+  struct objfile *objfile;
+  asection *shlib_info;
+
+  /* Detect and disallow recursion.  On HP-UX with aCC, infinite
+     recursion is a possibility because finding the hook for exception
+     callbacks involves making a call in the inferior, which means
+     re-inserting breakpoints which can re-invoke this code */
+
+  static int recurse = 0;
+  if (recurse > 0)
+    {
+      hp_cxx_exception_support_initialized = 0;
+      exception_support_initialized = 0;
+      return 0;
+    }
+
+  hp_cxx_exception_support = 0;
+
+  /* First check if we have seen any HP compiled objects; if not,
+     it is very unlikely that HP's idiosyncratic callback mechanism
+     for exception handling debug support will be available!
+     This will percolate back up to breakpoint.c, where our callers
+     will decide to try the g++ exception-handling support instead. */
+  if (!hp_som_som_object_present)
+    return 0;
+
+  /* We have a SOM executable with SOM debug info; find the hooks */
+
+  /* First look for the notify hook provided by aCC runtime libs */
+  /* If we find this symbol, we conclude that the executable must
+     have HP aCC exception support built in.  If this symbol is not
+     found, even though we're a HP SOM-SOM file, we may have been
+     built with some other compiler (not aCC).  This results percolates
+     back up to our callers in breakpoint.c which can decide to
+     try the g++ style of exception support instead.
+     If this symbol is found but the other symbols we require are
+     not found, there is something weird going on, and g++ support
+     should *not* be tried as an alternative.
+
+     ASSUMPTION: Only HP aCC code will have __eh_notify_hook defined.  
+     ASSUMPTION: HP aCC and g++ modules cannot be linked together. */
+
+  /* libCsup has this hook; it'll usually be non-debuggable */
+  msym = lookup_minimal_symbol (HP_ACC_EH_notify_hook, NULL, NULL);
+  if (msym)
+    {
+      eh_notify_hook_addr = SYMBOL_VALUE_ADDRESS (msym);
+      hp_cxx_exception_support = 1;
+    }
+  else
+    {
+      warning ("Unable to find exception callback hook (%s).", HP_ACC_EH_notify_hook);
+      warning ("Executable may not have been compiled debuggable with HP aCC.");
+      warning ("GDB will be unable to intercept exception events.");
+      eh_notify_hook_addr = 0;
+      hp_cxx_exception_support = 0;
+      return 0;
+    }
+
+  /* Next look for the notify callback routine in end.o */
+  /* This is always available in the SOM symbol dictionary if end.o is linked in */
+  msym = lookup_minimal_symbol (HP_ACC_EH_notify_callback, NULL, NULL);
+  if (msym)
+    {
+      eh_notify_callback_addr = SYMBOL_VALUE_ADDRESS (msym);
+      hp_cxx_exception_support = 1;
+    }
+  else
+    {
+      warning ("Unable to find exception callback routine (%s).", HP_ACC_EH_notify_callback);
+      warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
+      warning ("GDB will be unable to intercept exception events.");
+      eh_notify_callback_addr = 0;
+      return 0;
+    }
+
+#ifndef GDB_TARGET_IS_HPPA_20W
+  /* Check whether the executable is dynamically linked or archive bound */
+  /* With an archive-bound executable we can use the raw addresses we find
+     for the callback function, etc. without modification. For an executable
+     with shared libraries, we have to do more work to find the plabel, which
+     can be the target of a call through $$dyncall from the aCC runtime support
+     library (libCsup) which is linked shared by default by aCC. */
+  /* This test below was copied from somsolib.c/somread.c.  It may not be a very
+     reliable one to test that an executable is linked shared. pai/1997-07-18 */
+  shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
+  if (shlib_info && (bfd_section_size (symfile_objfile->obfd, shlib_info) != 0))
+    {
+      /* The minsym we have has the local code address, but that's not the
+         plabel that can be used by an inter-load-module call. */
+      /* Find solib handle for main image (which has end.o), and use that
+         and the min sym as arguments to __d_shl_get() (which does the equivalent
+         of shl_findsym()) to find the plabel. */
+
+      args_for_find_stub args;
+      static char message[] = "Error while finding exception callback hook:\n";
+
+      args.solib_handle = som_solib_get_solib_by_pc (eh_notify_callback_addr);
+      args.msym = msym;
+      args.return_val = 0;
+
+      recurse++;
+      catch_errors (cover_find_stub_with_shl_get, &args, message,
+		    RETURN_MASK_ALL);
+      eh_notify_callback_addr = args.return_val;
+      recurse--;
+
+      exception_catchpoints_are_fragile = 1;
+
+      if (!eh_notify_callback_addr)
+	{
+	  /* We can get here either if there is no plabel in the export list
+	     for the main image, or if something strange happened (?) */
+	  warning ("Couldn't find a plabel (indirect function label) for the exception callback.");
+	  warning ("GDB will not be able to intercept exception events.");
+	  return 0;
+	}
+    }
+  else
+    exception_catchpoints_are_fragile = 0;
+#endif
+
+  /* Now, look for the breakpointable routine in end.o */
+  /* This should also be available in the SOM symbol dict. if end.o linked in */
+  msym = lookup_minimal_symbol (HP_ACC_EH_break, NULL, NULL);
+  if (msym)
+    {
+      eh_break_addr = SYMBOL_VALUE_ADDRESS (msym);
+      hp_cxx_exception_support = 1;
+    }
+  else
+    {
+      warning ("Unable to find exception callback routine to set breakpoint (%s).", HP_ACC_EH_break);
+      warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
+      warning ("GDB will be unable to intercept exception events.");
+      eh_break_addr = 0;
+      return 0;
+    }
+
+  /* Next look for the catch enable flag provided in end.o */
+  sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL,
+		       VAR_DOMAIN, 0, (struct symtab **) NULL);
+  if (sym)			/* sometimes present in debug info */
+    {
+      eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (sym);
+      hp_cxx_exception_support = 1;
+    }
+  else
+    /* otherwise look in SOM symbol dict. */
+    {
+      msym = lookup_minimal_symbol (HP_ACC_EH_catch_catch, NULL, NULL);
+      if (msym)
+	{
+	  eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (msym);
+	  hp_cxx_exception_support = 1;
+	}
+      else
+	{
+	  warning ("Unable to enable interception of exception catches.");
+	  warning ("Executable may not have been compiled debuggable with HP aCC.");
+	  warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
+	  return 0;
+	}
+    }
+
+  /* Next look for the catch enable flag provided end.o */
+  sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL,
+		       VAR_DOMAIN, 0, (struct symtab **) NULL);
+  if (sym)			/* sometimes present in debug info */
+    {
+      eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (sym);
+      hp_cxx_exception_support = 1;
+    }
+  else
+    /* otherwise look in SOM symbol dict. */
+    {
+      msym = lookup_minimal_symbol (HP_ACC_EH_catch_throw, NULL, NULL);
+      if (msym)
+	{
+	  eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (msym);
+	  hp_cxx_exception_support = 1;
+	}
+      else
+	{
+	  warning ("Unable to enable interception of exception throws.");
+	  warning ("Executable may not have been compiled debuggable with HP aCC.");
+	  warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
+	  return 0;
+	}
+    }
+
+  /* Set the flags */
+  hp_cxx_exception_support = 2;	/* everything worked so far */
+  hp_cxx_exception_support_initialized = 1;
+  exception_support_initialized = 1;
+
+  return 1;
+}
+
+/* Target operation for enabling or disabling interception of
+   exception events.
+   KIND is either EX_EVENT_THROW or EX_EVENT_CATCH
+   ENABLE is either 0 (disable) or 1 (enable).
+   Return value is NULL if no support found;
+   -1 if something went wrong,
+   or a pointer to a symtab/line struct if the breakpointable
+   address was found. */
+
+struct symtab_and_line *
+child_enable_exception_callback (enum exception_event_kind kind, int enable)
+{
+  char buf[4];
+
+  if (!exception_support_initialized || !hp_cxx_exception_support_initialized)
+    if (!initialize_hp_cxx_exception_support ())
+      return NULL;
+
+  switch (hp_cxx_exception_support)
+    {
+    case 0:
+      /* Assuming no HP support at all */
+      return NULL;
+    case 1:
+      /* HP support should be present, but something went wrong */
+      return (struct symtab_and_line *) -1;	/* yuck! */
+      /* there may be other cases in the future */
+    }
+
+  /* Set the EH hook to point to the callback routine */
+  store_unsigned_integer (buf, 4, enable ? eh_notify_callback_addr : 0);	/* FIXME 32x64 problem */
+  /* pai: (temp) FIXME should there be a pack operation first? */
+  if (target_write_memory (eh_notify_hook_addr, buf, 4))	/* FIXME 32x64 problem */
+    {
+      warning ("Could not write to target memory for exception event callback.");
+      warning ("Interception of exception events may not work.");
+      return (struct symtab_and_line *) -1;
+    }
+  if (enable)
+    {
+      /* Ensure that __d_pid is set up correctly -- end.c code checks this. :-( */
+      if (PIDGET (inferior_ptid) > 0)
+	{
+	  if (setup_d_pid_in_inferior ())
+	    return (struct symtab_and_line *) -1;
+	}
+      else
+	{
+	  warning ("Internal error: Invalid inferior pid?  Cannot intercept exception events.");
+	  return (struct symtab_and_line *) -1;
+	}
+    }
+
+  switch (kind)
+    {
+    case EX_EVENT_THROW:
+      store_unsigned_integer (buf, 4, enable ? 1 : 0);
+      if (target_write_memory (eh_catch_throw_addr, buf, 4))	/* FIXME 32x64? */
+	{
+	  warning ("Couldn't enable exception throw interception.");
+	  return (struct symtab_and_line *) -1;
+	}
+      break;
+    case EX_EVENT_CATCH:
+      store_unsigned_integer (buf, 4, enable ? 1 : 0);
+      if (target_write_memory (eh_catch_catch_addr, buf, 4))	/* FIXME 32x64? */
+	{
+	  warning ("Couldn't enable exception catch interception.");
+	  return (struct symtab_and_line *) -1;
+	}
+      break;
+    default:
+      error ("Request to enable unknown or unsupported exception event.");
+    }
+
+  /* Copy break address into new sal struct, malloc'ing if needed. */
+  if (!break_callback_sal)
+    {
+      break_callback_sal = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line));
+    }
+  init_sal (break_callback_sal);
+  break_callback_sal->symtab = NULL;
+  break_callback_sal->pc = eh_break_addr;
+  break_callback_sal->line = 0;
+  break_callback_sal->end = eh_break_addr;
+
+  return break_callback_sal;
+}
+
+/* Record some information about the current exception event */
+static struct exception_event_record current_ex_event;
+/* Convenience struct */
+static struct symtab_and_line null_symtab_and_line =
+{NULL, 0, 0, 0};
+
+/* Report current exception event.  Returns a pointer to a record
+   that describes the kind of the event, where it was thrown from,
+   and where it will be caught.  More information may be reported
+   in the future */
+struct exception_event_record *
+child_get_current_exception_event (void)
+{
+  CORE_ADDR event_kind;
+  CORE_ADDR throw_addr;
+  CORE_ADDR catch_addr;
+  struct frame_info *fi, *curr_frame;
+  int level = 1;
+
+  curr_frame = get_current_frame ();
+  if (!curr_frame)
+    return (struct exception_event_record *) NULL;
+
+  /* Go up one frame to __d_eh_notify_callback, because at the
+     point when this code is executed, there's garbage in the
+     arguments of __d_eh_break. */
+  fi = find_relative_frame (curr_frame, &level);
+  if (level != 0)
+    return (struct exception_event_record *) NULL;
+
+  select_frame (fi);
+
+  /* Read in the arguments */
+  /* __d_eh_notify_callback() is called with 3 arguments:
+     1. event kind catch or throw
+     2. the target address if known
+     3. a flag -- not sure what this is. pai/1997-07-17 */
+  event_kind = read_register (ARG0_REGNUM);
+  catch_addr = read_register (ARG1_REGNUM);
+
+  /* Now go down to a user frame */
+  /* For a throw, __d_eh_break is called by
+     __d_eh_notify_callback which is called by
+     __notify_throw which is called
+     from user code.
+     For a catch, __d_eh_break is called by
+     __d_eh_notify_callback which is called by
+     <stackwalking stuff> which is called by
+     __throw__<stuff> or __rethrow_<stuff> which is called
+     from user code. */
+  /* FIXME: Don't use such magic numbers; search for the frames */
+  level = (event_kind == EX_EVENT_THROW) ? 3 : 4;
+  fi = find_relative_frame (curr_frame, &level);
+  if (level != 0)
+    return (struct exception_event_record *) NULL;
+
+  select_frame (fi);
+  throw_addr = get_frame_pc (fi);
+
+  /* Go back to original (top) frame */
+  select_frame (curr_frame);
+
+  current_ex_event.kind = (enum exception_event_kind) event_kind;
+  current_ex_event.throw_sal = find_pc_line (throw_addr, 1);
+  current_ex_event.catch_sal = find_pc_line (catch_addr, 1);
+
+  return &current_ex_event;
+}
+
 static void
 hppa_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
diff -uNrp gdb-cvs/gdb/hppa-linux-nat.c gdb-work/gdb/hppa-linux-nat.c
--- gdb-cvs/gdb/hppa-linux-nat.c	1969-12-31 16:00:00.000000000 -0800
+++ gdb-work/gdb/hppa-linux-nat.c	2004-04-03 19:55:42.596246880 -0800
@@ -0,0 +1,355 @@
+/* Functions specific to running gdb native on HPPA running Linux.
+   Copyright 2000, 2001 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "inferior.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "regcache.h"
+
+#include <signal.h>
+#include <sys/ptrace.h>
+#include <sys/wait.h>
+#ifdef HAVE_SYS_REG_H
+#include <sys/reg.h>
+#endif
+#include <sys/user.h>
+
+#include <string.h>
+
+#include <asm/offsets.h>
+#include <sys/procfs.h>
+
+/* Prototypes for supply_gregset etc. */
+#include "gregset.h"
+#include "hppa-linux-tdep.h"
+
+/* These must match the order of the register names.
+
+   Some sort of lookup table is needed because the offsets associated
+   with the registers are all over the board.  */
+
+static const int u_offsets[] =
+  {
+    /* general registers */
+    -1,
+    PT_GR1,
+    PT_GR2,
+    PT_GR3,
+    PT_GR4,
+    PT_GR5,
+    PT_GR6,
+    PT_GR7,
+    PT_GR8,
+    PT_GR9,
+    PT_GR10,
+    PT_GR11,
+    PT_GR12,
+    PT_GR13,
+    PT_GR14,
+    PT_GR15,
+    PT_GR16,
+    PT_GR17,
+    PT_GR18,
+    PT_GR19,
+    PT_GR20,
+    PT_GR21,
+    PT_GR22,
+    PT_GR23,
+    PT_GR24,
+    PT_GR25,
+    PT_GR26,
+    PT_GR27,
+    PT_GR28,
+    PT_GR29,
+    PT_GR30,
+    PT_GR31,
+
+    PT_SAR,
+    PT_IAOQ0,
+    PT_IASQ0,
+    PT_IAOQ1,
+    PT_IASQ1,
+    -1, /* eiem */
+    PT_IIR,
+    PT_ISR,
+    PT_IOR,
+    PT_PSW,
+    -1, /* goto */
+
+    PT_SR4,
+    PT_SR0,
+    PT_SR1,
+    PT_SR2,
+    PT_SR3,
+    PT_SR5,
+    PT_SR6,
+    PT_SR7,
+
+    -1, /* cr0 */
+    -1, /* pid0 */
+    -1, /* pid1 */
+    -1, /* ccr */
+    -1, /* pid2 */
+    -1, /* pid3 */
+    -1, /* cr24 */
+    -1, /* cr25 */
+    -1, /* cr26 */
+    PT_CR27,
+    -1, /* cr28 */
+    -1, /* cr29 */
+    -1, /* cr30 */
+
+    /* Floating point regs.  */
+    PT_FR0,  PT_FR0 + 4,
+    PT_FR1,  PT_FR1 + 4,
+    PT_FR2,  PT_FR2 + 4,
+    PT_FR3,  PT_FR3 + 4,
+    PT_FR4,  PT_FR4 + 4,
+    PT_FR5,  PT_FR5 + 4,
+    PT_FR6,  PT_FR6 + 4,
+    PT_FR7,  PT_FR7 + 4,
+    PT_FR8,  PT_FR8 + 4,
+    PT_FR9,  PT_FR9 + 4,
+    PT_FR10, PT_FR10 + 4,
+    PT_FR11, PT_FR11 + 4,
+    PT_FR12, PT_FR12 + 4,
+    PT_FR13, PT_FR13 + 4,
+    PT_FR14, PT_FR14 + 4,
+    PT_FR15, PT_FR15 + 4,
+    PT_FR16, PT_FR16 + 4,
+    PT_FR17, PT_FR17 + 4,
+    PT_FR18, PT_FR18 + 4,
+    PT_FR19, PT_FR19 + 4,
+    PT_FR20, PT_FR20 + 4,
+    PT_FR21, PT_FR21 + 4,
+    PT_FR22, PT_FR22 + 4,
+    PT_FR23, PT_FR23 + 4,
+    PT_FR24, PT_FR24 + 4,
+    PT_FR25, PT_FR25 + 4,
+    PT_FR26, PT_FR26 + 4,
+    PT_FR27, PT_FR27 + 4,
+    PT_FR28, PT_FR28 + 4,
+    PT_FR29, PT_FR29 + 4,
+    PT_FR30, PT_FR30 + 4,
+    PT_FR31, PT_FR31 + 4,
+  };
+
+CORE_ADDR
+register_addr (int regno, CORE_ADDR blockend)
+{
+  CORE_ADDR addr;
+
+  if ((unsigned) regno >= NUM_REGS)
+    error ("Invalid register number %d.", regno);
+
+  if (u_offsets[regno] == -1)
+    addr = 0;
+  else
+    {
+      addr = (CORE_ADDR) u_offsets[regno];
+      /* If this is a 64 bit kernel, but we are debugging a 32 bit
+	 task, then we want to pick up the low word of the register.  */
+      if (PT_GR2 - PT_GR1 == 8 && regno < PA_FR0_REGNUM)
+	addr += (PT_GR2 - PT_GR1) - DEPRECATED_REGISTER_RAW_SIZE (regno);
+    }
+
+  return addr;
+}
+
+int pa_cannot_fetch_register (regno)
+     int regno;
+{
+  return (unsigned int) regno >= NUM_REGS || u_offsets[regno] == -1;
+}
+
+int pa_cannot_store_register (regno)
+     int regno;
+{
+  return ((unsigned int) regno >= NUM_REGS
+	  || regno == PA_GR0_REGNUM
+	  || regno == PA_PCSQ_HEAD_REGNUM
+	  || (regno >= PA_PCSQ_TAIL_REGNUM && regno < PA_IPSW_REGNUM)
+	  || (regno > PA_IPSW_REGNUM && regno < PA_FR4_REGNUM));
+}
+
+static const int greg_map[] =
+  {
+    PA_GR0_REGNUM,
+    PA_GR1_REGNUM,
+    PA_GR2_REGNUM,
+    PA_GR3_REGNUM,
+    PA_GR4_REGNUM,
+    PA_GR5_REGNUM,
+    PA_GR6_REGNUM,
+    PA_GR7_REGNUM,
+    PA_GR8_REGNUM,
+    PA_GR9_REGNUM,
+    PA_GR10_REGNUM,
+    PA_GR11_REGNUM,
+    PA_GR12_REGNUM,
+    PA_GR13_REGNUM,
+    PA_GR14_REGNUM,
+    PA_GR15_REGNUM,
+    PA_GR16_REGNUM,
+    PA_GR17_REGNUM,
+    PA_GR18_REGNUM,
+    PA_GR19_REGNUM,
+    PA_GR20_REGNUM,
+    PA_GR21_REGNUM,
+    PA_GR22_REGNUM,
+    PA_GR23_REGNUM,
+    PA_GR24_REGNUM,
+    PA_GR25_REGNUM,
+    PA_GR26_REGNUM,
+    PA_GR27_REGNUM,
+    PA_GR28_REGNUM,
+    PA_GR29_REGNUM,
+    PA_GR30_REGNUM,
+    PA_GR31_REGNUM,
+    PA_SR0_REGNUM,
+    PA_SR1_REGNUM,
+    PA_SR2_REGNUM,
+    PA_SR3_REGNUM,
+    PA_SR4_REGNUM,
+    PA_SR5_REGNUM,
+    PA_SR6_REGNUM,
+    PA_SR7_REGNUM,
+    PA_PCOQ_HEAD_REGNUM,
+    PA_PCOQ_TAIL_REGNUM,
+    PA_PCSQ_HEAD_REGNUM,
+    PA_PCSQ_TAIL_REGNUM,
+    PA_CR11_REGNUM,
+    PA_CR19_REGNUM,
+    PA_CR20_REGNUM,
+    PA_CR21_REGNUM,
+    PA_CR22_REGNUM,
+    PA_CR0_REGNUM,
+    PA_CR24_REGNUM,
+    PA_CR25_REGNUM,
+    PA_CR26_REGNUM,
+    PA_CR27_REGNUM,
+    PA_CR28_REGNUM,
+    PA_CR29_REGNUM,
+    PA_CR30_REGNUM,
+    PA_CR31_REGNUM,
+    PA_CR8_REGNUM,
+    PA_CR9_REGNUM,
+    PA_CR12_REGNUM,
+    PA_CR13_REGNUM,
+    PA_CR10_REGNUM,
+    PA_CR15_REGNUM
+  };
+
+void
+supply_gregset (gdb_gregset_t *gregsetp)
+{
+  int i;
+  greg_t *regp = (greg_t *) gregsetp;
+
+  for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++, regp++)
+    {
+      int regno = greg_map[i];
+      /* When running a 64 bit kernel, a greg_t may be larger than the
+	 actual register, so just pick off the LS bits of big-endian word.  */
+      supply_register (regno,
+		       ((char *) (regp + 1)) - register_size (current_gdbarch, regno));
+    }
+}
+
+void
+fill_gregset (gdb_gregset_t *gregsetp, int regno)
+{
+  int i;
+  greg_t *regp = (greg_t *) gregsetp;
+
+  memset (gregsetp, 0, sizeof (*gregsetp));
+  for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++, regp++)
+    {
+      int regi = greg_map[i];
+
+      if (regno == -1 || regi == regno)
+	{
+	  int rawsize = register_size (current_gdbarch, regi);
+	  regcache_collect (regi, ((char *) (regp + 1)) - rawsize);
+	}
+    }
+}
+
+/*  Given a pointer to a floating point register set in /proc format
+   (fpregset_t *), unpack the register contents and supply them as gdb's
+   idea of the current floating point register values. */
+
+void
+supply_fpregset (gdb_fpregset_t *fpregsetp)
+{
+  register int regi;
+  char *from;
+
+  for (regi = 0; regi <= 31; regi++)
+    {
+      from = (char *) &((*fpregsetp)[regi]);
+      supply_register (2*regi + PA_FR0_REGNUM, from);
+      supply_register (2*regi + PA_FR0_REGNUM + 1, from + 4);
+    }
+}
+
+/*  Given a pointer to a floating point register set in /proc format
+   (fpregset_t *), update the register specified by REGNO from gdb's idea
+   of the current floating point register set.  If REGNO is -1, update
+   them all. */
+
+void
+fill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
+{
+  if (regno == -1)
+    deprecated_read_register_bytes (DEPRECATED_REGISTER_BYTE (PA_FR0_REGNUM),
+				    (char *)fpregsetp,
+				    32 * 2 * DEPRECATED_REGISTER_RAW_SIZE (PA_FR0_REGNUM));
+  else
+    {
+      /* Gross.  fpregset_t is double, registers[x] has single
+	 precision reg.  */
+      char *to = (char *) &((*fpregsetp)[(regno - PA_FR0_REGNUM) / 2]);
+      if ((regno - PA_FR0_REGNUM) & 1)
+	to += 4;
+      regcache_collect (regno, to);
+    }
+}
+
+int
+pa_linux_insert_watchpoint (int pid, CORE_ADDR addr, int len, int rw)
+{
+  return -1;
+}
+
+int
+pa_linux_remove_watchpoint (int pid, CORE_ADDR addr, int len)
+{
+  return -1;
+}
+
+CORE_ADDR
+pa_linux_stopped_by_watchpoint (int pid)
+{
+  return 0;
+}
+
+
diff -uNrp gdb-cvs/gdb/hppa-linux-tdep.c gdb-work/gdb/hppa-linux-tdep.c
--- gdb-cvs/gdb/hppa-linux-tdep.c	1969-12-31 16:00:00.000000000 -0800
+++ gdb-work/gdb/hppa-linux-tdep.c	2004-04-03 20:02:21.056671688 -0800
@@ -0,0 +1,58 @@
+/* Target-dependent code for Linux running on PA-RISC, for GDB.
+
+   Copyright 2004 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "arch-utils.h"
+#include "gdbcore.h"
+#include "osabi.h"
+#include "gdb_string.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+#include "objfiles.h"
+#include "elf/common.h"
+#include "solib-svr4.h"
+#include "glibc-tdep.h"
+
+#include "hppa-linux-tdep.h"
+
+/* Forward declarations.  */
+extern initialize_file_ftype _initialize_hppa_linux_tdep;
+
+static void
+hppa_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* GNU/Linux uses SVR4-style shared libraries.  */
+  set_solib_svr4_fetch_link_map_offsets
+    (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+
+  /* GNU/Linux uses the dynamic linker included in the GNU C Library.  */
+  set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
+}
+
+void
+_initialize_hppa_linux_tdep (void)
+{
+  gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_LINUX, hppa_linux_init_abi);
+}
+
+
diff -uNrp gdb-cvs/gdb/hppa-linux-tdep.c.new gdb-work/gdb/hppa-linux-tdep.c.new
--- gdb-cvs/gdb/hppa-linux-tdep.c.new	1969-12-31 16:00:00.000000000 -0800
+++ gdb-work/gdb/hppa-linux-tdep.c.new	2004-04-03 19:52:14.407896320 -0800
@@ -0,0 +1,107 @@
+/* Target-dependent code for Linux running on PA-RISC, for GDB.
+
+   Copyright 2004 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "arch-utils.h"
+#include "gdbcore.h"
+#include "osabi.h"
+#include "gdb_string.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+#include "objfiles.h"
+#include "elf/common.h"
+
+#include "hppa-linux-tdep.h"
+
+/* Forward declarations.  */
+extern initialize_file_ftype _initialize_hppa_linux_tdep;
+
+static struct gdbarch *
+hppa_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+#if 0
+  set_gdbarch_read_pc (gdbarch, hppa_target_read_pc);
+  set_gdbarch_write_pc (gdbarch, hppa_target_write_pc);
+  set_gdbarch_unwind_sp (gdbarch, hppa_unwind_sp);
+
+  set_gdbarch_num_regs (gdbarch, 128);
+  set_gdbarch_sp_regnum (gdbarch, PA_GR30_REGNUM);
+  set_gdbarch_fp0_regnum (gdbarch, PA_FR0_REGNUM);
+  set_gdbarch_register_name (gdbarch, hppa32_register_name);
+  set_gdbarch_register_type (gdbarch, hppa32_register_type);
+
+  set_gdbarch_cannot_store_register (gdbarch, hppa_cannot_store_register);
+  set_gdbarch_addr_bits_remove (gdbarch, hppa_smash_text_address);
+  set_gdbarch_smash_text_address (gdbarch, hppa_smash_text_address);
+  set_gdbarch_believe_pcc_promotion (gdbarch, 1);
+
+  /* Helper for function argument information.  */
+  set_gdbarch_fetch_pointer_argument (gdbarch, hppa_fetch_pointer_argument);
+
+  set_gdbarch_ptr_bit (gdbarch, 4 * TARGET_CHAR_BIT);
+  set_gdbarch_addr_bit (gdbarch, 4 * TARGET_CHAR_BIT);
+  set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
+  set_gdbarch_int_bit (gdbarch, 4 * TARGET_CHAR_BIT);
+  set_gdbarch_long_bit (gdbarch, 4 * TARGET_CHAR_BIT);
+  set_gdbarch_long_long_bit (gdbarch, 8 * TARGET_CHAR_BIT);
+  set_gdbarch_float_bit (gdbarch, 4 * TARGET_CHAR_BIT);
+  set_gdbarch_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
+  set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
+
+  set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_big);
+  set_gdbarch_double_format (gdbarch, &floatformat_ieee_double_big);
+  /* gcc doesn't support this yet */
+  set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big);
+
+  set_gdbarch_return_value (gdbarch, hppa32_return_value);
+  set_gdbarch_push_dummy_call (gdbarch, hppa32_push_dummy_call);
+
+  set_gdbarch_skip_prologue (gdbarch, hppa_skip_prologue);
+  set_gdbarch_skip_trampoline_code (gdbarch, hppa_skip_trampoline_code);
+  set_gdbarch_in_solib_call_trampoline (gdbarch, hppa_in_solib_call_trampoline);
+  set_gdbarch_in_solib_return_trampoline (gdbarch,
+                                          hppa_in_solib_return_trampoline);
+
+  /* stack grows upward */
+  set_gdbarch_inner_than (gdbarch, core_addr_greaterthan);
+  set_gdbarch_breakpoint_from_pc (gdbarch, hppa_breakpoint_from_pc);
+
+  set_gdbarch_frame_align (gdbarch, hppa32_frame_align);
+
+  frame_unwind_append_sniffer (gdbarch, hppa_frame_unwind_sniffer);
+  frame_base_append_sniffer (gdbarch, hppa_frame_base_sniffer);
+  frame_base_set_default (gdbarch, &hppa_frame_base);
+
+  set_gdbarch_unwind_dummy_id (gdbarch, hppa_unwind_dummy_id);
+  set_gdbarch_unwind_pc (gdbarch, hppa_unwind_pc);
+
+  return gdbarch;
+#endif
+}
+
+void
+_initialize_hppa_linux_tdep (void)
+{
+  denter();
+  gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_LINUX, hppa_linux_init_abi);
+}
+
+
diff -uNrp gdb-cvs/gdb/hppa-linux-tdep.h gdb-work/gdb/hppa-linux-tdep.h
--- gdb-cvs/gdb/hppa-linux-tdep.h	1969-12-31 16:00:00.000000000 -0800
+++ gdb-work/gdb/hppa-linux-tdep.h	2004-04-03 19:51:40.513049120 -0800
@@ -0,0 +1,140 @@
+/* Definitions to target GDB to any Hewlett-Packard PA-RISC machine.
+   Copyright 2004 Free Software Foundation, Inc. 
+
+   Contributed by Randolph Chung <tausq@debian.org>
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef HPPA_LINUX_TDEP_H
+#define HPPA_LINUX_TDEP_H
+
+#include "hppa-tdep.h"
+
+/* Register numbers of various registers,  */
+
+/* General registers.  */
+#define PA_GR0_REGNUM		0
+#define PA_GR1_REGNUM		(PA_GR0_REGNUM+1)
+#define PA_GR2_REGNUM		(PA_GR0_REGNUM+2)
+#define PA_GR3_REGNUM		(PA_GR0_REGNUM+3)
+#define PA_GR4_REGNUM		(PA_GR0_REGNUM+4)
+#define PA_GR5_REGNUM		(PA_GR0_REGNUM+5)
+#define PA_GR6_REGNUM		(PA_GR0_REGNUM+6)
+#define PA_GR7_REGNUM		(PA_GR0_REGNUM+7)
+#define PA_GR8_REGNUM		(PA_GR0_REGNUM+8)
+#define PA_GR9_REGNUM		(PA_GR0_REGNUM+9)
+#define PA_GR10_REGNUM		(PA_GR0_REGNUM+10)
+#define PA_GR11_REGNUM		(PA_GR0_REGNUM+11)
+#define PA_GR12_REGNUM		(PA_GR0_REGNUM+12)
+#define PA_GR13_REGNUM		(PA_GR0_REGNUM+13)
+#define PA_GR14_REGNUM		(PA_GR0_REGNUM+14)
+#define PA_GR15_REGNUM		(PA_GR0_REGNUM+15)
+#define PA_GR16_REGNUM		(PA_GR0_REGNUM+16)
+#define PA_GR17_REGNUM		(PA_GR0_REGNUM+17)
+#define PA_GR18_REGNUM		(PA_GR0_REGNUM+18)
+#define PA_GR19_REGNUM		(PA_GR0_REGNUM+19)
+#define PA_GR20_REGNUM		(PA_GR0_REGNUM+20)
+#define PA_GR21_REGNUM		(PA_GR0_REGNUM+21)
+#define PA_GR22_REGNUM		(PA_GR0_REGNUM+22)
+#define PA_GR23_REGNUM		(PA_GR0_REGNUM+23)
+#define PA_GR24_REGNUM		(PA_GR0_REGNUM+24)
+#define PA_GR25_REGNUM		(PA_GR0_REGNUM+25)
+#define PA_GR26_REGNUM		(PA_GR0_REGNUM+26)
+#define PA_GR27_REGNUM		(PA_GR0_REGNUM+27)
+#define PA_GR28_REGNUM		(PA_GR0_REGNUM+28)
+#define PA_GR29_REGNUM		(PA_GR0_REGNUM+29)
+#define PA_GR30_REGNUM		(PA_GR0_REGNUM+30)
+#define PA_GR31_REGNUM		(PA_GR0_REGNUM+31)
+
+/* Control registers.  The peculiar layout is to match HPUX interrupt save
+   state.  */
+#define PA_CR11_REGNUM		32
+#define PA_PCOQ_HEAD_REGNUM	33	/* CR18 */
+#define PA_PCSQ_HEAD_REGNUM	34	/* CR17 */
+#define PA_PCOQ_TAIL_REGNUM	35	/* CR18 */
+#define PA_PCSQ_TAIL_REGNUM	36	/* CR17 */
+#define PA_CR15_REGNUM		37
+#define PA_CR19_REGNUM		38
+#define PA_CR20_REGNUM		39
+#define PA_CR21_REGNUM		40
+#define PA_CR22_REGNUM		41
+#define PA_CR31_REGNUM		42
+
+/* Space registers.  */
+#define PA_SR4_REGNUM		43
+#define PA_SR0_REGNUM		44
+#define PA_SR1_REGNUM		45
+#define PA_SR2_REGNUM		46
+#define PA_SR3_REGNUM		47
+#define PA_SR5_REGNUM		48
+#define PA_SR6_REGNUM		49
+#define PA_SR7_REGNUM		50
+
+/* More control regs.  */
+#define PA_CR0_REGNUM		51
+#define PA_CR8_REGNUM		52
+#define PA_CR9_REGNUM		53
+#define PA_CR10_REGNUM		54
+#define PA_CR12_REGNUM		55
+#define PA_CR13_REGNUM		56
+#define PA_CR24_REGNUM		57
+#define PA_CR25_REGNUM		58
+#define PA_CR26_REGNUM		59
+#define PA_CR27_REGNUM		60
+#define PA_CR28_REGNUM		61
+#define PA_CR29_REGNUM		62
+#define PA_CR30_REGNUM		63
+
+/* Floating point registers.  */
+#define PA_FR0_REGNUM		64
+#define PA_FR1_REGNUM		(PA_FR0_REGNUM+2)
+#define PA_FR2_REGNUM		(PA_FR0_REGNUM+4)
+#define PA_FR3_REGNUM		(PA_FR0_REGNUM+6)
+#define PA_FR4_REGNUM		(PA_FR0_REGNUM+8)
+#define PA_FR5_REGNUM		(PA_FR0_REGNUM+10)
+#define PA_FR6_REGNUM		(PA_FR0_REGNUM+12)
+#define PA_FR7_REGNUM		(PA_FR0_REGNUM+14)
+#define PA_FR31_REGNUM		(PA_FR0_REGNUM+62)
+
+/* Some aliases.  */
+#define PA_FLAGS_REGNUM		PA_GR0_REGNUM
+#define PA_SAR_REGNUM		PA_CR11_REGNUM
+#define PA_IPSW_REGNUM		PA_CR22_REGNUM
+
+/*
+ * Processor Status Word Masks
+ */
+
+#define PSW_T   0x01000000	/* Taken Branch Trap Enable */
+#define PSW_H   0x00800000	/* Higher-Privilege Transfer Trap Enable */
+#define PSW_L   0x00400000	/* Lower-Privilege Transfer Trap Enable */
+#define PSW_N   0x00200000	/* PC Queue Front Instruction Nullified */
+#define PSW_X   0x00100000	/* Data Memory Break Disable */
+#define PSW_B   0x00080000	/* Taken Branch in Previous Cycle */
+#define PSW_C   0x00040000	/* Code Address Translation Enable */
+#define PSW_V   0x00020000	/* Divide Step Correction */
+#define PSW_M   0x00010000	/* High-Priority Machine Check Disable */
+#define PSW_CB  0x0000ff00	/* Carry/Borrow Bits */
+#define PSW_R   0x00000010	/* Recovery Counter Enable */
+#define PSW_Q   0x00000008	/* Interruption State Collection Enable */
+#define PSW_P   0x00000004	/* Protection ID Validation Enable */
+#define PSW_D   0x00000002	/* Data Address Translation Enable */
+#define PSW_I   0x00000001	/* External, Power Failure, Low-Priority */
+				/* Machine Check Interruption Enable */
+#endif
+
diff -uNrp gdb-cvs/gdb/hppa-tdep.c gdb-work/gdb/hppa-tdep.c
--- gdb-cvs/gdb/hppa-tdep.c	2004-04-03 09:49:06.000000000 -0800
+++ gdb-work/gdb/hppa-tdep.c	2004-04-03 20:33:08.276851536 -0800
@@ -48,12 +48,10 @@
 #include <sys/types.h>
 #endif
 
-#include <dl.h>
 #include <sys/param.h>
 #include <signal.h>
 
 #include <sys/ptrace.h>
-#include <machine/save_state.h>
 
 #ifdef COFF_ENCAPSULATE
 #include "a.out.encap.h"
@@ -152,24 +154,8 @@ CORE_ADDR hppa_smash_text_address (CORE_
 CORE_ADDR hppa_target_read_pc (ptid_t ptid);
 void hppa_target_write_pc (CORE_ADDR v, ptid_t ptid);
 
-typedef struct
-  {
-    struct minimal_symbol *msym;
-    CORE_ADDR solib_handle;
-    CORE_ADDR return_val;
-  }
-args_for_find_stub;
-
-static int cover_find_stub_with_shl_get (void *);
-
 static int is_pa_2 = 0;		/* False */
 
-/* This is declared in symtab.c; set to 1 in hp-symtab-read.c */
-extern int hp_som_som_object_present;
-
-/* In breakpoint.c */
-extern int exception_catchpoints_are_fragile;
-
 /* Handle 32/64-bit struct return conventions.  */
 
 static enum return_value_convention
@@ -1058,102 +1044,6 @@ hppa64_frame_align (struct gdbarch *gdba
 }
 
 
-/* elz: Used to lookup a symbol in the shared libraries.
-   This function calls shl_findsym, indirectly through a
-   call to __d_shl_get. __d_shl_get is in end.c, which is always
-   linked in by the hp compilers/linkers. 
-   The call to shl_findsym cannot be made directly because it needs
-   to be active in target address space. 
-   inputs: - minimal symbol pointer for the function we want to look up
-   - address in target space of the descriptor for the library
-   where we want to look the symbol up.
-   This address is retrieved using the 
-   som_solib_get_solib_by_pc function (somsolib.c). 
-   output: - real address in the library of the function.          
-   note: the handle can be null, in which case shl_findsym will look for
-   the symbol in all the loaded shared libraries.
-   files to look at if you need reference on this stuff:
-   dld.c, dld_shl_findsym.c
-   end.c
-   man entry for shl_findsym */
-
-CORE_ADDR
-find_stub_with_shl_get (struct minimal_symbol *function, CORE_ADDR handle)
-{
-  struct symbol *get_sym, *symbol2;
-  struct minimal_symbol *buff_minsym, *msymbol;
-  struct type *ftype;
-  struct value **args;
-  struct value *funcval;
-  struct value *val;
-
-  int x, namelen, err_value, tmp = -1;
-  CORE_ADDR endo_buff_addr, value_return_addr, errno_return_addr;
-  CORE_ADDR stub_addr;
-
-
-  args = alloca (sizeof (struct value *) * 8);		/* 6 for the arguments and one null one??? */
-  funcval = find_function_in_inferior ("__d_shl_get");
-  get_sym = lookup_symbol ("__d_shl_get", NULL, VAR_DOMAIN, NULL, NULL);
-  buff_minsym = lookup_minimal_symbol ("__buffer", NULL, NULL);
-  msymbol = lookup_minimal_symbol ("__shldp", NULL, NULL);
-  symbol2 = lookup_symbol ("__shldp", NULL, VAR_DOMAIN, NULL, NULL);
-  endo_buff_addr = SYMBOL_VALUE_ADDRESS (buff_minsym);
-  namelen = strlen (DEPRECATED_SYMBOL_NAME (function));
-  value_return_addr = endo_buff_addr + namelen;
-  ftype = check_typedef (SYMBOL_TYPE (get_sym));
-
-  /* do alignment */
-  if ((x = value_return_addr % 64) != 0)
-    value_return_addr = value_return_addr + 64 - x;
-
-  errno_return_addr = value_return_addr + 64;
-
-
-  /* set up stuff needed by __d_shl_get in buffer in end.o */
-
-  target_write_memory (endo_buff_addr, DEPRECATED_SYMBOL_NAME (function), namelen);
-
-  target_write_memory (value_return_addr, (char *) &tmp, 4);
-
-  target_write_memory (errno_return_addr, (char *) &tmp, 4);
-
-  target_write_memory (SYMBOL_VALUE_ADDRESS (msymbol),
-		       (char *) &handle, 4);
-
-  /* now prepare the arguments for the call */
-
-  args[0] = value_from_longest (TYPE_FIELD_TYPE (ftype, 0), 12);
-  args[1] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 1), SYMBOL_VALUE_ADDRESS (msymbol));
-  args[2] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 2), endo_buff_addr);
-  args[3] = value_from_longest (TYPE_FIELD_TYPE (ftype, 3), TYPE_PROCEDURE);
-  args[4] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 4), value_return_addr);
-  args[5] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 5), errno_return_addr);
-
-  /* now call the function */
-
-  val = call_function_by_hand (funcval, 6, args);
-
-  /* now get the results */
-
-  target_read_memory (errno_return_addr, (char *) &err_value, sizeof (err_value));
-
-  target_read_memory (value_return_addr, (char *) &stub_addr, sizeof (stub_addr));
-  if (stub_addr <= 0)
-    error ("call to __d_shl_get failed, error code is %d", err_value);
-
-  return (stub_addr);
-}
-
-/* Cover routine for find_stub_with_shl_get to pass to catch_errors */
-static int
-cover_find_stub_with_shl_get (void *args_untyped)
-{
-  args_for_find_stub *args = args_untyped;
-  args->return_val = find_stub_with_shl_get (args->msym, args->solib_handle);
-  return 0;
-}
-
 /* Get the PC from %r31 if currently in a syscall.  Also mask out privilege
    bits.  */
 
@@ -2493,460 +2383,6 @@ hppa_unwind_pc (struct gdbarch *gdbarch,
   return frame_unwind_register_signed (next_frame, PCOQ_HEAD_REGNUM) & ~3;
 }
 
-/* Exception handling support for the HP-UX ANSI C++ compiler.
-   The compiler (aCC) provides a callback for exception events;
-   GDB can set a breakpoint on this callback and find out what
-   exception event has occurred. */
-
-/* The name of the hook to be set to point to the callback function */
-static char HP_ACC_EH_notify_hook[] = "__eh_notify_hook";
-/* The name of the function to be used to set the hook value */
-static char HP_ACC_EH_set_hook_value[] = "__eh_set_hook_value";
-/* The name of the callback function in end.o */
-static char HP_ACC_EH_notify_callback[] = "__d_eh_notify_callback";
-/* Name of function in end.o on which a break is set (called by above) */
-static char HP_ACC_EH_break[] = "__d_eh_break";
-/* Name of flag (in end.o) that enables catching throws */
-static char HP_ACC_EH_catch_throw[] = "__d_eh_catch_throw";
-/* Name of flag (in end.o) that enables catching catching */
-static char HP_ACC_EH_catch_catch[] = "__d_eh_catch_catch";
-/* The enum used by aCC */
-typedef enum
-  {
-    __EH_NOTIFY_THROW,
-    __EH_NOTIFY_CATCH
-  }
-__eh_notification;
-
-/* Is exception-handling support available with this executable? */
-static int hp_cxx_exception_support = 0;
-/* Has the initialize function been run? */
-int hp_cxx_exception_support_initialized = 0;
-/* Similar to above, but imported from breakpoint.c -- non-target-specific */
-extern int exception_support_initialized;
-/* Address of __eh_notify_hook */
-static CORE_ADDR eh_notify_hook_addr = 0;
-/* Address of __d_eh_notify_callback */
-static CORE_ADDR eh_notify_callback_addr = 0;
-/* Address of __d_eh_break */
-static CORE_ADDR eh_break_addr = 0;
-/* Address of __d_eh_catch_catch */
-static CORE_ADDR eh_catch_catch_addr = 0;
-/* Address of __d_eh_catch_throw */
-static CORE_ADDR eh_catch_throw_addr = 0;
-/* Sal for __d_eh_break */
-static struct symtab_and_line *break_callback_sal = 0;
-
-/* Code in end.c expects __d_pid to be set in the inferior,
-   otherwise __d_eh_notify_callback doesn't bother to call
-   __d_eh_break!  So we poke the pid into this symbol
-   ourselves.
-   0 => success
-   1 => failure  */
-int
-setup_d_pid_in_inferior (void)
-{
-  CORE_ADDR anaddr;
-  struct minimal_symbol *msymbol;
-  char buf[4];			/* FIXME 32x64? */
-
-  /* Slam the pid of the process into __d_pid; failing is only a warning!  */
-  msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile);
-  if (msymbol == NULL)
-    {
-      warning ("Unable to find __d_pid symbol in object file.");
-      warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
-      return 1;
-    }
-
-  anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
-  store_unsigned_integer (buf, 4, PIDGET (inferior_ptid)); /* FIXME 32x64? */
-  if (target_write_memory (anaddr, buf, 4))	/* FIXME 32x64? */
-    {
-      warning ("Unable to write __d_pid");
-      warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
-      return 1;
-    }
-  return 0;
-}
-
-/* Initialize exception catchpoint support by looking for the
-   necessary hooks/callbacks in end.o, etc., and set the hook value to
-   point to the required debug function
-
-   Return 0 => failure
-   1 => success          */
-
-static int
-initialize_hp_cxx_exception_support (void)
-{
-  struct symtabs_and_lines sals;
-  struct cleanup *old_chain;
-  struct cleanup *canonical_strings_chain = NULL;
-  int i;
-  char *addr_start;
-  char *addr_end = NULL;
-  char **canonical = (char **) NULL;
-  int thread = -1;
-  struct symbol *sym = NULL;
-  struct minimal_symbol *msym = NULL;
-  struct objfile *objfile;
-  asection *shlib_info;
-
-  /* Detect and disallow recursion.  On HP-UX with aCC, infinite
-     recursion is a possibility because finding the hook for exception
-     callbacks involves making a call in the inferior, which means
-     re-inserting breakpoints which can re-invoke this code */
-
-  static int recurse = 0;
-  if (recurse > 0)
-    {
-      hp_cxx_exception_support_initialized = 0;
-      exception_support_initialized = 0;
-      return 0;
-    }
-
-  hp_cxx_exception_support = 0;
-
-  /* First check if we have seen any HP compiled objects; if not,
-     it is very unlikely that HP's idiosyncratic callback mechanism
-     for exception handling debug support will be available!
-     This will percolate back up to breakpoint.c, where our callers
-     will decide to try the g++ exception-handling support instead. */
-  if (!hp_som_som_object_present)
-    return 0;
-
-  /* We have a SOM executable with SOM debug info; find the hooks */
-
-  /* First look for the notify hook provided by aCC runtime libs */
-  /* If we find this symbol, we conclude that the executable must
-     have HP aCC exception support built in.  If this symbol is not
-     found, even though we're a HP SOM-SOM file, we may have been
-     built with some other compiler (not aCC).  This results percolates
-     back up to our callers in breakpoint.c which can decide to
-     try the g++ style of exception support instead.
-     If this symbol is found but the other symbols we require are
-     not found, there is something weird going on, and g++ support
-     should *not* be tried as an alternative.
-
-     ASSUMPTION: Only HP aCC code will have __eh_notify_hook defined.  
-     ASSUMPTION: HP aCC and g++ modules cannot be linked together. */
-
-  /* libCsup has this hook; it'll usually be non-debuggable */
-  msym = lookup_minimal_symbol (HP_ACC_EH_notify_hook, NULL, NULL);
-  if (msym)
-    {
-      eh_notify_hook_addr = SYMBOL_VALUE_ADDRESS (msym);
-      hp_cxx_exception_support = 1;
-    }
-  else
-    {
-      warning ("Unable to find exception callback hook (%s).", HP_ACC_EH_notify_hook);
-      warning ("Executable may not have been compiled debuggable with HP aCC.");
-      warning ("GDB will be unable to intercept exception events.");
-      eh_notify_hook_addr = 0;
-      hp_cxx_exception_support = 0;
-      return 0;
-    }
-
-  /* Next look for the notify callback routine in end.o */
-  /* This is always available in the SOM symbol dictionary if end.o is linked in */
-  msym = lookup_minimal_symbol (HP_ACC_EH_notify_callback, NULL, NULL);
-  if (msym)
-    {
-      eh_notify_callback_addr = SYMBOL_VALUE_ADDRESS (msym);
-      hp_cxx_exception_support = 1;
-    }
-  else
-    {
-      warning ("Unable to find exception callback routine (%s).", HP_ACC_EH_notify_callback);
-      warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
-      warning ("GDB will be unable to intercept exception events.");
-      eh_notify_callback_addr = 0;
-      return 0;
-    }
-
-#ifndef GDB_TARGET_IS_HPPA_20W
-  /* Check whether the executable is dynamically linked or archive bound */
-  /* With an archive-bound executable we can use the raw addresses we find
-     for the callback function, etc. without modification. For an executable
-     with shared libraries, we have to do more work to find the plabel, which
-     can be the target of a call through $$dyncall from the aCC runtime support
-     library (libCsup) which is linked shared by default by aCC. */
-  /* This test below was copied from somsolib.c/somread.c.  It may not be a very
-     reliable one to test that an executable is linked shared. pai/1997-07-18 */
-  shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
-  if (shlib_info && (bfd_section_size (symfile_objfile->obfd, shlib_info) != 0))
-    {
-      /* The minsym we have has the local code address, but that's not the
-         plabel that can be used by an inter-load-module call. */
-      /* Find solib handle for main image (which has end.o), and use that
-         and the min sym as arguments to __d_shl_get() (which does the equivalent
-         of shl_findsym()) to find the plabel. */
-
-      args_for_find_stub args;
-      static char message[] = "Error while finding exception callback hook:\n";
-
-      args.solib_handle = som_solib_get_solib_by_pc (eh_notify_callback_addr);
-      args.msym = msym;
-      args.return_val = 0;
-
-      recurse++;
-      catch_errors (cover_find_stub_with_shl_get, &args, message,
-		    RETURN_MASK_ALL);
-      eh_notify_callback_addr = args.return_val;
-      recurse--;
-
-      exception_catchpoints_are_fragile = 1;
-
-      if (!eh_notify_callback_addr)
-	{
-	  /* We can get here either if there is no plabel in the export list
-	     for the main image, or if something strange happened (?) */
-	  warning ("Couldn't find a plabel (indirect function label) for the exception callback.");
-	  warning ("GDB will not be able to intercept exception events.");
-	  return 0;
-	}
-    }
-  else
-    exception_catchpoints_are_fragile = 0;
-#endif
-
-  /* Now, look for the breakpointable routine in end.o */
-  /* This should also be available in the SOM symbol dict. if end.o linked in */
-  msym = lookup_minimal_symbol (HP_ACC_EH_break, NULL, NULL);
-  if (msym)
-    {
-      eh_break_addr = SYMBOL_VALUE_ADDRESS (msym);
-      hp_cxx_exception_support = 1;
-    }
-  else
-    {
-      warning ("Unable to find exception callback routine to set breakpoint (%s).", HP_ACC_EH_break);
-      warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
-      warning ("GDB will be unable to intercept exception events.");
-      eh_break_addr = 0;
-      return 0;
-    }
-
-  /* Next look for the catch enable flag provided in end.o */
-  sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL,
-		       VAR_DOMAIN, 0, (struct symtab **) NULL);
-  if (sym)			/* sometimes present in debug info */
-    {
-      eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (sym);
-      hp_cxx_exception_support = 1;
-    }
-  else
-    /* otherwise look in SOM symbol dict. */
-    {
-      msym = lookup_minimal_symbol (HP_ACC_EH_catch_catch, NULL, NULL);
-      if (msym)
-	{
-	  eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (msym);
-	  hp_cxx_exception_support = 1;
-	}
-      else
-	{
-	  warning ("Unable to enable interception of exception catches.");
-	  warning ("Executable may not have been compiled debuggable with HP aCC.");
-	  warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
-	  return 0;
-	}
-    }
-
-  /* Next look for the catch enable flag provided end.o */
-  sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL,
-		       VAR_DOMAIN, 0, (struct symtab **) NULL);
-  if (sym)			/* sometimes present in debug info */
-    {
-      eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (sym);
-      hp_cxx_exception_support = 1;
-    }
-  else
-    /* otherwise look in SOM symbol dict. */
-    {
-      msym = lookup_minimal_symbol (HP_ACC_EH_catch_throw, NULL, NULL);
-      if (msym)
-	{
-	  eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (msym);
-	  hp_cxx_exception_support = 1;
-	}
-      else
-	{
-	  warning ("Unable to enable interception of exception throws.");
-	  warning ("Executable may not have been compiled debuggable with HP aCC.");
-	  warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
-	  return 0;
-	}
-    }
-
-  /* Set the flags */
-  hp_cxx_exception_support = 2;	/* everything worked so far */
-  hp_cxx_exception_support_initialized = 1;
-  exception_support_initialized = 1;
-
-  return 1;
-}
-
-/* Target operation for enabling or disabling interception of
-   exception events.
-   KIND is either EX_EVENT_THROW or EX_EVENT_CATCH
-   ENABLE is either 0 (disable) or 1 (enable).
-   Return value is NULL if no support found;
-   -1 if something went wrong,
-   or a pointer to a symtab/line struct if the breakpointable
-   address was found. */
-
-struct symtab_and_line *
-child_enable_exception_callback (enum exception_event_kind kind, int enable)
-{
-  char buf[4];
-
-  if (!exception_support_initialized || !hp_cxx_exception_support_initialized)
-    if (!initialize_hp_cxx_exception_support ())
-      return NULL;
-
-  switch (hp_cxx_exception_support)
-    {
-    case 0:
-      /* Assuming no HP support at all */
-      return NULL;
-    case 1:
-      /* HP support should be present, but something went wrong */
-      return (struct symtab_and_line *) -1;	/* yuck! */
-      /* there may be other cases in the future */
-    }
-
-  /* Set the EH hook to point to the callback routine */
-  store_unsigned_integer (buf, 4, enable ? eh_notify_callback_addr : 0);	/* FIXME 32x64 problem */
-  /* pai: (temp) FIXME should there be a pack operation first? */
-  if (target_write_memory (eh_notify_hook_addr, buf, 4))	/* FIXME 32x64 problem */
-    {
-      warning ("Could not write to target memory for exception event callback.");
-      warning ("Interception of exception events may not work.");
-      return (struct symtab_and_line *) -1;
-    }
-  if (enable)
-    {
-      /* Ensure that __d_pid is set up correctly -- end.c code checks this. :-( */
-      if (PIDGET (inferior_ptid) > 0)
-	{
-	  if (setup_d_pid_in_inferior ())
-	    return (struct symtab_and_line *) -1;
-	}
-      else
-	{
-	  warning ("Internal error: Invalid inferior pid?  Cannot intercept exception events.");
-	  return (struct symtab_and_line *) -1;
-	}
-    }
-
-  switch (kind)
-    {
-    case EX_EVENT_THROW:
-      store_unsigned_integer (buf, 4, enable ? 1 : 0);
-      if (target_write_memory (eh_catch_throw_addr, buf, 4))	/* FIXME 32x64? */
-	{
-	  warning ("Couldn't enable exception throw interception.");
-	  return (struct symtab_and_line *) -1;
-	}
-      break;
-    case EX_EVENT_CATCH:
-      store_unsigned_integer (buf, 4, enable ? 1 : 0);
-      if (target_write_memory (eh_catch_catch_addr, buf, 4))	/* FIXME 32x64? */
-	{
-	  warning ("Couldn't enable exception catch interception.");
-	  return (struct symtab_and_line *) -1;
-	}
-      break;
-    default:
-      error ("Request to enable unknown or unsupported exception event.");
-    }
-
-  /* Copy break address into new sal struct, malloc'ing if needed. */
-  if (!break_callback_sal)
-    {
-      break_callback_sal = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line));
-    }
-  init_sal (break_callback_sal);
-  break_callback_sal->symtab = NULL;
-  break_callback_sal->pc = eh_break_addr;
-  break_callback_sal->line = 0;
-  break_callback_sal->end = eh_break_addr;
-
-  return break_callback_sal;
-}
-
-/* Record some information about the current exception event */
-static struct exception_event_record current_ex_event;
-/* Convenience struct */
-static struct symtab_and_line null_symtab_and_line =
-{NULL, 0, 0, 0};
-
-/* Report current exception event.  Returns a pointer to a record
-   that describes the kind of the event, where it was thrown from,
-   and where it will be caught.  More information may be reported
-   in the future */
-struct exception_event_record *
-child_get_current_exception_event (void)
-{
-  CORE_ADDR event_kind;
-  CORE_ADDR throw_addr;
-  CORE_ADDR catch_addr;
-  struct frame_info *fi, *curr_frame;
-  int level = 1;
-
-  curr_frame = get_current_frame ();
-  if (!curr_frame)
-    return (struct exception_event_record *) NULL;
-
-  /* Go up one frame to __d_eh_notify_callback, because at the
-     point when this code is executed, there's garbage in the
-     arguments of __d_eh_break. */
-  fi = find_relative_frame (curr_frame, &level);
-  if (level != 0)
-    return (struct exception_event_record *) NULL;
-
-  select_frame (fi);
-
-  /* Read in the arguments */
-  /* __d_eh_notify_callback() is called with 3 arguments:
-     1. event kind catch or throw
-     2. the target address if known
-     3. a flag -- not sure what this is. pai/1997-07-17 */
-  event_kind = read_register (ARG0_REGNUM);
-  catch_addr = read_register (ARG1_REGNUM);
-
-  /* Now go down to a user frame */
-  /* For a throw, __d_eh_break is called by
-     __d_eh_notify_callback which is called by
-     __notify_throw which is called
-     from user code.
-     For a catch, __d_eh_break is called by
-     __d_eh_notify_callback which is called by
-     <stackwalking stuff> which is called by
-     __throw__<stuff> or __rethrow_<stuff> which is called
-     from user code. */
-  /* FIXME: Don't use such magic numbers; search for the frames */
-  level = (event_kind == EX_EVENT_THROW) ? 3 : 4;
-  fi = find_relative_frame (curr_frame, &level);
-  if (level != 0)
-    return (struct exception_event_record *) NULL;
-
-  select_frame (fi);
-  throw_addr = get_frame_pc (fi);
-
-  /* Go back to original (top) frame */
-  select_frame (curr_frame);
-
-  current_ex_event.kind = (enum exception_event_kind) event_kind;
-  current_ex_event.throw_sal = find_pc_line (throw_addr, 1);
-  current_ex_event.catch_sal = find_pc_line (catch_addr, 1);
-
-  return &current_ex_event;
-}
-
 /* Instead of this nasty cast, add a method pvoid() that prints out a
    host VOID data type (remember %p isn't portable).  */
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]