struct type *
dwarf_expr_context::get_base_type (cu_offset die, int size)
{
- struct type *result;
-
- if (this->funcs->get_base_type)
- {
- result = this->funcs->get_base_type (this, die);
- 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"));
- }
- else
- /* Anything will do. */
- result = builtin_type (this->gdbarch)->builtin_int;
-
+ struct type *result = this->impl_get_base_type (die);
+ 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;
}
case DW_OP_GNU_addr_index:
op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
- result = (this->funcs->get_addr_index) (this->baton, uoffset);
+ result = this->get_addr_index (uoffset);
result += this->offset;
result_val = value_from_ulongest (address_type, result);
break;
case DW_OP_GNU_const_index:
op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
- result = (this->funcs->get_addr_index) (this->baton, uoffset);
+ result = this->get_addr_index (uoffset);
result_val = value_from_ulongest (address_type, result);
break;
case DW_OP_breg31:
{
op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
- result = (this->funcs->read_addr_from_reg) (this->baton,
- op - DW_OP_breg0);
+ result = this->read_addr_from_reg (op - DW_OP_breg0);
result += offset;
result_val = value_from_ulongest (address_type, result);
}
{
op_ptr = safe_read_uleb128 (op_ptr, op_end, ®);
op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
- result = (this->funcs->read_addr_from_reg) (this->baton, reg);
+ result = this->read_addr_from_reg (reg);
result += offset;
result_val = value_from_ulongest (address_type, result);
}
/* FIXME: cagney/2003-03-26: This code should be using
get_frame_base_address(), and then implement a dwarf2
specific this_base method. */
- (this->funcs->get_frame_base) (this->baton, &datastart, &datalen);
+ this->get_frame_base (&datastart, &datalen);
eval (datastart, datalen);
if (this->location == DWARF_VALUE_MEMORY)
result = fetch_address (0);
else if (this->location == DWARF_VALUE_REGISTER)
- result = (this->funcs->read_addr_from_reg)
- (this->baton,
- value_as_long (fetch (0)));
+ result = this->read_addr_from_reg (value_as_long (fetch (0)));
else
error (_("Not implemented: computing frame "
"base using explicit value operator"));
else
type = address_type;
- (this->funcs->read_mem) (this->baton, buf, addr, addr_size);
+ this->read_mem (buf, addr, addr_size);
/* If the size of the object read from memory is different
from the type length, we need to zero-extend it. */
break;
case DW_OP_call_frame_cfa:
- result = (this->funcs->get_frame_cfa) (this->baton);
+ result = this->get_frame_cfa ();
result_val = value_from_ulongest (address_type, result);
in_stack_memory = 1;
break;
returned. */
result = value_as_long (fetch (0));
pop ();
- result = (this->funcs->get_tls_address) (this->baton, result);
+ result = this->get_tls_address (result);
result_val = value_from_ulongest (address_type, result);
break;
offset.cu_off = extract_unsigned_integer (op_ptr, 2, byte_order);
op_ptr += 2;
- this->funcs->dwarf_call (this, offset);
+ this->dwarf_call (offset);
}
goto no_push;
offset.cu_off = extract_unsigned_integer (op_ptr, 4, byte_order);
op_ptr += 4;
- this->funcs->dwarf_call (this, offset);
+ this->dwarf_call (offset);
}
goto no_push;
if (kind_u.dwarf_reg != -1)
{
op_ptr += len;
- this->funcs->push_dwarf_reg_entry_value (this,
- CALL_SITE_PARAMETER_DWARF_REG,
- kind_u,
- -1 /* deref_size */);
+ this->push_dwarf_reg_entry_value (CALL_SITE_PARAMETER_DWARF_REG,
+ kind_u,
+ -1 /* deref_size */);
goto no_push;
}
if (deref_size == -1)
deref_size = this->addr_size;
op_ptr += len;
- this->funcs->push_dwarf_reg_entry_value (this,
- CALL_SITE_PARAMETER_DWARF_REG,
- kind_u, deref_size);
+ this->push_dwarf_reg_entry_value (CALL_SITE_PARAMETER_DWARF_REG,
+ kind_u, deref_size);
goto no_push;
}
kind_u.param_offset.cu_off = extract_unsigned_integer (op_ptr, 4,
byte_order);
op_ptr += 4;
- this->funcs->push_dwarf_reg_entry_value (this,
- CALL_SITE_PARAMETER_PARAM_OFFSET,
- kind_u,
- -1 /* deref_size */);
+ this->push_dwarf_reg_entry_value (CALL_SITE_PARAMETER_PARAM_OFFSET,
+ kind_u,
+ -1 /* deref_size */);
}
goto no_push;
type_die.cu_off = uoffset;
type = get_base_type (type_die, 0);
- result_val = this->funcs->get_reg_value (this->baton, type, reg);
+ result_val = this->get_reg_value (type, reg);
}
break;
case DW_OP_push_object_address:
/* Return the address of the object we are currently observing. */
- result = (this->funcs->get_object_address) (this->baton);
+ result = this->get_object_address ();
result_val = value_from_ulongest (address_type, result);
break;
gdb_assert (this->recursion_depth >= 0);
}
-/* Stub dwarf_expr_context_funcs.get_frame_base implementation. */
-
-void
-ctx_no_get_frame_base (void *baton, const gdb_byte **start, size_t *length)
-{
- error (_("%s is invalid in this context"), "DW_OP_fbreg");
-}
-
-/* Stub dwarf_expr_context_funcs.get_frame_cfa implementation. */
-
-CORE_ADDR
-ctx_no_get_frame_cfa (void *baton)
-{
- error (_("%s is invalid in this context"), "DW_OP_call_frame_cfa");
-}
-
-/* Stub dwarf_expr_context_funcs.get_frame_pc implementation. */
-
-CORE_ADDR
-ctx_no_get_frame_pc (void *baton)
-{
- error (_("%s is invalid in this context"), "DW_OP_GNU_implicit_pointer");
-}
-
-/* Stub dwarf_expr_context_funcs.get_tls_address implementation. */
-
-CORE_ADDR
-ctx_no_get_tls_address (void *baton, CORE_ADDR offset)
-{
- error (_("%s is invalid in this context"), "DW_OP_form_tls_address");
-}
-
-/* Stub dwarf_expr_context_funcs.dwarf_call implementation. */
-
-void
-ctx_no_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset)
-{
- error (_("%s is invalid in this context"), "DW_OP_call*");
-}
-
-/* Stub dwarf_expr_context_funcs.get_base_type implementation. */
-
-struct type *
-ctx_no_get_base_type (struct dwarf_expr_context *ctx, cu_offset die)
-{
- error (_("Support for typed DWARF is not supported in this context"));
-}
-
-/* Stub dwarf_expr_context_funcs.push_dwarf_block_entry_value
- implementation. */
-
-void
-ctx_no_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)
-{
- internal_error (__FILE__, __LINE__,
- _("Support for DW_OP_GNU_entry_value is unimplemented"));
-}
-
-/* Stub dwarf_expr_context_funcs.get_addr_index implementation. */
-
-CORE_ADDR
-ctx_no_get_addr_index (void *baton, unsigned int index)
-{
- error (_("%s is invalid in this context"), "DW_OP_GNU_addr_index");
-}
-
/* Provide a prototype to silence -Wmissing-prototypes. */
extern initialize_file_ftype _initialize_dwarf2expr;
#include "leb128.h"
#include "gdbtypes.h"
-struct dwarf_expr_context;
-
-/* Virtual method table for struct dwarf_expr_context below. */
-
-struct dwarf_expr_context_funcs
-{
- /* Return the value of register number REGNUM (a DWARF register number),
- read as an address. */
- CORE_ADDR (*read_addr_from_reg) (void *baton, int regnum);
-
- /* Return a value of type TYPE, stored in register number REGNUM
- of the frame associated to the given BATON.
-
- REGNUM is a DWARF register number. */
- struct value *(*get_reg_value) (void *baton, struct type *type, int regnum);
-
- /* Read LENGTH bytes at ADDR into BUF. */
- void (*read_mem) (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t length);
-
- /* Return the location expression for the frame base attribute, in
- START and LENGTH. The result must be live until the current
- expression evaluation is complete. */
- void (*get_frame_base) (void *baton, const gdb_byte **start, size_t *length);
-
- /* Return the CFA for the frame. */
- CORE_ADDR (*get_frame_cfa) (void *baton);
-
- /* Return the PC for the frame. */
- CORE_ADDR (*get_frame_pc) (void *baton);
-
- /* Return the thread-local storage address for
- DW_OP_GNU_push_tls_address or DW_OP_form_tls_address. */
- CORE_ADDR (*get_tls_address) (void *baton, CORE_ADDR offset);
-
- /* Execute DW_AT_location expression for the DWARF expression subroutine in
- the DIE at DIE_OFFSET in the CU from CTX. Do not touch STACK while it
- being passed to and returned from the called DWARF subroutine. */
- void (*dwarf_call) (struct dwarf_expr_context *ctx, cu_offset die_offset);
-
- /* Return the base type given by the indicated DIE. This can throw
- an exception if the DIE is invalid or does not represent a base
- type. If can also be NULL in the special case where the
- callbacks are not performing evaluation, and thus it is
- meaningful to substitute a stub type of the correct size. */
- struct type *(*get_base_type) (struct dwarf_expr_context *ctx, cu_offset die);
-
- /* Push on DWARF stack an entry evaluated for DW_TAG_GNU_call_site's
- parameter matching KIND and KIND_U at the caller of specified BATON.
- If DEREF_SIZE is not -1 then use DW_AT_GNU_call_site_data_value instead of
- DW_AT_GNU_call_site_value. */
- void (*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);
-
- /* Return the address indexed by DW_OP_GNU_addr_index.
- This can throw an exception if the index is out of range. */
- CORE_ADDR (*get_addr_index) (void *baton, unsigned int index);
-
- /* Return the `object address' for DW_OP_push_object_address. */
- CORE_ADDR (*get_object_address) (void *baton);
-};
-
/* The location of a value. */
enum dwarf_value_location
{
/* Offset used to relocate DW_OP_addr and DW_OP_GNU_addr_index arguments. */
CORE_ADDR offset;
- /* An opaque argument provided by the caller, which will be passed
- to all of the callback functions. */
- void *baton;
-
- /* Callback functions. */
- const struct dwarf_expr_context_funcs *funcs;
-
/* The current depth of dwarf expression recursion, via DW_OP_call*,
DW_OP_fbreg, DW_OP_push_object_address, etc., and the maximum
depth we'll tolerate before raising an error. */
int num_pieces;
struct dwarf_expr_piece *pieces;
+ /* Return the value of register number REGNUM (a DWARF register number),
+ read as an address. */
+ virtual CORE_ADDR read_addr_from_reg (int regnum) = 0;
+
+ /* Return a value of type TYPE, stored in register number REGNUM
+ of the frame associated to the given BATON.
+
+ REGNUM is a DWARF register number. */
+ virtual struct value *get_reg_value (struct type *type, int regnum) = 0;
+
+ /* Read LENGTH bytes at ADDR into BUF. */
+ virtual void read_mem (gdb_byte *buf, CORE_ADDR addr, size_t length) = 0;
+
+ /* Return the location expression for the frame base attribute, in
+ START and LENGTH. The result must be live until the current
+ expression evaluation is complete. */
+ virtual void get_frame_base (const gdb_byte **start, size_t *length)
+ {
+ error (_("%s is invalid in this context"), "DW_OP_fbreg");
+ }
+
+ /* Return the CFA for the frame. */
+ virtual CORE_ADDR get_frame_cfa ()
+ {
+ error (_("%s is invalid in this context"), "DW_OP_call_frame_cfa");
+ }
+
+ /* Return the PC for the frame. */
+ virtual CORE_ADDR get_frame_pc ()
+ {
+ error (_("%s is invalid in this context"), "DW_OP_GNU_implicit_pointer");
+ }
+
+ /* Return the thread-local storage address for
+ DW_OP_GNU_push_tls_address or DW_OP_form_tls_address. */
+ virtual CORE_ADDR get_tls_address (CORE_ADDR offset)
+ {
+ error (_("%s is invalid in this context"), "DW_OP_form_tls_address");
+ }
+
+ /* Execute DW_AT_location expression for the DWARF expression
+ subroutine in the DIE at DIE_OFFSET in the CU. Do not touch
+ STACK while it being passed to and returned from the called DWARF
+ subroutine. */
+ virtual void dwarf_call (cu_offset die_offset)
+ {
+ error (_("%s is invalid in this context"), "DW_OP_call*");
+ }
+
+ /* Return the base type given by the indicated DIE. This can throw
+ an exception if the DIE is invalid or does not represent a base
+ type. If can also be NULL in the special case where the
+ callbacks are not performing evaluation, and thus it is
+ meaningful to substitute a stub type of the correct size. */
+ virtual struct type *impl_get_base_type (cu_offset die)
+ {
+ /* Anything will do. */
+ return builtin_type (this->gdbarch)->builtin_int;
+ }
+
+ /* Push on DWARF stack an entry evaluated for DW_TAG_GNU_call_site's
+ parameter matching KIND and KIND_U at the caller of specified BATON.
+ If DEREF_SIZE is not -1 then use DW_AT_GNU_call_site_data_value instead of
+ DW_AT_GNU_call_site_value. */
+ virtual void push_dwarf_reg_entry_value (enum call_site_parameter_kind kind,
+ union call_site_parameter_u kind_u,
+ int deref_size)
+ {
+ internal_error (__FILE__, __LINE__,
+ _("Support for DW_OP_GNU_entry_value is unimplemented"));
+ }
+
+ /* Return the address indexed by DW_OP_GNU_addr_index.
+ This can throw an exception if the index is out of range. */
+ virtual CORE_ADDR get_addr_index (unsigned int index)
+ {
+ error (_("%s is invalid in this context"), "DW_OP_GNU_addr_index");
+ }
+
+ /* Return the `object address' for DW_OP_push_object_address. */
+ virtual CORE_ADDR get_object_address ()
+ {
+ internal_error (__FILE__, __LINE__,
+ _("Support for DW_OP_push_object_address "
+ "is unimplemented"));
+ }
+
private:
struct type *address_type () const;
void dwarf_expr_require_composition (const gdb_byte *, const gdb_byte *,
const char *);
-/* Stub dwarf_expr_context_funcs implementations. */
-
-void ctx_no_get_frame_base (void *baton, const gdb_byte **start,
- size_t *length);
-CORE_ADDR ctx_no_get_frame_cfa (void *baton);
-CORE_ADDR ctx_no_get_frame_pc (void *baton);
-CORE_ADDR ctx_no_get_tls_address (void *baton, CORE_ADDR offset);
-void ctx_no_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset);
-struct type *ctx_no_get_base_type (struct dwarf_expr_context *ctx,
- cu_offset die);
-void ctx_no_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);
-CORE_ADDR ctx_no_get_addr_index (void *baton, unsigned int index);
-
int dwarf_block_to_dwarf_reg (const gdb_byte *buf, const gdb_byte *buf_end);
int dwarf_block_to_dwarf_reg_deref (const gdb_byte *buf,
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);
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);
-}
+ struct frame_info *frame;
+ struct dwarf2_per_cu_data *per_cu;
+ CORE_ADDR obj_address;
-/* Callback function for dwarf2_evaluate_loc_desc. */
+ /* Helper function for dwarf2_evaluate_loc_desc. Computes the CFA for
+ the frame in BATON. */
-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;
+ CORE_ADDR get_frame_cfa () OVERRIDE
+ {
+ return dwarf2_frame_cfa (frame);
+ }
- return dwarf2_get_die_type (die_offset, debaton->per_cu);
-}
+ /* 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);
+ }
+
+ /* Callback function for dwarf2_evaluate_loc_desc. */
+ struct type *impl_get_base_type (cu_offset die_offset) OVERRIDE
+ {
+ return dwarf2_get_die_type (die_offset, per_cu);
+ }
+
+ /* 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 dwarf_expr_baton baton_local;
+ 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"));
+
+ baton_local.frame = caller_frame;
+ baton_local.per_cu = caller_per_cu;
+ baton_local.obj_address = 0;
+
+ scoped_restore save_arch = make_scoped_restore (&this->gdbarch);
+ this->gdbarch
+ = get_objfile_arch (dwarf2_per_cu_objfile (baton_local.per_cu));
+ scoped_restore save_addr_size = make_scoped_restore (&this->addr_size);
+ this->addr_size = dwarf2_per_cu_addr_size (baton_local.per_cu);
+ scoped_restore save_offset = make_scoped_restore (&this->offset);
+ this->offset = dwarf2_per_cu_text_offset (baton_local.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. */
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;
-
- ctx->eval (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.. */
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 cleanup *value_chain;
struct objfile *objfile = dwarf2_per_cu_objfile (per_cu);
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;
- 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;
TRY
{
CORE_ADDR addr,
CORE_ADDR *valp)
{
- struct dwarf_expr_baton baton;
struct objfile *objfile;
struct cleanup *cleanup;
if (dlbaton == NULL || dlbaton->size == 0)
return 0;
- 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.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.eval (dlbaton->data, dlbaton->size);
case DWARF_VALUE_STACK:
*valp = ctx.fetch_address (0);
if (ctx.location == DWARF_VALUE_REGISTER)
- *valp = dwarf_expr_read_addr_from_reg (&baton, *valp);
+ *valp = ctx.read_addr_from_reg (*valp);
return 1;
case DWARF_VALUE_LITERAL:
*valp = extract_signed_integer (ctx.data, ctx.len,
\f
/* Helper functions and baton for dwarf2_loc_desc_get_symbol_read_needs. */
-struct symbol_needs_baton
+class symbol_needs_eval_context : public dwarf_expr_context
{
+ public:
+
enum symbol_needs_kind needs;
struct dwarf2_per_cu_data *per_cu;
-};
-
-/* Reads from registers do require a frame. */
-static CORE_ADDR
-symbol_needs_read_addr_from_reg (void *baton, int regnum)
-{
- struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton;
-
- nf_baton->needs = SYMBOL_NEEDS_FRAME;
- return 1;
-}
-
-/* struct dwarf_expr_context_funcs' "get_reg_value" callback:
- Reads from registers do require a frame. */
-
-static struct value *
-symbol_needs_get_reg_value (void *baton, struct type *type, int regnum)
-{
- struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton;
-
- nf_baton->needs = SYMBOL_NEEDS_FRAME;
- return value_zero (type, not_lval);
-}
-
-/* Reads from memory do not require a frame. */
-static void
-symbol_needs_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
-symbol_needs_frame_base (void *baton, const gdb_byte **start, size_t * length)
-{
- static gdb_byte lit0 = DW_OP_lit0;
- struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton;
-
- *start = &lit0;
- *length = 1;
- nf_baton->needs = SYMBOL_NEEDS_FRAME;
-}
-
-/* CFA accesses require a frame. */
-
-static CORE_ADDR
-symbol_needs_frame_cfa (void *baton)
-{
- struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton;
-
- nf_baton->needs = SYMBOL_NEEDS_FRAME;
- return 1;
-}
-
-/* Thread-local accesses require registers, but not a frame. */
-static CORE_ADDR
-symbol_needs_tls_address (void *baton, CORE_ADDR offset)
-{
- struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton;
-
- if (nf_baton->needs <= SYMBOL_NEEDS_REGISTERS)
- nf_baton->needs = SYMBOL_NEEDS_REGISTERS;
- return 1;
-}
-
-/* Helper interface of per_cu_dwarf_call for
- dwarf2_loc_desc_get_symbol_read_needs. */
-
-static void
-symbol_needs_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset)
-{
- struct symbol_needs_baton *nf_baton =
- (struct symbol_needs_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 symbol_needs_baton *nf_baton =
- (struct symbol_needs_baton *) ctx->baton;
-
- nf_baton->needs = SYMBOL_NEEDS_FRAME;
-
- /* The expression may require some stub values on DWARF stack. */
- ctx->push_address (0, 0);
-}
-
-/* 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;
+ }
+
+ /* 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_get_symbol_read_needs
- below. */
+ /* DW_OP_push_object_address has a frame already passed through. */
-static const struct dwarf_expr_context_funcs symbol_needs_ctx_funcs =
-{
- symbol_needs_read_addr_from_reg,
- symbol_needs_get_reg_value,
- symbol_needs_read_mem,
- symbol_needs_frame_base,
- symbol_needs_frame_cfa,
- symbol_needs_frame_cfa, /* get_frame_pc */
- symbol_needs_tls_address,
- symbol_needs_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;
+ }
};
/* Compute the correct symbol_needs_kind value for the location
dwarf2_loc_desc_get_symbol_read_needs (const gdb_byte *data, size_t size,
struct dwarf2_per_cu_data *per_cu)
{
- struct symbol_needs_baton baton;
int in_reg;
struct cleanup *old_chain;
struct objfile *objfile = dwarf2_per_cu_objfile (per_cu);
- baton.needs = SYMBOL_NEEDS_NONE;
- baton.per_cu = per_cu;
+ symbol_needs_eval_context ctx;
+
+ ctx.needs = SYMBOL_NEEDS_NONE;
+ ctx.per_cu = per_cu;
- dwarf_expr_context ctx;
old_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 = &symbol_needs_ctx_funcs;
ctx.eval (data, size);
do_cleanups (old_chain);
if (in_reg)
- baton.needs = SYMBOL_NEEDS_FRAME;
- return baton.needs;
+ ctx.needs = SYMBOL_NEEDS_FRAME;
+ return ctx.needs;
}
/* A helper function that throws an unimplemented error mentioning a