* values.c (value_as_address): If VAL is a function or method,
authorJim Blandy <jimb@codesourcery.com>
Fri, 9 Nov 2001 16:41:50 +0000 (16:41 +0000)
committerJim Blandy <jimb@codesourcery.com>
Fri, 9 Nov 2001 16:41:50 +0000 (16:41 +0000)
just return its address; don't let COERCE_ARRAY convert its
address to a pointer, and then have unpack_long convert it back to
an address.

gdb/ChangeLog
gdb/values.c

index 940c06b..04d1f19 100644 (file)
@@ -1,3 +1,10 @@
+2001-11-09  Jim Blandy  <jimb@redhat.com>
+
+       * values.c (value_as_address): If VAL is a function or method,
+       just return its address; don't let COERCE_ARRAY convert its
+       address to a pointer, and then have unpack_long convert it back to
+       an address.
+
 2001-11-06 Pierre Muller  <muller@ics.u-strasbg.fr>
 
        * p-lang.c (is_pascal_string_type): New function to determine if a 
index 639f7bf..e75941f 100644 (file)
@@ -571,6 +571,48 @@ value_as_address (value_ptr val)
      for pointers to char, in which the low bits *are* significant.  */
   return ADDR_BITS_REMOVE (value_as_long (val));
 #else
+
+  /* There are several targets (IA-64, PowerPC, and others) which
+     don't represent pointers to functions as simply the address of
+     the function's entry point.  For example, on the IA-64, a
+     function pointer points to a two-word descriptor, generated by
+     the linker, which contains the function's entry point, and the
+     value the IA-64 "global pointer" register should have --- to
+     support position-independent code.  The linker generates
+     descriptors only for those functions whose addresses are taken.
+
+     On such targets, it's difficult for GDB to convert an arbitrary
+     function address into a function pointer; it has to either find
+     an existing descriptor for that function, or call malloc and
+     build its own.  On some targets, it is impossible for GDB to
+     build a descriptor at all: the descriptor must contain a jump
+     instruction; data memory cannot be executed; and code memory
+     cannot be modified.
+
+     Upon entry to this function, if VAL is a value of type `function'
+     (that is, TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FUNC), then
+     VALUE_ADDRESS (val) is the address of the function.  This is what
+     you'll get if you evaluate an expression like `main'.  The call
+     to COERCE_ARRAY below actually does all the usual unary
+     conversions, which includes converting values of type `function'
+     to `pointer to function'.  This is the challenging conversion
+     discussed above.  Then, `unpack_long' will convert that pointer
+     back into an address.
+
+     So, suppose the user types `disassemble foo' on an architecture
+     with a strange function pointer representation, on which GDB
+     cannot build its own descriptors, and suppose further that `foo'
+     has no linker-built descriptor.  The address->pointer conversion
+     will signal an error and prevent the command from running, even
+     though the next step would have been to convert the pointer
+     directly back into the same address.
+
+     The following shortcut avoids this whole mess.  If VAL is a
+     function, just return its address directly.  */
+  if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FUNC
+      || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_METHOD)
+    return VALUE_ADDRESS (val);
+
   COERCE_ARRAY (val);
 
   /* Some architectures (e.g. Harvard), map instruction and data