From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from NAM10-BN7-obe.outbound.protection.outlook.com (mail-bn7nam10on2083.outbound.protection.outlook.com [40.107.92.83]) by sourceware.org (Postfix) with ESMTPS id AC61E3858010 for ; Fri, 5 Nov 2021 11:39:26 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org AC61E3858010 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=lPvgzH5O1E8oiMpSremaj5/wj4bdbHxlrHegdVgSlzJZQxtjzJuxsmYwrGa1QcznAGov24XOXIxcxu9MIz8Os+pjBJtYbTut1VZbcs5iKPwh+ww0JM0A/kAE9ul1yU13t99PaHbxSecqKRKxwbyV75vTk5Of76xu3K8ei0fzzL95eHp5OJfE5lAv0DL+MyCi60hPz+N92Nmw1KE+jpCZP06lXgsoy/DTGL9AZl1t11urFZ+UTFCwCghf3hgBMROD0VmF5DkY+PHp2D9iQxhZ6H1KrRHvZjynFLtfGfD5D1pWSacAsvNp8voTkKDZaUQ0G5bI+Q/SCMc8PpxtTINWVw== 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-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=CmKTKwVG2C7uSltsE2NptKKj1c0LZ184Bo71W39uvA4=; b=ZjnKV5S/m5El8rTnFGPdE5xkxl4d+JUemi2Oclk+6T4rf5UgMBcHE4G1Uuhi6bj/SgBtTXYaY2j33tmSbvbiM2JRwtTdkIGcdrOkDZ74sg6UNAHJ5QrsDoVy1rGUSsQCcqe+WVL2Mc9WsghIjt9lJL7Ss2tr6mierHHApGViwhmHBbtB2d+wNmIm00H+8U3XTHpexqHL7b5oGQuHPUJqDd0Nx7/j+H0GVB4AX9zDtJS6i7ua3fVnjXv+UmdESIwYP2EvEXvyWCltCSxCA8vt6O9/zCTYqHEUmcD8d3qqA6NgEClp05mapK8JHKlEB7S5PoNv5wrGidDsBvgGGSBucQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=sourceware.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none Received: from MW4PR04CA0170.namprd04.prod.outlook.com (2603:10b6:303:85::25) by BL0PR12MB2819.namprd12.prod.outlook.com (2603:10b6:208:8a::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4669.10; Fri, 5 Nov 2021 11:39:22 +0000 Received: from CO1NAM11FT047.eop-nam11.prod.protection.outlook.com (2603:10b6:303:85:cafe::69) by MW4PR04CA0170.outlook.office365.com (2603:10b6:303:85::25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4669.11 via Frontend Transport; Fri, 5 Nov 2021 11:39:21 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; sourceware.org; dkim=none (message not signed) header.d=none;sourceware.org; dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; Received: from SATLEXMB04.amd.com (165.204.84.17) by CO1NAM11FT047.mail.protection.outlook.com (10.13.174.132) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.4669.10 via Frontend Transport; Fri, 5 Nov 2021 11:39:21 +0000 Received: from localhost.localdomain (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.15; Fri, 5 Nov 2021 06:39:18 -0500 From: Zoran Zaric To: Subject: [PATCH v4 14/28] Add new computed struct value callback interface Date: Fri, 5 Nov 2021 11:38:35 +0000 Message-ID: <20211105113849.118800-15-zoran.zaric@amd.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20211105113849.118800-1-zoran.zaric@amd.com> References: <20211105113849.118800-1-zoran.zaric@amd.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-Originating-IP: [10.180.168.240] X-ClientProxiedBy: SATLEXMB04.amd.com (10.181.40.145) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 049a618c-b4bd-4703-8309-08d9a050e8e8 X-MS-TrafficTypeDiagnostic: BL0PR12MB2819: X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:9508; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: RpYnNEK9lh5g/tnbhD78reEg0/mB9iGECa7Kr9/Sz1B41QZhgDKLGgVogflWIoVbjeEyC2SigkFrhNvANE4oMeo++dceUhpBf732xLXJdamLtUTTmGjIbpuPZ1vyDq8XwoWlA03ipKoZlzPF/CiFIlm3p675q/B3fKqT+jrUbzi+4C9R3BcUz6FJJDvPJcQCixFkltPvcWQ1NCuSY1gRO2EYocIRXbFVcyMRW2e5uKcQjHpHPfnFPjf1m/IbU4KmxS5o5Pj4NHdmDAumnTOpMRy5FKzKEiEeJl1pEtVRP0rm7vKuwPll3U56gfGDuMkgBWkTFNnVvtY8LnSbihDp3eeJretLUbJ/3EjOAoWzJ2FyS63uG0Urqt5rXwPhcoP5vBe2sst/QDZWDkTd8yK/M8sz0qLtjBDRbum4vnlgCzE8vMRB0GDHxzrJN50rTa8AH1JZYxA2z3OEuvW4fqJbFtBKrSLLYT57JLgjfWLqCG4wuMK14ld+9nObfNzl+5lb1QagqoVBtdJF18FONt7Cs0V3xMiTXHOMrOytYuNHSdkMRvf2cPrgLBbBBk6y7voRL3DPEV1/jTBH9ZewWWTIWSEXHMb4C5RuOTzdikxbUbdMWckHhbd/9t+KzvVAJsDwEgHOZ1i26kO64IVnbg6dXVJY1/xJ6BwBt/4pjR6lVKQJHjAws9vE0BaHqGTrQLApuDviXCvKKSJN2ZufmvWbDTx7/FMfuJ5dQnEDczExA64= X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(4636009)(46966006)(36840700001)(86362001)(36860700001)(83380400001)(426003)(508600001)(316002)(70206006)(70586007)(1076003)(30864003)(2616005)(81166007)(44832011)(336012)(2906002)(47076005)(82310400003)(5660300002)(8676002)(26005)(36756003)(8936002)(356005)(4326008)(6916009)(6666004)(16526019)(186003)(36900700001); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Nov 2021 11:39:21.3326 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 049a618c-b4bd-4703-8309-08d9a050e8e8 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CO1NAM11FT047.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BL0PR12MB2819 X-Spam-Status: No, score=-12.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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: Fri, 05 Nov 2021 11:39:29 -0000 From: Zoran Zaric At this point all support is there to add a new callback interface for the computed struct value infrastructure. Original callback interface (piece closure) is going to be removed as soon as the switch to the new DWARF entry classes is done in the next few patches. gdb/ChangeLog: * dwarf2/expr.c (class computed_closure): New class. (closure_value_funcs): New closure callback structure. (copy_value_closure): New function. (free_value_closure): New function. (rw_closure_value): New function. (check_synthetic_pointer): New function. (write_closure_value): New function. (read_closure_value): New function. (is_optimized_out_closure_value): New function. (indirect_closure_value): New function. (coerce_closure_ref): New function. --- gdb/dwarf2/expr.c | 324 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 324 insertions(+) diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c index a16c53377b7..d76dddab643 100644 --- a/gdb/dwarf2/expr.c +++ b/gdb/dwarf2/expr.c @@ -312,6 +312,96 @@ address_type (gdbarch *arch, int addr_size) class dwarf_location; class dwarf_value; +/* Closure callback functions. */ + +static void * +copy_value_closure (const value *v); + +static void +free_value_closure (value *v); + +static void +rw_closure_value (value *v, value *from); + +static int +check_synthetic_pointer (const value *value, LONGEST bit_offset, + int bit_length); + +static void +write_closure_value (value *to, value *from); + +static void +read_closure_value (value *v); + +static bool +is_optimized_out_closure_value (value *v); + +static value * +indirect_closure_value (value *value); + +static value * +coerce_closure_ref (const value *value); + +/* Functions for accessing a variable described by DW_OP_piece, + DW_OP_bit_piece or DW_OP_implicit_pointer. */ + +static const lval_funcs closure_value_funcs = { + read_closure_value, + write_closure_value, + is_optimized_out_closure_value, + indirect_closure_value, + coerce_closure_ref, + check_synthetic_pointer, + copy_value_closure, + free_value_closure +}; + +/* Closure class that encapsulates a DWARF location description and a + frame information used when that location description was created. + Used for lval_computed value abstraction. */ + +class computed_closure : public refcounted_object +{ +public: + computed_closure (std::unique_ptr location, + struct frame_id frame_id) + : m_location (std::move (location)), m_frame_id (frame_id) + {} + + computed_closure (std::unique_ptr location, + struct frame_info *frame) + : m_location (std::move (location)), m_frame (frame) + {} + + const dwarf_location &get_location () const + { + return *m_location; + } + + frame_id get_frame_id () const + { + gdb_assert (m_frame == nullptr); + return m_frame_id; + } + + frame_info *get_frame () const + { + return m_frame; + } + +private: + /* Entry that this class encloses. */ + const std::unique_ptr m_location; + + /* Frame ID context of the closure. */ + frame_id m_frame_id; + + /* In the case of frame expression evaluator the frame_id + is not safe to use because the frame itself is being built. + Only in these cases we set and use frame info directly. */ + frame_info *m_frame = nullptr; +}; + /* Base class that describes entries found on a DWARF expression evaluation stack. */ @@ -1592,6 +1682,240 @@ dwarf_composite::is_optimized_out (frame_info *frame, bool big_endian, return false; } +static void * +copy_value_closure (const value *v) +{ + computed_closure *closure = ((computed_closure*) value_computed_closure (v)); + + if (closure == nullptr) + internal_error (__FILE__, __LINE__, _("invalid closure type")); + + closure->incref (); + return closure; +} + +static void +free_value_closure (value *v) +{ + computed_closure *closure = ((computed_closure*) value_computed_closure (v)); + + if (closure == nullptr) + internal_error (__FILE__, __LINE__, _("invalid closure type")); + + closure->decref (); + + if (closure->refcount () == 0) + delete closure; +} + +/* Read or write a closure value V. If FROM != NULL, operate in "write + mode": copy FROM into the closure comprising V. If FROM == NULL, + operate in "read mode": fetch the contents of the (lazy) value V by + composing it from its closure. */ + +static void +rw_closure_value (value *v, value *from) +{ + LONGEST bit_offset = 0, max_bit_size; + computed_closure *closure = (computed_closure*) value_computed_closure (v); + struct type *v_type = value_type (v); + bool big_endian = type_byte_order (v_type) == BFD_ENDIAN_BIG; + const dwarf_location &location = closure->get_location (); + /* DWARF evaluator only supports targets with byte size of 8 bits, + while struct value offset is expressed in memory unit size. */ + int unit_size = gdbarch_addressable_memory_unit_size (v_type->arch ()); + + if (from == nullptr) + { + if (v_type != value_enclosing_type (v)) + internal_error (__FILE__, __LINE__, + _("Should not be able to create a lazy value with " + "an enclosing type")); + } + + ULONGEST bits_to_skip = HOST_CHAR_BIT * unit_size * value_offset (v); + + /* If there are bits that don't complete a byte, count them in. */ + if (value_bitsize (v)) + { + bits_to_skip + += HOST_CHAR_BIT * unit_size * value_offset (value_parent (v)) + + value_bitpos (v); + if (from != nullptr && big_endian) + { + /* Use the least significant bits of FROM. */ + max_bit_size = HOST_CHAR_BIT * TYPE_LENGTH (value_type (from)); + bit_offset = max_bit_size - value_bitsize (v); + } + else + max_bit_size = value_bitsize (v); + } + else + max_bit_size = HOST_CHAR_BIT * TYPE_LENGTH (v_type); + + frame_info *frame = closure->get_frame (); + + if (frame == nullptr) + frame = frame_find_by_id (closure->get_frame_id ()); + + if (from == nullptr) + { + location.write_to_gdb_value (frame, v, bit_offset, bits_to_skip, + max_bit_size - bit_offset, 0); + } + else + { + location.read_from_gdb_value (frame, from, bit_offset, bits_to_skip, + max_bit_size - bit_offset, 0); + } +} + +static void +read_closure_value (value *v) +{ + rw_closure_value (v, NULL); +} + +static void +write_closure_value (value *to, value *from) +{ + rw_closure_value (to, from); +} + +/* Check if a closure value V describes any piece of the + underlying location description as optimized out. */ + +static bool +is_optimized_out_closure_value (value *v) +{ + LONGEST max_bit_size; + computed_closure *closure = (computed_closure*) value_computed_closure (v); + struct type *v_type = value_type (v); + bool big_endian = type_byte_order (v_type) == BFD_ENDIAN_BIG; + const dwarf_location &location = closure->get_location (); + /* DWARF evaluator only supports targets with byte size of 8 bits, + while struct value offset is expressed in memory unit size. */ + int unit_size = gdbarch_addressable_memory_unit_size (v_type->arch ()); + + if (v_type != value_enclosing_type (v)) + internal_error (__FILE__, __LINE__, + _("Should not be able to create a lazy value with " + "an enclosing type")); + + ULONGEST bits_to_skip = HOST_CHAR_BIT * unit_size * value_offset (v); + + /* If there are bits that don't complete a byte, count them in. */ + if (value_bitsize (v)) + { + bits_to_skip + += HOST_CHAR_BIT * unit_size * value_offset (value_parent (v)) + + value_bitpos (v); + max_bit_size = value_bitsize (v); + } + else + max_bit_size = HOST_CHAR_BIT * TYPE_LENGTH (v_type); + + frame_info *frame = closure->get_frame (); + + if (frame == nullptr) + frame = frame_find_by_id (closure->get_frame_id ()); + + return location.is_optimized_out (frame, big_endian, bits_to_skip, + max_bit_size, 0); +} + +/* An implementation of an lval_funcs method to see whether a value is + a synthetic pointer. */ + +static int +check_synthetic_pointer (const value *value, LONGEST bit_offset, + int bit_length) +{ + /* DWARF evaluator only supports targets with byte size of 8 bits, + while struct value offset is expressed in memory unit size. */ + int unit_size + = gdbarch_addressable_memory_unit_size (value_type (value)->arch ()); + LONGEST total_bit_offset + = HOST_CHAR_BIT * unit_size * value_offset (value) + bit_offset; + + if (value_bitsize (value)) + total_bit_offset += value_bitpos (value); + + computed_closure *closure + = (computed_closure *) value_computed_closure (value); + + return closure->get_location ().is_implicit_ptr_at (total_bit_offset, + bit_length); +} + +/* An implementation of an lval_funcs method to indirect through a + pointer. This handles the synthetic pointer case when needed. */ + +static value * +indirect_closure_value (value *value) +{ + computed_closure *closure + = (computed_closure *) value_computed_closure (value); + + struct type *type = check_typedef (value_type (value)); + if (type->code () != TYPE_CODE_PTR) + return nullptr; + + /* DWARF evaluator only supports targets with byte size of 8 bits, + while struct value offset is expressed in memory unit size. */ + int unit_size = gdbarch_addressable_memory_unit_size (type->arch ()); + LONGEST bit_length = HOST_CHAR_BIT * TYPE_LENGTH (type); + LONGEST bit_offset = HOST_CHAR_BIT * unit_size * value_offset (value); + + if (value_bitsize (value)) + bit_offset += value_bitpos (value); + + frame_info *frame = get_selected_frame (_("No frame selected.")); + + /* This is an offset requested by GDB, such as value subscripts. + However, due to how synthetic pointers are implemented, this is + always presented to us as a pointer type. This means we have to + sign-extend it manually as appropriate. Use raw + extract_signed_integer directly rather than value_as_address and + sign extend afterwards on architectures that would need it + (mostly everywhere except MIPS, which has signed addresses) as + the later would go through gdbarch_pointer_to_address and thus + return a CORE_ADDR with high bits set on architectures that + encode address spaces and other things in CORE_ADDR. */ + bfd_endian byte_order = gdbarch_byte_order (get_frame_arch (frame)); + LONGEST pointer_offset + = extract_signed_integer (value_contents (value).data (), + TYPE_LENGTH (type), byte_order); + + return closure->get_location ().indirect_implicit_ptr (frame, type, + pointer_offset, + bit_offset, bit_length); +} + +/* Implementation of the coerce_ref method of lval_funcs for synthetic C++ + references. */ + +static value * +coerce_closure_ref (const value *value) +{ + struct type *type = check_typedef (value_type (value)); + + if (value_bits_synthetic_pointer (value, value_embedded_offset (value), + HOST_CHAR_BIT * TYPE_LENGTH (type))) + { + computed_closure *closure + = (computed_closure *) value_computed_closure (value); + frame_info *frame = get_selected_frame (_("No frame selected.")); + + return closure->get_location ().indirect_implicit_ptr (frame, type); + } + else + { + /* Else: not a synthetic reference; do nothing. */ + return nullptr; + } +} + struct piece_closure { /* Reference count. */ -- 2.17.1