/* Find a variable's value in memory, for GDB, the GNU debugger.
- Copyright (C) 1986-2017 Free Software Foundation, Inc.
+ Copyright (C) 1986-2023 Free Software Foundation, Inc.
This file is part of GDB.
#include "gdbcore.h"
#include "inferior.h"
#include "target.h"
-#include "floatformat.h"
-#include "symfile.h" /* for overlay functions */
+#include "symfile.h"
#include "regcache.h"
#include "user-regs.h"
#include "block.h"
#include "objfiles.h"
#include "language.h"
-#include "dwarf2loc.h"
+#include "dwarf2/loc.h"
+#include "gdbsupport/selftest.h"
/* Basic byte-swapping routines. All 'extract' functions return a
host-format integer from a target-format integer at ADDR which is
you lose
#endif
-LONGEST
-extract_signed_integer (const gdb_byte *addr, int len,
- enum bfd_endian byte_order)
+template<typename T, typename>
+T
+extract_integer (gdb::array_view<const gdb_byte> buf, enum bfd_endian byte_order)
{
- LONGEST retval;
- const unsigned char *p;
- const unsigned char *startaddr = addr;
- const unsigned char *endaddr = startaddr + len;
+ typename std::make_unsigned<T>::type retval = 0;
- if (len > (int) sizeof (LONGEST))
+ if (buf.size () > (int) sizeof (T))
error (_("\
That operation is not available on integers of more than %d bytes."),
- (int) sizeof (LONGEST));
+ (int) sizeof (T));
/* Start at the most significant end of the integer, and work towards
the least significant. */
if (byte_order == BFD_ENDIAN_BIG)
{
- 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;
-}
+ size_t i = 0;
-ULONGEST
-extract_unsigned_integer (const gdb_byte *addr, int len,
- enum bfd_endian byte_order)
-{
- ULONGEST retval;
- const unsigned char *p;
- const unsigned char *startaddr = addr;
- const unsigned char *endaddr = startaddr + len;
-
- if (len > (int) sizeof (ULONGEST))
- error (_("\
-That operation is not available on integers of more than %d bytes."),
- (int) sizeof (ULONGEST));
-
- /* Start at the most significant end of the integer, and work towards
- the least significant. */
- retval = 0;
- if (byte_order == BFD_ENDIAN_BIG)
- {
- for (p = startaddr; p < endaddr; ++p)
- retval = (retval << 8) | *p;
+ if (std::is_signed<T>::value)
+ {
+ /* Do the sign extension once at the start. */
+ retval = ((LONGEST) buf[i] ^ 0x80) - 0x80;
+ ++i;
+ }
+ for (; i < buf.size (); ++i)
+ retval = (retval << 8) | buf[i];
}
else
{
- for (p = endaddr - 1; p >= startaddr; --p)
- retval = (retval << 8) | *p;
+ ssize_t i = buf.size () - 1;
+
+ if (std::is_signed<T>::value)
+ {
+ /* Do the sign extension once at the start. */
+ retval = ((LONGEST) buf[i] ^ 0x80) - 0x80;
+ --i;
+ }
+ for (; i >= 0; --i)
+ retval = (retval << 8) | buf[i];
}
return retval;
}
+/* Explicit instantiations. */
+template LONGEST extract_integer<LONGEST> (gdb::array_view<const gdb_byte> buf,
+ enum bfd_endian byte_order);
+template ULONGEST extract_integer<ULONGEST>
+ (gdb::array_view<const gdb_byte> buf, enum bfd_endian byte_order);
+
/* 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
CORE_ADDR
extract_typed_address (const gdb_byte *buf, struct type *type)
{
- if (TYPE_CODE (type) != TYPE_CODE_PTR && !TYPE_IS_REFERENCE (type))
- internal_error (__FILE__, __LINE__,
- _("extract_typed_address: "
- "type is not a pointer or reference"));
-
- return gdbarch_pointer_to_address (get_type_arch (type), type, buf);
+ gdb_assert (type->is_pointer_or_reference ());
+ return gdbarch_pointer_to_address (type->arch (), type, buf);
}
/* All 'store' functions accept a host-format integer and store a
target-format integer at ADDR which is LEN bytes long. */
-
+template<typename T, typename>
void
-store_signed_integer (gdb_byte *addr, int len,
- enum bfd_endian byte_order, LONGEST val)
+store_integer (gdb_byte *addr, int len, enum bfd_endian byte_order,
+ T val)
{
gdb_byte *p;
gdb_byte *startaddr = addr;
}
}
-void
-store_unsigned_integer (gdb_byte *addr, int len,
- enum bfd_endian byte_order, ULONGEST val)
-{
- unsigned char *p;
- unsigned char *startaddr = (unsigned char *) addr;
- unsigned char *endaddr = startaddr + len;
+/* Explicit instantiations. */
+template void store_integer (gdb_byte *addr, int len,
+ enum bfd_endian byte_order,
+ LONGEST val);
- /* Start at the least significant end of the integer, and work towards
- the most significant. */
- if (byte_order == BFD_ENDIAN_BIG)
- {
- for (p = endaddr - 1; p >= startaddr; --p)
- {
- *p = val & 0xff;
- val >>= 8;
- }
- }
- else
- {
- for (p = startaddr; p < endaddr; ++p)
- {
- *p = val & 0xff;
- val >>= 8;
- }
- }
-}
+template void store_integer (gdb_byte *addr, int len,
+ enum bfd_endian byte_order,
+ ULONGEST val);
/* Store the address ADDR as a pointer of type TYPE at BUF, in target
form. */
void
store_typed_address (gdb_byte *buf, struct type *type, CORE_ADDR addr)
{
- if (TYPE_CODE (type) != TYPE_CODE_PTR && !TYPE_IS_REFERENCE (type))
- internal_error (__FILE__, __LINE__,
- _("store_typed_address: "
- "type is not a pointer or reference"));
-
- gdbarch_address_to_pointer (get_type_arch (type), type, buf, addr);
+ gdb_assert (type->is_pointer_or_reference ());
+ gdbarch_address_to_pointer (type->arch (), type, buf, addr);
}
+/* Copy a value from SOURCE of size SOURCE_SIZE bytes to DEST of size DEST_SIZE
+ bytes. If SOURCE_SIZE is greater than DEST_SIZE, then truncate the most
+ significant bytes. If SOURCE_SIZE is less than DEST_SIZE then either sign
+ or zero extended according to IS_SIGNED. Values are stored in memory with
+ endianness BYTE_ORDER. */
+
+void
+copy_integer_to_size (gdb_byte *dest, int dest_size, const gdb_byte *source,
+ int source_size, bool is_signed,
+ enum bfd_endian byte_order)
+{
+ signed int size_diff = dest_size - source_size;
+
+ /* Copy across everything from SOURCE that can fit into DEST. */
+
+ if (byte_order == BFD_ENDIAN_BIG && size_diff > 0)
+ memcpy (dest + size_diff, source, source_size);
+ else if (byte_order == BFD_ENDIAN_BIG && size_diff < 0)
+ memcpy (dest, source - size_diff, dest_size);
+ else
+ memcpy (dest, source, std::min (source_size, dest_size));
+ /* Fill the remaining space in DEST by either zero extending or sign
+ extending. */
+
+ if (size_diff > 0)
+ {
+ gdb_byte extension = 0;
+ if (is_signed
+ && ((byte_order != BFD_ENDIAN_BIG && source[source_size - 1] & 0x80)
+ || (byte_order == BFD_ENDIAN_BIG && source[0] & 0x80)))
+ extension = 0xff;
+
+ /* Extend into MSBs of SOURCE. */
+ if (byte_order == BFD_ENDIAN_BIG)
+ memset (dest, extension, size_diff);
+ else
+ memset (dest + source_size, extension, size_diff);
+ }
+}
/* Return a `value' with the contents of (virtual or cooked) register
REGNUM as found in the specified FRAME. The register's type is
- determined by register_type(). */
+ determined by register_type (). */
struct value *
-value_of_register (int regnum, struct frame_info *frame)
+value_of_register (int regnum, frame_info_ptr frame)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
struct value *reg_val;
/* User registers lie completely outside of the range of normal
registers. Catch them early so that the target never sees them. */
- if (regnum >= gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch))
+ if (regnum >= gdbarch_num_cooked_regs (gdbarch))
return value_of_user_reg (regnum, frame);
reg_val = value_of_register_lazy (frame, regnum);
- value_fetch_lazy (reg_val);
+ reg_val->fetch_lazy ();
return reg_val;
}
/* Return a `value' with the contents of (virtual or cooked) register
REGNUM as found in the specified FRAME. The register's type is
- determined by register_type(). The value is not fetched. */
+ determined by register_type (). The value is not fetched. */
struct value *
-value_of_register_lazy (struct frame_info *frame, int regnum)
+value_of_register_lazy (frame_info_ptr frame, int regnum)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
struct value *reg_val;
- struct frame_info *next_frame;
+ frame_info_ptr next_frame;
- gdb_assert (regnum < (gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch)));
+ gdb_assert (regnum < gdbarch_num_cooked_regs (gdbarch));
gdb_assert (frame != NULL);
next_frame = get_next_frame_sentinel_okay (frame);
+ /* In some cases NEXT_FRAME may not have a valid frame-id yet. This can
+ happen if we end up trying to unwind a register as part of the frame
+ sniffer. The only time that we get here without a valid frame-id is
+ if NEXT_FRAME is an inline frame. If this is the case then we can
+ avoid getting into trouble here by skipping past the inline frames. */
+ while (get_frame_type (next_frame) == INLINE_FRAME)
+ next_frame = get_next_frame_sentinel_okay (next_frame);
+
/* We should have a valid next frame. */
gdb_assert (frame_id_p (get_frame_id (next_frame)));
- reg_val = allocate_value_lazy (register_type (gdbarch, regnum));
- VALUE_LVAL (reg_val) = lval_register;
+ reg_val = value::allocate_lazy (register_type (gdbarch, regnum));
+ reg_val->set_lval (lval_register);
VALUE_REGNUM (reg_val) = regnum;
VALUE_NEXT_FRAME_ID (reg_val) = get_frame_id (next_frame);
unsigned_pointer_to_address (struct gdbarch *gdbarch,
struct type *type, const gdb_byte *buf)
{
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ enum bfd_endian byte_order = type_byte_order (type);
- return extract_unsigned_integer (buf, TYPE_LENGTH (type), byte_order);
+ return extract_unsigned_integer (buf, type->length (), byte_order);
}
CORE_ADDR
signed_pointer_to_address (struct gdbarch *gdbarch,
struct type *type, const gdb_byte *buf)
{
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ enum bfd_endian byte_order = type_byte_order (type);
- return extract_signed_integer (buf, TYPE_LENGTH (type), byte_order);
+ return extract_signed_integer (buf, type->length (), byte_order);
}
/* Given an address, store it as a pointer of type TYPE in target
unsigned_address_to_pointer (struct gdbarch *gdbarch, struct type *type,
gdb_byte *buf, CORE_ADDR addr)
{
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ enum bfd_endian byte_order = type_byte_order (type);
- store_unsigned_integer (buf, TYPE_LENGTH (type), byte_order, addr);
+ store_unsigned_integer (buf, type->length (), byte_order, addr);
}
void
address_to_signed_pointer (struct gdbarch *gdbarch, struct type *type,
gdb_byte *buf, CORE_ADDR addr)
{
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ enum bfd_endian byte_order = type_byte_order (type);
- store_signed_integer (buf, TYPE_LENGTH (type), byte_order, addr);
+ store_signed_integer (buf, type->length (), byte_order, addr);
}
\f
/* See value.h. */
if (SYMBOL_COMPUTED_OPS (sym) != NULL)
return SYMBOL_COMPUTED_OPS (sym)->get_symbol_read_needs (sym);
- switch (SYMBOL_CLASS (sym))
+ switch (sym->aclass ())
{
/* All cases listed explicitly so that gcc -Wall will detect it if
- we failed to consider one. */
+ we failed to consider one. */
case LOC_COMPUTED:
- gdb_assert_not_reached (_("LOC_COMPUTED variable missing a method"));
+ gdb_assert_not_reached ("LOC_COMPUTED variable missing a method");
case LOC_REGISTER:
case LOC_ARG:
case LOC_LABEL:
/* Getting the address of a label can be done independently of the block,
- even if some *uses* of that address wouldn't work so well without
- the right frame. */
+ even if some *uses* of that address wouldn't work so well without
+ the right frame. */
case LOC_BLOCK:
case LOC_CONST_BYTES:
return symbol_read_needs (sym) == SYMBOL_NEEDS_FRAME;
}
-/* 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 bound_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.minsym == NULL);
-
- data->result = lookup_minimal_symbol (data->name, NULL, objfile);
-
- /* The iterator should stop iff a match was found. */
- return (data->result.minsym != NULL);
-}
-
/* Given static link expression and the frame it lives in, look for the frame
the static links points to and return it. Return NULL if we could not find
such a frame. */
-static struct frame_info *
-follow_static_link (struct frame_info *frame,
+static frame_info_ptr
+follow_static_link (frame_info_ptr frame,
const struct dynamic_prop *static_link)
{
CORE_ADDR upper_frame_base;
QUIT;
/* If we don't know how to compute FRAME's base address, don't give up:
- maybe the frame we are looking for is upper in the stace frame. */
+ maybe the frame we are looking for is upper in the stack frame. */
if (framefunc != NULL
&& SYMBOL_BLOCK_OPS (framefunc) != NULL
&& SYMBOL_BLOCK_OPS (framefunc)->get_frame_base != NULL
For backward compatibility purposes (with old compilers), we then look for
the first frame that can host it. */
-static struct frame_info *
+static frame_info_ptr
get_hosting_frame (struct symbol *var, const struct block *var_block,
- struct frame_info *frame)
+ frame_info_ptr frame)
{
const struct block *frame_block = NULL;
tests that embed global/static symbols with null location lists.
We want to get <optimized out> instead of <frame required> when evaluating
them so return a frame instead of raising an error. */
- else if (var_block == block_global_block (var_block)
- || var_block == block_static_block (var_block))
+ else if (var_block->is_global_block () || var_block->is_static_block ())
return frame;
/* We have to handle the "my_func::my_local_var" notation. This requires us
/* If we failed to find the proper frame, fallback to the heuristic
method below. */
- else if (frame_block == block_global_block (frame_block))
+ else if (frame_block->is_global_block ())
{
frame = NULL;
break;
/* Assuming we have a block for this frame: if we are at the function
level, the immediate upper lexical block is in an outer function:
follow the static link. */
- else if (BLOCK_FUNCTION (frame_block))
+ else if (frame_block->function ())
{
const struct dynamic_prop *static_link
- = block_static_link (frame_block);
+ = frame_block->static_link ();
int could_climb_up = 0;
if (static_link != NULL)
else
/* We must be in some function nested lexical block. Just get the
outer block: both must share the same frame. */
- frame_block = BLOCK_SUPERBLOCK (frame_block);
+ frame_block = frame_block->superblock ();
}
/* Old compilers may not provide a static link, or they may provide an
frame = block_innermost_frame (var_block);
if (frame == NULL)
{
- if (BLOCK_FUNCTION (var_block)
- && !block_inlined_p (var_block)
- && SYMBOL_PRINT_NAME (BLOCK_FUNCTION (var_block)))
+ if (var_block->function ()
+ && !var_block->inlined_p ()
+ && var_block->function ()->print_name ())
error (_("No frame is currently executing in block %s."),
- SYMBOL_PRINT_NAME (BLOCK_FUNCTION (var_block)));
+ var_block->function ()->print_name ());
else
error (_("No frame is currently executing in specified"
" block"));
return frame;
}
-/* A default implementation for the "la_read_var_value" hook in
- the language vector which should work in most situations. */
+/* See language.h. */
struct value *
-default_read_var_value (struct symbol *var, const struct block *var_block,
- struct frame_info *frame)
+language_defn::read_var_value (struct symbol *var,
+ const struct block *var_block,
+ frame_info_ptr frame) const
{
struct value *v;
- struct type *type = SYMBOL_TYPE (var);
+ struct type *type = var->type ();
CORE_ADDR addr;
enum symbol_needs_kind sym_need;
sym_need = symbol_read_needs (var);
if (sym_need == SYMBOL_NEEDS_FRAME)
gdb_assert (frame != NULL);
- else if (sym_need == SYMBOL_NEEDS_REGISTERS && !target_has_registers)
- error (_("Cannot read `%s' without registers"), SYMBOL_PRINT_NAME (var));
+ else if (sym_need == SYMBOL_NEEDS_REGISTERS && !target_has_registers ())
+ error (_("Cannot read `%s' without registers"), var->print_name ());
if (frame != NULL)
frame = get_hosting_frame (var, var_block, frame);
if (SYMBOL_COMPUTED_OPS (var) != NULL)
return SYMBOL_COMPUTED_OPS (var)->read_variable (var, frame);
- switch (SYMBOL_CLASS (var))
+ switch (var->aclass ())
{
case LOC_CONST:
if (is_dynamic_type (type))
{
/* Value is a constant byte-sequence and needs no memory access. */
- type = resolve_dynamic_type (type, NULL, /* Unused address. */ 0);
+ type = resolve_dynamic_type (type, {}, /* Unused address. */ 0);
}
/* Put the constant back in target format. */
- v = allocate_value (type);
- store_signed_integer (value_contents_raw (v), TYPE_LENGTH (type),
- gdbarch_byte_order (get_type_arch (type)),
- (LONGEST) SYMBOL_VALUE (var));
- VALUE_LVAL (v) = not_lval;
+ v = value::allocate (type);
+ store_signed_integer (v->contents_raw ().data (), type->length (),
+ type_byte_order (type), var->value_longest ());
+ v->set_lval (not_lval);
return v;
case LOC_LABEL:
- /* Put the constant back in target format. */
- v = allocate_value (type);
- if (overlay_debugging)
- {
- CORE_ADDR addr
- = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var),
- SYMBOL_OBJ_SECTION (symbol_objfile (var),
- var));
-
- store_typed_address (value_contents_raw (v), type, addr);
- }
- else
- store_typed_address (value_contents_raw (v), type,
- SYMBOL_VALUE_ADDRESS (var));
- VALUE_LVAL (v) = not_lval;
- return v;
+ {
+ /* Put the constant back in target format. */
+ if (overlay_debugging)
+ {
+ struct objfile *var_objfile = var->objfile ();
+ addr = symbol_overlayed_address (var->value_address (),
+ var->obj_section (var_objfile));
+ }
+ else
+ addr = var->value_address ();
+
+ /* First convert the CORE_ADDR to a function pointer type, this
+ ensures the gdbarch knows what type of pointer we are
+ manipulating when value_from_pointer is called. */
+ type = builtin_type (var->arch ())->builtin_func_ptr;
+ v = value_from_pointer (type, addr);
+
+ /* But we want to present the value as 'void *', so cast it to the
+ required type now, this will not change the values bit
+ representation. */
+ struct type *void_ptr_type
+ = builtin_type (var->arch ())->builtin_data_ptr;
+ v = value_cast_pointers (void_ptr_type, v, 0);
+ v->set_lval (not_lval);
+ return v;
+ }
case LOC_CONST_BYTES:
if (is_dynamic_type (type))
{
/* Value is a constant byte-sequence and needs no memory access. */
- type = resolve_dynamic_type (type, NULL, /* Unused address. */ 0);
+ type = resolve_dynamic_type (type, {}, /* Unused address. */ 0);
}
- v = allocate_value (type);
- memcpy (value_contents_raw (v), SYMBOL_VALUE_BYTES (var),
- TYPE_LENGTH (type));
- VALUE_LVAL (v) = not_lval;
+ v = value::allocate (type);
+ memcpy (v->contents_raw ().data (), var->value_bytes (),
+ type->length ());
+ v->set_lval (not_lval);
return v;
case LOC_STATIC:
if (overlay_debugging)
- addr = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var),
- SYMBOL_OBJ_SECTION (symbol_objfile (var),
- var));
+ addr
+ = symbol_overlayed_address (var->value_address (),
+ var->obj_section (var->objfile ()));
else
- addr = SYMBOL_VALUE_ADDRESS (var);
+ addr = var->value_address ();
break;
case LOC_ARG:
addr = get_frame_args_address (frame);
if (!addr)
error (_("Unknown argument list address for `%s'."),
- SYMBOL_PRINT_NAME (var));
- addr += SYMBOL_VALUE (var);
+ var->print_name ());
+ addr += var->value_longest ();
break;
case LOC_REF_ARG:
argref = get_frame_args_address (frame);
if (!argref)
error (_("Unknown argument list address for `%s'."),
- SYMBOL_PRINT_NAME (var));
- argref += SYMBOL_VALUE (var);
+ var->print_name ());
+ argref += var->value_longest ();
ref = value_at (lookup_pointer_type (type), argref);
addr = value_as_address (ref);
break;
case LOC_LOCAL:
addr = get_frame_locals_address (frame);
- addr += SYMBOL_VALUE (var);
+ addr += var->value_longest ();
break;
case LOC_TYPEDEF:
error (_("Cannot look up value of a typedef `%s'."),
- SYMBOL_PRINT_NAME (var));
+ var->print_name ());
break;
case LOC_BLOCK:
if (overlay_debugging)
addr = symbol_overlayed_address
- (BLOCK_START (SYMBOL_BLOCK_VALUE (var)),
- SYMBOL_OBJ_SECTION (symbol_objfile (var), var));
+ (var->value_block ()->entry_pc (),
+ var->obj_section (var->objfile ()));
else
- addr = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
+ addr = var->value_block ()->entry_pc ();
break;
case LOC_REGISTER:
->register_number (var, get_frame_arch (frame));
struct value *regval;
- if (SYMBOL_CLASS (var) == LOC_REGPARM_ADDR)
+ if (var->aclass () == LOC_REGPARM_ADDR)
{
regval = value_from_register (lookup_pointer_type (type),
regno,
if (regval == NULL)
error (_("Value of register variable not available for `%s'."),
- SYMBOL_PRINT_NAME (var));
+ var->print_name ());
addr = value_as_address (regval);
}
if (regval == NULL)
error (_("Value of register variable not available for `%s'."),
- SYMBOL_PRINT_NAME (var));
+ var->print_name ());
return regval;
}
}
break;
case LOC_COMPUTED:
- gdb_assert_not_reached (_("LOC_COMPUTED variable missing a method"));
+ gdb_assert_not_reached ("LOC_COMPUTED variable missing a method");
case LOC_UNRESOLVED:
{
- struct minsym_lookup_data lookup_data;
- struct minimal_symbol *msym;
struct obj_section *obj_section;
-
- memset (&lookup_data, 0, sizeof (lookup_data));
- lookup_data.name = SYMBOL_LINKAGE_NAME (var);
+ bound_minimal_symbol bmsym;
gdbarch_iterate_over_objfiles_in_search_order
- (symbol_arch (var),
- minsym_lookup_iterator_cb, &lookup_data,
- symbol_objfile (var));
- msym = lookup_data.result.minsym;
+ (var->arch (),
+ [var, &bmsym] (objfile *objfile)
+ {
+ bmsym = lookup_minimal_symbol (var->linkage_name (), nullptr,
+ objfile);
+
+ /* Stop if a match is found. */
+ return bmsym.minsym != nullptr;
+ },
+ var->objfile ());
/* If we can't find the minsym there's a problem in the symbol info.
The symbol exists in the debug info, but it's missing in the minsym
table. */
- if (msym == NULL)
+ if (bmsym.minsym == nullptr)
{
const char *flavour_name
- = objfile_flavour_name (symbol_objfile (var));
+ = objfile_flavour_name (var->objfile ());
/* We can't get here unless we've opened the file, so flavour_name
can't be NULL. */
gdb_assert (flavour_name != NULL);
error (_("Missing %s symbol \"%s\"."),
- flavour_name, SYMBOL_LINKAGE_NAME (var));
+ flavour_name, var->linkage_name ());
}
- obj_section = MSYMBOL_OBJ_SECTION (lookup_data.result.objfile, msym);
+
+ obj_section = bmsym.minsym->obj_section (bmsym.objfile);
/* Relocate address, unless there is no section or the variable is
a TLS variable. */
if (obj_section == NULL
|| (obj_section->the_bfd_section->flags & SEC_THREAD_LOCAL) != 0)
- addr = MSYMBOL_VALUE_RAW_ADDRESS (msym);
+ addr = CORE_ADDR (bmsym.minsym->unrelocated_address ());
else
- addr = BMSYMBOL_VALUE_ADDRESS (lookup_data.result);
+ addr = bmsym.value_address ();
if (overlay_debugging)
addr = symbol_overlayed_address (addr, obj_section);
/* Determine address of TLS variable. */
break;
case LOC_OPTIMIZED_OUT:
- return allocate_optimized_out_value (type);
+ if (is_dynamic_type (type))
+ type = resolve_dynamic_type (type, {}, /* Unused address. */ 0);
+ return value::allocate_optimized_out (type);
default:
error (_("Cannot look up value of a botched symbol `%s'."),
- SYMBOL_PRINT_NAME (var));
+ var->print_name ());
break;
}
return v;
}
-/* Calls VAR's language la_read_var_value hook with the given arguments. */
+/* Calls VAR's language read_var_value hook with the given arguments. */
struct value *
read_var_value (struct symbol *var, const struct block *var_block,
- struct frame_info *frame)
+ frame_info_ptr frame)
{
- const struct language_defn *lang = language_def (SYMBOL_LANGUAGE (var));
+ const struct language_defn *lang = language_def (var->language ());
gdb_assert (lang != NULL);
- gdb_assert (lang->la_read_var_value != NULL);
- return lang->la_read_var_value (var, var_block, frame);
+ return lang->read_var_value (var, var_block, frame);
}
/* Install default attributes for register values. */
struct value *
default_value_from_register (struct gdbarch *gdbarch, struct type *type,
- int regnum, struct frame_id frame_id)
+ int regnum, struct frame_id frame_id)
{
- int len = TYPE_LENGTH (type);
- struct value *value = allocate_value (type);
- struct frame_info *frame;
+ int len = type->length ();
+ struct value *value = value::allocate (type);
+ frame_info_ptr frame;
- VALUE_LVAL (value) = lval_register;
+ value->set_lval (lval_register);
frame = frame_find_by_id (frame_id);
if (frame == NULL)
an integral number of registers. Otherwise, you need to do
some fiddling with the last register copied here for little
endian machines. */
- if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG
+ if (type_byte_order (type) == BFD_ENDIAN_BIG
&& len < register_size (gdbarch, regnum))
/* Big-endian, and we want less than full size. */
- set_value_offset (value, register_size (gdbarch, regnum) - len);
+ value->set_offset (register_size (gdbarch, regnum) - len);
else
- set_value_offset (value, 0);
+ value->set_offset (0);
return value;
}
complete resulting value as optimized out. */
void
-read_frame_register_value (struct value *value, struct frame_info *frame)
+read_frame_register_value (struct value *value, frame_info_ptr frame)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
LONGEST offset = 0;
- LONGEST reg_offset = value_offset (value);
+ LONGEST reg_offset = value->offset ();
int regnum = VALUE_REGNUM (value);
- int len = type_length_units (check_typedef (value_type (value)));
+ int len = type_length_units (check_typedef (value->type ()));
- gdb_assert (VALUE_LVAL (value) == lval_register);
+ gdb_assert (value->lval () == lval_register);
/* Skip registers wholly inside of REG_OFFSET. */
while (reg_offset >= register_size (gdbarch, regnum))
while (len > 0)
{
struct value *regval = get_frame_register_value (frame, regnum);
- int reg_len = type_length_units (value_type (regval)) - reg_offset;
+ int reg_len = type_length_units (regval->type ()) - reg_offset;
/* If the register length is larger than the number of bytes
- remaining to copy, then only copy the appropriate 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);
+ regval->contents_copy (value, offset, reg_offset, reg_len);
offset += reg_len;
len -= reg_len;
/* Return a value of type TYPE, stored in register REGNUM, in frame FRAME. */
struct value *
-value_from_register (struct type *type, int regnum, struct frame_info *frame)
+value_from_register (struct type *type, int regnum, frame_info_ptr frame)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
struct type *type1 = check_typedef (type);
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
- i386). It might need to convert the [float] register into
- the corresponding [integer] type (see Alpha). The assumption
- is that gdbarch_register_to_value populates the entire value
- including the location. */
- v = allocate_value (type);
- VALUE_LVAL (v) = lval_register;
+ specified value from this register. It might need to
+ re-order non-adjacent, starting with REGNUM (see MIPS and
+ i386). It might need to convert the [float] register into
+ the corresponding [integer] type (see Alpha). The assumption
+ is that gdbarch_register_to_value populates the entire value
+ including the location. */
+ v = value::allocate (type);
+ v->set_lval (lval_register);
VALUE_NEXT_FRAME_ID (v) = get_frame_id (get_next_frame_sentinel_okay (frame));
VALUE_REGNUM (v) = regnum;
ok = gdbarch_register_to_value (gdbarch, frame, regnum, type1,
- value_contents_raw (v), &optim,
+ v->contents_raw ().data (), &optim,
&unavail);
if (!ok)
{
if (optim)
- mark_value_bytes_optimized_out (v, 0, TYPE_LENGTH (type));
+ v->mark_bytes_optimized_out (0, type->length ());
if (unavail)
- mark_value_bytes_unavailable (v, 0, TYPE_LENGTH (type));
+ v->mark_bytes_unavailable (0, type->length ());
}
}
else
Will abort if register value is not available. */
CORE_ADDR
-address_from_register (int regnum, struct frame_info *frame)
+address_from_register (int regnum, frame_info_ptr frame)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
struct type *type = builtin_type (gdbarch)->builtin_data_ptr;
struct value *value;
CORE_ADDR result;
- int regnum_max_excl = (gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch));
+ int regnum_max_excl = gdbarch_num_cooked_regs (gdbarch);
if (regnum < 0 || regnum >= regnum_max_excl)
error (_("Invalid register #%d, expecting 0 <= # < %d"), regnum,
pointer types. Avoid constructing a value object in those cases. */
if (gdbarch_convert_register_p (gdbarch, regnum, type))
{
- gdb_byte *buf = (gdb_byte *) alloca (TYPE_LENGTH (type));
+ gdb_byte *buf = (gdb_byte *) alloca (type->length ());
int optim, unavail, ok;
ok = gdbarch_register_to_value (gdbarch, frame, regnum, type,
value = gdbarch_value_from_register (gdbarch, type, regnum, null_frame_id);
read_frame_register_value (value, frame);
- if (value_optimized_out (value))
+ if (value->optimized_out ())
{
/* This function is used while computing a location expression.
Complain about the value being optimized out, rather than
result = value_as_address (value);
release_value (value);
- value_free (value);
return result;
}
+#if GDB_SELF_TEST
+namespace selftests {
+namespace findvar_tests {
+
+/* Function to test copy_integer_to_size. Store SOURCE_VAL with size
+ SOURCE_SIZE to a buffer, making sure no sign extending happens at this
+ stage. Copy buffer to a new buffer using copy_integer_to_size. Extract
+ copied value and compare to DEST_VALU. Copy again with a signed
+ copy_integer_to_size and compare to DEST_VALS. Do everything for both
+ LITTLE and BIG target endians. Use unsigned values throughout to make
+ sure there are no implicit sign extensions. */
+
+static void
+do_cint_test (ULONGEST dest_valu, ULONGEST dest_vals, int dest_size,
+ ULONGEST src_val, int src_size)
+{
+ for (int i = 0; i < 2 ; i++)
+ {
+ gdb_byte srcbuf[sizeof (ULONGEST)] = {};
+ gdb_byte destbuf[sizeof (ULONGEST)] = {};
+ enum bfd_endian byte_order = i ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE;
+
+ /* Fill the src buffer (and later the dest buffer) with non-zero junk,
+ to ensure zero extensions aren't hidden. */
+ memset (srcbuf, 0xaa, sizeof (srcbuf));
+
+ /* Store (and later extract) using unsigned to ensure there are no sign
+ extensions. */
+ store_unsigned_integer (srcbuf, src_size, byte_order, src_val);
+
+ /* Test unsigned. */
+ memset (destbuf, 0xaa, sizeof (destbuf));
+ copy_integer_to_size (destbuf, dest_size, srcbuf, src_size, false,
+ byte_order);
+ SELF_CHECK (dest_valu == extract_unsigned_integer (destbuf, dest_size,
+ byte_order));
+
+ /* Test signed. */
+ memset (destbuf, 0xaa, sizeof (destbuf));
+ copy_integer_to_size (destbuf, dest_size, srcbuf, src_size, true,
+ byte_order);
+ SELF_CHECK (dest_vals == extract_unsigned_integer (destbuf, dest_size,
+ byte_order));
+ }
+}
+
+static void
+copy_integer_to_size_test ()
+{
+ /* Destination is bigger than the source, which has the signed bit unset. */
+ do_cint_test (0x12345678, 0x12345678, 8, 0x12345678, 4);
+ do_cint_test (0x345678, 0x345678, 8, 0x12345678, 3);
+
+ /* Destination is bigger than the source, which has the signed bit set. */
+ do_cint_test (0xdeadbeef, 0xffffffffdeadbeef, 8, 0xdeadbeef, 4);
+ do_cint_test (0xadbeef, 0xffffffffffadbeef, 8, 0xdeadbeef, 3);
+
+ /* Destination is smaller than the source. */
+ do_cint_test (0x5678, 0x5678, 2, 0x12345678, 3);
+ do_cint_test (0xbeef, 0xbeef, 2, 0xdeadbeef, 3);
+
+ /* Destination and source are the same size. */
+ do_cint_test (0x8765432112345678, 0x8765432112345678, 8, 0x8765432112345678,
+ 8);
+ do_cint_test (0x432112345678, 0x432112345678, 6, 0x8765432112345678, 6);
+ do_cint_test (0xfeedbeaddeadbeef, 0xfeedbeaddeadbeef, 8, 0xfeedbeaddeadbeef,
+ 8);
+ do_cint_test (0xbeaddeadbeef, 0xbeaddeadbeef, 6, 0xfeedbeaddeadbeef, 6);
+
+ /* Destination is bigger than the source. Source is bigger than 32bits. */
+ do_cint_test (0x3412345678, 0x3412345678, 8, 0x3412345678, 6);
+ do_cint_test (0xff12345678, 0xff12345678, 8, 0xff12345678, 6);
+ do_cint_test (0x432112345678, 0x432112345678, 8, 0x8765432112345678, 6);
+ do_cint_test (0xff2112345678, 0xffffff2112345678, 8, 0xffffff2112345678, 6);
+}
+
+} // namespace findvar_test
+} // namespace selftests
+
+#endif
+
+void _initialize_findvar ();
+void
+_initialize_findvar ()
+{
+#if GDB_SELF_TEST
+ selftests::register_test
+ ("copy_integer_to_size",
+ selftests::findvar_tests::copy_integer_to_size_test);
+#endif
+}