This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[hppa-hpux] Fix passing function pointers into dummy call
- From: Randolph Chung <randolph at tausq dot org>
- To: gdb-patches at sources dot redhat dot com
- Date: Fri, 18 Nov 2005 23:30:18 +0800
- Subject: [hppa-hpux] Fix passing function pointers into dummy call
hppa is one of the platforms that uses function descriptors. When
calling an inferior function from gdb and passing a function pointer, we
need to make sure that we are passing the function descriptor address
instead of the function entry point. Fix this case for hppa64-*
This fixes all the interesting cases in callfuncs.exp, including two
tests that were marked kfail.
note that for hppa-*, we do not need to worry about this because the
compiler puts in additional code to handle this at runtime.
I'll check this in over the weekend if there are no comments. (at that
point i'll remove the kfails as well)
randolph
2005-11-18 Randolph Chung <tausq@debian.org>
* hppa-tdep.c (hppa64_convert_code_addr_to_fptr): New function.
(hppa64_push_dummy_call): If passing a function pointer, ensure
it is a function description address instead of the function entry
point.
Index: hppa-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/hppa-tdep.c,v
retrieving revision 1.212
diff -u -p -r1.212 hppa-tdep.c
--- hppa-tdep.c 3 Oct 2005 20:53:00 -0000 1.212
+++ hppa-tdep.c 18 Nov 2005 15:23:03 -0000
@@ -882,6 +882,50 @@ hppa64_floating_p (const struct type *ty
return 0;
}
+/* If CODE points to a function entry address, try to look up the corresponding
+ function descriptor and return its address instead. If CODE is not a
+ function entry address, then just return it unchanged. */
+static CORE_ADDR
+hppa64_convert_code_addr_to_fptr (CORE_ADDR code)
+{
+ struct obj_section *sec, *opd;
+
+ sec = find_pc_section (code);
+
+ if (!sec)
+ return code;
+
+ /* If CODE is in a data section, assume it's already a fptr. */
+ if (!(sec->the_bfd_section->flags & SEC_CODE))
+ return code;
+
+ ALL_OBJFILE_OSECTIONS (sec->objfile, opd)
+ {
+ if (strcmp (opd->the_bfd_section->name, ".opd") == 0)
+ break;
+ }
+
+ if (opd < sec->objfile->sections_end)
+ {
+ CORE_ADDR addr;
+
+ for (addr = opd->addr; addr < opd->endaddr; addr += 2 * 8)
+ {
+ ULONGEST opdaddr;
+ char tmp[8];
+
+ if (target_read_memory (addr, tmp, sizeof (tmp)))
+ break;
+ opdaddr = extract_unsigned_integer (tmp, sizeof (tmp));
+
+ if (opdaddr == code)
+ return addr - 16;
+ }
+ }
+
+ return code;
+}
+
static CORE_ADDR
hppa64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
struct regcache *regcache, CORE_ADDR bp_addr,
@@ -902,6 +946,7 @@ hppa64_push_dummy_call (struct gdbarch *
struct type *type = value_type (arg);
int len = TYPE_LENGTH (type);
const bfd_byte *valbuf;
+ bfd_byte fptrbuf[8];
int regnum;
/* "Each parameter begins on a 64-bit (8-byte) boundary." */
@@ -977,10 +1022,26 @@ hppa64_push_dummy_call (struct gdbarch *
}
}
+ /* If we are passing a function pointer, make sure we pass a function
+ descriptor instead of the function entry address. */
+ if (TYPE_CODE (type) == TYPE_CODE_PTR
+ && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC)
+ {
+ ULONGEST codeptr, fptr;
+
+ codeptr = unpack_long (type, value_contents (arg));
+ fptr = hppa64_convert_code_addr_to_fptr (codeptr);
+ store_unsigned_integer (fptrbuf, TYPE_LENGTH (type), fptr);
+ valbuf = fptrbuf;
+ }
+ else
+ {
+ valbuf = value_contents (arg);
+ }
+
/* Always store the argument in memory. */
- write_memory (sp + offset, value_contents (arg), len);
+ write_memory (sp + offset, valbuf, len);
- valbuf = value_contents (arg);
regnum = HPPA_ARG0_REGNUM - offset / 8;
while (regnum > HPPA_ARG0_REGNUM - 8 && len > 0)
{