funnies to integer to address conversions.
+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>.
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);
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.
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);
+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
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
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
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;
0,
0,
0,
+ 0,
/* startup_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))
(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",
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)
{
#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))
#
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
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)
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;
}
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
-
- With the cast, the MIPS gets: 0xa0000000 -> (unsigned int)
- 0xa0000000 -> (void*) 0xa0000000 -> (LONGEST) 0xffffffffa0000000.
-
- 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.
-
- 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.
-
- 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);
- }
+
+ /* 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. */
+
+ /* JimB writes:
+
+ 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.
+
+ 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));
+
return unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val));
#endif
}