aboutsummaryrefslogtreecommitdiff
path: root/gdb/frv-tdep.c
diff options
context:
space:
mode:
authorKevin Buettner <kevinb@redhat.com>2004-03-13 00:50:53 +0000
committerKevin Buettner <kevinb@redhat.com>2004-03-13 00:50:53 +0000
commitc4d1051556563d76c32f144c8442773ab42de419 (patch)
treea8a6f61bc49a4d206ddfac12db8f537c4dcd7c68 /gdb/frv-tdep.c
parented1bd989f78ed9daec1061f8ec2e6c298dfd4d16 (diff)
downloadgdb-c4d1051556563d76c32f144c8442773ab42de419.zip
gdb-c4d1051556563d76c32f144c8442773ab42de419.tar.gz
gdb-c4d1051556563d76c32f144c8442773ab42de419.tar.bz2
Add shared library support for FR-V FDPIC ABI.
Diffstat (limited to 'gdb/frv-tdep.c')
-rw-r--r--gdb/frv-tdep.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/gdb/frv-tdep.c b/gdb/frv-tdep.c
index 3c424b0..6020b38 100644
--- a/gdb/frv-tdep.c
+++ b/gdb/frv-tdep.c
@@ -1037,6 +1037,45 @@ frv_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
}
static CORE_ADDR
+find_func_descr (struct gdbarch *gdbarch, CORE_ADDR entry_point)
+{
+ CORE_ADDR descr;
+ char valbuf[4];
+
+ descr = frv_fdpic_find_canonical_descriptor (entry_point);
+
+ if (descr != 0)
+ return descr;
+
+ /* Construct a non-canonical descriptor from space allocated on
+ the stack. */
+
+ descr = value_as_long (value_allocate_space_in_inferior (8));
+ store_unsigned_integer (valbuf, 4, entry_point);
+ write_memory (descr, valbuf, 4);
+ store_unsigned_integer (valbuf, 4,
+ frv_fdpic_find_global_pointer (entry_point));
+ write_memory (descr + 4, valbuf, 4);
+ return descr;
+}
+
+static CORE_ADDR
+frv_convert_from_func_ptr_addr (struct gdbarch *gdbarch, CORE_ADDR addr,
+ struct target_ops *targ)
+{
+ CORE_ADDR entry_point;
+ CORE_ADDR got_address;
+
+ entry_point = get_target_memory_unsigned (targ, addr, 4);
+ got_address = get_target_memory_unsigned (targ, addr + 4, 4);
+
+ if (got_address == frv_fdpic_find_global_pointer (entry_point))
+ return entry_point;
+ else
+ return addr;
+}
+
+static CORE_ADDR
frv_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
struct regcache *regcache, CORE_ADDR bp_addr,
int nargs, struct value **args, CORE_ADDR sp,
@@ -1053,6 +1092,7 @@ frv_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
CORE_ADDR regval;
int stack_space;
int stack_offset;
+ enum frv_abi abi = frv_abi (gdbarch);
#if 0
printf("Push %d args at sp = %x, struct_return=%d (%x)\n",
@@ -1092,6 +1132,22 @@ frv_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
len = 4;
val = valbuf;
}
+ else if (abi == FRV_ABI_FDPIC
+ && len == 4
+ && typecode == TYPE_CODE_PTR
+ && TYPE_CODE (TYPE_TARGET_TYPE (arg_type)) == TYPE_CODE_FUNC)
+ {
+ /* The FDPIC ABI requires function descriptors to be passed instead
+ of entry points. */
+ store_unsigned_integer
+ (valbuf, 4,
+ find_func_descr (gdbarch,
+ extract_unsigned_integer (VALUE_CONTENTS (arg),
+ 4)));
+ typecode = TYPE_CODE_PTR;
+ len = 4;
+ val = valbuf;
+ }
else
{
val = (char *) VALUE_CONTENTS (arg);
@@ -1129,6 +1185,14 @@ frv_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
always at BP_ADDR. */
regcache_cooked_write_unsigned (regcache, lr_regnum, bp_addr);
+ if (abi == FRV_ABI_FDPIC)
+ {
+ /* Set the GOT register for the FDPIC ABI. */
+ regcache_cooked_write_unsigned
+ (regcache, first_gpr_regnum + 15,
+ frv_fdpic_find_global_pointer (func_addr));
+ }
+
/* Finally, update the SP register. */
regcache_cooked_write_unsigned (regcache, sp_regnum, sp);
@@ -1449,6 +1513,9 @@ frv_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
}
set_gdbarch_print_insn (gdbarch, print_insn_frv);
+ if (frv_abi (gdbarch) == FRV_ABI_FDPIC)
+ set_gdbarch_convert_from_func_ptr_addr (gdbarch,
+ frv_convert_from_func_ptr_addr);
return gdbarch;
}