summaryrefslogtreecommitdiff
path: root/gdb/values.c
diff options
context:
space:
mode:
authorJim Blandy <jimb@codesourcery.com>2001-11-09 16:41:50 +0000
committerJim Blandy <jimb@codesourcery.com>2001-11-09 16:41:50 +0000
commitf312f057407f275b27753c401ede0938c45d299c (patch)
treedca01a0418007b80920aa0e1e13f34e4fa0bb4dc /gdb/values.c
parente333d2c4011881ec0a6b72d6a8093c9dbeb6a448 (diff)
downloadbinutils-gdb-f312f057407f275b27753c401ede0938c45d299c.tar.gz
* 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.
Diffstat (limited to 'gdb/values.c')
-rw-r--r--gdb/values.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/gdb/values.c b/gdb/values.c
index 639f7bf4081..e75941fa3c8 100644
--- a/gdb/values.c
+++ b/gdb/values.c
@@ -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