/* DWARF 2 location expression support for GDB.
- Copyright (C) 2003-2020 Free Software Foundation, Inc.
+ Copyright (C) 2003-2023 Free Software Foundation, Inc.
Contributed by Daniel Jacobowitz, MontaVista Software, Inc.
#include "gdbsupport/underlying.h"
#include "gdbsupport/byte-vector.h"
-static struct value *dwarf2_evaluate_loc_desc_full (struct type *type,
- struct frame_info *frame,
- const gdb_byte *data,
- size_t size,
- struct dwarf2_per_cu_data *per_cu,
- struct type *subobj_type,
- LONGEST subobj_byte_offset);
-
-static struct call_site_parameter *dwarf_expr_reg_to_entry_parameter
- (struct frame_info *frame,
- enum call_site_parameter_kind kind,
- union call_site_parameter_u kind_u,
- struct dwarf2_per_cu_data **per_cu_return);
-
-static struct value *indirect_synthetic_pointer
- (sect_offset die, LONGEST byte_offset,
- struct dwarf2_per_cu_data *per_cu,
- struct frame_info *frame,
- struct type *type, bool resolve_abstract_p = false);
+static struct value *dwarf2_evaluate_loc_desc_full
+ (struct type *type, frame_info_ptr frame, const gdb_byte *data,
+ size_t size, dwarf2_per_cu_data *per_cu, dwarf2_per_objfile *per_objfile,
+ struct type *subobj_type, LONGEST subobj_byte_offset, bool as_lval = true);
/* Until these have formal names, we define these here.
ref: http://gcc.gnu.org/wiki/DebugFission
/* Helper function which throws an error if a synthetic pointer is
invalid. */
-static void
+void
invalid_synthetic_pointer (void)
{
error (_("access outside bounds of object "
if (*low == 0 && *high == 0)
return DEBUG_LOC_END_OF_LIST;
- return DEBUG_LOC_START_END;
+ /* We want the caller to apply the base address, so we must return
+ DEBUG_LOC_OFFSET_PAIR here. */
+ return DEBUG_LOC_OFFSET_PAIR;
}
/* Decode the addresses in .debug_loclists entry.
The result indicates the kind of entry found. */
static enum debug_loc_kind
-decode_debug_loclists_addresses (struct dwarf2_per_cu_data *per_cu,
+decode_debug_loclists_addresses (dwarf2_per_cu_data *per_cu,
+ dwarf2_per_objfile *per_objfile,
const gdb_byte *loc_ptr,
const gdb_byte *buf_end,
const gdb_byte **new_ptr,
loc_ptr = gdb_read_uleb128 (loc_ptr, buf_end, &u64);
if (loc_ptr == NULL)
return DEBUG_LOC_BUFFER_OVERFLOW;
- *high = dwarf2_read_addr_index (per_cu, u64);
+
+ *high = dwarf2_read_addr_index (per_cu, per_objfile, u64);
*new_ptr = loc_ptr;
return DEBUG_LOC_BASE_ADDRESS;
+
case DW_LLE_startx_length:
loc_ptr = gdb_read_uleb128 (loc_ptr, buf_end, &u64);
if (loc_ptr == NULL)
return DEBUG_LOC_BUFFER_OVERFLOW;
- *low = dwarf2_read_addr_index (per_cu, u64);
+
+ *low = dwarf2_read_addr_index (per_cu, per_objfile, u64);
*high = *low;
loc_ptr = gdb_read_uleb128 (loc_ptr, buf_end, &u64);
if (loc_ptr == NULL)
return DEBUG_LOC_BUFFER_OVERFLOW;
+
*high += u64;
*new_ptr = loc_ptr;
return DEBUG_LOC_START_LENGTH;
+
case DW_LLE_start_length:
if (buf_end - loc_ptr < addr_size)
return DEBUG_LOC_BUFFER_OVERFLOW;
+
if (signed_addr_p)
*low = extract_signed_integer (loc_ptr, addr_size, byte_order);
else
*low = extract_unsigned_integer (loc_ptr, addr_size, byte_order);
+
loc_ptr += addr_size;
*high = *low;
+
loc_ptr = gdb_read_uleb128 (loc_ptr, buf_end, &u64);
if (loc_ptr == NULL)
return DEBUG_LOC_BUFFER_OVERFLOW;
+
*high += u64;
*new_ptr = loc_ptr;
return DEBUG_LOC_START_LENGTH;
+
case DW_LLE_end_of_list:
*new_ptr = loc_ptr;
return DEBUG_LOC_END_OF_LIST;
+
case DW_LLE_base_address:
if (loc_ptr + addr_size > buf_end)
return DEBUG_LOC_BUFFER_OVERFLOW;
+
if (signed_addr_p)
*high = extract_signed_integer (loc_ptr, addr_size, byte_order);
else
*high = extract_unsigned_integer (loc_ptr, addr_size, byte_order);
+
loc_ptr += addr_size;
*new_ptr = loc_ptr;
return DEBUG_LOC_BASE_ADDRESS;
+
case DW_LLE_offset_pair:
loc_ptr = gdb_read_uleb128 (loc_ptr, buf_end, &u64);
if (loc_ptr == NULL)
return DEBUG_LOC_BUFFER_OVERFLOW;
+
*low = u64;
loc_ptr = gdb_read_uleb128 (loc_ptr, buf_end, &u64);
if (loc_ptr == NULL)
return DEBUG_LOC_BUFFER_OVERFLOW;
+
*high = u64;
*new_ptr = loc_ptr;
return DEBUG_LOC_OFFSET_PAIR;
+
+ case DW_LLE_start_end:
+ if (loc_ptr + 2 * addr_size > buf_end)
+ return DEBUG_LOC_BUFFER_OVERFLOW;
+
+ if (signed_addr_p)
+ *low = extract_signed_integer (loc_ptr, addr_size, byte_order);
+ else
+ *low = extract_unsigned_integer (loc_ptr, addr_size, byte_order);
+
+ loc_ptr += addr_size;
+ if (signed_addr_p)
+ *high = extract_signed_integer (loc_ptr, addr_size, byte_order);
+ else
+ *high = extract_unsigned_integer (loc_ptr, addr_size, byte_order);
+
+ loc_ptr += addr_size;
+ *new_ptr = loc_ptr;
+ return DEBUG_LOC_START_END;
+
/* Following cases are not supported yet. */
case DW_LLE_startx_endx:
- case DW_LLE_start_end:
case DW_LLE_default_location:
default:
return DEBUG_LOC_INVALID_ENTRY;
The result indicates the kind of entry found. */
static enum debug_loc_kind
-decode_debug_loc_dwo_addresses (struct dwarf2_per_cu_data *per_cu,
+decode_debug_loc_dwo_addresses (dwarf2_per_cu_data *per_cu,
+ dwarf2_per_objfile *per_objfile,
const gdb_byte *loc_ptr,
const gdb_byte *buf_end,
const gdb_byte **new_ptr,
case DW_LLE_GNU_end_of_list_entry:
*new_ptr = loc_ptr;
return DEBUG_LOC_END_OF_LIST;
+
case DW_LLE_GNU_base_address_selection_entry:
*low = 0;
loc_ptr = gdb_read_uleb128 (loc_ptr, buf_end, &high_index);
if (loc_ptr == NULL)
return DEBUG_LOC_BUFFER_OVERFLOW;
- *high = dwarf2_read_addr_index (per_cu, high_index);
+
+ *high = dwarf2_read_addr_index (per_cu, per_objfile, high_index);
*new_ptr = loc_ptr;
return DEBUG_LOC_BASE_ADDRESS;
+
case DW_LLE_GNU_start_end_entry:
loc_ptr = gdb_read_uleb128 (loc_ptr, buf_end, &low_index);
if (loc_ptr == NULL)
return DEBUG_LOC_BUFFER_OVERFLOW;
- *low = dwarf2_read_addr_index (per_cu, low_index);
+
+ *low = dwarf2_read_addr_index (per_cu, per_objfile, low_index);
loc_ptr = gdb_read_uleb128 (loc_ptr, buf_end, &high_index);
if (loc_ptr == NULL)
return DEBUG_LOC_BUFFER_OVERFLOW;
- *high = dwarf2_read_addr_index (per_cu, high_index);
+
+ *high = dwarf2_read_addr_index (per_cu, per_objfile, high_index);
*new_ptr = loc_ptr;
return DEBUG_LOC_START_END;
+
case DW_LLE_GNU_start_length_entry:
loc_ptr = gdb_read_uleb128 (loc_ptr, buf_end, &low_index);
if (loc_ptr == NULL)
return DEBUG_LOC_BUFFER_OVERFLOW;
- *low = dwarf2_read_addr_index (per_cu, low_index);
+
+ *low = dwarf2_read_addr_index (per_cu, per_objfile, low_index);
if (loc_ptr + 4 > buf_end)
return DEBUG_LOC_BUFFER_OVERFLOW;
+
*high = *low;
*high += extract_unsigned_integer (loc_ptr, 4, byte_order);
*new_ptr = loc_ptr + 4;
return DEBUG_LOC_START_LENGTH;
+
default:
return DEBUG_LOC_INVALID_ENTRY;
}
dwarf2_find_location_expression (struct dwarf2_loclist_baton *baton,
size_t *locexpr_length, CORE_ADDR pc)
{
- struct objfile *objfile = baton->per_cu->objfile ();
- struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ dwarf2_per_objfile *per_objfile = baton->per_objfile;
+ struct objfile *objfile = per_objfile->objfile;
+ struct gdbarch *gdbarch = objfile->arch ();
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
unsigned int addr_size = baton->per_cu->addr_size ();
- int signed_addr_p = bfd_get_sign_extend_vma (objfile->obfd);
- /* Adjust base_address for relocatable objects. */
- CORE_ADDR base_offset = baton->per_cu->text_offset ();
- CORE_ADDR base_address = baton->base_address + base_offset;
+ int signed_addr_p = bfd_get_sign_extend_vma (objfile->obfd.get ());
+ /* Adjustment for relocatable objects. */
+ CORE_ADDR text_offset = baton->per_objfile->objfile->text_section_offset ();
+ CORE_ADDR base_address = baton->base_address;
const gdb_byte *loc_ptr, *buf_end;
loc_ptr = baton->data;
if (baton->per_cu->version () < 5 && baton->from_dwo)
kind = decode_debug_loc_dwo_addresses (baton->per_cu,
+ baton->per_objfile,
loc_ptr, buf_end, &new_ptr,
&low, &high, byte_order);
else if (baton->per_cu->version () < 5)
signed_addr_p);
else
kind = decode_debug_loclists_addresses (baton->per_cu,
+ baton->per_objfile,
loc_ptr, buf_end, &new_ptr,
&low, &high, byte_order,
addr_size, signed_addr_p);
case DEBUG_LOC_END_OF_LIST:
*locexpr_length = 0;
return NULL;
+
case DEBUG_LOC_BASE_ADDRESS:
- base_address = high + base_offset;
+ base_address = high;
continue;
+
case DEBUG_LOC_START_END:
case DEBUG_LOC_START_LENGTH:
case DEBUG_LOC_OFFSET_PAIR:
break;
+
case DEBUG_LOC_BUFFER_OVERFLOW:
case DEBUG_LOC_INVALID_ENTRY:
error (_("dwarf2_find_location_expression: "
"Corrupted DWARF expression."));
+
default:
gdb_assert_not_reached ("bad debug_loc_kind");
}
/* Otherwise, a location expression entry.
If the entry is from a DWO, don't add base address: the entry is from
.debug_addr which already has the DWARF "base address". We still add
- base_offset in case we're debugging a PIE executable. However, if the
+ text offset in case we're debugging a PIE executable. However, if the
entry is DW_LLE_offset_pair from a DWO, add the base address as the
- operands are offsets relative to the applicable base address. */
- if (baton->from_dwo && kind != DEBUG_LOC_OFFSET_PAIR)
- {
- low += base_offset;
- high += base_offset;
- }
- else
+ operands are offsets relative to the applicable base address.
+ If the entry is DW_LLE_start_end or DW_LLE_start_length, then
+ it already is an address, and we don't need to add the base. */
+ low += text_offset;
+ high += text_offset;
+ if (!baton->from_dwo && kind == DEBUG_LOC_OFFSET_PAIR)
{
low += base_address;
high += base_address;
if (pc_block)
pc_func = block_linkage_function (pc_block);
- if (pc_func && pc == BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (pc_func)))
+ if (pc_func && pc == pc_func->value_block ()->entry_pc ())
{
*locexpr_length = length;
return loc_ptr;
LOC_BLOCK functions using a DWARF expression as its DW_AT_frame_base. */
static CORE_ADDR
-locexpr_get_frame_base (struct symbol *framefunc, struct frame_info *frame)
+locexpr_get_frame_base (struct symbol *framefunc, frame_info_ptr frame)
{
struct gdbarch *gdbarch;
struct type *type;
SYMBOL_BLOCK_OPS (framefunc)->find_frame_base_location
(framefunc, get_frame_pc (frame), &start, &length);
result = dwarf2_evaluate_loc_desc (type, frame, start, length,
- dlbaton->per_cu);
+ dlbaton->per_cu, dlbaton->per_objfile);
/* The DW_AT_frame_base attribute contains a location description which
computes the base address itself. However, the call to
dwarf2_evaluate_loc_desc returns a value representing a variable at
that address. The frame base address is thus this variable's
address. */
- return value_address (result);
+ return result->address ();
}
/* Vector for inferior functions as represented by LOC_BLOCK, if the inferior
LOC_BLOCK functions using a DWARF location list as its DW_AT_frame_base. */
static CORE_ADDR
-loclist_get_frame_base (struct symbol *framefunc, struct frame_info *frame)
+loclist_get_frame_base (struct symbol *framefunc, frame_info_ptr frame)
{
struct gdbarch *gdbarch;
struct type *type;
SYMBOL_BLOCK_OPS (framefunc)->find_frame_base_location
(framefunc, get_frame_pc (frame), &start, &length);
result = dwarf2_evaluate_loc_desc (type, frame, start, length,
- dlbaton->per_cu);
+ dlbaton->per_cu, dlbaton->per_objfile);
/* The DW_AT_frame_base attribute contains a location description which
computes the base address itself. However, the call to
dwarf2_evaluate_loc_desc returns a value representing a variable at
that address. The frame base address is thus this variable's
address. */
- return value_address (result);
+ return result->address ();
}
/* Vector for inferior functions as represented by LOC_BLOCK, if the inferior
loclist_get_frame_base
};
-/* See dwarf2loc.h. */
+/* See dwarf2/loc.h. */
void
func_get_frame_base_dwarf_block (struct symbol *framefunc, CORE_ADDR pc,
framefunc->natural_name ());
}
-static CORE_ADDR
-get_frame_pc_for_per_cu_dwarf_call (void *baton)
-{
- dwarf_expr_context *ctx = (dwarf_expr_context *) baton;
-
- return ctx->get_frame_pc ();
-}
-
-static void
-per_cu_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset,
- struct dwarf2_per_cu_data *per_cu)
-{
- struct dwarf2_locexpr_baton block;
-
- block = dwarf2_fetch_die_loc_cu_off (die_offset, per_cu,
- get_frame_pc_for_per_cu_dwarf_call,
- ctx);
-
- /* DW_OP_call_ref is currently not supported. */
- gdb_assert (block.per_cu == per_cu);
-
- ctx->eval (block.data, block.size);
-}
-
-/* Given context CTX, section offset SECT_OFF, and compilation unit
- data PER_CU, execute the "variable value" operation on the DIE
- found at SECT_OFF. */
+/* See loc.h. */
-static struct value *
-sect_variable_value (struct dwarf_expr_context *ctx, sect_offset sect_off,
- struct dwarf2_per_cu_data *per_cu)
+value *
+compute_var_value (const char *name)
{
- struct type *die_type = dwarf2_fetch_die_type_sect_off (sect_off, per_cu);
-
- if (die_type == NULL)
- error (_("Bad DW_OP_GNU_variable_value DIE."));
-
- /* Note: Things still work when the following test is removed. This
- test and error is here to conform to the proposed specification. */
- if (TYPE_CODE (die_type) != TYPE_CODE_INT
- && TYPE_CODE (die_type) != TYPE_CODE_PTR)
- error (_("Type of DW_OP_GNU_variable_value DIE must be an integer or pointer."));
-
- struct type *type = lookup_pointer_type (die_type);
- struct frame_info *frame = get_selected_frame (_("No frame selected."));
- return indirect_synthetic_pointer (sect_off, 0, per_cu, frame, type, true);
+ struct block_symbol sym = lookup_symbol (name, nullptr, VAR_DOMAIN,
+ nullptr);
+ if (sym.symbol != nullptr)
+ return value_of_variable (sym.symbol, sym.block);
+ return nullptr;
}
-class dwarf_evaluate_loc_desc : public dwarf_expr_context
-{
- public:
-
- struct frame_info *frame;
- struct dwarf2_per_cu_data *per_cu;
- CORE_ADDR obj_address;
-
- /* Helper function for dwarf2_evaluate_loc_desc. Computes the CFA for
- the frame in BATON. */
-
- CORE_ADDR get_frame_cfa () override
- {
- return dwarf2_frame_cfa (frame);
- }
-
- /* Helper function for dwarf2_evaluate_loc_desc. Computes the PC for
- the frame in BATON. */
-
- CORE_ADDR get_frame_pc () override
- {
- return get_frame_address_in_block (frame);
- }
-
- /* Using the objfile specified in BATON, find the address for the
- current thread's thread-local storage with offset OFFSET. */
- CORE_ADDR get_tls_address (CORE_ADDR offset) override
- {
- struct objfile *objfile = per_cu->objfile ();
-
- return target_translate_tls_address (objfile, offset);
- }
-
- /* Helper interface of per_cu_dwarf_call for
- dwarf2_evaluate_loc_desc. */
-
- void dwarf_call (cu_offset die_offset) override
- {
- per_cu_dwarf_call (this, die_offset, per_cu);
- }
-
- /* Helper interface of sect_variable_value for
- dwarf2_evaluate_loc_desc. */
-
- struct value *dwarf_variable_value (sect_offset sect_off) override
- {
- return sect_variable_value (this, sect_off, per_cu);
- }
-
- struct type *get_base_type (cu_offset die_offset, int size) override
- {
- struct type *result = dwarf2_get_die_type (die_offset, per_cu);
- if (result == NULL)
- error (_("Could not find type for DW_OP_const_type"));
- if (size != 0 && TYPE_LENGTH (result) != size)
- error (_("DW_OP_const_type has different sizes for type and data"));
- return result;
- }
-
- /* Callback function for dwarf2_evaluate_loc_desc.
- Fetch the address indexed by DW_OP_addrx or DW_OP_GNU_addr_index. */
-
- CORE_ADDR get_addr_index (unsigned int index) override
- {
- return dwarf2_read_addr_index (per_cu, index);
- }
-
- /* Callback function for get_object_address. Return the address of the VLA
- object. */
-
- CORE_ADDR get_object_address () override
- {
- if (obj_address == 0)
- error (_("Location address is not set."));
- return obj_address;
- }
-
- /* Execute DWARF block of call_site_parameter which matches KIND and
- KIND_U. Choose DEREF_SIZE value of that parameter. Search
- caller of this objects's frame.
-
- The caller can be from a different CU - per_cu_dwarf_call
- implementation can be more simple as it does not support cross-CU
- DWARF executions. */
-
- void push_dwarf_reg_entry_value (enum call_site_parameter_kind kind,
- union call_site_parameter_u kind_u,
- int deref_size) override
- {
- struct frame_info *caller_frame;
- struct dwarf2_per_cu_data *caller_per_cu;
- struct call_site_parameter *parameter;
- const gdb_byte *data_src;
- size_t size;
-
- caller_frame = get_prev_frame (frame);
-
- parameter = dwarf_expr_reg_to_entry_parameter (frame, kind, kind_u,
- &caller_per_cu);
- data_src = deref_size == -1 ? parameter->value : parameter->data_value;
- size = deref_size == -1 ? parameter->value_size : parameter->data_value_size;
-
- /* DEREF_SIZE size is not verified here. */
- if (data_src == NULL)
- throw_error (NO_ENTRY_VALUE_ERROR,
- _("Cannot resolve DW_AT_call_data_value"));
-
- scoped_restore save_frame = make_scoped_restore (&this->frame,
- caller_frame);
- scoped_restore save_per_cu = make_scoped_restore (&this->per_cu,
- caller_per_cu);
- scoped_restore save_obj_addr = make_scoped_restore (&this->obj_address,
- (CORE_ADDR) 0);
-
- scoped_restore save_arch = make_scoped_restore (&this->gdbarch);
- this->gdbarch = get_objfile_arch (per_cu->objfile ());
- scoped_restore save_addr_size = make_scoped_restore (&this->addr_size);
- this->addr_size = per_cu->addr_size ();
- scoped_restore save_offset = make_scoped_restore (&this->offset);
- this->offset = per_cu->text_offset ();
-
- this->eval (data_src, size);
- }
-
- /* Using the frame specified in BATON, find the location expression
- describing the frame base. Return a pointer to it in START and
- its length in LENGTH. */
- void get_frame_base (const gdb_byte **start, size_t * length) override
- {
- /* FIXME: cagney/2003-03-26: This code should be using
- get_frame_base_address(), and then implement a dwarf2 specific
- this_base method. */
- struct symbol *framefunc;
- const struct block *bl = get_frame_block (frame, NULL);
-
- if (bl == NULL)
- error (_("frame address is not available."));
-
- /* Use block_linkage_function, which returns a real (not inlined)
- function, instead of get_frame_function, which may return an
- inlined function. */
- framefunc = block_linkage_function (bl);
-
- /* If we found a frame-relative symbol then it was certainly within
- some function associated with a frame. If we can't find the frame,
- something has gone wrong. */
- gdb_assert (framefunc != NULL);
-
- func_get_frame_base_dwarf_block (framefunc,
- get_frame_address_in_block (frame),
- start, length);
- }
-
- /* Read memory at ADDR (length LEN) into BUF. */
-
- void read_mem (gdb_byte *buf, CORE_ADDR addr, size_t len) override
- {
- read_memory (addr, buf, len);
- }
-
- /* Using the frame specified in BATON, return the value of register
- REGNUM, treated as a pointer. */
- CORE_ADDR read_addr_from_reg (int dwarf_regnum) override
- {
- struct gdbarch *gdbarch = get_frame_arch (frame);
- int regnum = dwarf_reg_to_regnum_or_error (gdbarch, dwarf_regnum);
-
- return address_from_register (regnum, frame);
- }
-
- /* Implement "get_reg_value" callback. */
-
- struct value *get_reg_value (struct type *type, int dwarf_regnum) override
- {
- struct gdbarch *gdbarch = get_frame_arch (frame);
- int regnum = dwarf_reg_to_regnum_or_error (gdbarch, dwarf_regnum);
-
- return value_from_register (type, regnum, frame);
- }
-};
-
-/* See dwarf2loc.h. */
+/* See dwarf2/loc.h. */
unsigned int entry_values_debug = 0;
show_entry_values_debug (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- fprintf_filtered (file,
- _("Entry values and tail call frames debugging is %s.\n"),
- value);
+ gdb_printf (file,
+ _("Entry values and tail call frames debugging is %s.\n"),
+ value);
}
-/* Find DW_TAG_call_site's DW_AT_call_target address.
- CALLER_FRAME (for registers) can be NULL if it is not known. This function
- always returns valid address or it throws NO_ENTRY_VALUE_ERROR. */
+/* See gdbtypes.h. */
-static CORE_ADDR
-call_site_to_target_addr (struct gdbarch *call_site_gdbarch,
- struct call_site *call_site,
- struct frame_info *caller_frame)
+void
+call_site_target::iterate_over_addresses
+ (struct gdbarch *call_site_gdbarch,
+ const struct call_site *call_site,
+ frame_info_ptr caller_frame,
+ iterate_ftype callback) const
{
- switch (FIELD_LOC_KIND (call_site->target))
+ switch (m_loc_kind)
{
- case FIELD_LOC_KIND_DWARF_BLOCK:
+ case call_site_target::DWARF_BLOCK:
{
struct dwarf2_locexpr_baton *dwarf_block;
struct value *val;
struct type *caller_core_addr_type;
struct gdbarch *caller_arch;
- dwarf_block = FIELD_DWARF_BLOCK (call_site->target);
+ dwarf_block = m_loc.dwarf_block;
if (dwarf_block == NULL)
{
struct bound_minimal_symbol msym;
- msym = lookup_minimal_symbol_by_pc (call_site->pc - 1);
+ msym = lookup_minimal_symbol_by_pc (call_site->pc () - 1);
throw_error (NO_ENTRY_VALUE_ERROR,
_("DW_AT_call_target is not specified at %s in %s"),
- paddress (call_site_gdbarch, call_site->pc),
+ paddress (call_site_gdbarch, call_site->pc ()),
(msym.minsym == NULL ? "???"
: msym.minsym->print_name ()));
{
struct bound_minimal_symbol msym;
- msym = lookup_minimal_symbol_by_pc (call_site->pc - 1);
+ msym = lookup_minimal_symbol_by_pc (call_site->pc () - 1);
throw_error (NO_ENTRY_VALUE_ERROR,
_("DW_AT_call_target DWARF block resolving "
"requires known frame which is currently not "
"available at %s in %s"),
- paddress (call_site_gdbarch, call_site->pc),
+ paddress (call_site_gdbarch, call_site->pc ()),
(msym.minsym == NULL ? "???"
: msym.minsym->print_name ()));
caller_core_addr_type = builtin_type (caller_arch)->builtin_func_ptr;
val = dwarf2_evaluate_loc_desc (caller_core_addr_type, caller_frame,
dwarf_block->data, dwarf_block->size,
- dwarf_block->per_cu);
+ dwarf_block->per_cu,
+ dwarf_block->per_objfile);
/* DW_AT_call_target is a DWARF expression, not a DWARF location. */
if (VALUE_LVAL (val) == lval_memory)
- return value_address (val);
+ callback (val->address ());
else
- return value_as_address (val);
+ callback (value_as_address (val));
}
+ break;
- case FIELD_LOC_KIND_PHYSNAME:
+ case call_site_target::PHYSNAME:
{
const char *physname;
struct bound_minimal_symbol msym;
- physname = FIELD_STATIC_PHYSNAME (call_site->target);
+ physname = m_loc.physname;
/* Handle both the mangled and demangled PHYSNAME. */
msym = lookup_minimal_symbol (physname, NULL, NULL);
if (msym.minsym == NULL)
{
- msym = lookup_minimal_symbol_by_pc (call_site->pc - 1);
+ msym = lookup_minimal_symbol_by_pc (call_site->pc () - 1);
throw_error (NO_ENTRY_VALUE_ERROR,
_("Cannot find function \"%s\" for a call site target "
"at %s in %s"),
- physname, paddress (call_site_gdbarch, call_site->pc),
+ physname, paddress (call_site_gdbarch, call_site->pc ()),
(msym.minsym == NULL ? "???"
: msym.minsym->print_name ()));
}
- return BMSYMBOL_VALUE_ADDRESS (msym);
+ callback (msym.value_address ());
+ }
+ break;
+
+ case call_site_target::PHYSADDR:
+ {
+ dwarf2_per_objfile *per_objfile = call_site->per_objfile;
+ CORE_ADDR delta = per_objfile->objfile->text_section_offset ();
+
+ callback (m_loc.physaddr + delta);
}
+ break;
+
+ case call_site_target::ADDRESSES:
+ {
+ dwarf2_per_objfile *per_objfile = call_site->per_objfile;
+ CORE_ADDR delta = per_objfile->objfile->text_section_offset ();
- case FIELD_LOC_KIND_PHYSADDR:
- return FIELD_STATIC_PHYSADDR (call_site->target);
+ for (unsigned i = 0; i < m_loc.addresses.length; ++i)
+ callback (m_loc.addresses.values[i] + delta);
+ }
+ break;
default:
- internal_error (__FILE__, __LINE__, _("invalid call site target kind"));
+ internal_error (_("invalid call site target kind"));
}
}
struct symbol *sym = find_pc_function (addr);
struct type *type;
- if (sym == NULL || BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym)) != addr)
+ if (sym == NULL || sym->value_block ()->entry_pc () != addr)
throw_error (NO_ENTRY_VALUE_ERROR,
_("DW_TAG_call_site resolving failed to find function "
"name for address %s"),
paddress (gdbarch, addr));
- type = SYMBOL_TYPE (sym);
- gdb_assert (TYPE_CODE (type) == TYPE_CODE_FUNC);
+ type = sym->type ();
+ gdb_assert (type->code () == TYPE_CODE_FUNC);
gdb_assert (TYPE_SPECIFIC_FIELD (type) == TYPE_SPECIFIC_FUNC);
return sym;
func_sym = func_addr_to_tail_call_list (gdbarch, addr);
- for (call_site = TYPE_TAIL_CALL_LIST (SYMBOL_TYPE (func_sym));
+ for (call_site = TYPE_TAIL_CALL_LIST (func_sym->type ());
call_site; call_site = call_site->tail_call_next)
{
- CORE_ADDR target_addr;
-
/* CALLER_FRAME with registers is not available for tail-call jumped
frames. */
- target_addr = call_site_to_target_addr (gdbarch, call_site, NULL);
-
- if (target_addr == verify_addr)
+ call_site->iterate_over_addresses (gdbarch, nullptr,
+ [&] (CORE_ADDR target_addr)
{
- struct bound_minimal_symbol msym;
-
- msym = lookup_minimal_symbol_by_pc (verify_addr);
- throw_error (NO_ENTRY_VALUE_ERROR,
- _("DW_OP_entry_value resolving has found "
- "function \"%s\" at %s can call itself via tail "
- "calls"),
- (msym.minsym == NULL ? "???"
- : msym.minsym->print_name ()),
- paddress (gdbarch, verify_addr));
- }
+ if (target_addr == verify_addr)
+ {
+ struct bound_minimal_symbol msym;
+
+ msym = lookup_minimal_symbol_by_pc (verify_addr);
+ throw_error (NO_ENTRY_VALUE_ERROR,
+ _("DW_OP_entry_value resolving has found "
+ "function \"%s\" at %s can call itself via tail "
+ "calls"),
+ (msym.minsym == NULL ? "???"
+ : msym.minsym->print_name ()),
+ paddress (gdbarch, verify_addr));
+ }
- if (addr_hash.insert (target_addr).second)
- todo.push_back (target_addr);
+ if (addr_hash.insert (target_addr).second)
+ todo.push_back (target_addr);
+ });
}
}
}
static void
tailcall_dump (struct gdbarch *gdbarch, const struct call_site *call_site)
{
- CORE_ADDR addr = call_site->pc;
+ CORE_ADDR addr = call_site->pc ();
struct bound_minimal_symbol msym = lookup_minimal_symbol_by_pc (addr - 1);
- fprintf_unfiltered (gdb_stdlog, " %s(%s)", paddress (gdbarch, addr),
- (msym.minsym == NULL ? "???"
- : msym.minsym->print_name ()));
+ gdb_printf (gdb_stdlog, " %s(%s)", paddress (gdbarch, addr),
+ (msym.minsym == NULL ? "???"
+ : msym.minsym->print_name ()));
}
static void
chain_candidate (struct gdbarch *gdbarch,
gdb::unique_xmalloc_ptr<struct call_site_chain> *resultp,
- std::vector<struct call_site *> *chain)
+ const std::vector<struct call_site *> &chain)
{
- long length = chain->size ();
+ long length = chain.size ();
int callers, callees, idx;
if (*resultp == NULL)
+ sizeof (*result->call_site) * (length - 1)));
result->length = length;
result->callers = result->callees = length;
- if (!chain->empty ())
- memcpy (result->call_site, chain->data (),
+ if (!chain.empty ())
+ memcpy (result->call_site, chain.data (),
sizeof (*result->call_site) * length);
resultp->reset (result);
if (entry_values_debug)
{
- fprintf_unfiltered (gdb_stdlog, "tailcall: initial:");
+ gdb_printf (gdb_stdlog, "tailcall: initial:");
for (idx = 0; idx < length; idx++)
tailcall_dump (gdbarch, result->call_site[idx]);
- fputc_unfiltered ('\n', gdb_stdlog);
+ gdb_putc ('\n', gdb_stdlog);
}
return;
if (entry_values_debug)
{
- fprintf_unfiltered (gdb_stdlog, "tailcall: compare:");
+ gdb_printf (gdb_stdlog, "tailcall: compare:");
for (idx = 0; idx < length; idx++)
- tailcall_dump (gdbarch, chain->at (idx));
- fputc_unfiltered ('\n', gdb_stdlog);
+ tailcall_dump (gdbarch, chain[idx]);
+ gdb_putc ('\n', gdb_stdlog);
}
/* Intersect callers. */
callers = std::min ((long) (*resultp)->callers, length);
for (idx = 0; idx < callers; idx++)
- if ((*resultp)->call_site[idx] != chain->at (idx))
+ if ((*resultp)->call_site[idx] != chain[idx])
{
(*resultp)->callers = idx;
break;
callees = std::min ((long) (*resultp)->callees, length);
for (idx = 0; idx < callees; idx++)
if ((*resultp)->call_site[(*resultp)->length - 1 - idx]
- != chain->at (length - 1 - idx))
+ != chain[length - 1 - idx])
{
(*resultp)->callees = idx;
break;
if (entry_values_debug)
{
- fprintf_unfiltered (gdb_stdlog, "tailcall: reduced:");
+ gdb_printf (gdb_stdlog, "tailcall: reduced:");
for (idx = 0; idx < (*resultp)->callers; idx++)
tailcall_dump (gdbarch, (*resultp)->call_site[idx]);
- fputs_unfiltered (" |", gdb_stdlog);
+ gdb_puts (" |", gdb_stdlog);
for (idx = 0; idx < (*resultp)->callees; idx++)
tailcall_dump (gdbarch,
(*resultp)->call_site[(*resultp)->length
- (*resultp)->callees + idx]);
- fputc_unfiltered ('\n', gdb_stdlog);
+ gdb_putc ('\n', gdb_stdlog);
}
if ((*resultp)->callers == 0 && (*resultp)->callees == 0)
gdb_assert ((*resultp)->callers + (*resultp)->callees <= (*resultp)->length);
}
-/* Create and return call_site_chain for CALLER_PC and CALLEE_PC. All the
- assumed frames between them use GDBARCH. Use depth first search so we can
- keep single CHAIN of call_site's back to CALLER_PC. Function recursion
- would have needless GDB stack overhead. Any unreliability results
- in thrown NO_ENTRY_VALUE_ERROR. */
+/* Recursively try to construct the call chain. GDBARCH, RESULTP, and
+ CHAIN are passed to chain_candidate. ADDR_HASH tracks which
+ addresses have already been seen along the current chain.
+ CALL_SITE is the call site to visit, and CALLEE_PC is the PC we're
+ trying to "reach". Returns false if an error has already been
+ detected and so an early return can be done. If it makes sense to
+ keep trying (even if no answer has yet been found), returns
+ true. */
+
+static bool
+call_site_find_chain_2
+ (struct gdbarch *gdbarch,
+ gdb::unique_xmalloc_ptr<struct call_site_chain> *resultp,
+ std::vector<struct call_site *> &chain,
+ std::unordered_set<CORE_ADDR> &addr_hash,
+ struct call_site *call_site,
+ CORE_ADDR callee_pc)
+{
+ std::vector<CORE_ADDR> addresses;
+ bool found_exact = false;
+ call_site->iterate_over_addresses (gdbarch, nullptr,
+ [&] (CORE_ADDR addr)
+ {
+ if (addr == callee_pc)
+ found_exact = true;
+ else
+ addresses.push_back (addr);
+ });
+
+ if (found_exact)
+ {
+ chain_candidate (gdbarch, resultp, chain);
+ /* If RESULTP was reset, then chain_candidate failed, and so we
+ can tell our callers to early-return. */
+ return *resultp != nullptr;
+ }
+
+ for (CORE_ADDR target_func_addr : addresses)
+ {
+ struct symbol *target_func
+ = func_addr_to_tail_call_list (gdbarch, target_func_addr);
+ for (struct call_site *target_call_site
+ = TYPE_TAIL_CALL_LIST (target_func->type ());
+ target_call_site != nullptr;
+ target_call_site = target_call_site->tail_call_next)
+ {
+ if (addr_hash.insert (target_call_site->pc ()).second)
+ {
+ /* Successfully entered TARGET_CALL_SITE. */
+ chain.push_back (target_call_site);
+
+ if (!call_site_find_chain_2 (gdbarch, resultp, chain,
+ addr_hash, target_call_site,
+ callee_pc))
+ return false;
+
+ size_t removed = addr_hash.erase (target_call_site->pc ());
+ gdb_assert (removed == 1);
+ chain.pop_back ();
+ }
+ }
+ }
+
+ return true;
+}
+
+/* Create and return call_site_chain for CALLER_PC and CALLEE_PC. All
+ the assumed frames between them use GDBARCH. Any unreliability
+ results in thrown NO_ENTRY_VALUE_ERROR. */
static gdb::unique_xmalloc_ptr<call_site_chain>
call_site_find_chain_1 (struct gdbarch *gdbarch, CORE_ADDR caller_pc,
TAIL_CALL_NEXT. This is inappropriate for CALLER_PC's call_site. */
std::vector<struct call_site *> chain;
+ /* A given call site may have multiple associated addresses. This
+ can happen if, e.g., the caller is split by hot/cold
+ partitioning. This vector tracks the ones we haven't visited
+ yet. */
+ std::vector<std::vector<CORE_ADDR>> unvisited_addresses;
+
/* We are not interested in the specific PC inside the callee function. */
callee_pc = get_pc_function_start (callee_pc);
if (callee_pc == 0)
target's function will get iterated as already pushed into CHAIN via their
TAIL_CALL_NEXT. */
call_site = call_site_for_pc (gdbarch, caller_pc);
-
- while (call_site)
- {
- CORE_ADDR target_func_addr;
- struct call_site *target_call_site;
-
- /* CALLER_FRAME with registers is not available for tail-call jumped
- frames. */
- target_func_addr = call_site_to_target_addr (gdbarch, call_site, NULL);
-
- if (target_func_addr == callee_pc)
- {
- chain_candidate (gdbarch, &retval, &chain);
- if (retval == NULL)
- break;
-
- /* There is no way to reach CALLEE_PC again as we would prevent
- entering it twice as being already marked in ADDR_HASH. */
- target_call_site = NULL;
- }
- else
- {
- struct symbol *target_func;
-
- target_func = func_addr_to_tail_call_list (gdbarch, target_func_addr);
- target_call_site = TYPE_TAIL_CALL_LIST (SYMBOL_TYPE (target_func));
- }
-
- do
- {
- /* Attempt to visit TARGET_CALL_SITE. */
-
- if (target_call_site)
- {
- if (addr_hash.insert (target_call_site->pc).second)
- {
- /* Successfully entered TARGET_CALL_SITE. */
-
- chain.push_back (target_call_site);
- break;
- }
- }
-
- /* Backtrack (without revisiting the originating call_site). Try the
- callers's sibling; if there isn't any try the callers's callers's
- sibling etc. */
-
- target_call_site = NULL;
- while (!chain.empty ())
- {
- call_site = chain.back ();
- chain.pop_back ();
-
- size_t removed = addr_hash.erase (call_site->pc);
- gdb_assert (removed == 1);
-
- target_call_site = call_site->tail_call_next;
- if (target_call_site)
- break;
- }
- }
- while (target_call_site);
-
- if (chain.empty ())
- call_site = NULL;
- else
- call_site = chain.back ();
- }
+ /* No need to check the return value here, because we no longer care
+ about possible early returns. */
+ call_site_find_chain_2 (gdbarch, &retval, chain, addr_hash, call_site,
+ callee_pc);
if (retval == NULL)
{
{
case CALL_SITE_PARAMETER_DWARF_REG:
return kind_u.dwarf_reg == parameter->u.dwarf_reg;
+
case CALL_SITE_PARAMETER_FB_OFFSET:
return kind_u.fb_offset == parameter->u.fb_offset;
+
case CALL_SITE_PARAMETER_PARAM_OFFSET:
return kind_u.param_cu_off == parameter->u.param_cu_off;
}
return 0;
}
-/* Fetch call_site_parameter from caller matching KIND and KIND_U.
- FRAME is for callee.
-
- Function always returns non-NULL, it throws NO_ENTRY_VALUE_ERROR
- otherwise. */
+/* See loc.h. */
-static struct call_site_parameter *
-dwarf_expr_reg_to_entry_parameter (struct frame_info *frame,
+struct call_site_parameter *
+dwarf_expr_reg_to_entry_parameter (frame_info_ptr frame,
enum call_site_parameter_kind kind,
union call_site_parameter_u kind_u,
- struct dwarf2_per_cu_data **per_cu_return)
+ dwarf2_per_cu_data **per_cu_return,
+ dwarf2_per_objfile **per_objfile_return)
{
CORE_ADDR func_addr, caller_pc;
struct gdbarch *gdbarch;
- struct frame_info *caller_frame;
+ frame_info_ptr caller_frame;
struct call_site *call_site;
int iparams;
/* Initialize it just to avoid a GCC false warning. */
caller_pc = get_frame_pc (caller_frame);
call_site = call_site_for_pc (gdbarch, caller_pc);
- target_addr = call_site_to_target_addr (gdbarch, call_site, caller_frame);
- if (target_addr != func_addr)
+ bool found = false;
+ unsigned count = 0;
+ call_site->iterate_over_addresses (gdbarch, caller_frame,
+ [&] (CORE_ADDR addr)
+ {
+ /* Preserve any address. */
+ target_addr = addr;
+ ++count;
+ if (addr == func_addr)
+ found = true;
+ });
+ if (!found)
{
struct minimal_symbol *target_msym, *func_msym;
target_msym = lookup_minimal_symbol_by_pc (target_addr).minsym;
func_msym = lookup_minimal_symbol_by_pc (func_addr).minsym;
throw_error (NO_ENTRY_VALUE_ERROR,
- _("DW_OP_entry_value resolving expects callee %s at %s "
+ _("DW_OP_entry_value resolving expects callee %s at %s %s"
"but the called frame is for %s at %s"),
(target_msym == NULL ? "???"
: target_msym->print_name ()),
paddress (gdbarch, target_addr),
+ (count > 0
+ ? _("(but note there are multiple addresses not listed)")
+ : ""),
func_msym == NULL ? "???" : func_msym->print_name (),
paddress (gdbarch, func_addr));
}
}
*per_cu_return = call_site->per_cu;
+ *per_objfile_return = call_site->per_objfile;
return parameter;
}
static struct value *
dwarf_entry_parameter_to_value (struct call_site_parameter *parameter,
CORE_ADDR deref_size, struct type *type,
- struct frame_info *caller_frame,
- struct dwarf2_per_cu_data *per_cu)
+ frame_info_ptr caller_frame,
+ dwarf2_per_cu_data *per_cu,
+ dwarf2_per_objfile *per_objfile)
{
const gdb_byte *data_src;
- gdb_byte *data;
size_t size;
data_src = deref_size == -1 ? parameter->value : parameter->data_value;
throw_error (NO_ENTRY_VALUE_ERROR,
_("Cannot resolve DW_AT_call_data_value"));
- /* DW_AT_call_value is a DWARF expression, not a DWARF
- location. Postprocessing of DWARF_VALUE_MEMORY would lose the type from
- DWARF block. */
- data = (gdb_byte *) alloca (size + 1);
- memcpy (data, data_src, size);
- data[size] = DW_OP_stack_value;
-
- return dwarf2_evaluate_loc_desc (type, caller_frame, data, size + 1, per_cu);
+ return dwarf2_evaluate_loc_desc (type, caller_frame, data_src, size, per_cu,
+ per_objfile, false);
}
/* VALUE must be of type lval_computed with entry_data_value_funcs. Perform
static struct value *
entry_data_value_coerce_ref (const struct value *value)
{
- struct type *checked_type = check_typedef (value_type (value));
+ struct type *checked_type = check_typedef (value->type ());
struct value *target_val;
if (!TYPE_IS_REFERENCE (checked_type))
return NULL;
- target_val = (struct value *) value_computed_closure (value);
- value_incref (target_val);
+ target_val = (struct value *) value->computed_closure ();
+ target_val->incref ();
return target_val;
}
static void *
entry_data_value_copy_closure (const struct value *v)
{
- struct value *target_val = (struct value *) value_computed_closure (v);
+ struct value *target_val = (struct value *) v->computed_closure ();
- value_incref (target_val);
+ target_val->incref ();
return target_val;
}
static void
entry_data_value_free_closure (struct value *v)
{
- struct value *target_val = (struct value *) value_computed_closure (v);
+ struct value *target_val = (struct value *) v->computed_closure ();
- value_decref (target_val);
+ target_val->decref ();
}
/* Vector for methods for an entry value reference where the referenced value
{
NULL, /* read */
NULL, /* write */
+ nullptr,
NULL, /* indirect */
entry_data_value_coerce_ref,
NULL, /* check_synthetic_pointer */
entry_data_value_free_closure
};
-/* Read parameter of TYPE at (callee) FRAME's function entry. KIND and KIND_U
- are used to match DW_AT_location at the caller's
- DW_TAG_call_site_parameter.
-
- Function always returns non-NULL value. It throws NO_ENTRY_VALUE_ERROR if it
- cannot resolve the parameter for any reason. */
-
-static struct value *
-value_of_dwarf_reg_entry (struct type *type, struct frame_info *frame,
+/* See dwarf2/loc.h. */
+struct value *
+value_of_dwarf_reg_entry (struct type *type, frame_info_ptr frame,
enum call_site_parameter_kind kind,
union call_site_parameter_u kind_u)
{
struct type *checked_type = check_typedef (type);
- struct type *target_type = TYPE_TARGET_TYPE (checked_type);
- struct frame_info *caller_frame = get_prev_frame (frame);
+ struct type *target_type = checked_type->target_type ();
+ frame_info_ptr caller_frame = get_prev_frame (frame);
struct value *outer_val, *target_val, *val;
struct call_site_parameter *parameter;
- struct dwarf2_per_cu_data *caller_per_cu;
+ dwarf2_per_cu_data *caller_per_cu;
+ dwarf2_per_objfile *caller_per_objfile;
parameter = dwarf_expr_reg_to_entry_parameter (frame, kind, kind_u,
- &caller_per_cu);
+ &caller_per_cu,
+ &caller_per_objfile);
outer_val = dwarf_entry_parameter_to_value (parameter, -1 /* deref_size */,
type, caller_frame,
- caller_per_cu);
+ caller_per_cu,
+ caller_per_objfile);
/* Check if DW_AT_call_data_value cannot be used. If it should be
used and it is not available do not fall back to OUTER_VAL - dereferencing
entry value. */
if (!TYPE_IS_REFERENCE (checked_type)
- || TYPE_TARGET_TYPE (checked_type) == NULL)
+ || checked_type->target_type () == NULL)
return outer_val;
target_val = dwarf_entry_parameter_to_value (parameter,
- TYPE_LENGTH (target_type),
+ target_type->length (),
target_type, caller_frame,
- caller_per_cu);
+ caller_per_cu,
+ caller_per_objfile);
- val = allocate_computed_value (type, &entry_data_value_funcs,
+ val = value::allocate_computed (type, &entry_data_value_funcs,
release_value (target_val).release ());
/* Copy the referencing pointer to the new computed value. */
- memcpy (value_contents_raw (val), value_contents_raw (outer_val),
- TYPE_LENGTH (checked_type));
- set_value_lazy (val, 0);
+ memcpy (val->contents_raw ().data (),
+ outer_val->contents_raw ().data (),
+ checked_type->length ());
+ val->set_lazy (0);
return val;
}
cannot resolve the parameter for any reason. */
static struct value *
-value_of_dwarf_block_entry (struct type *type, struct frame_info *frame,
+value_of_dwarf_block_entry (struct type *type, frame_info_ptr frame,
const gdb_byte *block, size_t block_len)
{
union call_site_parameter_u kind_u;
if (dwarf_block_to_fb_offset (block, block + block_len, &kind_u.fb_offset))
return value_of_dwarf_reg_entry (type, frame, CALL_SITE_PARAMETER_FB_OFFSET,
- kind_u);
+ kind_u);
/* This can normally happen - throw NO_ENTRY_VALUE_ERROR to get the message
suppressed during normal operation. The expression can be arbitrary if
"only for single DW_OP_reg* or for DW_OP_fbreg(*)"));
}
-struct piece_closure
-{
- /* Reference count. */
- int refc = 0;
-
- /* The CU from which this closure's expression came. */
- struct dwarf2_per_cu_data *per_cu = NULL;
-
- /* The pieces describing this variable. */
- std::vector<dwarf_expr_piece> pieces;
-
- /* Frame ID of frame to which a register value is relative, used
- only by DWARF_VALUE_REGISTER. */
- struct frame_id frame_id;
-};
-
-/* Allocate a closure for a value formed from separately-described
- PIECES. */
-
-static struct piece_closure *
-allocate_piece_closure (struct dwarf2_per_cu_data *per_cu,
- std::vector<dwarf_expr_piece> &&pieces,
- struct frame_info *frame)
-{
- struct piece_closure *c = new piece_closure;
-
- c->refc = 1;
- c->per_cu = per_cu;
- c->pieces = std::move (pieces);
- if (frame == NULL)
- c->frame_id = null_frame_id;
- else
- c->frame_id = get_frame_id (frame);
-
- for (dwarf_expr_piece &piece : c->pieces)
- if (piece.location == DWARF_VALUE_STACK)
- value_incref (piece.v.value);
-
- return c;
-}
-
-/* Return the number of bytes overlapping a contiguous chunk of N_BITS
- bits whose first bit is located at bit offset START. */
-
-static size_t
-bits_to_bytes (ULONGEST start, ULONGEST n_bits)
-{
- return (start % 8 + n_bits + 7) / 8;
-}
-
-/* Read or write a pieced value V. If FROM != NULL, operate in "write
- mode": copy FROM into the pieces comprising V. If FROM == NULL,
- operate in "read mode": fetch the contents of the (lazy) value V by
- composing it from its pieces. */
-
-static void
-rw_pieced_value (struct value *v, struct value *from)
-{
- int i;
- LONGEST offset = 0, max_offset;
- ULONGEST bits_to_skip;
- gdb_byte *v_contents;
- const gdb_byte *from_contents;
- struct piece_closure *c
- = (struct piece_closure *) value_computed_closure (v);
- gdb::byte_vector buffer;
- bool bits_big_endian = type_byte_order (value_type (v)) == BFD_ENDIAN_BIG;
-
- if (from != NULL)
- {
- from_contents = value_contents (from);
- v_contents = NULL;
- }
- else
- {
- if (value_type (v) != value_enclosing_type (v))
- internal_error (__FILE__, __LINE__,
- _("Should not be able to create a lazy value with "
- "an enclosing type"));
- v_contents = value_contents_raw (v);
- from_contents = NULL;
- }
-
- bits_to_skip = 8 * value_offset (v);
- if (value_bitsize (v))
- {
- bits_to_skip += (8 * value_offset (value_parent (v))
- + value_bitpos (v));
- if (from != NULL
- && (type_byte_order (value_type (from))
- == BFD_ENDIAN_BIG))
- {
- /* Use the least significant bits of FROM. */
- max_offset = 8 * TYPE_LENGTH (value_type (from));
- offset = max_offset - value_bitsize (v);
- }
- else
- max_offset = value_bitsize (v);
- }
- else
- max_offset = 8 * TYPE_LENGTH (value_type (v));
-
- /* Advance to the first non-skipped piece. */
- for (i = 0; i < c->pieces.size () && bits_to_skip >= c->pieces[i].size; i++)
- bits_to_skip -= c->pieces[i].size;
-
- for (; i < c->pieces.size () && offset < max_offset; i++)
- {
- struct dwarf_expr_piece *p = &c->pieces[i];
- size_t this_size_bits, this_size;
-
- this_size_bits = p->size - bits_to_skip;
- if (this_size_bits > max_offset - offset)
- this_size_bits = max_offset - offset;
-
- switch (p->location)
- {
- case DWARF_VALUE_REGISTER:
- {
- struct frame_info *frame = frame_find_by_id (c->frame_id);
- struct gdbarch *arch = get_frame_arch (frame);
- int gdb_regnum = dwarf_reg_to_regnum_or_error (arch, p->v.regno);
- ULONGEST reg_bits = 8 * register_size (arch, gdb_regnum);
- int optim, unavail;
-
- if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG
- && p->offset + p->size < reg_bits)
- {
- /* Big-endian, and we want less than full size. */
- bits_to_skip += reg_bits - (p->offset + p->size);
- }
- else
- bits_to_skip += p->offset;
-
- this_size = bits_to_bytes (bits_to_skip, this_size_bits);
- buffer.resize (this_size);
-
- if (from == NULL)
- {
- /* Read mode. */
- if (!get_frame_register_bytes (frame, gdb_regnum,
- bits_to_skip / 8,
- this_size, buffer.data (),
- &optim, &unavail))
- {
- if (optim)
- mark_value_bits_optimized_out (v, offset,
- this_size_bits);
- if (unavail)
- mark_value_bits_unavailable (v, offset,
- this_size_bits);
- break;
- }
-
- copy_bitwise (v_contents, offset,
- buffer.data (), bits_to_skip % 8,
- this_size_bits, bits_big_endian);
- }
- else
- {
- /* Write mode. */
- if (bits_to_skip % 8 != 0 || this_size_bits % 8 != 0)
- {
- /* Data is copied non-byte-aligned into the register.
- Need some bits from original register value. */
- get_frame_register_bytes (frame, gdb_regnum,
- bits_to_skip / 8,
- this_size, buffer.data (),
- &optim, &unavail);
- if (optim)
- throw_error (OPTIMIZED_OUT_ERROR,
- _("Can't do read-modify-write to "
- "update bitfield; containing word "
- "has been optimized out"));
- if (unavail)
- throw_error (NOT_AVAILABLE_ERROR,
- _("Can't do read-modify-write to "
- "update bitfield; containing word "
- "is unavailable"));
- }
-
- copy_bitwise (buffer.data (), bits_to_skip % 8,
- from_contents, offset,
- this_size_bits, bits_big_endian);
- put_frame_register_bytes (frame, gdb_regnum,
- bits_to_skip / 8,
- this_size, buffer.data ());
- }
- }
- break;
-
- case DWARF_VALUE_MEMORY:
- {
- bits_to_skip += p->offset;
-
- CORE_ADDR start_addr = p->v.mem.addr + bits_to_skip / 8;
-
- if (bits_to_skip % 8 == 0 && this_size_bits % 8 == 0
- && offset % 8 == 0)
- {
- /* Everything is byte-aligned; no buffer needed. */
- if (from != NULL)
- write_memory_with_notification (start_addr,
- (from_contents
- + offset / 8),
- this_size_bits / 8);
- else
- read_value_memory (v, offset,
- p->v.mem.in_stack_memory,
- p->v.mem.addr + bits_to_skip / 8,
- v_contents + offset / 8,
- this_size_bits / 8);
- break;
- }
-
- this_size = bits_to_bytes (bits_to_skip, this_size_bits);
- buffer.resize (this_size);
-
- if (from == NULL)
- {
- /* Read mode. */
- read_value_memory (v, offset,
- p->v.mem.in_stack_memory,
- p->v.mem.addr + bits_to_skip / 8,
- buffer.data (), this_size);
- copy_bitwise (v_contents, offset,
- buffer.data (), bits_to_skip % 8,
- this_size_bits, bits_big_endian);
- }
- else
- {
- /* Write mode. */
- if (bits_to_skip % 8 != 0 || this_size_bits % 8 != 0)
- {
- if (this_size <= 8)
- {
- /* Perform a single read for small sizes. */
- read_memory (start_addr, buffer.data (),
- this_size);
- }
- else
- {
- /* Only the first and last bytes can possibly have
- any bits reused. */
- read_memory (start_addr, buffer.data (), 1);
- read_memory (start_addr + this_size - 1,
- &buffer[this_size - 1], 1);
- }
- }
-
- copy_bitwise (buffer.data (), bits_to_skip % 8,
- from_contents, offset,
- this_size_bits, bits_big_endian);
- write_memory_with_notification (start_addr,
- buffer.data (),
- this_size);
- }
- }
- break;
-
- case DWARF_VALUE_STACK:
- {
- if (from != NULL)
- {
- mark_value_bits_optimized_out (v, offset, this_size_bits);
- break;
- }
-
- struct objfile *objfile = c->per_cu->objfile ();
- struct gdbarch *objfile_gdbarch = get_objfile_arch (objfile);
- ULONGEST stack_value_size_bits
- = 8 * TYPE_LENGTH (value_type (p->v.value));
-
- /* Use zeroes if piece reaches beyond stack value. */
- if (p->offset + p->size > stack_value_size_bits)
- break;
-
- /* Piece is anchored at least significant bit end. */
- if (gdbarch_byte_order (objfile_gdbarch) == BFD_ENDIAN_BIG)
- bits_to_skip += stack_value_size_bits - p->offset - p->size;
- else
- bits_to_skip += p->offset;
-
- copy_bitwise (v_contents, offset,
- value_contents_all (p->v.value),
- bits_to_skip,
- this_size_bits, bits_big_endian);
- }
- break;
-
- case DWARF_VALUE_LITERAL:
- {
- if (from != NULL)
- {
- mark_value_bits_optimized_out (v, offset, this_size_bits);
- break;
- }
-
- ULONGEST literal_size_bits = 8 * p->v.literal.length;
- size_t n = this_size_bits;
-
- /* Cut off at the end of the implicit value. */
- bits_to_skip += p->offset;
- if (bits_to_skip >= literal_size_bits)
- break;
- if (n > literal_size_bits - bits_to_skip)
- n = literal_size_bits - bits_to_skip;
-
- copy_bitwise (v_contents, offset,
- p->v.literal.data, bits_to_skip,
- n, bits_big_endian);
- }
- break;
-
- case DWARF_VALUE_IMPLICIT_POINTER:
- if (from != NULL)
- {
- mark_value_bits_optimized_out (v, offset, this_size_bits);
- break;
- }
-
- /* These bits show up as zeros -- but do not cause the value to
- be considered optimized-out. */
- break;
-
- case DWARF_VALUE_OPTIMIZED_OUT:
- mark_value_bits_optimized_out (v, offset, this_size_bits);
- break;
-
- default:
- internal_error (__FILE__, __LINE__, _("invalid location type"));
- }
-
- offset += this_size_bits;
- bits_to_skip = 0;
- }
-}
-
-
-static void
-read_pieced_value (struct value *v)
-{
- rw_pieced_value (v, NULL);
-}
-
-static void
-write_pieced_value (struct value *to, struct value *from)
-{
- rw_pieced_value (to, from);
-}
-
-/* An implementation of an lval_funcs method to see whether a value is
- a synthetic pointer. */
-
-static int
-check_pieced_synthetic_pointer (const struct value *value, LONGEST bit_offset,
- int bit_length)
-{
- struct piece_closure *c
- = (struct piece_closure *) value_computed_closure (value);
- int i;
-
- bit_offset += 8 * value_offset (value);
- if (value_bitsize (value))
- bit_offset += value_bitpos (value);
-
- for (i = 0; i < c->pieces.size () && bit_length > 0; i++)
- {
- struct dwarf_expr_piece *p = &c->pieces[i];
- size_t this_size_bits = p->size;
-
- if (bit_offset > 0)
- {
- if (bit_offset >= this_size_bits)
- {
- bit_offset -= this_size_bits;
- continue;
- }
-
- bit_length -= this_size_bits - bit_offset;
- bit_offset = 0;
- }
- else
- bit_length -= this_size_bits;
-
- if (p->location != DWARF_VALUE_IMPLICIT_POINTER)
- return 0;
- }
-
- return 1;
-}
-
-/* A wrapper function for get_frame_address_in_block. */
-
-static CORE_ADDR
-get_frame_address_in_block_wrapper (void *baton)
-{
- return get_frame_address_in_block ((struct frame_info *) baton);
-}
-
/* Fetch a DW_AT_const_value through a synthetic pointer. */
static struct value *
fetch_const_value_from_synthetic_pointer (sect_offset die, LONGEST byte_offset,
- struct dwarf2_per_cu_data *per_cu,
+ dwarf2_per_cu_data *per_cu,
+ dwarf2_per_objfile *per_objfile,
struct type *type)
{
struct value *result = NULL;
LONGEST len;
auto_obstack temp_obstack;
- bytes = dwarf2_fetch_constant_bytes (die, per_cu, &temp_obstack, &len);
+ bytes = dwarf2_fetch_constant_bytes (die, per_cu, per_objfile,
+ &temp_obstack, &len);
if (bytes != NULL)
{
if (byte_offset >= 0
- && byte_offset + TYPE_LENGTH (TYPE_TARGET_TYPE (type)) <= len)
+ && byte_offset + type->target_type ()->length () <= len)
{
bytes += byte_offset;
- result = value_from_contents (TYPE_TARGET_TYPE (type), bytes);
+ result = value_from_contents (type->target_type (), bytes);
}
else
invalid_synthetic_pointer ();
}
else
- result = allocate_optimized_out_value (TYPE_TARGET_TYPE (type));
+ result = value::allocate_optimized_out (type->target_type ());
return result;
}
-/* Fetch the value pointed to by a synthetic pointer. */
+/* See loc.h. */
-static struct value *
+struct value *
indirect_synthetic_pointer (sect_offset die, LONGEST byte_offset,
- struct dwarf2_per_cu_data *per_cu,
- struct frame_info *frame, struct type *type,
+ dwarf2_per_cu_data *per_cu,
+ dwarf2_per_objfile *per_objfile,
+ frame_info_ptr frame, struct type *type,
bool resolve_abstract_p)
{
/* Fetch the location expression of the DIE we're pointing to. */
+ auto get_frame_address_in_block_wrapper = [frame] ()
+ {
+ return get_frame_address_in_block (frame);
+ };
struct dwarf2_locexpr_baton baton
- = dwarf2_fetch_die_loc_sect_off (die, per_cu,
- get_frame_address_in_block_wrapper, frame,
+ = dwarf2_fetch_die_loc_sect_off (die, per_cu, per_objfile,
+ get_frame_address_in_block_wrapper,
resolve_abstract_p);
/* Get type of pointed-to DIE. */
- struct type *orig_type = dwarf2_fetch_die_type_sect_off (die, per_cu);
+ struct type *orig_type = dwarf2_fetch_die_type_sect_off (die, per_cu,
+ per_objfile);
if (orig_type == NULL)
invalid_synthetic_pointer ();
if (baton.data != NULL)
return dwarf2_evaluate_loc_desc_full (orig_type, frame, baton.data,
baton.size, baton.per_cu,
- TYPE_TARGET_TYPE (type),
+ baton.per_objfile,
+ type->target_type (),
byte_offset);
else
return fetch_const_value_from_synthetic_pointer (die, byte_offset, per_cu,
- type);
-}
-
-/* An implementation of an lval_funcs method to indirect through a
- pointer. This handles the synthetic pointer case when needed. */
-
-static struct value *
-indirect_pieced_value (struct value *value)
-{
- struct piece_closure *c
- = (struct piece_closure *) value_computed_closure (value);
- struct type *type;
- struct frame_info *frame;
- int i, bit_length;
- LONGEST bit_offset;
- struct dwarf_expr_piece *piece = NULL;
- LONGEST byte_offset;
- enum bfd_endian byte_order;
-
- type = check_typedef (value_type (value));
- if (TYPE_CODE (type) != TYPE_CODE_PTR)
- return NULL;
-
- bit_length = 8 * TYPE_LENGTH (type);
- bit_offset = 8 * value_offset (value);
- if (value_bitsize (value))
- bit_offset += value_bitpos (value);
-
- for (i = 0; i < c->pieces.size () && bit_length > 0; i++)
- {
- struct dwarf_expr_piece *p = &c->pieces[i];
- size_t this_size_bits = p->size;
-
- if (bit_offset > 0)
- {
- if (bit_offset >= this_size_bits)
- {
- bit_offset -= this_size_bits;
- continue;
- }
-
- bit_length -= this_size_bits - bit_offset;
- bit_offset = 0;
- }
- else
- bit_length -= this_size_bits;
-
- if (p->location != DWARF_VALUE_IMPLICIT_POINTER)
- return NULL;
-
- if (bit_length != 0)
- error (_("Invalid use of DW_OP_implicit_pointer"));
-
- piece = p;
- break;
- }
-
- gdb_assert (piece != NULL);
- frame = get_selected_frame (_("No frame selected."));
-
- /* This is an offset requested by GDB, such as value subscripts.
- However, due to how synthetic pointers are implemented, this is
- always presented to us as a pointer type. This means we have to
- sign-extend it manually as appropriate. Use raw
- extract_signed_integer directly rather than value_as_address and
- sign extend afterwards on architectures that would need it
- (mostly everywhere except MIPS, which has signed addresses) as
- the later would go through gdbarch_pointer_to_address and thus
- return a CORE_ADDR with high bits set on architectures that
- encode address spaces and other things in CORE_ADDR. */
- byte_order = gdbarch_byte_order (get_frame_arch (frame));
- byte_offset = extract_signed_integer (value_contents (value),
- TYPE_LENGTH (type), byte_order);
- byte_offset += piece->v.ptr.offset;
-
- return indirect_synthetic_pointer (piece->v.ptr.die_sect_off,
- byte_offset, c->per_cu,
- frame, type);
+ per_objfile, type);
}
-/* Implementation of the coerce_ref method of lval_funcs for synthetic C++
- references. */
-
-static struct value *
-coerce_pieced_ref (const struct value *value)
-{
- struct type *type = check_typedef (value_type (value));
-
- if (value_bits_synthetic_pointer (value, value_embedded_offset (value),
- TARGET_CHAR_BIT * TYPE_LENGTH (type)))
- {
- const struct piece_closure *closure
- = (struct piece_closure *) value_computed_closure (value);
- struct frame_info *frame
- = get_selected_frame (_("No frame selected."));
-
- /* gdb represents synthetic pointers as pieced values with a single
- piece. */
- gdb_assert (closure != NULL);
- gdb_assert (closure->pieces.size () == 1);
-
- return indirect_synthetic_pointer
- (closure->pieces[0].v.ptr.die_sect_off,
- closure->pieces[0].v.ptr.offset,
- closure->per_cu, frame, type);
- }
- else
- {
- /* Else: not a synthetic reference; do nothing. */
- return NULL;
- }
-}
-
-static void *
-copy_pieced_value_closure (const struct value *v)
-{
- struct piece_closure *c
- = (struct piece_closure *) value_computed_closure (v);
-
- ++c->refc;
- return c;
-}
-
-static void
-free_pieced_value_closure (struct value *v)
-{
- struct piece_closure *c
- = (struct piece_closure *) value_computed_closure (v);
-
- --c->refc;
- if (c->refc == 0)
- {
- for (dwarf_expr_piece &p : c->pieces)
- if (p.location == DWARF_VALUE_STACK)
- value_decref (p.v.value);
-
- delete c;
- }
-}
-
-/* Functions for accessing a variable described by DW_OP_piece. */
-static const struct lval_funcs pieced_value_funcs = {
- read_pieced_value,
- write_pieced_value,
- indirect_pieced_value,
- coerce_pieced_ref,
- check_pieced_synthetic_pointer,
- copy_pieced_value_closure,
- free_pieced_value_closure
-};
-
/* Evaluate a location description, starting at DATA and with length
SIZE, to find the current location of variable of TYPE in the
context of FRAME. If SUBOBJ_TYPE is non-NULL, return instead the
SUBOBJ_BYTE_OFFSET within the variable of type TYPE. */
static struct value *
-dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
+dwarf2_evaluate_loc_desc_full (struct type *type, frame_info_ptr frame,
const gdb_byte *data, size_t size,
- struct dwarf2_per_cu_data *per_cu,
+ dwarf2_per_cu_data *per_cu,
+ dwarf2_per_objfile *per_objfile,
struct type *subobj_type,
- LONGEST subobj_byte_offset)
+ LONGEST subobj_byte_offset,
+ bool as_lval)
{
- struct value *retval;
- struct objfile *objfile = per_cu->objfile ();
-
if (subobj_type == NULL)
{
subobj_type = type;
invalid_synthetic_pointer ();
if (size == 0)
- return allocate_optimized_out_value (subobj_type);
+ return value::allocate_optimized_out (subobj_type);
- dwarf_evaluate_loc_desc ctx;
- ctx.frame = frame;
- ctx.per_cu = per_cu;
- ctx.obj_address = 0;
+ dwarf_expr_context ctx (per_objfile, per_cu->addr_size ());
+ value *retval;
scoped_value_mark free_values;
- ctx.gdbarch = get_objfile_arch (objfile);
- ctx.addr_size = per_cu->addr_size ();
- ctx.ref_addr_size = per_cu->ref_addr_size ();
- ctx.offset = per_cu->text_offset ();
-
try
{
- ctx.eval (data, size);
+ retval = ctx.evaluate (data, size, as_lval, per_cu, frame, nullptr,
+ type, subobj_type, subobj_byte_offset);
}
catch (const gdb_exception_error &ex)
{
if (ex.error == NOT_AVAILABLE_ERROR)
{
free_values.free_to_mark ();
- retval = allocate_value (subobj_type);
- mark_value_bytes_unavailable (retval, 0,
- TYPE_LENGTH (subobj_type));
+ retval = value::allocate (subobj_type);
+ retval->mark_bytes_unavailable (0,
+ subobj_type->length ());
return retval;
}
else if (ex.error == NO_ENTRY_VALUE_ERROR)
if (entry_values_debug)
exception_print (gdb_stdout, ex);
free_values.free_to_mark ();
- return allocate_optimized_out_value (subobj_type);
+ return value::allocate_optimized_out (subobj_type);
}
else
throw;
}
- if (ctx.pieces.size () > 0)
- {
- struct piece_closure *c;
- ULONGEST bit_size = 0;
-
- for (dwarf_expr_piece &piece : ctx.pieces)
- bit_size += piece.size;
- /* Complain if the expression is larger than the size of the
- outer type. */
- if (bit_size > 8 * TYPE_LENGTH (type))
- invalid_synthetic_pointer ();
+ /* We need to clean up all the values that are not needed any more.
+ The problem with a value_ref_ptr class is that it disconnects the
+ RETVAL from the value garbage collection, so we need to make
+ a copy of that value on the stack to keep everything consistent.
+ The value_ref_ptr will clean up after itself at the end of this block. */
+ value_ref_ptr value_holder = value_ref_ptr::new_reference (retval);
+ free_values.free_to_mark ();
- c = allocate_piece_closure (per_cu, std::move (ctx.pieces), frame);
- /* We must clean up the value chain after creating the piece
- closure but before allocating the result. */
- free_values.free_to_mark ();
- retval = allocate_computed_value (subobj_type,
- &pieced_value_funcs, c);
- set_value_offset (retval, subobj_byte_offset);
- }
- else
- {
- switch (ctx.location)
- {
- case DWARF_VALUE_REGISTER:
- {
- struct gdbarch *arch = get_frame_arch (frame);
- int dwarf_regnum
- = longest_to_int (value_as_long (ctx.fetch (0)));
- int gdb_regnum = dwarf_reg_to_regnum_or_error (arch, dwarf_regnum);
-
- if (subobj_byte_offset != 0)
- error (_("cannot use offset on synthetic pointer to register"));
- free_values.free_to_mark ();
- retval = value_from_register (subobj_type, gdb_regnum, frame);
- if (value_optimized_out (retval))
- {
- struct value *tmp;
-
- /* This means the register has undefined value / was
- not saved. As we're computing the location of some
- variable etc. in the program, not a value for
- inspecting a register ($pc, $sp, etc.), return a
- generic optimized out value instead, so that we show
- <optimized out> instead of <not saved>. */
- tmp = allocate_value (subobj_type);
- value_contents_copy (tmp, 0, retval, 0,
- TYPE_LENGTH (subobj_type));
- retval = tmp;
- }
- }
- break;
-
- case DWARF_VALUE_MEMORY:
- {
- struct type *ptr_type;
- CORE_ADDR address = ctx.fetch_address (0);
- bool in_stack_memory = ctx.fetch_in_stack_memory (0);
-
- /* DW_OP_deref_size (and possibly other operations too) may
- create a pointer instead of an address. Ideally, the
- pointer to address conversion would be performed as part
- of those operations, but the type of the object to
- which the address refers is not known at the time of
- the operation. Therefore, we do the conversion here
- since the type is readily available. */
-
- switch (TYPE_CODE (subobj_type))
- {
- case TYPE_CODE_FUNC:
- case TYPE_CODE_METHOD:
- ptr_type = builtin_type (ctx.gdbarch)->builtin_func_ptr;
- break;
- default:
- ptr_type = builtin_type (ctx.gdbarch)->builtin_data_ptr;
- break;
- }
- address = value_as_address (value_from_pointer (ptr_type, address));
-
- free_values.free_to_mark ();
- retval = value_at_lazy (subobj_type,
- address + subobj_byte_offset);
- if (in_stack_memory)
- set_value_stack (retval, 1);
- }
- break;
-
- case DWARF_VALUE_STACK:
- {
- struct value *value = ctx.fetch (0);
- size_t n = TYPE_LENGTH (value_type (value));
- size_t len = TYPE_LENGTH (subobj_type);
- size_t max = TYPE_LENGTH (type);
- struct gdbarch *objfile_gdbarch = get_objfile_arch (objfile);
-
- if (subobj_byte_offset + len > max)
- invalid_synthetic_pointer ();
-
- /* Preserve VALUE because we are going to free values back
- to the mark, but we still need the value contents
- below. */
- value_ref_ptr value_holder = value_ref_ptr::new_reference (value);
- free_values.free_to_mark ();
-
- retval = allocate_value (subobj_type);
-
- /* The given offset is relative to the actual object. */
- if (gdbarch_byte_order (objfile_gdbarch) == BFD_ENDIAN_BIG)
- subobj_byte_offset += n - max;
-
- memcpy (value_contents_raw (retval),
- value_contents_all (value) + subobj_byte_offset, len);
- }
- break;
-
- case DWARF_VALUE_LITERAL:
- {
- bfd_byte *contents;
- size_t n = TYPE_LENGTH (subobj_type);
-
- if (subobj_byte_offset + n > ctx.len)
- invalid_synthetic_pointer ();
-
- free_values.free_to_mark ();
- retval = allocate_value (subobj_type);
- contents = value_contents_raw (retval);
- memcpy (contents, ctx.data + subobj_byte_offset, n);
- }
- break;
-
- case DWARF_VALUE_OPTIMIZED_OUT:
- free_values.free_to_mark ();
- retval = allocate_optimized_out_value (subobj_type);
- break;
-
- /* DWARF_VALUE_IMPLICIT_POINTER was converted to a pieced
- operation by execute_stack_op. */
- case DWARF_VALUE_IMPLICIT_POINTER:
- /* DWARF_VALUE_OPTIMIZED_OUT can't occur in this context --
- it can only be encountered when making a piece. */
- default:
- internal_error (__FILE__, __LINE__, _("invalid location type"));
- }
- }
-
- set_value_initialized (retval, ctx.initialized);
-
- return retval;
+ return retval->copy ();
}
/* The exported interface to dwarf2_evaluate_loc_desc_full; it always
passes 0 as the byte_offset. */
struct value *
-dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame,
+dwarf2_evaluate_loc_desc (struct type *type, frame_info_ptr frame,
const gdb_byte *data, size_t size,
- struct dwarf2_per_cu_data *per_cu)
+ dwarf2_per_cu_data *per_cu,
+ dwarf2_per_objfile *per_objfile, bool as_lval)
{
return dwarf2_evaluate_loc_desc_full (type, frame, data, size, per_cu,
- NULL, 0);
+ per_objfile, NULL, 0, as_lval);
}
-/* Evaluates a dwarf expression and stores the result in VAL, expecting
- that the dwarf expression only produces a single CORE_ADDR. FRAME is the
- frame in which the expression is evaluated. ADDR is a context (location of
- a variable) and might be needed to evaluate the location expression.
- Returns 1 on success, 0 otherwise. */
+/* Evaluates a dwarf expression and stores the result in VAL,
+ expecting that the dwarf expression only produces a single
+ CORE_ADDR. FRAME is the frame in which the expression is
+ evaluated. ADDR_STACK is a context (location of a variable) and
+ might be needed to evaluate the location expression.
+
+ PUSH_VALUES is an array of values to be pushed to the expression stack
+ before evaluation starts. PUSH_VALUES[0] is pushed first, then
+ PUSH_VALUES[1], and so on.
+
+ Returns 1 on success, 0 otherwise. */
static int
dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
- struct frame_info *frame,
- CORE_ADDR addr,
- CORE_ADDR *valp)
+ frame_info_ptr frame,
+ const struct property_addr_info *addr_stack,
+ CORE_ADDR *valp,
+ gdb::array_view<CORE_ADDR> push_values,
+ bool *is_reference)
{
- struct objfile *objfile;
-
if (dlbaton == NULL || dlbaton->size == 0)
return 0;
- dwarf_evaluate_loc_desc ctx;
+ dwarf2_per_objfile *per_objfile = dlbaton->per_objfile;
+ dwarf2_per_cu_data *per_cu = dlbaton->per_cu;
+ dwarf_expr_context ctx (per_objfile, per_cu->addr_size ());
- ctx.frame = frame;
- ctx.per_cu = dlbaton->per_cu;
- ctx.obj_address = addr;
-
- objfile = dlbaton->per_cu->objfile ();
+ value *result;
+ scoped_value_mark free_values;
- ctx.gdbarch = get_objfile_arch (objfile);
- ctx.addr_size = dlbaton->per_cu->addr_size ();
- ctx.ref_addr_size = dlbaton->per_cu->ref_addr_size ();
- ctx.offset = dlbaton->per_cu->text_offset ();
+ /* Place any initial values onto the expression stack. */
+ for (const auto &val : push_values)
+ ctx.push_address (val, false);
try
{
- ctx.eval (dlbaton->data, dlbaton->size);
+ result = ctx.evaluate (dlbaton->data, dlbaton->size,
+ true, per_cu, frame, addr_stack);
}
catch (const gdb_exception_error &ex)
{
throw;
}
- switch (ctx.location)
+ if (result->optimized_out ())
+ return 0;
+
+ if (VALUE_LVAL (result) == lval_memory)
+ *valp = result->address ();
+ else
{
- case DWARF_VALUE_REGISTER:
- case DWARF_VALUE_MEMORY:
- case DWARF_VALUE_STACK:
- *valp = ctx.fetch_address (0);
- if (ctx.location == DWARF_VALUE_REGISTER)
- *valp = ctx.read_addr_from_reg (*valp);
- return 1;
- case DWARF_VALUE_LITERAL:
- *valp = extract_signed_integer (ctx.data, ctx.len,
- gdbarch_byte_order (ctx.gdbarch));
- return 1;
- /* Unsupported dwarf values. */
- case DWARF_VALUE_OPTIMIZED_OUT:
- case DWARF_VALUE_IMPLICIT_POINTER:
- break;
+ if (VALUE_LVAL (result) == not_lval)
+ *is_reference = false;
+
+ *valp = value_as_address (result);
}
- return 0;
+ return 1;
}
-/* See dwarf2loc.h. */
+/* See dwarf2/loc.h. */
bool
dwarf2_evaluate_property (const struct dynamic_prop *prop,
- struct frame_info *frame,
+ frame_info_ptr frame,
const struct property_addr_info *addr_stack,
- CORE_ADDR *value)
+ CORE_ADDR *value,
+ gdb::array_view<CORE_ADDR> push_values)
{
if (prop == NULL)
return false;
+ /* Evaluating a property should not change the current language.
+ Without this here this could happen if the code below selects a
+ frame. */
+ scoped_restore_current_language save_language;
+
if (frame == NULL && has_stack_frames ())
frame = get_selected_frame (NULL);
- switch (prop->kind)
+ switch (prop->kind ())
{
case PROP_LOCEXPR:
{
const struct dwarf2_property_baton *baton
- = (const struct dwarf2_property_baton *) prop->data.baton;
+ = (const struct dwarf2_property_baton *) prop->baton ();
gdb_assert (baton->property_type != NULL);
- if (dwarf2_locexpr_baton_eval (&baton->locexpr, frame,
- addr_stack ? addr_stack->addr : 0,
- value))
+ bool is_reference = baton->locexpr.is_reference;
+ if (dwarf2_locexpr_baton_eval (&baton->locexpr, frame, addr_stack,
+ value, push_values, &is_reference))
{
- if (baton->locexpr.is_reference)
+ if (is_reference)
{
struct value *val = value_at (baton->property_type, *value);
*value = value_as_address (val);
gdb_assert (baton->property_type != NULL);
struct type *type = check_typedef (baton->property_type);
- if (TYPE_LENGTH (type) < sizeof (CORE_ADDR)
- && !TYPE_UNSIGNED (type))
+ if (type->length () < sizeof (CORE_ADDR)
+ && !type->is_unsigned ())
{
/* If we have a valid return candidate and it's value
is signed, we have to sign-extend the value because
case PROP_LOCLIST:
{
struct dwarf2_property_baton *baton
- = (struct dwarf2_property_baton *) prop->data.baton;
+ = (struct dwarf2_property_baton *) prop->baton ();
CORE_ADDR pc;
const gdb_byte *data;
struct value *val;
if (data != NULL)
{
val = dwarf2_evaluate_loc_desc (baton->property_type, frame, data,
- size, baton->loclist.per_cu);
- if (!value_optimized_out (val))
+ size, baton->loclist.per_cu,
+ baton->loclist.per_objfile);
+ if (!val->optimized_out ())
{
*value = value_as_address (val);
return true;
break;
case PROP_CONST:
- *value = prop->data.const_val;
+ *value = prop->const_val ();
return true;
case PROP_ADDR_OFFSET:
{
struct dwarf2_property_baton *baton
- = (struct dwarf2_property_baton *) prop->data.baton;
+ = (struct dwarf2_property_baton *) prop->baton ();
const struct property_addr_info *pinfo;
struct value *val;
}
if (pinfo == NULL)
error (_("cannot find reference address for offset property"));
- if (pinfo->valaddr != NULL)
+ if (pinfo->valaddr.data () != NULL)
val = value_from_contents
(baton->offset_info.type,
- pinfo->valaddr + baton->offset_info.offset);
+ pinfo->valaddr.data () + baton->offset_info.offset);
else
val = value_at (baton->offset_info.type,
pinfo->addr + baton->offset_info.offset);
*value = value_as_address (val);
return true;
}
+
+ case PROP_VARIABLE_NAME:
+ {
+ struct value *val = compute_var_value (prop->variable_name ());
+ if (val != nullptr)
+ {
+ *value = value_as_long (val);
+ return true;
+ }
+ }
+ break;
}
return false;
}
-/* See dwarf2loc.h. */
+/* See dwarf2/loc.h. */
void
dwarf2_compile_property_to_c (string_file *stream,
const char *result_name,
struct gdbarch *gdbarch,
- unsigned char *registers_used,
+ std::vector<bool> ®isters_used,
const struct dynamic_prop *prop,
CORE_ADDR pc,
struct symbol *sym)
{
struct dwarf2_property_baton *baton
- = (struct dwarf2_property_baton *) prop->data.baton;
+ = (struct dwarf2_property_baton *) prop->baton ();
const gdb_byte *data;
size_t size;
- struct dwarf2_per_cu_data *per_cu;
+ dwarf2_per_cu_data *per_cu;
+ dwarf2_per_objfile *per_objfile;
+
+ if (prop->kind () == PROP_LOCEXPR)
+ {
+ data = baton->locexpr.data;
+ size = baton->locexpr.size;
+ per_cu = baton->locexpr.per_cu;
+ per_objfile = baton->locexpr.per_objfile;
+ }
+ else
+ {
+ gdb_assert (prop->kind () == PROP_LOCLIST);
+
+ data = dwarf2_find_location_expression (&baton->loclist, &size, pc);
+ per_cu = baton->loclist.per_cu;
+ per_objfile = baton->loclist.per_objfile;
+ }
+
+ compile_dwarf_bounds_to_c (stream, result_name, prop, sym, pc,
+ gdbarch, registers_used,
+ per_cu->addr_size (),
+ data, data + size, per_cu, per_objfile);
+}
+
+/* Compute the correct symbol_needs_kind value for the location
+ expression in EXPR.
+
+ Implemented by traversing the logical control flow graph of the
+ expression. */
+
+static enum symbol_needs_kind
+dwarf2_get_symbol_read_needs (gdb::array_view<const gdb_byte> expr,
+ dwarf2_per_cu_data *per_cu,
+ dwarf2_per_objfile *per_objfile,
+ bfd_endian byte_order,
+ int addr_size,
+ int ref_addr_size,
+ int depth = 0)
+{
+ enum symbol_needs_kind symbol_needs = SYMBOL_NEEDS_NONE;
+
+ /* If the expression is empty, we have nothing to do. */
+ if (expr.empty ())
+ return symbol_needs;
+
+ const gdb_byte *expr_end = expr.data () + expr.size ();
+
+ /* List of operations to visit. Operations in this list are not visited yet,
+ so are not in VISITED_OPS (and vice-versa). */
+ std::vector<const gdb_byte *> ops_to_visit;
+
+ /* Operations already visited. */
+ std::unordered_set<const gdb_byte *> visited_ops;
+
+ /* Insert OP in OPS_TO_VISIT if it is within the expression's range and
+ hasn't been visited yet. */
+ auto insert_in_ops_to_visit
+ = [expr_end, &visited_ops, &ops_to_visit] (const gdb_byte *op_ptr)
+ {
+ if (op_ptr >= expr_end)
+ return;
+
+ if (visited_ops.find (op_ptr) != visited_ops.end ())
+ return;
+
+ ops_to_visit.push_back (op_ptr);
+ };
+
+ /* Expressions can invoke other expressions with DW_OP_call*. Protect against
+ a loop of calls. */
+ const int max_depth = 256;
+
+ if (depth > max_depth)
+ error (_("DWARF-2 expression error: Loop detected."));
+
+ depth++;
+
+ /* Initialize the to-visit list with the first operation. */
+ insert_in_ops_to_visit (&expr[0]);
+
+ while (!ops_to_visit.empty ())
+ {
+ /* Pop one op to visit, mark it as visited. */
+ const gdb_byte *op_ptr = ops_to_visit.back ();
+ ops_to_visit.pop_back ();
+ gdb_assert (visited_ops.find (op_ptr) == visited_ops.end ());
+ visited_ops.insert (op_ptr);
+
+ dwarf_location_atom op = (dwarf_location_atom) *op_ptr;
+
+ /* Most operations have a single possible following operation
+ (they are not conditional branches). The code below updates
+ OP_PTR to point to that following operation, which is pushed
+ back to OPS_TO_VISIT, if needed, at the bottom. Here, leave
+ OP_PTR pointing just after the operand. */
+ op_ptr++;
+
+ /* The DWARF expression might have a bug causing an infinite
+ loop. In that case, quitting is the only way out. */
+ QUIT;
+
+ switch (op)
+ {
+ case DW_OP_lit0:
+ case DW_OP_lit1:
+ case DW_OP_lit2:
+ case DW_OP_lit3:
+ case DW_OP_lit4:
+ case DW_OP_lit5:
+ case DW_OP_lit6:
+ case DW_OP_lit7:
+ case DW_OP_lit8:
+ case DW_OP_lit9:
+ case DW_OP_lit10:
+ case DW_OP_lit11:
+ case DW_OP_lit12:
+ case DW_OP_lit13:
+ case DW_OP_lit14:
+ case DW_OP_lit15:
+ case DW_OP_lit16:
+ case DW_OP_lit17:
+ case DW_OP_lit18:
+ case DW_OP_lit19:
+ case DW_OP_lit20:
+ case DW_OP_lit21:
+ case DW_OP_lit22:
+ case DW_OP_lit23:
+ case DW_OP_lit24:
+ case DW_OP_lit25:
+ case DW_OP_lit26:
+ case DW_OP_lit27:
+ case DW_OP_lit28:
+ case DW_OP_lit29:
+ case DW_OP_lit30:
+ case DW_OP_lit31:
+ case DW_OP_stack_value:
+ case DW_OP_dup:
+ case DW_OP_drop:
+ case DW_OP_swap:
+ case DW_OP_over:
+ case DW_OP_rot:
+ case DW_OP_deref:
+ case DW_OP_abs:
+ case DW_OP_neg:
+ case DW_OP_not:
+ case DW_OP_and:
+ case DW_OP_div:
+ case DW_OP_minus:
+ case DW_OP_mod:
+ case DW_OP_mul:
+ case DW_OP_or:
+ case DW_OP_plus:
+ case DW_OP_shl:
+ case DW_OP_shr:
+ case DW_OP_shra:
+ case DW_OP_xor:
+ case DW_OP_le:
+ case DW_OP_ge:
+ case DW_OP_eq:
+ case DW_OP_lt:
+ case DW_OP_gt:
+ case DW_OP_ne:
+ case DW_OP_GNU_push_tls_address:
+ case DW_OP_nop:
+ case DW_OP_GNU_uninit:
+ case DW_OP_push_object_address:
+ break;
- if (prop->kind == PROP_LOCEXPR)
- {
- data = baton->locexpr.data;
- size = baton->locexpr.size;
- per_cu = baton->locexpr.per_cu;
- }
- else
- {
- gdb_assert (prop->kind == PROP_LOCLIST);
+ case DW_OP_form_tls_address:
+ if (symbol_needs <= SYMBOL_NEEDS_REGISTERS)
+ symbol_needs = SYMBOL_NEEDS_REGISTERS;
+ break;
- data = dwarf2_find_location_expression (&baton->loclist, &size, pc);
- per_cu = baton->loclist.per_cu;
- }
+ case DW_OP_convert:
+ case DW_OP_GNU_convert:
+ case DW_OP_reinterpret:
+ case DW_OP_GNU_reinterpret:
+ case DW_OP_addrx:
+ case DW_OP_GNU_addr_index:
+ case DW_OP_GNU_const_index:
+ case DW_OP_constu:
+ case DW_OP_plus_uconst:
+ case DW_OP_piece:
+ op_ptr = safe_skip_leb128 (op_ptr, expr_end);
+ break;
- compile_dwarf_bounds_to_c (stream, result_name, prop, sym, pc,
- gdbarch, registers_used,
- per_cu->addr_size (),
- data, data + size, per_cu);
-}
+ case DW_OP_consts:
+ op_ptr = safe_skip_leb128 (op_ptr, expr_end);
+ break;
-\f
-/* Helper functions and baton for dwarf2_loc_desc_get_symbol_read_needs. */
+ case DW_OP_bit_piece:
+ op_ptr = safe_skip_leb128 (op_ptr, expr_end);
+ op_ptr = safe_skip_leb128 (op_ptr, expr_end);
+ break;
-class symbol_needs_eval_context : public dwarf_expr_context
-{
- public:
+ case DW_OP_deref_type:
+ case DW_OP_GNU_deref_type:
+ op_ptr++;
+ op_ptr = safe_skip_leb128 (op_ptr, expr_end);
+ break;
- enum symbol_needs_kind needs;
- struct dwarf2_per_cu_data *per_cu;
+ case DW_OP_addr:
+ op_ptr += addr_size;
+ break;
- /* Reads from registers do require a frame. */
- CORE_ADDR read_addr_from_reg (int regnum) override
- {
- needs = SYMBOL_NEEDS_FRAME;
- return 1;
- }
+ case DW_OP_const1u:
+ case DW_OP_const1s:
+ op_ptr += 1;
+ break;
- /* "get_reg_value" callback: Reads from registers do require a
- frame. */
+ case DW_OP_const2u:
+ case DW_OP_const2s:
+ op_ptr += 2;
+ break;
- struct value *get_reg_value (struct type *type, int regnum) override
- {
- needs = SYMBOL_NEEDS_FRAME;
- return value_zero (type, not_lval);
- }
-
- /* Reads from memory do not require a frame. */
- void read_mem (gdb_byte *buf, CORE_ADDR addr, size_t len) override
- {
- memset (buf, 0, len);
- }
-
- /* Frame-relative accesses do require a frame. */
- void get_frame_base (const gdb_byte **start, size_t *length) override
- {
- static gdb_byte lit0 = DW_OP_lit0;
-
- *start = &lit0;
- *length = 1;
-
- needs = SYMBOL_NEEDS_FRAME;
- }
-
- /* CFA accesses require a frame. */
- CORE_ADDR get_frame_cfa () override
- {
- needs = SYMBOL_NEEDS_FRAME;
- return 1;
- }
-
- CORE_ADDR get_frame_pc () override
- {
- needs = SYMBOL_NEEDS_FRAME;
- return 1;
- }
-
- /* Thread-local accesses require registers, but not a frame. */
- CORE_ADDR get_tls_address (CORE_ADDR offset) override
- {
- if (needs <= SYMBOL_NEEDS_REGISTERS)
- needs = SYMBOL_NEEDS_REGISTERS;
- return 1;
- }
-
- /* Helper interface of per_cu_dwarf_call for
- dwarf2_loc_desc_get_symbol_read_needs. */
-
- void dwarf_call (cu_offset die_offset) override
- {
- per_cu_dwarf_call (this, die_offset, per_cu);
- }
-
- /* Helper interface of sect_variable_value for
- dwarf2_loc_desc_get_symbol_read_needs. */
-
- struct value *dwarf_variable_value (sect_offset sect_off) override
- {
- return sect_variable_value (this, sect_off, per_cu);
- }
-
- /* DW_OP_entry_value accesses require a caller, therefore a
- frame. */
+ case DW_OP_const4s:
+ case DW_OP_const4u:
+ op_ptr += 4;
+ break;
- void push_dwarf_reg_entry_value (enum call_site_parameter_kind kind,
- union call_site_parameter_u kind_u,
- int deref_size) override
- {
- needs = SYMBOL_NEEDS_FRAME;
+ case DW_OP_const8s:
+ case DW_OP_const8u:
+ op_ptr += 8;
+ break;
- /* The expression may require some stub values on DWARF stack. */
- push_address (0, 0);
- }
+ case DW_OP_reg0:
+ case DW_OP_reg1:
+ case DW_OP_reg2:
+ case DW_OP_reg3:
+ case DW_OP_reg4:
+ case DW_OP_reg5:
+ case DW_OP_reg6:
+ case DW_OP_reg7:
+ case DW_OP_reg8:
+ case DW_OP_reg9:
+ case DW_OP_reg10:
+ case DW_OP_reg11:
+ case DW_OP_reg12:
+ case DW_OP_reg13:
+ case DW_OP_reg14:
+ case DW_OP_reg15:
+ case DW_OP_reg16:
+ case DW_OP_reg17:
+ case DW_OP_reg18:
+ case DW_OP_reg19:
+ case DW_OP_reg20:
+ case DW_OP_reg21:
+ case DW_OP_reg22:
+ case DW_OP_reg23:
+ case DW_OP_reg24:
+ case DW_OP_reg25:
+ case DW_OP_reg26:
+ case DW_OP_reg27:
+ case DW_OP_reg28:
+ case DW_OP_reg29:
+ case DW_OP_reg30:
+ case DW_OP_reg31:
+ case DW_OP_regx:
+ case DW_OP_breg0:
+ case DW_OP_breg1:
+ case DW_OP_breg2:
+ case DW_OP_breg3:
+ case DW_OP_breg4:
+ case DW_OP_breg5:
+ case DW_OP_breg6:
+ case DW_OP_breg7:
+ case DW_OP_breg8:
+ case DW_OP_breg9:
+ case DW_OP_breg10:
+ case DW_OP_breg11:
+ case DW_OP_breg12:
+ case DW_OP_breg13:
+ case DW_OP_breg14:
+ case DW_OP_breg15:
+ case DW_OP_breg16:
+ case DW_OP_breg17:
+ case DW_OP_breg18:
+ case DW_OP_breg19:
+ case DW_OP_breg20:
+ case DW_OP_breg21:
+ case DW_OP_breg22:
+ case DW_OP_breg23:
+ case DW_OP_breg24:
+ case DW_OP_breg25:
+ case DW_OP_breg26:
+ case DW_OP_breg27:
+ case DW_OP_breg28:
+ case DW_OP_breg29:
+ case DW_OP_breg30:
+ case DW_OP_breg31:
+ case DW_OP_bregx:
+ case DW_OP_fbreg:
+ case DW_OP_call_frame_cfa:
+ case DW_OP_entry_value:
+ case DW_OP_GNU_entry_value:
+ case DW_OP_GNU_parameter_ref:
+ case DW_OP_regval_type:
+ case DW_OP_GNU_regval_type:
+ symbol_needs = SYMBOL_NEEDS_FRAME;
+ break;
- /* DW_OP_addrx and DW_OP_GNU_addr_index doesn't require a frame. */
+ case DW_OP_implicit_value:
+ {
+ uint64_t uoffset;
+ op_ptr = safe_read_uleb128 (op_ptr, expr_end, &uoffset);
+ op_ptr += uoffset;
+ break;
+ }
- CORE_ADDR get_addr_index (unsigned int index) override
- {
- /* Nothing to do. */
- return 1;
- }
+ case DW_OP_implicit_pointer:
+ case DW_OP_GNU_implicit_pointer:
+ op_ptr += ref_addr_size;
+ op_ptr = safe_skip_leb128 (op_ptr, expr_end);
+ break;
- /* DW_OP_push_object_address has a frame already passed through. */
+ case DW_OP_deref_size:
+ case DW_OP_pick:
+ op_ptr++;
+ break;
- CORE_ADDR get_object_address () override
- {
- /* Nothing to do. */
- return 1;
- }
-};
+ case DW_OP_skip:
+ {
+ int64_t offset = extract_signed_integer (op_ptr, 2, byte_order);
+ op_ptr += 2;
+ op_ptr += offset;
+ break;
+ }
-/* Compute the correct symbol_needs_kind value for the location
- expression at DATA (length SIZE). */
+ case DW_OP_bra:
+ {
+ /* This is the only operation that pushes two operations in
+ the to-visit list, so handle it all here. */
+ LONGEST offset = extract_signed_integer (op_ptr, 2, byte_order);
+ op_ptr += 2;
+
+ insert_in_ops_to_visit (op_ptr + offset);
+ insert_in_ops_to_visit (op_ptr);
+ continue;
+ }
-static enum symbol_needs_kind
-dwarf2_loc_desc_get_symbol_read_needs (const gdb_byte *data, size_t size,
- struct dwarf2_per_cu_data *per_cu)
-{
- int in_reg;
- struct objfile *objfile = per_cu->objfile ();
+ case DW_OP_call2:
+ case DW_OP_call4:
+ {
+ unsigned int len = op == DW_OP_call2 ? 2 : 4;
+ cu_offset cu_off
+ = (cu_offset) extract_unsigned_integer (op_ptr, len, byte_order);
+ op_ptr += len;
- scoped_value_mark free_values;
+ auto get_frame_pc = [&symbol_needs] ()
+ {
+ symbol_needs = SYMBOL_NEEDS_FRAME;
+ return 0;
+ };
+
+ struct dwarf2_locexpr_baton baton
+ = dwarf2_fetch_die_loc_cu_off (cu_off, per_cu,
+ per_objfile,
+ get_frame_pc);
+
+ /* If SYMBOL_NEEDS_FRAME is returned from the previous call,
+ we dont have to check the baton content. */
+ if (symbol_needs != SYMBOL_NEEDS_FRAME)
+ {
+ gdbarch *arch = baton.per_objfile->objfile->arch ();
+ gdb::array_view<const gdb_byte> sub_expr (baton.data,
+ baton.size);
+ symbol_needs
+ = dwarf2_get_symbol_read_needs (sub_expr,
+ baton.per_cu,
+ baton.per_objfile,
+ gdbarch_byte_order (arch),
+ baton.per_cu->addr_size (),
+ baton.per_cu->ref_addr_size (),
+ depth);
+ }
+ break;
+ }
- symbol_needs_eval_context ctx;
+ case DW_OP_GNU_variable_value:
+ {
+ sect_offset sect_off
+ = (sect_offset) extract_unsigned_integer (op_ptr,
+ ref_addr_size,
+ byte_order);
+ op_ptr += ref_addr_size;
+
+ struct type *die_type
+ = dwarf2_fetch_die_type_sect_off (sect_off, per_cu,
+ per_objfile);
+
+ if (die_type == NULL)
+ error (_("Bad DW_OP_GNU_variable_value DIE."));
+
+ /* Note: Things still work when the following test is
+ removed. This test and error is here to conform to the
+ proposed specification. */
+ if (die_type->code () != TYPE_CODE_INT
+ && die_type->code () != TYPE_CODE_PTR)
+ error (_("Type of DW_OP_GNU_variable_value DIE must be "
+ "an integer or pointer."));
+
+ auto get_frame_pc = [&symbol_needs] ()
+ {
+ symbol_needs = SYMBOL_NEEDS_FRAME;
+ return 0;
+ };
+
+ struct dwarf2_locexpr_baton baton
+ = dwarf2_fetch_die_loc_sect_off (sect_off, per_cu,
+ per_objfile,
+ get_frame_pc, true);
+
+ /* If SYMBOL_NEEDS_FRAME is returned from the previous call,
+ we dont have to check the baton content. */
+ if (symbol_needs != SYMBOL_NEEDS_FRAME)
+ {
+ gdbarch *arch = baton.per_objfile->objfile->arch ();
+ gdb::array_view<const gdb_byte> sub_expr (baton.data,
+ baton.size);
+ symbol_needs
+ = dwarf2_get_symbol_read_needs (sub_expr,
+ baton.per_cu,
+ baton.per_objfile,
+ gdbarch_byte_order (arch),
+ baton.per_cu->addr_size (),
+ baton.per_cu->ref_addr_size (),
+ depth);
+ }
+ break;
+ }
- ctx.needs = SYMBOL_NEEDS_NONE;
- ctx.per_cu = per_cu;
- ctx.gdbarch = get_objfile_arch (objfile);
- ctx.addr_size = per_cu->addr_size ();
- ctx.ref_addr_size = per_cu->ref_addr_size ();
- ctx.offset = per_cu->text_offset ();
+ case DW_OP_const_type:
+ case DW_OP_GNU_const_type:
+ {
+ uint64_t uoffset;
+ op_ptr = safe_read_uleb128 (op_ptr, expr_end, &uoffset);
+ gdb_byte offset = *op_ptr++;
+ op_ptr += offset;
+ break;
+ }
- ctx.eval (data, size);
+ default:
+ error (_("Unhandled DWARF expression opcode 0x%x"), op);
+ }
- in_reg = ctx.location == DWARF_VALUE_REGISTER;
+ /* If it is known that a frame information is
+ needed we can stop parsing the expression. */
+ if (symbol_needs == SYMBOL_NEEDS_FRAME)
+ break;
- /* If the location has several pieces, and any of them are in
- registers, then we will need a frame to fetch them from. */
- for (dwarf_expr_piece &p : ctx.pieces)
- if (p.location == DWARF_VALUE_REGISTER)
- in_reg = 1;
+ insert_in_ops_to_visit (op_ptr);
+ }
- if (in_reg)
- ctx.needs = SYMBOL_NEEDS_FRAME;
- return ctx.needs;
+ return symbol_needs;
}
/* A helper function that throws an unimplemented error mentioning a
op);
}
-/* See dwarf2loc.h.
+/* See dwarf2/loc.h.
This is basically a wrapper on gdbarch_dwarf2_reg_to_regnum so that we
can issue a complaint, which is better than having every target's
pulongest (dwarf_reg));
}
-/* See dwarf2loc.h. */
+/* See dwarf2/loc.h. */
int
dwarf_reg_to_regnum_or_error (struct gdbarch *arch, ULONGEST dwarf_reg)
}
}
-/* A helper function to return the frame's PC. */
-
-static CORE_ADDR
-get_ax_pc (void *baton)
-{
- struct agent_expr *expr = (struct agent_expr *) baton;
-
- return expr->scope;
-}
-
/* Compile a DWARF location expression to an agent expression.
EXPR is the agent expression we are building.
dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc,
unsigned int addr_size, const gdb_byte *op_ptr,
const gdb_byte *op_end,
- struct dwarf2_per_cu_data *per_cu)
+ dwarf2_per_cu_data *per_cu,
+ dwarf2_per_objfile *per_objfile)
{
gdbarch *arch = expr->gdbarch;
std::vector<int> dw_labels, patches;
index, not an address. We don't support things like
branching between the address and the TLS op. */
if (op_ptr >= op_end || *op_ptr != DW_OP_GNU_push_tls_address)
- uoffset += per_cu->text_offset ();
+ uoffset += per_objfile->objfile->text_section_offset ();
ax_const_l (expr, uoffset);
break;
ax_const_l (expr, extract_unsigned_integer (op_ptr, 1, byte_order));
op_ptr += 1;
break;
+
case DW_OP_const1s:
ax_const_l (expr, extract_signed_integer (op_ptr, 1, byte_order));
op_ptr += 1;
break;
+
case DW_OP_const2u:
ax_const_l (expr, extract_unsigned_integer (op_ptr, 2, byte_order));
op_ptr += 2;
break;
+
case DW_OP_const2s:
ax_const_l (expr, extract_signed_integer (op_ptr, 2, byte_order));
op_ptr += 2;
break;
+
case DW_OP_const4u:
ax_const_l (expr, extract_unsigned_integer (op_ptr, 4, byte_order));
op_ptr += 4;
break;
+
case DW_OP_const4s:
ax_const_l (expr, extract_signed_integer (op_ptr, 4, byte_order));
op_ptr += 4;
break;
+
case DW_OP_const8u:
ax_const_l (expr, extract_unsigned_integer (op_ptr, 8, byte_order));
op_ptr += 8;
break;
+
case DW_OP_const8s:
ax_const_l (expr, extract_signed_integer (op_ptr, 8, byte_order));
op_ptr += 8;
break;
+
case DW_OP_constu:
op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
ax_const_l (expr, uoffset);
break;
+
case DW_OP_consts:
op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
ax_const_l (expr, offset);
ax_simple (expr, aop_add);
}
break;
+
case DW_OP_bregx:
{
op_ptr = safe_read_uleb128 (op_ptr, op_end, ®);
}
}
break;
+
case DW_OP_fbreg:
{
const gdb_byte *datastart;
op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
dwarf2_compile_expr_to_ax (expr, loc, addr_size, datastart,
- datastart + datalen, per_cu);
+ datastart + datalen, per_cu,
+ per_objfile);
if (loc->kind == axs_lvalue_register)
require_rvalue (expr, loc);
offset = *op_ptr++;
ax_pick (expr, offset);
break;
-
+
case DW_OP_swap:
ax_simple (expr, aop_swap);
break;
/* Another expression. */
ax_const_l (expr, text_offset);
dwarf2_compile_expr_to_ax (expr, loc, addr_size, cfa_start,
- cfa_end, per_cu);
+ cfa_end, per_cu, per_objfile);
}
loc->kind = axs_lvalue_memory;
case DW_OP_nop:
break;
- case DW_OP_piece:
+ case DW_OP_piece:
case DW_OP_bit_piece:
{
uint64_t size;
error (_("Cannot translate empty pieces to agent expressions"));
previous_piece = op_ptr - 1;
- op_ptr = safe_read_uleb128 (op_ptr, op_end, &size);
+ op_ptr = safe_read_uleb128 (op_ptr, op_end, &size);
if (op == DW_OP_piece)
{
size *= 8;
uoffset = extract_unsigned_integer (op_ptr, size, byte_order);
op_ptr += size;
+ auto get_frame_pc_from_expr = [expr] ()
+ {
+ return expr->scope;
+ };
cu_offset cuoffset = (cu_offset) uoffset;
- block = dwarf2_fetch_die_loc_cu_off (cuoffset, per_cu,
- get_ax_pc, expr);
+ block = dwarf2_fetch_die_loc_cu_off (cuoffset, per_cu, per_objfile,
+ get_frame_pc_from_expr);
/* DW_OP_call_ref is currently not supported. */
gdb_assert (block.per_cu == per_cu);
dwarf2_compile_expr_to_ax (expr, loc, addr_size, block.data,
- block.data + block.size, per_cu);
+ block.data + block.size, per_cu,
+ per_objfile);
}
break;
{
int targ = offsets[dw_labels[i]];
if (targ == -1)
- internal_error (__FILE__, __LINE__, _("invalid label"));
+ internal_error (_("invalid label"));
ax_label (expr, patches[i], targ);
}
}
/* Return the value of SYMBOL in FRAME using the DWARF-2 expression
evaluator to calculate the location. */
static struct value *
-locexpr_read_variable (struct symbol *symbol, struct frame_info *frame)
+locexpr_read_variable (struct symbol *symbol, frame_info_ptr frame)
{
struct dwarf2_locexpr_baton *dlbaton
= (struct dwarf2_locexpr_baton *) SYMBOL_LOCATION_BATON (symbol);
struct value *val;
- val = dwarf2_evaluate_loc_desc (SYMBOL_TYPE (symbol), frame, dlbaton->data,
- dlbaton->size, dlbaton->per_cu);
+ val = dwarf2_evaluate_loc_desc (symbol->type (), frame, dlbaton->data,
+ dlbaton->size, dlbaton->per_cu,
+ dlbaton->per_objfile);
return val;
}
will be thrown. */
static struct value *
-locexpr_read_variable_at_entry (struct symbol *symbol, struct frame_info *frame)
+locexpr_read_variable_at_entry (struct symbol *symbol, frame_info_ptr frame)
{
struct dwarf2_locexpr_baton *dlbaton
= (struct dwarf2_locexpr_baton *) SYMBOL_LOCATION_BATON (symbol);
- return value_of_dwarf_block_entry (SYMBOL_TYPE (symbol), frame, dlbaton->data,
+ return value_of_dwarf_block_entry (symbol->type (), frame, dlbaton->data,
dlbaton->size);
}
struct dwarf2_locexpr_baton *dlbaton
= (struct dwarf2_locexpr_baton *) SYMBOL_LOCATION_BATON (symbol);
- return dwarf2_loc_desc_get_symbol_read_needs (dlbaton->data, dlbaton->size,
- dlbaton->per_cu);
+ gdbarch *arch = dlbaton->per_objfile->objfile->arch ();
+ gdb::array_view<const gdb_byte> expr (dlbaton->data, dlbaton->size);
+
+ return dwarf2_get_symbol_read_needs (expr,
+ dlbaton->per_cu,
+ dlbaton->per_objfile,
+ gdbarch_byte_order (arch),
+ dlbaton->per_cu->addr_size (),
+ dlbaton->per_cu->ref_addr_size ());
}
/* Return true if DATA points to the end of a piece. END is one past
static const gdb_byte *
locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream,
- CORE_ADDR addr, struct objfile *objfile,
- struct dwarf2_per_cu_data *per_cu,
+ CORE_ADDR addr, dwarf2_per_cu_data *per_cu,
+ dwarf2_per_objfile *per_objfile,
const gdb_byte *data, const gdb_byte *end,
unsigned int addr_size)
{
- struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ objfile *objfile = per_objfile->objfile;
+ struct gdbarch *gdbarch = objfile->arch ();
size_t leb128_size;
if (data[0] >= DW_OP_reg0 && data[0] <= DW_OP_reg31)
{
- fprintf_filtered (stream, _("a variable in $%s"),
- locexpr_regname (gdbarch, data[0] - DW_OP_reg0));
+ gdb_printf (stream, _("a variable in $%s"),
+ locexpr_regname (gdbarch, data[0] - DW_OP_reg0));
data += 1;
}
else if (data[0] == DW_OP_regx)
uint64_t reg;
data = safe_read_uleb128 (data + 1, end, ®);
- fprintf_filtered (stream, _("a variable in $%s"),
- locexpr_regname (gdbarch, reg));
+ gdb_printf (stream, _("a variable in $%s"),
+ locexpr_regname (gdbarch, reg));
}
else if (data[0] == DW_OP_fbreg)
{
return save_data;
}
- fprintf_filtered (stream,
- _("a variable at frame base reg $%s offset %s+%s"),
- locexpr_regname (gdbarch, frame_reg),
- plongest (base_offset), plongest (frame_offset));
+ gdb_printf (stream,
+ _("a variable at frame base reg $%s offset %s+%s"),
+ locexpr_regname (gdbarch, frame_reg),
+ plongest (base_offset), plongest (frame_offset));
}
else if (data[0] >= DW_OP_breg0 && data[0] <= DW_OP_breg31
&& piece_end_p (data, end))
data = safe_read_sleb128 (data + 1, end, &offset);
- fprintf_filtered (stream,
- _("a variable at offset %s from base reg $%s"),
- plongest (offset),
- locexpr_regname (gdbarch, data[0] - DW_OP_breg0));
+ gdb_printf (stream,
+ _("a variable at offset %s from base reg $%s"),
+ plongest (offset),
+ locexpr_regname (gdbarch, data[0] - DW_OP_breg0));
}
/* The location expression for a TLS variable looks like this (on a
64-bit LE machine):
DW_AT_location : 10 byte block: 3 4 0 0 0 0 0 0 0 e0
- (DW_OP_addr: 4; DW_OP_GNU_push_tls_address)
+ (DW_OP_addr: 4; DW_OP_GNU_push_tls_address)
0x3 is the encoding for DW_OP_addr, which has an operand as long
as the size of an address on the target machine (here is 8
offset = extract_unsigned_integer (data + 1, addr_size,
gdbarch_byte_order (gdbarch));
- fprintf_filtered (stream,
- _("a thread-local variable at offset 0x%s "
- "in the thread-local storage for `%s'"),
- phex_nz (offset, addr_size), objfile_name (objfile));
+ gdb_printf (stream,
+ _("a thread-local variable at offset 0x%s "
+ "in the thread-local storage for `%s'"),
+ phex_nz (offset, addr_size), objfile_name (objfile));
data += 1 + addr_size + 1;
}
/* With -gsplit-dwarf a TLS variable can also look like this:
DW_AT_location : 3 byte block: fc 4 e0
- (DW_OP_GNU_const_index: 4;
+ (DW_OP_GNU_const_index: 4;
DW_OP_GNU_push_tls_address) */
else if (data + 3 <= end
&& data + 1 + (leb128_size = skip_leb128 (data + 1, end)) < end
uint64_t offset;
data = safe_read_uleb128 (data + 1, end, &offset);
- offset = dwarf2_read_addr_index (per_cu, offset);
- fprintf_filtered (stream,
- _("a thread-local variable at offset 0x%s "
- "in the thread-local storage for `%s'"),
- phex_nz (offset, addr_size), objfile_name (objfile));
+ offset = dwarf2_read_addr_index (per_cu, per_objfile, offset);
+ gdb_printf (stream,
+ _("a thread-local variable at offset 0x%s "
+ "in the thread-local storage for `%s'"),
+ phex_nz (offset, addr_size), objfile_name (objfile));
++data;
}
&& data + 1 < end
&& data[1] == DW_OP_stack_value)
{
- fprintf_filtered (stream, _("the constant %d"), data[0] - DW_OP_lit0);
+ gdb_printf (stream, _("the constant %d"), data[0] - DW_OP_lit0);
data += 2;
}
int offset_size, const gdb_byte *start,
const gdb_byte *data, const gdb_byte *end,
int indent, int all,
- struct dwarf2_per_cu_data *per_cu)
+ dwarf2_per_cu_data *per_cu,
+ dwarf2_per_objfile *per_objfile)
{
while (data < end
&& (all
if (!name)
error (_("Unrecognized DWARF opcode 0x%02x at %ld"),
op, (long) (data - 1 - start));
- fprintf_filtered (stream, " %*ld: %s", indent + 4,
- (long) (data - 1 - start), name);
+ gdb_printf (stream, " %*ld: %s", indent + 4,
+ (long) (data - 1 - start), name);
switch (op)
{
ul = extract_unsigned_integer (data, addr_size,
gdbarch_byte_order (arch));
data += addr_size;
- fprintf_filtered (stream, " 0x%s", phex_nz (ul, addr_size));
+ gdb_printf (stream, " 0x%s", phex_nz (ul, addr_size));
break;
case DW_OP_const1u:
ul = extract_unsigned_integer (data, 1, gdbarch_byte_order (arch));
data += 1;
- fprintf_filtered (stream, " %s", pulongest (ul));
+ gdb_printf (stream, " %s", pulongest (ul));
break;
+
case DW_OP_const1s:
l = extract_signed_integer (data, 1, gdbarch_byte_order (arch));
data += 1;
- fprintf_filtered (stream, " %s", plongest (l));
+ gdb_printf (stream, " %s", plongest (l));
break;
+
case DW_OP_const2u:
ul = extract_unsigned_integer (data, 2, gdbarch_byte_order (arch));
data += 2;
- fprintf_filtered (stream, " %s", pulongest (ul));
+ gdb_printf (stream, " %s", pulongest (ul));
break;
+
case DW_OP_const2s:
l = extract_signed_integer (data, 2, gdbarch_byte_order (arch));
data += 2;
- fprintf_filtered (stream, " %s", plongest (l));
+ gdb_printf (stream, " %s", plongest (l));
break;
+
case DW_OP_const4u:
ul = extract_unsigned_integer (data, 4, gdbarch_byte_order (arch));
data += 4;
- fprintf_filtered (stream, " %s", pulongest (ul));
+ gdb_printf (stream, " %s", pulongest (ul));
break;
+
case DW_OP_const4s:
l = extract_signed_integer (data, 4, gdbarch_byte_order (arch));
data += 4;
- fprintf_filtered (stream, " %s", plongest (l));
+ gdb_printf (stream, " %s", plongest (l));
break;
+
case DW_OP_const8u:
ul = extract_unsigned_integer (data, 8, gdbarch_byte_order (arch));
data += 8;
- fprintf_filtered (stream, " %s", pulongest (ul));
+ gdb_printf (stream, " %s", pulongest (ul));
break;
+
case DW_OP_const8s:
l = extract_signed_integer (data, 8, gdbarch_byte_order (arch));
data += 8;
- fprintf_filtered (stream, " %s", plongest (l));
+ gdb_printf (stream, " %s", plongest (l));
break;
+
case DW_OP_constu:
data = safe_read_uleb128 (data, end, &ul);
- fprintf_filtered (stream, " %s", pulongest (ul));
+ gdb_printf (stream, " %s", pulongest (ul));
break;
+
case DW_OP_consts:
data = safe_read_sleb128 (data, end, &l);
- fprintf_filtered (stream, " %s", plongest (l));
+ gdb_printf (stream, " %s", plongest (l));
break;
case DW_OP_reg0:
case DW_OP_reg29:
case DW_OP_reg30:
case DW_OP_reg31:
- fprintf_filtered (stream, " [$%s]",
- locexpr_regname (arch, op - DW_OP_reg0));
+ gdb_printf (stream, " [$%s]",
+ locexpr_regname (arch, op - DW_OP_reg0));
break;
case DW_OP_regx:
data = safe_read_uleb128 (data, end, &ul);
- fprintf_filtered (stream, " %s [$%s]", pulongest (ul),
- locexpr_regname (arch, (int) ul));
+ gdb_printf (stream, " %s [$%s]", pulongest (ul),
+ locexpr_regname (arch, (int) ul));
break;
case DW_OP_implicit_value:
data = safe_read_uleb128 (data, end, &ul);
data += ul;
- fprintf_filtered (stream, " %s", pulongest (ul));
+ gdb_printf (stream, " %s", pulongest (ul));
break;
case DW_OP_breg0:
case DW_OP_breg30:
case DW_OP_breg31:
data = safe_read_sleb128 (data, end, &l);
- fprintf_filtered (stream, " %s [$%s]", plongest (l),
- locexpr_regname (arch, op - DW_OP_breg0));
+ gdb_printf (stream, " %s [$%s]", plongest (l),
+ locexpr_regname (arch, op - DW_OP_breg0));
break;
case DW_OP_bregx:
data = safe_read_uleb128 (data, end, &ul);
data = safe_read_sleb128 (data, end, &l);
- fprintf_filtered (stream, " register %s [$%s] offset %s",
- pulongest (ul),
- locexpr_regname (arch, (int) ul),
- plongest (l));
+ gdb_printf (stream, " register %s [$%s] offset %s",
+ pulongest (ul),
+ locexpr_regname (arch, (int) ul),
+ plongest (l));
break;
case DW_OP_fbreg:
data = safe_read_sleb128 (data, end, &l);
- fprintf_filtered (stream, " %s", plongest (l));
+ gdb_printf (stream, " %s", plongest (l));
break;
case DW_OP_xderef_size:
case DW_OP_deref_size:
case DW_OP_pick:
- fprintf_filtered (stream, " %d", *data);
+ gdb_printf (stream, " %d", *data);
++data;
break;
case DW_OP_plus_uconst:
data = safe_read_uleb128 (data, end, &ul);
- fprintf_filtered (stream, " %s", pulongest (ul));
+ gdb_printf (stream, " %s", pulongest (ul));
break;
case DW_OP_skip:
l = extract_signed_integer (data, 2, gdbarch_byte_order (arch));
data += 2;
- fprintf_filtered (stream, " to %ld",
- (long) (data + l - start));
+ gdb_printf (stream, " to %ld",
+ (long) (data + l - start));
break;
case DW_OP_bra:
l = extract_signed_integer (data, 2, gdbarch_byte_order (arch));
data += 2;
- fprintf_filtered (stream, " %ld",
- (long) (data + l - start));
+ gdb_printf (stream, " %ld",
+ (long) (data + l - start));
break;
case DW_OP_call2:
ul = extract_unsigned_integer (data, 2, gdbarch_byte_order (arch));
data += 2;
- fprintf_filtered (stream, " offset %s", phex_nz (ul, 2));
+ gdb_printf (stream, " offset %s", phex_nz (ul, 2));
break;
case DW_OP_call4:
ul = extract_unsigned_integer (data, 4, gdbarch_byte_order (arch));
data += 4;
- fprintf_filtered (stream, " offset %s", phex_nz (ul, 4));
+ gdb_printf (stream, " offset %s", phex_nz (ul, 4));
break;
case DW_OP_call_ref:
ul = extract_unsigned_integer (data, offset_size,
gdbarch_byte_order (arch));
data += offset_size;
- fprintf_filtered (stream, " offset %s", phex_nz (ul, offset_size));
+ gdb_printf (stream, " offset %s", phex_nz (ul, offset_size));
break;
- case DW_OP_piece:
+ case DW_OP_piece:
data = safe_read_uleb128 (data, end, &ul);
- fprintf_filtered (stream, " %s (bytes)", pulongest (ul));
+ gdb_printf (stream, " %s (bytes)", pulongest (ul));
break;
case DW_OP_bit_piece:
data = safe_read_uleb128 (data, end, &ul);
data = safe_read_uleb128 (data, end, &offset);
- fprintf_filtered (stream, " size %s offset %s (bits)",
- pulongest (ul), pulongest (offset));
+ gdb_printf (stream, " size %s offset %s (bits)",
+ pulongest (ul), pulongest (offset));
}
break;
data = safe_read_sleb128 (data, end, &l);
- fprintf_filtered (stream, " DIE %s offset %s",
- phex_nz (ul, offset_size),
- plongest (l));
+ gdb_printf (stream, " DIE %s offset %s",
+ phex_nz (ul, offset_size),
+ plongest (l));
}
break;
data = safe_read_uleb128 (data, end, &ul);
cu_offset offset = (cu_offset) ul;
- type = dwarf2_get_die_type (offset, per_cu);
- fprintf_filtered (stream, "<");
+ type = dwarf2_get_die_type (offset, per_cu, per_objfile);
+ gdb_printf (stream, "<");
type_print (type, "", stream, -1);
- fprintf_filtered (stream, " [0x%s]> %d",
- phex_nz (to_underlying (offset), 0),
- deref_addr_size);
+ gdb_printf (stream, " [0x%s]> %d",
+ phex_nz (to_underlying (offset), 0),
+ deref_addr_size);
}
break;
data = safe_read_uleb128 (data, end, &ul);
cu_offset type_die = (cu_offset) ul;
- type = dwarf2_get_die_type (type_die, per_cu);
- fprintf_filtered (stream, "<");
+ type = dwarf2_get_die_type (type_die, per_cu, per_objfile);
+ gdb_printf (stream, "<");
type_print (type, "", stream, -1);
- fprintf_filtered (stream, " [0x%s]>",
- phex_nz (to_underlying (type_die), 0));
+ gdb_printf (stream, " [0x%s]>",
+ phex_nz (to_underlying (type_die), 0));
int n = *data++;
- fprintf_filtered (stream, " %d byte block:", n);
+ gdb_printf (stream, " %d byte block:", n);
for (int i = 0; i < n; ++i)
- fprintf_filtered (stream, " %02x", data[i]);
+ gdb_printf (stream, " %02x", data[i]);
data += n;
}
break;
data = safe_read_uleb128 (data, end, &ul);
cu_offset type_die = (cu_offset) ul;
- type = dwarf2_get_die_type (type_die, per_cu);
- fprintf_filtered (stream, "<");
+ type = dwarf2_get_die_type (type_die, per_cu, per_objfile);
+ gdb_printf (stream, "<");
type_print (type, "", stream, -1);
- fprintf_filtered (stream, " [0x%s]> [$%s]",
- phex_nz (to_underlying (type_die), 0),
- locexpr_regname (arch, reg));
+ gdb_printf (stream, " [0x%s]> [$%s]",
+ phex_nz (to_underlying (type_die), 0),
+ locexpr_regname (arch, reg));
}
break;
cu_offset type_die = (cu_offset) ul;
if (to_underlying (type_die) == 0)
- fprintf_filtered (stream, "<0>");
+ gdb_printf (stream, "<0>");
else
{
struct type *type;
- type = dwarf2_get_die_type (type_die, per_cu);
- fprintf_filtered (stream, "<");
+ type = dwarf2_get_die_type (type_die, per_cu, per_objfile);
+ gdb_printf (stream, "<");
type_print (type, "", stream, -1);
- fprintf_filtered (stream, " [0x%s]>",
- phex_nz (to_underlying (type_die), 0));
+ gdb_printf (stream, " [0x%s]>",
+ phex_nz (to_underlying (type_die), 0));
}
}
break;
case DW_OP_entry_value:
case DW_OP_GNU_entry_value:
data = safe_read_uleb128 (data, end, &ul);
- fputc_filtered ('\n', stream);
+ gdb_putc ('\n', stream);
disassemble_dwarf_expression (stream, arch, addr_size, offset_size,
start, data, data + ul, indent + 2,
- all, per_cu);
+ all, per_cu, per_objfile);
data += ul;
continue;
case DW_OP_GNU_parameter_ref:
ul = extract_unsigned_integer (data, 4, gdbarch_byte_order (arch));
data += 4;
- fprintf_filtered (stream, " offset %s", phex_nz (ul, 4));
+ gdb_printf (stream, " offset %s", phex_nz (ul, 4));
break;
case DW_OP_addrx:
case DW_OP_GNU_addr_index:
data = safe_read_uleb128 (data, end, &ul);
- ul = dwarf2_read_addr_index (per_cu, ul);
- fprintf_filtered (stream, " 0x%s", phex_nz (ul, addr_size));
+ ul = dwarf2_read_addr_index (per_cu, per_objfile, ul);
+ gdb_printf (stream, " 0x%s", phex_nz (ul, addr_size));
break;
+
case DW_OP_GNU_const_index:
data = safe_read_uleb128 (data, end, &ul);
- ul = dwarf2_read_addr_index (per_cu, ul);
- fprintf_filtered (stream, " %s", pulongest (ul));
+ ul = dwarf2_read_addr_index (per_cu, per_objfile, ul);
+ gdb_printf (stream, " %s", pulongest (ul));
break;
case DW_OP_GNU_variable_value:
ul = extract_unsigned_integer (data, offset_size,
gdbarch_byte_order (arch));
data += offset_size;
- fprintf_filtered (stream, " offset %s", phex_nz (ul, offset_size));
+ gdb_printf (stream, " offset %s", phex_nz (ul, offset_size));
break;
}
- fprintf_filtered (stream, "\n");
+ gdb_printf (stream, "\n");
}
return data;
show_dwarf_always_disassemble (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- fprintf_filtered (file,
- _("Whether to always disassemble "
- "DWARF expressions is %s.\n"),
- value);
+ gdb_printf (file,
+ _("Whether to always disassemble "
+ "DWARF expressions is %s.\n"),
+ value);
}
/* Describe a single location, which may in turn consist of multiple
locexpr_describe_location_1 (struct symbol *symbol, CORE_ADDR addr,
struct ui_file *stream,
const gdb_byte *data, size_t size,
- struct objfile *objfile, unsigned int addr_size,
- int offset_size, struct dwarf2_per_cu_data *per_cu)
+ unsigned int addr_size,
+ int offset_size, dwarf2_per_cu_data *per_cu,
+ dwarf2_per_objfile *per_objfile)
{
const gdb_byte *end = data + size;
int first_piece = 1, bad = 0;
+ objfile *objfile = per_objfile->objfile;
while (data < end)
{
if (first_piece)
first_piece = 0;
else
- fprintf_filtered (stream, _(", and "));
+ gdb_printf (stream, _(", and "));
if (!dwarf_always_disassemble)
{
data = locexpr_describe_location_piece (symbol, stream,
- addr, objfile, per_cu,
+ addr, per_cu, per_objfile,
data, end, addr_size);
/* If we printed anything, or if we have an empty piece,
then don't disassemble. */
}
if (disassemble)
{
- fprintf_filtered (stream, _("a complex DWARF expression:\n"));
+ gdb_printf (stream, _("a complex DWARF expression:\n"));
data = disassemble_dwarf_expression (stream,
- get_objfile_arch (objfile),
+ objfile->arch (),
addr_size, offset_size, data,
data, end, 0,
dwarf_always_disassemble,
- per_cu);
+ per_cu, per_objfile);
}
if (data < end)
int empty = data == here;
if (disassemble)
- fprintf_filtered (stream, " ");
+ gdb_printf (stream, " ");
if (data[0] == DW_OP_piece)
{
uint64_t bytes;
data = safe_read_uleb128 (data + 1, end, &bytes);
if (empty)
- fprintf_filtered (stream, _("an empty %s-byte piece"),
- pulongest (bytes));
+ gdb_printf (stream, _("an empty %s-byte piece"),
+ pulongest (bytes));
else
- fprintf_filtered (stream, _(" [%s-byte piece]"),
- pulongest (bytes));
+ gdb_printf (stream, _(" [%s-byte piece]"),
+ pulongest (bytes));
}
else if (data[0] == DW_OP_bit_piece)
{
data = safe_read_uleb128 (data, end, &offset);
if (empty)
- fprintf_filtered (stream,
- _("an empty %s-bit piece"),
- pulongest (bits));
+ gdb_printf (stream,
+ _("an empty %s-bit piece"),
+ pulongest (bits));
else
- fprintf_filtered (stream,
- _(" [%s-bit piece, offset %s bits]"),
- pulongest (bits), pulongest (offset));
+ gdb_printf (stream,
+ _(" [%s-bit piece, offset %s bits]"),
+ pulongest (bits), pulongest (offset));
}
else
{
{
struct dwarf2_locexpr_baton *dlbaton
= (struct dwarf2_locexpr_baton *) SYMBOL_LOCATION_BATON (symbol);
- struct objfile *objfile = dlbaton->per_cu->objfile ();
unsigned int addr_size = dlbaton->per_cu->addr_size ();
int offset_size = dlbaton->per_cu->offset_size ();
locexpr_describe_location_1 (symbol, addr, stream,
dlbaton->data, dlbaton->size,
- objfile, addr_size, offset_size,
- dlbaton->per_cu);
+ addr_size, offset_size,
+ dlbaton->per_cu, dlbaton->per_objfile);
}
/* Describe the location of SYMBOL as an agent value in VALUE, generating
value->optimized_out = 1;
else
dwarf2_compile_expr_to_ax (ax, value, addr_size, dlbaton->data,
- dlbaton->data + dlbaton->size, dlbaton->per_cu);
+ dlbaton->data + dlbaton->size, dlbaton->per_cu,
+ dlbaton->per_objfile);
}
/* symbol_computed_ops 'generate_c_location' method. */
static void
locexpr_generate_c_location (struct symbol *sym, string_file *stream,
struct gdbarch *gdbarch,
- unsigned char *registers_used,
+ std::vector<bool> ®isters_used,
CORE_ADDR pc, const char *result_name)
{
struct dwarf2_locexpr_baton *dlbaton
compile_dwarf_expr_to_c (stream, result_name,
sym, pc, gdbarch, registers_used, addr_size,
dlbaton->data, dlbaton->data + dlbaton->size,
- dlbaton->per_cu);
+ dlbaton->per_cu, dlbaton->per_objfile);
}
/* The set of location functions used with the DWARF-2 expression
/* Return the value of SYMBOL in FRAME using the DWARF-2 expression
evaluator to calculate the location. */
static struct value *
-loclist_read_variable (struct symbol *symbol, struct frame_info *frame)
+loclist_read_variable (struct symbol *symbol, frame_info_ptr frame)
{
struct dwarf2_loclist_baton *dlbaton
= (struct dwarf2_loclist_baton *) SYMBOL_LOCATION_BATON (symbol);
CORE_ADDR pc = frame ? get_frame_address_in_block (frame) : 0;
data = dwarf2_find_location_expression (dlbaton, &size, pc);
- val = dwarf2_evaluate_loc_desc (SYMBOL_TYPE (symbol), frame, data, size,
- dlbaton->per_cu);
+ val = dwarf2_evaluate_loc_desc (symbol->type (), frame, data, size,
+ dlbaton->per_cu, dlbaton->per_objfile);
return val;
}
if it cannot resolve the parameter for any reason. */
static struct value *
-loclist_read_variable_at_entry (struct symbol *symbol, struct frame_info *frame)
+loclist_read_variable_at_entry (struct symbol *symbol, frame_info_ptr frame)
{
struct dwarf2_loclist_baton *dlbaton
= (struct dwarf2_loclist_baton *) SYMBOL_LOCATION_BATON (symbol);
CORE_ADDR pc;
if (frame == NULL || !get_frame_func_if_available (frame, &pc))
- return allocate_optimized_out_value (SYMBOL_TYPE (symbol));
+ return value::allocate_optimized_out (symbol->type ());
data = dwarf2_find_location_expression (dlbaton, &size, pc);
if (data == NULL)
- return allocate_optimized_out_value (SYMBOL_TYPE (symbol));
+ return value::allocate_optimized_out (symbol->type ());
- return value_of_dwarf_block_entry (SYMBOL_TYPE (symbol), frame, data, size);
+ return value_of_dwarf_block_entry (symbol->type (), frame, data, size);
}
/* Implementation of get_symbol_read_needs from
struct dwarf2_loclist_baton *dlbaton
= (struct dwarf2_loclist_baton *) SYMBOL_LOCATION_BATON (symbol);
const gdb_byte *loc_ptr, *buf_end;
- struct objfile *objfile = dlbaton->per_cu->objfile ();
- struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ dwarf2_per_objfile *per_objfile = dlbaton->per_objfile;
+ struct objfile *objfile = per_objfile->objfile;
+ struct gdbarch *gdbarch = objfile->arch ();
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
unsigned int addr_size = dlbaton->per_cu->addr_size ();
int offset_size = dlbaton->per_cu->offset_size ();
- int signed_addr_p = bfd_get_sign_extend_vma (objfile->obfd);
- /* Adjust base_address for relocatable objects. */
- CORE_ADDR base_offset = dlbaton->per_cu->text_offset ();
- CORE_ADDR base_address = dlbaton->base_address + base_offset;
+ int signed_addr_p = bfd_get_sign_extend_vma (objfile->obfd.get ());
+ /* Adjustment for relocatable objects. */
+ CORE_ADDR text_offset = objfile->text_section_offset ();
+ CORE_ADDR base_address = dlbaton->base_address;
int done = 0;
loc_ptr = dlbaton->data;
buf_end = dlbaton->data + dlbaton->size;
- fprintf_filtered (stream, _("multi-location:\n"));
+ gdb_printf (stream, _("multi-location:\n"));
/* Iterate through locations until we run out. */
while (!done)
enum debug_loc_kind kind;
const gdb_byte *new_ptr = NULL; /* init for gcc -Wall */
- if (dlbaton->from_dwo)
+ if (dlbaton->per_cu->version () < 5 && dlbaton->from_dwo)
kind = decode_debug_loc_dwo_addresses (dlbaton->per_cu,
+ dlbaton->per_objfile,
loc_ptr, buf_end, &new_ptr,
&low, &high, byte_order);
- else
+ else if (dlbaton->per_cu->version () < 5)
kind = decode_debug_loc_addresses (loc_ptr, buf_end, &new_ptr,
&low, &high,
byte_order, addr_size,
signed_addr_p);
+ else
+ kind = decode_debug_loclists_addresses (dlbaton->per_cu,
+ dlbaton->per_objfile,
+ loc_ptr, buf_end, &new_ptr,
+ &low, &high, byte_order,
+ addr_size, signed_addr_p);
loc_ptr = new_ptr;
switch (kind)
{
case DEBUG_LOC_END_OF_LIST:
done = 1;
continue;
+
case DEBUG_LOC_BASE_ADDRESS:
- base_address = high + base_offset;
- fprintf_filtered (stream, _(" Base address %s"),
- paddress (gdbarch, base_address));
+ base_address = high;
+ gdb_printf (stream, _(" Base address %s"),
+ paddress (gdbarch, base_address));
continue;
+
case DEBUG_LOC_START_END:
case DEBUG_LOC_START_LENGTH:
+ case DEBUG_LOC_OFFSET_PAIR:
break;
+
case DEBUG_LOC_BUFFER_OVERFLOW:
case DEBUG_LOC_INVALID_ENTRY:
error (_("Corrupted DWARF expression for symbol \"%s\"."),
symbol->print_name ());
+
default:
gdb_assert_not_reached ("bad debug_loc_kind");
}
/* Otherwise, a location expression entry. */
- low += base_address;
- high += base_address;
+ low += text_offset;
+ high += text_offset;
+ if (!dlbaton->from_dwo && kind == DEBUG_LOC_OFFSET_PAIR)
+ {
+ low += base_address;
+ high += base_address;
+ }
low = gdbarch_adjust_dwarf2_addr (gdbarch, low);
high = gdbarch_adjust_dwarf2_addr (gdbarch, high);
- length = extract_unsigned_integer (loc_ptr, 2, byte_order);
- loc_ptr += 2;
+ if (dlbaton->per_cu->version () < 5)
+ {
+ length = extract_unsigned_integer (loc_ptr, 2, byte_order);
+ loc_ptr += 2;
+ }
+ else
+ {
+ unsigned int bytes_read;
+ length = read_unsigned_leb128 (NULL, loc_ptr, &bytes_read);
+ loc_ptr += bytes_read;
+ }
/* (It would improve readability to print only the minimum
necessary digits of the second number of the range.) */
- fprintf_filtered (stream, _(" Range %s-%s: "),
- paddress (gdbarch, low), paddress (gdbarch, high));
+ gdb_printf (stream, _(" Range %s-%s: "),
+ paddress (gdbarch, low), paddress (gdbarch, high));
/* Now describe this particular location. */
locexpr_describe_location_1 (symbol, low, stream, loc_ptr, length,
- objfile, addr_size, offset_size,
- dlbaton->per_cu);
+ addr_size, offset_size,
+ dlbaton->per_cu, dlbaton->per_objfile);
- fprintf_filtered (stream, "\n");
+ gdb_printf (stream, "\n");
loc_ptr += length;
}
value->optimized_out = 1;
else
dwarf2_compile_expr_to_ax (ax, value, addr_size, data, data + size,
- dlbaton->per_cu);
+ dlbaton->per_cu, dlbaton->per_objfile);
}
/* symbol_computed_ops 'generate_c_location' method. */
static void
loclist_generate_c_location (struct symbol *sym, string_file *stream,
struct gdbarch *gdbarch,
- unsigned char *registers_used,
+ std::vector<bool> ®isters_used,
CORE_ADDR pc, const char *result_name)
{
struct dwarf2_loclist_baton *dlbaton
compile_dwarf_expr_to_c (stream, result_name,
sym, pc, gdbarch, registers_used, addr_size,
data, data + size,
- dlbaton->per_cu);
+ dlbaton->per_cu,
+ dlbaton->per_objfile);
}
/* The set of location functions used with the DWARF-2 expression