aboutsummaryrefslogtreecommitdiff
path: root/gdb/hppa-tdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/hppa-tdep.c')
-rw-r--r--gdb/hppa-tdep.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c
index 4af061f..a5b2f85 100644
--- a/gdb/hppa-tdep.c
+++ b/gdb/hppa-tdep.c
@@ -727,6 +727,12 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
/* Two passes. First pass computes the location of everything,
second pass writes the bytes out. */
int write_pass;
+
+ /* Global pointer (r19) of the function we are trying to call. */
+ CORE_ADDR gp;
+
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
for (write_pass = 0; write_pass < 2; write_pass++)
{
CORE_ADDR struct_ptr = 0;
@@ -847,6 +853,11 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
if (struct_return)
write_register (28, struct_addr);
+ gp = tdep->find_global_pointer (function);
+
+ if (gp != 0)
+ write_register (19, gp);
+
/* Set the return address. */
regcache_cooked_write_unsigned (regcache, HPPA_RP_REGNUM, bp_addr);
@@ -980,6 +991,22 @@ hppa64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
}
static CORE_ADDR
+hppa32_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
+ CORE_ADDR addr,
+ struct target_ops *targ)
+{
+ if (addr & 2)
+ {
+ CORE_ADDR plabel;
+
+ plabel = addr & ~3;
+ target_read_memory(plabel, (char *)&addr, 4);
+ }
+
+ return addr;
+}
+
+static CORE_ADDR
hppa32_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
{
/* HP frames are 64-byte (or cache line) aligned (yes that's _byte_
@@ -2309,6 +2336,12 @@ hppa_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
store_unsigned_integer (buf, sizeof(tmp), tmp);
}
+static CORE_ADDR
+hppa_find_global_pointer (struct value *function)
+{
+ return 0;
+}
+
void
hppa_frame_prev_register_helper (struct frame_info *next_frame,
struct trad_frame_saved_reg saved_regs[],
@@ -2410,6 +2443,8 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
else
tdep->bytes_per_address = 4;
+ tdep->find_global_pointer = hppa_find_global_pointer;
+
/* Some parts of the gdbarch vector depend on whether we are running
on a 32 bits or 64 bits target. */
switch (tdep->bytes_per_address)
@@ -2469,6 +2504,8 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
case 4:
set_gdbarch_push_dummy_call (gdbarch, hppa32_push_dummy_call);
set_gdbarch_frame_align (gdbarch, hppa32_frame_align);
+ set_gdbarch_convert_from_func_ptr_addr
+ (gdbarch, hppa32_convert_from_func_ptr_addr);
break;
case 8:
set_gdbarch_push_dummy_call (gdbarch, hppa64_push_dummy_call);