aboutsummaryrefslogtreecommitdiff
path: root/gdb/dwarf2/expr.c
diff options
context:
space:
mode:
authorZoran Zaric <zoran.zaric@amd.com>2020-09-15 16:52:11 +0100
committerZoran Zaric <zoran.zaric@amd.com>2021-08-05 16:40:47 +0100
commitba5bc3e5a9268bcdc701d5a6701a9b41538a3f51 (patch)
treed90bed1f7780e64faf9fe4e92cc7060ab8533745 /gdb/dwarf2/expr.c
parentefa86d3c26457c4c619fddef8232738d5091978b (diff)
downloadbinutils-ba5bc3e5a9268bcdc701d5a6701a9b41538a3f51.zip
binutils-ba5bc3e5a9268bcdc701d5a6701a9b41538a3f51.tar.gz
binutils-ba5bc3e5a9268bcdc701d5a6701a9b41538a3f51.tar.bz2
Make DWARF evaluator return a single struct value
The patch is addressing the issue of class users writing and reading the internal data of the dwarf_expr_context class. At this point, all conditions are met for the DWARF evaluator to return an evaluation result in a form of a single struct value object. gdb/ChangeLog: * dwarf2/expr.c (pieced_value_funcs): Chenge to static function. (allocate_piece_closure): Change to static function. (dwarf_expr_context::fetch_result): New function. * dwarf2/expr.h (struct piece_closure): Remove declaration. (struct dwarf_expr_context): fetch_result new declaration. fetch, fetch_address and fetch_in_stack_memory members move to private. (allocate_piece_closure): Remove. * dwarf2/frame.c (execute_stack_op): Change to use fetch_result. * dwarf2/loc.c (dwarf2_evaluate_loc_desc_full): Change to use fetch_result. (dwarf2_locexpr_baton_eval): Change to use fetch_result. * dwarf2/loc.h (invalid_synthetic_pointer): Expose function.
Diffstat (limited to 'gdb/dwarf2/expr.c')
-rw-r--r--gdb/dwarf2/expr.c159
1 files changed, 156 insertions, 3 deletions
diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
index d0a74f1..5b4b734 100644
--- a/gdb/dwarf2/expr.c
+++ b/gdb/dwarf2/expr.c
@@ -117,9 +117,10 @@ struct piece_closure
struct frame_id frame_id;
};
-/* See expr.h. */
+/* Allocate a closure for a value formed from separately-described
+ PIECES. */
-piece_closure *
+static piece_closure *
allocate_piece_closure (dwarf2_per_cu_data *per_cu,
dwarf2_per_objfile *per_objfile,
std::vector<dwarf_expr_piece> &&pieces,
@@ -612,7 +613,7 @@ free_pieced_value_closure (value *v)
}
/* Functions for accessing a variable described by DW_OP_piece. */
-const struct lval_funcs pieced_value_funcs = {
+static const struct lval_funcs pieced_value_funcs = {
read_pieced_value,
write_pieced_value,
indirect_pieced_value,
@@ -879,6 +880,158 @@ dwarf_expr_context::push_dwarf_reg_entry_value (call_site_parameter_kind kind,
this->eval (data_src, size);
}
+/* See expr.h. */
+
+value *
+dwarf_expr_context::fetch_result (struct type *type, struct type *subobj_type,
+ LONGEST subobj_offset)
+{
+ value *retval = nullptr;
+
+ if (type == nullptr)
+ type = address_type ();
+
+ if (subobj_type == nullptr)
+ subobj_type = type;
+
+ if (this->pieces.size () > 0)
+ {
+ ULONGEST bit_size = 0;
+
+ for (dwarf_expr_piece &piece : this->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 ();
+
+ piece_closure *c
+ = allocate_piece_closure (this->per_cu, this->per_objfile,
+ std::move (this->pieces), this->frame);
+ retval = allocate_computed_value (subobj_type,
+ &pieced_value_funcs, c);
+ set_value_offset (retval, subobj_offset);
+ }
+ else
+ {
+ switch (this->location)
+ {
+ case DWARF_VALUE_REGISTER:
+ {
+ int dwarf_regnum
+ = longest_to_int (value_as_long (this->fetch (0)));
+ int gdb_regnum = dwarf_reg_to_regnum_or_error (this->gdbarch,
+ dwarf_regnum);
+
+ if (subobj_offset != 0)
+ error (_("cannot use offset on synthetic pointer to register"));
+
+ gdb_assert (this->frame != NULL);
+
+ retval = value_from_register (subobj_type, gdb_regnum,
+ this->frame);
+ if (value_optimized_out (retval))
+ {
+ /* 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>. */
+ value *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 = this->fetch_address (0);
+ bool in_stack_memory = this->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 (subobj_type->code ())
+ {
+ case TYPE_CODE_FUNC:
+ case TYPE_CODE_METHOD:
+ ptr_type = builtin_type (this->gdbarch)->builtin_func_ptr;
+ break;
+ default:
+ ptr_type = builtin_type (this->gdbarch)->builtin_data_ptr;
+ break;
+ }
+ address = value_as_address (value_from_pointer (ptr_type, address));
+
+ retval = value_at_lazy (subobj_type,
+ address + subobj_offset);
+ if (in_stack_memory)
+ set_value_stack (retval, 1);
+ }
+ break;
+
+ case DWARF_VALUE_STACK:
+ {
+ value *val = this->fetch (0);
+ size_t n = TYPE_LENGTH (value_type (val));
+ size_t len = TYPE_LENGTH (subobj_type);
+ size_t max = TYPE_LENGTH (type);
+
+ if (subobj_offset + len > max)
+ invalid_synthetic_pointer ();
+
+ retval = allocate_value (subobj_type);
+
+ /* The given offset is relative to the actual object. */
+ if (gdbarch_byte_order (this->gdbarch) == BFD_ENDIAN_BIG)
+ subobj_offset += n - max;
+
+ memcpy (value_contents_raw (retval),
+ value_contents_all (val) + subobj_offset, len);
+ }
+ break;
+
+ case DWARF_VALUE_LITERAL:
+ {
+ size_t n = TYPE_LENGTH (subobj_type);
+
+ if (subobj_offset + n > this->len)
+ invalid_synthetic_pointer ();
+
+ retval = allocate_value (subobj_type);
+ bfd_byte *contents = value_contents_raw (retval);
+ memcpy (contents, this->data + subobj_offset, n);
+ }
+ break;
+
+ case DWARF_VALUE_OPTIMIZED_OUT:
+ 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, this->initialized);
+
+ return retval;
+}
+
/* Require that TYPE be an integral type; throw an exception if not. */
static void