/* 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 Free Software Foundation, Inc.
This file is part of GDB.
#include "gdbcore.h"
#include "inferior.h"
#include "target.h"
+#include <string.h>
+
+static void write_register_pid PARAMS ((int regno, LONGEST val, int pid));
/* 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. */
/* Start at the most significant end of the integer, and work towards
the least significant. */
-#if TARGET_BYTE_ORDER == BIG_ENDIAN
- p = startaddr;
-#else
- p = endaddr - 1;
-#endif
- /* Do the sign extension once at the start. */
- retval = ((LONGEST)*p ^ 0x80) - 0x80;
-#if TARGET_BYTE_ORDER == BIG_ENDIAN
- for (++p; p < endaddr; ++p)
-#else
- for (--p; p >= startaddr; --p)
-#endif
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
{
- retval = (retval << 8) | *p;
+ p = startaddr;
+ /* Do the sign extension once at the start. */
+ retval = ((LONGEST)*p ^ 0x80) - 0x80;
+ for (++p; p < endaddr; ++p)
+ retval = (retval << 8) | *p;
+ }
+ else
+ {
+ p = endaddr - 1;
+ /* Do the sign extension once at the start. */
+ retval = ((LONGEST)*p ^ 0x80) - 0x80;
+ for (--p; p >= startaddr; --p)
+ retval = (retval << 8) | *p;
}
return retval;
}
/* Start at the most significant end of the integer, and work towards
the least significant. */
retval = 0;
-#if TARGET_BYTE_ORDER == BIG_ENDIAN
- for (p = startaddr; p < endaddr; ++p)
-#else
- for (p = endaddr - 1; p >= startaddr; --p)
-#endif
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
{
- retval = (retval << 8) | *p;
+ for (p = startaddr; p < endaddr; ++p)
+ retval = (retval << 8) | *p;
+ }
+ else
+ {
+ for (p = endaddr - 1; p >= startaddr; --p)
+ retval = (retval << 8) | *p;
}
return retval;
}
/* Start at the least significant end of the integer, and work towards
the most significant. */
-#if TARGET_BYTE_ORDER == BIG_ENDIAN
- for (p = endaddr - 1; p >= startaddr; --p)
-#else
- for (p = startaddr; p < endaddr; ++p)
-#endif
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ {
+ for (p = endaddr - 1; p >= startaddr; --p)
+ {
+ *p = val & 0xff;
+ val >>= 8;
+ }
+ }
+ else
{
- *p = val & 0xff;
- val >>= 8;
+ for (p = startaddr; p < endaddr; ++p)
+ {
+ *p = val & 0xff;
+ val >>= 8;
+ }
}
}
/* Start at the least significant end of the integer, and work towards
the most significant. */
-#if TARGET_BYTE_ORDER == BIG_ENDIAN
- for (p = endaddr - 1; p >= startaddr; --p)
-#else
- for (p = startaddr; p < endaddr; ++p)
-#endif
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
{
- *p = val & 0xff;
- val >>= 8;
+ for (p = endaddr - 1; p >= startaddr; --p)
+ {
+ *p = val & 0xff;
+ val >>= 8;
+ }
+ }
+ else
+ {
+ for (p = startaddr; p < endaddr; ++p)
+ {
+ *p = val & 0xff;
+ val >>= 8;
+ }
}
}
store_unsigned_integer (addr, len, (LONGEST)val);
}
\f
-/* Swap LEN bytes at BUFFER between target and host byte-order. This is
- the wrong way to do byte-swapping because it assumes that you have a way
- to have a host variable of exactly the right size. Once extract_floating
- and store_floating have been fixed, this can go away. */
-#if TARGET_BYTE_ORDER == HOST_BYTE_ORDER
-#define SWAP_TARGET_AND_HOST(buffer,len)
-#else /* Target and host byte order differ. */
-#define SWAP_TARGET_AND_HOST(buffer,len) \
- { \
- char tmp; \
- char *p = (char *)(buffer); \
- char *q = ((char *)(buffer)) + len - 1; \
- for (; p < q; p++, q--) \
- { \
- tmp = *q; \
- *q = *p; \
- *p = tmp; \
- } \
- }
-#endif /* Target and host byte order differ. */
-
-/* There are many problems with floating point cross-debugging.
+/* 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,
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 a fixed version of
- ieee-float.c (the current version can't deal with single or double,
- and I suspect it is probably broken for some extendeds too).
+ 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.
{
float retval;
memcpy (&retval, addr, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+ SWAP_FLOATING (&retval, sizeof (retval));
return retval;
}
else if (len == sizeof (double))
{
double retval;
memcpy (&retval, addr, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+ SWAP_FLOATING (&retval, sizeof (retval));
return retval;
}
else
if (len == sizeof (float))
{
float floatval = val;
- SWAP_TARGET_AND_HOST (&floatval, sizeof (floatval));
+ SWAP_FLOATING (&floatval, sizeof (floatval));
memcpy (addr, &floatval, sizeof (floatval));
}
else if (len == sizeof (double))
{
- SWAP_TARGET_AND_HOST (&val, sizeof (val));
+ SWAP_FLOATING (&val, sizeof (val));
memcpy (addr, &val, sizeof (val));
}
else
CORE_ADDR
find_saved_register (frame, regnum)
- FRAME frame;
+ struct frame_info *frame;
int regnum;
{
- struct frame_info *fi;
struct frame_saved_regs saved_regs;
- register FRAME frame1 = 0;
+ register struct frame_info *frame1 = NULL;
register CORE_ADDR addr = 0;
- if (frame == 0) /* No regs saved if want current frame */
+ if (frame == NULL) /* No regs saved if want current frame */
return 0;
#ifdef HAVE_REGISTER_WINDOWS
stack pointer saved for *this* frame; this is returned from the
next frame. */
-
if (REGISTER_IN_WINDOW_P(regnum))
{
frame1 = get_next_frame (frame);
- if (!frame1) return 0; /* Registers of this frame are
- active. */
+ if (!frame1) return 0; /* Registers of this frame are active. */
/* Get the SP from the next frame in; it will be this
current frame. */
if (regnum != SP_REGNUM)
frame1 = frame;
- fi = get_frame_info (frame1);
- get_frame_saved_regs (fi, &saved_regs);
+ get_frame_saved_regs (frame1, &saved_regs);
return saved_regs.regs[regnum]; /* ... which might be zero */
}
#endif /* HAVE_REGISTER_WINDOWS */
frame1 = get_prev_frame (frame1);
if (frame1 == 0 || frame1 == frame)
break;
- fi = get_frame_info (frame1);
- get_frame_saved_regs (fi, &saved_regs);
+ get_frame_saved_regs (frame1, &saved_regs);
if (saved_regs.regs[regnum])
addr = saved_regs.regs[regnum];
}
char *raw_buffer;
int *optimized;
CORE_ADDR *addrp;
- FRAME frame;
+ struct frame_info *frame;
int regnum;
enum lval_type *lval;
{
CORE_ADDR addr;
+
+ if (!target_has_registers)
+ error ("No registers.");
+
/* Normal systems don't optimize out things with register numbers. */
if (optimized != NULL)
*optimized = 0;
in its virtual format, with the type specified by
REGISTER_VIRTUAL_TYPE. */
-value
+value_ptr
value_of_register (regnum)
int regnum;
{
CORE_ADDR addr;
int optim;
- register value val;
+ register value_ptr reg_val;
char raw_buffer[MAX_REGISTER_RAW_SIZE];
enum lval_type lval;
get_saved_register (raw_buffer, &optim, &addr,
selected_frame, regnum, &lval);
- val = allocate_value (REGISTER_VIRTUAL_TYPE (regnum));
+ reg_val = allocate_value (REGISTER_VIRTUAL_TYPE (regnum));
/* Convert raw data to virtual format if necessary. */
if (REGISTER_CONVERTIBLE (regnum))
{
REGISTER_CONVERT_TO_VIRTUAL (regnum, REGISTER_VIRTUAL_TYPE (regnum),
- raw_buffer, VALUE_CONTENTS_RAW (val));
+ raw_buffer, VALUE_CONTENTS_RAW (reg_val));
}
else
#endif
- memcpy (VALUE_CONTENTS_RAW (val), raw_buffer,
+ memcpy (VALUE_CONTENTS_RAW (reg_val), raw_buffer,
REGISTER_RAW_SIZE (regnum));
- VALUE_LVAL (val) = lval;
- VALUE_ADDRESS (val) = addr;
- VALUE_REGNO (val) = regnum;
- VALUE_OPTIMIZED_OUT (val) = optim;
- return val;
+ VALUE_LVAL (reg_val) = lval;
+ VALUE_ADDRESS (reg_val) = addr;
+ VALUE_REGNO (reg_val) = regnum;
+ VALUE_OPTIMIZED_OUT (reg_val) = optim;
+ return reg_val;
}
\f
/* Low level examining and depositing of registers.
/* Nonzero if that register has been fetched. */
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'. */
+int registers_pid = -1;
+
/* Indicate that registers may have changed, so invalidate the cache. */
+
void
registers_changed ()
{
int i;
- for (i = 0; i < NUM_REGS; i++)
+ int numregs = ARCH_NUM_REGS;
+
+ registers_pid = -1;
+
+ for (i = 0; i < numregs; i++)
register_valid[i] = 0;
}
registers_fetched ()
{
int i;
- for (i = 0; i < NUM_REGS; i++)
+ int numregs = ARCH_NUM_REGS;
+ for (i = 0; i < numregs; i++)
register_valid[i] = 1;
}
int len;
{
/* Fetch all registers. */
- int i;
- for (i = 0; i < NUM_REGS; i++)
+ int i, numregs;
+
+ if (registers_pid != inferior_pid)
+ {
+ registers_changed ();
+ registers_pid = inferior_pid;
+ }
+
+ numregs = ARCH_NUM_REGS;
+ for (i = 0; i < numregs; i++)
if (!register_valid[i])
{
target_fetch_registers (-1);
int regno;
char *myaddr;
{
+ if (registers_pid != inferior_pid)
+ {
+ registers_changed ();
+ registers_pid = inferior_pid;
+ }
+
if (!register_valid[regno])
target_fetch_registers (regno);
memcpy (myaddr, ®isters[REGISTER_BYTE (regno)],
char *myaddr;
int len;
{
+ 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 (®isters[regbyte], myaddr, len);
read_register (regno)
int regno;
{
+ if (registers_pid != inferior_pid)
+ {
+ registers_changed ();
+ registers_pid = inferior_pid;
+ }
+
if (!register_valid[regno])
target_fetch_registers (regno);
REGISTER_RAW_SIZE(regno));
}
+CORE_ADDR
+read_register_pid (regno, pid)
+ int regno, pid;
+{
+ int save_pid;
+ CORE_ADDR retval;
+
+ if (pid == inferior_pid)
+ return read_register (regno);
+
+ save_pid = inferior_pid;
+
+ inferior_pid = pid;
+
+ retval = read_register (regno);
+
+ inferior_pid = save_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)
if (CANNOT_STORE_REGISTER (regno))
return;
+ if (registers_pid != inferior_pid)
+ {
+ registers_changed ();
+ registers_pid = inferior_pid;
+ }
+
size = REGISTER_RAW_SIZE(regno);
buf = alloca (size);
store_signed_integer (buf, size, (LONGEST) val);
/* 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])
- {
- if (memcmp (®isters[REGISTER_BYTE (regno)], buf, size) == 0)
- return;
- }
+ if (register_valid [regno]
+ && memcmp (®isters[REGISTER_BYTE (regno)], buf, size) == 0)
+ return;
target_prepare_to_store ();
target_store_registers (regno);
}
+static void
+write_register_pid (regno, val, pid)
+ int regno;
+ LONGEST val;
+ int pid;
+{
+ int save_pid;
+
+ if (pid == inferior_pid)
+ {
+ write_register (regno, val);
+ return;
+ }
+
+ save_pid = inferior_pid;
+
+ inferior_pid = pid;
+
+ write_register (regno, val);
+
+ inferior_pid = save_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. */
int regno;
char *val;
{
+ if (registers_pid != inferior_pid)
+ {
+ registers_changed ();
+ registers_pid = inferior_pid;
+ }
+
register_valid[regno] = 1;
memcpy (®isters[REGISTER_BYTE (regno)], val, REGISTER_RAW_SIZE (regno));
CLEAN_UP_REGISTER_VALUE(regno, ®isters[REGISTER_BYTE(regno)]);
#endif
}
+
+
+/* This routine is getting awfully cluttered with #if's. It's probably
+ 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;
+{
+#ifdef TARGET_READ_PC
+ return TARGET_READ_PC (pid);
+#else
+ return ADDR_BITS_REMOVE ((CORE_ADDR) read_register_pid (PC_REGNUM, pid));
+#endif
+}
+
+void
+write_pc (val)
+ CORE_ADDR val;
+{
+#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
+}
+
+void
+write_pc_pid (val, pid)
+ CORE_ADDR val;
+ int pid;
+{
+#ifdef TARGET_WRITE_PC
+ TARGET_WRITE_PC (val, pid);
+#else
+ write_register_pid (PC_REGNUM, val, pid);
+#ifdef NPC_REGNUM
+ write_register_pid (NPC_REGNUM, val + 4, pid);
+#ifdef NNPC_REGNUM
+ write_register_pid (NNPC_REGNUM, val + 8, pid);
+#endif
+#endif
+#endif
+}
+
+/* Cope with strage ways of getting to the stack and frame pointers */
+
+CORE_ADDR
+read_sp ()
+{
+#ifdef TARGET_READ_SP
+ return TARGET_READ_SP ();
+#else
+ return read_register (SP_REGNUM);
+#endif
+}
+
+void
+write_sp (val)
+ CORE_ADDR val;
+{
+#ifdef TARGET_WRITE_SP
+ TARGET_WRITE_SP (val);
+#else
+ write_register (SP_REGNUM, val);
+#endif
+}
+
+CORE_ADDR
+read_fp ()
+{
+#ifdef TARGET_READ_FP
+ return TARGET_READ_FP ();
+#else
+ return read_register (FP_REGNUM);
+#endif
+}
+
+void
+write_fp (val)
+ CORE_ADDR val;
+{
+#ifdef TARGET_WRITE_FP
+ TARGET_WRITE_FP (val);
+#else
+ write_register (FP_REGNUM, val);
+#endif
+}
\f
/* Will calling read_var_value or locate_var_value on SYM end
up caring what frame it is being evaluated relative to? SYM must
If the variable cannot be found, return a zero pointer.
If FRAME is NULL, use the selected_frame. */
-value
+value_ptr
read_var_value (var, frame)
register struct symbol *var;
- FRAME frame;
+ struct frame_info *frame;
{
- register value v;
- struct frame_info *fi;
+ register value_ptr v;
struct type *type = SYMBOL_TYPE (var);
CORE_ADDR addr;
register int len;
VALUE_LVAL (v) = lval_memory; /* The most likely possibility. */
len = TYPE_LENGTH (type);
- if (frame == 0) frame = selected_frame;
+ if (frame == NULL) frame = selected_frame;
switch (SYMBOL_CLASS (var))
{
break;
case LOC_ARG:
- fi = get_frame_info (frame);
- if (fi == NULL)
+ if (frame == NULL)
return 0;
- addr = FRAME_ARGS_ADDRESS (fi);
+ addr = FRAME_ARGS_ADDRESS (frame);
if (!addr)
- {
- return 0;
- }
+ return 0;
addr += SYMBOL_VALUE (var);
break;
case LOC_REF_ARG:
- fi = get_frame_info (frame);
- if (fi == NULL)
+ if (frame == NULL)
return 0;
- addr = FRAME_ARGS_ADDRESS (fi);
+ addr = FRAME_ARGS_ADDRESS (frame);
if (!addr)
- {
- return 0;
- }
+ return 0;
addr += SYMBOL_VALUE (var);
addr = read_memory_unsigned_integer
(addr, TARGET_PTR_BIT / TARGET_CHAR_BIT);
case LOC_LOCAL:
case LOC_LOCAL_ARG:
- fi = get_frame_info (frame);
- if (fi == NULL)
+ if (frame == NULL)
return 0;
- addr = FRAME_LOCALS_ADDRESS (fi);
+ addr = FRAME_LOCALS_ADDRESS (frame);
addr += SYMBOL_VALUE (var);
break;
return 0;
b = get_frame_block (frame);
- v = value_from_register (type, SYMBOL_VALUE (var), frame);
if (SYMBOL_CLASS (var) == LOC_REGPARM_ADDR)
{
- addr = *(CORE_ADDR *)VALUE_CONTENTS (v);
+ addr =
+ value_as_pointer (value_from_register (lookup_pointer_type (type),
+ SYMBOL_VALUE (var),
+ frame));
VALUE_LVAL (v) = lval_memory;
}
else
- return v;
+ return value_from_register (type, SYMBOL_VALUE (var), frame);
}
break;
/* Return a value of type TYPE, stored in register REGNUM, in frame
FRAME. */
-value
+value_ptr
value_from_register (type, regnum, frame)
struct type *type;
int regnum;
- FRAME frame;
+ struct frame_info *frame;
{
char raw_buffer [MAX_REGISTER_RAW_SIZE];
CORE_ADDR addr;
int optim;
- value v = allocate_value (type);
+ value_ptr v = allocate_value (type);
int len = TYPE_LENGTH (type);
char *value_bytes = 0;
int value_bytes_copied = 0;
{
/* Raw and virtual formats are the same for this register. */
-#if TARGET_BYTE_ORDER == BIG_ENDIAN
- if (len < REGISTER_RAW_SIZE (regnum))
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN && len < REGISTER_RAW_SIZE (regnum))
{
/* Big-endian, and we want less than full size. */
VALUE_OFFSET (v) = REGISTER_RAW_SIZE (regnum) - len;
}
-#endif
memcpy (VALUE_CONTENTS_RAW (v), raw_buffer + VALUE_OFFSET (v), len);
}
return a (pointer to a) struct value containing the properly typed
address. */
-value
+value_ptr
locate_var_value (var, frame)
register struct symbol *var;
- FRAME frame;
+ struct frame_info *frame;
{
CORE_ADDR addr = 0;
struct type *type = SYMBOL_TYPE (var);
- value lazy_value;
+ value_ptr lazy_value;
/* Evaluate it first; if the result is a memory address, we're fine.
Lazy evaluation pays off here. */