This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
Re: Does anybody remember...
- From: Michael Snyder <msnyder at redhat dot com>
- To: Jim Blandy <jimb at redhat dot com>
- Cc: gdb-patches at sources dot redhat dot com
- Date: Wed, 29 May 2002 11:53:20 -0700
- Subject: Re: Does anybody remember...
- Organization: Red Hat, Inc.
- References: <3CEEC758.2B52BB2A@redhat.com> <np4rgxnkgk.fsf@zwingli.cygnus.com>
Jim Blandy wrote:
>
> Michael Snyder <msnyder@redhat.com> writes:
>
> > Does anybody remember a Harvard Architecture issue, wherein you did
> > something
> > like take the address of a function, which caused gdb to scrunch the
> > address
> > down into the target-pointer format and then re-expand it into the
> > unified-address
> > format, with possible loss of information in the process?
> >
> > I think Jim Blandy did something to prevent this from happening,
> > but it seems to have crept back in again.
>
> Here's what I think you're referring to, from values.c. The comment
> only talks about non-Harvard architectures, but `descriptors' are also
> used often in Harvard architectures to keep data and function pointers
> the same size even when the code space is much larger than the data
> space.
OK, good. Now I know what I need to talk to you about, which is:
back in April of 2000, you made a change in "locate_var_value"
so that, if the var is a function pointer, it will call
value_from_pointer
instead of value_from_long. This has exactly the same effect as the one
you are trying to avoid with the code shown below: the address of the
function is crunched down into a pointer (which could be eg. 16 bits),
and then later converted back to an address (with loss of information).
Can you help me see how to avoid this?
>
> /* Extract a value as a C pointer. Does not deallocate the value.
> Note that val's type may not actually be a pointer; value_as_long
> handles all the cases. */
> CORE_ADDR
> value_as_address (struct value *val)
> {
> /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
> whether we want this to be true eventually. */
> #if 0
> /* ADDR_BITS_REMOVE is wrong if we are being called for a
> non-address (e.g. argument to "signal", "info break", etc.), or
> 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);