1999-01-19 Fernando Nasser <fnasser@totem.to.cygnus.com>
[deliverable/binutils-gdb.git] / gdb / findvar.c
index 591dc7f987f863c32398f1297565278e436f09cf..298abf7d631aaa38b13a16de825b003c4650e7e2 100644 (file)
@@ -1,5 +1,6 @@
 /* Find a variable's value in memory, for GDB, the GNU debugger.
-   Copyright 1986, 1987, 1989, 1991, 1994, 1995 Free Software Foundation, Inc.
+   Copyright 1986, 87, 89, 91, 94, 95, 96, 1998
+   Free Software Foundation, Inc.
 
 This file is part of GDB.
 
@@ -15,7 +16,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,9 +26,23 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "gdbcore.h"
 #include "inferior.h"
 #include "target.h"
-#include <string.h>
+#include "gdb_string.h"
+#include "floatformat.h"
+#include "symfile.h"   /* for overlay functions */
 
-static void write_register_pid PARAMS ((int regno, LONGEST val, int pid));
+/* 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_gen PARAMS ((int, char *));
 
 /* Basic byte-swapping routines.  GDB has needed these for a long time...
    All extract a target-format integer at ADDR which is LEN bytes long.  */
@@ -50,7 +65,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));
@@ -76,20 +91,20 @@ That operation is not available on integers of more than %d bytes.",
   return retval;
 }
 
-unsigned LONGEST
+ULONGEST
 extract_unsigned_integer (addr, len)
      PTR addr;
      int len;
 {
-  unsigned LONGEST retval;
+  ULONGEST retval;
   unsigned char *p;
   unsigned char *startaddr = (unsigned char *)addr;
   unsigned char *endaddr = startaddr + len;
 
-  if (len > sizeof (unsigned LONGEST))
+  if (len > (int) sizeof (ULONGEST))
     error ("\
 That operation is not available on integers of more than %d bytes.",
-          sizeof (unsigned LONGEST));
+          sizeof (ULONGEST));
 
   /* Start at the most significant end of the integer, and work towards
      the least significant.  */
@@ -107,6 +122,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;
@@ -151,7 +218,7 @@ void
 store_unsigned_integer (addr, len, val)
      PTR addr;
      int len;
-     unsigned LONGEST val;
+     ULONGEST val;
 {
   unsigned char *p;
   unsigned char *startaddr = (unsigned char *)addr;
@@ -207,63 +274,99 @@ store_address (addr, len, val)
     }                                                                   \
   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,
-   or vice-versa, it loses.  This means that we can't (yet) use these
-   routines for extendeds.  Extendeds are handled by
-   REGISTER_CONVERTIBLE.  What we want is to use floatformat.h, but that
-   doesn't yet handle VAX floating at all.
+/* Extract a floating-point number from a target-order byte-stream at ADDR.
+   Returns the value as type DOUBLEST.
 
-   2.  We can't deal with it if there is more than one floating point
-   format in use.  This has to be fixed at the unpack_double level.
+   If the host and target formats agree, we just copy the raw data into the
+   appropriate type of variable and return, letting the host increase precision
+   as necessary.  Otherwise, we call the conversion routine and let it do the
+   dirty work.  */
 
-   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_FLOATING (&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_FLOATING (&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_FLOATING (&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_FLOATING (&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
     {
@@ -427,12 +530,19 @@ read_relative_register_raw_bytes (regnum, myaddr)
 
   get_saved_register (myaddr, &optim, (CORE_ADDR *) NULL, selected_frame,
                       regnum, (enum lval_type *)NULL);
+
+  if (register_valid [regnum] < 0)
+    return 1;  /* register value not available */
+
   return optim;
 }
 
 /* Return a `value' with the contents of register REGNUM
    in its virtual format, with the type specified by
-   REGISTER_VIRTUAL_TYPE.  */
+   REGISTER_VIRTUAL_TYPE.  
+
+   NOTE: returns NULL if register value is not available.
+   Caller will check return value or die!  */
 
 value_ptr
 value_of_register (regnum)
@@ -447,6 +557,9 @@ value_of_register (regnum)
   get_saved_register (raw_buffer, &optim, &addr,
                      selected_frame, regnum, &lval);
 
+  if (register_valid[regnum] < 0)
+    return NULL;       /* register value not available */
+
   reg_val = allocate_value (REGISTER_VIRTUAL_TYPE (regnum));
 
   /* Convert raw data to virtual format if necessary.  */
@@ -459,8 +572,13 @@ value_of_register (regnum)
     }
   else
 #endif
-    memcpy (VALUE_CONTENTS_RAW (reg_val), raw_buffer,
-           REGISTER_RAW_SIZE (regnum));
+    if (REGISTER_RAW_SIZE (regnum) == REGISTER_VIRTUAL_SIZE (regnum))
+      memcpy (VALUE_CONTENTS_RAW (reg_val), raw_buffer,
+             REGISTER_RAW_SIZE (regnum));
+    else
+      fatal ("Register \"%s\" (%d) has conflicting raw (%d) and virtual (%d) size",
+            REGISTER_NAME (regnum), regnum,
+            REGISTER_RAW_SIZE (regnum), REGISTER_VIRTUAL_SIZE (regnum));
   VALUE_LVAL (reg_val) = lval;
   VALUE_ADDRESS (reg_val) = addr;
   VALUE_REGNO (reg_val) = regnum;
@@ -476,12 +594,14 @@ value_of_register (regnum)
    the caller got the value from the last stop).  */
 
 /* Contents of the registers in target byte order.
-   We allocate some extra slop since we do a lot of memcpy's around `registers',
-   and failing-soft is better than failing hard.  */
+   We allocate some extra slop since we do a lot of memcpy's around 
+   `registers', and failing-soft is better than failing hard.  */
+
 char registers[REGISTER_BYTES + /* SLOP */ 256];
 
-/* Nonzero if that register has been fetched.  */
-char register_valid[NUM_REGS];
+/* Nonzero if that register has been fetched,
+   -1 if register value not available. */
+SIGNED char register_valid[NUM_REGS];
 
 /* The thread/process associated with the current set of registers.  For now,
    -1 is special, and means `no current process'.  */
@@ -497,8 +617,18 @@ registers_changed ()
 
   registers_pid = -1;
 
+  /* Force cleanup of any alloca areas if using C alloca instead of
+     a builtin alloca.  This particular call is used to clean up
+     areas allocated by low level target code which may build up
+     during lengthy interactions between gdb and the target before
+     gdb gives control to the user (ie watchpoints).  */
+  alloca (0);
+
   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.  */
@@ -511,18 +641,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)
     {
@@ -530,15 +675,40 @@ 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;
+
+      if (REGISTER_NAME (regno) == NULL || *REGISTER_NAME (regno) == '\0')
+       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
@@ -562,25 +732,102 @@ 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;
+static void
+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);
+
+  if (regno == PC_REGNUM && pc_changed_hook)
+    pc_changed_hook ();
+}
+
+/* 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.  */
@@ -624,11 +871,6 @@ 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.  */
 
 void
@@ -670,7 +912,7 @@ write_register (regno, val)
   target_store_registers (regno);
 }
 
-static void
+void
 write_register_pid (regno, val, pid)
      int regno;
      LONGEST val;
@@ -695,21 +937,31 @@ write_register_pid (regno, val, pid)
 
 /* Record that register REGNO contains VAL.
    This is used when the value is obtained from the inferior or core dump,
-   so there is no need to store the value there.  */
+   so there is no need to store the value there.
+
+   If VAL is a NULL pointer, then it's probably an unsupported register.  We
+   just set it's value to all zeros.  We might want to record this fact, and
+   report it to the users of read_register and friends.
+*/
 
 void
 supply_register (regno, val)
      int regno;
      char *val;
 {
+#if 1
   if (registers_pid != inferior_pid)
     {
       registers_changed ();
       registers_pid = inferior_pid;
     }
+#endif
 
   register_valid[regno] = 1;
-  memcpy (&registers[REGISTER_BYTE (regno)], val, REGISTER_RAW_SIZE (regno));
+  if (val)
+    memcpy (&registers[REGISTER_BYTE (regno)], val, REGISTER_RAW_SIZE (regno));
+  else
+    memset (&registers[REGISTER_BYTE (regno)], '\000', REGISTER_RAW_SIZE (regno));
 
   /* On some architectures, e.g. HPPA, there are a few stray bits in some
      registers, that the rest of the code would like to ignore.  */
@@ -723,16 +975,6 @@ supply_register (regno, val)
    time to turn this into READ_PC and define it in the tm.h file.
    Ditto for write_pc.  */
 
-CORE_ADDR
-read_pc ()
-{
-#ifdef TARGET_READ_PC
-  return TARGET_READ_PC (inferior_pid);
-#else
-  return ADDR_BITS_REMOVE ((CORE_ADDR) read_register_pid (PC_REGNUM, inferior_pid));
-#endif
-}
-
 CORE_ADDR
 read_pc_pid (pid)
      int pid;
@@ -744,41 +986,37 @@ read_pc_pid (pid)
 #endif
 }
 
-void
-write_pc (val)
-     CORE_ADDR val;
+CORE_ADDR
+read_pc ()
 {
-#ifdef TARGET_WRITE_PC
-  TARGET_WRITE_PC (val, inferior_pid);
-#else
-  write_register_pid (PC_REGNUM, val, inferior_pid);
-#ifdef NPC_REGNUM
-  write_register_pid (NPC_REGNUM, val + 4, inferior_pid);
-#ifdef NNPC_REGNUM
-  write_register_pid (NNPC_REGNUM, val + 8, inferior_pid);
-#endif
-#endif
-#endif
+  return read_pc_pid (inferior_pid);
 }
 
 void
-write_pc_pid (val, pid)
-     CORE_ADDR val;
+write_pc_pid (pc, pid)
+     CORE_ADDR pc;
      int pid;
 {
 #ifdef TARGET_WRITE_PC
-  TARGET_WRITE_PC (val, pid);
+  TARGET_WRITE_PC (pc, pid);
 #else
-  write_register_pid (PC_REGNUM, val, pid);
+  write_register_pid (PC_REGNUM, pc, pid);
 #ifdef NPC_REGNUM
-  write_register_pid (NPC_REGNUM, val + 4, pid);
+  write_register_pid (NPC_REGNUM, pc + 4, pid);
 #ifdef NNPC_REGNUM
-  write_register_pid (NNPC_REGNUM, val + 8, pid);
+  write_register_pid (NNPC_REGNUM, pc + 8, pid);
 #endif
 #endif
 #endif
 }
 
+void
+write_pc (pc)
+     CORE_ADDR pc;
+{
+  write_pc_pid (pc, inferior_pid);
+}
+
 /* Cope with strage ways of getting to the stack and frame pointers */
 
 CORE_ADDR
@@ -857,6 +1095,7 @@ symbol_read_needs_frame (sym)
 
     case LOC_BLOCK:
     case LOC_CONST_BYTES:
+    case LOC_UNRESOLVED:
     case LOC_OPTIMIZED_OUT:
       return 0;
     }
@@ -881,6 +1120,8 @@ read_var_value (var, frame)
 
   v = allocate_value (type);
   VALUE_LVAL (v) = lval_memory;        /* The most likely possibility.  */
+  VALUE_BFD_SECTION (v) = SYMBOL_BFD_SECTION (var);
+
   len = TYPE_LENGTH (type);
 
   if (frame == NULL) frame = selected_frame;
@@ -896,7 +1137,13 @@ read_var_value (var, frame)
 
     case LOC_LABEL:
       /* Put the constant back in target format.  */
-      store_address (VALUE_CONTENTS_RAW (v), len, SYMBOL_VALUE_ADDRESS (var));
+      if (overlay_debugging)
+       store_address (VALUE_CONTENTS_RAW (v), len, 
+                      symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var),
+                                                SYMBOL_BFD_SECTION (var)));
+      else
+       store_address (VALUE_CONTENTS_RAW (v), len, 
+                      SYMBOL_VALUE_ADDRESS (var));
       VALUE_LVAL (v) = not_lval;
       return v;
 
@@ -910,7 +1157,11 @@ read_var_value (var, frame)
       }
 
     case LOC_STATIC:
-      addr = SYMBOL_VALUE_ADDRESS (var);
+      if (overlay_debugging)
+       addr = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var),
+                                        SYMBOL_BFD_SECTION (var));
+      else
+       addr = SYMBOL_VALUE_ADDRESS (var);
       break;
 
     case LOC_ARG:
@@ -957,7 +1208,11 @@ read_var_value (var, frame)
       break;
 
     case LOC_BLOCK:
-      VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
+      if (overlay_debugging)
+       VALUE_ADDRESS (v) = symbol_overlayed_address 
+         (BLOCK_START (SYMBOL_BLOCK_VALUE (var)), SYMBOL_BFD_SECTION (var));
+      else
+       VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
       return v;
 
     case LOC_REGISTER:
@@ -965,22 +1220,48 @@ read_var_value (var, frame)
     case LOC_REGPARM_ADDR:
       {
        struct block *b;
+       int regno = SYMBOL_VALUE (var);
+       value_ptr regval;
 
        if (frame == NULL)
          return 0;
        b = get_frame_block (frame);
-       
 
        if (SYMBOL_CLASS (var) == LOC_REGPARM_ADDR)
          {
-           addr =
-             value_as_pointer (value_from_register (lookup_pointer_type (type),
-                                                    SYMBOL_VALUE (var),
-                                                    frame));
+           regval = value_from_register (lookup_pointer_type (type),
+                                         regno, 
+                                         frame);
+
+           if (regval == NULL)
+             error ("Value of register variable not available.");
+
+           addr   = value_as_pointer (regval);
            VALUE_LVAL (v) = lval_memory;
          }
        else
-         return value_from_register (type, SYMBOL_VALUE (var), frame);
+         {
+           regval = value_from_register (type, regno, frame);
+
+           if (regval == NULL)
+             error ("Value of register variable not available.");
+           return regval;
+         }
+      }
+      break;
+
+    case LOC_UNRESOLVED:
+      {
+       struct minimal_symbol *msym;
+
+       msym = lookup_minimal_symbol (SYMBOL_NAME (var), NULL, NULL);
+       if (msym == NULL)
+         return 0;
+       if (overlay_debugging)
+         addr = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (msym),
+                                          SYMBOL_BFD_SECTION (msym));
+       else
+         addr = SYMBOL_VALUE_ADDRESS (msym);
       }
       break;
 
@@ -1000,7 +1281,10 @@ read_var_value (var, frame)
 }
 
 /* Return a value of type TYPE, stored in register REGNUM, in frame
-   FRAME. */
+   FRAME. 
+
+   NOTE: returns NULL if register value is not available.
+   Caller will check return value or die!  */
 
 value_ptr
 value_from_register (type, regnum, frame)
@@ -1012,11 +1296,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;
 
@@ -1076,6 +1363,9 @@ value_from_register (type, regnum, frame)
                              page_regnum,
                              &lval);
 
+         if (register_valid[page_regnum] == -1)
+           return NULL;        /* register value not available */
+
          if (lval == lval_register)
            reg_stor++;
          else
@@ -1090,6 +1380,9 @@ value_from_register (type, regnum, frame)
                              regnum,
                              &lval);
 
+         if (register_valid[regnum] == -1)
+           return NULL;        /* register value not available */
+
          if (lval == lval_register)
            reg_stor++;
          else
@@ -1113,6 +1406,9 @@ value_from_register (type, regnum, frame)
                                local_regnum,
                                &lval);
 
+         if (register_valid[local_regnum] == -1)
+           return NULL;        /* register value not available */
+
            if (regnum == local_regnum)
              first_addr = addr;
            if (lval == lval_register)
@@ -1174,6 +1470,10 @@ value_from_register (type, regnum, frame)
      read the data in raw format.  */
 
   get_saved_register (raw_buffer, &optim, &addr, frame, regnum, &lval);
+
+  if (register_valid[regnum] == -1)
+    return NULL;       /* register value not available */
+
   VALUE_OPTIMIZED_OUT (v) = optim;
   VALUE_LVAL (v) = lval;
   VALUE_ADDRESS (v) = addr;
@@ -1227,8 +1527,12 @@ locate_var_value (var, frame)
   if (VALUE_LAZY (lazy_value)
       || TYPE_CODE (type) == TYPE_CODE_FUNC)
     {
+      value_ptr val;
+
       addr = VALUE_ADDRESS (lazy_value);
-      return value_from_longest (lookup_pointer_type (type), (LONGEST) addr);
+      val =  value_from_longest (lookup_pointer_type (type), (LONGEST) addr);
+      VALUE_BFD_SECTION (val) = VALUE_BFD_SECTION (lazy_value);
+      return val;
     }
 
   /* Not a memory address; check what the problem was.  */
This page took 0.032745 seconds and 4 git commands to generate.