2004-12-07 Randolph Chung <tausq@debian.org>
authorRandolph Chung <tausq@debian.org>
Wed, 8 Dec 2004 01:48:03 +0000 (01:48 +0000)
committerRandolph Chung <tausq@debian.org>
Wed, 8 Dec 2004 01:48:03 +0000 (01:48 +0000)
* hppa-tdep.h (gdbarch_tdep): Add unwind_adjust_stub method.
* hppa-hpux-tdep.c (hppa_hpux_unwind_adjust_stub): New function.
(hppa_hpux_init_abi) Set unwind_adjust_stub method.
* hppa-tdep.c (hppa_frame_cache): Call unwind_adjust_stub method
     if defined.

gdb/ChangeLog
gdb/hppa-hpux-tdep.c
gdb/hppa-tdep.c
gdb/hppa-tdep.h

index a337deaf48f7a7fb3750d00eb7c4b69c56bb24c4..248197e6905f2d480a9290ab3e350fd4b2873772 100644 (file)
@@ -1,3 +1,11 @@
+2004-12-07  Randolph Chung  <tausq@debian.org>
+
+       * hppa-tdep.h (gdbarch_tdep): Add unwind_adjust_stub method.
+       * hppa-hpux-tdep.c (hppa_hpux_unwind_adjust_stub): New function.
+       (hppa_hpux_init_abi) Set unwind_adjust_stub method.
+       * hppa-tdep.c (hppa_frame_cache): Call unwind_adjust_stub method
+       if defined.
+
 2004-12-07  Randolph Chung  <tausq@debian.org>
 
        * hppa-tdep.c (hppa_stub_Frame_unwind_cache): Stop unwinding if 
index cd5c0163522a37dc88492e8d065cef19cfe0d221..9aebb041ca399e4a7cf6199fb49fb1e4e916d6ce 100644 (file)
@@ -1471,6 +1471,44 @@ hppa_hpux_inferior_created (struct target_ops *objfile, int from_tty)
   hp_cxx_exception_support_initialized = 0;
 }
 
+/* Given the current value of the pc, check to see if it is inside a stub, and
+   if so, change the value of the pc to point to the caller of the stub.
+   NEXT_FRAME is the next frame in the current list of frames.
+   BASE contains to stack frame base of the current frame. 
+   SAVE_REGS is the register file stored in the frame cache. */
+static void
+hppa_hpux_unwind_adjust_stub (struct frame_info *next_frame, CORE_ADDR base,
+                             struct trad_frame_saved_reg *saved_regs)
+{
+  int optimized, realreg;
+  enum lval_type lval;
+  CORE_ADDR addr;
+  char buffer[sizeof(ULONGEST)];
+  ULONGEST val;
+  CORE_ADDR stubpc;
+  struct unwind_table_entry *u;
+
+  trad_frame_get_prev_register (next_frame, saved_regs, 
+                               HPPA_PCOQ_HEAD_REGNUM, 
+                               &optimized, &lval, &addr, &realreg, buffer);
+  val = extract_unsigned_integer (buffer, 
+                                 register_size (get_frame_arch (next_frame), 
+                                                HPPA_PCOQ_HEAD_REGNUM));
+
+  u = find_unwind_entry (val);
+  if (u && u->stub_unwind.stub_type == EXPORT)
+    {
+      stubpc = read_memory_integer (base - 24, TARGET_PTR_BIT / 8);
+      trad_frame_set_value (saved_regs, HPPA_PCOQ_HEAD_REGNUM, stubpc);
+    }
+  else if (hppa_symbol_address ("__gcc_plt_call") 
+           == get_pc_function_start (val))
+    {
+      stubpc = read_memory_integer (base - 8, TARGET_PTR_BIT / 8);
+      trad_frame_set_value (saved_regs, HPPA_PCOQ_HEAD_REGNUM, stubpc);
+    }
+}
+
 static void
 hppa_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
@@ -1481,6 +1519,8 @@ hppa_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   else
     tdep->in_solib_call_trampoline = hppa64_hpux_in_solib_call_trampoline;
 
+  tdep->unwind_adjust_stub = hppa_hpux_unwind_adjust_stub;
+
   set_gdbarch_in_solib_return_trampoline (gdbarch,
                                          hppa_hpux_in_solib_return_trampoline);
   set_gdbarch_skip_trampoline_code (gdbarch, hppa_hpux_skip_trampoline_code);
index ae7c519240978e762e66ec815ffc191598405afe..6be4ad52d3946ae9f46ec3bd55a18fa65fbbb119 100644 (file)
@@ -1905,6 +1905,19 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
       }
   }
 
+  {
+    struct gdbarch *gdbarch;
+    struct gdbarch_tdep *tdep;
+
+    gdbarch = get_frame_arch (next_frame);
+    tdep = gdbarch_tdep (gdbarch);
+
+    if (tdep->unwind_adjust_stub)
+      {
+        tdep->unwind_adjust_stub (next_frame, cache->base, cache->saved_regs);
+      }
+  }
+
   if (hppa_debug)
     fprintf_unfiltered (gdb_stdlog, "base=0x%s }", 
       paddr_nz (((struct hppa_frame_cache *)*this_cache)->base));
index a0632de21f6c26a553d2f25641b427865df262cb..0b4185a47ccf5be3ca8d97064a6b932dbcda6150 100644 (file)
@@ -88,6 +88,15 @@ struct gdbarch_tdep
      IN_SOLIB_CALL_TRAMPOLINE evaluates to nonzero if we are currently
      stopped in one of these.  */
   int (*in_solib_call_trampoline) (CORE_ADDR pc, char *name);
+
+  /* For targets that support multiple spaces, we may have additional stubs
+     in the return path.  These stubs are internal to the ABI, and users are
+     not interested in them.  If we detect that we are returning to a stub,
+     adjust the pc to the real caller.  This improves the behavior of commands
+     that traverse frames such as "up" and "finish".  */
+  void (*unwind_adjust_stub) (struct frame_info *next_frame, CORE_ADDR base,
+                             struct trad_frame_saved_reg *saved_regs);
+
 };
 
 /*