[RFC PATCH v4 08/15] GDB: Allow DWARF expression evaluation to use regcache
Luis Machado
luis.machado@arm.com
Mon Dec 16 16:56:04 GMT 2024
On 11/2/24 02:56, Thiago Jung Bauermann wrote:
> Currently, expression evaluation is done in the context of a frame.
> However, for variable-size registers we will need to evaluate
> expressions when no frame is available, but we do have a regcache.
> Therefore, allow passing a regcache to dwarf2_evaluate_property.
>
> This requires adding a regcache parameter to resolve_dynamic_type and
> its internal functions.
>
> Also, this means that a DWARF expression may not be associated with an
> objfile, so when it needs a gdbarch it may not be possible to get the
> one from the objfile. The solution is to add an m_gdbarch member to
> dwarf_expr_context, and make it point to the gdbarch of either the
> objfile, frame or regcache associated with the expression.
>
> Simon suggested using GDB Agent Expressions rather than DWARF
> expressions to encode the register length. I will try it out, and if it
> works then this patch can be dropped.
Between using DWARF expressions and agent expressions, I suppose DWARF would
be the most promising as it is properly documented. Agent expressions are a
bit obscure at this point I think, and IIRC gdb-specific. But if it provides
something simpler, might be worth a shot.
> ---
> gdb/dwarf2/expr.c | 63 +++++++++++++++++++++++++++++++------
> gdb/dwarf2/expr.h | 17 +++++++++-
> gdb/dwarf2/frame.c | 2 +-
> gdb/dwarf2/loc.c | 41 +++++++++++++++++-------
> gdb/dwarf2/loc.h | 2 ++
> gdb/findvar.c | 17 ++++++++++
> gdb/frame.c | 3 +-
> gdb/gdbtypes.c | 77 ++++++++++++++++++++++++++--------------------
> gdb/gdbtypes.h | 5 ++-
> gdb/gnu-v3-abi.c | 2 +-
> gdb/value.h | 3 ++
> 11 files changed, 173 insertions(+), 59 deletions(-)
>
> diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
> index 5ad17eaaaff8..4a667dbd8107 100644
> --- a/gdb/dwarf2/expr.c
> +++ b/gdb/dwarf2/expr.c
> @@ -56,6 +56,20 @@ ensure_have_frame (const frame_info_ptr &frame, const char *op_name)
> _("%s evaluation requires a frame."), op_name);
> }
>
> +/* Ensure that either a FRAME or a REGCACHE is defined, throw an exception
> + otherwise. */
> +
> +static void
> +ensure_have_frame_or_regcache (const frame_info_ptr &frame,
> + const reg_buffer *regcache,
> + const char *op_name)
> +{
> + if (frame == nullptr && regcache == nullptr)
> + throw_error (GENERIC_ERROR,
> + _("%s evaluation requires a frame or register cache."),
> + op_name);
> +}
> +
> /* Ensure that a PER_CU is defined and throw an exception otherwise. */
>
> static void
> @@ -86,6 +100,16 @@ read_addr_from_reg (const frame_info_ptr &frame, int reg)
> return address_from_register (regnum, frame);
> }
>
> +/* See expr.h. */
> +
> +CORE_ADDR
> +read_addr_from_reg (reg_buffer *regcache, int reg)
> +{
> + int regnum = dwarf_reg_to_regnum_or_error (regcache->arch (), reg);
> +
> + return address_from_register (regnum, regcache);
> +}
> +
> struct piece_closure
> {
> /* Reference count. */
> @@ -690,7 +714,8 @@ sect_variable_value (sect_offset sect_off,
> struct type *
> dwarf_expr_context::address_type () const
> {
> - gdbarch *arch = this->m_per_objfile->objfile->arch ();
> + gdbarch *arch = (m_gdbarch == nullptr ? this->m_per_objfile->objfile->arch ()
> + : m_gdbarch);
> dwarf_gdbarch_types *types = dwarf_arch_cookie.get (arch);
> if (types == nullptr)
> types = dwarf_arch_cookie.emplace (arch);
> @@ -720,9 +745,11 @@ dwarf_expr_context::address_type () const
> /* Create a new context for the expression evaluator. */
>
> dwarf_expr_context::dwarf_expr_context (dwarf2_per_objfile *per_objfile,
> - int addr_size)
> + int addr_size,
> + gdbarch *gdbarch)
> : m_addr_size (addr_size),
> - m_per_objfile (per_objfile)
> + m_per_objfile (per_objfile),
> + m_gdbarch (gdbarch)
> {
> }
>
> @@ -915,7 +942,6 @@ dwarf_expr_context::fetch_result (struct type *type, struct type *subobj_type,
> LONGEST subobj_offset, bool as_lval)
> {
> value *retval = nullptr;
> - gdbarch *arch = this->m_per_objfile->objfile->arch ();
>
> if (type == nullptr)
> type = address_type ();
> @@ -948,6 +974,9 @@ dwarf_expr_context::fetch_result (struct type *type, struct type *subobj_type,
> }
> else
> {
> + gdbarch *arch = (m_gdbarch == nullptr ? this->m_per_objfile->objfile->arch ()
> + : m_gdbarch);
> +
> /* If AS_LVAL is false, means that the implicit conversion
> from a location description to value is expected. */
> if (!as_lval)
> @@ -1077,12 +1106,14 @@ dwarf_expr_context::fetch_result (struct type *type, struct type *subobj_type,
> value *
> dwarf_expr_context::evaluate (const gdb_byte *addr, size_t len, bool as_lval,
> dwarf2_per_cu_data *per_cu, const frame_info_ptr &frame,
> + reg_buffer *regcache,
> const struct property_addr_info *addr_info,
> struct type *type, struct type *subobj_type,
> LONGEST subobj_offset)
> {
> this->m_per_cu = per_cu;
> this->m_frame = frame;
> + this->m_regcache = regcache;
> this->m_addr_info = addr_info;
>
> eval (addr, len);
> @@ -1149,7 +1180,8 @@ get_signed_type (struct gdbarch *gdbarch, struct type *type)
> CORE_ADDR
> dwarf_expr_context::fetch_address (int n)
> {
> - gdbarch *arch = this->m_per_objfile->objfile->arch ();
> + gdbarch *arch = (m_gdbarch == nullptr ? this->m_per_objfile->objfile->arch ()
> + : m_gdbarch);
> value *result_val = fetch (n);
> bfd_endian byte_order = gdbarch_byte_order (arch);
> ULONGEST result;
> @@ -1493,7 +1525,8 @@ void
> dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
> const gdb_byte *op_end)
> {
> - gdbarch *arch = this->m_per_objfile->objfile->arch ();
> + gdbarch *arch = (this->m_gdbarch ? this->m_gdbarch
> + : this->m_per_objfile->objfile->arch ());
> bfd_endian byte_order = gdbarch_byte_order (arch);
> /* Old-style "untyped" DWARF values need special treatment in a
> couple of places, specifically DW_OP_mod and DW_OP_shr. We need
> @@ -1784,9 +1817,14 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
> case DW_OP_breg31:
> {
> op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
> - ensure_have_frame (this->m_frame, "DW_OP_breg");
> + ensure_have_frame_or_regcache (this->m_frame, this->m_regcache,
> + "DW_OP_breg");
> +
> + if (this->m_frame != nullptr)
> + result = read_addr_from_reg (this->m_frame, op - DW_OP_breg0);
> + else
> + result = read_addr_from_reg (this->m_regcache, op - DW_OP_breg0);
>
> - result = read_addr_from_reg (this->m_frame, op - DW_OP_breg0);
> result += offset;
> result_val = value_from_ulongest (address_type, result);
> }
> @@ -1795,9 +1833,14 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
> {
> op_ptr = safe_read_uleb128 (op_ptr, op_end, ®);
> op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
> - ensure_have_frame (this->m_frame, "DW_OP_bregx");
> + ensure_have_frame_or_regcache (this->m_frame, this->m_regcache,
> + "DW_OP_bregx");
> +
> + if (this->m_frame != nullptr)
> + result = read_addr_from_reg (this->m_frame, reg);
> + else
> + result = read_addr_from_reg (this->m_regcache, reg);
>
> - result = read_addr_from_reg (this->m_frame, reg);
> result += offset;
> result_val = value_from_ulongest (address_type, result);
> }
> diff --git a/gdb/dwarf2/expr.h b/gdb/dwarf2/expr.h
> index b02cc5316406..9a3c92650664 100644
> --- a/gdb/dwarf2/expr.h
> +++ b/gdb/dwarf2/expr.h
> @@ -115,12 +115,14 @@ struct dwarf_stack_value
> bool in_stack_memory;
> };
>
> +struct reg_buffer;
> +
> /* The expression evaluator works with a dwarf_expr_context, describing
> its current state and its callbacks. */
> struct dwarf_expr_context
> {
> dwarf_expr_context (dwarf2_per_objfile *per_objfile,
> - int addr_size);
> + int addr_size, gdbarch *gdbarch = nullptr);
> virtual ~dwarf_expr_context () = default;
>
> void push_address (CORE_ADDR value, bool in_stack_memory);
> @@ -128,6 +130,8 @@ struct dwarf_expr_context
> /* Evaluate the expression at ADDR (LEN bytes long) in a given PER_CU
> and FRAME context.
>
> + If FRAME is nullptr, then registers are read from REGCACHE.
> +
> AS_LVAL defines if the returned struct value is expected to be a
> value (false) or a location description (true).
>
> @@ -138,6 +142,7 @@ struct dwarf_expr_context
> memory addresses with the passed in buffer. */
> value *evaluate (const gdb_byte *addr, size_t len, bool as_lval,
> dwarf2_per_cu_data *per_cu, const frame_info_ptr &frame,
> + reg_buffer *regcache,
> const struct property_addr_info *addr_info = nullptr,
> struct type *type = nullptr,
> struct type *subobj_type = nullptr,
> @@ -198,6 +203,12 @@ struct dwarf_expr_context
> /* Frame information used for the evaluation. */
> frame_info_ptr m_frame = nullptr;
>
> + /* Register cache used for the evaluation, in case there's no frame. */
> + reg_buffer *m_regcache = nullptr;
> +
> + /* gdbarch used for the evaluation. */
> + gdbarch *m_gdbarch = nullptr;
> +
> /* Compilation unit used for the evaluation. */
> dwarf2_per_cu_data *m_per_cu = nullptr;
>
> @@ -258,6 +269,10 @@ struct dwarf_expr_context
> read as an address in a given FRAME. */
> CORE_ADDR read_addr_from_reg (const frame_info_ptr &frame, int reg);
>
> +/* Return the value of register number REG (a DWARF register number),
> + read as an address in a given REGCACHE. */
> +CORE_ADDR read_addr_from_reg (reg_buffer *regcache, int reg);
> +
> void dwarf_expr_require_composition (const gdb_byte *, const gdb_byte *,
> const char *);
>
> diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c
> index 841d2d4a2fec..3da9551a7ace 100644
> --- a/gdb/dwarf2/frame.c
> +++ b/gdb/dwarf2/frame.c
> @@ -237,7 +237,7 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size,
> scoped_value_mark free_values;
>
> ctx.push_address (initial, initial_in_stack_memory);
> - value *result_val = ctx.evaluate (exp, len, true, nullptr, this_frame);
> + value *result_val = ctx.evaluate (exp, len, true, nullptr, this_frame, nullptr);
>
> if (result_val->lval () == lval_memory)
> return result_val->address ();
> diff --git a/gdb/dwarf2/loc.c b/gdb/dwarf2/loc.c
> index d5153862a01d..d7fa58047cdd 100644
> --- a/gdb/dwarf2/loc.c
> +++ b/gdb/dwarf2/loc.c
> @@ -1518,7 +1518,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, const frame_info_ptr &frame,
> try
> {
> retval = ctx.evaluate (data, size, as_lval, per_cu, frame, nullptr,
> - type, subobj_type, subobj_byte_offset);
> + nullptr, type, subobj_type, subobj_byte_offset);
> }
> catch (const gdb_exception_error &ex)
> {
> @@ -1565,11 +1565,12 @@ dwarf2_evaluate_loc_desc (struct type *type, const frame_info_ptr &frame,
> per_objfile, NULL, 0, as_lval);
> }
>
> -/* Evaluates a dwarf expression and stores the result in VAL,
> - expecting that the dwarf expression only produces a single
> - CORE_ADDR. FRAME is the frame in which the expression is
> - evaluated. ADDR_STACK is a context (location of a variable) and
> - might be needed to evaluate the location expression.
> +/* Evaluates a dwarf expression and stores the result in VAL, expecting
> + that the dwarf expression only produces a single CORE_ADDR. FRAME is
> + the frame in which the expression is evaluated. If FRAME is nullptr,
> + then registers are read from REGCACHE instead. ADDR_STACK is a context
> + (location of a variable) and might be needed to evaluate the location
> + expression.
>
> PUSH_VALUES is an array of values to be pushed to the expression stack
> before evaluation starts. PUSH_VALUES[0] is pushed first, then
> @@ -1580,6 +1581,7 @@ dwarf2_evaluate_loc_desc (struct type *type, const frame_info_ptr &frame,
> static int
> dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
> const frame_info_ptr &frame,
> + reg_buffer *regcache,
> const struct property_addr_info *addr_stack,
> CORE_ADDR *valp,
> gdb::array_view<CORE_ADDR> push_values,
> @@ -1590,7 +1592,21 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
>
> dwarf2_per_objfile *per_objfile = dlbaton->per_objfile;
> dwarf2_per_cu_data *per_cu = dlbaton->per_cu;
> - dwarf_expr_context ctx (per_objfile, per_cu->addr_size ());
> + gdbarch *gdbarch;
> +
> + if (per_objfile != nullptr)
> + gdbarch = per_objfile->objfile->arch ();
> + else if (frame != nullptr)
> + gdbarch = get_frame_arch (frame);
> + else
> + {
> + gdb_assert (regcache != nullptr);
> + gdbarch = regcache->arch ();
> + }
> +
> + int addr_size = (per_cu == nullptr ? gdbarch_addr_bit (gdbarch) / 8
> + : per_cu->addr_size ());
> + dwarf_expr_context ctx (per_objfile, addr_size, gdbarch);
>
> value *result;
> scoped_value_mark free_values;
> @@ -1602,7 +1618,7 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
> try
> {
> result = ctx.evaluate (dlbaton->data, dlbaton->size,
> - true, per_cu, frame, addr_stack);
> + true, per_cu, frame, regcache, addr_stack);
> }
> catch (const gdb_exception_error &ex)
> {
> @@ -1641,6 +1657,7 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
> bool
> dwarf2_evaluate_property (const dynamic_prop *prop,
> const frame_info_ptr &initial_frame,
> + reg_buffer *regcache,
> const property_addr_info *addr_stack,
> CORE_ADDR *value,
> gdb::array_view<CORE_ADDR> push_values)
> @@ -1654,7 +1671,8 @@ dwarf2_evaluate_property (const dynamic_prop *prop,
> scoped_restore_current_language save_language;
> frame_info_ptr frame = initial_frame;
>
> - if (frame == NULL && has_stack_frames ())
> + /* Only try to get a frame if no regcache was provided. */
> + if (frame == nullptr && regcache == nullptr && has_stack_frames ())
> frame = get_selected_frame (NULL);
>
> switch (prop->kind ())
> @@ -1665,8 +1683,9 @@ dwarf2_evaluate_property (const dynamic_prop *prop,
> gdb_assert (baton->property_type != NULL);
>
> bool is_reference = baton->locexpr.is_reference;
> - if (dwarf2_locexpr_baton_eval (&baton->locexpr, frame, addr_stack,
> - value, push_values, &is_reference))
> + if (dwarf2_locexpr_baton_eval (&baton->locexpr, frame, regcache,
> + addr_stack, value, push_values,
> + &is_reference))
> {
> if (is_reference)
> {
> diff --git a/gdb/dwarf2/loc.h b/gdb/dwarf2/loc.h
> index 4fb743618e7c..679c4962d137 100644
> --- a/gdb/dwarf2/loc.h
> +++ b/gdb/dwarf2/loc.h
> @@ -118,8 +118,10 @@ struct property_addr_info
> etc. This means the during evaluation PUSH_VALUES[0] will be at the
> bottom of the stack. */
>
> +struct reg_buffer;
> bool dwarf2_evaluate_property (const struct dynamic_prop *prop,
> const frame_info_ptr &frame,
> + reg_buffer *regcache,
> const property_addr_info *addr_stack,
> CORE_ADDR *value,
> gdb::array_view<CORE_ADDR> push_values = {});
> diff --git a/gdb/findvar.c b/gdb/findvar.c
> index f7760aa61ca9..d65bf2fc278c 100644
> --- a/gdb/findvar.c
> +++ b/gdb/findvar.c
> @@ -656,3 +656,20 @@ address_from_register (int regnum, const frame_info_ptr &frame)
>
> return value_as_address (v.get ());
> }
> +
> +/* Return contents of register REGNUM in REGCACHE as address.
> + Will abort if register value is not available. */
> +
> +CORE_ADDR
> +address_from_register (int regnum, reg_buffer *regcache)
> +{
> + if (regcache->get_register_status (regnum) != REG_VALID)
> + throw_error (NOT_AVAILABLE_ERROR, _("register %d is not available"),
> + regnum);
> +
> + gdb_byte buffer[sizeof (CORE_ADDR)];
> + regcache->raw_collect (regnum, buffer);
> +
> + type *type = builtin_type (regcache->arch ())->builtin_data_ptr;
> + return extract_typed_address (buffer, type);
> +}
> diff --git a/gdb/frame.c b/gdb/frame.c
> index 2c1ea012191b..663ff7fa773b 100644
> --- a/gdb/frame.c
> +++ b/gdb/frame.c
> @@ -3175,7 +3175,8 @@ frame_follow_static_link (const frame_info_ptr &initial_frame)
>
> CORE_ADDR upper_frame_base;
>
> - if (!dwarf2_evaluate_property (static_link, initial_frame, NULL, &upper_frame_base))
> + if (!dwarf2_evaluate_property (static_link, initial_frame, nullptr, nullptr,
> + &upper_frame_base))
> return {};
>
> /* Now climb up the stack frame until we reach the frame we are interested
> diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
> index 2a3aea229cb0..ea8bad4e826c 100644
> --- a/gdb/gdbtypes.c
> +++ b/gdb/gdbtypes.c
> @@ -2146,7 +2146,7 @@ is_dynamic_type (struct type *type)
>
> static struct type *resolve_dynamic_type_internal
> (struct type *type, struct property_addr_info *addr_stack,
> - const frame_info_ptr &frame, bool top_level);
> + const frame_info_ptr &frame, reg_buffer *regcache, bool top_level);
>
> /* Given a dynamic range type (dyn_range_type) and a stack of
> struct property_addr_info elements, return a static version
> @@ -2168,6 +2168,7 @@ static struct type *
> resolve_dynamic_range (struct type *dyn_range_type,
> struct property_addr_info *addr_stack,
> const frame_info_ptr &frame,
> + reg_buffer *regcache,
> int rank, bool resolve_p = true)
> {
> CORE_ADDR value;
> @@ -2180,7 +2181,7 @@ resolve_dynamic_range (struct type *dyn_range_type,
> const struct dynamic_prop *prop = &dyn_range_type->bounds ()->low;
> if (resolve_p)
> {
> - if (dwarf2_evaluate_property (prop, frame, addr_stack, &value,
> + if (dwarf2_evaluate_property (prop, frame, regcache, addr_stack, &value,
> { (CORE_ADDR) rank }))
> low_bound.set_const_val (value);
> else if (prop->kind () == PROP_UNDEFINED)
> @@ -2194,7 +2195,7 @@ resolve_dynamic_range (struct type *dyn_range_type,
> prop = &dyn_range_type->bounds ()->high;
> if (resolve_p)
> {
> - if (dwarf2_evaluate_property (prop, frame, addr_stack, &value,
> + if (dwarf2_evaluate_property (prop, frame, regcache, addr_stack, &value,
> { (CORE_ADDR) rank }))
> {
> high_bound.set_const_val (value);
> @@ -2213,8 +2214,8 @@ resolve_dynamic_range (struct type *dyn_range_type,
>
> bool byte_stride_p = dyn_range_type->bounds ()->flag_is_byte_stride;
> prop = &dyn_range_type->bounds ()->stride;
> - if (resolve_p && dwarf2_evaluate_property (prop, frame, addr_stack, &value,
> - { (CORE_ADDR) rank }))
> + if (resolve_p && dwarf2_evaluate_property (prop, frame, regcache, addr_stack,
> + &value, { (CORE_ADDR) rank }))
> {
> stride.set_const_val (value);
>
> @@ -2236,7 +2237,7 @@ resolve_dynamic_range (struct type *dyn_range_type,
>
> static_target_type
> = resolve_dynamic_type_internal (dyn_range_type->target_type (),
> - addr_stack, frame, false);
> + addr_stack, frame, regcache, false);
> LONGEST bias = dyn_range_type->bounds ()->bias;
> type_allocator alloc (dyn_range_type);
> static_range_type = create_range_type_with_stride
> @@ -2270,6 +2271,7 @@ static struct type *
> resolve_dynamic_array_or_string_1 (struct type *type,
> struct property_addr_info *addr_stack,
> const frame_info_ptr &frame,
> + reg_buffer *regcache,
> int rank, bool resolve_p)
> {
> CORE_ADDR value;
> @@ -2299,7 +2301,7 @@ resolve_dynamic_array_or_string_1 (struct type *type,
> dimension of the array. */
> prop = TYPE_ALLOCATED_PROP (type);
> if (prop != NULL && resolve_p
> - && dwarf2_evaluate_property (prop, frame, addr_stack, &value))
> + && dwarf2_evaluate_property (prop, frame, regcache, addr_stack, &value))
> {
> prop->set_const_val (value);
> if (value == 0)
> @@ -2308,7 +2310,7 @@ resolve_dynamic_array_or_string_1 (struct type *type,
>
> prop = TYPE_ASSOCIATED_PROP (type);
> if (prop != NULL && resolve_p
> - && dwarf2_evaluate_property (prop, frame, addr_stack, &value))
> + && dwarf2_evaluate_property (prop, frame, regcache, addr_stack, &value))
> {
> prop->set_const_val (value);
> if (value == 0)
> @@ -2317,14 +2319,15 @@ resolve_dynamic_array_or_string_1 (struct type *type,
>
> range_type = check_typedef (type->index_type ());
> range_type
> - = resolve_dynamic_range (range_type, addr_stack, frame, rank, resolve_p);
> + = resolve_dynamic_range (range_type, addr_stack, frame, regcache, rank,
> + resolve_p);
>
> ary_dim = check_typedef (type->target_type ());
> if (ary_dim != NULL && ary_dim->code () == TYPE_CODE_ARRAY)
> {
> ary_dim = copy_type (ary_dim);
> elt_type = resolve_dynamic_array_or_string_1 (ary_dim, addr_stack,
> - frame, rank - 1,
> + frame, regcache, rank - 1,
> resolve_p);
> }
> else if (ary_dim != nullptr && ary_dim->code () == TYPE_CODE_STRING)
> @@ -2355,7 +2358,7 @@ resolve_dynamic_array_or_string_1 (struct type *type,
> Fortran, and hope that this doesn't cause problems for anyone
> else. */
> elt_type = resolve_dynamic_type_internal (type->target_type (),
> - addr_stack, frame, 0);
> + addr_stack, frame, regcache, 0);
> }
> else
> elt_type = type->target_type ();
> @@ -2365,7 +2368,7 @@ resolve_dynamic_array_or_string_1 (struct type *type,
> prop = nullptr;
> if (prop != NULL && resolve_p)
> {
> - if (dwarf2_evaluate_property (prop, frame, addr_stack, &value))
> + if (dwarf2_evaluate_property (prop, frame, regcache, addr_stack, &value))
> {
> type->remove_dyn_prop (DYN_PROP_BYTE_STRIDE);
> bit_stride = (unsigned int) (value * 8);
> @@ -2397,7 +2400,8 @@ resolve_dynamic_array_or_string_1 (struct type *type,
> static struct type *
> resolve_dynamic_array_or_string (struct type *type,
> struct property_addr_info *addr_stack,
> - const frame_info_ptr &frame)
> + const frame_info_ptr &frame,
> + reg_buffer *regcache)
> {
> CORE_ADDR value;
> int rank = 0;
> @@ -2411,7 +2415,7 @@ resolve_dynamic_array_or_string (struct type *type,
>
> /* Resolve the rank property to get rank value. */
> struct dynamic_prop *prop = TYPE_RANK_PROP (type);
> - if (dwarf2_evaluate_property (prop, frame, addr_stack, &value))
> + if (dwarf2_evaluate_property (prop, frame, regcache, addr_stack, &value))
> {
> prop->set_const_val (value);
> rank = value;
> @@ -2479,8 +2483,8 @@ resolve_dynamic_array_or_string (struct type *type,
> reduce the rank by 1 here. */
> --rank;
>
> - return resolve_dynamic_array_or_string_1 (type, addr_stack, frame, rank,
> - true);
> + return resolve_dynamic_array_or_string_1 (type, addr_stack, frame, regcache,
> + rank, true);
> }
>
> /* Resolve dynamic bounds of members of the union TYPE to static
> @@ -2490,7 +2494,8 @@ resolve_dynamic_array_or_string (struct type *type,
> static struct type *
> resolve_dynamic_union (struct type *type,
> struct property_addr_info *addr_stack,
> - const frame_info_ptr &frame)
> + const frame_info_ptr &frame,
> + reg_buffer *regcache)
> {
> struct type *resolved_type;
> int i;
> @@ -2508,7 +2513,7 @@ resolve_dynamic_union (struct type *type,
> continue;
>
> t = resolve_dynamic_type_internal (resolved_type->field (i).type (),
> - addr_stack, frame, false);
> + addr_stack, frame, regcache, false);
> resolved_type->field (i).set_type (t);
>
> struct type *real_type = check_typedef (t);
> @@ -2682,7 +2687,8 @@ compute_variant_fields (struct type *type,
> static struct type *
> resolve_dynamic_struct (struct type *type,
> struct property_addr_info *addr_stack,
> - const frame_info_ptr &frame)
> + const frame_info_ptr &frame,
> + reg_buffer *regcache)
> {
> struct type *resolved_type;
> int i;
> @@ -2725,8 +2731,8 @@ resolve_dynamic_struct (struct type *type,
> prop.set_locexpr (&baton);
>
> CORE_ADDR addr;
> - if (dwarf2_evaluate_property (&prop, frame, addr_stack, &addr,
> - {addr_stack->addr}))
> + if (dwarf2_evaluate_property (&prop, frame, regcache, addr_stack,
> + &addr, {addr_stack->addr}))
> resolved_type->field (i).set_loc_bitpos
> (TARGET_CHAR_BIT * (addr - addr_stack->addr));
> }
> @@ -2752,7 +2758,7 @@ resolve_dynamic_struct (struct type *type,
>
> resolved_type->field (i).set_type
> (resolve_dynamic_type_internal (resolved_type->field (i).type (),
> - &pinfo, frame, false));
> + &pinfo, frame, regcache, false));
> gdb_assert (resolved_type->field (i).loc_kind ()
> == FIELD_LOC_KIND_BITPOS);
>
> @@ -2798,6 +2804,7 @@ static struct type *
> resolve_dynamic_type_internal (struct type *type,
> struct property_addr_info *addr_stack,
> const frame_info_ptr &frame,
> + reg_buffer *regcache,
> bool top_level)
> {
> struct type *real_type = check_typedef (type);
> @@ -2811,7 +2818,7 @@ resolve_dynamic_type_internal (struct type *type,
> std::optional<CORE_ADDR> type_length;
> prop = TYPE_DYNAMIC_LENGTH (type);
> if (prop != NULL
> - && dwarf2_evaluate_property (prop, frame, addr_stack, &value))
> + && dwarf2_evaluate_property (prop, frame, regcache, addr_stack, &value))
> type_length = value;
>
> if (type->code () == TYPE_CODE_TYPEDEF)
> @@ -2819,7 +2826,7 @@ resolve_dynamic_type_internal (struct type *type,
> resolved_type = copy_type (type);
> resolved_type->set_target_type
> (resolve_dynamic_type_internal (type->target_type (), addr_stack,
> - frame, top_level));
> + frame, regcache, top_level));
> }
> else
> {
> @@ -2849,8 +2856,8 @@ resolve_dynamic_type_internal (struct type *type,
> {
> resolved_type = copy_type (type);
> resolved_type->set_target_type
> - (resolve_dynamic_type_internal (type->target_type (),
> - &pinfo, frame, true));
> + (resolve_dynamic_type_internal (type->target_type (), &pinfo,
> + frame, regcache, true));
> }
> break;
> }
> @@ -2860,7 +2867,7 @@ resolve_dynamic_type_internal (struct type *type,
> treated as one here. */
> case TYPE_CODE_ARRAY:
> resolved_type = resolve_dynamic_array_or_string (type, addr_stack,
> - frame);
> + frame, regcache);
> break;
>
> case TYPE_CODE_RANGE:
> @@ -2869,15 +2876,18 @@ resolve_dynamic_type_internal (struct type *type,
> this rank value is not actually required for the resolution of
> the dynamic range, otherwise, we'd be resolving this range
> within the context of a dynamic array. */
> - resolved_type = resolve_dynamic_range (type, addr_stack, frame, 0);
> + resolved_type = resolve_dynamic_range (type, addr_stack, frame,
> + regcache, 0);
> break;
>
> case TYPE_CODE_UNION:
> - resolved_type = resolve_dynamic_union (type, addr_stack, frame);
> + resolved_type = resolve_dynamic_union (type, addr_stack, frame,
> + regcache);
> break;
>
> case TYPE_CODE_STRUCT:
> - resolved_type = resolve_dynamic_struct (type, addr_stack, frame);
> + resolved_type = resolve_dynamic_struct (type, addr_stack, frame,
> + regcache);
> break;
> }
> }
> @@ -2894,7 +2904,7 @@ resolve_dynamic_type_internal (struct type *type,
> /* Resolve data_location attribute. */
> prop = TYPE_DATA_LOCATION (resolved_type);
> if (prop != NULL
> - && dwarf2_evaluate_property (prop, frame, addr_stack, &value))
> + && dwarf2_evaluate_property (prop, frame, regcache, addr_stack, &value))
> {
> /* Start of Fortran hack. See comment in f-lang.h for what is going
> on here.*/
> @@ -2915,7 +2925,8 @@ struct type *
> resolve_dynamic_type (struct type *type,
> gdb::array_view<const gdb_byte> valaddr,
> CORE_ADDR addr,
> - const frame_info_ptr *in_frame)
> + const frame_info_ptr *in_frame,
> + reg_buffer *regcache)
> {
> struct property_addr_info pinfo
> = {check_typedef (type), valaddr, addr, NULL};
> @@ -2924,7 +2935,7 @@ resolve_dynamic_type (struct type *type,
> if (in_frame != nullptr)
> frame = *in_frame;
>
> - return resolve_dynamic_type_internal (type, &pinfo, frame, true);
> + return resolve_dynamic_type_internal (type, &pinfo, frame, regcache, true);
> }
>
> /* See gdbtypes.h */
> diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
> index f80bd7e071a3..514af300de3b 100644
> --- a/gdb/gdbtypes.h
> +++ b/gdb/gdbtypes.h
> @@ -2625,9 +2625,12 @@ extern CORE_ADDR get_pointer_type_max (struct type *);
> have a different type when resolved (depending on the contents of
> memory). In this situation, 'is_dynamic_type' will still return
> true for the return value of this function. */
> +
> +struct reg_buffer;
> extern struct type *resolve_dynamic_type
> (struct type *type, gdb::array_view<const gdb_byte> valaddr,
> - CORE_ADDR addr, const frame_info_ptr *frame = nullptr);
> + CORE_ADDR addr, const frame_info_ptr *frame = nullptr,
> + reg_buffer *regcache = nullptr);
>
> /* * Predicate if the type has dynamic values, which are not resolved yet.
> See the caveat in 'resolve_dynamic_type' to understand a scenario
> diff --git a/gdb/gnu-v3-abi.c b/gdb/gnu-v3-abi.c
> index aefbee542703..5cc0d1d2d4f4 100644
> --- a/gdb/gnu-v3-abi.c
> +++ b/gdb/gnu-v3-abi.c
> @@ -493,7 +493,7 @@ gnuv3_baseclass_offset (struct type *type, int index,
> addr_stack.next = nullptr;
>
> CORE_ADDR result;
> - if (dwarf2_evaluate_property (&prop, nullptr, &addr_stack, &result,
> + if (dwarf2_evaluate_property (&prop, nullptr, nullptr, &addr_stack, &result,
> {addr_stack.addr}))
> return (int) (result - addr_stack.addr);
> }
> diff --git a/gdb/value.h b/gdb/value.h
> index 13cfb007aa2c..802a49066288 100644
> --- a/gdb/value.h
> +++ b/gdb/value.h
> @@ -1133,6 +1133,9 @@ extern struct value *value_from_register (struct type *type, int regnum,
>
> extern CORE_ADDR address_from_register (int regnum,
> const frame_info_ptr &frame);
> +struct reg_buffer;
> +extern CORE_ADDR address_from_register (int regnum,
> + reg_buffer *regcache);
>
> extern struct value *value_of_variable (struct symbol *var,
> const struct block *b);
More information about the Gdb-patches
mailing list