* test-build.mk (HOLES): Add "xargs" for gdb.
[deliverable/binutils-gdb.git] / gdb / findvar.c
index 922572786b3d109ba51631bc7e753eb37e8bb749..6cb7d37cab82e215ee33ef220f107809c0cb04c1 100644 (file)
@@ -1,5 +1,5 @@
 /* Find a variable's value in memory, for GDB, the GNU debugger.
-   Copyright 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+   Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996 Free Software Foundation, Inc.
 
 This file is part of GDB.
 
@@ -15,7 +15,7 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
 #include "symtab.h"
@@ -25,6 +25,19 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "gdbcore.h"
 #include "inferior.h"
 #include "target.h"
+#include "gdb_string.h"
+#include "floatformat.h"
+
+/* This is used to indicate that we don't know the format of the floating point
+   number.  Typically, this is useful for native ports, where the actual format
+   is irrelevant, since no conversions will be taking place.  */
+
+const struct floatformat floatformat_unknown;
+
+/* Registers we shouldn't try to store.  */
+#if !defined (CANNOT_STORE_REGISTER)
+#define CANNOT_STORE_REGISTER(regno) 0
+#endif
 
 static void write_register_pid PARAMS ((int regno, LONGEST val, int pid));
 
@@ -49,7 +62,7 @@ extract_signed_integer (addr, len)
   unsigned char *startaddr = (unsigned char *)addr;
   unsigned char *endaddr = startaddr + len;
 
-  if (len > sizeof (LONGEST))
+  if (len > (int) sizeof (LONGEST))
     error ("\
 That operation is not available on integers of more than %d bytes.",
           sizeof (LONGEST));
@@ -85,7 +98,7 @@ extract_unsigned_integer (addr, len)
   unsigned char *startaddr = (unsigned char *)addr;
   unsigned char *endaddr = startaddr + len;
 
-  if (len > sizeof (unsigned LONGEST))
+  if (len > (int) sizeof (unsigned LONGEST))
     error ("\
 That operation is not available on integers of more than %d bytes.",
           sizeof (unsigned LONGEST));
@@ -106,6 +119,58 @@ That operation is not available on integers of more than %d bytes.",
   return retval;
 }
 
+/* Sometimes a long long unsigned integer can be extracted as a
+   LONGEST value.  This is done so that we can print these values
+   better.  If this integer can be converted to a LONGEST, this
+   function returns 1 and sets *PVAL.  Otherwise it returns 0.  */
+
+int
+extract_long_unsigned_integer (addr, orig_len, pval)
+     PTR addr;
+     int orig_len;
+     LONGEST *pval;
+{
+  char *p, *first_addr;
+  int len;
+
+  len = orig_len;
+  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+    {
+      for (p = (char *) addr;
+          len > (int) sizeof (LONGEST) && p < (char *) addr + orig_len;
+          p++)
+       {
+         if (*p == 0)
+           len--;
+         else
+           break;
+       }
+      first_addr = p;
+    }
+  else
+    {
+      first_addr = (char *) addr;
+      for (p = (char *) addr + orig_len - 1;
+          len > (int) sizeof (LONGEST) && p >= (char *) addr;
+          p--)
+       {
+         if (*p == 0)
+           len--;
+         else
+           break;
+       }
+    }
+
+  if (len <= (int) sizeof (LONGEST))
+    {
+      *pval = (LONGEST) extract_unsigned_integer (first_addr,
+                                                 sizeof (LONGEST));
+      return 1;
+    }
+
+  return 0;
+}
+
 CORE_ADDR
 extract_address (addr, len)
      PTR addr;
@@ -187,9 +252,27 @@ store_address (addr, len, val)
   store_unsigned_integer (addr, len, (LONGEST)val);
 }
 \f
-
-/* There are many problems with floating point cross-debugging
-   in macro SWAP_TARGET_AND_HOST().
+/* Swap LEN bytes at BUFFER between target and host byte-order.  */
+#define SWAP_FLOATING(buffer,len) \
+  do                                                                    \
+    {                                                                   \
+      if (TARGET_BYTE_ORDER != HOST_BYTE_ORDER)                         \
+        {                                                               \
+          char tmp;                                                     \
+          char *p = (char *)(buffer);                                   \
+          char *q = ((char *)(buffer)) + len - 1;                       \
+          for (; p < q; p++, q--)                                       \
+            {                                                           \
+              tmp = *q;                                                 \
+              *q = *p;                                                  \
+              *p = tmp;                                                 \
+            }                                                           \
+        }                                                               \
+    }                                                                   \
+  while (0)
+
+/* There are various problems with the extract_floating and store_floating
+   routines.
 
    1.  These routines only handle byte-swapping, not conversion of
    formats.  So if host is IEEE floating and target is VAX floating,
@@ -204,47 +287,91 @@ store_address (addr, len, val)
    3.  We probably should have a LONGEST_DOUBLE or DOUBLEST or whatever
    we want to call it which is long double where available.  */
 
-double
+DOUBLEST
 extract_floating (addr, len)
      PTR addr;
      int len;
 {
+  DOUBLEST dretval;
+
   if (len == sizeof (float))
     {
-      float retval;
-      memcpy (&retval, addr, sizeof (retval));
-      SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
-      return retval;
+      if (HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT)
+       {
+         float retval;
+
+         memcpy (&retval, addr, sizeof (retval));
+         return retval;
+       }
+      else
+       FLOATFORMAT_TO_DOUBLEST (TARGET_FLOAT_FORMAT, addr, &dretval);
     }
   else if (len == sizeof (double))
     {
-      double retval;
-      memcpy (&retval, addr, sizeof (retval));
-      SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
-      return retval;
+      if (HOST_DOUBLE_FORMAT == TARGET_DOUBLE_FORMAT)
+       {
+         double retval;
+
+         memcpy (&retval, addr, sizeof (retval));
+         return retval;
+       }
+      else
+       FLOATFORMAT_TO_DOUBLEST (TARGET_DOUBLE_FORMAT, addr, &dretval);
+    }
+  else if (len == sizeof (DOUBLEST))
+    {
+      if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT)
+       {
+         DOUBLEST retval;
+
+         memcpy (&retval, addr, sizeof (retval));
+         return retval;
+       }
+      else
+       FLOATFORMAT_TO_DOUBLEST (TARGET_LONG_DOUBLE_FORMAT, addr, &dretval);
     }
   else
     {
       error ("Can't deal with a floating point number of %d bytes.", len);
     }
+
+  return dretval;
 }
 
 void
 store_floating (addr, len, val)
      PTR addr;
      int len;
-     double val;
+     DOUBLEST val;
 {
   if (len == sizeof (float))
     {
-      float floatval = val;
-      SWAP_TARGET_AND_HOST (&floatval, sizeof (floatval));
-      memcpy (addr, &floatval, sizeof (floatval));
+      if (HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT)
+       {
+         float floatval = val;
+
+         memcpy (addr, &floatval, sizeof (floatval));
+       }
+      else
+       FLOATFORMAT_FROM_DOUBLEST (TARGET_FLOAT_FORMAT, &val, addr);
     }
   else if (len == sizeof (double))
     {
-      SWAP_TARGET_AND_HOST (&val, sizeof (val));
-      memcpy (addr, &val, sizeof (val));
+      if (HOST_DOUBLE_FORMAT == TARGET_DOUBLE_FORMAT)
+       {
+         double doubleval = val;
+
+         memcpy (addr, &doubleval, sizeof (doubleval));
+       }
+      else
+       FLOATFORMAT_FROM_DOUBLEST (TARGET_DOUBLE_FORMAT, &val, addr);
+    }
+  else if (len == sizeof (DOUBLEST))
+    {
+      if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT)
+       memcpy (addr, &val, sizeof (val));
+      else
+       FLOATFORMAT_FROM_DOUBLEST (TARGET_LONG_DOUBLE_FORMAT, &val, addr);
     }
   else
     {
@@ -480,6 +607,9 @@ registers_changed ()
 
   for (i = 0; i < numregs; i++)
     register_valid[i] = 0;
+
+  if (registers_changed_hook)
+    registers_changed_hook ();
 }
 
 /* Indicate that all registers have been fetched, so mark them all valid.  */
@@ -492,18 +622,33 @@ registers_fetched ()
     register_valid[i] = 1;
 }
 
-/* Copy LEN bytes of consecutive data from registers
-   starting with the REGBYTE'th byte of register data
+/* read_register_bytes and write_register_bytes are generally a *BAD* idea.
+   They are inefficient because they need to check for partial updates, which
+   can only be done by scanning through all of the registers and seeing if the
+   bytes that are being read/written fall inside of an invalid register.  [The
+    main reason this is necessary is that register sizes can vary, so a simple
+    index won't suffice.]  It is far better to call read_register_gen if you
+   want to get at the raw register contents, as it only takes a regno as an
+   argument, and therefore can't do a partial register update.  It would also
+   be good to have a write_register_gen for similar reasons.
+
+   Prior to the recent fixes to check for partial updates, both read and
+   write_register_bytes always checked to see if any registers were stale, and
+   then called target_fetch_registers (-1) to update the whole set.  This
+   caused really slowed things down for remote targets.  */
+
+/* Copy INLEN bytes of consecutive data from registers
+   starting with the INREGBYTE'th byte of register data
    into memory at MYADDR.  */
 
 void
-read_register_bytes (regbyte, myaddr, len)
-     int regbyte;
+read_register_bytes (inregbyte, myaddr, inlen)
+     int inregbyte;
      char *myaddr;
-     int len;
+     int inlen;
 {
-  /* Fetch all registers.  */
-  int i, numregs;
+  int inregend = inregbyte + inlen;
+  int regno;
 
   if (registers_pid != inferior_pid)
     {
@@ -511,15 +656,37 @@ read_register_bytes (regbyte, myaddr, len)
       registers_pid = inferior_pid;
     }
 
-  numregs = ARCH_NUM_REGS;
-  for (i = 0; i < numregs; i++)
-    if (!register_valid[i])
-      {
-       target_fetch_registers (-1);
-       break;
-      }
+  /* See if we are trying to read bytes from out-of-date registers.  If so,
+     update just those registers.  */
+
+  for (regno = 0; regno < NUM_REGS; regno++)
+    {
+      int regstart, regend;
+      int startin, endin;
+
+      if (register_valid[regno])
+       continue;
+
+      regstart = REGISTER_BYTE (regno);
+      regend = regstart + REGISTER_RAW_SIZE (regno);
+
+      startin = regstart >= inregbyte && regstart < inregend;
+      endin = regend > inregbyte && regend <= inregend;
+
+      if (!startin && !endin)
+       continue;
+
+      /* We've found an invalid register where at least one byte will be read.
+        Update it from the target.  */
+
+      target_fetch_registers (regno);
+
+      if (!register_valid[regno])
+       error ("read_register_bytes:  Couldn't update register %d.", regno);
+    }
+
   if (myaddr != NULL)
-    memcpy (myaddr, &registers[regbyte], len);
+    memcpy (myaddr, &registers[inregbyte], inlen);
 }
 
 /* Read register REGNO into memory at MYADDR, which must be large enough
@@ -543,25 +710,99 @@ read_register_gen (regno, myaddr)
          REGISTER_RAW_SIZE (regno));
 }
 
-/* Copy LEN bytes of consecutive data from memory at MYADDR
-   into registers starting with the REGBYTE'th byte of register data.  */
+/* Write register REGNO at MYADDR to the target.  MYADDR points at
+   REGISTER_RAW_BYTES(REGNO), which must be in target byte-order.  */
 
 void
-write_register_bytes (regbyte, myaddr, len)
-     int regbyte;
+write_register_gen (regno, myaddr)
+     int regno;
      char *myaddr;
-     int len;
 {
+  int size;
+
+  /* On the sparc, writing %g0 is a no-op, so we don't even want to change
+     the registers array if something writes to this register.  */
+  if (CANNOT_STORE_REGISTER (regno))
+    return;
+
   if (registers_pid != inferior_pid)
     {
       registers_changed ();
       registers_pid = inferior_pid;
     }
 
-  /* Make sure the entire registers array is valid.  */
-  read_register_bytes (0, (char *)NULL, REGISTER_BYTES);
-  memcpy (&registers[regbyte], myaddr, len);
-  target_store_registers (-1);
+  size = REGISTER_RAW_SIZE(regno);
+
+  /* If we have a valid copy of the register, and new value == old value,
+     then don't bother doing the actual store. */
+
+  if (register_valid [regno]
+      && memcmp (&registers[REGISTER_BYTE (regno)], myaddr, size) == 0)
+    return;
+  
+  target_prepare_to_store ();
+
+  memcpy (&registers[REGISTER_BYTE (regno)], myaddr, size);
+
+  register_valid [regno] = 1;
+
+  target_store_registers (regno);
+}
+
+/* Copy INLEN bytes of consecutive data from memory at MYADDR
+   into registers starting with the MYREGSTART'th byte of register data.  */
+
+void
+write_register_bytes (myregstart, myaddr, inlen)
+     int myregstart;
+     char *myaddr;
+     int inlen;
+{
+  int myregend = myregstart + inlen;
+  int regno;
+
+  target_prepare_to_store ();
+
+  /* Scan through the registers updating any that are covered by the range
+     myregstart<=>myregend using write_register_gen, which does nice things
+     like handling threads, and avoiding updates when the new and old contents
+     are the same.  */
+
+  for (regno = 0; regno < NUM_REGS; regno++)
+    {
+      int regstart, regend;
+      int startin, endin;
+      char regbuf[MAX_REGISTER_RAW_SIZE];
+
+      regstart = REGISTER_BYTE (regno);
+      regend = regstart + REGISTER_RAW_SIZE (regno);
+
+      startin = regstart >= myregstart && regstart < myregend;
+      endin = regend > myregstart && regend <= myregend;
+
+      if (!startin && !endin)
+       continue;               /* Register is completely out of range */
+
+      if (startin && endin)    /* register is completely in range */
+       {
+         write_register_gen (regno, myaddr + (regstart - myregstart));
+         continue;
+       }
+
+      /* We may be doing a partial update of an invalid register.  Update it
+        from the target before scribbling on it.  */
+      read_register_gen (regno, regbuf);
+
+      if (startin)
+       memcpy (registers + regstart,
+               myaddr + regstart - myregstart,
+               myregend - regstart);
+      else                     /* endin */
+       memcpy (registers + myregstart,
+               myaddr,
+               regend - myregstart);
+      target_store_registers (regno);
+    }
 }
 
 /* Return the raw contents of register REGNO, regarding it as an integer.  */
@@ -605,13 +846,7 @@ read_register_pid (regno, pid)
   return retval;
 }
 
-/* Registers we shouldn't try to store.  */
-#if !defined (CANNOT_STORE_REGISTER)
-#define CANNOT_STORE_REGISTER(regno) 0
-#endif
-
 /* Store VALUE, into the raw contents of register number REGNO.  */
-/* FIXME: The val arg should probably be a LONGEST.  */
 
 void
 write_register (regno, val)
@@ -839,6 +1074,7 @@ symbol_read_needs_frame (sym)
 
     case LOC_BLOCK:
     case LOC_CONST_BYTES:
+    case LOC_UNRESOLVED:
     case LOC_OPTIMIZED_OUT:
       return 0;
     }
@@ -966,6 +1202,17 @@ read_var_value (var, frame)
       }
       break;
 
+    case LOC_UNRESOLVED:
+      {
+       struct minimal_symbol *msym;
+
+       msym = lookup_minimal_symbol (SYMBOL_NAME (var), NULL, NULL);
+       if (msym == NULL)
+         return 0;
+       addr = SYMBOL_VALUE_ADDRESS (msym);
+      }
+      break;
+
     case LOC_OPTIMIZED_OUT:
       VALUE_LVAL (v) = not_lval;
       VALUE_OPTIMIZED_OUT (v) = 1;
@@ -994,11 +1241,14 @@ value_from_register (type, regnum, frame)
   CORE_ADDR addr;
   int optim;
   value_ptr v = allocate_value (type);
-  int len = TYPE_LENGTH (type);
   char *value_bytes = 0;
   int value_bytes_copied = 0;
   int num_storage_locs;
   enum lval_type lval;
+  int len;
+
+  CHECK_TYPEDEF (type);
+  len = TYPE_LENGTH (type);
 
   VALUE_REGNO (v) = regnum;
 
This page took 0.03062 seconds and 4 git commands to generate.