Message ID | 20241102025635.586759-9-thiago.bauermann@linaro.org |
---|---|
State | New |
Headers | show |
Series | gdbserver improvements for AArch64 SVE support | expand |
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);
Luis Machado <luis.machado@arm.com> writes: > 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. I agree. I'll experiment with agent expressions and report back. -- Thiago
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);