/* Find a variable's value in memory, for GDB, the GNU debugger.
- Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
- 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2007, 2008, 2009,
- 2010, 2011 Free Software Foundation, Inc.
+ Copyright (C) 1986-2001, 2003-2005, 2007-2012 Free Software
+ Foundation, Inc.
This file is part of GDB.
#include "user-regs.h"
#include "block.h"
#include "objfiles.h"
+#include "language.h"
/* Basic byte-swapping routines. All 'extract' functions return a
host-format integer from a target-format integer at ADDR which is
struct gdbarch *gdbarch = get_frame_arch (frame);
CORE_ADDR addr;
int optim;
+ int unavail;
struct value *reg_val;
int realnum;
gdb_byte raw_buffer[MAX_REGISTER_SIZE];
+ gdbarch_num_pseudo_regs (gdbarch))
return value_of_user_reg (regnum, frame);
- frame_register (frame, regnum, &optim, &lval, &addr, &realnum, raw_buffer);
+ frame_register (frame, regnum, &optim, &unavail,
+ &lval, &addr, &realnum, raw_buffer);
reg_val = allocate_value (register_type (gdbarch, regnum));
- memcpy (value_contents_raw (reg_val), raw_buffer,
- register_size (gdbarch, regnum));
+ if (!optim && !unavail)
+ memcpy (value_contents_raw (reg_val), raw_buffer,
+ register_size (gdbarch, regnum));
+ else
+ memset (value_contents_raw (reg_val), 0,
+ register_size (gdbarch, regnum));
+
VALUE_LVAL (reg_val) = lval;
set_value_address (reg_val, addr);
VALUE_REGNUM (reg_val) = regnum;
set_value_optimized_out (reg_val, optim);
+ if (unavail)
+ mark_value_bytes_unavailable (reg_val, 0, register_size (gdbarch, regnum));
VALUE_FRAME_ID (reg_val) = get_frame_id (frame);
return reg_val;
}
return 1;
}
-/* Given a struct symbol for a variable,
- and a stack frame id, read the value of the variable
- and return a (pointer to a) struct value containing the value.
- If the variable cannot be found, return a zero pointer. */
+/* Private data to be used with minsym_lookup_iterator_cb. */
+
+struct minsym_lookup_data
+{
+ /* The name of the minimal symbol we are searching for. */
+ const char *name;
+
+ /* The field where the callback should store the minimal symbol
+ if found. It should be initialized to NULL before the search
+ is started. */
+ struct minimal_symbol *result;
+};
+
+/* A callback function for gdbarch_iterate_over_objfiles_in_search_order.
+ It searches by name for a minimal symbol within the given OBJFILE.
+ The arguments are passed via CB_DATA, which in reality is a pointer
+ to struct minsym_lookup_data. */
+
+static int
+minsym_lookup_iterator_cb (struct objfile *objfile, void *cb_data)
+{
+ struct minsym_lookup_data *data = (struct minsym_lookup_data *) cb_data;
+
+ gdb_assert (data->result == NULL);
+
+ data->result = lookup_minimal_symbol (data->name, NULL, objfile);
+
+ /* The iterator should stop iff a match was found. */
+ return (data->result != NULL);
+}
+
+/* A default implementation for the "la_read_var_value" hook in
+ the language vector which should work in most situations. */
struct value *
-read_var_value (struct symbol *var, struct frame_info *frame)
+default_read_var_value (struct symbol *var, struct frame_info *frame)
{
struct value *v;
struct type *type = SYMBOL_TYPE (var);
case LOC_ARG:
addr = get_frame_args_address (frame);
if (!addr)
- return 0;
+ error (_("Unknown argument list address for `%s'."),
+ SYMBOL_PRINT_NAME (var));
addr += SYMBOL_VALUE (var);
v = allocate_value_lazy (type);
break;
argref = get_frame_args_address (frame);
if (!argref)
- return 0;
+ error (_("Unknown argument list address for `%s'."),
+ SYMBOL_PRINT_NAME (var));
argref += SYMBOL_VALUE (var);
ref = value_at (lookup_pointer_type (type), argref);
addr = value_as_address (ref);
break;
case LOC_TYPEDEF:
- error (_("Cannot look up value of a typedef"));
+ error (_("Cannot look up value of a typedef `%s'."),
+ SYMBOL_PRINT_NAME (var));
break;
case LOC_BLOCK:
frame);
if (regval == NULL)
- error (_("Value of register variable not available."));
+ error (_("Value of register variable not available for `%s'."),
+ SYMBOL_PRINT_NAME (var));
addr = value_as_address (regval);
v = allocate_value_lazy (type);
regval = value_from_register (type, regno, frame);
if (regval == NULL)
- error (_("Value of register variable not available."));
+ error (_("Value of register variable not available for `%s'."),
+ SYMBOL_PRINT_NAME (var));
return regval;
}
}
case LOC_UNRESOLVED:
{
+ struct minsym_lookup_data lookup_data;
struct minimal_symbol *msym;
struct obj_section *obj_section;
- msym = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (var), NULL, NULL);
+ memset (&lookup_data, 0, sizeof (lookup_data));
+ lookup_data.name = SYMBOL_LINKAGE_NAME (var);
+
+ gdbarch_iterate_over_objfiles_in_search_order
+ (get_objfile_arch (SYMBOL_SYMTAB (var)->objfile),
+ minsym_lookup_iterator_cb, &lookup_data,
+ SYMBOL_SYMTAB (var)->objfile);
+ msym = lookup_data.result;
+
if (msym == NULL)
- return 0;
+ error (_("No global symbol \"%s\"."), SYMBOL_LINKAGE_NAME (var));
if (overlay_debugging)
addr = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (msym),
SYMBOL_OBJ_SECTION (msym));
break;
case LOC_OPTIMIZED_OUT:
- v = allocate_value_lazy (type);
- VALUE_LVAL (v) = not_lval;
- set_value_optimized_out (v, 1);
- return v;
+ return allocate_optimized_out_value (type);
default:
- error (_("Cannot look up value of a botched symbol."));
+ error (_("Cannot look up value of a botched symbol `%s'."),
+ SYMBOL_PRINT_NAME (var));
break;
}
return v;
}
+/* Calls VAR's language la_read_var_value hook with the given arguments. */
+
+struct value *
+read_var_value (struct symbol *var, struct frame_info *frame)
+{
+ const struct language_defn *lang = language_def (SYMBOL_LANGUAGE (var));
+
+ gdb_assert (lang != NULL);
+ gdb_assert (lang->la_read_var_value != NULL);
+
+ return lang->la_read_var_value (var, frame);
+}
+
/* Install default attributes for register values. */
struct value *
return value;
}
+/* VALUE must be an lval_register value. If regnum is the value's
+ associated register number, and len the length of the values type,
+ read one or more registers in FRAME, starting with register REGNUM,
+ until we've read LEN bytes. */
+
+void
+read_frame_register_value (struct value *value, struct frame_info *frame)
+{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ int offset = 0;
+ int reg_offset = value_offset (value);
+ int regnum = VALUE_REGNUM (value);
+ int len = TYPE_LENGTH (check_typedef (value_type (value)));
+
+ gdb_assert (VALUE_LVAL (value) == lval_register);
+
+ /* Skip registers wholly inside of REG_OFFSET. */
+ while (reg_offset >= register_size (gdbarch, regnum))
+ {
+ reg_offset -= register_size (gdbarch, regnum);
+ regnum++;
+ }
+
+ /* Copy the data. */
+ while (len > 0)
+ {
+ struct value *regval = get_frame_register_value (frame, regnum);
+ int reg_len = TYPE_LENGTH (value_type (regval)) - reg_offset;
+
+ /* If the register length is larger than the number of bytes
+ remaining to copy, then only copy the appropriate bytes. */
+ if (reg_len > len)
+ reg_len = len;
+
+ value_contents_copy (value, offset, regval, reg_offset, reg_len);
+
+ offset += reg_len;
+ len -= reg_len;
+ reg_offset = 0;
+ regnum++;
+ }
+}
+
/* Return a value of type TYPE, stored in register REGNUM, in frame FRAME. */
struct value *
if (gdbarch_convert_register_p (gdbarch, regnum, type1))
{
+ int optim, unavail, ok;
+
/* The ISA/ABI need to something weird when obtaining the
specified value from this register. It might need to
re-order non-adjacent, starting with REGNUM (see MIPS and
VALUE_LVAL (v) = lval_register;
VALUE_FRAME_ID (v) = get_frame_id (frame);
VALUE_REGNUM (v) = regnum;
- gdbarch_register_to_value (gdbarch,
- frame, regnum, type1, value_contents_raw (v));
+ ok = gdbarch_register_to_value (gdbarch, frame, regnum, type1,
+ value_contents_raw (v), &optim,
+ &unavail);
+
+ if (!ok)
+ {
+ if (optim)
+ set_value_optimized_out (v, 1);
+ if (unavail)
+ mark_value_bytes_unavailable (v, 0, TYPE_LENGTH (type));
+ }
}
else
{
- int len = TYPE_LENGTH (type);
-
/* Construct the value. */
v = gdbarch_value_from_register (gdbarch, type, regnum, frame);
/* Get the data. */
- if (!get_frame_register_bytes (frame, regnum, value_offset (v), len,
- value_contents_raw (v)))
- set_value_optimized_out (v, 1);
+ read_frame_register_value (v, frame);
}
+
return v;
}
return result;
}
+