/* Find a variable's value in memory, for GDB, the GNU debugger.
- Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996 Free Software Foundation, Inc.
+ Copyright 1986, 87, 89, 91, 94, 95, 96, 1998
+ Free Software Foundation, Inc.
This file is part of GDB.
#include "target.h"
#include "gdb_string.h"
#include "floatformat.h"
+#include "symfile.h" /* for overlay functions */
/* 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
const struct floatformat floatformat_unknown;
-#ifdef HAVE_LONG_DOUBLE
-void (*floatformat_to_doublest)
- PARAMS ((const struct floatformat *,
- char *, DOUBLEST *)) = floatformat_to_long_double;
-void (*floatformat_from_doublest)
- PARAMS ((const struct floatformat *,
- DOUBLEST *, char *)) = floatformat_from_long_double;
-#else
-void (*floatformat_to_doublest)
- PARAMS ((const struct floatformat *,
- char *, DOUBLEST *)) = floatformat_to_double;
-void (*floatformat_from_doublest)
- PARAMS ((const struct floatformat *,
- DOUBLEST *, char *)) = floatformat_from_double;
-#endif
-
/* 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));
+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. */
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 > (int) 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. */
store_unsigned_integer (addr, len, val)
PTR addr;
int len;
- unsigned LONGEST val;
+ ULONGEST val;
{
unsigned char *p;
unsigned char *startaddr = (unsigned char *)addr;
} \
while (0)
-/* There are various problems with the extract_floating and store_floating
- routines.
+/* Extract a floating-point number from a target-order byte-stream at ADDR.
+ Returns the value as type DOUBLEST.
- 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.
-
- 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.
-
- 3. We probably should have a LONGEST_DOUBLE or DOUBLEST or whatever
- we want to call it which is long double where available. */
+ 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. */
DOUBLEST
extract_floating (addr, len)
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)
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. */
}
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;
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'. */
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 (register_valid[regno])
continue;
+ if (REGISTER_NAME (regno) == NULL || *REGISTER_NAME (regno) == '\0')
+ continue;
+
regstart = REGISTER_BYTE (regno);
regend = regstart + REGISTER_RAW_SIZE (regno);
/* Write register REGNO at MYADDR to the target. MYADDR points at
REGISTER_RAW_BYTES(REGNO), which must be in target byte-order. */
-void
+static void
write_register_gen (regno, myaddr)
int regno;
char *myaddr;
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
target_store_registers (regno);
}
-static void
+void
write_register_pid (regno, val, pid)
int regno;
LONGEST val;
/* 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 (®isters[REGISTER_BYTE (regno)], val, REGISTER_RAW_SIZE (regno));
+ if (val)
+ memcpy (®isters[REGISTER_BYTE (regno)], val, REGISTER_RAW_SIZE (regno));
+ else
+ memset (®isters[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. */
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;
#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
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;
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;
}
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:
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:
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;
msym = lookup_minimal_symbol (SYMBOL_NAME (var), NULL, NULL);
if (msym == NULL)
return 0;
- addr = SYMBOL_VALUE_ADDRESS (msym);
+ if (overlay_debugging)
+ addr = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (msym),
+ SYMBOL_BFD_SECTION (msym));
+ else
+ addr = SYMBOL_VALUE_ADDRESS (msym);
}
break;
}
/* 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)
page_regnum,
&lval);
+ if (register_valid[page_regnum] == -1)
+ return NULL; /* register value not available */
+
if (lval == lval_register)
reg_stor++;
else
regnum,
&lval);
+ if (register_valid[regnum] == -1)
+ return NULL; /* register value not available */
+
if (lval == lval_register)
reg_stor++;
else
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)
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;
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. */