mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2025-02-16 07:27:56 +00:00
Add INTEGER_TO_ADDRESS to hadle nasty harvard architectures that do
funnies to integer to address conversions.
This commit is contained in:
parent
cf5c0c5bc6
commit
fc0c74b114
@ -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>.
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
62
gdb/values.c
62
gdb/values.c
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user