Add INTEGER_TO_ADDRESS to hadle nasty harvard architectures that do

funnies to integer to address conversions.
This commit is contained in:
Andrew Cagney 2001-10-15 18:18:30 +00:00
parent cf5c0c5bc6
commit fc0c74b114
10 changed files with 196 additions and 29 deletions

View File

@ -1,3 +1,21 @@
2001-10-15 Andrew Cagney <ac131313@redhat.com>
* mips-tdep.c (mips_integer_to_address): New function.
(mips_gdbarch_init): Initialize pointer_to_address,
address_to_pointer and integer_to_address.
* config/mips/tm-mips.h (POINTER_TO_ADDRESS): Delete
(ADDRESS_TO_POINTER): Delete.
* d10v-tdep.c (d10v_integer_to_address): New function.
(d10v_gdbarch_init): Initialize integer_to_address.
* values.c (value_as_pointer): Use INTEGER_TO_ADDRESS when
available.
* gdbarch.sh (INTEGER_TO_ADDRESS): New predicate and function.
* gdbarch.h, gdbarch.c: Regenerate.
2001-10-14 Mark Kettenis <kettenis@gnu.org>
* config/s390/nm-linux.h: Don't include <signal.h>.

View File

@ -499,9 +499,5 @@ typedef unsigned long t_inst; /* Integer big enough to hold an instruction */
extern void mips_set_processor_type_command (char *, int);
/* MIPS sign extends addresses */
#define POINTER_TO_ADDRESS(TYPE,BUF) (signed_pointer_to_address (TYPE, BUF))
#define ADDRESS_TO_POINTER(TYPE,BUF,ADDR) (address_to_signed_pointer (TYPE, BUF, ADDR))
/* Single step based on where the current instruction will take us. */
extern void mips_software_single_step (enum target_signal, int);

View File

@ -419,6 +419,21 @@ d10v_pointer_to_address (struct type *type, void *buf)
return d10v_make_daddr (addr);
}
static CORE_ADDR
d10v_integer_to_address (struct type *type, void *buf)
{
LONGEST val;
val = unpack_long (type, buf);
if (TYPE_CODE (type) == TYPE_CODE_INT
&& TYPE_LENGTH (type) <= TYPE_LENGTH (builtin_type_void_data_ptr))
/* Convert small integers that would would be directly copied into
a pointer variable into an address pointing into data space. */
return d10v_make_daddr (val & 0xffff);
else
/* The value is too large to fit in a pointer. Assume this was
intentional and that the user in fact specified a raw address. */
return val;
}
/* Store the address of the place in which to copy the structure the
subroutine will return. This is called from call_function.
@ -1478,6 +1493,7 @@ d10v_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_addr_bit (gdbarch, 32);
set_gdbarch_address_to_pointer (gdbarch, d10v_address_to_pointer);
set_gdbarch_pointer_to_address (gdbarch, d10v_pointer_to_address);
set_gdbarch_integer_to_address (gdbarch, d10v_integer_to_address);
set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
set_gdbarch_int_bit (gdbarch, 2 * TARGET_CHAR_BIT);
set_gdbarch_long_bit (gdbarch, 4 * TARGET_CHAR_BIT);

View File

@ -1,3 +1,10 @@
2001-10-15 Andrew Cagney <ac131313@redhat.com>
* gdbint.texinfo (Target Architecture Definition): Default
POINTER_TO_ADDRESS functions assume unsigned addresses.
(INTEGER_TO_ADDRESS): Document. Derive pragmatics section from a
posting by Jim Blandy.
2001-10-12 Jim Blandy <jimb@redhat.com>
* Makefile.in (MAKEHTMLFLAGS): Remove -glossary; the most recent

View File

@ -2489,7 +2489,7 @@ appropriate way for the current architecture. If you can, use
Here are some macros which architectures can define to indicate the
relationship between pointers and addresses. These have default
definitions, appropriate for architectures on which all pointers are
simple byte addresses.
simple unsigned byte addresses.
@deftypefn {Target Macro} CORE_ADDR POINTER_TO_ADDRESS (struct type *@var{type}, char *@var{buf})
Assume that @var{buf} holds a pointer of type @var{type}, in the
@ -3141,6 +3141,29 @@ function. A zero value indicates that it is not important or necessary
to set a breakpoint to get through the dynamic linker and that single
stepping will suffice.
@item INTEGER_TO_ADDRESS (@var{type}, @var{buf})
@findex INTEGER_TO_ADDRESS
@cindex converting integers to addresses
Define this when the architecture needs to handle non-pointer to address
conversions specially. Converts that value to an address according to
the current architectures conventions.
@emph{Pragmatics: When the user copies a well defined expression from
their source code and passes it, as a parameter, to @value{GDBN}'s
@code{print} command, they should get the same value as would have been
computed by the target program. Any deviation from this rule can cause
major confusion and annoyance, and needs to be justified carefully. In
other words, @value{GDBN} doesn't really have the freedom to do these
conversions in clever and useful ways. It has, however, been pointed
out that users aren't complaining about how @value{GDBN} casts integers
to pointers; they are complaining that they can't take an address from a
disassembly listing and give it to @code{x/i}. Adding an architecture
method like @code{INTEGER_TO_ADDRESS} certainly makes it possible for
@value{GDBN} to ``get it right'' in all circumstances.}
@xref{Target Architecture Definition, , Pointers Are Not Always
Addresses}.
@item IS_TRAPPED_INTERNALVAR (@var{name})
@findex IS_TRAPPED_INTERNALVAR
This is an ugly hook to allow the specification of special actions that

View File

@ -207,6 +207,7 @@ struct gdbarch
gdbarch_store_pseudo_register_ftype *store_pseudo_register;
gdbarch_pointer_to_address_ftype *pointer_to_address;
gdbarch_address_to_pointer_ftype *address_to_pointer;
gdbarch_integer_to_address_ftype *integer_to_address;
gdbarch_return_value_on_stack_ftype *return_value_on_stack;
gdbarch_extract_return_value_ftype *extract_return_value;
gdbarch_push_arguments_ftype *push_arguments;
@ -387,6 +388,7 @@ struct gdbarch startup_gdbarch =
0,
0,
0,
0,
/* startup_gdbarch() */
};
@ -679,6 +681,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of store_pseudo_register, invalid_p == 0 */
/* Skip verify of pointer_to_address, invalid_p == 0 */
/* Skip verify of address_to_pointer, invalid_p == 0 */
/* Skip verify of integer_to_address, has predicate */
/* Skip verify of return_value_on_stack, invalid_p == 0 */
if ((GDB_MULTI_ARCH >= 2)
&& (gdbarch->extract_return_value == 0))
@ -1312,6 +1315,17 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
(long) current_gdbarch->inner_than
/*INNER_THAN ()*/);
#endif
#ifdef INTEGER_TO_ADDRESS
fprintf_unfiltered (file,
"gdbarch_dump: %s # %s\n",
"INTEGER_TO_ADDRESS(type, buf)",
XSTRING (INTEGER_TO_ADDRESS (type, buf)));
if (GDB_MULTI_ARCH)
fprintf_unfiltered (file,
"gdbarch_dump: INTEGER_TO_ADDRESS = 0x%08lx\n",
(long) current_gdbarch->integer_to_address
/*INTEGER_TO_ADDRESS ()*/);
#endif
#ifdef MAX_REGISTER_RAW_SIZE
fprintf_unfiltered (file,
"gdbarch_dump: MAX_REGISTER_RAW_SIZE # %s\n",
@ -3393,6 +3407,30 @@ set_gdbarch_address_to_pointer (struct gdbarch *gdbarch,
gdbarch->address_to_pointer = address_to_pointer;
}
int
gdbarch_integer_to_address_p (struct gdbarch *gdbarch)
{
return gdbarch->integer_to_address != 0;
}
CORE_ADDR
gdbarch_integer_to_address (struct gdbarch *gdbarch, struct type *type, void *buf)
{
if (gdbarch->integer_to_address == 0)
internal_error (__FILE__, __LINE__,
"gdbarch: gdbarch_integer_to_address invalid");
if (gdbarch_debug >= 2)
fprintf_unfiltered (gdb_stdlog, "gdbarch_integer_to_address called\n");
return gdbarch->integer_to_address (type, buf);
}
void
set_gdbarch_integer_to_address (struct gdbarch *gdbarch,
gdbarch_integer_to_address_ftype integer_to_address)
{
gdbarch->integer_to_address = integer_to_address;
}
int
gdbarch_return_value_on_stack (struct gdbarch *gdbarch, struct type *type)
{

View File

@ -1239,6 +1239,43 @@ extern void set_gdbarch_address_to_pointer (struct gdbarch *gdbarch, gdbarch_add
#endif
#endif
#if defined (INTEGER_TO_ADDRESS)
/* Legacy for systems yet to multi-arch INTEGER_TO_ADDRESS */
#if !defined (INTEGER_TO_ADDRESS_P)
#define INTEGER_TO_ADDRESS_P() (1)
#endif
#endif
/* Default predicate for non- multi-arch targets. */
#if (!GDB_MULTI_ARCH) && !defined (INTEGER_TO_ADDRESS_P)
#define INTEGER_TO_ADDRESS_P() (0)
#endif
extern int gdbarch_integer_to_address_p (struct gdbarch *gdbarch);
#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (INTEGER_TO_ADDRESS_P)
#error "Non multi-arch definition of INTEGER_TO_ADDRESS"
#endif
#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) || !defined (INTEGER_TO_ADDRESS_P)
#define INTEGER_TO_ADDRESS_P() (gdbarch_integer_to_address_p (current_gdbarch))
#endif
/* Default (function) for non- multi-arch platforms. */
#if (!GDB_MULTI_ARCH) && !defined (INTEGER_TO_ADDRESS)
#define INTEGER_TO_ADDRESS(type, buf) ( (type, buf))
#endif
typedef CORE_ADDR (gdbarch_integer_to_address_ftype) (struct type *type, void *buf);
extern CORE_ADDR gdbarch_integer_to_address (struct gdbarch *gdbarch, struct type *type, void *buf);
extern void set_gdbarch_integer_to_address (struct gdbarch *gdbarch, gdbarch_integer_to_address_ftype *integer_to_address);
#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (INTEGER_TO_ADDRESS)
#error "Non multi-arch definition of INTEGER_TO_ADDRESS"
#endif
#if GDB_MULTI_ARCH
#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) || !defined (INTEGER_TO_ADDRESS)
#define INTEGER_TO_ADDRESS(type, buf) (gdbarch_integer_to_address (current_gdbarch, type, buf))
#endif
#endif
/* Default (function) for non- multi-arch platforms. */
#if (!GDB_MULTI_ARCH) && !defined (RETURN_VALUE_ON_STACK)
#define RETURN_VALUE_ON_STACK(type) (generic_return_value_on_stack_not (type))

View File

@ -472,6 +472,7 @@ f:2:STORE_PSEUDO_REGISTER:void:store_pseudo_register:int regnum:regnum:::0::0
#
f:2:POINTER_TO_ADDRESS:CORE_ADDR:pointer_to_address:struct type *type, void *buf:type, buf:::unsigned_pointer_to_address::0
f:2:ADDRESS_TO_POINTER:void:address_to_pointer:struct type *type, void *buf, CORE_ADDR addr:type, buf, addr:::unsigned_address_to_pointer::0
F:2:INTEGER_TO_ADDRESS:CORE_ADDR:integer_to_address:struct type *type, void *buf:type, buf
#
f:2:RETURN_VALUE_ON_STACK:int:return_value_on_stack:struct type *type:type:::generic_return_value_on_stack_not::0
f:2:EXTRACT_RETURN_VALUE:void:extract_return_value:struct type *type, char *regbuf, char *valbuf:type, regbuf, valbuf::0:0

View File

@ -3950,6 +3950,20 @@ mips_ecoff_reg_to_regnum (int num)
return num + FP0_REGNUM - 32;
}
/* Convert an integer into an address. By first converting the value
into a pointer and then extracting it signed, the address is
guarenteed to be correctly sign extended. */
static CORE_ADDR
mips_integer_to_address (struct type *type, void *buf)
{
char *tmp = alloca (TYPE_LENGTH (builtin_type_void_data_ptr));
LONGEST val = unpack_long (type, buf);
store_signed_integer (tmp, TYPE_LENGTH (builtin_type_void_data_ptr), val);
return extract_signed_integer (tmp,
TYPE_LENGTH (builtin_type_void_data_ptr));
}
static struct gdbarch *
mips_gdbarch_init (struct gdbarch_info info,
struct gdbarch_list *arches)
@ -4259,6 +4273,9 @@ mips_gdbarch_init (struct gdbarch_info info,
set_gdbarch_skip_prologue (gdbarch, mips_skip_prologue);
set_gdbarch_saved_pc_after_call (gdbarch, mips_saved_pc_after_call);
set_gdbarch_pointer_to_address (gdbarch, signed_pointer_to_address);
set_gdbarch_address_to_pointer (gdbarch, address_to_signed_pointer);
set_gdbarch_integer_to_address (gdbarch, mips_integer_to_address);
return gdbarch;
}

View File

@ -572,35 +572,49 @@ value_as_pointer (value_ptr val)
return ADDR_BITS_REMOVE (value_as_long (val));
#else
COERCE_ARRAY (val);
/* In converting VAL to an address (CORE_ADDR), any small integers
are first cast to a generic pointer. The function unpack_long
will then correctly convert that pointer into a canonical address
(using POINTER_TO_ADDRESS).
Without the cast, the MIPS gets: 0xa0000000 -> (unsigned int)
0xa0000000 -> (LONGEST) 0x00000000a0000000
/* Some architectures (e.g. Harvard), map instruction and data
addresses onto a single large unified address space. For
instance: An architecture may consider a large integer in the
range 0x10000000 .. 0x1000ffff to already represent a data
addresses (hence not need a pointer to address conversion) while
a small integer would still need to be converted integer to
pointer to address. Just assume such architectures handle all
integer conversions in a single function. */
With the cast, the MIPS gets: 0xa0000000 -> (unsigned int)
0xa0000000 -> (void*) 0xa0000000 -> (LONGEST) 0xffffffffa0000000.
/* JimB writes:
If the user specifies an integer that is larger than the target
pointer type, it is assumed that it was intentional and the value
is converted directly into an ADDRESS. This ensures that no
information is discarded.
I think INTEGER_TO_ADDRESS is a good idea as proposed --- but we
must admonish GDB hackers to make sure its behavior matches the
compiler's, whenever possible.
NOTE: The cast operation may eventualy be converted into a TARGET
method (see POINTER_TO_ADDRESS() and ADDRESS_TO_POINTER()) so
that the TARGET ISA/ABI can apply an arbitrary conversion.
In general, I think GDB should evaluate expressions the same way
the compiler does. When the user copies an expression out of
their source code and hands it to a `print' command, they should
get the same value the compiler would have computed. Any
deviation from this rule can cause major confusion and annoyance,
and needs to be justified carefully. In other words, GDB doesn't
really have the freedom to do these conversions in clever and
useful ways.
AndrewC pointed out that users aren't complaining about how GDB
casts integers to pointers; they are complaining that they can't
take an address from a disassembly listing and give it to `x/i'.
This is certainly important.
Adding an architecture method like INTEGER_TO_ADDRESS certainly
makes it possible for GDB to "get it right" in all circumstances
--- the target has complete control over how things get done, so
people can Do The Right Thing for their target without breaking
anyone else. The standard doesn't specify how integers get
converted to pointers; usually, the ABI doesn't either, but
ABI-specific code is a more reasonable place to handle it. */
if (TYPE_CODE (VALUE_TYPE (val)) != TYPE_CODE_PTR
&& TYPE_CODE (VALUE_TYPE (val)) != TYPE_CODE_REF
&& INTEGER_TO_ADDRESS_P ())
return INTEGER_TO_ADDRESS (VALUE_TYPE (val), VALUE_CONTENTS (val));
NOTE: In pure harvard architectures function and data pointers
can be different and may require different integer to pointer
conversions. */
if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_INT
&& (TYPE_LENGTH (VALUE_TYPE (val))
<= TYPE_LENGTH (builtin_type_void_data_ptr)))
{
val = value_cast (builtin_type_void_data_ptr, val);
}
return unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val));
#endif
}