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 8258E39540CD for ; Mon, 7 Dec 2020 19:01:48 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 8258E39540CD ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=XC8sS+0EcKQzVpmif3Hd2rkw1/x3u2UyGe4/KLm7FiXINbHKxdJGmOFttmw19klIsnsWgjLaBQR9B85mv0oT7frgDZ/ZTZQdKU+hvwKNFHaAp67j2LbcxSDpow1ngWWnJdM6k96pkmdaWqmSI/T910s5Y2CEnBEFYQu+tGgdSskdk48h04WwGRsfq1fJUhyq2jbscPvIH4LmQ40X5R0TWCU/t3fqTVPXO+ktqJ0elcsMvNwmlzkSduylpGPxnxWZ7J5UBv/f11ZH8AwTeBwU6YElqYTB+kqq/qym6vft8XTSXZ2BKx7+sWL1Lrrb2Spl6KOrEXg2LInwP7tuUVuYXQ== 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=VB6eUN1Ke8XzTGy2aywJBux3iVhrWGmLjA+75Sqnad4=; b=SwLMy9o95fIW+E6Un3yD8FNeXJW/0jrpiOqgyFid61mL+INZ34CZCiqUGxlabpkABm2+YK7vuOXvDdd9meOE62YAF0aH36o6Ees7I4FANezvnnnaKxXGV+A+NI7GJffdccl28mGQrp9vdlEGSsuUyMhPz/uDzedKKxuDPy05Q12yG6whUA6/1fxrrUDpg1FHbixQtByC9C36kALCfoXwm05lfDEoKW0CU2zS0gBAeHpLvyvOHhBL2qzxsGpvSumX+zxB7uys7hj2Z2vW0qUyXeAHjq8GQhBSav58ouu+ufDqAf1p5upv5J5gCRTlAw4XYtT1eNqF8rGGo9xH1cD+9Q== 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:40 +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:40 +0000 From: Zoran Zaric To: gdb-patches@sourceware.org Cc: Zoran Zaric Subject: [PATCH 30/30] Add support for nested composite locations Date: Mon, 7 Dec 2020 19:00:31 +0000 Message-Id: <20201207190031.13341-31-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:39 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: 95e47ca6-5a13-4717-a7ac-08d89ae28803 X-MS-TrafficTypeDiagnostic: DM6PR12MB4561: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:5797; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: Rr9bVRJnvP9sCE7gVL0pqTYRXM3hQPRVJjO2glWq8ep3EN6Gf9pyVIJH0sNzdBxmyPnhmsScY4OyXN5GBH/SZC85xExkXsGjpOVJihPPZVxTOPKe8gLSxjAl41HHDcsPNN08P0o7KNocweym1KmaE4DynEXOK4k7dlmh09SiL1VRCZSFYPHxyCG7D3nqqUSCzz0M78CJ33avxYmLVHYpRiuO47jtoK514IcS34jMCRzRxxjWz+5iqoCuRWfLzJZzoi5k3Q7cZIo0WSxPBSv560Gum7HzbHWoYzizQxJttPlkpUzRzZg3JuhUkJZexMzqf1BZKMd64bK4u7Q3E0sQF8HOCv7yRQzNdbIkI/VB49f05HTWmQgaZK+2kcWxu9DoD5o2oX8SwTj0oaTVjKqAT/axL2ausGIszDh3KLcZy88rf6ChxFWrXaCdzH6cTeIXdDKPVfxec6Fxuf0wdoXLiTLKcq8MKyKv0y8EPGLTfsU= 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)(966005)(6486002)(16526019)(2616005)(66946007)(66476007)(66556008)(6916009)(5660300002)(186003)(8936002)(478600001)(6666004)(316002)(2004002); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData: =?us-ascii?Q?Fhcog8s9atO2YAi4weAQMlm5YchM0XQ/ECSc4eDpl7AVs9ib0MG7fYryav6Y?= =?us-ascii?Q?pPQznASUVbR8noHgi9HVMucGnxMem0/dLpKeq4QHPSs+laUuXxlhu/RcwcQ5?= =?us-ascii?Q?YmkYnugCgXP7ozPlBMvfDt5vy8ry8eya1TXNYwLp5/KjHv2ZgFawE7UsWjjZ?= =?us-ascii?Q?bGi+8dSZmiTt4zV4YkGfDi7skzFPCLGQD+Abj1cf3kvyvd/nSi7CtGpn3Nj8?= =?us-ascii?Q?GB4LP8E4rdj0+AWyI62N70CI/EqnRb8UpvCEeer88h11eyZgN652FAEqQ0bK?= =?us-ascii?Q?26AJn1377OaTI+/CfkeMmvVQBIOrjalyplyuLrlDEjK278Hu0EfVedbZ1pXI?= =?us-ascii?Q?aiLEQ+gASwgk5tJzpjDPYOhL9oy8UHtlAAuXpUGL0hdjWHKgwPkKuXR7og/S?= =?us-ascii?Q?YJpRbZGcWzWvmtX/wQ2KYNXYVptLNvaxcTlO/oTiAJBhKVWSX0Olq4W6L7Ce?= =?us-ascii?Q?G9eWRUXGsufzJlvPQOZHCv+Vhde1QjslY5Vqq6DkwnP3cbpbyyoB/ViZfFw3?= =?us-ascii?Q?cfMY+cpbuew3BF7UIfcDXSkP1WrZsGIFQJJDfiNyfuukLSraAwi0jXCTmCHF?= =?us-ascii?Q?U404Aq/kdYZbTQcyaA2fNUOQftmXEvm45Q+ES8IP5jzQO7faDpowKDgOFFtD?= =?us-ascii?Q?i3r/01xX5cJC1O5Tj+ABDhqQXOgGll1veTC2NImrQ7u2yj+vxcngQUrMuuyJ?= =?us-ascii?Q?bk55YozsKU2PzqwGzWCHPx6+PVhksAK86GqdCP13VYLtRxF0Avqmd+3eRCFU?= =?us-ascii?Q?q2KpX0F8N4iqy7T1bpN3lLn8hYsHW21U0SRJj2HqEkxgkMh6egWk+P2ZAsK/?= =?us-ascii?Q?JeyE65j/1QFpPNBQXM1ZMZd8R4e1QY7Gk+5P8uQAN/dB3PDbg7dq9IoqoVK0?= =?us-ascii?Q?V74fVTk02X6YFa6oF1TiYVuCjK6Ydtbvo1vrUcmgygaGBm8BCdUin09f0rfC?= =?us-ascii?Q?fXcE+RCtNBNn60UVfyQ9YUJmKHEZx8OBSMF6aCXs73UHsLY1aXJJRV6gVWkW?= =?us-ascii?Q?JNXK8LUauWPvzx6s+owAtOtJd4u55zl6Sbe6zfCBZrqZIbsRCyl9BFGVnqY3?= =?us-ascii?Q?Eb1nqlWS?= 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:40.7562 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-Network-Message-Id: 95e47ca6-5a13-4717-a7ac-08d89ae28803 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: k2OA2L5bWOCmsw660SUlNr2vcmRGEioG17trmWmugEeA7rQa/A5Kz40TKIp4llFELdr2zq8gzkTaaVlptb7xLw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR12MB4561 X-Spam-Status: No, score=-12.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, KAM_SHORT, 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:51 -0000 After allowing a location description to be placed on a DWARF stack, in an effort to achieve a full composability of the DWARF expression, it is necessary to enable forming of a nested composite location descriptions. To be able do this, a new operation DW_OP_LLVM_piece_end needs to be introduced, along with some additional rules on the way how the composite location description is formed using the existing DW_OP_piece and DW_OP_bit_piece operations. These new rules are fully compatible with the composite forming rules from the DWARF 5 standard. More details on the new operation and added rules can be found here: https://llvm.org/docs/AMDGPUDwarfExtensionsForHeterogeneousDebugging.html gdb/ChangeLog: * compile/compile-loc2c.c (compute_stack_depth_worker): Add new DW_OP_LLVM_piece_end operation support. * dwarf2/expr.c (class dwarf_value): Add copy constructor. (class dwarf_location): Add copy constructor. (class dwarf_undefined): Add copy constructor. (class dwarf_memory): Add copy constructor. (class dwarf_register): Add copy constructor. (class dwarf_implicit): Add copy constructor. (class dwarf_implicit_pointer): Add copy constructor. (class dwarf_composite): Add copy constructor. (read_from_location): Add composite completed check. (write_to_location): Add composite completed check. (read_value_contents_from_location): New function. (dwarf_entry_factory::copy_entry): New method. (rw_closure_value): Now calls read_value_contents_from_location function. (dwarf_expr_context::add_piece): Use new composite forming rules. (dwarf_expr_context::execute_stack_op): Add new DW_OP_LLVM_piece_end operation support. * dwarf2/loc.c (dwarf2_get_symbol_read_needs): Add new DW_OP_LLVM_piece_end operation support. include/ChangeLog: * dwarf2.def (DW_OP_DUP): Add new DW_OP_LLVM_piece_end enumeration. gdb/testsuite/ChangeLog: * gdb.dwarf2/dw2-llvm-piece-end.exp: New test. --- gdb/compile/compile-loc2c.c | 1 + gdb/dwarf2/expr.c | 305 ++++++++++++++++-- gdb/dwarf2/loc.c | 1 + .../gdb.dwarf2/dw2-llvm-piece-end.exp | 191 +++++++++++ include/dwarf2.def | 1 + 5 files changed, 469 insertions(+), 30 deletions(-) create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-llvm-piece-end.exp diff --git a/gdb/compile/compile-loc2c.c b/gdb/compile/compile-loc2c.c index e9698a758e..fd28f2cd4e 100644 --- a/gdb/compile/compile-loc2c.c +++ b/gdb/compile/compile-loc2c.c @@ -365,6 +365,7 @@ compute_stack_depth_worker (int start, int *need_tempvar, ++stack_depth; break; + case DW_OP_LLVM_piece_end: case DW_OP_LLVM_offset_constu: case DW_OP_nop: break; diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c index a65d18d492..647bf8810a 100644 --- a/gdb/dwarf2/expr.c +++ b/gdb/dwarf2/expr.c @@ -308,6 +308,17 @@ class dwarf_value : public dwarf_entry m_type = type; } + dwarf_value (const dwarf_value &value) + { + struct type *type = value.m_type; + size_t type_len = TYPE_LENGTH (type); + + m_contents.reset ((gdb_byte *) xzalloc (type_len)); + + memcpy (m_contents.get (), value.m_contents.get (), type_len); + m_type = type; + } + virtual ~dwarf_value () = default; const gdb_byte* get_contents () const @@ -352,6 +363,12 @@ class dwarf_location : public dwarf_entry m_bit_suboffset = bit_suboffset % HOST_CHAR_BIT; } + dwarf_location (const dwarf_location &location) + : m_offset (location.m_offset), + m_bit_suboffset (location.m_bit_suboffset), + m_initialised (location.m_initialised) + {} + virtual ~dwarf_location () = default; LONGEST get_offset () const @@ -404,6 +421,11 @@ class dwarf_undefined : public dwarf_location dwarf_undefined (LONGEST offset = 0, LONGEST bit_suboffset = 0) : dwarf_location (offset, bit_suboffset) {} + + dwarf_undefined (const dwarf_undefined &undefined_entry) + : dwarf_location (undefined_entry) + {} + }; class dwarf_memory : public dwarf_location @@ -415,6 +437,11 @@ class dwarf_memory : public dwarf_location m_stack (stack) {} + dwarf_memory (const dwarf_memory &memory_entry) + : dwarf_location (memory_entry), + m_stack (memory_entry.m_stack) + {} + bool in_stack () const { return m_stack; @@ -440,6 +467,11 @@ class dwarf_register : public dwarf_location m_regnum (regnum) {} + dwarf_register (const dwarf_register ®ister_entry) + : dwarf_location (register_entry), + m_regnum (register_entry.m_regnum) + {} + unsigned int get_regnum () const { return m_regnum; @@ -468,6 +500,17 @@ class dwarf_implicit : public dwarf_location m_byte_order = byte_order; } + dwarf_implicit (const dwarf_implicit &implicit_entry) + : dwarf_location (implicit_entry) + { + size_t size = implicit_entry.m_size; + m_contents.reset ((gdb_byte *) xzalloc (size)); + + memcpy (m_contents.get (), implicit_entry.m_contents.get (), size); + m_size = size; + m_byte_order = implicit_entry.m_byte_order; + } + const gdb_byte* get_contents () const { return m_contents.get (); @@ -508,6 +551,14 @@ class dwarf_implicit_pointer : public dwarf_location m_addr_size (addr_size), m_die_offset (die_offset) {} + dwarf_implicit_pointer (const dwarf_implicit_pointer &implicit_ptr_entry) + : dwarf_location (implicit_ptr_entry), + m_per_objfile (implicit_ptr_entry.m_per_objfile), + m_per_cu (implicit_ptr_entry.m_per_cu), + m_addr_size (implicit_ptr_entry.m_addr_size), + m_die_offset (implicit_ptr_entry.m_die_offset) + {} + dwarf2_per_objfile *get_per_objfile () const { return m_per_objfile; @@ -551,6 +602,22 @@ class dwarf_composite : public dwarf_location : dwarf_location (offset, bit_suboffset) {} + dwarf_composite (const dwarf_composite &composite_entry) + : dwarf_location (composite_entry) + { + /* We do a shallow copy of the pieces because they are not + expected to be modified after they are already formed. */ + for (unsigned int i = 0; i < composite_entry.m_pieces.size (); i++) + { + dwarf_location* location = composite_entry.m_pieces[i].m_location; + + location->incref (); + m_pieces.emplace_back (location, composite_entry.m_pieces[i].m_size); + } + + m_completed = composite_entry.m_completed; + } + /* A composite location gets detached from its factory object for the purpose of lval_computed resolution, which means that it needs to take care of garbage collecting its pieces. */ @@ -591,6 +658,16 @@ class dwarf_composite : public dwarf_location return m_pieces.size (); } + void set_completed (bool completed) + { + m_completed = completed; + }; + + bool is_completed () const + { + return m_completed; + }; + private: /* Composite piece that contains a piece location description and it's size. */ @@ -608,6 +685,9 @@ class dwarf_composite : public dwarf_location /* Vector of composite pieces. */ std::vector m_pieces; + + /* True if location description is completed. */ + bool m_completed = false; }; /* Read contents from the location specified by the DWARF location @@ -789,6 +869,9 @@ read_from_location (const dwarf_location *location, struct frame_info *frame, unsigned int pieces_num = composite_entry->get_pieces_num (); unsigned int i; + if (!composite_entry->is_completed ()) + ill_formed_expression (); + total_bits_to_skip += offset * HOST_CHAR_BIT + bit_suboffset; /* Skip pieces covered by the read offset. */ @@ -971,6 +1054,9 @@ write_to_location (const dwarf_location *location, struct frame_info *frame, unsigned int pieces_num = composite_entry->get_pieces_num (); unsigned int i; + if (!composite_entry->is_completed ()) + ill_formed_expression (); + total_bits_to_skip += offset * HOST_CHAR_BIT + bit_suboffset; /* Skip pieces covered by the write offset. */ @@ -1008,6 +1094,92 @@ write_to_location (const dwarf_location *location, struct frame_info *frame, internal_error (__FILE__, __LINE__, _("invalid location type")); } +/* Read value contents from the location specified by the DWARF + location description entry LOCATION. + + The read operation is performed in the context of FRAME. BIT_SIZE + is the number of bits to read. The data read is copied to the + caller-managed buffer BUF. BITS_TO_SKIP is a bit offset into the + location and BUF_BIT_OFFSET is buffer BUF's bit offset. + LOCATION_BIT_LIMIT is a maximum number of bits that location can + hold, where value zero signifies that there is no such restriction. + + Note that some location types can be read without a FRAME context. */ + +static void +read_value_contents_from_location (struct value * value, + const dwarf_location *location, + struct frame_info *frame, + LONGEST bits_to_skip, + int value_bit_offset, size_t bit_size, + size_t location_bit_limit) +{ + /* Implicit pointers are handled later. */ + if (dynamic_cast (location) != nullptr) + return; + + auto composite_entry = dynamic_cast (location); + + if (composite_entry == nullptr) + { + int optimized, unavailable; + bool big_endian = type_byte_order (value_type (value)) == BFD_ENDIAN_BIG; + + read_from_location (location, frame, bits_to_skip, + value_contents_raw (value), + value_bit_offset, bit_size, location_bit_limit, + big_endian, &optimized, &unavailable); + + if (optimized) + mark_value_bits_optimized_out (value, value_bit_offset, bit_size); + if (unavailable) + mark_value_bits_unavailable (value, value_bit_offset, bit_size); + + return; + } + + if (!composite_entry->is_completed ()) + ill_formed_expression (); + + unsigned int pieces_num = composite_entry->get_pieces_num (); + unsigned int i; + + LONGEST total_bits_to_skip = bits_to_skip + + composite_entry->get_offset () * HOST_CHAR_BIT + + composite_entry->get_bit_suboffset (); + + /* Skip pieces covered by the read offset. */ + for (i = 0; i < pieces_num; i++) + { + LONGEST piece_bit_size = composite_entry->get_bit_size_at (i); + + if (total_bits_to_skip < piece_bit_size) + break; + + total_bits_to_skip -= piece_bit_size; + } + + for (; i < pieces_num; i++) + { + LONGEST piece_bit_size = composite_entry->get_bit_size_at (i); + const dwarf_location *piece = composite_entry->get_piece_at (i); + + if (piece_bit_size > bit_size) + piece_bit_size = bit_size; + + read_value_contents_from_location (value, piece, frame, + total_bits_to_skip, + value_bit_offset, piece_bit_size, + piece_bit_size); + + if (bit_size == piece_bit_size) + break; + + value_bit_offset += piece_bit_size; + bit_size -= piece_bit_size; + } +} + /* Convert a value entry to the matching struct value representation of a given TYPE. OFFSET defines the offset into the value contents. @@ -1107,6 +1279,9 @@ class dwarf_entry_factory dwarf_composite *create_composite (LONGEST offset = 0, LONGEST bit_suboffset = 0); + /* Create a deep copy of the DWARF ENTRY. */ + dwarf_entry *copy_entry (dwarf_entry *entry); + /* Convert an entry to a location description entry. If the entry is a location description entry a dynamic cast is applied. @@ -1252,6 +1427,33 @@ dwarf_entry_factory::create_composite (LONGEST offset, LONGEST bit_suboffset) return composite_entry; } +dwarf_entry * +dwarf_entry_factory::copy_entry (dwarf_entry *entry) +{ + dwarf_entry *entry_copy; + + if (auto value = dynamic_cast (entry)) + entry_copy = new dwarf_value (*value); + else if (auto undefined = dynamic_cast (entry)) + entry_copy = new dwarf_undefined (*undefined); + else if (auto memory = dynamic_cast (entry)) + entry_copy = new dwarf_memory (*memory); + else if (auto reg = dynamic_cast (entry)) + entry_copy = new dwarf_register (*reg); + else if (auto implicit = dynamic_cast (entry)) + entry_copy = new dwarf_implicit (*implicit); + else if (auto implicit_pointer + = dynamic_cast (entry)) + entry_copy = new dwarf_implicit_pointer (*implicit_pointer); + else if (auto composite = dynamic_cast (entry)) + entry_copy = new dwarf_composite (*composite); + else + internal_error (__FILE__, __LINE__, _("invalid DWARF entry to copy.")); + + record_entry (entry_copy); + return entry_copy; +} + dwarf_location * dwarf_entry_factory::entry_to_location (dwarf_entry *entry) { @@ -1460,30 +1662,19 @@ rw_closure_value (struct value *v, struct value *from) const dwarf_location *location = composite_entry->get_piece_at (i); ULONGEST bit_size = composite_entry->get_bit_size_at (i); size_t this_bit_size = bit_size - bits_to_skip; - int optimized, unavailable; if (this_bit_size > max_bit_offset - bit_offset) this_bit_size = max_bit_offset - bit_offset; if (from == NULL) { - /* Implicit pointers are handled later. */ - if (dynamic_cast - (location) == nullptr) - { - read_from_location (location, frame, bits_to_skip, - value_contents_raw (v), bit_offset, - this_bit_size, bit_size, big_endian, - &optimized, &unavailable); - - if (optimized) - mark_value_bits_optimized_out (v, bit_offset, this_bit_size); - if (unavailable) - mark_value_bits_unavailable (v, bit_offset, this_bit_size); - } + read_value_contents_from_location (v, location, frame, bits_to_skip, + bit_offset, this_bit_size, bit_size); } else { + int optimized, unavailable; + write_to_location (location, frame, bits_to_skip, value_contents (from), bit_offset, this_bit_size, bit_size, big_endian, @@ -1892,10 +2083,34 @@ struct dwarf_expr_context /* 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. */ + The action is based on the context: + + - If the stack is empty, then an incomplete composite location + description (comprised of one undefined location description), + is pushed on the stack. + + - Otherwise, if the top stack entry is an incomplete composite + location description, then it is updated to append a new piece + comprised of one undefined location description. The + incomplete composite location description is then left on the + stack. + + - Otherwise, if the top stack entry is a location description or + can be converted to one, it is popped. Then: + + - If the top stack entry (after popping) is a location + description comprised of one incomplete composite location + description, then it is updated to append a new piece + specified by the previously popped location description. + The incomplete composite location description is then left + on the stack. + + - Otherwise, a new location description comprised of one + incomplete composite location description, with a new piece + specified by the previously popped location description, is + pushed on the stack. + + - Otherwise, the DWARF expression is ill-formed */ dwarf_entry *add_piece (ULONGEST bit_size, ULONGEST bit_offset); /* The engine for the expression evaluator. Using the context in this @@ -2534,26 +2749,39 @@ dwarf_expr_context::add_piece (ULONGEST bit_size, ULONGEST bit_offset) dwarf_location *piece_entry; dwarf_composite *composite_entry; - if (!stack_empty_p () - && dynamic_cast (fetch (0)) == nullptr) + if (stack_empty_p ()) + piece_entry = entry_factory->create_undefined (); + else { piece_entry = entry_factory->entry_to_location (fetch (0)); - pop (); + + if (auto old_composite_entry + = dynamic_cast (piece_entry)) + { + if (!old_composite_entry->is_completed ()) + piece_entry = entry_factory->create_undefined (); + } + else if (dynamic_cast (piece_entry) != nullptr) + pop (); } - else - piece_entry = entry_factory->create_undefined (); - piece_entry->add_bit_offset (bit_offset); + if (dynamic_cast (piece_entry) == nullptr) + { + piece_entry->add_bit_offset (bit_offset); + pop (); + } - /* If stack is empty then it is a start of a new composite. In the - future this will check if the composite is finished or not. */ if (stack_empty_p () || dynamic_cast (fetch (0)) == nullptr) composite_entry = entry_factory->create_composite (); else { composite_entry = dynamic_cast (fetch (0)); - pop (); + + if (composite_entry->is_completed ()) + composite_entry = entry_factory->create_composite (); + else + pop (); } composite_entry->add_piece (piece_entry, bit_size); @@ -3156,7 +3384,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, break; case DW_OP_dup: - result_entry = fetch (0); + result_entry = entry_factory->copy_entry (fetch (0)); break; case DW_OP_drop: @@ -3182,7 +3410,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, } case DW_OP_over: - result_entry = fetch (1); + result_entry = entry_factory->copy_entry (fetch (1)); break; case DW_OP_rot: @@ -3742,6 +3970,23 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, result_entry = entry_factory->create_undefined (); break; + case DW_OP_LLVM_piece_end: + { + dwarf_entry *entry = fetch (0); + + dwarf_composite *composite_entry + = dynamic_cast (entry); + + if (composite_entry == nullptr) + ill_formed_expression (); + + if (composite_entry->is_completed ()) + ill_formed_expression (); + + composite_entry->set_completed (true); + goto no_push; + } + default: error (_("Unhandled dwarf expression opcode 0x%x"), op); } diff --git a/gdb/dwarf2/loc.c b/gdb/dwarf2/loc.c index 1a903ce123..e98d6fb39d 100644 --- a/gdb/dwarf2/loc.c +++ b/gdb/dwarf2/loc.c @@ -1832,6 +1832,7 @@ dwarf2_get_symbol_read_needs (gdb::array_view expr, case DW_OP_LLVM_offset: case DW_OP_LLVM_bit_offset: case DW_OP_LLVM_undefined: + case DW_OP_LLVM_piece_end: break; case DW_OP_form_tls_address: diff --git a/gdb/testsuite/gdb.dwarf2/dw2-llvm-piece-end.exp b/gdb/testsuite/gdb.dwarf2/dw2-llvm-piece-end.exp new file mode 100644 index 0000000000..3da739ea72 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-llvm-piece-end.exp @@ -0,0 +1,191 @@ +# Copyright 2017-2020 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Test the nested composition location description by using the new +# DW_OP_LLVM_piece_end operation. +# +# The test uses three nested levels of composite location descriptions +# to define a location of an array. + +load_lib dwarf.exp + +# This test can only be run on targets which support DWARF-2 and use gas. +if {![dwarf2_support]} { + return 0 +} + +# Choose suitable integer registers for the test. + +set dwarf_regnum 0 + +if { [is_aarch64_target] } { + set regname x0 +} elseif { [is_aarch32_target] + || [istarget "s390*-*-*" ] + || [istarget "powerpc*-*-*"] + || [istarget "rs6000*-*-aix*"] } { + set regname r0 +} elseif { [is_x86_like_target] } { + set regname eax +} elseif { [is_amd64_regs_target] } { + set regname rax +} else { + verbose "Skipping ${gdb_test_file_name}." + return +} + +standard_testfile var-access.c ${gdb_test_file_name}-dw.S + +# Make some DWARF for the test. + +set asm_file [standard_output_file $srcfile2] +Dwarf::assemble $asm_file { + global dwarf_regnum regname srcdir subdir srcfile + set buf_src [gdb_target_symbol buf] + + set main_result [function_range main ${srcdir}/${subdir}/${srcfile}] + set main_start [lindex $main_result 0] + set main_length [lindex $main_result 1] + + cu {} { + DW_TAG_compile_unit { + {DW_AT_name var-access.c} + {DW_AT_comp_dir /tmp} + } { + declare_labels array_type_label int_type_label char_type_label + + # define char type + char_type_label: DW_TAG_base_type { + {DW_AT_name "char"} + {DW_AT_encoding @DW_ATE_signed} + {DW_AT_byte_size 1 DW_FORM_sdata} + } + + int_type_label: DW_TAG_base_type { + {DW_AT_name "int"} + {DW_AT_encoding @DW_ATE_signed} + {DW_AT_byte_size 4 DW_FORM_sdata} + } + + array_type_label: DW_TAG_array_type { + {DW_AT_type :$char_type_label} + } { + DW_TAG_subrange_type { + {DW_AT_type :$int_type_label} + {DW_AT_upper_bound 7 DW_FORM_udata} + } + } + + DW_TAG_subprogram { + {DW_AT_name main} + {DW_AT_low_pc $main_start addr} + {DW_AT_high_pc $main_length data8} + } { + # Array spread in different pieces, of which some are + # undefined (1st and sixth bytes) and some are either + # in buf variable or REGNAME register. + # + # Location consists of three nested composite levels: + # - Third level consists of a composite location + # descriptions which hold a single simple location + # description each. + # - Second level consist of two more composite location + # descriptions that hold two of the third level + # composite location descriptions. + # - First level holds two of the second level composite + # location descriptions. + + DW_TAG_variable { + {DW_AT_name var_array} + {DW_AT_type :$array_type_label} + {DW_AT_location { + # First level composite start + # Second level first composite start + # Third level first composite start + DW_OP_addr $buf_src + DW_OP_piece 0x2 + DW_OP_LLVM_piece_end + # Third level first composite end + + # Third level second composite start + DW_OP_LLVM_undefined + DW_OP_piece 0x1 + DW_OP_LLVM_piece_end + # Third level second composite end + + DW_OP_piece 0x1 + DW_OP_swap + DW_OP_piece 0x2 + DW_OP_LLVM_piece_end + # Second level first composite end + + # Second level second composite start + # Third level third composite start + DW_OP_regx $dwarf_regnum + DW_OP_piece 0x4 + DW_OP_LLVM_piece_end + # Third level third composite end + + # Third level fourth composite start + DW_OP_LLVM_undefined + DW_OP_piece 0x1 + DW_OP_LLVM_piece_end + # Third level fourth composite end + + DW_OP_piece 0x1 + DW_OP_swap + DW_OP_piece 0x4 + DW_OP_LLVM_piece_end + # Second level second composite end + + DW_OP_piece 0x5 + DW_OP_swap + DW_OP_piece 0x3 + DW_OP_LLVM_piece_end + # First level composite end + + } SPECIAL_expr} + } + } + } + } +} + +if { [prepare_for_testing ${testfile}.exp ${testfile} \ + [list $srcfile $asm_file] {nodebug}] } { + return -1 +} + +if ![runto_main] { + return -1 +} + +gdb_test_no_output "set var \$$regname = 0x4030201" "init reg" + +# Determine byte order. +set endian [get_endianness] +set optimized "" + +switch $endian { + little { + set val "$optimized, 0x1, 0x2, 0x3, 0x4, $optimized, 0x0, 0x1" + } + big { + set val "$optimized, 0x4, 0x3, 0x2, 0x1, $optimized, 0x0, 0x1" + } +} + +gdb_test "print/x var_array" " = \\{${val}\\}" "var_array print" + diff --git a/include/dwarf2.def b/include/dwarf2.def index b58560296d..fa6c20a9ef 100644 --- a/include/dwarf2.def +++ b/include/dwarf2.def @@ -709,6 +709,7 @@ DW_OP_DUP (DW_OP_LLVM_offset, 0xe3) DW_OP_DUP (DW_OP_LLVM_offset_constu, 0xe4) DW_OP_DUP (DW_OP_LLVM_bit_offset, 0xe5) DW_OP (DW_OP_LLVM_undefined, 0xe7) +DW_OP_DUP (DW_OP_LLVM_piece_end, 0xea) DW_END_OP DW_FIRST_ATE (DW_ATE_void, 0x0) -- 2.17.1