+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
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)
{
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);
}
}
+ {
+ 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));
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);
+
};
/*