From: Zoran Zaric via Gdb-patches <gdb-patches@sourceware.org>
To: gdb-patches@sourceware.org
Subject: [PATCH 32/43] Change DWARF stack to use new dwarf_entry classes
Date: Mon, 1 Mar 2021 14:46:09 +0000 [thread overview]
Message-ID: <20210301144620.103016-33-Zoran.Zaric@amd.com> (raw)
In-Reply-To: <20210301144620.103016-1-Zoran.Zaric@amd.com>
To replace existing DWARF stack element (dwarf_stack_value) with
dwarf_entry class based objects, a support for conversion between
struct value and the new classes is needed. The reason for this is
that dwarf_entry based classes are not designed to be visible outside
the expr.c file. This makes the DWARF expression evaluator more self
contained. This can be beneficial if there is ever a need to have a
DWARF support in gdbserver.
In the previous patch the conversion between the DWARF entry classes to
the struct value has been already added in a form of a to_gdb_value
method.
The interface that is still missing is to convert from struct value to
the DWARF entry classes. New static function gdb_value_to_dwarf_entry
has been added for this purpose.
We also need a way to perform DWARF arithmetic and logical operations
on DWARF values and for this a new set of static functions
(dwarf_value_X) has been provided.
Currently the existing struct value operations are used under the
hood of these functions to avoid the code duplication. Vector types
are planned to be promoted to base types in the future anyway which
means that the operations subset needed is just going to grow.
Now, everything is ready so that the DWARF stack element can easily be
swapped out.
gdb/ChangeLog:
* dwarf2/expr.c (gdb_value_to_dwarf_entry): New function.
(dwarf_value_cast_op): New function.
(dwarf_value_complement_op): New function.
(dwarf_value_negation_op): New function.
(dwarf_value_binary_op): New function.
(dwarf_value_less_op): New function.
(dwarf_value_equal_op): New function.
(allocate_piece_closure): Remove unused function.
(dwarf_expr_context::push): Change to use dwarf_entry based
classes.
(dwarf_expr_context::push_address): Change to use dwarf_entry
based classes.
(dwarf_expr_context::fetch): Change to use dwarf_entry based
classes.
(dwarf_expr_context::read_mem): Remove method.
(dwarf_expr_context::fetch_result): Change to use dwarf_entry
based classes.
(dwarf_expr_context::fetch_address): Change to use dwarf_entry
based classes.
(dwarf_expr_context::fetch_in_stack_memory): Remove method.
(dwarf_expr_context::add_piece): Change to use dwarf_entry based
classes.
(dwarf_expr_context::execute_stack_op): Change to use dwarf_entry
based classes.
* dwarf2/expr.h (class dwarf_entry): New declaration.
(struct dwarf_stack_value): Remove structure.
(struct dwarf_expr_context): Change to use dwarf_entry based.
---
gdb/dwarf2/expr.c | 978 ++++++++++++++++++++++------------------------
gdb/dwarf2/expr.h | 70 +---
2 files changed, 466 insertions(+), 582 deletions(-)
diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
index a2bdee95725..d51366007ab 100644
--- a/gdb/dwarf2/expr.c
+++ b/gdb/dwarf2/expr.c
@@ -1875,6 +1875,92 @@ dwarf_composite::to_gdb_value (struct frame_info *frame, struct type *type,
return retval;
}
+/* Set of functions that perform different arithmetic operations
+ on a given DWARF value arguments.
+
+ Currently the existing struct value operations are used under the
+ hood to avoid the code duplication. Vector types are planned to be
+ promoted to base types in the future anyway which means that the
+ operations subset needed is just going to grow anyway. */
+
+/* Compare two DWARF value's ARG1 and ARG2 for equality in a context
+ of a value entry comparison. */
+
+static bool
+dwarf_value_equal_op (std::shared_ptr<const dwarf_value> arg1,
+ std::shared_ptr<const dwarf_value> arg2)
+{
+ struct value *arg1_value = arg1->convert_to_gdb_value (arg1->get_type ());
+ struct value *arg2_value = arg2->convert_to_gdb_value (arg2->get_type ());
+
+ return value_equal (arg1_value, arg2_value);
+}
+
+/* Compare if DWARF value ARG1 is lesser then DWARF value ARG2 in a
+ context of a value entry comparison. */
+
+static bool
+dwarf_value_less_op (std::shared_ptr<const dwarf_value> arg1,
+ std::shared_ptr<const dwarf_value> arg2)
+{
+ struct value *arg1_value = arg1->convert_to_gdb_value (arg1->get_type ());
+ struct value *arg2_value = arg2->convert_to_gdb_value (arg2->get_type ());
+
+ return value_less (arg1_value, arg2_value);
+}
+
+/* Apply binary operation OP on given ARG1 and ARG2 arguments
+ and return a new value entry containing the result of that
+ operation. */
+
+static std::shared_ptr<dwarf_value>
+dwarf_value_binary_op (std::shared_ptr<const dwarf_value> arg1,
+ std::shared_ptr<const dwarf_value> arg2,
+ enum exp_opcode op)
+{
+ struct value *arg1_value = arg1->convert_to_gdb_value (arg1->get_type ());
+ struct value *arg2_value = arg2->convert_to_gdb_value (arg2->get_type ());
+ struct value *result = value_binop (arg1_value, arg2_value, op);
+
+ return std::make_shared<dwarf_value> (value_contents_raw (result),
+ value_type (result));
+}
+
+/* Apply a negation operation on ARG and return a new value entry
+ containing the result of that operation. */
+
+static std::shared_ptr<dwarf_value>
+dwarf_value_negation_op (std::shared_ptr<const dwarf_value> arg)
+{
+ struct value *result
+ = value_neg (arg->convert_to_gdb_value (arg->get_type ()));
+ return std::make_shared<dwarf_value> (value_contents_raw (result),
+ value_type (result));
+}
+
+/* Apply a complement operation on ARG and return a new value entry
+ containing the result of that operation. */
+
+static std::shared_ptr<dwarf_value>
+dwarf_value_complement_op (std::shared_ptr<const dwarf_value> arg)
+{
+ struct value *result
+ = value_complement (arg->convert_to_gdb_value (arg->get_type ()));
+ return std::make_shared<dwarf_value> (value_contents_raw (result),
+ value_type (result));
+}
+
+/* Apply a cast operation on ARG and return a new value entry
+ containing the result of that operation. */
+
+static std::shared_ptr<dwarf_value>
+dwarf_value_cast_op (std::shared_ptr<const dwarf_value> arg, struct type *type)
+{
+ struct value *result
+ = value_cast (type, arg->convert_to_gdb_value (arg->get_type ()));
+ return std::make_shared<dwarf_value> (value_contents_raw (result), type);
+}
+
static void *
copy_value_closure (const struct value *v)
{
@@ -2055,6 +2141,59 @@ coerce_closure_ref (const struct value *value)
}
}
+/* Convert struct value VALUE to the matching DWARF entry
+ representation. ARCH describes an architecture of the new
+ entry. */
+
+static std::shared_ptr<dwarf_entry>
+gdb_value_to_dwarf_entry (struct gdbarch *arch, struct value *value)
+{
+ struct type *type = value_type (value);
+
+ if (value_optimized_out (value))
+ return std::make_shared<dwarf_undefined> (arch);
+
+ LONGEST offset = value_offset (value);
+
+ switch (value_lval_const (value))
+ {
+ /* We can only convert struct value to a location because
+ we can't distinguish between the implicit value and
+ not_lval. */
+ case not_lval:
+ {
+ gdb_byte *contents_start = value_contents_raw (value) + offset;
+
+ return std::make_shared<dwarf_implicit> (arch, contents_start,
+ TYPE_LENGTH (type),
+ type_byte_order (type));
+ }
+ case lval_memory:
+ return std::make_shared<dwarf_memory> (arch,
+ value_address (value) + offset,
+ 0, value_stack (value));
+ case lval_register:
+ return std::make_shared<dwarf_register> (arch, VALUE_REGNUM (value),
+ false, offset);
+ case lval_computed:
+ {
+ /* Dwarf entry is enclosed by the closure anyway so we just
+ need to unwrap it here. */
+ computed_closure *closure
+ = ((computed_closure *) value_computed_closure (value));
+ auto location = closure->get_location ();
+
+ if (location == nullptr)
+ internal_error (__FILE__, __LINE__, _("invalid closure type"));
+
+ location->add_bit_offset (offset * HOST_CHAR_BIT);
+ return location;
+ }
+ default:
+ internal_error (__FILE__, __LINE__, _("invalid location type"));
+ }
+}
+
struct piece_closure
{
/* Reference count. */
@@ -2074,34 +2213,6 @@ struct piece_closure
struct frame_id frame_id;
};
-/* Allocate a closure for a value formed from separately-described
- PIECES. */
-
-static struct piece_closure *
-allocate_piece_closure (dwarf2_per_cu_data *per_cu,
- dwarf2_per_objfile *per_objfile,
- std::vector<dwarf_expr_piece> &&pieces,
- struct frame_info *frame)
-{
- struct piece_closure *c = new piece_closure;
-
- c->refc = 1;
- /* We must capture this here due to sharing of DWARF state. */
- c->per_objfile = per_objfile;
- 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;
-}
-
/* 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
@@ -2649,22 +2760,24 @@ dwarf_expr_context::dwarf_expr_context (dwarf2_per_objfile *per_objfile,
{
}
-/* Push VALUE onto the stack. */
+/* Push ENTRY onto the stack. */
void
-dwarf_expr_context::push (struct value *value, bool in_stack_memory)
+dwarf_expr_context::push (std::shared_ptr<dwarf_entry> entry)
{
- stack.emplace_back (value, in_stack_memory);
+ stack.emplace_back (entry);
}
-/* Push VALUE onto the stack. */
+/* Push ADDR onto the stack. */
void
-dwarf_expr_context::push_address (CORE_ADDR value, bool in_stack_memory)
+dwarf_expr_context::push_address (CORE_ADDR addr, bool in_stack_memory)
{
- push (value_from_ulongest (address_type (), value), in_stack_memory);
+ stack.emplace_back (std::make_shared<dwarf_memory> (this->gdbarch, addr,
+ 0, in_stack_memory));
}
+
/* Pop the top item off of the stack. */
void
@@ -2678,14 +2791,14 @@ dwarf_expr_context::pop ()
/* Retrieve the N'th item on the stack. */
-struct value *
+std::shared_ptr<dwarf_entry>
dwarf_expr_context::fetch (int n)
{
if (stack.size () <= n)
error (_("Asked for position %d of stack, "
"stack only has %zu elements on it."),
n, stack.size ());
- return stack[stack.size () - (1 + n)].value;
+ return stack[stack.size () - (1 + n)];
}
/* See expr.h. */
@@ -2762,31 +2875,6 @@ dwarf_expr_context::dwarf_call (cu_offset die_cu_off)
/* See expr.h. */
-void
-dwarf_expr_context::read_mem (gdb_byte *buf, CORE_ADDR addr,
- size_t length)
-{
- if (length == 0)
- return;
-
- /* Prefer the passed-in memory, if it exists. */
- if (addr_info != nullptr)
- {
- CORE_ADDR offset = addr - addr_info->addr;
-
- if (offset < addr_info->valaddr.size ()
- && offset + length <= addr_info->valaddr.size ())
- {
- memcpy (buf, addr_info->valaddr.data (), length);
- return;
- }
- }
-
- read_memory (addr, buf, length);
-}
-
-/* See expr.h. */
-
void
dwarf_expr_context::push_dwarf_reg_entry_value
(enum call_site_parameter_kind kind,
@@ -2844,158 +2932,20 @@ dwarf_expr_context::fetch_result (struct type *type,
LONGEST subobj_offset,
bool as_lval)
{
- struct value *retval = nullptr;
-
if (type == nullptr)
type = address_type ();
if (subobj_type == nullptr)
subobj_type = type;
- if (this->pieces.size () > 0)
- {
- struct piece_closure *c;
- 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 ();
-
- 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
- {
- /* If AS_LVAL is false, means that the implicit conversion
- from a location description to value is expected. */
- if (as_lval == false)
- this->location = DWARF_VALUE_STACK;
-
- 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))
- {
- 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 = 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:
- {
- struct value *value = this->fetch (0);
- size_t n = TYPE_LENGTH (value_type (value));
- 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 (value) + subobj_offset, len);
- }
- break;
-
- case DWARF_VALUE_LITERAL:
- {
- bfd_byte *contents;
- size_t n = TYPE_LENGTH (subobj_type);
+ auto entry = fetch (0);
- if (subobj_offset + n > this->len)
- invalid_synthetic_pointer ();
-
- retval = allocate_value (subobj_type);
- 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);
+ if (!as_lval)
+ entry = entry->to_value (address_type ());
+ else
+ entry = entry->to_location (this->gdbarch);
- return retval;
+ return entry->to_gdb_value (this->frame, type, subobj_type, subobj_offset);
}
/* See expr.h. */
@@ -3075,51 +3025,6 @@ get_signed_type (struct gdbarch *gdbarch, struct type *type)
}
}
-/* Retrieve the N'th item on the stack, converted to an address. */
-
-CORE_ADDR
-dwarf_expr_context::fetch_address (int n)
-{
- struct value *result_val = fetch (n);
- enum bfd_endian byte_order = gdbarch_byte_order (this->gdbarch);
- ULONGEST result;
-
- dwarf_require_integral (value_type (result_val));
- result = extract_unsigned_integer (value_contents (result_val),
- TYPE_LENGTH (value_type (result_val)),
- byte_order);
-
- /* For most architectures, calling extract_unsigned_integer() alone
- is sufficient for extracting an address. However, some
- architectures (e.g. MIPS) use signed addresses and using
- extract_unsigned_integer() will not produce a correct
- result. Make sure we invoke gdbarch_integer_to_address()
- for those architectures which require it. */
- if (gdbarch_integer_to_address_p (this->gdbarch))
- {
- gdb_byte *buf = (gdb_byte *) alloca (this->addr_size);
- struct type *int_type = get_unsigned_type (this->gdbarch,
- value_type (result_val));
-
- store_unsigned_integer (buf, this->addr_size, byte_order, result);
- return gdbarch_integer_to_address (this->gdbarch, int_type, buf);
- }
-
- return (CORE_ADDR) result;
-}
-
-/* Retrieve the in_stack_memory flag of the N'th item on the stack. */
-
-bool
-dwarf_expr_context::fetch_in_stack_memory (int n)
-{
- if (stack.size () <= n)
- error (_("Asked for position %d of stack, "
- "stack only has %zu elements on it."),
- n, stack.size ());
- return stack[stack.size () - (1 + n)].in_stack_memory;
-}
-
/* Return true if the expression stack is empty. */
bool
@@ -3128,49 +3033,42 @@ dwarf_expr_context::stack_empty_p () const
return stack.empty ();
}
-/* Add a new piece to the dwarf_expr_context's piece list. */
-void
-dwarf_expr_context::add_piece (ULONGEST size, ULONGEST offset)
-{
- this->pieces.emplace_back ();
- dwarf_expr_piece &p = this->pieces.back ();
+/* Add a new piece to the composite on top of the stack. */
- p.location = this->location;
- p.size = size;
- p.offset = offset;
+std::shared_ptr<dwarf_entry>
+dwarf_expr_context::add_piece (ULONGEST bit_size, ULONGEST bit_offset)
+{
+ std::shared_ptr<dwarf_location> piece;
+ std::shared_ptr<dwarf_composite> composite;
- if (p.location == DWARF_VALUE_LITERAL)
- {
- p.v.literal.data = this->data;
- p.v.literal.length = this->len;
- }
- else if (stack_empty_p ())
- {
- p.location = DWARF_VALUE_OPTIMIZED_OUT;
- /* Also reset the context's location, for our callers. This is
- a somewhat strange approach, but this lets us avoid setting
- the location to DWARF_VALUE_MEMORY in all the individual
- cases in the evaluator. */
- this->location = DWARF_VALUE_OPTIMIZED_OUT;
- }
- else if (p.location == DWARF_VALUE_MEMORY)
- {
- p.v.mem.addr = fetch_address (0);
- p.v.mem.in_stack_memory = fetch_in_stack_memory (0);
- }
- else if (p.location == DWARF_VALUE_IMPLICIT_POINTER)
+ if (!stack_empty_p ()
+ && std::dynamic_pointer_cast<dwarf_composite> (fetch (0)) == nullptr)
{
- p.v.ptr.die_sect_off = (sect_offset) this->len;
- p.v.ptr.offset = value_as_long (fetch (0));
+ piece = fetch (0)->to_location (this->gdbarch);
+ pop ();
}
- else if (p.location == DWARF_VALUE_REGISTER)
- p.v.regno = value_as_long (fetch (0));
+ else
+ piece = std::make_shared<dwarf_undefined> (this->gdbarch);
+
+ piece->add_bit_offset (bit_offset);
+
+ /* If stack is empty then it is a start of a new composite. In the
+ future this will check if the composite is finished or not. */
+ if (stack_empty_p ()
+ || std::dynamic_pointer_cast<dwarf_composite> (fetch (0)) == nullptr)
+ composite = std::make_shared<dwarf_composite> (this->gdbarch,
+ this->per_cu);
else
{
- p.v.value = fetch (0);
+ composite = std::dynamic_pointer_cast<dwarf_composite> (fetch (0));
+ pop ();
}
+
+ composite->add_piece (piece, bit_size);
+ return composite;
}
+
/* Evaluate the expression at ADDR (LEN bytes long). */
void
@@ -3217,7 +3115,6 @@ safe_skip_leb128 (const gdb_byte *buf, const gdb_byte *buf_end)
error (_("DWARF expression error: ran off end of buffer reading leb128 value"));
return buf;
}
-\f
/* Check that the current operator is either at the end of an
expression, or that it is followed by a composition operator or by
@@ -3436,9 +3333,6 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
CU. */
struct type *address_type = this->address_type ();
- this->location = DWARF_VALUE_MEMORY;
- this->initialized = 1; /* Default is initialized. */
-
if (this->recursion_depth > this->max_recursion_depth)
error (_("DWARF-2 expression error: Loop detected (%d)."),
this->recursion_depth);
@@ -3448,16 +3342,9 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
{
enum dwarf_location_atom op = (enum dwarf_location_atom) *op_ptr++;
ULONGEST result;
- /* Assume the value is not in stack memory.
- Code that knows otherwise sets this to true.
- Some arithmetic on stack addresses can probably be assumed to still
- be a stack address, but we skip this complication for now.
- This is just an optimization, so it's always ok to punt
- and leave this as false. */
- bool in_stack_memory = false;
uint64_t uoffset, reg;
int64_t offset;
- struct value *result_val = NULL;
+ std::shared_ptr<dwarf_entry> result_entry = nullptr;
/* The DWARF expression might have a bug causing an infinite
loop. In that case, quitting is the only way out. */
@@ -3498,7 +3385,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
case DW_OP_lit30:
case DW_OP_lit31:
result = op - DW_OP_lit0;
- result_val = value_from_ulongest (address_type, result);
+ result_entry = std::make_shared<dwarf_value> (result, address_type);
break;
case DW_OP_addr:
@@ -3510,8 +3397,15 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
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)
- result += this->per_objfile->objfile->text_section_offset ();
- result_val = value_from_ulongest (address_type, result);
+ {
+ result += this->per_objfile->objfile->text_section_offset ();
+ result_entry
+ = std::make_shared<dwarf_memory> (this->gdbarch, result);
+ }
+ else
+ /* This is a special case where the value is expected to be
+ created instead of memory location. */
+ result_entry = std::make_shared<dwarf_value> (result, address_type);
break;
case DW_OP_addrx:
@@ -3522,7 +3416,8 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
result = dwarf2_read_addr_index (this->per_cu, this->per_objfile,
uoffset);
result += this->per_objfile->objfile->text_section_offset ();
- result_val = value_from_ulongest (address_type, result);
+ result_entry
+ = std::make_shared<dwarf_memory> (this->gdbarch, result);
break;
case DW_OP_GNU_const_index:
ensure_have_per_cu (per_cu, "DW_OP_GNU_const_index");
@@ -3530,58 +3425,58 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
result = dwarf2_read_addr_index (this->per_cu, this->per_objfile,
uoffset);
- result_val = value_from_ulongest (address_type, result);
+ result_entry = std::make_shared<dwarf_value> (result, address_type);
break;
case DW_OP_const1u:
result = extract_unsigned_integer (op_ptr, 1, byte_order);
- result_val = value_from_ulongest (address_type, result);
+ result_entry = std::make_shared<dwarf_value> (result, address_type);
op_ptr += 1;
break;
case DW_OP_const1s:
result = extract_signed_integer (op_ptr, 1, byte_order);
- result_val = value_from_ulongest (address_type, result);
+ result_entry = std::make_shared<dwarf_value> (result, address_type);
op_ptr += 1;
break;
case DW_OP_const2u:
result = extract_unsigned_integer (op_ptr, 2, byte_order);
- result_val = value_from_ulongest (address_type, result);
+ result_entry = std::make_shared<dwarf_value> (result, address_type);
op_ptr += 2;
break;
case DW_OP_const2s:
result = extract_signed_integer (op_ptr, 2, byte_order);
- result_val = value_from_ulongest (address_type, result);
+ result_entry = std::make_shared<dwarf_value> (result, address_type);
op_ptr += 2;
break;
case DW_OP_const4u:
result = extract_unsigned_integer (op_ptr, 4, byte_order);
- result_val = value_from_ulongest (address_type, result);
+ result_entry = std::make_shared<dwarf_value> (result, address_type);
op_ptr += 4;
break;
case DW_OP_const4s:
result = extract_signed_integer (op_ptr, 4, byte_order);
- result_val = value_from_ulongest (address_type, result);
+ result_entry = std::make_shared<dwarf_value> (result, address_type);
op_ptr += 4;
break;
case DW_OP_const8u:
result = extract_unsigned_integer (op_ptr, 8, byte_order);
- result_val = value_from_ulongest (address_type, result);
+ result_entry = std::make_shared<dwarf_value> (result, address_type);
op_ptr += 8;
break;
case DW_OP_const8s:
result = extract_signed_integer (op_ptr, 8, byte_order);
- result_val = value_from_ulongest (address_type, result);
+ result_entry = std::make_shared<dwarf_value> (result, address_type);
op_ptr += 8;
break;
case DW_OP_constu:
op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
result = uoffset;
- result_val = value_from_ulongest (address_type, result);
+ result_entry = std::make_shared<dwarf_value> (result, address_type);
break;
case DW_OP_consts:
op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
result = offset;
- result_val = value_from_ulongest (address_type, result);
+ result_entry = std::make_shared<dwarf_value> (result, address_type);
break;
/* The DW_OP_reg operations are required to occur alone in
@@ -3621,8 +3516,8 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
dwarf_expr_require_composition (op_ptr, op_end, "DW_OP_reg");
result = op - DW_OP_reg0;
- result_val = value_from_ulongest (address_type, result);
- this->location = DWARF_VALUE_REGISTER;
+ result_entry
+ = std::make_shared<dwarf_register> (this->gdbarch, result);
break;
case DW_OP_regx:
@@ -3630,8 +3525,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
dwarf_expr_require_composition (op_ptr, op_end, "DW_OP_regx");
result = reg;
- result_val = value_from_ulongest (address_type, result);
- this->location = DWARF_VALUE_REGISTER;
+ result_entry = std::make_shared<dwarf_register> (this->gdbarch, reg);
break;
case DW_OP_implicit_value:
@@ -3641,19 +3535,32 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
op_ptr = safe_read_uleb128 (op_ptr, op_end, &len);
if (op_ptr + len > op_end)
error (_("DW_OP_implicit_value: too few bytes available."));
- this->len = len;
- this->data = op_ptr;
- this->location = DWARF_VALUE_LITERAL;
+ result_entry
+ = std::make_shared<dwarf_implicit> (this->gdbarch, op_ptr, len,
+ BFD_ENDIAN_UNKNOWN);
op_ptr += len;
dwarf_expr_require_composition (op_ptr, op_end,
"DW_OP_implicit_value");
}
- goto no_push;
+ break;
case DW_OP_stack_value:
- this->location = DWARF_VALUE_STACK;
- dwarf_expr_require_composition (op_ptr, op_end, "DW_OP_stack_value");
- goto no_push;
+ {
+ auto value = fetch (0)->to_value (address_type);
+ pop ();
+
+ struct type* type = value->get_type ();
+
+ result_entry
+ = std::make_shared<dwarf_implicit> (this->gdbarch,
+ value->get_contents (),
+ TYPE_LENGTH (type),
+ type_byte_order (type));
+
+ dwarf_expr_require_composition (op_ptr, op_end,
+ "DW_OP_stack_value");
+ }
+ break;
case DW_OP_implicit_pointer:
case DW_OP_GNU_implicit_pointer:
@@ -3662,16 +3569,20 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
ensure_have_per_cu (per_cu, "DW_OP_implicit_pointer");
/* The referred-to DIE of sect_offset kind. */
- this->len = extract_unsigned_integer (op_ptr, this->ref_addr_size,
- byte_order);
+ sect_offset die_offset
+ = (sect_offset) extract_unsigned_integer (op_ptr,
+ this->ref_addr_size,
+ byte_order);
op_ptr += this->ref_addr_size;
/* The byte offset into the data. */
op_ptr = safe_read_sleb128 (op_ptr, op_end, &len);
- result = (ULONGEST) len;
- result_val = value_from_ulongest (address_type, result);
-
- this->location = DWARF_VALUE_IMPLICIT_POINTER;
+ result_entry
+ = std::make_shared<dwarf_implicit_pointer> (this->gdbarch,
+ this->per_objfile,
+ this->per_cu,
+ this->addr_size,
+ die_offset, len);
dwarf_expr_require_composition (op_ptr, op_end,
"DW_OP_implicit_pointer");
}
@@ -3713,9 +3624,18 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
ensure_have_frame (this->frame, "DW_OP_breg");
- result = read_addr_from_reg (this->frame, op - DW_OP_breg0);
- result += offset;
- result_val = value_from_ulongest (address_type, result);
+ reg = op - DW_OP_breg0;
+
+ int regnum = dwarf_reg_to_regnum_or_error (this->gdbarch, reg);
+ ULONGEST reg_size = register_size (this->gdbarch, regnum);
+ std::shared_ptr<dwarf_location> location
+ = std::make_shared<dwarf_register> (this->gdbarch, reg);
+ result_entry = location->deref (frame, this->addr_info,
+ address_type, reg_size);
+
+ location = result_entry->to_location (this->gdbarch);
+ location->add_bit_offset (offset * HOST_CHAR_BIT);
+ result_entry = location;
}
break;
case DW_OP_bregx:
@@ -3724,51 +3644,64 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
ensure_have_frame (this->frame, "DW_OP_bregx");
- result = read_addr_from_reg (this->frame, reg);
- result += offset;
- result_val = value_from_ulongest (address_type, result);
+ int regnum = dwarf_reg_to_regnum_or_error (this->gdbarch, reg);
+ ULONGEST reg_size = register_size (this->gdbarch, regnum);
+ std::shared_ptr<dwarf_location> location
+ = std::make_shared<dwarf_register> (this->gdbarch, reg);
+ result_entry = location->deref (frame, this->addr_info,
+ address_type, reg_size);
+
+ location = result_entry->to_location (this->gdbarch);
+ location->add_bit_offset (offset * HOST_CHAR_BIT);
+ result_entry = location;
}
break;
case DW_OP_fbreg:
{
- const gdb_byte *datastart;
- size_t datalen;
-
op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
/* Rather than create a whole new context, we simply
backup the current stack locally and install a new empty stack,
then reset it afterwards, effectively erasing whatever the
recursive call put there. */
- std::vector<dwarf_stack_value> saved_stack = std::move (stack);
+ std::vector<std::shared_ptr<dwarf_entry>> saved_stack
+ = std::move (stack);
stack.clear ();
- /* FIXME: cagney/2003-03-26: This code should be using
- get_frame_base_address(), and then implement a dwarf2
- specific this_base method. */
+ const gdb_byte *datastart;
+ size_t 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 = read_addr_from_reg (this->frame, value_as_long (fetch (0)));
- else
- error (_("Not implemented: computing frame "
- "base using explicit value operator"));
- result = result + offset;
- result_val = value_from_ulongest (address_type, result);
- in_stack_memory = true;
+ result_entry = fetch (0);
+
+ auto registr
+ = std::dynamic_pointer_cast<dwarf_register> (result_entry);
+
+ if (registr != nullptr)
+ result_entry
+ = registr->deref (frame, this->addr_info, address_type);
+
+ result_entry = result_entry->to_location (this->gdbarch);
+ auto memory
+ = std::dynamic_pointer_cast<dwarf_memory> (result_entry);
+
+ /* If we get anything else then memory location here,
+ the DWARF standard defines the expression as ill formed. */
+ if (memory == nullptr)
+ ill_formed_expression ();
+
+ memory->add_bit_offset (offset * HOST_CHAR_BIT);
+ memory->set_stack (true);
+ result_entry = memory;
/* Restore the content of the original stack. */
stack = std::move (saved_stack);
-
- this->location = DWARF_VALUE_MEMORY;
}
break;
case DW_OP_dup:
- result_val = fetch (0);
- in_stack_memory = fetch_in_stack_memory (0);
+ result_entry = fetch (0);
break;
case DW_OP_drop:
@@ -3777,8 +3710,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
case DW_OP_pick:
offset = *op_ptr++;
- result_val = fetch (offset);
- in_stack_memory = fetch_in_stack_memory (offset);
+ result_entry = fetch (offset);
break;
case DW_OP_swap:
@@ -3788,15 +3720,14 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
"DW_OP_swap. Need 2, have %zu."),
stack.size ());
- dwarf_stack_value &t1 = stack[stack.size () - 1];
- dwarf_stack_value &t2 = stack[stack.size () - 2];
- std::swap (t1, t2);
+ auto temp = stack[stack.size () - 1];
+ stack[stack.size () - 1] = stack[stack.size () - 2];
+ stack[stack.size () - 2] = temp;
goto no_push;
}
case DW_OP_over:
- result_val = fetch (1);
- in_stack_memory = fetch_in_stack_memory (1);
+ result_entry = fetch (1);
break;
case DW_OP_rot:
@@ -3806,7 +3737,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
"DW_OP_rot. Need 3, have %zu."),
stack.size ());
- dwarf_stack_value temp = stack[stack.size () - 1];
+ auto temp = stack[stack.size () - 1];
stack[stack.size () - 1] = stack[stack.size () - 2];
stack[stack.size () - 2] = stack[stack.size () - 3];
stack[stack.size () - 3] = temp;
@@ -3819,38 +3750,22 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
case DW_OP_GNU_deref_type:
{
int addr_size = (op == DW_OP_deref ? this->addr_size : *op_ptr++);
- gdb_byte *buf = (gdb_byte *) alloca (addr_size);
- CORE_ADDR addr = fetch_address (0);
- struct type *type;
-
- pop ();
+ struct type *type = address_type;
if (op == DW_OP_deref_type || op == DW_OP_GNU_deref_type)
{
op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
cu_offset type_die_cu_off = (cu_offset) uoffset;
type = get_base_type (type_die_cu_off, 0);
- }
- else
- type = address_type;
-
- 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. */
- if (TYPE_LENGTH (type) != addr_size)
- {
- ULONGEST datum =
- extract_unsigned_integer (buf, addr_size, byte_order);
-
- buf = (gdb_byte *) alloca (TYPE_LENGTH (type));
- store_unsigned_integer (buf, TYPE_LENGTH (type),
- byte_order, datum);
+ addr_size = TYPE_LENGTH (type);
}
- result_val = value_from_contents_and_address (type, buf, addr);
- break;
+ auto location = fetch (0)->to_location (this->gdbarch);
+ result_entry = location->deref (frame, this->addr_info,
+ type, addr_size);
+ pop ();
}
+ break;
case DW_OP_abs:
case DW_OP_neg:
@@ -3858,31 +3773,37 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
case DW_OP_plus_uconst:
{
/* Unary operations. */
- result_val = fetch (0);
+ auto arg
+ = fetch (0)->to_value (address_type);
pop ();
switch (op)
{
case DW_OP_abs:
- if (value_less (result_val,
- value_zero (value_type (result_val), not_lval)))
- result_val = value_neg (result_val);
+ {
+ struct value *arg_value
+ = arg->convert_to_gdb_value (arg->get_type ());
+
+ if (value_less (arg_value,
+ value_zero (arg->get_type (), not_lval)))
+ arg = dwarf_value_negation_op (arg);
+ }
break;
case DW_OP_neg:
- result_val = value_neg (result_val);
+ arg = dwarf_value_negation_op (arg);
break;
case DW_OP_not:
- dwarf_require_integral (value_type (result_val));
- result_val = value_complement (result_val);
+ dwarf_require_integral (arg->get_type ());
+ arg = dwarf_value_complement_op (arg);
break;
case DW_OP_plus_uconst:
- dwarf_require_integral (value_type (result_val));
- result = value_as_long (result_val);
+ dwarf_require_integral (arg->get_type ());
op_ptr = safe_read_uleb128 (op_ptr, op_end, ®);
- result += reg;
- result_val = value_from_ulongest (address_type, result);
+ result = arg->to_long () + reg;
+ arg = std::make_shared<dwarf_value> (result, address_type);
break;
}
+ result_entry = arg;
}
break;
@@ -3905,34 +3826,37 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
case DW_OP_ne:
{
/* Binary operations. */
- struct value *first, *second;
-
- second = fetch (0);
+ auto arg2 = fetch (0)->to_value (address_type);
pop ();
- first = fetch (0);
+ auto arg1 = fetch (0)->to_value (address_type);
pop ();
- if (! base_types_equal_p (value_type (first), value_type (second)))
+ if (! base_types_equal_p (arg1->get_type (), arg2->get_type ()))
error (_("Incompatible types on DWARF stack"));
+ std::shared_ptr<dwarf_value> op_result;
+
switch (op)
{
case DW_OP_and:
- dwarf_require_integral (value_type (first));
- dwarf_require_integral (value_type (second));
- result_val = value_binop (first, second, BINOP_BITWISE_AND);
+ dwarf_require_integral (arg1->get_type ());
+ dwarf_require_integral (arg2->get_type ());
+ op_result = dwarf_value_binary_op (arg1, arg2,
+ BINOP_BITWISE_AND);
break;
case DW_OP_div:
- result_val = value_binop (first, second, BINOP_DIV);
+ op_result
+ = dwarf_value_binary_op (arg1, arg2, BINOP_DIV);
break;
case DW_OP_minus:
- result_val = value_binop (first, second, BINOP_SUB);
+ op_result
+ = dwarf_value_binary_op (arg1, arg2, BINOP_SUB);
break;
case DW_OP_mod:
{
int cast_back = 0;
- struct type *orig_type = value_type (first);
+ struct type *orig_type = arg1->get_type ();
/* We have to special-case "old-style" untyped values
-- these must have mod computed using unsigned
@@ -3943,102 +3867,117 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
= get_unsigned_type (this->gdbarch, orig_type);
cast_back = 1;
- first = value_cast (utype, first);
- second = value_cast (utype, second);
+ arg1 = dwarf_value_cast_op (arg1, utype);
+ arg2 = dwarf_value_cast_op (arg2, utype);
}
/* Note that value_binop doesn't handle float or
decimal float here. This seems unimportant. */
- result_val = value_binop (first, second, BINOP_MOD);
+ op_result = dwarf_value_binary_op (arg1, arg2, BINOP_MOD);
if (cast_back)
- result_val = value_cast (orig_type, result_val);
+ op_result = dwarf_value_cast_op (op_result, orig_type);
}
break;
case DW_OP_mul:
- result_val = value_binop (first, second, BINOP_MUL);
+ op_result
+ = dwarf_value_binary_op (arg1, arg2, BINOP_MUL);
break;
case DW_OP_or:
- dwarf_require_integral (value_type (first));
- dwarf_require_integral (value_type (second));
- result_val = value_binop (first, second, BINOP_BITWISE_IOR);
+ dwarf_require_integral (arg1->get_type ());
+ dwarf_require_integral (arg2->get_type ());
+ op_result
+ = dwarf_value_binary_op (arg1, arg2, BINOP_BITWISE_IOR);
break;
case DW_OP_plus:
- result_val = value_binop (first, second, BINOP_ADD);
+ op_result
+ = dwarf_value_binary_op (arg1, arg2, BINOP_ADD);
break;
case DW_OP_shl:
- dwarf_require_integral (value_type (first));
- dwarf_require_integral (value_type (second));
- result_val = value_binop (first, second, BINOP_LSH);
+ dwarf_require_integral (arg1->get_type ());
+ dwarf_require_integral (arg2->get_type ());
+ op_result
+ = dwarf_value_binary_op (arg1, arg2, BINOP_LSH);
break;
case DW_OP_shr:
- dwarf_require_integral (value_type (first));
- dwarf_require_integral (value_type (second));
- if (!value_type (first)->is_unsigned ())
+ dwarf_require_integral (arg1->get_type ());
+ dwarf_require_integral (arg2->get_type ());
+ if (!arg1->get_type ()->is_unsigned ())
{
struct type *utype
- = get_unsigned_type (this->gdbarch, value_type (first));
+ = get_unsigned_type (this->gdbarch, arg1->get_type ());
- first = value_cast (utype, first);
+ arg1 = dwarf_value_cast_op (arg1, utype);
}
- result_val = value_binop (first, second, BINOP_RSH);
+ op_result
+ = dwarf_value_binary_op (arg1, arg2, BINOP_RSH);
/* Make sure we wind up with the same type we started
with. */
- if (value_type (result_val) != value_type (second))
- result_val = value_cast (value_type (second), result_val);
+ if (op_result->get_type () != arg2->get_type ())
+ op_result
+ = dwarf_value_cast_op (op_result, arg2->get_type ());
break;
case DW_OP_shra:
- dwarf_require_integral (value_type (first));
- dwarf_require_integral (value_type (second));
- if (value_type (first)->is_unsigned ())
+ dwarf_require_integral (arg1->get_type ());
+ dwarf_require_integral (arg2->get_type ());
+ if (arg1->get_type ()->is_unsigned ())
{
struct type *stype
- = get_signed_type (this->gdbarch, value_type (first));
+ = get_signed_type (this->gdbarch, arg1->get_type ());
- first = value_cast (stype, first);
+ arg1 = dwarf_value_cast_op (arg1, stype);
}
- result_val = value_binop (first, second, BINOP_RSH);
- /* Make sure we wind up with the same type we started
- with. */
- if (value_type (result_val) != value_type (second))
- result_val = value_cast (value_type (second), result_val);
+ op_result
+ = dwarf_value_binary_op (arg1, arg2, BINOP_RSH);
+ /* Make sure we wind up with the same type we started with. */
+ if (op_result->get_type () != arg2->get_type ())
+ op_result
+ = dwarf_value_cast_op (op_result, arg2->get_type ());
break;
case DW_OP_xor:
- dwarf_require_integral (value_type (first));
- dwarf_require_integral (value_type (second));
- result_val = value_binop (first, second, BINOP_BITWISE_XOR);
+ dwarf_require_integral (arg1->get_type ());
+ dwarf_require_integral (arg2->get_type ());
+ op_result
+ = dwarf_value_binary_op (arg1, arg2, BINOP_BITWISE_XOR);
break;
case DW_OP_le:
/* A <= B is !(B < A). */
- result = ! value_less (second, first);
- result_val = value_from_ulongest (address_type, result);
+ result = ! dwarf_value_less_op (arg2, arg1);
+ op_result
+ = std::make_shared<dwarf_value> (result, address_type);
break;
case DW_OP_ge:
/* A >= B is !(A < B). */
- result = ! value_less (first, second);
- result_val = value_from_ulongest (address_type, result);
+ result = ! dwarf_value_less_op (arg1, arg2);
+ op_result
+ = std::make_shared<dwarf_value> (result, address_type);
break;
case DW_OP_eq:
- result = value_equal (first, second);
- result_val = value_from_ulongest (address_type, result);
+ result = dwarf_value_equal_op (arg1, arg2);
+ op_result
+ = std::make_shared<dwarf_value> (result, address_type);
break;
case DW_OP_lt:
- result = value_less (first, second);
- result_val = value_from_ulongest (address_type, result);
+ result = dwarf_value_less_op (arg1, arg2);
+ op_result
+ = std::make_shared<dwarf_value> (result, address_type);
break;
case DW_OP_gt:
/* A > B is B < A. */
- result = value_less (second, first);
- result_val = value_from_ulongest (address_type, result);
+ result = dwarf_value_less_op (arg2, arg1);
+ op_result
+ = std::make_shared<dwarf_value> (result, address_type);
break;
case DW_OP_ne:
- result = ! value_equal (first, second);
- result_val = value_from_ulongest (address_type, result);
+ result = ! dwarf_value_equal_op (arg1, arg2);
+ op_result
+ = std::make_shared<dwarf_value> (result, address_type);
break;
default:
internal_error (__FILE__, __LINE__,
_("Can't be reached."));
}
+ result_entry = op_result;
}
break;
@@ -4046,8 +3985,8 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
ensure_have_frame (this->frame, "DW_OP_call_frame_cfa");
result = dwarf2_frame_cfa (this->frame);
- result_val = value_from_ulongest (address_type, result);
- in_stack_memory = true;
+ result_entry
+ = std::make_shared<dwarf_memory> (this->gdbarch, result, 0, true);
break;
case DW_OP_GNU_push_tls_address:
@@ -4060,11 +3999,12 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
control block at which the variable is located. Nothing
should follow this operator, so the top of stack would be
returned. */
- result = value_as_long (fetch (0));
+ result = fetch (0)->to_value (address_type)->to_long ();
pop ();
result = target_translate_tls_address (this->per_objfile->objfile,
result);
- result_val = value_from_ulongest (address_type, result);
+ result_entry
+ = std::make_shared<dwarf_memory> (this->gdbarch, result);
break;
case DW_OP_skip:
@@ -4075,13 +4015,12 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
case DW_OP_bra:
{
- struct value *val;
+ auto dwarf_value = fetch (0)->to_value (address_type);
offset = extract_signed_integer (op_ptr, 2, byte_order);
op_ptr += 2;
- val = fetch (0);
- dwarf_require_integral (value_type (val));
- if (value_as_long (val) != 0)
+ dwarf_require_integral (dwarf_value->get_type ());
+ if (dwarf_value->to_long () != 0)
op_ptr += offset;
pop ();
}
@@ -4096,16 +4035,9 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
/* Record the piece. */
op_ptr = safe_read_uleb128 (op_ptr, op_end, &size);
- add_piece (8 * size, 0);
-
- /* Pop off the address/regnum, and reset the location
- type. */
- if (this->location != DWARF_VALUE_LITERAL
- && this->location != DWARF_VALUE_OPTIMIZED_OUT)
- pop ();
- this->location = DWARF_VALUE_MEMORY;
+ result_entry = add_piece (HOST_CHAR_BIT * size, 0);
}
- goto no_push;
+ break;
case DW_OP_bit_piece:
{
@@ -4114,23 +4046,24 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
/* Record the piece. */
op_ptr = safe_read_uleb128 (op_ptr, op_end, &size);
op_ptr = safe_read_uleb128 (op_ptr, op_end, &uleb_offset);
- add_piece (size, uleb_offset);
-
- /* Pop off the address/regnum, and reset the location
- type. */
- if (this->location != DWARF_VALUE_LITERAL
- && this->location != DWARF_VALUE_OPTIMIZED_OUT)
- pop ();
- this->location = DWARF_VALUE_MEMORY;
+ result_entry = add_piece (size, uleb_offset);
}
- goto no_push;
+ break;
case DW_OP_GNU_uninit:
- if (op_ptr != op_end)
- error (_("DWARF-2 expression error: DW_OP_GNU_uninit must always "
- "be the very last op."));
+ {
+ if (op_ptr != op_end)
+ error (_("DWARF-2 expression error: DW_OP_GNU_uninit must always "
+ "be the very last op."));
- this->initialized = 0;
+ auto location = std::dynamic_pointer_cast<dwarf_location> (fetch (0));
+
+ if (location == nullptr)
+ ill_formed_expression ();
+
+ location->set_initialised (false);
+ result_entry = location;
+ }
goto no_push;
case DW_OP_call2:
@@ -4160,9 +4093,22 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
this->ref_addr_size,
byte_order);
op_ptr += this->ref_addr_size;
- result_val = sect_variable_value (sect_off, this->per_cu,
- this->per_objfile);
- result_val = value_cast (address_type, result_val);
+ struct value *value
+ = sect_variable_value (sect_off, per_cu, per_objfile);
+ value = value_cast (address_type, value);
+
+ result_entry
+ = gdb_value_to_dwarf_entry (this->gdbarch, value);
+
+ auto undefined
+ = std::dynamic_pointer_cast<dwarf_undefined> (result_entry);
+
+ if (undefined != nullptr)
+ error_value_optimized_out ();
+
+ auto location = result_entry->to_location (this->gdbarch);
+ result_entry = location->deref (frame, this->addr_info,
+ address_type);
}
break;
@@ -4221,19 +4167,15 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
case DW_OP_const_type:
case DW_OP_GNU_const_type:
{
- int n;
- const gdb_byte *data;
- struct type *type;
-
op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
cu_offset type_die_cu_off = (cu_offset) uoffset;
- n = *op_ptr++;
- data = op_ptr;
+ int n = *op_ptr++;
+ const gdb_byte *data = op_ptr;
op_ptr += n;
- type = get_base_type (type_die_cu_off, n);
- result_val = value_from_contents (type, data);
+ struct type *type = get_base_type (type_die_cu_off, n);
+ result_entry = std::make_shared<dwarf_value> (data, type);
}
break;
@@ -4245,12 +4187,11 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
cu_offset type_die_cu_off = (cu_offset) uoffset;
ensure_have_frame (this->frame, "DW_OP_regval_type");
-
struct type *type = get_base_type (type_die_cu_off, 0);
- int regnum
- = dwarf_reg_to_regnum_or_error (get_frame_arch (this->frame),
- reg);
- result_val = value_from_register (type, regnum, this->frame);
+
+ auto registr
+ = std::make_shared<dwarf_register> (this->gdbarch, reg);
+ result_entry = registr->deref (frame, this->addr_info, type);
}
break;
@@ -4259,42 +4200,45 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
case DW_OP_reinterpret:
case DW_OP_GNU_reinterpret:
{
- struct type *type;
+ std::shared_ptr<dwarf_value> value
+ = fetch (0)->to_value (address_type);
+
+ pop ();
op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
cu_offset type_die_cu_off = (cu_offset) uoffset;
+ struct type *type;
+
if (to_underlying (type_die_cu_off) == 0)
type = address_type;
else
type = get_base_type (type_die_cu_off, 0);
- result_val = fetch (0);
- pop ();
-
if (op == DW_OP_convert || op == DW_OP_GNU_convert)
- result_val = value_cast (type, result_val);
- else if (type == value_type (result_val))
+ value = dwarf_value_cast_op (value, type);
+ else if (type == value->get_type ())
{
/* Nothing. */
}
else if (TYPE_LENGTH (type)
- != TYPE_LENGTH (value_type (result_val)))
+ != TYPE_LENGTH (value->get_type ()))
error (_("DW_OP_reinterpret has wrong size"));
else
- result_val
- = value_from_contents (type,
- value_contents_all (result_val));
+ value
+ = std::make_shared<dwarf_value> (value->get_contents (), type);
+ result_entry = value;
}
break;
case DW_OP_push_object_address:
- /* Return the address of the object we are currently observing. */
if (addr_info == nullptr)
error (_("Location address is not set."));
- result_val
- = value_from_ulongest (address_type, this->addr_info->addr);
+ /* Return the address of the object we are currently observing. */
+ result_entry
+ = std::make_shared<dwarf_memory> (this->gdbarch,
+ this->addr_info->addr);
break;
default:
@@ -4302,18 +4246,12 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
}
/* Most things push a result value. */
- gdb_assert (result_val != NULL);
- push (result_val, in_stack_memory);
+ gdb_assert (result_entry != NULL);
+ push (result_entry);
no_push:
;
}
- /* To simplify our main caller, if the result is an implicit
- pointer, then make a pieced value. This is ok because we can't
- have implicit pointers in contexts where pieces are invalid. */
- if (this->location == DWARF_VALUE_IMPLICIT_POINTER)
- add_piece (8 * this->addr_size, 0);
-
this->recursion_depth--;
gdb_assert (this->recursion_depth >= 0);
}
diff --git a/gdb/dwarf2/expr.h b/gdb/dwarf2/expr.h
index 3f519e81849..2d24f4402db 100644
--- a/gdb/dwarf2/expr.h
+++ b/gdb/dwarf2/expr.h
@@ -25,6 +25,7 @@
#include "leb128.h"
#include "gdbtypes.h"
+class dwarf_entry;
struct dwarf2_per_objfile;
/* The location of a value. */
@@ -98,22 +99,6 @@ struct dwarf_expr_piece
ULONGEST offset;
};
-/* The dwarf expression stack. */
-
-struct dwarf_stack_value
-{
- dwarf_stack_value (struct value *value_, int in_stack_memory_)
- : value (value_), in_stack_memory (in_stack_memory_)
- {}
-
- struct value *value;
-
- /* True if the piece is in memory and is known to be on the program's stack.
- It is always ok to set this to zero. This is used, for example, to
- optimize memory access from the target. It can vastly speed up backtraces
- on long latency connections when "set stack-cache on". */
- bool in_stack_memory;
-};
/* The expression evaluator works with a dwarf_expr_context, describing
its current state and its callbacks. */
@@ -127,7 +112,7 @@ struct dwarf_expr_context
int addr_size);
virtual ~dwarf_expr_context () = default;
- void push_address (CORE_ADDR value, bool in_stack_memory);
+ void push_address (CORE_ADDR addr, bool in_stack_memory);
/* Evaluate the expression at ADDR (LEN bytes long) in a given PER_CU
FRAME context. AS_LVAL defines if the returned struct value is
@@ -145,8 +130,8 @@ struct dwarf_expr_context
LONGEST subobj_offset = 0);
private:
- /* The stack of values. */
- std::vector<dwarf_stack_value> stack;
+ /* The stack of DWARF entries. */
+ std::vector<std::shared_ptr<dwarf_entry>> stack;
/* Target architecture to use for address operations. */
struct gdbarch *gdbarch = nullptr;
@@ -163,43 +148,6 @@ struct dwarf_expr_context
depth we'll tolerate before raising an error. */
int recursion_depth = 0, max_recursion_depth = 0x100;
- /* Location of the value. */
- enum dwarf_value_location location = DWARF_VALUE_MEMORY;
-
- /* For DWARF_VALUE_LITERAL, the current literal value's length and
- data. For DWARF_VALUE_IMPLICIT_POINTER, LEN is the offset of the
- target DIE of sect_offset kind. */
- ULONGEST len = 0;
- const gdb_byte *data = nullptr;
-
- /* Initialization status of variable: Non-zero if variable has been
- initialized; zero otherwise. */
- int initialized = 0;
-
- /* A vector of pieces.
-
- Each time DW_OP_piece is executed, we add a new element to the
- end of this array, recording the current top of the stack, the
- current location, and the size given as the operand to
- DW_OP_piece. We then pop the top value from the stack, reset the
- location, and resume evaluation.
-
- The Dwarf spec doesn't say whether DW_OP_piece pops the top value
- from the stack. We do, ensuring that clients of this interface
- expecting to see a value left on the top of the stack (say, code
- evaluating frame base expressions or CFA's specified with
- DW_CFA_def_cfa_expression) will get an error if the expression
- actually marks all the values it computes as pieces.
-
- If an expression never uses DW_OP_piece, num_pieces will be zero.
- (It would be nice to present these cases as expressions yielding
- a single piece, so that callers need not distinguish between the
- no-DW_OP_piece and one-DW_OP_piece cases. But expressions with
- no DW_OP_piece operations have no value to place in a piece's
- 'size' field; the size comes from the surrounding data. So the
- two cases need to be handled separately.) */
- std::vector<dwarf_expr_piece> pieces;
-
/* We evaluate the expression in the context of this objfile. */
dwarf2_per_objfile *per_objfile;
@@ -214,14 +162,13 @@ struct dwarf_expr_context
void eval (const gdb_byte *addr, size_t len);
struct type *address_type () const;
- void push (struct value *value, bool in_stack_memory);
+ void push (std::shared_ptr<dwarf_entry> value);
bool stack_empty_p () const;
- void add_piece (ULONGEST size, ULONGEST offset);
+ std::shared_ptr<dwarf_entry> add_piece (ULONGEST bit_size,
+ ULONGEST bit_offset);
void execute_stack_op (const gdb_byte *op_ptr, const gdb_byte *op_end);
void pop ();
- struct value *fetch (int n);
- CORE_ADDR fetch_address (int n);
- bool fetch_in_stack_memory (int n);
+ std::shared_ptr<dwarf_entry> fetch (int n);
/* Fetch the result of the expression evaluation in a form of
a struct value, where TYPE, SUBOBJ_TYPE and SUBOBJ_OFFSET
@@ -257,7 +204,6 @@ struct dwarf_expr_context
void push_dwarf_reg_entry_value (enum call_site_parameter_kind kind,
union call_site_parameter_u kind_u,
int deref_size);
- void read_mem (gdb_byte *buf, CORE_ADDR addr, size_t length);
};
/* Return the value of register number REG (a DWARF register number),
--
2.17.1
next prev parent reply other threads:[~2021-03-01 14:48 UTC|newest]
Thread overview: 86+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-01 14:45 [PATCH 00/43 V2] Allow location description on the DWARF stack Zoran Zaric via Gdb-patches
2021-03-01 14:45 ` [PATCH 01/43] Replace the symbol needs evaluator with a parser Zoran Zaric via Gdb-patches
2021-04-27 1:20 ` Simon Marchi via Gdb-patches
2021-04-28 10:17 ` Zoran Zaric via Gdb-patches
2021-04-28 14:08 ` Simon Marchi via Gdb-patches
2021-04-28 15:02 ` Zoran Zaric via Gdb-patches
2021-04-28 15:31 ` Zoran Zaric via Gdb-patches
2021-03-01 14:45 ` [PATCH 02/43] Cleanup of the dwarf_expr_context constructor Zoran Zaric via Gdb-patches
2021-04-27 1:23 ` Simon Marchi via Gdb-patches
2021-04-28 10:19 ` Zoran Zaric via Gdb-patches
2021-03-01 14:45 ` [PATCH 03/43] Move frame context info to dwarf_expr_context Zoran Zaric via Gdb-patches
2021-04-27 2:19 ` Simon Marchi via Gdb-patches
2021-04-28 10:51 ` Zoran Zaric via Gdb-patches
2021-04-28 14:14 ` Simon Marchi via Gdb-patches
2021-04-28 15:55 ` Zoran Zaric via Gdb-patches
2021-03-01 14:45 ` [PATCH 04/43] Remove get_frame_cfa from dwarf_expr_context Zoran Zaric via Gdb-patches
2021-03-01 14:45 ` [PATCH 05/43] Move compilation unit info to dwarf_expr_context Zoran Zaric via Gdb-patches
2021-04-27 2:58 ` Simon Marchi via Gdb-patches
2021-04-28 11:28 ` Zoran Zaric via Gdb-patches
2021-03-01 14:45 ` [PATCH 06/43] Move dwarf_call " Zoran Zaric via Gdb-patches
2021-03-01 14:45 ` [PATCH 07/43] Move get_object_address " Zoran Zaric via Gdb-patches
2021-04-27 3:12 ` Simon Marchi via Gdb-patches
2021-04-28 11:34 ` Zoran Zaric via Gdb-patches
2021-03-01 14:45 ` [PATCH 08/43] Move read_mem " Zoran Zaric via Gdb-patches
2021-03-01 14:45 ` [PATCH 09/43] Move push_dwarf_reg_entry_value to expr.c Zoran Zaric via Gdb-patches
2021-04-27 3:56 ` Simon Marchi via Gdb-patches
2021-04-28 11:36 ` Zoran Zaric via Gdb-patches
2021-03-01 14:45 ` [PATCH 10/43] Inline get_reg_value method of dwarf_expr_context Zoran Zaric via Gdb-patches
2021-03-01 14:45 ` [PATCH 11/43] Remove empty frame and full evaluators Zoran Zaric via Gdb-patches
2021-03-01 14:45 ` [PATCH 12/43] Merge evaluate_for_locexpr_baton evaluator Zoran Zaric via Gdb-patches
2021-04-28 1:33 ` Simon Marchi via Gdb-patches
2021-04-28 11:39 ` Zoran Zaric via Gdb-patches
2021-03-01 14:45 ` [PATCH 13/43] Move piece_closure and its support to expr.c Zoran Zaric via Gdb-patches
2021-04-28 1:56 ` Simon Marchi via Gdb-patches
2021-04-28 11:40 ` Zoran Zaric via Gdb-patches
2021-03-01 14:45 ` [PATCH 14/43] Make value_copy also copy the stack data member Zoran Zaric via Gdb-patches
2021-04-28 2:01 ` Simon Marchi via Gdb-patches
2021-04-28 11:43 ` Zoran Zaric via Gdb-patches
2021-03-01 14:45 ` [PATCH 15/43] Make DWARF evaluator return a single struct value Zoran Zaric via Gdb-patches
2021-04-28 2:21 ` Simon Marchi via Gdb-patches
2021-04-28 11:47 ` Zoran Zaric via Gdb-patches
2021-04-28 14:24 ` Simon Marchi via Gdb-patches
2021-03-01 14:45 ` [PATCH 16/43] Simplify dwarf_expr_context class interface Zoran Zaric via Gdb-patches
2021-04-28 2:45 ` Simon Marchi via Gdb-patches
2021-04-28 13:15 ` Zoran Zaric via Gdb-patches
2021-04-28 14:41 ` Simon Marchi via Gdb-patches
2021-04-28 15:39 ` Zoran Zaric via Gdb-patches
2021-04-28 19:19 ` Simon Marchi via Gdb-patches
2021-04-29 15:49 ` Simon Marchi via Gdb-patches
2021-04-29 15:55 ` Zoran Zaric via Gdb-patches
2021-03-01 14:45 ` [PATCH 17/43] Add as_lval argument to expression evaluator Zoran Zaric via Gdb-patches
2021-04-28 3:04 ` Simon Marchi via Gdb-patches
2021-04-28 13:16 ` Zoran Zaric via Gdb-patches
2021-04-28 3:30 ` Simon Marchi via Gdb-patches
2021-03-01 14:45 ` [PATCH 18/43] Add new register access interface to expr.c Zoran Zaric via Gdb-patches
2021-03-08 23:52 ` Lancelot SIX via Gdb-patches
2021-04-28 3:25 ` Simon Marchi via Gdb-patches
2021-04-28 13:29 ` Zoran Zaric via Gdb-patches
2021-04-28 14:48 ` Simon Marchi via Gdb-patches
2021-04-28 15:42 ` Zoran Zaric via Gdb-patches
2021-03-01 14:45 ` [PATCH 19/43] Add new memory " Zoran Zaric via Gdb-patches
2021-04-30 21:24 ` Simon Marchi via Gdb-patches
2021-03-01 14:45 ` [PATCH 20/43] Add new classes that model DWARF stack element Zoran Zaric via Gdb-patches
2021-03-01 14:45 ` [PATCH 21/43] Add to_location method to DWARF entry classes Zoran Zaric via Gdb-patches
2021-03-01 14:45 ` [PATCH 22/43] Add to_value " Zoran Zaric via Gdb-patches
2021-03-01 14:46 ` [PATCH 23/43] Add read method to location description classes Zoran Zaric via Gdb-patches
2021-03-01 14:46 ` [PATCH 24/43] Add write " Zoran Zaric via Gdb-patches
2021-03-01 14:46 ` [PATCH 25/43] Add deref " Zoran Zaric via Gdb-patches
2021-03-01 14:46 ` [PATCH 26/43] Add read_from_gdb_value method to dwarf_location Zoran Zaric via Gdb-patches
2021-03-01 14:46 ` [PATCH 27/43] Add write_to_gdb_value " Zoran Zaric via Gdb-patches
2021-03-01 14:46 ` [PATCH 28/43] Add is_implicit_ptr_at " Zoran Zaric via Gdb-patches
2021-03-01 14:46 ` [PATCH 29/43] Add indirect_implicit_ptr to dwarf_location class Zoran Zaric via Gdb-patches
2021-03-01 14:46 ` [PATCH 30/43] Add new computed struct value callback interface Zoran Zaric via Gdb-patches
2021-03-01 14:46 ` [PATCH 31/43] Add to_gdb_value method to DWARF entry class Zoran Zaric via Gdb-patches
2021-03-01 14:46 ` Zoran Zaric via Gdb-patches [this message]
2021-03-01 14:46 ` [PATCH 33/43] Remove old computed struct value callbacks Zoran Zaric via Gdb-patches
2021-03-01 14:46 ` [PATCH 34/43] Comments cleanup between expr.h and expr.c Zoran Zaric via Gdb-patches
2021-03-01 14:46 ` [PATCH 35/43] Remove dwarf_expr_context from expr.h interface Zoran Zaric via Gdb-patches
2021-03-01 14:46 ` [PATCH 36/43] Move read_addr_from_reg function to frame.c Zoran Zaric via Gdb-patches
2021-03-01 14:46 ` [PATCH 37/43] Add frame info check to DW_OP_reg operations Zoran Zaric via Gdb-patches
2021-03-01 14:46 ` [PATCH 38/43] Remove DWARF expression composition check Zoran Zaric via Gdb-patches
2021-03-01 14:46 ` [PATCH 39/43] Change back the symbol needs to use the evaluator Zoran Zaric via Gdb-patches
2021-03-01 14:46 ` [PATCH 40/43] Add support for any location description in CFI Zoran Zaric via Gdb-patches
2021-03-01 14:46 ` [PATCH 41/43] Add DWARF operations for byte and bit offset Zoran Zaric via Gdb-patches
2021-03-01 14:46 ` [PATCH 42/43] Add support for DW_OP_LLVM_undefined operation Zoran Zaric via Gdb-patches
2021-03-01 14:46 ` [PATCH 43/43] Add support for nested composite locations Zoran Zaric via Gdb-patches
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210301144620.103016-33-Zoran.Zaric@amd.com \
--to=gdb-patches@sourceware.org \
--cc=Zoran.Zaric@amd.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox