From patchwork Sat Nov 2 02:56:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thiago Jung Bauermann X-Patchwork-Id: 840279 Delivered-To: patch@linaro.org Received: by 2002:adf:a38c:0:b0:37d:45d0:187 with SMTP id l12csp1158542wrb; Fri, 1 Nov 2024 19:59:15 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCVj+NnKoC9gxZkxo65my24uNlkabC3yuwsQt6qW4Vk/TF4FJNXF+povsP+q3bsgjcqJy/NOcg==@linaro.org X-Google-Smtp-Source: AGHT+IERziMiaCUIU462lsU65FI4B2kH/c3srfY05925SCYhrB7yR6cOO/RvHEH9ae4fl0LHrCoq X-Received: by 2002:a05:620a:29ca:b0:7b1:4ff4:69f3 with SMTP id af79cd13be357-7b1aedb9fd5mr1506001985a.29.1730516354781; Fri, 01 Nov 2024 19:59:14 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1730516354; cv=pass; d=google.com; s=arc-20240605; b=ZwPGwoUqMjgVsV5J1W4oh6099BrpB6mQTazboQN94fRjxwzxizi63C6GL8mw9eI1io MxsEwEeveJfvCsU0VZJptCO1gHpIVsGvkyKIlu82deSzPr7DM1RFY2TI62/DaTuvkkqT S94o5FRNr0kqyqii8KShrNWXpg2JZ4C0TokMD+tYjBvf1RFX21WVAytaSr0AVpk95v1V 3VOgRyOZBStcrlwGugvj9IQ96nLSp4kZd55oudlwwzxuGOBdlEvHKAxNvXTaLgasQ6rY Dp/UTqLRSzinKinOtZdQpU/Vi9BZEVUehmRKHxvuiAdSPJW/rGLcpPBQOhwTIy7vTuLe Mp3w== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:to:from :dkim-signature:arc-filter:dmarc-filter:delivered-to; bh=Fgy85mf7FAd/+4Qn9FNEByi9VYvsuM3Y314OR32iWmo=; fh=72kqq0iQhigvR9Vv/oqX5ebs3Yyyw7XhzWxOOEPdupI=; b=kU5YVL6uz6KOtkvg0VihAwvRAmPboRQyUKp1DP33O0QxP2IbUkZ5d/o2UGLHOvdbZn oC6rfKDqjaFcqkZQVtpOYly7Nw1pR4qgpTuLqsiF1rmmpTo6ufzHkL85yaY2S8SEJ4XM xJQJe7Ew6aLOBCFYw0/MN2OUpCXe2woVHntlWHrtBN3/n8dP7mAyg7G2MVSE+zWc90mD a4LAdXKPKPaMKVXc9K5W4h52Lc5wqU2nKMeVFGHEeF8LryeyP/X4UVC+CwzIzYl5qeWY dvYQPpw6ySKPFsi26u64mJLUIRdLrWg4MoKwEmJwNzLYNZBE/1U2zDy54vPOLy0JMNpw rovQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=u89ZmSDV; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id 6a1803df08f44-6d35416a9d8si55441186d6.263.2024.11.01.19.59.14 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:59:14 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=u89ZmSDV; arc=pass (i=1); spf=pass (google.com: domain of gdb-patches-bounces~patch=linaro.org@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gdb-patches-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 68A813857BAF for ; Sat, 2 Nov 2024 02:59:14 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-pf1-x434.google.com (mail-pf1-x434.google.com [IPv6:2607:f8b0:4864:20::434]) by sourceware.org (Postfix) with ESMTPS id 5F9633858019 for ; Sat, 2 Nov 2024 02:57:05 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 5F9633858019 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 5F9633858019 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::434 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516229; cv=none; b=NBtC18lVojg2HflcUVRmmYjAyUTgd+/rFDPOE6cWhVDnY3anApRgJjZArrL5JTPwDQOPCbkhxChXPWp21nVo+fJuIEdYNkD1+8KkKLCBmO1+z3i7302VVmFlghXJWPCiVTmqbpE0Do4Z59sjqlhwmWqe8ikLoYHtz8fZUGhWcRQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730516229; c=relaxed/simple; bh=javaxhnSj17ex2NysK1LiHJh9C1+zmIJaslM+ApknCU=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=PgYYSCwJXc6eQ39NkLAUXrzjVA1SVfjr0/jYm9ANnG6W7sMnkNK2MPit9/rCDFz+C9lfaCTWtTVxvBu0CbLBmfRyI9+DJ6wy+RVcG/RyWlW7znU5hfSGLpMlY8lmX4E7sOkKSz+7dGsvAsB/xhABkI/DAZ05xkx5WXHH7rIK5lU= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pf1-x434.google.com with SMTP id d2e1a72fcca58-71ec997ad06so2175246b3a.3 for ; Fri, 01 Nov 2024 19:57:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1730516224; x=1731121024; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=Fgy85mf7FAd/+4Qn9FNEByi9VYvsuM3Y314OR32iWmo=; b=u89ZmSDVPcA8zAclpNeeFjcdLLpCLc+otPCAKsIr1fmWe/vLKK7wZksearGYGY2FHZ WbZ7xjG7I+FaJhdjLnGyfSK6k5RdtaUPTHxlJuYwOV2bp/FXF+6uAr6M4BUiJ7tQ3n/T WEcNzVnE+/U8ECwwjnGZsRQNj/HRayfzobhs4KyR0VjOrhAwXkGnXxbnOF91Tpv6JBHm dy566M/jh1fwIDGlGhZ9XozK4FQhFl3U3todA2DkivvIXXQFzWxSBQpAwSBLLMPHCypx YYJG0O7mf+ai/GA9vij9oGHvVwkBIW4LaV9/hBquGg/PxMoj13jpwQf4NFBJP7QiM21/ j/1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730516224; x=1731121024; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Fgy85mf7FAd/+4Qn9FNEByi9VYvsuM3Y314OR32iWmo=; b=nLkMRvMxtpR8G2FgoE1/ErWGqYceW8NnpKF90+Z5da6V5ofX6y7QXn3a2YV7JK9zJg 7Lcu4I8uJJtWzeSgYqhkQle5ngzEic9U0GV8bhECexYG1MArBd1geMQe+BtCq0ZzXwiF zuqCzi4gk73Wma57qzin/VrHLsGRDYn503H8SELNuA5ZxGFTJCZrTzHWLagc1/MAh8hv +DkfrsfCKfWYpIkyef80VZNkKP4oZyjVcHkQOX9My4jTcEyOYlLWaqA0PCo6X5Y/mKGT kmiKmxBUkhqyvPS9OQs8YpEyHJ/4X/cahLf8mdSbq6LmJaXIAbT5at9sR8oErknzuIEw 04XQ== X-Gm-Message-State: AOJu0YywSkBfFjt4pAva334d0z7Rrd+AYVgzCBsCV6NacIyqmZruX5VD xtf/6STptrRx5AgPxR2QA5nOHyciy8VzgUi3u/syFO8rmMuPyiUEJdWRUQR1frsZayF51MmPmOe V X-Received: by 2002:a05:6a20:9d8e:b0:1d9:ed47:3b7d with SMTP id adf61e73a8af0-1d9eeb95e1cmr19404245637.13.1730516224159; Fri, 01 Nov 2024 19:57:04 -0700 (PDT) Received: from localhost ([2804:14d:7e39:8470:f214:b4dc:314a:c1ee]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-7ee74cc2a59sm181737a12.54.2024.11.01.19.57.03 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Nov 2024 19:57:03 -0700 (PDT) From: Thiago Jung Bauermann To: gdb-patches@sourceware.org Subject: [RFC PATCH v4 08/15] GDB: Allow DWARF expression evaluation to use regcache Date: Fri, 1 Nov 2024 23:56:28 -0300 Message-ID: <20241102025635.586759-9-thiago.bauermann@linaro.org> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20241102025635.586759-1-thiago.bauermann@linaro.org> References: <20241102025635.586759-1-thiago.bauermann@linaro.org> MIME-Version: 1.0 X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~patch=linaro.org@sourceware.org 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. --- 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 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 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 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 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 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 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);