From 76f72769715a959fa98482f201ca9967950490db Mon Sep 17 00:00:00 2001 From: Thiago Jung Bauermann Date: Sun, 27 Apr 2025 22:57:17 -0300 Subject: [PATCH] GDB: Allow passing regcache to resolve_dynamic_type () When reg_buffer::initialize_variable_size_registers () is called, there may not be any frame available yet. On the other hand, the reg_buffer should already have any register values needed to calculate target description parameter values and therefore resolve dynamic types. So allow passing a regcache to resolve_dynamic_type (), and use it in dwarf2_evaluate_property () when processing a target description parameter property. Because initialize_variable_size_registers () is a reg_buffer method, dwarf2_evaluate_property () can't call tdesc_parameter_value () which is a readable_regcache method. So we need to add a collect_tdesc_parameter () method to reg_buffer and check that the collected parameter is valid. --- gdb/dwarf2/loc.c | 20 +++++++++++-- gdb/dwarf2/loc.h | 2 ++ gdb/frame.c | 3 +- gdb/gdbtypes.c | 77 +++++++++++++++++++++++++++--------------------- gdb/gdbtypes.h | 5 +++- gdb/gnu-v3-abi.c | 2 +- gdb/regcache.c | 18 +++++++---- gdb/regcache.h | 4 +++ 8 files changed, 88 insertions(+), 43 deletions(-) diff --git a/gdb/dwarf2/loc.c b/gdb/dwarf2/loc.c index 9df9a453240..acbb241c8e4 100644 --- a/gdb/dwarf2/loc.c +++ b/gdb/dwarf2/loc.c @@ -1642,6 +1642,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 push_values) @@ -1772,7 +1773,8 @@ dwarf2_evaluate_property (const dynamic_prop *prop, case PROP_TDESC_PARAMETER: { - gdbarch *gdbarch = get_frame_arch (frame); + gdbarch *gdbarch = (regcache == nullptr ? + get_frame_arch (frame) : regcache->arch ()); auto [feature, param_name, element_length] = prop->tdesc_parameter (); std::optional param_id = tdesc_parameter_id (gdbarch, feature, @@ -1780,7 +1782,21 @@ dwarf2_evaluate_property (const dynamic_prop *prop, if (!param_id.has_value ()) return false; - return read_frame_tdesc_parameter_unsigned (frame, *param_id, value); + if (regcache == nullptr) + return read_frame_tdesc_parameter_unsigned (frame, *param_id, value); + else + { + if (regcache->get_tdesc_parameter_status (*param_id) != REG_VALID) + return false; + + gdb::byte_vector buf (tdesc_parameter_size (gdbarch, *param_id)); + + regcache->collect_tdesc_parameter (*param_id, buf); + + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + *value = extract_unsigned_integer (buf, byte_order); + return true; + } } break; } diff --git a/gdb/dwarf2/loc.h b/gdb/dwarf2/loc.h index 30c528b525d..aba1d7ea184 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 push_values = {}); diff --git a/gdb/frame.c b/gdb/frame.c index 960e6884456..e8c2b894e46 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -3261,7 +3261,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 e6dd6d64e25..6472dda8034 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -2207,7 +2207,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 @@ -2229,6 +2229,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; @@ -2241,7 +2242,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) @@ -2255,7 +2256,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 })) { /* In the case of a vector with tdesc parameter in the range, we @@ -2287,8 +2288,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); @@ -2310,7 +2311,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 @@ -2344,6 +2345,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; @@ -2373,7 +2375,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) @@ -2382,7 +2384,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) @@ -2391,14 +2393,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) @@ -2429,7 +2432,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 (); @@ -2439,7 +2442,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); @@ -2471,7 +2474,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; @@ -2485,7 +2489,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; @@ -2553,8 +2557,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 @@ -2564,7 +2568,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; @@ -2582,7 +2587,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); @@ -2756,7 +2761,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; @@ -2799,8 +2805,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)); } @@ -2826,7 +2832,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); @@ -2872,6 +2878,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); @@ -2885,7 +2892,7 @@ resolve_dynamic_type_internal (struct type *type, std::optional 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) @@ -2893,7 +2900,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 { @@ -2923,8 +2930,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; } @@ -2934,7 +2941,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: @@ -2943,15 +2950,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; } } @@ -2968,7 +2978,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.*/ @@ -2989,7 +2999,8 @@ struct type * resolve_dynamic_type (struct type *type, gdb::array_view 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}; @@ -2998,7 +3009,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 3132e4478f0..68ca02039a7 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -2640,9 +2640,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 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 4f53e9ff154..b0c42e33d1b 100644 --- a/gdb/gnu-v3-abi.c +++ b/gdb/gnu-v3-abi.c @@ -494,7 +494,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/regcache.c b/gdb/regcache.c index 120de8fd790..8942722f803 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -375,11 +375,9 @@ reg_buffer::initialize_variable_size_registers () continue; } - /* Assume the register cache is for the current frame. */ - frame_info_ptr frame = get_current_frame (); m_variable_size_register_type[i] = resolve_dynamic_type (m_descr->register_type[i], {}, - /* Unused address. */ 0, &frame); + /* Unused address. */ 0, nullptr, this); ULONGEST size = m_variable_size_register_type[i]->length (); gdb_assert (size != 0); @@ -454,6 +452,18 @@ reg_buffer::invalidate_tdesc_parameter (unsigned int param_id) /* See regcache.h. */ +void +reg_buffer::collect_tdesc_parameter (unsigned int param_id, + gdb::array_view dst) +{ + gdb::array_view buf = tdesc_parameter_buffer (param_id); + gdb_assert (buf.size () == dst.size ()); + + copy (buf, dst); +} + +/* See regcache.h. */ + void reg_buffer::supply_parameter (unsigned int param_id, gdb::array_view src) @@ -1421,8 +1431,6 @@ register_status readable_regcache::tdesc_parameter_value (unsigned int param_id, gdb::array_view dst) { - gdb_assert (param_id < m_tdesc_parameter_status.size ()); - ULONGEST size = tdesc_parameter_size (m_descr->gdbarch, param_id); gdb_assert (dst.size () == size); diff --git a/gdb/regcache.h b/gdb/regcache.h index 8fc82d1913b..97552474a9c 100644 --- a/gdb/regcache.h +++ b/gdb/regcache.h @@ -272,6 +272,10 @@ public: /* See gdbsupport/common-regcache.h. */ int register_size (int regnum) const override; + /* FIXME: Document. */ + void collect_tdesc_parameter (unsigned int param_id, + gdb::array_view dst); + /* FIXME: Document. Assumes SRC contains an integer in target byte order. */ void supply_parameter (unsigned int param_id, -- 2.47.2