Add INTEGER_TO_ADDRESS to hadle nasty harvard architectures that do
authorAndrew Cagney <cagney@redhat.com>
Mon, 15 Oct 2001 18:18:30 +0000 (18:18 +0000)
committerAndrew Cagney <cagney@redhat.com>
Mon, 15 Oct 2001 18:18:30 +0000 (18:18 +0000)
funnies to integer to address conversions.

gdb/ChangeLog
gdb/config/mips/tm-mips.h
gdb/d10v-tdep.c
gdb/doc/ChangeLog
gdb/doc/gdbint.texinfo
gdb/gdbarch.c
gdb/gdbarch.h
gdb/gdbarch.sh
gdb/mips-tdep.c
gdb/values.c

index aa84f1dcaba06ca16e07699ce2f7577483fed709..a3d4087de7c78d1f83265413e318861cc932bf8c 100644 (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>.
index a865e96223de0bcb6b6b693d2febd01f738afcff..f89d7abe10885bbacd6dcca9d1633dd615a91cf3 100644 (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);
index b0dd3bcac184d381e42c4650842ded3006321d3a..e9c926995b0907c71c57117f5d14bc332adc1b69 100644 (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);
index 66300bb8ffba681d0d27802f0b3b0e353599803d..9466bd210b3753072895a1259038a0abf34bcd6a 100644 (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
index 46778f8995cbc18d520899361de40ff870ec677f..3c867fef761cd951e5e15a26ce3240fd29f5a110 100644 (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
index 2517ebaf7b7be13d643c7ee57144f712a564b2de..4dceeac2cdca4a8cb9a5ce0daee1427e3ee59e51 100644 (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)
 {
index 29ed0208567629af775096138439dfb96627b5e9..7e7091767935aa937a1a266940eaae189c4cb452 100644 (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))
index a1d5962b5b9a0377fed2d30a4b00c98f3706f205..cdb9e2014909be0ba31c83d0bac7ddd5236f0371 100755 (executable)
@@ -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
index a6e06bbf394b5657bd30a66dde035c5153f52816..df2bc3ba839b6a0648bf335c9b1059aee188019d 100644 (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;
 }
 
index ededf9d368f6db3618c838d7d9fcc87a08598551..bf032af358f1f9868cd140ac7a57b81c4f2a722d 100644 (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
-
-     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
 }