2004-11-08 Andrew Cagney <cagney@gnu.org>
[deliverable/binutils-gdb.git] / gdb / hppa-hpux-tdep.c
index e6ff1a5aa9105ec2312c6e042b9ea77f9a7dcf78..9623abeb759c049388f968d7b6daf13dd19cdbf7 100644 (file)
@@ -24,15 +24,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "osabi.h"
 #include "gdb_string.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 <dl.h>
 #include <machine/save_state.h>
 
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+#endif
+
 /* Forward declarations.  */
 extern void _initialize_hppa_hpux_tdep (void);
 extern initialize_file_ftype _initialize_hppa_hpux_tdep;
@@ -45,125 +52,6 @@ typedef struct
   }
 args_for_find_stub;
 
-/* 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);
-void hppa32_hpux_frame_saved_pc_in_sigtramp (struct frame_info *fi,
-                                             CORE_ADDR *tmp);
-void hppa32_hpux_frame_base_before_sigtramp (struct frame_info *fi,
-                                             CORE_ADDR *tmp);
-void hppa32_hpux_frame_find_saved_regs_in_sigtramp (struct frame_info *fi,
-                                                    CORE_ADDR *fsr);
-void hppa64_hpux_frame_saved_pc_in_sigtramp (struct frame_info *fi,
-                                             CORE_ADDR *tmp);
-void hppa64_hpux_frame_base_before_sigtramp (struct frame_info *fi,
-                                             CORE_ADDR *tmp);
-void hppa64_hpux_frame_find_saved_regs_in_sigtramp (struct frame_info *fi,
-                                                    CORE_ADDR *fsr);
-
-int
-hppa_hpux_pc_in_sigtramp (CORE_ADDR pc, char *name)
-{
-  /* Actually, for a PA running HPUX the kernel calls the signal handler
-     without an intermediate trampoline.  Luckily the kernel always sets
-     the return pointer for the signal handler to point to _sigreturn.  */
-  return (name && (strcmp ("_sigreturn", name) == 0));
-}
-
-/* For hppa32_hpux_frame_saved_pc_in_sigtramp, 
-   hppa32_hpux_frame_base_before_sigtramp and
-   hppa32_hpux_frame_find_saved_regs_in_sigtramp:
-
-   The signal context structure pointer is always saved at the base
-   of the frame which "calls" the signal handler.  We only want to find
-   the hardware save state structure, which lives 10 32bit words into
-   sigcontext structure.
-
-   Within the hardware save state structure, registers are found in the
-   same order as the register numbers in GDB.
-
-   At one time we peeked at %r31 rather than the PC queues to determine
-   what instruction took the fault.  This was done on purpose, but I don't
-   remember why.  Looking at the PC queues is really the right way, and
-   I don't remember why that didn't work when this code was originally
-   written.  */
-
-void
-hppa32_hpux_frame_saved_pc_in_sigtramp (struct frame_info *fi, CORE_ADDR *tmp)
-{
-  *tmp = read_memory_integer (get_frame_base (fi) + (43 * 4), 4);
-}
-
-void
-hppa32_hpux_frame_base_before_sigtramp (struct frame_info *fi,
-                                        CORE_ADDR *tmp)
-{
-  *tmp = read_memory_integer (get_frame_base (fi) + (40 * 4), 4);
-}
-
-void
-hppa32_hpux_frame_find_saved_regs_in_sigtramp (struct frame_info *fi,
-                                              CORE_ADDR *fsr)
-{
-  int i;
-  const CORE_ADDR tmp = get_frame_base (fi) + (10 * 4);
-
-  for (i = 0; i < NUM_REGS; i++)
-    {
-      if (i == HPPA_SP_REGNUM)
-       fsr[HPPA_SP_REGNUM] = read_memory_integer (tmp + HPPA_SP_REGNUM * 4, 4);
-      else
-       fsr[i] = tmp + i * 4;
-    }
-}
-
-/* For hppa64_hpux_frame_saved_pc_in_sigtramp, 
-   hppa64_hpux_frame_base_before_sigtramp and
-   hppa64_hpux_frame_find_saved_regs_in_sigtramp:
-
-   These functions are the PA64 ABI equivalents of the 32bits counterparts
-   above. See the comments there.
-
-   For PA64, the save_state structure is at an offset of 24 32-bit words
-   from the sigcontext structure. The 64 bit general registers are at an
-   offset of 640 bytes from the beginning of the save_state structure,
-   and the floating pointer register are at an offset of 256 bytes from
-   the beginning of the save_state structure.  */
-
-void
-hppa64_hpux_frame_saved_pc_in_sigtramp (struct frame_info *fi, CORE_ADDR *tmp)
-{
-  *tmp = read_memory_integer
-           (get_frame_base (fi) + (24 * 4) + 640 + (33 * 8), 8);
-}
-
-void
-hppa64_hpux_frame_base_before_sigtramp (struct frame_info *fi,
-                                        CORE_ADDR *tmp)
-{
-  *tmp = read_memory_integer
-           (get_frame_base (fi) + (24 * 4) + 640 + (30 * 8), 8);
-}
-
-void
-hppa64_hpux_frame_find_saved_regs_in_sigtramp (struct frame_info *fi,
-                                              CORE_ADDR *fsr)
-{
-  int i;
-  const CORE_ADDR tmp1 = get_frame_base (fi) + (24 * 4) + 640;
-  const CORE_ADDR tmp2 = get_frame_base (fi) + (24 * 4) + 256;
-
-  for (i = 0; i < NUM_REGS; i++)
-    {
-      if (i == HPPA_SP_REGNUM)
-        fsr[HPPA_SP_REGNUM] = read_memory_integer (tmp1 + HPPA_SP_REGNUM * 8, 8);
-      else if (i >= HPPA_FP0_REGNUM)
-        fsr[i] = tmp2 + (i - HPPA_FP0_REGNUM) * 8;
-      else
-        fsr[i] = tmp1 + i * 8;
-    }
-}
-
 /* 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
@@ -174,32 +62,10 @@ hppa32_hpux_in_solib_call_trampoline (CORE_ADDR pc, char *name)
 {
   struct minimal_symbol *minsym;
   struct unwind_table_entry *u;
-  static CORE_ADDR dyncall = 0;
-  static CORE_ADDR sr4export = 0;
-
-  /* FIXME XXX - dyncall and sr4export must be initialized whenever we get a
-     new exec file */
 
   /* First see if PC is in one of the two C-library trampolines.  */
-  if (!dyncall)
-    {
-      minsym = lookup_minimal_symbol ("$$dyncall", NULL, NULL);
-      if (minsym)
-       dyncall = SYMBOL_VALUE_ADDRESS (minsym);
-      else
-       dyncall = -1;
-    }
-
-  if (!sr4export)
-    {
-      minsym = lookup_minimal_symbol ("_sr4export", NULL, NULL);
-      if (minsym)
-       sr4export = SYMBOL_VALUE_ADDRESS (minsym);
-      else
-       sr4export = -1;
-    }
-
-  if (pc == dyncall || pc == sr4export)
+  if (pc == hppa_symbol_address("$$dyncall") 
+      || pc == hppa_symbol_address("_sr4export"))
     return 1;
 
   minsym = lookup_minimal_symbol_by_pc (pc);
@@ -408,45 +274,12 @@ hppa_hpux_skip_trampoline_code (CORE_ADDR pc)
 {
   long orig_pc = pc;
   long prev_inst, curr_inst, loc;
-  static CORE_ADDR dyncall = 0;
-  static CORE_ADDR dyncall_external = 0;
-  static CORE_ADDR sr4export = 0;
   struct minimal_symbol *msym;
   struct unwind_table_entry *u;
 
-  /* FIXME XXX - dyncall and sr4export must be initialized whenever we get a
-     new exec file */
-
-  if (!dyncall)
-    {
-      msym = lookup_minimal_symbol ("$$dyncall", NULL, NULL);
-      if (msym)
-       dyncall = SYMBOL_VALUE_ADDRESS (msym);
-      else
-       dyncall = -1;
-    }
-
-  if (!dyncall_external)
-    {
-      msym = lookup_minimal_symbol ("$$dyncall_external", NULL, NULL);
-      if (msym)
-       dyncall_external = SYMBOL_VALUE_ADDRESS (msym);
-      else
-       dyncall_external = -1;
-    }
-
-  if (!sr4export)
-    {
-      msym = lookup_minimal_symbol ("_sr4export", NULL, NULL);
-      if (msym)
-       sr4export = SYMBOL_VALUE_ADDRESS (msym);
-      else
-       sr4export = -1;
-    }
-
   /* Addresses passed to dyncall may *NOT* be the actual address
      of the function.  So we may have to do something special.  */
-  if (pc == dyncall)
+  if (pc == hppa_symbol_address("$$dyncall"))
     {
       pc = (CORE_ADDR) read_register (22);
 
@@ -456,12 +289,12 @@ hppa_hpux_skip_trampoline_code (CORE_ADDR pc)
       if (pc & 0x2)
        pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, TARGET_PTR_BIT / 8);
     }
-  if (pc == dyncall_external)
+  if (pc == hppa_symbol_address("$$dyncall_external"))
     {
       pc = (CORE_ADDR) read_register (22);
       pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, TARGET_PTR_BIT / 8);
     }
-  else if (pc == sr4export)
+  else if (pc == hppa_symbol_address("_sr4export"))
     pc = (CORE_ADDR) (read_register (22));
 
   /* Get the unwind descriptor corresponding to PC, return zero
@@ -701,7 +534,7 @@ __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;
+static int hp_cxx_exception_support_initialized = 0;
 /* Address of __eh_notify_hook */
 static CORE_ADDR eh_notify_hook_addr = 0;
 /* Address of __d_eh_notify_callback */
@@ -1222,21 +1055,372 @@ child_get_current_exception_event (void)
   return &current_ex_event;
 }
 
+/* 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 *next_frame,
+                                      void **this_cache)
+
+{
+  struct gdbarch *gdbarch = get_frame_arch (next_frame);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  struct hppa_hpux_sigtramp_unwind_cache *info;
+  unsigned int flag;
+  CORE_ADDR sp, scptr;
+  int i, incr, off, 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 (next_frame);
+
+  sp = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
+
+  scptr = sp - 1352;
+  off = scptr;
+
+  /* See /usr/include/machine/save_state.h for the structure of the save_state_t
+     structure. */
+  
+  flag = read_memory_unsigned_integer(scptr, 4);
+    
+  if (!(flag & 0x40))
+    {
+      /* Narrow registers. */
+      off = scptr + offsetof (save_state_t, ss_narrow);
+      incr = 4;
+      szoff = 0;
+    }
+  else
+    {
+      /* Wide registers. */
+      off = scptr + offsetof (save_state_t, ss_wide) + 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 < sizeof(hppa_hpux_tramp_reg) / sizeof(hppa_hpux_tramp_reg[0]);
+       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 = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
+
+  return info;
+}
+
+static void
+hppa_hpux_sigtramp_frame_this_id (struct frame_info *next_frame,
+                                  void **this_prologue_cache,
+                                  struct frame_id *this_id)
+{
+  struct hppa_hpux_sigtramp_unwind_cache *info
+    = hppa_hpux_sigtramp_frame_unwind_cache (next_frame, this_prologue_cache);
+  *this_id = frame_id_build (info->base, frame_pc_unwind (next_frame));
+}
+
+static void
+hppa_hpux_sigtramp_frame_prev_register (struct frame_info *next_frame,
+                                        void **this_prologue_cache,
+                                        int regnum, int *optimizedp,
+                                        enum lval_type *lvalp, 
+                                        CORE_ADDR *addrp,
+                                        int *realnump, void *valuep)
+{
+  struct hppa_hpux_sigtramp_unwind_cache *info
+    = hppa_hpux_sigtramp_frame_unwind_cache (next_frame, this_prologue_cache);
+  hppa_frame_prev_register_helper (next_frame, info->saved_regs, regnum,
+                                  optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind hppa_hpux_sigtramp_frame_unwind = {
+  SIGTRAMP_FRAME,
+  hppa_hpux_sigtramp_frame_this_id,
+  hppa_hpux_sigtramp_frame_prev_register
+};
+
+static const struct frame_unwind *
+hppa_hpux_sigtramp_unwind_sniffer (struct frame_info *next_frame)
+{
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  char *name;
+
+  find_pc_partial_function (pc, &name, NULL, NULL);
+
+  if (name && strcmp(name, "_sigreturn") == 0)
+    return &hppa_hpux_sigtramp_frame_unwind;
+
+  return NULL;
+}
+
+static CORE_ADDR
+hppa_hpux_som_find_global_pointer (struct value *function)
+{
+  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;
+      char buf[4];
+
+      faddr &= ~3;
+
+      status = target_read_memory (faddr + 4, buf, sizeof (buf));
+      if (status == 0)
+       return extract_unsigned_integer (buf, sizeof (buf));
+    }
+
+  return som_solib_get_got_by_pc (faddr);
+}
+
+static CORE_ADDR
+hppa_hpux_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp,
+                          CORE_ADDR funcaddr, int using_gcc,
+                          struct value **args, int nargs,
+                          struct type *value_type,
+                          CORE_ADDR *real_pc, CORE_ADDR *bp_addr)
+{
+  /* FIXME: tausq/2004-06-09: This needs much more testing.  It is broken
+     for pa64, but we should be able to get it to work with a little bit
+     of work. gdb-6.1 has a lot of code to handle various cases; I've tried to
+     simplify it and avoid compile-time conditionals.  */
+
+  /* On HPUX, functions in the main executable and in libraries can be located
+     in different spaces.  In order for us to be able to select the right 
+     space for the function call, we need to go through an instruction seqeunce
+     to select the right space for the target function, call it, and then
+     restore the space on return.
+
+     There are two helper routines that can be used for this task -- if
+     an application is linked with gcc, it will contain a __gcc_plt_call
+     helper function.  __gcc_plt_call, when passed the entry point of an
+     import stub, will do the necessary space setting/restoration for the
+     target function.
+
+     For programs that are compiled/linked with the HP compiler, a similar
+     function called __d_plt_call exists; __d_plt_call expects a PLABEL instead
+     of an import stub as an argument.
+
+     // *INDENT-OFF*
+     To summarize, the call flow is:
+       current function -> dummy frame -> __gcc_plt_call (import stub) 
+                        -> target function
+     or
+       current function -> dummy frame -> __d_plt_call (plabel)
+                        -> target function
+     // *INDENT-ON*
+
+     In general the "funcaddr" argument passed to push_dummy_code is the actual
+     entry point of the target function.  For __gcc_plt_call, we need to 
+     locate the import stub for the corresponding function.  Failing that,
+     we construct a dummy "import stub" on the stack to pass as an argument.
+     For __d_plt_call, we similarly synthesize a PLABEL on the stack to
+     pass to the helper function.
+
+     An additional twist is that, in order for us to restore the space register
+     to its starting state, we need __gcc_plt_call/__d_plt_call to return
+     to the instruction where we started the call.  However, if we put
+     the breakpoint there, gdb will complain because it will find two 
+     frames on the stack with the same (sp, pc) (with the dummy frame in 
+     between).  Currently, we set the return pointer to (pc - 4) of the 
+     current function.  FIXME: This is not an ideal solution; possibly if the 
+     current pc is at the beginning of a page, this will cause a page fault. 
+     Need to understand this better and figure out a better way to fix it.  */
+
+  struct minimal_symbol *sym;
+
+  /* Nonzero if we will use GCC's PLT call routine.  This routine must be
+     passed an import stub, not a PLABEL.  It is also necessary to get %r19
+     before performing the call.  (This is done by push_dummy_call.)  */
+  int use_gcc_plt_call = 1;
+
+  /* See if __gcc_plt_call is available; if not we will use the HP version
+     instead.  */
+  sym = lookup_minimal_symbol ("__gcc_plt_call", NULL, NULL);
+  if (sym == NULL)
+    use_gcc_plt_call = 0;
+
+  /* If using __gcc_plt_call, we need to make sure we pass in an import
+     stub.  funcaddr can be pointing to an export stub or a real function,
+     so we try to resolve it to the import stub.  */
+  if (use_gcc_plt_call)
+    {
+      struct objfile *objfile;
+      struct minimal_symbol *funsym, *stubsym;
+      CORE_ADDR stubaddr = 0;
+
+      funsym = lookup_minimal_symbol_by_pc (funcaddr);
+      if (!funsym)
+        error ("Unable to find symbol for target function.\n");
+
+      ALL_OBJFILES (objfile)
+        {
+         stubsym = lookup_minimal_symbol_solib_trampoline
+           (SYMBOL_LINKAGE_NAME (funsym), objfile);
+
+          if (stubsym)
+           {
+             struct unwind_table_entry *u;
+
+             u = find_unwind_entry (SYMBOL_VALUE (stubsym));
+             if (u == NULL 
+                 || (u->stub_unwind.stub_type != IMPORT
+                     && u->stub_unwind.stub_type != IMPORT_SHLIB))
+               continue;
+
+              stubaddr = SYMBOL_VALUE (stubsym);
+
+             /* 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;
+           }
+       }
+
+      if (stubaddr != 0)
+        {
+          /* Argument to __gcc_plt_call is passed in r22.  */
+          regcache_cooked_write_unsigned (current_regcache, 22, stubaddr);
+        }
+      else
+        {
+         /* No import stub found; let's synthesize one.  */
+
+         /* ldsid %r21, %r1 */
+         write_memory_unsigned_integer (sp, 4, 0x02a010a1);
+         /* mtsp %r1,%sr0 */
+         write_memory_unsigned_integer (sp + 4, 4, 0x00011820);
+         /* be 0(%sr0, %r21) */
+         write_memory_unsigned_integer (sp + 8, 4, 0xe2a00000);
+          /* nop */
+          write_memory_unsigned_integer (sp + 12, 4, 0x08000240);
+
+          regcache_cooked_write_unsigned (current_regcache, 21, funcaddr);
+          regcache_cooked_write_unsigned (current_regcache, 22, sp);
+       }
+
+      /* We set the breakpoint address and r31 to (close to) where the current
+         pc is; when __gcc_plt_call returns, it will restore pcsqh to the
+        current value based on this.  The -4 is needed for frame unwinding
+        to work properly -- we need to land in a different function than
+        the current function.  */
+      *bp_addr = (read_register (HPPA_PCOQ_HEAD_REGNUM) & ~3) - 4;
+      regcache_cooked_write_unsigned (current_regcache, 31, *bp_addr);
+
+      /* Continue from __gcc_plt_call.  */
+      *real_pc = SYMBOL_VALUE (sym);
+    }
+  else
+    {
+      unsigned int gp;
+
+      /* Use __d_plt_call as a fallback; __d_plt_call expects to be called 
+         with a plabel, so we need to build one.  */
+
+      sym = lookup_minimal_symbol ("__d_plt_call", NULL, NULL);
+      if (sym == NULL)
+        error("Can't find an address for __d_plt_call or __gcc_plt_call "
+             "trampoline\nSuggest linking executable with -g or compiling "
+             "with gcc.");
+
+      gp = gdbarch_tdep (gdbarch)->find_global_pointer (funcaddr);
+      write_memory_unsigned_integer (sp, 4, funcaddr);
+      write_memory_unsigned_integer (sp + 4, 4, gp);
+
+      /* plabel is passed in r22 */
+      regcache_cooked_write_unsigned (current_regcache, 22, sp);
+    }
+
+  /* Pushed one stack frame, which has to be 64-byte aligned.  */
+  sp += 64;
+
+  return sp;
+}
+
+static void
+hppa_hpux_inferior_created (struct target_ops *objfile, int from_tty)
+{
+  /* Some HP-UX related globals to clear when a new "main"
+     symbol file is loaded.  HP-specific.  */
+  deprecated_hp_som_som_object_present = 0;
+  hp_cxx_exception_support_initialized = 0;
+}
+
 static void
 hppa_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   if (tdep->bytes_per_address == 4)
-    set_gdbarch_in_solib_call_trampoline (gdbarch, 
-                                         hppa32_hpux_in_solib_call_trampoline);
+    tdep->in_solib_call_trampoline = hppa32_hpux_in_solib_call_trampoline;
   else
-    set_gdbarch_in_solib_call_trampoline (gdbarch, 
-                                         hppa64_hpux_in_solib_call_trampoline);
+    tdep->in_solib_call_trampoline = hppa64_hpux_in_solib_call_trampoline;
 
   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);
+
+  frame_unwind_append_sniffer (gdbarch, hppa_hpux_sigtramp_unwind_sniffer);
+
+  observer_attach_inferior_created (hppa_hpux_inferior_created);
 }
 
 static void
@@ -1245,6 +1429,8 @@ 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 = hppa_hpux_som_find_global_pointer;
   hppa_hpux_init_abi (info, gdbarch);
 }
 
This page took 0.055897 seconds and 4 git commands to generate.