From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from NAM12-MW2-obe.outbound.protection.outlook.com (mail-mw2nam12on2056.outbound.protection.outlook.com [40.107.244.56]) by sourceware.org (Postfix) with ESMTPS id F116B393D02B for ; Mon, 7 Dec 2020 19:01:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org F116B393D02B ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=jROsf5vVTghXs2DBc/+3iuN9bPRECgSvJPHGXcUx+dcGW3XF3qFCw0BiX3Z7ZX430fv3U4PgZXRRVHwSrQgsiDbdwA1Dxf+d4rEBjv599eGnyUhV/opUzx0ADL0+nWe4PS/z08n2remUIuCKnM1fQUeWTCoQjBp1mVYB6+CJdd/rHeLXIopZY3S1W383LN+GDUvF9vGBqVpL42qDqKnTNCiUSfuXkI1ejARQYLzuIHJ91msSeTqcp4aKMRO+ESBzr1b/ysxU9gPvxpDU3msKox6BvNdrmP4JMOaHQiYhfN9DN6YuRC2ueAuy5f616VwHN+Pf9cS6uoOyUTGHgBYPMA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=0QbWvy2LfjTdt6Z2P/tAFXVoHyzGrkGsI3OzpFn8v20=; b=i/h7kReRmO5TCP3b6nRObcSNpMzllbAy86lipVc7w0M0bXN18HgudBn2WbvfGLao9XWNjl4xLZswRXj3gKk1TAHohaOFQBzIbnaT9qZt+dUQiA8IkIGR7yEQxaGQshbVI3vHLdo5wMnCZHFAVBAkbNaQH3mGFK7R3yVH9XX+WfN6M+5aQD1QmPfdefO1gR2BRt1ezOYnpfI14F/ZZhNwJBbAQIg7AXQF4YRM/JXSDNlyg0Or2BUcwB/gqdOmCbOI89ANJjXY+2bc0pIi1vFF+l16BWOQLwnJAGNkrbElQJQqGHyIPHSrphjB3ghLnR2/xrY758BpkSXn+vIWszrwhg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=amd.com; dmarc=pass action=none header.from=amd.com; dkim=pass header.d=amd.com; arc=none Received: from DM6PR12MB2762.namprd12.prod.outlook.com (2603:10b6:5:45::15) by DM6PR12MB4561.namprd12.prod.outlook.com (2603:10b6:5:2ac::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3632.18; Mon, 7 Dec 2020 19:01:29 +0000 Received: from DM6PR12MB2762.namprd12.prod.outlook.com ([fe80::6841:61df:984b:b3c]) by DM6PR12MB2762.namprd12.prod.outlook.com ([fe80::6841:61df:984b:b3c%3]) with mapi id 15.20.3632.021; Mon, 7 Dec 2020 19:01:29 +0000 From: Zoran Zaric To: gdb-patches@sourceware.org Cc: Zoran Zaric Subject: [PATCH 22/30] Remove dwarf_expr_context from expr.h interface Date: Mon, 7 Dec 2020 19:00:23 +0000 Message-Id: <20201207190031.13341-23-Zoran.Zaric@amd.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201207190031.13341-1-Zoran.Zaric@amd.com> References: <20201207190031.13341-1-Zoran.Zaric@amd.com> Content-Type: text/plain X-Originating-IP: [2a00:23c7:5a85:6801:5c7:2db6:d2c2:ae4e] X-ClientProxiedBy: AM4PR0101CA0053.eurprd01.prod.exchangelabs.com (2603:10a6:200:41::21) To DM6PR12MB2762.namprd12.prod.outlook.com (2603:10b6:5:45::15) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from localhost.localdomain (2a00:23c7:5a85:6801:5c7:2db6:d2c2:ae4e) by AM4PR0101CA0053.eurprd01.prod.exchangelabs.com (2603:10a6:200:41::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3632.17 via Frontend Transport; Mon, 7 Dec 2020 19:01:26 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: 625a7d1c-d6ab-459d-bac4-08d89ae28122 X-MS-TrafficTypeDiagnostic: DM6PR12MB4561: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:3968; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 4+IV3EeF1OPA2duG0YIwkoGLTq0IldfSqcxNeKumQi5NQnCbvVrxC4Tu/xAIAmyDa8RtyenY42EQ2JbLVLOc678qow2LwmpJFe62Oda8wVNOWRPpjkRmauytF9SMGQJZep2wdeUSU3/8IREmL2CKG7Rt20Brw423yFR/vxCcV8Ynwn1rCzzzYJWVQGPLpcJ8rn008wlV4PZXpcOYh5XL50OIcvjUqFH4P++cJ02FJ+3/1jE9HH9JUWd7P5OVj3eAIhJ/G2lDILafwCNkdeq0V/vQO9oYywlaewJKGE5uhrhLI/HpR8Y/mzaSCybx09UAiqyJEKrUh9en9xEXT623/IjSlf6dzAF57DbhnXdjNxKW429bwFvBsbO/0A9w7NS3 X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:DM6PR12MB2762.namprd12.prod.outlook.com; PTR:; CAT:NONE; SFS:(4636009)(376002)(346002)(39860400002)(366004)(136003)(396003)(1076003)(30864003)(83380400001)(86362001)(6506007)(4326008)(69590400008)(52116002)(36756003)(2906002)(6512007)(8676002)(6486002)(16526019)(2616005)(66946007)(66476007)(66556008)(6916009)(5660300002)(186003)(8936002)(478600001)(6666004)(316002); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData: =?us-ascii?Q?XvxIzBpbf5jeXLbXgRTtX5mD0kmL/AJt6h+DFG9vNLDFerprjCt+06n0roc7?= =?us-ascii?Q?oZUbSHp+GOXw8DLR9xW36OtHznOD0PetUcZ6O1uLxaocKYKGEIf7YJatEpkK?= =?us-ascii?Q?Sbv+NXn8VELaQJu8XBWZK4Gezy6Rchnejqk5CLoUuFmuMwBJxduaqleXUrql?= =?us-ascii?Q?Ep5Xlv4jBxN4TB6/Nx8UJPb69Hn26QeJdLmkcEQNLaIP+5VkvcQOXhcQG4OF?= =?us-ascii?Q?BRZlyceMPoC0cCGIHm31HemhTi7M4CnHbNOn2x2SA0ivdBmNmnmy0H0Lp42H?= =?us-ascii?Q?mwvllPfBRhjI64nwmGnRWslEAHvIcpfOZQeJeCz67hdW5D3f/9/7h7HzcS9U?= =?us-ascii?Q?9eTLE9Gu1bzczFbyg6LhHMrhqAUT+ppzS8x4X7rT/uIV6FNkyWlLdYCz7Jam?= =?us-ascii?Q?X2tKK8q63ahKLS1HZGHA+IRSVjRweMPYTrW2HtbBr2MEVGxK6gIXfHKzOUd4?= =?us-ascii?Q?6HyaC4zKjUrb+V2PeRys4hMedP89lGV8NKT43xVM1DvFSSUdmDSFQfuKsi87?= =?us-ascii?Q?eIHFHJBjATCj3znye5l1QyffrJWIfugnF1FMYXYNunzybKC2rckgVPxYZx0c?= =?us-ascii?Q?i36e9owz9mGkmayiNcQwbznTsCciMsChQ6L4wPszEpd7flC87G2zeCwmD6bw?= =?us-ascii?Q?joFKTuxKhGOOkld2vfmlddjUEWcN3wELcwt91QIowdEG9W/ngdLPUvn7UJwQ?= =?us-ascii?Q?eggdVaWAe9YTCc2sYaPPLEIm4MgE/Tp+q0TDvZk6OXJ8wI/4jCU6YT98GmeH?= =?us-ascii?Q?n5NhCONOCyVkmS5yoGEwVsrKT3Y40nbzRkfFpJiUScym6aoLC5vbSaL5bbmS?= =?us-ascii?Q?SyUu6E7ats8k59UaMolzyZk6rC1Ygy8IKacTwoxlmCkeHxRzTCg+F8eQslZw?= =?us-ascii?Q?iRu6sZhA8Jxrs1KtU14mZsz2BFmtRZM9o2PyW3PC/tvikqoOV2ACXbYJGVy5?= =?us-ascii?Q?4MWPqL5dvKVWeV5wd8YN2H1RvMaEIzGVIPtUUSlgjfKw5WrP1/9wZbJDXq/G?= =?us-ascii?Q?AKQqs/JqxpMV9f7j+P2YYGpVN1XmcaWMbOFdKT8aknZy8GUjJbUE9LgqoYZl?= =?us-ascii?Q?T1ZGLo8l?= X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-AuthSource: DM6PR12MB2762.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Dec 2020 19:01:29.1908 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-Network-Message-Id: 625a7d1c-d6ab-459d-bac4-08d89ae28122 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: otkGQVke/rpSyZWhRwIqv5Z1hqTGU4AQNay1WkydQZ+3bzIcNRxgST7fUGqJYOZ+jOY1hP6Lkn/rkNQi200miQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR12MB4561 X-Spam-Status: No, score=-12.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, MSGID_FROM_MTA_HEADER, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 07 Dec 2020 19:01:39 -0000 After the switch to the new evaluator implementation, it is now possible to completely remove the dwarf_expr_context class from the expr.h interface and encapsulate it inside the expr.c file. The new interface consists of a new function called dwarf2_eval_exp that takes a DWARF expression stream, initial DWARF stack elements (in a form of a vector of a struct value objects), evaluation context and expected result type information. Function returns an evaluation result in a form of a struct value object. Currently, there is ever only one initial stack element provided to the evaluator and that element is always a memory address, so having a vector of struct value object might seems like an overkill. In reality this new flexibility allows implementation of a new DWARF attribute extensions that could provide any number of initial stack elements to describe any location description or value. gdb/ChangeLog: * dwarf2/expr.c (dwarf2_eval_exp): New function. (struct dwarf_expr_context): Move from expr.h. (dwarf_expr_context::push_address): Remove function. * dwarf2/expr.h (struct dwarf_expr_context): Move to expr.c. * dwarf2/frame.c (execute_stack_op): Now calls dwarf2_eval_exp. * dwarf2/loc.c (dwarf2_evaluate_loc_desc_full): Now calls dwarf2_eval_exp. (dwarf2_locexpr_baton_eval): Now calls dwarf2_eval_exp. --- gdb/dwarf2/expr.c | 226 ++++++++++++++++++++++++++++++++++++--------- gdb/dwarf2/expr.h | 181 ++++-------------------------------- gdb/dwarf2/frame.c | 14 ++- gdb/dwarf2/loc.c | 23 +++-- 4 files changed, 227 insertions(+), 217 deletions(-) diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c index aefbeb3dad..9ed0ad8baf 100644 --- a/gdb/dwarf2/expr.c +++ b/gdb/dwarf2/expr.c @@ -1820,7 +1820,165 @@ sect_variable_value (sect_offset sect_off, type, true); } -/* See expr.h. */ +/* The expression evaluator works with a dwarf_expr_context, describing + its current state and its callbacks. */ +struct dwarf_expr_context +{ + /* Create a new context for the expression evaluator. + + We should ever only pass in the PER_OBJFILE and the ADDR_SIZE + information should be retrievable from there. The PER_OBJFILE + contains a pointer to the PER_BFD information anyway and the + address size information must be the same for the whole BFD. */ + dwarf_expr_context (struct dwarf2_per_objfile *per_objfile, + int addr_size); + + /* Destroy dwarf entry factory object. */ + virtual ~dwarf_expr_context (); + + /* Evaluate the expression at ADDR (LEN bytes long) in a given PER_CU + FRAME context. INIT_VALUES vector contains values that are + expected to be pushed on a DWARF expression stack before the + evaluation. AS_LVAL defines if the returned struct value is + expected to be a value or a location description. Where TYPE, + SUBOBJ_TYPE and SUBOBJ_OFFSET describe expected struct value + representation of the evaluation result. The ADDR_INFO property + can be specified to override the range of memory addresses with + the passed in buffer. */ + struct value *eval_exp (const gdb_byte *addr, size_t len, bool as_lval, + struct dwarf2_per_cu_data *per_cu, + struct frame_info *frame, + std::vector *init_values, + const struct property_addr_info *addr_info, + struct type *type, struct type *subobj_type, + LONGEST subobj_offset); + +private: + /* The stack of values. */ + std::vector stack; + + /* Target architecture to use for address operations. */ + struct gdbarch *gdbarch; + + /* Target address size in bytes. */ + int addr_size; + + /* DW_FORM_ref_addr size in bytes. If -1 DWARF is executed + from a frame context and operations depending on DW_FORM_ref_addr + are not allowed. */ + int ref_addr_size; + + /* The current depth of dwarf expression recursion, via DW_OP_call*, + DW_OP_fbreg, DW_OP_push_object_address, etc., and the maximum + depth we'll tolerate before raising an error. */ + int recursion_depth, max_recursion_depth; + + /* We evaluate the expression in the context of this objfile. */ + dwarf2_per_objfile *per_objfile; + + /* Frame information used for the evaluation. */ + struct frame_info *frame; + + /* Compilation unit used for the evaluation. */ + struct dwarf2_per_cu_data *per_cu; + + /* Property address info used for the evaluation. */ + const struct property_addr_info *addr_info; + + /* Factory in charge of the dwarf entry's life cycle. */ + dwarf_entry_factory *entry_factory; + + /* Evaluate the expression at ADDR (LEN bytes long). */ + void eval (const gdb_byte *addr, size_t len); + + /* Return the type used for DWARF operations where the type is + unspecified in the DWARF spec. Only certain sizes are + supported. */ + struct type *address_type () const; + + /* Push ENTRY onto the stack. */ + void push (dwarf_entry *value); + + /* Return true if the expression stack is empty. */ + bool stack_empty_p () const; + + /* Pop a top element of the stack and add as a composite piece. + + If the fallowing top element of the stack is a composite + location description, the piece will be added to it. Otherwise + a new composite location description will be created and + the piece will be added to that composite. */ + dwarf_entry *add_piece (ULONGEST bit_size, ULONGEST bit_offset); + + /* The engine for the expression evaluator. Using the context in this + object, evaluate the expression between OP_PTR and OP_END. */ + void execute_stack_op (const gdb_byte *op_ptr, const gdb_byte *op_end); + + /* Pop the top item off of the stack. */ + void pop (); + + /* Retrieve the N'th item on the stack. */ + dwarf_entry *fetch (int n); + + /* Fetch the result of the expression evaluation in a form of + a struct value, where TYPE, SUBOBJ_TYPE and SUBOBJ_OFFSET + describe the source level representation of that result. + AS_LVAL defines if the fetched struct value is expected to + be a value or a location description. */ + struct value *fetch_result (struct type *type, + struct type *subobj_type, + LONGEST subobj_offset, + bool as_lval); + + /* Return the location expression for the frame base attribute, in + START and LENGTH. The result must be live until the current + expression evaluation is complete. */ + void get_frame_base (const gdb_byte **start, size_t *length); + + /* Return the base type given by the indicated DIE at DIE_CU_OFF. + This can throw an exception if the DIE is invalid or does not + represent a base type. SIZE is non-zero if this function should + verify that the resulting type has the correct size. */ + struct type *get_base_type (cu_offset die_cu_off, int size); + + /* Execute DW_AT_location expression for the DWARF expression + subroutine in the DIE at DIE_CU_OFF in the CU. Do not touch + STACK while it being passed to and returned from the called DWARF + subroutine. */ + void dwarf_call (cu_offset die_cu_off); + + /* Push on DWARF stack an entry evaluated for DW_TAG_call_site's + parameter matching KIND and KIND_U at the caller of specified + BATON. If DEREF_SIZE is not -1 then use DW_AT_call_data_value + instead of DW_AT_call_value. */ + void push_dwarf_reg_entry_value (enum call_site_parameter_kind kind, + union call_site_parameter_u kind_u, + int deref_size); + + /* Apply dereference operation on the DWARF ENTRY. In the case of a + value entry, the entry will be implicitly converted to the + appropriate location description before the operation is applied. + If the SIZE is specified, it must be equal or smaller then the + TYPE type size. If SIZE is smaller then the type size, the value + will be zero extended to the difference. */ + dwarf_entry* dwarf_entry_deref (dwarf_entry *entry, struct type *type, + size_t size = 0); + + /* Convert struct value to the matching DWARF entry representation. + Used for non-standard DW_OP_GNU_variable_value operation + support. */ + dwarf_entry *gdb_value_to_dwarf_entry (struct value *value); + + /* Convert DWARF entry to the matching struct value representation + of the given TYPE type. SUBOBJ_TYPE information if specified, will + be used for more precise description of the source variable type + information. Where SUBOBJ_OFFSET defines an offset into the DWARF + entry contents. */ + struct value *dwarf_entry_to_gdb_value (dwarf_entry *entry, + struct type *type, + struct type *subobj_type = nullptr, + LONGEST subobj_offset = 0); +}; struct type * address_type (struct gdbarch *gdbarch, int addr_size) @@ -1875,31 +2033,17 @@ dwarf_expr_context::dwarf_expr_context (dwarf2_per_objfile *per_objfile, entry_factory = new dwarf_entry_factory (); } -/* See expr.h. */ - dwarf_expr_context::~dwarf_expr_context () { delete entry_factory; } -/* See expr.h. */ - void dwarf_expr_context::push (dwarf_entry *entry) { stack.emplace_back (entry); } -/* See expr.h. */ - -void -dwarf_expr_context::push_address (CORE_ADDR addr, bool in_stack_memory) -{ - stack.emplace_back (entry_factory->create_memory (addr, 0, in_stack_memory)); -} - -/* See expr.h. */ - void dwarf_expr_context::pop () { @@ -1909,8 +2053,6 @@ dwarf_expr_context::pop () stack.pop_back (); } -/* See expr.h. */ - dwarf_entry * dwarf_expr_context::fetch (int n) { @@ -1921,8 +2063,6 @@ dwarf_expr_context::fetch (int n) return stack[stack.size () - (1 + n)]; } -/* See expr.h. */ - void dwarf_expr_context::get_frame_base (const gdb_byte **start, size_t * length) @@ -1949,8 +2089,6 @@ dwarf_expr_context::get_frame_base (const gdb_byte **start, start, length); } -/* See expr.h. */ - struct type * dwarf_expr_context::get_base_type (cu_offset die_cu_off, int size) { @@ -1968,8 +2106,6 @@ dwarf_expr_context::get_base_type (cu_offset die_cu_off, int size) return result; } -/* See expr.h. */ - void dwarf_expr_context::dwarf_call (cu_offset die_cu_off) { @@ -1993,8 +2129,6 @@ dwarf_expr_context::dwarf_call (cu_offset die_cu_off) this->eval (block.data, block.size); } -/* See expr.h. */ - void dwarf_expr_context::push_dwarf_reg_entry_value (enum call_site_parameter_kind kind, @@ -2044,8 +2178,6 @@ dwarf_expr_context::push_dwarf_reg_entry_value this->eval (data_src, size); } -/* See expr.h. */ - struct value * dwarf_expr_context::fetch_result (struct type *type, struct type *subobj_type, @@ -2068,12 +2200,11 @@ dwarf_expr_context::fetch_result (struct type *type, return dwarf_entry_to_gdb_value (entry, type, subobj_type, subobj_offset); } -/* See expr.h. */ - struct value * dwarf_expr_context::eval_exp (const gdb_byte *addr, size_t len, bool as_lval, struct dwarf2_per_cu_data *per_cu, struct frame_info *frame, + std::vector *init_values, const struct property_addr_info *addr_info, struct type *type, struct type *subobj_type, @@ -2086,12 +2217,14 @@ dwarf_expr_context::eval_exp (const gdb_byte *addr, size_t len, bool as_lval, if (per_cu != nullptr) this->ref_addr_size = per_cu->ref_addr_size (); + if (init_values != nullptr) + for (unsigned int i = 0; i < init_values->size (); i++) + push (gdb_value_to_dwarf_entry ((*init_values)[i])); + eval (addr, len); return fetch_result (type, subobj_type, subobj_offset, as_lval); } -/* See expr.h. */ - dwarf_entry * dwarf_expr_context::dwarf_entry_deref (dwarf_entry *entry, struct type *type, size_t size) @@ -2167,8 +2300,6 @@ dwarf_expr_context::dwarf_entry_deref (dwarf_entry *entry, return entry_factory->create_value (read_buf.data (), type); } -/* See expr.h. */ - dwarf_entry * dwarf_expr_context::gdb_value_to_dwarf_entry (struct value *value) { @@ -2215,8 +2346,6 @@ dwarf_expr_context::gdb_value_to_dwarf_entry (struct value *value) } } -/* See expr.h. */ - struct value * dwarf_expr_context::dwarf_entry_to_gdb_value (dwarf_entry *entry, struct type *type, @@ -2387,16 +2516,12 @@ get_signed_type (struct gdbarch *gdbarch, struct type *type) } } -/* See expr.h. */ - bool dwarf_expr_context::stack_empty_p () const { return stack.empty (); } -/* See expr.h. */ - dwarf_entry * dwarf_expr_context::add_piece (ULONGEST bit_size, ULONGEST bit_offset) { @@ -2429,8 +2554,6 @@ dwarf_expr_context::add_piece (ULONGEST bit_size, ULONGEST bit_offset) return composite_entry; } -/* See expr.h. */ - void dwarf_expr_context::eval (const gdb_byte *addr, size_t len) { @@ -2667,8 +2790,6 @@ dwarf_block_to_sp_offset (struct gdbarch *gdbarch, const gdb_byte *buf, return 1; } -/* See expr.h. */ - void dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, const gdb_byte *op_end) @@ -3584,6 +3705,25 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, gdb_assert (this->recursion_depth >= 0); } +/* See expr.h. */ + +struct value * +dwarf2_eval_exp (const gdb_byte *addr, size_t len, bool as_lval, + struct dwarf2_per_objfile *per_objfile, + struct dwarf2_per_cu_data *per_cu, + struct frame_info *frame, int addr_size, + std::vector *init_values, + const struct property_addr_info *addr_info, + struct type *type, struct type *subobj_type, + LONGEST subobj_offset) +{ + dwarf_expr_context ctx (per_objfile, addr_size); + + return ctx.eval_exp (addr, len, as_lval, per_cu, + frame, init_values, addr_info, + type, subobj_type, subobj_offset); +} + void _initialize_dwarf2expr (); void _initialize_dwarf2expr () diff --git a/gdb/dwarf2/expr.h b/gdb/dwarf2/expr.h index 19c28754bb..5fb4b0857e 100644 --- a/gdb/dwarf2/expr.h +++ b/gdb/dwarf2/expr.h @@ -25,170 +25,27 @@ #include "leb128.h" #include "gdbtypes.h" -class dwarf_entry; -class dwarf_entry_factory; struct dwarf2_per_objfile; -/* The expression evaluator works with a dwarf_expr_context, describing - its current state and its callbacks. */ -struct dwarf_expr_context -{ - /* Create a new context for the expression evaluator. - - We should ever only pass in the PER_OBJFILE and the ADDR_SIZE - information should be retrievable from there. The PER_OBJFILE - contains a pointer to the PER_BFD information anyway and the - address size information must be the same for the whole BFD. */ - dwarf_expr_context (struct dwarf2_per_objfile *per_objfile, - int addr_size); - - /* Destroy dwarf entry factory object. */ - virtual ~dwarf_expr_context (); - - /* Push ADDR onto the stack. */ - void push_address (CORE_ADDR addr, bool in_stack_memory); - - /* Evaluate the expression at ADDR (LEN bytes long) in a given PER_CU - FRAME context. AS_LVAL defines if the returned struct value is - expected to be a value or a location description. Where TYPE, - SUBOBJ_TYPE and SUBOBJ_OFFSET describe expected struct value - representation of the evaluation result. The ADDR_INFO property - can be specified to override the range of memory addresses with - the passed in buffer. */ - struct value *eval_exp (const gdb_byte *addr, size_t len, bool as_lval, - struct dwarf2_per_cu_data *per_cu, - struct frame_info *frame, - const struct property_addr_info *addr_info = nullptr, - struct type *type = nullptr, - struct type *subobj_type = nullptr, - LONGEST subobj_offset = 0); - -private: - /* The stack of values. */ - std::vector stack; - - /* Target architecture to use for address operations. */ - struct gdbarch *gdbarch; - - /* Target address size in bytes. */ - int addr_size; - - /* DW_FORM_ref_addr size in bytes. If -1 DWARF is executed - from a frame context and operations depending on DW_FORM_ref_addr - are not allowed. */ - int ref_addr_size; - - /* The current depth of dwarf expression recursion, via DW_OP_call*, - DW_OP_fbreg, DW_OP_push_object_address, etc., and the maximum - depth we'll tolerate before raising an error. */ - int recursion_depth, max_recursion_depth; - - /* We evaluate the expression in the context of this objfile. */ - dwarf2_per_objfile *per_objfile; - - /* Frame information used for the evaluation. */ - struct frame_info *frame; - - /* Compilation unit used for the evaluation. */ - struct dwarf2_per_cu_data *per_cu; - - /* Property address info used for the evaluation. */ - const struct property_addr_info *addr_info; - - /* Factory in charge of the dwarf entry's life cycle. */ - dwarf_entry_factory *entry_factory; - - /* Evaluate the expression at ADDR (LEN bytes long). */ - void eval (const gdb_byte *addr, size_t len); - - /* Return the type used for DWARF operations where the type is - unspecified in the DWARF spec. Only certain sizes are - supported. */ - struct type *address_type () const; - - /* Push ENTRY onto the stack. */ - void push (dwarf_entry *value); - - /* Return true if the expression stack is empty. */ - bool stack_empty_p () const; - - /* Pop a top element of the stack and add as a composite piece. - - If the fallowing top element of the stack is a composite - location description, the piece will be added to it. Otherwise - a new composite location description will be created and - the piece will be added to that composite. */ - dwarf_entry *add_piece (ULONGEST bit_size, ULONGEST bit_offset); - - /* The engine for the expression evaluator. Using the context in this - object, evaluate the expression between OP_PTR and OP_END. */ - void execute_stack_op (const gdb_byte *op_ptr, const gdb_byte *op_end); - - /* Pop the top item off of the stack. */ - void pop (); - - /* Retrieve the N'th item on the stack. */ - dwarf_entry *fetch (int n); - - /* Fetch the result of the expression evaluation in a form of - a struct value, where TYPE, SUBOBJ_TYPE and SUBOBJ_OFFSET - describe the source level representation of that result. - AS_LVAL defines if the fetched struct value is expected to - be a value or a location description. */ - struct value *fetch_result (struct type *type, - struct type *subobj_type, - LONGEST subobj_offset, - bool as_lval); - - /* Return the location expression for the frame base attribute, in - START and LENGTH. The result must be live until the current - expression evaluation is complete. */ - void get_frame_base (const gdb_byte **start, size_t *length); - - /* Return the base type given by the indicated DIE at DIE_CU_OFF. - This can throw an exception if the DIE is invalid or does not - represent a base type. SIZE is non-zero if this function should - verify that the resulting type has the correct size. */ - struct type *get_base_type (cu_offset die_cu_off, int size); - - /* Execute DW_AT_location expression for the DWARF expression - subroutine in the DIE at DIE_CU_OFF in the CU. Do not touch - STACK while it being passed to and returned from the called DWARF - subroutine. */ - void dwarf_call (cu_offset die_cu_off); - - /* Push on DWARF stack an entry evaluated for DW_TAG_call_site's - parameter matching KIND and KIND_U at the caller of specified - BATON. If DEREF_SIZE is not -1 then use DW_AT_call_data_value - instead of DW_AT_call_value. */ - void push_dwarf_reg_entry_value (enum call_site_parameter_kind kind, - union call_site_parameter_u kind_u, - int deref_size); - - /* Apply dereference operation on the DWARF ENTRY. In the case of a - value entry, the entry will be implicitly converted to the - appropriate location description before the operation is applied. - If the SIZE is specified, it must be equal or smaller then the - TYPE type size. If SIZE is smaller then the type size, the value - will be zero extended to the difference. */ - dwarf_entry* dwarf_entry_deref (dwarf_entry *entry, struct type *type, - size_t size = 0); - - /* Convert struct value to the matching DWARF entry representation. - Used for non-standard DW_OP_GNU_variable_value operation - support. */ - dwarf_entry *gdb_value_to_dwarf_entry (struct value *value); - - /* Convert DWARF entry to the matching struct value representation - of the given TYPE type. SUBOBJ_TYPE information if specified, will - be used for more precise description of the source variable type - information. Where SUBOBJ_OFFSET defines an offset into the DWARF - entry contents. */ - struct value *dwarf_entry_to_gdb_value (dwarf_entry *entry, - struct type *type, - struct type *subobj_type = nullptr, - LONGEST subobj_offset = 0); -}; +/* Evaluate the expression at ADDR (LEN bytes long) in a given PER_CU + FRAME context. The PER_OBJFILE contains a pointer to the PER_BFD + information. ADDR_SIZE defines a size of the DWARF generic type. + INIT_VALUES vector contains values that are expected to be pushed + on a DWARF expression stack before the evaluation. AS_LVAL defines + if the returned struct value is expected to be a value or a location + description. Where TYPE, SUBOBJ_TYPE and SUBOBJ_OFFSET describe + expected struct value representation of the evaluation result. The + ADDR_INFO property can be specified to override the range of memory + addresses with the passed in buffer. */ +struct value *dwarf2_eval_exp (const gdb_byte *addr, size_t len, bool as_lval, + struct dwarf2_per_objfile *per_objfile, + struct dwarf2_per_cu_data *per_cu, + struct frame_info *frame, int addr_size, + std::vector *init_values, + const struct property_addr_info *addr_info, + struct type *type = nullptr, + struct type *subobj_type = nullptr, + LONGEST subobj_offset = 0); /* Return the address type used of the GDBARCH architecture and ADDR_SIZE is expected size of the type. */ diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c index 4037653106..dd4eca9aac 100644 --- a/gdb/dwarf2/frame.c +++ b/gdb/dwarf2/frame.c @@ -228,11 +228,19 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size, struct frame_info *this_frame, CORE_ADDR initial, int initial_in_stack_memory, dwarf2_per_objfile *per_objfile) { - dwarf_expr_context ctx (per_objfile, addr_size); scoped_value_mark free_values; + struct type *type = address_type (per_objfile->objfile->arch (), + addr_size); - ctx.push_address (initial, initial_in_stack_memory); - struct value *result_val = ctx.eval_exp (exp, len, true, nullptr, this_frame); + struct value *init_value = value_at_lazy (type, initial); + std::vector init_values; + + set_value_stack (init_value, initial_in_stack_memory); + init_values.push_back (init_value); + + struct value *result_val + = dwarf2_eval_exp (exp, len, true, per_objfile, nullptr, + this_frame, addr_size, &init_values, nullptr); if (VALUE_LVAL (result_val) == lval_memory) return value_address (result_val); diff --git a/gdb/dwarf2/loc.c b/gdb/dwarf2/loc.c index 1a23e0b2da..d2aa1eddc9 100644 --- a/gdb/dwarf2/loc.c +++ b/gdb/dwarf2/loc.c @@ -1434,15 +1434,15 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, if (size == 0) return allocate_optimized_out_value (subobj_type); - dwarf_expr_context ctx (per_objfile, per_cu->addr_size ()); - struct value *retval; scoped_value_mark free_values; try { - retval = ctx.eval_exp (data, size, as_lval, per_cu, frame, nullptr, - type, subobj_type, subobj_byte_offset); + retval + = dwarf2_eval_exp (data, size, as_lval, per_objfile, per_cu, + frame, per_cu->addr_size (), nullptr, nullptr, + type, subobj_type, subobj_byte_offset); } catch (const gdb_exception_error &ex) { @@ -1513,23 +1513,28 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton, dwarf2_per_objfile *per_objfile = dlbaton->per_objfile; struct dwarf2_per_cu_data *per_cu = dlbaton->per_cu; - dwarf_expr_context ctx (per_objfile, per_cu->addr_size ()); struct value *result; scoped_value_mark free_values; + std::vector init_values; if (push_initial_value) { + struct type *type = address_type (per_objfile->objfile->arch (), + per_cu->addr_size ()); + if (addr_stack != nullptr) - ctx.push_address (addr_stack->addr, false); + init_values.push_back (value_at_lazy (type, addr_stack->addr)); else - ctx.push_address (0, false); + init_values.push_back (value_at_lazy (type, 0)); } try { - result = ctx.eval_exp (dlbaton->data, dlbaton->size, - true, per_cu, frame, addr_stack); + result + = dwarf2_eval_exp (dlbaton->data, dlbaton->size, true, per_objfile, + per_cu, frame, per_cu->addr_size (), &init_values, + addr_stack); } catch (const gdb_exception_error &ex) { -- 2.17.1