/* 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 *));
+
+static int read_relative_register_raw_bytes_for_frame PARAMS ((int regnum, char *myaddr, struct frame_info *frame));
/* 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. */
{
/* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
whether we want this to be true eventually. */
- return extract_unsigned_integer (addr, len);
+ return (CORE_ADDR)extract_unsigned_integer (addr, len);
}
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;
}
}
+/* Store the literal address "val" into
+ gdb-local memory pointed to by "addr"
+ for "len" bytes. */
void
store_address (addr, len, val)
PTR addr;
int len;
- CORE_ADDR val;
+ LONGEST val;
{
- /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
- whether we want this to be true eventually. */
- store_unsigned_integer (addr, len, (LONGEST)val);
+ store_unsigned_integer (addr, len, val);
}
\f
/* Swap LEN bytes at BUFFER between target and host byte-order. */
} \
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)
}
}
\f
-#if !defined (GET_SAVED_REGISTER)
/* Return the address in which frame FRAME's value of register REGNUM
has been saved in memory. Or return zero if it has not been saved.
struct frame_info *frame;
int regnum;
{
- struct frame_saved_regs saved_regs;
-
register struct frame_info *frame1 = NULL;
register CORE_ADDR addr = 0;
if (regnum != SP_REGNUM)
frame1 = frame;
- get_frame_saved_regs (frame1, &saved_regs);
- return saved_regs.regs[regnum]; /* ... which might be zero */
+ FRAME_INIT_SAVED_REGS (frame1);
+ return frame1->saved_regs[regnum]; /* ... which might be zero */
}
#endif /* HAVE_REGISTER_WINDOWS */
frame1 = get_prev_frame (frame1);
if (frame1 == 0 || frame1 == frame)
break;
- get_frame_saved_regs (frame1, &saved_regs);
- if (saved_regs.regs[regnum])
- addr = saved_regs.regs[regnum];
+ FRAME_INIT_SAVED_REGS (frame1);
+ if (frame1->saved_regs[regnum])
+ addr = frame1->saved_regs[regnum];
}
return addr;
The argument RAW_BUFFER must point to aligned memory. */
void
-get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
+default_get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
char *raw_buffer;
int *optimized;
CORE_ADDR *addrp;
if (raw_buffer != NULL)
{
/* Put it back in target format. */
- store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), addr);
+ store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), (LONGEST)addr);
}
if (addrp != NULL)
*addrp = 0;
if (addrp != NULL)
*addrp = addr;
}
-#endif /* GET_SAVED_REGISTER. */
-/* Copy the bytes of register REGNUM, relative to the current stack frame,
+#if !defined (GET_SAVED_REGISTER)
+#define GET_SAVED_REGISTER(raw_buffer, optimized, addrp, frame, regnum, lval) \
+ default_get_saved_register(raw_buffer, optimized, addrp, frame, regnum, lval)
+#endif
+void
+get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
+ char *raw_buffer;
+ int *optimized;
+ CORE_ADDR *addrp;
+ struct frame_info *frame;
+ int regnum;
+ enum lval_type *lval;
+{
+ GET_SAVED_REGISTER (raw_buffer, optimized, addrp, frame, regnum, lval);
+}
+
+/* Copy the bytes of register REGNUM, relative to the input stack frame,
into our memory at MYADDR, in target byte order.
The number of bytes copied is REGISTER_RAW_SIZE (REGNUM).
Returns 1 if could not be read, 0 if could. */
-int
-read_relative_register_raw_bytes (regnum, myaddr)
+static int
+read_relative_register_raw_bytes_for_frame (regnum, myaddr, frame)
int regnum;
char *myaddr;
+ struct frame_info *frame;
{
int optim;
- if (regnum == FP_REGNUM && selected_frame)
+ if (regnum == FP_REGNUM && frame)
{
- /* Put it back in target format. */
+ /* Put it back in target format. */
store_address (myaddr, REGISTER_RAW_SIZE(FP_REGNUM),
- FRAME_FP(selected_frame));
+ (LONGEST)FRAME_FP(frame));
+
return 0;
}
- get_saved_register (myaddr, &optim, (CORE_ADDR *) NULL, selected_frame,
+ get_saved_register (myaddr, &optim, (CORE_ADDR *) NULL, frame,
regnum, (enum lval_type *)NULL);
+
+ if (register_valid [regnum] < 0)
+ return 1; /* register value not available */
+
return optim;
}
+/* Copy the bytes of register REGNUM, relative to the current stack frame,
+ into our memory at MYADDR, in target byte order.
+ The number of bytes copied is REGISTER_RAW_SIZE (REGNUM).
+
+ Returns 1 if could not be read, 0 if could. */
+
+int
+read_relative_register_raw_bytes (regnum, myaddr)
+ int regnum;
+ char *myaddr;
+{
+ return read_relative_register_raw_bytes_for_frame (regnum, myaddr,
+ selected_frame);
+}
+
/* 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;
or it will get garbage. (a change from GDB version 3, in which
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. */
-char registers[REGISTER_BYTES + /* SLOP */ 256];
+/* Contents and state of the registers (in target byte order). */
-/* Nonzero if that register has been fetched. */
-char register_valid[NUM_REGS];
+char *registers;
+
+/* VALID_REGISTER is non-zero if it has been fetched, -1 if the
+ register value was not available. */
+
+signed char *register_valid;
/* 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;
if (!register_valid[regno])
target_fetch_registers (regno);
- return extract_address (®isters[REGISTER_BYTE (regno)],
- REGISTER_RAW_SIZE(regno));
+ return (CORE_ADDR)extract_address (®isters[REGISTER_BYTE (regno)],
+ REGISTER_RAW_SIZE(regno));
}
CORE_ADDR
return retval;
}
-/* Store VALUE, into the raw contents of register number REGNO. */
+/* Store VALUE, into the raw contents of register number REGNO.
+ This should probably write a LONGEST rather than a CORE_ADDR */
void
write_register (regno, val)
size = REGISTER_RAW_SIZE(regno);
buf = alloca (size);
- store_signed_integer (buf, size, (LONGEST) val);
+ 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. */
target_store_registers (regno);
}
-static void
+void
write_register_pid (regno, val, pid)
int regno;
- LONGEST val;
+ CORE_ADDR val;
int pid;
{
int 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. */
+ 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. */
Ditto for write_pc. */
CORE_ADDR
-read_pc ()
+read_pc_pid (pid)
+ int pid;
{
+ int saved_inferior_pid;
+ CORE_ADDR pc_val;
+
+ /* In case pid != inferior_pid. */
+ saved_inferior_pid = inferior_pid;
+ inferior_pid = pid;
+
#ifdef TARGET_READ_PC
- return TARGET_READ_PC (inferior_pid);
+ pc_val = TARGET_READ_PC (pid);
#else
- return ADDR_BITS_REMOVE ((CORE_ADDR) read_register_pid (PC_REGNUM, inferior_pid));
+ pc_val = ADDR_BITS_REMOVE ((CORE_ADDR) read_register_pid (PC_REGNUM, pid));
#endif
+
+ inferior_pid = saved_inferior_pid;
+ return pc_val;
}
CORE_ADDR
-read_pc_pid (pid)
- int pid;
+read_pc ()
{
-#ifdef TARGET_READ_PC
- return TARGET_READ_PC (pid);
-#else
- return ADDR_BITS_REMOVE ((CORE_ADDR) read_register_pid (PC_REGNUM, pid));
-#endif
+ return read_pc_pid (inferior_pid);
}
void
-write_pc (val)
- CORE_ADDR val;
+write_pc_pid (pc, pid)
+ CORE_ADDR pc;
+ int pid;
{
+ int saved_inferior_pid;
+
+ /* In case pid != inferior_pid. */
+ saved_inferior_pid = inferior_pid;
+ inferior_pid = pid;
+
#ifdef TARGET_WRITE_PC
- TARGET_WRITE_PC (val, inferior_pid);
+ TARGET_WRITE_PC (pc, pid);
#else
- write_register_pid (PC_REGNUM, val, inferior_pid);
+ write_register_pid (PC_REGNUM, pc, pid);
#ifdef NPC_REGNUM
- write_register_pid (NPC_REGNUM, val + 4, inferior_pid);
+ write_register_pid (NPC_REGNUM, pc + 4, pid);
#ifdef NNPC_REGNUM
- write_register_pid (NNPC_REGNUM, val + 8, inferior_pid);
+ write_register_pid (NNPC_REGNUM, pc + 8, pid);
#endif
#endif
#endif
+
+ inferior_pid = saved_inferior_pid;
}
void
-write_pc_pid (val, pid)
- CORE_ADDR val;
- int pid;
+write_pc (pc)
+ CORE_ADDR pc;
{
-#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
+ write_pc_pid (pc, inferior_pid);
}
/* Cope with strage ways of getting to the stack and frame pointers */
case LOC_LOCAL_ARG:
case LOC_BASEREG:
case LOC_BASEREG_ARG:
+ case LOC_THREAD_LOCAL_STATIC:
return 1;
case LOC_UNDEF:
case LOC_CONST:
case LOC_STATIC:
+ case LOC_INDIRECT:
case LOC_TYPEDEF:
case LOC_LABEL:
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,
+ (LONGEST)symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var),
+ SYMBOL_BFD_SECTION (var)));
+ else
+ store_address (VALUE_CONTENTS_RAW (v), len,
+ (LONGEST)SYMBOL_VALUE_ADDRESS (var));
VALUE_LVAL (v) = not_lval;
return v;
}
case LOC_STATIC:
+ if (overlay_debugging)
+ addr = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var),
+ SYMBOL_BFD_SECTION (var));
+ else
+ addr = SYMBOL_VALUE_ADDRESS (var);
+ break;
+
+ case LOC_INDIRECT:
+ /* The import slot does not have a real address in it from the
+ dynamic loader (dld.sl on HP-UX), if the target hasn't begun
+ execution yet, so check for that. */
+ if (!target_has_execution)
+ error ("\
+Attempt to access variable defined in different shared object or load module when\n\
+addresses have not been bound by the dynamic loader. Try again when executable is running.");
+
addr = SYMBOL_VALUE_ADDRESS (var);
+ addr = read_memory_unsigned_integer
+ (addr, TARGET_PTR_BIT / TARGET_CHAR_BIT);
break;
case LOC_ARG:
break;
}
+ case LOC_THREAD_LOCAL_STATIC:
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ get_saved_register(buf, NULL, NULL, frame, SYMBOL_BASEREG (var),
+ NULL);
+ addr = extract_address (buf, REGISTER_RAW_SIZE (SYMBOL_BASEREG (var)));
+ addr += SYMBOL_VALUE (var );
+ break;
+ }
+
case LOC_TYPEDEF:
error ("Cannot look up value of a typedef");
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. */
}
return 0; /* For lint -- never reached */
}
+
+\f
+static void build_findvar PARAMS ((void));
+static void
+build_findvar ()
+{
+ /* We allocate some extra slop since we do a lot of memcpy's around
+ `registers', and failing-soft is better than failing hard. */
+ int sizeof_registers = REGISTER_BYTES + /* SLOP */ 256;
+ int sizeof_register_valid = NUM_REGS * sizeof (*register_valid);
+ registers = xmalloc (sizeof_registers);
+ memset (registers, 0, sizeof_registers);
+ register_valid = xmalloc (sizeof_register_valid);
+ memset (register_valid, 0, sizeof_register_valid);
+}
+
+void _initialize_findvar PARAMS ((void));
+void
+_initialize_findvar ()
+{
+ build_findvar ();
+}