From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id kO1SNK7+PGAGJAAAWB0awg (envelope-from ) for ; Mon, 01 Mar 2021 09:48:14 -0500 Received: by simark.ca (Postfix, from userid 112) id 5AD721EFC1; Mon, 1 Mar 2021 09:48:12 -0500 (EST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on simark.ca X-Spam-Level: X-Spam-Status: No, score=0.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,MAILING_LIST_MULTI,MSGID_FROM_MTA_HEADER,RDNS_NONE, URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.2 Received: from sourceware.org (unknown [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 345E71E590 for ; Mon, 1 Mar 2021 09:48:07 -0500 (EST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B11143939C2F; Mon, 1 Mar 2021 14:48:06 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B11143939C2F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1614610086; bh=+umT0XHTLWadidZ3gqnU/Z9j4bCFoQI1osRNeWKEjBY=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=KAnZzVChFCjCaecQfxBFkRJvMahqBjDZ9KH7T8vH3u89KNWGnmYC8L8yieQD9endH vrpoI3gg+DZ7VGJSG7MhBG1EzJypIJve8tIi2tlM66CbnyWyF5AEzWNnf05H3yLpVO H6ilkrs60t9V5CG8ZQB+s9lt6NOicwL3EYHSDsfk= Received: from NAM12-BN8-obe.outbound.protection.outlook.com (mail-bn8nam12on2060.outbound.protection.outlook.com [40.107.237.60]) by sourceware.org (Postfix) with ESMTPS id A47DC393C864 for ; Mon, 1 Mar 2021 14:48:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org A47DC393C864 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=RRlp4ya1sq215UWpO324veKU9DwsyU/NuVNgw6zWQ1ExqYuCfaLiKjBkSNtc5g9MO4vpI9FaiM9e1F0Zkn0GJJnn5RsfNHbRkgY+Eobxyap/F3mDuiVTEjVuz3+YfsYg+zhOQ/+JCOlSuMraa609Ke6htE8NZ9Mn5DSc9diUY67hD+NJ2j2/l9OVlBYjYFBogYZ5/L2ND7yZb/gUssZLyEJhMooCclDA390Z+giDwzHaybNd4GC2arL2WhFSvWzOQaG3DBnr4Kdh/Ykk/vdYy4c16lk5l11htrG5/C8V6oKgvoL5FLrnBQ3625ukBHMYkbQXEsWxmCkbNHDYPBPEQw== 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=+umT0XHTLWadidZ3gqnU/Z9j4bCFoQI1osRNeWKEjBY=; b=j85UJnyC9Spi6Vd7j5AHx96NZlv3eXQgPgWeUXUn8+vPguALYcCmTix44SznuWz7XWhESk9nQqBBf1qE3AKar3d6HNsoupcx9NtZqb6q9S+xhI4YJL8qOzXxbVE4dcSkCid2jIHlVunBF2G6JPFe8ZioZSLBvb+vKfwl032/Yt3ilmorgmQI5kQ8BOQ/TZDKqolTCMzC4P+KD0FXuPLON7ooS6AWiM4pVCNKJsZhjgig6EDXzyR2mCgGdwZCaEnqLlA0F+gZct0R1tjRyBPK7iWxPt5Cz16A1bhKEteTDoOvqmhASLng0om5K2dE5YPwJgqysqWGIcEnvnijlT4wWQ== 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 DM5PR12MB2342.namprd12.prod.outlook.com (2603:10b6:4:ba::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3890.28; Mon, 1 Mar 2021 14:47:51 +0000 Received: from DM6PR12MB2762.namprd12.prod.outlook.com ([fe80::31d8:f503:f7b2:f44]) by DM6PR12MB2762.namprd12.prod.outlook.com ([fe80::31d8:f503:f7b2:f44%3]) with mapi id 15.20.3868.033; Mon, 1 Mar 2021 14:47:51 +0000 To: gdb-patches@sourceware.org Subject: [PATCH 43/43] Add support for nested composite locations Date: Mon, 1 Mar 2021 14:46:20 +0000 Message-Id: <20210301144620.103016-44-Zoran.Zaric@amd.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210301144620.103016-1-Zoran.Zaric@amd.com> References: <20210301144620.103016-1-Zoran.Zaric@amd.com> Content-Type: text/plain X-Originating-IP: [2a00:23c7:5a85:6801:b4ed:fe7b:8064:d4d] X-ClientProxiedBy: AM0PR04CA0073.eurprd04.prod.outlook.com (2603:10a6:208:be::14) 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:b4ed:fe7b:8064:d4d) by AM0PR04CA0073.eurprd04.prod.outlook.com (2603:10a6:208:be::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3890.19 via Frontend Transport; Mon, 1 Mar 2021 14:47:30 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: 6675a988-8102-4132-d395-08d8dcc0f15e X-MS-TrafficTypeDiagnostic: DM5PR12MB2342: X-MS-Exchange-MinimumUrlDomainAge: llvm.org#6197 X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:8273; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: q9SW8BKrnPCQYeuo5wOLvRQZmyB0Uen5M2aJznu5ImeFdlKD5XuAMVPggzwSPDPjJUDkJ8z09n4Jr8mwcTdzsbQbpozE2gJiRDcOrWzAGgtvSDIVeqYLuMdj+6htWh0PIwQLP7xIKmb7XPgTuUv4yJmZm/TUC4KDJ7NUfcNKm8MNOnqamq3Ov3GjvwpKLXVv1tgjUxyrfweBQCniP3UqZK1jEsukkVYC8MaYjgnSodk0rD20lVQoCJKQ2UHOmLGWcH8Zg8OaMskjzJosMrreh9k9WhIZbdUER0LNZL3cDAnGjQt/P+9qrkT0SxY2z2a4dz7+HCkJW7ofcQQmEhUo9C9ZQAPyTtOT2r77jBhjwxmoAXP4Z/M34+bjOPmVr9jZqVD9mCVrcM5Xjzaz3sHuELvbqmPeWopYjOe0ZAKuzQcOTzwTbQYi6a5AoscAcmQFPXQCh16wpgQMzYD/4UuY5tG7kusKShrPaHfMNCLaANFozUttbN8fh+SmFUhC1BsynUZg5PVoVzKzqZVR/xU06fZvqPlTEy7AGuW/B/b1/FYc+TbPrWYQSqMVEKmjv38NmqQ10le/3S4ZpfIY57RHsmEKRrGAsaV/2YSfp4xKqLnkTJ/l0gDOdGhq367Sp8L/NzlyQd83QQN4wzBGje5c69yTu1tWmJZqLmgpqo45sIs= 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)(366004)(346002)(396003)(376002)(39860400002)(136003)(6486002)(66476007)(966005)(4326008)(478600001)(66556008)(2906002)(66946007)(69590400012)(316002)(52116002)(6666004)(6916009)(2616005)(86362001)(16526019)(6512007)(36756003)(8676002)(8936002)(6506007)(30864003)(5660300002)(186003)(1076003)(83380400001)(2004002); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData: =?us-ascii?Q?7fPbRKMMA9ZFBJ7gwHLmKu2hpzK3qZ+9eYEzYz/KfDZqg5rCd1V0D+BdCUfg?= =?us-ascii?Q?feZn3Q8rn8LoH3s0z4hN8udozUldrK8IS1bmWaEMnZ+Y1xOVvKWlrMEzp2WH?= =?us-ascii?Q?uG2zdGYyhn0S0Qd64TUp0Vk8qIlkEMxJH6ruWTzTsZ8w1QHqfK7k/6WvCzbi?= =?us-ascii?Q?SDK3tJfiy1X11crJk/F58h9l0oBg9LI/2760IrAjTxbadS5bF35zAYbnw0Vp?= =?us-ascii?Q?lqu0mXbWq0voEPr4lYCLfXQTJqp7fiJleNfQvLW0g4gAab9FzNiZ/MMFROnj?= =?us-ascii?Q?VasNW+QFR24VzTUyN/Yp00muyG5E70ktcaBspbb5X7ii1CRBYHemABKtud8M?= =?us-ascii?Q?yxVLu81Tjmxiv64WAdkUmcVuH5syflTLVFOW93MCbCYJw2RIjayq66QZHu+S?= =?us-ascii?Q?93s0SlueegvzIc134io304D6IoiePia7qO0kGRKyuwEVpKG7qI5v5EM125Ng?= =?us-ascii?Q?hZI1cryn4c3aPNhE+CvKrItJsbUQInjL9DQ1ZbraGAqSvUgjPETycrQ4G2cA?= =?us-ascii?Q?5/vxY4e334TeQWm/U5muh+HV0v8lBpJVFZdN4b2N117vYlCP5NGKcbYfnyR4?= =?us-ascii?Q?go+x7Na0WsqFr9exzt55tgGH7LPeT2GzSg38tZLyOlt23WmXU1y47+wr7eCb?= =?us-ascii?Q?xlZu9jT8L02OUz8QyqddjTb/kwFXnhvUQ5ZrL2UsM7RVt/blrchnUpByUra+?= =?us-ascii?Q?/zk/r0JBBkJ5jSgJV2Tq8mFFS5IWxKCYBPHs+6Zojs3MWbdnUj36bAJ78m4x?= =?us-ascii?Q?KSHf8RPm921l3yKGqV65F9RntH3JjzR0hI7YUA7OC6mku5BA6sjsJAXGWr8E?= =?us-ascii?Q?ogFvDQ2p5O4WydSDjNFMShYDd72m8GJ9yrYMOtdGIfuzZc7J5gf9H5QAjPv3?= =?us-ascii?Q?bG0TOM9PupYx1PnYenxvw6a+f+/Ey5zpELbgBBIOSeautoFXUwe46HWnuhMs?= =?us-ascii?Q?0qLFhvqdszhFBkoCRbcKHw3dKnF8S4NUyI7w+uJPELmrGFakMgm1GZjdC6gp?= =?us-ascii?Q?/4A8PnLik/9X/lC5DA9C5fZYa4nFkGg/mMiWy7Kkk5Xr1JPqbtf+5n6kI6J/?= =?us-ascii?Q?LkMsAWWCy0Zi7NsGo207klG9/l8BisE+JhJieGx+naLYIuj2MlIHOqNgQsQN?= =?us-ascii?Q?R4RuZtuh1iXC2j+vXbyXwqOuQD6TutEVajiZYUpgnnet2MS9lB6iYZWkOS1y?= =?us-ascii?Q?QfjJXPpbs4XRrM85GPnjVdRW9lWtBebgNBzN2KdEgKrOjZsnLg922rKu0Q87?= =?us-ascii?Q?bqcu1Bv0pjTZnWFiiO2ID+vsaadZ2KPolV66tT7+YDzDu21rXDtTiOdx7uXE?= =?us-ascii?Q?yA2d2fYAvLrrHnuII6L4gygD4SsvTh90ROKKRrJls4Zppi1LKL5LHzQUjgw5?= =?us-ascii?Q?YKju5JY1KUGnjtYKt5gb6cIiZ7G6?= X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-Network-Message-Id: 6675a988-8102-4132-d395-08d8dcc0f15e X-MS-Exchange-CrossTenant-AuthSource: DM6PR12MB2762.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 01 Mar 2021 14:47:31.6429 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: wh0Yo0oKnveyeaXAPhrA2MGd20+CqZljgs5dcXdBl7F7m9OOhSowVlFn7qK8OBnIVZxdBgIFN12UINz1/5LMew== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR12MB2342 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: , From: Zoran Zaric via Gdb-patches Reply-To: Zoran Zaric Errors-To: gdb-patches-bounces@sourceware.org Sender: "Gdb-patches" 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 The dwarf_composite also needed to be modified to make a distinction between completed composite locationd description and not completed one. This also mean that some DWARF expression operations can duplicate a composite location description that is not completed and end up with more then one different composite location description on the stack. To be able to do this, classes that derive from a DWARF entry class need to have a clone method. gdb/ChangeLog: * compile/compile-loc2c.c (compute_stack_depth_worker): Add new DW_OP_LLVM_piece_end operation support. * dwarf2/expr.c (dwarf_composite::m_completed): New data member. (dwarf_entry::dwarf_entry): New copy constructor. (dwarf_location::dwarf_location): New copy constructor. (dwarf_value::dwarf_value): New copy constructor. (dwarf_undefined::dwarf_undefined): New copy constructor. (dwarf_memory::dwarf_memory): New copy constructor. (dwarf_register::dwarf_register): New copy constructor. (dwarf_implicit::dwarf_implicit): New method. (dwarf_implicit_pointer::dwarf_implicit_pointer): New copy constructor. (dwarf_composite::dwarf_composite): New copy constructor. (dwarf_entry::clone): New method. (dwarf_location::clone): New method. (dwarf_value::clone): New method. (dwarf_undefined::clone): New method. (dwarf_memory::clone): New method. (dwarf_register::clone): New method. (dwarf_implicit::clone): New method. (dwarf_implicit_pointer::clone): New method. (dwarf_composite::clone): New method. (dwarf_composite::is_completed): New method. (dwarf_composite::set_completed): New method. (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. 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 | 206 ++++++++++++++++-- .../gdb.dwarf2/dw2-llvm-piece-end.exp | 192 ++++++++++++++++ include/dwarf2.def | 1 + 4 files changed, 384 insertions(+), 16 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 057d68823f9..86a8fb9e354 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 ec7837e1935..8b80d1fd09f 100644 --- a/gdb/dwarf2/expr.c +++ b/gdb/dwarf2/expr.c @@ -402,6 +402,9 @@ class dwarf_entry : public std::enable_shared_from_this virtual ~dwarf_entry () = 0; + /* Clones entry. */ + virtual std::shared_ptr clone () const = 0; + /* Convert DWARF entry into a DWARF location description. ARCH defines an architecture of the location described. */ virtual std::shared_ptr to_location @@ -446,6 +449,13 @@ class dwarf_location : public dwarf_entry m_bit_suboffset = bit_suboffset % HOST_CHAR_BIT; } + dwarf_location (const dwarf_location &location) + : m_arch (location.m_arch), + m_offset (location.m_offset), + m_bit_suboffset (location.m_bit_suboffset), + m_initialised (location.m_initialised) + {} + virtual ~dwarf_location () = default; /* Add bit offset to the location description. */ @@ -725,6 +735,22 @@ 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; + } + + std::shared_ptr clone () const override + { + return std::make_shared (*this); + } + const gdb_byte* get_contents () const { return m_contents.get (); @@ -822,6 +848,15 @@ class dwarf_undefined : public dwarf_location : dwarf_location (arch, offset, bit_suboffset) {} + dwarf_undefined (const dwarf_undefined &undefined) + : dwarf_location (undefined) + {} + + std::shared_ptr clone () const override + { + return std::make_shared (*this); + } + void read (struct frame_info *frame, gdb_byte *buf, int buf_bit_offset, size_t bit_size, LONGEST bits_to_skip, size_t location_bit_limit, bool big_endian, int *optimized, int *unavailable) const override @@ -863,6 +898,16 @@ class dwarf_memory : public dwarf_location m_stack (stack) {} + dwarf_memory (const dwarf_memory &memory) + : dwarf_location (memory), + m_stack (memory.m_stack) + {} + + std::shared_ptr clone () const override + { + return std::make_shared (*this); + } + void set_stack (bool stack) { m_stack = stack; @@ -1094,6 +1139,16 @@ class dwarf_register : public dwarf_location m_regnum (regnum) {} + dwarf_register (const dwarf_register ®istr) + : dwarf_location (registr), + m_regnum (registr.m_regnum) + {} + + std::shared_ptr clone () const override + { + return std::make_shared (*this); + } + void read (struct frame_info *frame, gdb_byte *buf, int buf_bit_offset, size_t bit_size, LONGEST bits_to_skip, size_t location_bit_limit, bool big_endian, int *optimized, int *unavailable) const override; @@ -1263,6 +1318,22 @@ class dwarf_implicit : public dwarf_location m_byte_order = byte_order; } + dwarf_implicit (const dwarf_implicit &implicit) + : dwarf_location (implicit) + { + size_t size = implicit.m_size; + m_contents.reset ((gdb_byte *) xzalloc (size)); + + memcpy (m_contents.get (), implicit.m_contents.get (), size); + m_size = size; + m_byte_order = implicit.m_byte_order; + } + + std::shared_ptr clone () const override + { + return std::make_shared (*this); + } + void read (struct frame_info *frame, gdb_byte *buf, int buf_bit_offset, size_t bit_size, LONGEST bits_to_skip, size_t location_bit_limit, bool big_endian, int *optimized, int *unavailable) const override; @@ -1375,6 +1446,19 @@ 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) + : dwarf_location (implicit_ptr), + m_per_objfile (implicit_ptr.m_per_objfile), + m_per_cu (implicit_ptr.m_per_cu), + m_addr_size (implicit_ptr.m_addr_size), + m_die_offset (implicit_ptr.m_die_offset) + {} + + std::shared_ptr clone () const override + { + return std::make_shared (*this); + } + void read (struct frame_info *frame, gdb_byte *buf, int buf_bit_offset, size_t bit_size, LONGEST bits_to_skip, size_t location_bit_limit, bool big_endian, int *optimized, int *unavailable) const override; @@ -1518,12 +1602,39 @@ class dwarf_composite : public dwarf_location : dwarf_location (arch, offset, bit_suboffset), m_per_cu (per_cu) {} + dwarf_composite (const dwarf_composite &composite) + : dwarf_location (composite), m_per_cu (composite.m_per_cu) + { + /* 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.m_pieces.size (); i++) + m_pieces.emplace_back (composite.m_pieces[i].m_location, + composite.m_pieces[i].m_size); + + m_completed = composite.m_completed; + } + + std::shared_ptr clone () const override + { + return std::make_shared (*this); + } + void add_piece (std::shared_ptr location, ULONGEST bit_size) { gdb_assert (location != nullptr); m_pieces.emplace_back (location, bit_size); } + void set_completed (bool completed) + { + m_completed = completed; + }; + + bool is_completed () const + { + return m_completed; + }; + void read (struct frame_info *frame, gdb_byte *buf, int buf_bit_offset, size_t bit_size, LONGEST bits_to_skip, size_t location_bit_limit, bool big_endian, int *optimized, int *unavailable) const override; @@ -1575,6 +1686,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; }; void @@ -1587,6 +1701,9 @@ dwarf_composite::read (struct frame_info *frame, gdb_byte *buf, LONGEST total_bits_to_skip = bits_to_skip; unsigned int i; + if (!m_completed) + ill_formed_expression (); + total_bits_to_skip += m_offset * HOST_CHAR_BIT + m_bit_suboffset; /* Skip pieces covered by the read offset. */ @@ -1632,6 +1749,9 @@ dwarf_composite::write (struct frame_info *frame, const gdb_byte *buf, unsigned int pieces_num = m_pieces.size (); unsigned int i; + if (!m_completed) + ill_formed_expression (); + total_bits_to_skip += m_offset * HOST_CHAR_BIT + m_bit_suboffset; /* Skip pieces covered by the write offset. */ @@ -2287,11 +2407,34 @@ struct dwarf_expr_context 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. */ + 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 */ std::shared_ptr add_piece (ULONGEST bit_size, ULONGEST bit_offset); @@ -2615,19 +2758,28 @@ dwarf_expr_context::add_piece (ULONGEST bit_size, ULONGEST bit_offset) std::shared_ptr piece; std::shared_ptr composite; - if (!stack_empty_p () - && std::dynamic_pointer_cast (fetch (0)) == nullptr) + if (stack_empty_p ()) + piece = std::make_shared (this->gdbarch); + else { piece = fetch (0)->to_location (this->gdbarch); - pop (); + + if (auto old_composite + = std::dynamic_pointer_cast (piece)) + { + if (!old_composite->is_completed ()) + piece = std::make_shared (this->gdbarch); + } + else if (std::dynamic_pointer_cast (piece) != nullptr) + pop (); } - else - piece = std::make_shared (this->gdbarch); - piece->add_bit_offset (bit_offset); + if (std::dynamic_pointer_cast (piece) == nullptr) + { + piece->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 () || std::dynamic_pointer_cast (fetch (0)) == nullptr) composite = std::make_shared (this->gdbarch, @@ -2635,7 +2787,12 @@ dwarf_expr_context::add_piece (ULONGEST bit_size, ULONGEST bit_offset) else { composite = std::dynamic_pointer_cast (fetch (0)); - pop (); + + if (composite->is_completed ()) + composite = std::make_shared (this->gdbarch, + this->per_cu); + else + pop (); } composite->add_piece (piece, bit_size); @@ -3255,7 +3412,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, break; case DW_OP_dup: - result_entry = fetch (0); + result_entry = fetch (0)->clone (); break; case DW_OP_drop: @@ -3281,7 +3438,7 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, } case DW_OP_over: - result_entry = fetch (1); + result_entry = fetch (1)->clone (); break; case DW_OP_rot: @@ -3842,6 +3999,23 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr, result_entry = std::make_shared (this->gdbarch); break; + case DW_OP_LLVM_piece_end: + { + auto entry = fetch (0); + + auto composite + = std::dynamic_pointer_cast (entry); + + if (composite == nullptr) + ill_formed_expression (); + + if (composite->is_completed ()) + ill_formed_expression (); + + composite->set_completed (true); + goto no_push; + } + default: error (_("Unhandled dwarf expression opcode 0x%x"), op); } 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 00000000000..8a8d0d8ec17 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-llvm-piece-end.exp @@ -0,0 +1,192 @@ +# Copyright (C) 2017-2021 Free Software Foundation, Inc. +# Copyright (C) 2020-2021 Advanced Micro Devices, Inc. All rights reserved. + +# 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 1b626362ec4..c6669221041 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