[hppa-hpux] Fix passing function pointers into dummy call

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[hppa-hpux] Fix passing function pointers into dummy call

Randolph Chung
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  <[hidden email]>

        * 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)
  {