#include "dwarf2loc.h"
#include "dwarf2-frame.h"
#include "compile/compile.h"
+#include <algorithm>
+#include <vector>
extern int dwarf_always_disassemble;
-extern const struct dwarf_expr_context_funcs dwarf_expr_ctx_funcs;
-
static struct value *dwarf2_evaluate_loc_desc_full (struct type *type,
struct frame_info *frame,
const gdb_byte *data,
struct dwarf2_per_cu_data *per_cu,
LONGEST 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);
+
/* Until these have formal names, we define these here.
ref: http://gcc.gnu.org/wiki/DebugFission
Each entry in .debug_loc.dwo begins with a byte that describes the entry,
CORE_ADDR obj_address;
};
-/* Helper functions for dwarf2_evaluate_loc_desc. */
-
-/* Using the frame specified in BATON, return the value of register
- REGNUM, treated as a pointer. */
-static CORE_ADDR
-dwarf_expr_read_addr_from_reg (void *baton, int dwarf_regnum)
-{
- struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
- struct gdbarch *gdbarch = get_frame_arch (debaton->frame);
- int regnum = dwarf_reg_to_regnum_or_error (gdbarch, dwarf_regnum);
-
- return address_from_register (regnum, debaton->frame);
-}
-
-/* Implement struct dwarf_expr_context_funcs' "get_reg_value" callback. */
-
-static struct value *
-dwarf_expr_get_reg_value (void *baton, struct type *type, int dwarf_regnum)
-{
- struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
- struct gdbarch *gdbarch = get_frame_arch (debaton->frame);
- int regnum = dwarf_reg_to_regnum_or_error (gdbarch, dwarf_regnum);
-
- return value_from_register (type, regnum, debaton->frame);
-}
-
-/* Read memory at ADDR (length LEN) into BUF. */
-
-static void
-dwarf_expr_read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len)
-{
- read_memory (addr, buf, len);
-}
-
-/* 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. */
-static void
-dwarf_expr_frame_base (void *baton, const gdb_byte **start, size_t * length)
-{
- /* 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;
- struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
- const struct block *bl = get_frame_block (debaton->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 (debaton->frame),
- start, length);
-}
-
/* Implement find_frame_base_location method for LOC_BLOCK functions using
DWARF expression for its DW_AT_frame_base. */
SYMBOL_NATURAL_NAME (framefunc));
}
-/* Helper function for dwarf2_evaluate_loc_desc. Computes the CFA for
- the frame in BATON. */
-
-static CORE_ADDR
-dwarf_expr_frame_cfa (void *baton)
-{
- struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-
- return dwarf2_frame_cfa (debaton->frame);
-}
-
-/* Helper function for dwarf2_evaluate_loc_desc. Computes the PC for
- the frame in BATON. */
-
-static CORE_ADDR
-dwarf_expr_frame_pc (void *baton)
-{
- struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-
- return get_frame_address_in_block (debaton->frame);
-}
-
-/* Using the objfile specified in BATON, find the address for the
- current thread's thread-local storage with offset OFFSET. */
static CORE_ADDR
-dwarf_expr_tls_address (void *baton, CORE_ADDR offset)
+get_frame_pc_for_per_cu_dwarf_call (void *baton)
{
- struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
- struct objfile *objfile = dwarf2_per_cu_objfile (debaton->per_cu);
+ dwarf_expr_context *ctx = (dwarf_expr_context *) baton;
- return target_translate_tls_address (objfile, offset);
+ return ctx->get_frame_pc ();
}
-/* Call DWARF subroutine from DW_AT_location of DIE at DIE_OFFSET in
- current CU (as is PER_CU). State of the CTX is not affected by the
- call and return. */
-
static void
per_cu_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset,
- struct dwarf2_per_cu_data *per_cu,
- CORE_ADDR (*get_frame_pc) (void *baton),
- void *baton)
+ 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, baton);
+ 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);
- dwarf_expr_eval (ctx, block.data, block.size);
+ ctx->eval (block.data, block.size);
}
-/* Helper interface of per_cu_dwarf_call for dwarf2_evaluate_loc_desc. */
-
-static void
-dwarf_expr_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset)
+class dwarf_evaluate_loc_desc : public dwarf_expr_context
{
- struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) ctx->baton;
+ public:
- per_cu_dwarf_call (ctx, die_offset, debaton->per_cu,
- ctx->funcs->get_frame_pc, ctx->baton);
-}
-
-/* Callback function for dwarf2_evaluate_loc_desc. */
-
-static struct type *
-dwarf_expr_get_base_type (struct dwarf_expr_context *ctx,
- cu_offset die_offset)
-{
- struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) ctx->baton;
+ struct frame_info *frame;
+ struct dwarf2_per_cu_data *per_cu;
+ CORE_ADDR obj_address;
- return dwarf2_get_die_type (die_offset, debaton->per_cu);
-}
+ /* 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 = dwarf2_per_cu_objfile (per_cu);
+
+ 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);
+ }
+
+ 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_GNU_const_type"));
+ if (size != 0 && TYPE_LENGTH (result) != size)
+ error (_("DW_OP_GNU_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_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_GNU_call_site_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 (dwarf2_per_cu_objfile (per_cu));
+ scoped_restore save_addr_size = make_scoped_restore (&this->addr_size);
+ this->addr_size = dwarf2_per_cu_addr_size (per_cu);
+ scoped_restore save_offset = make_scoped_restore (&this->offset);
+ this->offset = dwarf2_per_cu_text_offset (per_cu);
+
+ 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. */
/* Intersect callers. */
- callers = min (result->callers, length);
+ callers = std::min ((long) result->callers, length);
for (idx = 0; idx < callers; idx++)
if (result->call_site[idx] != VEC_index (call_sitep, chain, idx))
{
/* Intersect callees. */
- callees = min (result->callees, length);
+ callees = std::min ((long) result->callees, length);
for (idx = 0; idx < callees; idx++)
if (result->call_site[result->length - 1 - idx]
!= VEC_index (call_sitep, chain, length - 1 - idx))
return dwarf2_evaluate_loc_desc (type, caller_frame, data, size + 1, per_cu);
}
-/* Execute DWARF block of call_site_parameter which matches KIND and KIND_U.
- Choose DEREF_SIZE value of that parameter. Search caller of the CTX's
- frame. CTX must be of dwarf_expr_ctx_funcs kind.
-
- The CTX 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. */
-
-static void
-dwarf_expr_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
- enum call_site_parameter_kind kind,
- union call_site_parameter_u kind_u,
- int deref_size)
-{
- struct dwarf_expr_baton *debaton;
- struct frame_info *frame, *caller_frame;
- struct dwarf2_per_cu_data *caller_per_cu;
- struct dwarf_expr_baton baton_local;
- struct dwarf_expr_context saved_ctx;
- struct call_site_parameter *parameter;
- const gdb_byte *data_src;
- size_t size;
-
- gdb_assert (ctx->funcs == &dwarf_expr_ctx_funcs);
- debaton = (struct dwarf_expr_baton *) ctx->baton;
- frame = debaton->frame;
- 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_GNU_call_site_data_value"));
-
- baton_local.frame = caller_frame;
- baton_local.per_cu = caller_per_cu;
- baton_local.obj_address = 0;
-
- saved_ctx.gdbarch = ctx->gdbarch;
- saved_ctx.addr_size = ctx->addr_size;
- saved_ctx.offset = ctx->offset;
- saved_ctx.baton = ctx->baton;
- ctx->gdbarch = get_objfile_arch (dwarf2_per_cu_objfile (baton_local.per_cu));
- ctx->addr_size = dwarf2_per_cu_addr_size (baton_local.per_cu);
- ctx->offset = dwarf2_per_cu_text_offset (baton_local.per_cu);
- ctx->baton = &baton_local;
-
- dwarf_expr_eval (ctx, data_src, size);
-
- ctx->gdbarch = saved_ctx.gdbarch;
- ctx->addr_size = saved_ctx.addr_size;
- ctx->offset = saved_ctx.offset;
- ctx->baton = saved_ctx.baton;
-}
-
-/* Callback function for dwarf2_evaluate_loc_desc.
- Fetch the address indexed by DW_OP_GNU_addr_index. */
-
-static CORE_ADDR
-dwarf_expr_get_addr_index (void *baton, unsigned int index)
-{
- struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-
- return dwarf2_read_addr_index (debaton->per_cu, index);
-}
-
-/* Callback function for get_object_address. Return the address of the VLA
- object. */
-
-static CORE_ADDR
-dwarf_expr_get_obj_addr (void *baton)
-{
- struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-
- gdb_assert (debaton != NULL);
-
- if (debaton->obj_address == 0)
- error (_("Location address is not set."));
-
- return debaton->obj_address;
-}
-
/* VALUE must be of type lval_computed with entry_data_value_funcs. Perform
the indirect method on it, that is use its stored target value, the sole
purpose of entry_data_value_funcs.. */
struct frame_info *frame = frame_find_by_id (VALUE_FRAME_ID (v));
size_t type_len;
size_t buffer_size = 0;
- gdb_byte *buffer = NULL;
- struct cleanup *cleanup;
+ std::vector<gdb_byte> buffer;
int bits_big_endian
= gdbarch_bits_big_endian (get_type_arch (value_type (v)));
_("Should not be able to create a lazy value with "
"an enclosing type"));
- cleanup = make_cleanup (free_current_contents, &buffer);
-
contents = value_contents_raw (v);
bits_to_skip = 8 * value_offset (v);
if (value_bitsize (v))
if (buffer_size < this_size)
{
buffer_size = this_size;
- buffer = (gdb_byte *) xrealloc (buffer, buffer_size);
+ buffer.reserve (buffer_size);
}
- intermediate_buffer = buffer;
+ intermediate_buffer = buffer.data ();
/* Copy from the source to DEST_BUFFER. */
switch (p->location)
}
if (!get_frame_register_bytes (frame, gdb_regnum, reg_offset,
- this_size, buffer,
+ this_size, buffer.data (),
&optim, &unavail))
{
/* Just so garbage doesn't ever shine through. */
- memset (buffer, 0, this_size);
+ memset (buffer.data (), 0, this_size);
if (optim)
mark_value_bits_optimized_out (v, offset, this_size_bits);
read_value_memory (v, offset,
p->v.mem.in_stack_memory,
p->v.mem.addr + source_offset,
- buffer, this_size);
+ buffer.data (), this_size);
break;
case DWARF_VALUE_STACK:
offset += this_size_bits;
}
-
- do_cleanups (cleanup);
}
static void
struct frame_info *frame = frame_find_by_id (VALUE_FRAME_ID (to));
size_t type_len;
size_t buffer_size = 0;
- gdb_byte *buffer = NULL;
- struct cleanup *cleanup;
+ std::vector<gdb_byte> buffer;
int bits_big_endian
= gdbarch_bits_big_endian (get_type_arch (value_type (to)));
return;
}
- cleanup = make_cleanup (free_current_contents, &buffer);
-
contents = value_contents (from);
bits_to_skip = 8 * value_offset (to);
if (value_bitsize (to))
if (buffer_size < this_size)
{
buffer_size = this_size;
- buffer = (gdb_byte *) xrealloc (buffer, buffer_size);
+ buffer.reserve (buffer_size);
}
- source_buffer = buffer;
+ source_buffer = buffer.data ();
need_bitwise = 1;
}
int optim, unavail;
if (!get_frame_register_bytes (frame, gdb_regnum, reg_offset,
- this_size, buffer,
+ this_size, buffer.data (),
&optim, &unavail))
{
if (optim)
"bitfield; containing word "
"is unavailable"));
}
- copy_bitwise (buffer, dest_offset_bits,
+ copy_bitwise (buffer.data (), dest_offset_bits,
contents, source_offset_bits,
this_size_bits,
bits_big_endian);
{
/* Only the first and last bytes can possibly have any
bits reused. */
- read_memory (p->v.mem.addr + dest_offset, buffer, 1);
+ read_memory (p->v.mem.addr + dest_offset, buffer.data (), 1);
read_memory (p->v.mem.addr + dest_offset + this_size - 1,
- buffer + this_size - 1, 1);
- copy_bitwise (buffer, dest_offset_bits,
+ &buffer[this_size - 1], 1);
+ copy_bitwise (buffer.data (), dest_offset_bits,
contents, source_offset_bits,
this_size_bits,
bits_big_endian);
}
offset += this_size_bits;
}
-
- do_cleanups (cleanup);
}
/* An implementation of an lval_funcs method to see whether a value is
free_pieced_value_closure
};
-/* Virtual method table for dwarf2_evaluate_loc_desc_full below. */
-
-const struct dwarf_expr_context_funcs dwarf_expr_ctx_funcs =
-{
- dwarf_expr_read_addr_from_reg,
- dwarf_expr_get_reg_value,
- dwarf_expr_read_mem,
- dwarf_expr_frame_base,
- dwarf_expr_frame_cfa,
- dwarf_expr_frame_pc,
- dwarf_expr_tls_address,
- dwarf_expr_dwarf_call,
- dwarf_expr_get_base_type,
- dwarf_expr_push_dwarf_reg_entry_value,
- dwarf_expr_get_addr_index,
- dwarf_expr_get_obj_addr
-};
-
/* 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. BYTE_OFFSET is applied after the contents are
LONGEST byte_offset)
{
struct value *retval;
- struct dwarf_expr_baton baton;
- struct dwarf_expr_context *ctx;
- struct cleanup *old_chain, *value_chain;
+ struct cleanup *value_chain;
struct objfile *objfile = dwarf2_per_cu_objfile (per_cu);
if (byte_offset < 0)
if (size == 0)
return allocate_optimized_out_value (type);
- baton.frame = frame;
- baton.per_cu = per_cu;
- baton.obj_address = 0;
+ dwarf_evaluate_loc_desc ctx;
+ ctx.frame = frame;
+ ctx.per_cu = per_cu;
+ ctx.obj_address = 0;
- ctx = new_dwarf_expr_context ();
- old_chain = make_cleanup_free_dwarf_expr_context (ctx);
value_chain = make_cleanup_value_free_to_mark (value_mark ());
- ctx->gdbarch = get_objfile_arch (objfile);
- ctx->addr_size = dwarf2_per_cu_addr_size (per_cu);
- ctx->ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu);
- ctx->offset = dwarf2_per_cu_text_offset (per_cu);
- ctx->baton = &baton;
- ctx->funcs = &dwarf_expr_ctx_funcs;
+ ctx.gdbarch = get_objfile_arch (objfile);
+ ctx.addr_size = dwarf2_per_cu_addr_size (per_cu);
+ ctx.ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu);
+ ctx.offset = dwarf2_per_cu_text_offset (per_cu);
TRY
{
- dwarf_expr_eval (ctx, data, size);
+ ctx.eval (data, size);
}
CATCH (ex, RETURN_MASK_ERROR)
{
if (ex.error == NOT_AVAILABLE_ERROR)
{
- do_cleanups (old_chain);
+ do_cleanups (value_chain);
retval = allocate_value (type);
mark_value_bytes_unavailable (retval, 0, TYPE_LENGTH (type));
return retval;
{
if (entry_values_debug)
exception_print (gdb_stdout, ex);
- do_cleanups (old_chain);
+ do_cleanups (value_chain);
return allocate_optimized_out_value (type);
}
else
}
END_CATCH
- if (ctx->num_pieces > 0)
+ if (ctx.num_pieces > 0)
{
struct piece_closure *c;
struct frame_id frame_id = get_frame_id (frame);
ULONGEST bit_size = 0;
int i;
- for (i = 0; i < ctx->num_pieces; ++i)
- bit_size += ctx->pieces[i].size;
+ for (i = 0; i < ctx.num_pieces; ++i)
+ bit_size += ctx.pieces[i].size;
if (8 * (byte_offset + TYPE_LENGTH (type)) > bit_size)
invalid_synthetic_pointer ();
- c = allocate_piece_closure (per_cu, ctx->num_pieces, ctx->pieces,
- ctx->addr_size);
+ c = allocate_piece_closure (per_cu, ctx.num_pieces, ctx.pieces,
+ ctx.addr_size);
/* We must clean up the value chain after creating the piece
closure but before allocating the result. */
do_cleanups (value_chain);
}
else
{
- switch (ctx->location)
+ switch (ctx.location)
{
case DWARF_VALUE_REGISTER:
{
struct gdbarch *arch = get_frame_arch (frame);
int dwarf_regnum
- = longest_to_int (value_as_long (dwarf_expr_fetch (ctx, 0)));
+ = longest_to_int (value_as_long (ctx.fetch (0)));
int gdb_regnum = dwarf_reg_to_regnum_or_error (arch, dwarf_regnum);
if (byte_offset != 0)
case DWARF_VALUE_MEMORY:
{
struct type *ptr_type;
- CORE_ADDR address = dwarf_expr_fetch_address (ctx, 0);
- int in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0);
+ CORE_ADDR address = ctx.fetch_address (0);
+ int 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
{
case TYPE_CODE_FUNC:
case TYPE_CODE_METHOD:
- ptr_type = builtin_type (ctx->gdbarch)->builtin_func_ptr;
+ ptr_type = builtin_type (ctx.gdbarch)->builtin_func_ptr;
break;
default:
- ptr_type = builtin_type (ctx->gdbarch)->builtin_data_ptr;
+ ptr_type = builtin_type (ctx.gdbarch)->builtin_data_ptr;
break;
}
address = value_as_address (value_from_pointer (ptr_type, address));
case DWARF_VALUE_STACK:
{
- struct value *value = dwarf_expr_fetch (ctx, 0);
+ struct value *value = ctx.fetch (0);
gdb_byte *contents;
const gdb_byte *val_bytes;
size_t n = TYPE_LENGTH (value_type (value));
{
bfd_byte *contents;
const bfd_byte *ldata;
- size_t n = ctx->len;
+ size_t n = ctx.len;
if (byte_offset + TYPE_LENGTH (type) > n)
invalid_synthetic_pointer ();
retval = allocate_value (type);
contents = value_contents_raw (retval);
- ldata = ctx->data + byte_offset;
+ ldata = ctx.data + byte_offset;
n -= byte_offset;
if (n > TYPE_LENGTH (type))
}
}
- set_value_initialized (retval, ctx->initialized);
+ set_value_initialized (retval, ctx.initialized);
- do_cleanups (old_chain);
+ do_cleanups (value_chain);
return retval;
}
CORE_ADDR addr,
CORE_ADDR *valp)
{
- struct dwarf_expr_context *ctx;
- struct dwarf_expr_baton baton;
struct objfile *objfile;
struct cleanup *cleanup;
if (dlbaton == NULL || dlbaton->size == 0)
return 0;
- ctx = new_dwarf_expr_context ();
- cleanup = make_cleanup_free_dwarf_expr_context (ctx);
+ dwarf_evaluate_loc_desc ctx;
- baton.frame = frame;
- baton.per_cu = dlbaton->per_cu;
- baton.obj_address = addr;
+ ctx.frame = frame;
+ ctx.per_cu = dlbaton->per_cu;
+ ctx.obj_address = addr;
objfile = dwarf2_per_cu_objfile (dlbaton->per_cu);
- ctx->gdbarch = get_objfile_arch (objfile);
- ctx->addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
- ctx->ref_addr_size = dwarf2_per_cu_ref_addr_size (dlbaton->per_cu);
- ctx->offset = dwarf2_per_cu_text_offset (dlbaton->per_cu);
- ctx->funcs = &dwarf_expr_ctx_funcs;
- ctx->baton = &baton;
+ ctx.gdbarch = get_objfile_arch (objfile);
+ ctx.addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
+ ctx.ref_addr_size = dwarf2_per_cu_ref_addr_size (dlbaton->per_cu);
+ ctx.offset = dwarf2_per_cu_text_offset (dlbaton->per_cu);
- dwarf_expr_eval (ctx, dlbaton->data, dlbaton->size);
+ ctx.eval (dlbaton->data, dlbaton->size);
- switch (ctx->location)
+ switch (ctx.location)
{
case DWARF_VALUE_REGISTER:
case DWARF_VALUE_MEMORY:
case DWARF_VALUE_STACK:
- *valp = dwarf_expr_fetch_address (ctx, 0);
- if (ctx->location == DWARF_VALUE_REGISTER)
- *valp = dwarf_expr_read_addr_from_reg (&baton, *valp);
- do_cleanups (cleanup);
+ *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));
- do_cleanups (cleanup);
+ *valp = extract_signed_integer (ctx.data, ctx.len,
+ gdbarch_byte_order (ctx.gdbarch));
return 1;
/* Unsupported dwarf values. */
case DWARF_VALUE_OPTIMIZED_OUT:
break;
}
- do_cleanups (cleanup);
return 0;
}
}
\f
-/* Helper functions and baton for dwarf2_loc_desc_needs_frame. */
-
-struct needs_frame_baton
-{
- int needs_frame;
- struct dwarf2_per_cu_data *per_cu;
-};
-
-/* Reads from registers do require a frame. */
-static CORE_ADDR
-needs_frame_read_addr_from_reg (void *baton, int regnum)
-{
- struct needs_frame_baton *nf_baton = (struct needs_frame_baton *) baton;
+/* Helper functions and baton for dwarf2_loc_desc_get_symbol_read_needs. */
- nf_baton->needs_frame = 1;
- return 1;
-}
-
-/* struct dwarf_expr_context_funcs' "get_reg_value" callback:
- Reads from registers do require a frame. */
-
-static struct value *
-needs_frame_get_reg_value (void *baton, struct type *type, int regnum)
-{
- struct needs_frame_baton *nf_baton = (struct needs_frame_baton *) baton;
-
- nf_baton->needs_frame = 1;
- return value_zero (type, not_lval);
-}
-
-/* Reads from memory do not require a frame. */
-static void
-needs_frame_read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len)
-{
- memset (buf, 0, len);
-}
-
-/* Frame-relative accesses do require a frame. */
-static void
-needs_frame_frame_base (void *baton, const gdb_byte **start, size_t * length)
+class symbol_needs_eval_context : public dwarf_expr_context
{
- static gdb_byte lit0 = DW_OP_lit0;
- struct needs_frame_baton *nf_baton = (struct needs_frame_baton *) baton;
-
- *start = &lit0;
- *length = 1;
-
- nf_baton->needs_frame = 1;
-}
+ public:
-/* CFA accesses require a frame. */
-
-static CORE_ADDR
-needs_frame_frame_cfa (void *baton)
-{
- struct needs_frame_baton *nf_baton = (struct needs_frame_baton *) baton;
-
- nf_baton->needs_frame = 1;
- return 1;
-}
-
-/* Thread-local accesses do require a frame. */
-static CORE_ADDR
-needs_frame_tls_address (void *baton, CORE_ADDR offset)
-{
- struct needs_frame_baton *nf_baton = (struct needs_frame_baton *) baton;
-
- nf_baton->needs_frame = 1;
- return 1;
-}
-
-/* Helper interface of per_cu_dwarf_call for dwarf2_loc_desc_needs_frame. */
-
-static void
-needs_frame_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset)
-{
- struct needs_frame_baton *nf_baton = (struct needs_frame_baton *) ctx->baton;
-
- per_cu_dwarf_call (ctx, die_offset, nf_baton->per_cu,
- ctx->funcs->get_frame_pc, ctx->baton);
-}
-
-/* DW_OP_GNU_entry_value accesses require a caller, therefore a frame. */
-
-static void
-needs_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
- enum call_site_parameter_kind kind,
- union call_site_parameter_u kind_u, int deref_size)
-{
- struct needs_frame_baton *nf_baton = (struct needs_frame_baton *) ctx->baton;
-
- nf_baton->needs_frame = 1;
-
- /* The expression may require some stub values on DWARF stack. */
- dwarf_expr_push_address (ctx, 0, 0);
-}
+ enum symbol_needs_kind needs;
+ struct dwarf2_per_cu_data *per_cu;
-/* DW_OP_GNU_addr_index doesn't require a frame. */
+ /* Reads from registers do require a frame. */
+ CORE_ADDR read_addr_from_reg (int regnum) OVERRIDE
+ {
+ needs = SYMBOL_NEEDS_FRAME;
+ return 1;
+ }
+
+ /* "get_reg_value" callback: Reads from registers do require a
+ frame. */
+
+ 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);
+ }
+
+ /* DW_OP_GNU_entry_value accesses require a caller, therefore a
+ frame. */
+
+ 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;
-static CORE_ADDR
-needs_get_addr_index (void *baton, unsigned int index)
-{
- /* Nothing to do. */
- return 1;
-}
+ /* The expression may require some stub values on DWARF stack. */
+ push_address (0, 0);
+ }
-/* DW_OP_push_object_address has a frame already passed through. */
+ /* DW_OP_GNU_addr_index doesn't require a frame. */
-static CORE_ADDR
-needs_get_obj_addr (void *baton)
-{
- /* Nothing to do. */
- return 1;
-}
+ CORE_ADDR get_addr_index (unsigned int index) OVERRIDE
+ {
+ /* Nothing to do. */
+ return 1;
+ }
-/* Virtual method table for dwarf2_loc_desc_needs_frame below. */
+ /* DW_OP_push_object_address has a frame already passed through. */
-static const struct dwarf_expr_context_funcs needs_frame_ctx_funcs =
-{
- needs_frame_read_addr_from_reg,
- needs_frame_get_reg_value,
- needs_frame_read_mem,
- needs_frame_frame_base,
- needs_frame_frame_cfa,
- needs_frame_frame_cfa, /* get_frame_pc */
- needs_frame_tls_address,
- needs_frame_dwarf_call,
- NULL, /* get_base_type */
- needs_dwarf_reg_entry_value,
- needs_get_addr_index,
- needs_get_obj_addr
+ CORE_ADDR get_object_address () OVERRIDE
+ {
+ /* Nothing to do. */
+ return 1;
+ }
};
-/* Return non-zero iff the location expression at DATA (length SIZE)
- requires a frame to evaluate. */
+/* Compute the correct symbol_needs_kind value for the location
+ expression at DATA (length SIZE). */
-static int
-dwarf2_loc_desc_needs_frame (const gdb_byte *data, size_t size,
- struct dwarf2_per_cu_data *per_cu)
+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)
{
- struct needs_frame_baton baton;
- struct dwarf_expr_context *ctx;
int in_reg;
struct cleanup *old_chain;
struct objfile *objfile = dwarf2_per_cu_objfile (per_cu);
- baton.needs_frame = 0;
- baton.per_cu = per_cu;
+ symbol_needs_eval_context ctx;
- ctx = new_dwarf_expr_context ();
- old_chain = make_cleanup_free_dwarf_expr_context (ctx);
- make_cleanup_value_free_to_mark (value_mark ());
+ ctx.needs = SYMBOL_NEEDS_NONE;
+ ctx.per_cu = per_cu;
- ctx->gdbarch = get_objfile_arch (objfile);
- ctx->addr_size = dwarf2_per_cu_addr_size (per_cu);
- ctx->ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu);
- ctx->offset = dwarf2_per_cu_text_offset (per_cu);
- ctx->baton = &baton;
- ctx->funcs = &needs_frame_ctx_funcs;
+ old_chain = make_cleanup_value_free_to_mark (value_mark ());
- dwarf_expr_eval (ctx, data, size);
+ ctx.gdbarch = get_objfile_arch (objfile);
+ ctx.addr_size = dwarf2_per_cu_addr_size (per_cu);
+ ctx.ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu);
+ ctx.offset = dwarf2_per_cu_text_offset (per_cu);
- in_reg = ctx->location == DWARF_VALUE_REGISTER;
+ ctx.eval (data, size);
- if (ctx->num_pieces > 0)
+ in_reg = ctx.location == DWARF_VALUE_REGISTER;
+
+ if (ctx.num_pieces > 0)
{
int i;
/* If the location has several pieces, and any of them are in
registers, then we will need a frame to fetch them from. */
- for (i = 0; i < ctx->num_pieces; i++)
- if (ctx->pieces[i].location == DWARF_VALUE_REGISTER)
+ for (i = 0; i < ctx.num_pieces; i++)
+ if (ctx.pieces[i].location == DWARF_VALUE_REGISTER)
in_reg = 1;
}
do_cleanups (old_chain);
- return baton.needs_frame || in_reg;
+ if (in_reg)
+ ctx.needs = SYMBOL_NEEDS_FRAME;
+ return ctx.needs;
}
/* A helper function that throws an unimplemented error mentioning a
const gdb_byte *op_ptr, const gdb_byte *op_end,
struct dwarf2_per_cu_data *per_cu)
{
- struct cleanup *cleanups;
- int i, *offsets;
- VEC(int) *dw_labels = NULL, *patches = NULL;
+ int i;
+ std::vector<int> dw_labels, patches;
const gdb_byte * const base = op_ptr;
const gdb_byte *previous_piece = op_ptr;
enum bfd_endian byte_order = gdbarch_byte_order (arch);
unsigned int addr_size_bits = 8 * addr_size;
int bits_big_endian = gdbarch_bits_big_endian (arch);
- offsets = XNEWVEC (int, op_end - op_ptr);
- cleanups = make_cleanup (xfree, offsets);
-
- for (i = 0; i < op_end - op_ptr; ++i)
- offsets[i] = -1;
-
- make_cleanup (VEC_cleanup (int), &dw_labels);
- make_cleanup (VEC_cleanup (int), &patches);
+ std::vector<int> offsets (op_end - op_ptr, -1);
/* By default we are making an address. */
loc->kind = axs_lvalue_memory;
break;
case DW_OP_GNU_push_tls_address:
+ case DW_OP_form_tls_address:
unimplemented (op);
break;
offset = extract_signed_integer (op_ptr, 2, byte_order);
op_ptr += 2;
i = ax_goto (expr, aop_goto);
- VEC_safe_push (int, dw_labels, op_ptr + offset - base);
- VEC_safe_push (int, patches, i);
+ dw_labels.push_back (op_ptr + offset - base);
+ patches.push_back (i);
break;
case DW_OP_bra:
/* Zero extend the operand. */
ax_zero_ext (expr, addr_size_bits);
i = ax_goto (expr, aop_if_goto);
- VEC_safe_push (int, dw_labels, op_ptr + offset - base);
- VEC_safe_push (int, patches, i);
+ dw_labels.push_back (op_ptr + offset - base);
+ patches.push_back (i);
break;
case DW_OP_nop:
}
/* Patch all the branches we emitted. */
- for (i = 0; i < VEC_length (int, patches); ++i)
+ for (i = 0; i < patches.size (); ++i)
{
- int targ = offsets[VEC_index (int, dw_labels, i)];
+ int targ = offsets[dw_labels[i]];
if (targ == -1)
internal_error (__FILE__, __LINE__, _("invalid label"));
- ax_label (expr, VEC_index (int, patches, i), targ);
+ ax_label (expr, patches[i], targ);
}
-
- do_cleanups (cleanups);
}
\f
dlbaton->size);
}
-/* Return non-zero iff we need a frame to evaluate SYMBOL. */
-static int
-locexpr_read_needs_frame (struct symbol *symbol)
+/* Implementation of get_symbol_read_needs from
+ symbol_computed_ops. */
+
+static enum symbol_needs_kind
+locexpr_get_symbol_read_needs (struct symbol *symbol)
{
struct dwarf2_locexpr_baton *dlbaton
= (struct dwarf2_locexpr_baton *) SYMBOL_LOCATION_BATON (symbol);
- return dwarf2_loc_desc_needs_frame (dlbaton->data, dlbaton->size,
- dlbaton->per_cu);
+ return dwarf2_loc_desc_get_symbol_read_needs (dlbaton->data, dlbaton->size,
+ dlbaton->per_cu);
}
/* Return true if DATA points to the end of a piece. END is one past
&& (data[0] == DW_OP_addr
|| (addr_size == 4 && data[0] == DW_OP_const4u)
|| (addr_size == 8 && data[0] == DW_OP_const8u))
- && data[1 + addr_size] == DW_OP_GNU_push_tls_address
+ && (data[1 + addr_size] == DW_OP_GNU_push_tls_address
+ || data[1 + addr_size] == DW_OP_form_tls_address)
&& piece_end_p (data + 2 + addr_size, end))
{
ULONGEST offset;
&& data + 1 + (leb128_size = skip_leb128 (data + 1, end)) < end
&& data[0] == DW_OP_GNU_const_index
&& leb128_size > 0
- && data[1 + leb128_size] == DW_OP_GNU_push_tls_address
+ && (data[1 + leb128_size] == DW_OP_GNU_push_tls_address
+ || data[1 + leb128_size] == DW_OP_form_tls_address)
&& piece_end_p (data + 2 + leb128_size, end))
{
uint64_t offset;
const struct symbol_computed_ops dwarf2_locexpr_funcs = {
locexpr_read_variable,
locexpr_read_variable_at_entry,
- locexpr_read_needs_frame,
+ locexpr_get_symbol_read_needs,
locexpr_describe_location,
0, /* location_has_loclist */
locexpr_tracepoint_var_ref,
return value_of_dwarf_block_entry (SYMBOL_TYPE (symbol), frame, data, size);
}
-/* Return non-zero iff we need a frame to evaluate SYMBOL. */
-static int
-loclist_read_needs_frame (struct symbol *symbol)
+/* Implementation of get_symbol_read_needs from
+ symbol_computed_ops. */
+
+static enum symbol_needs_kind
+loclist_symbol_needs (struct symbol *symbol)
{
/* If there's a location list, then assume we need to have a frame
to choose the appropriate location expression. With tracking of
is disabled in GCC at the moment until we figure out how to
represent it. */
- return 1;
+ return SYMBOL_NEEDS_FRAME;
}
/* Print a natural-language description of SYMBOL to STREAM. This
const struct symbol_computed_ops dwarf2_loclist_funcs = {
loclist_read_variable,
loclist_read_variable_at_entry,
- loclist_read_needs_frame,
+ loclist_symbol_needs,
loclist_describe_location,
1, /* location_has_loclist */
loclist_tracepoint_var_ref,