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 a337dea..248197e 100644 (file)
@@ -1,5 +1,13 @@
 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 
        unwinding from a frame with pc == 0.
        (hppa_stub_frame_this_id): Likewise.
index cd5c016..9aebb04 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 ae7c519..6be4ad5 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 a0632de..0b4185a 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);
+
 };
 
 /*