From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx0b-00069f02.pphosted.com (mx0b-00069f02.pphosted.com [205.220.177.32]) by sourceware.org (Postfix) with ESMTPS id 59605385381B for ; Tue, 2 Aug 2022 08:07:47 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 59605385381B Received: from pps.filterd (m0246632.ppops.net [127.0.0.1]) by mx0b-00069f02.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 2726XcW8012140; Tue, 2 Aug 2022 08:07:46 GMT Received: from phxpaimrmta02.imrmtpd1.prodappphxaev1.oraclevcn.com (phxpaimrmta02.appoci.oracle.com [147.154.114.232]) by mx0b-00069f02.pphosted.com (PPS) with ESMTPS id 3hmv8s61df-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 02 Aug 2022 08:07:46 +0000 Received: from pps.filterd (phxpaimrmta02.imrmtpd1.prodappphxaev1.oraclevcn.com [127.0.0.1]) by phxpaimrmta02.imrmtpd1.prodappphxaev1.oraclevcn.com (8.17.1.5/8.17.1.5) with ESMTP id 2726j1GD006773; Tue, 2 Aug 2022 08:07:45 GMT Received: from nam02-bn1-obe.outbound.protection.outlook.com (mail-bn1nam07lp2048.outbound.protection.outlook.com [104.47.51.48]) by phxpaimrmta02.imrmtpd1.prodappphxaev1.oraclevcn.com (PPS) with ESMTPS id 3hmu31tn5m-4 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 02 Aug 2022 08:07:44 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=DEzcLq/VlQVG7jHhApujMpIVCYlDdIN07AiukszZ9KyrmGfCcfEikfn5xzP2OdCdeisMJhyN07F3B9tKC7Kpb/rH2GICLKiZFipKS7D8O9eBZ+U308OU77BCKi9v+lgySoWq0v4/4/1l36TPmn37eRrdzQeXz02WHhwKSbWltWZ8gVaql+6w/Ku/vho4nMD/Ow8Abmq3W0c/Zt6/flnM3CSBEbJmdD9eqGTyE8Kvr4YllNpOIPCjCSZw8PZtix9xVcRCv6fv87Dhlw0TWPKFWcH35aOTB0sYfpemgpxqIV70Rerd8vbAdpEWq9l4HpfyClYnFYz8jwSLwncuWDmjPQ== 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=op6Iq3N3Nl/NWw2XvGOjzPKUDbOdeku2KyInA7M6xI8=; b=FgwQZNl9whimQin1c1dmKFaaIcFVKWJPir/LBhl9vW2mUWvmqffj4lLu6jkh2h/D/d/zVh9s1h21tcv+AVXk3eSy8N/huxuC2N5zXOA5Qr9X5W9r8hcJS6XbSWy5zgulfYAn7IVRgAr7U1TNg4zaeYrfMsqsdkzfrvHKEjAg1M21khOBhp5o7mzFwJsGYt0uL7aaZa1geAb4Z7knLrR/0e6vdZqyuSF3U/+7zIUZhvHxgzX6EaIBtZkgikheQR3N/mmubvlgi3bJ/ac25VrVdJmtpPkT3yHgYZ4/fF0wbwa0I+rAMNsRPPcI2ppJoBq77w6ZHG5F8VoLfPFJWO3FEg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oracle.com; dmarc=pass action=none header.from=oracle.com; dkim=pass header.d=oracle.com; arc=none Received: from MWHPR1001MB2158.namprd10.prod.outlook.com (2603:10b6:301:2d::17) by CH2PR10MB4184.namprd10.prod.outlook.com (2603:10b6:610:7f::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5482.11; Tue, 2 Aug 2022 08:07:40 +0000 Received: from MWHPR1001MB2158.namprd10.prod.outlook.com ([fe80::65fb:fa92:9a15:f89b]) by MWHPR1001MB2158.namprd10.prod.outlook.com ([fe80::65fb:fa92:9a15:f89b%6]) with mapi id 15.20.5482.016; Tue, 2 Aug 2022 08:07:40 +0000 From: Indu Bhagat To: binutils@sourceware.org Cc: amodra@gmail.com, weimin.pan@oracle.com, Indu Bhagat Subject: [PATCH,V6 06/10] bfd: linker: merge .ctf_frame sections Date: Tue, 2 Aug 2022 01:04:48 -0700 Message-Id: <20220802080452.1143351-7-indu.bhagat@oracle.com> X-Mailer: git-send-email 2.37.1 In-Reply-To: <20220802080452.1143351-1-indu.bhagat@oracle.com> References: <20220802080452.1143351-1-indu.bhagat@oracle.com> Content-Transfer-Encoding: 8bit Content-Type: text/plain X-ClientProxiedBy: MW4PR04CA0074.namprd04.prod.outlook.com (2603:10b6:303:6b::19) To MWHPR1001MB2158.namprd10.prod.outlook.com (2603:10b6:301:2d::17) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 6b60315f-37c7-45cd-e6ac-08da745e117b X-MS-TrafficTypeDiagnostic: CH2PR10MB4184:EE_ X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: Aj3Q/G41J1GkhlV4ECCK1WKgNrjCu1pKQccbk/npHo45HPqjSb8kW5RLbu05n+1XA5w7iMbfzqcLmZkTGcSayXe7nNbt/feVU0T/Q2CatE6w+UNf62F/UqS+LRnNwFyahAz3fb65AL2PTrP573o7DzMXzdfMfKpIgM8/Y+JgyW0pJWNy+siInwLnJmi3ELGpcgVd7KJP4XZmKql4OD+0L7qjzf3JnrP9EmcTKVpBIMR9x59+0xPRRTcED/Lerjx9Wr0i/ZHx4awN2Qu/b4YGlgT/+lDf+Ppt61B7z0n76G0Hgq7K4NY62dCSPuBc9qfrSD/FXM2z8YJD7X4cckGbCj5Sra5tX7BixfTVLUWBFJ/OArrJ1Vu8X0wFtsUko1qYJ5MCNJwDj0Y9CdfxQ7yLLVZEx9loGzgX/Mevl9XipxVEz/POsY+GnVDvacVbFqs4k+flgsFCCXOt8SZvL8kwt5UJbmJ+nNRyYByPg0vFO96k9XLQ8o0cfsZiDHZ2l+NNACDqOrzLvH6spUWcRQV+tReKbwiEiO0scrcsNd3rfw8P5R1KUX1KydfzXgHwxMIrsyNyjDmGSZ3z1USJjSBuBgO61Rb7OcieFCV6YcGi1xKq8a8utJAaGWAX9Pqo9BJ96gpHm5O6q/8tpud3QSVG7sXthqDFOZHEtOZiQzUOEHQBqPT6iMg0D6EOsuPTD8L4N0K9zcT2ai2VUX+JAhCCAQhQG7WiiwKLYOagGYPn+r+ExCcgC/Yl7c8+TAqTqvhf4j+bdM29KYEsimJEKbt2oyA+LZdeoQTc3tk6WBJBpEXJVBqYC/f0qgoKreZDe8O0errmu52EjJ0Zhk2x5oTtdPiRnDJNEb1nLHIXylBuKPk= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:MWHPR1001MB2158.namprd10.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230016)(376002)(366004)(136003)(346002)(396003)(39860400002)(4326008)(2616005)(1076003)(107886003)(83380400001)(186003)(66476007)(8936002)(66556008)(44832011)(8676002)(5660300002)(30864003)(66946007)(2906002)(36756003)(316002)(86362001)(478600001)(6916009)(6506007)(52116002)(41300700001)(6512007)(26005)(38350700002)(38100700002)(6486002)(142923001)(2004002)(559001)(579004); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?VuQdK/LbAuIrVuXdmQi3pbTMwTRnV0hv/H6aeH9ihWKCUYd0u/giRigf9QcX?= =?us-ascii?Q?jXOzVS1Q5oJlhjmRX2152PTReS7vYP+9Dm8eu5DZpmFf0lcp8wEsf4/+CN3P?= =?us-ascii?Q?TMD6/L7YfT8Q6jPKsu6gN/LUI7nfUw5WTsq1e5sFEdoc+14nS9o9xByJC8Yy?= =?us-ascii?Q?xRQ+QlfA29QENyxtRZEHZzV22XvOTHXspjgVRss0z6ceHn0/jUX8DXkgJzPP?= =?us-ascii?Q?b3noVjUmi/luldeitaLlPpRmgu4s0E36zoYveEermIre++k1XhFYX23fEJnV?= =?us-ascii?Q?eOkSS3OhXTMXym3n42uNk5t1xLyRweNJNDuxUZ/gu279+SsV0PMADSyPOWbt?= =?us-ascii?Q?auLkJQVT2B36+NHA7sNqNQFqnrPhlvjNvDig53w6fMQbrRVH7OaA69BsR+z5?= =?us-ascii?Q?8Siek4cf76sgDbxAGzPbJ8p/7f4TtebfomcVf/inEs6ESHe9AFJbtaiZxMxP?= =?us-ascii?Q?wDIXlgNwRlFSRQrnH06BiCGS3A61ibALUZz7ttGL836h6xxqsu2MGCDAvqxD?= =?us-ascii?Q?p3/ZDdffP20IjSjFAQXOJyiaLBKft+w8YmK2VXILE/Byz9+vZom/0w2qmMHQ?= =?us-ascii?Q?TBNlsZeUHK+GQmpJ8o6J4f6WhijdRMO9hzgBImirE7U5mC68rHXzkJU0akxg?= =?us-ascii?Q?nFOYybgrohIvDYCn4JBshVunHlA2tctzwQ3NIqNGlmPkgcGvHgpaExkLlc3m?= =?us-ascii?Q?SN3RxZ2BWrkNS6XrfxIpxECm5WVKPpLlDpKTEbq12vd8K7BBknsaH84mEdGp?= =?us-ascii?Q?cyNuKKBr9P0gs0UlVAv+AW/CDzlkmw5uXVQ/5+p6glqlSDFZYcus9UCb31ts?= =?us-ascii?Q?uhJPJtMisKpB7nDDxgXB6oI5M1PxRY9ydO/5G9pvwkZooCKp35gJ3S5G58eu?= =?us-ascii?Q?/yz4Jo0VEkyLAOlD5kxa3l/yEb6GFscFTxo2B4A65J6SNj1i2WQxZW70D4Fs?= =?us-ascii?Q?k2Oc0VKU+Wsqus3uJBs8M/ZAkCSeDfyAl0kMDzATKW40z7anKV265kZHU10+?= =?us-ascii?Q?xTzwpvs59+MN8qsbv6w1P2ShkCCGMhYYGCP+kbY/bf1xjNklz1QFoTfALbR9?= =?us-ascii?Q?d9oaziINXxO/k29n3jIz7hcZfGwfmLLz14h2K4Vvz4dwt46pAsK6PXEp8pWB?= =?us-ascii?Q?kiaD9+1qwR0MuxK5LYmrf7QbE8E5EXoZnUtrK9MSnEB+zjdaeKTCMQxItLQI?= =?us-ascii?Q?Z0TieSKrw/1jNd8bhK65S9PXwZBRbY1LBJM/HWV748XjqL1i8vqme7/59/2I?= =?us-ascii?Q?6f99JaN95Ok7c2w0yfA4JjyK+8N+sq9UpQ3vDgHY6ozrtGSdHk71rcmHbAWw?= =?us-ascii?Q?zNEqwqtjwdRFn2863xzufINWXHoN5brdbo0y5R1sTndbmUmyIshgO/3lDMF8?= =?us-ascii?Q?6PAqDxghN6MC4z56FibF2pEeGbGsghU055AbsKeeMLdpMZmIPVT9OfB5bCIA?= =?us-ascii?Q?fm+b7EruVL7AePZCYDUb+KekQlw5/hd5PzHq+krlzral34pQg8JoCbwP3hoX?= =?us-ascii?Q?ycxsn/L94Sloa5xjUJkN3uZy/qCo59FCF45nMpkBCK9DLMHCPLdUguKZCQbz?= =?us-ascii?Q?rGdrcQ9UH4yHgOSthRL0GNA88vHcS8WlUodz7ARh?= X-OriginatorOrg: oracle.com X-MS-Exchange-CrossTenant-Network-Message-Id: 6b60315f-37c7-45cd-e6ac-08da745e117b X-MS-Exchange-CrossTenant-AuthSource: MWHPR1001MB2158.namprd10.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 02 Aug 2022 08:07:40.3707 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 4e2c6054-71cb-48f1-bd6c-3a9705aca71b X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: zbgBPrtUaI3y3C6OEugaCMnCHYja/bVbN94P7HrsWtPnqkeaT5Q05Vz2AD8m+Lc1KGl+FSQJvUrtvMMeqScN4w== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CH2PR10MB4184 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.883,Hydra:6.0.517,FMLib:17.11.122.1 definitions=2022-08-02_04,2022-08-01_01,2022-06-22_01 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 spamscore=0 mlxscore=0 suspectscore=0 adultscore=0 bulkscore=0 malwarescore=0 mlxlogscore=999 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2206140000 definitions=main-2208020038 X-Proofpoint-GUID: m4_rnlTq-dPXmlxrWJ-kfnIeReKtQp8C X-Proofpoint-ORIG-GUID: m4_rnlTq-dPXmlxrWJ-kfnIeReKtQp8C X-Spam-Status: No, score=-12.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SCC_5_SHORT_WORD_LINES, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 02 Aug 2022 08:07:53 -0000 [No Changes from V4, V5] [Changes from V3] - Fix generation of CTF Frame unwind info for pltn entries. Use FDE type CTF_FRAME_DESCRIPTOR_ENTRY_TYPE_ADDRMASK for pltn entries. - Testsuite: Split out the checks for CTF Frame unwind info for the plt entries into a separate test. This test now serves to check the pltn unwind info generation on x86_64. [End of changes from V3] [Changes from V2] - consistent use of terminology around CTF Frame and its components. - few bugfixes: - CTF Frame unwind info generation for plt0 was incorrect. - do not update section size in _bfd_elf_write_section_ctf_frame for relocatable link. - added a testsuite in ld for CTF Frame. [End of changes from V2] [Changes from V1] - Refactor the code associated with the writing of .ctf_frame section for the dynamic .plt sections. - bugfix: Do not add a new segment PT_GNU_CTF_FRAME if .ctf_frame is an empty section. - ld: testsuite: fix ld bootstrap testcase by including libctfframe. - bugfix: linker-script: remove KEEP keyword for .ctf_frame secitons. [End of changes from V1] The linker merges all the input .ctf_frame sections. When merging, the linker verifies that all the input .ctf_frame sections have the same abi/arch. The linker uses libctfframe library to perform key actions on the .ctf_frame sections - decode, read, and create output data. This implies buildsystem changes to make and install libctfframe before libbfd. The linker places the output .ctf_frame section in a new segment of its own: PT_GNU_CTF_FRAME. When a section is discarded from the final link, the corresponding entries in the .ctf_frame section for those functions are also deleted. This patch also adds support for generation of CTF Frame unwind information for the .plt* sections on x86_64. CTF Frame unwind info is generated for IBT enabled PLT, lazy/non-lazy PLT. These bits are arguably unsatisfactory in terms of code quality and will be improved upon. Also recall that the CTF Frame format for PLT entries needs adjustments, so these chunks around .plt* sections are bound to evolve for the better. The existing linker option --no-ld-generated-unwind-info has been adapted to include the control of whether .ctf_frame unwind information will be generated for the linker generated sections like PLT. Changes to the linker script have been made as necessary. ChangeLog: * Makefile.def: Add install dependency on libctfframe for libbfd. * Makefile.in: Regenerated. * bfd/Makefile.am: Add elf-ctf-frame.c * bfd/Makefile.in: Regenerated. * bfd/bfd-in2.h (SEC_INFO_TYPE_CTF_FRAME): Regenerated. * bfd/configure: Regenerate. * bfd/configure.ac: Add elf-ctf-frame.lo. * bfd/elf-bfd.h (struct ctf_frame_func_bfdinfo): New struct. (struct ctf_frame_dec_info): Likewise. (struct ctf_frame_enc_info): Likewise. (struct elf_link_hash_table): New member for encoded .ctf_frame object. (struct output_elf_obj_tdata): New member. (elf_ctf_frame): New access macro. (_bfd_elf_set_section_ctf_frame): New declaration. * bfd/elf.c (get_segment_type): Handle new segment PT_GNU_CTF_FRAME. (bfd_section_from_phdr): Likewise. (get_program_header_size): Likewise. (_bfd_elf_map_sections_to_segments): Likewise. * bfd/elf64-x86-64.c (elf_x86_64_link_setup_gnu_properties): Add contents to the .ctf_frame sections or .plt* entries. * bfd/elflink.c (elf_section_ignore_discarded_relocs): Handle SEC_INFO_TYPE_CTF_FRAME. (_bfd_elf_default_action_discarded): Handle .ctf_frame section. (elf_link_input_bfd): Merge .ctf_frame section. (bfd_elf_final_link): Write the output .ctf_frame section. (bfd_elf_discard_info): Handle discarding .ctf_frame section. * bfd/elfxx-x86.c (_bfd_x86_elf_size_dynamic_sections): Create .ctf_frame section for .plt and .plt.sec. (_bfd_x86_elf_finish_dynamic_sections): Handle .ctf_frame from .plt* sections. * bfd/elfxx-x86.h (PLT_CTF_FRAME_FDE_START_OFFSET): New definition. (CTF_FRAME_PLT0_MAX_NUM_FRES): Likewise. (CTF_FRAME_PLTN_MAX_NUM_FRES): Likewise. (struct elf_x86_ctf_frame_plt): New structure. (struct elf_x86_link_hash_table): New member. (struct elf_x86_init_table): New members for .ctf_frame creation. * bfd/section.c: Add new definition SEC_INFO_TYPE_CTF_FRAME. * binutils/readelf.c (get_segment_type): Handle new segment PT_GNU_CTF_FRAME. * ld/ld.texi: Update documentation for --no-ld-generated-unwind-info. * ld/scripttempl/elf.sc: Support .ctf_frame sections. * Makefile.am (TESTCTFFRAMELIB): Use it. (check-DEJAGNU): Likewise. * configure.ac (TESTCTFFRAMELIB): Set to the .so or .a like TESTBFDLIB. * testsuite/ld-bootstrap/bootstrap.exp: Add CTFFRAMELIB. * bfd/elf-ctf-frame.c: New file. include/ChangeLog: * elf/common.h (PT_GNU_CTF_FRAME): New definition. * elf/internal.h (struct elf_segment_map): Handle new segment type PT_GNU_CTF_FRAME. ld/testsuite/ChangeLog: * ld/testsuite/ld-aarch64/aarch64-elf.exp: Add new test ctf-frame-simple-1. * ld/testsuite/ld-aarch64/ctf-frame-bar.s: New file. * ld/testsuite/ld-aarch64/ctf-frame-foo.s: Likewise. * ld/testsuite/ld-aarch64/ctf-frame-simple-1.d: Likewise. * ld/testsuite/ld-ctf-frame/ctf-frame-empty.d: New test. * ld/testsuite/ld-ctf-frame/ctf-frame-empty.s: New file. * ld/testsuite/ld-ctf-frame/ctfframe.exp: New testsuite. * ld/testsuite/ld-x86-64/ctf-frame-bar.s: New file. * ld/testsuite/ld-x86-64/ctf-frame-foo.s: Likewise. * ld/testsuite/ld-x86-64/ctf-frame-simple-1.d: Likewise. * ld/testsuite/ld-x86-64/ctf-frame-plt-1.d: Likewise. * ld/testsuite/ld-x86-64/ctf-frame-simple-1.d: Likewise. * ld/testsuite/ld-x86-64/x86-64.exp: Add new tests - ctf-frame-simple-1, ctf-frame-plt-1. * ld/testsuite/lib/ld-lib.exp: Add new proc to check if assembler supports CTF Frame section. * ld/testsuite/ld-ctf-frame/discard.d: New file. * ld/testsuite/ld-ctf-frame/discard.ld: Likewise. * ld/testsuite/ld-ctf-frame/discard.s: Likewise. --- Makefile.def | 5 +- Makefile.in | 21 +- bfd/Makefile.am | 6 +- bfd/Makefile.in | 7 +- bfd/bfd-in2.h | 1 + bfd/configure | 2 +- bfd/configure.ac | 2 +- bfd/elf-bfd.h | 55 ++ bfd/elf-ctf-frame.c | 529 +++++++++++++++++++ bfd/elf.c | 32 ++ bfd/elf64-x86-64.c | 97 +++- bfd/elflink.c | 52 ++ bfd/elfxx-x86.c | 379 ++++++++++++- bfd/elfxx-x86.h | 46 ++ bfd/section.c | 1 + binutils/readelf.c | 1 + include/ctf-frame-api.h | 2 +- include/elf/common.h | 1 + include/elf/internal.h | 1 + ld/Makefile.am | 2 + ld/Makefile.in | 2 + ld/configure | 8 +- ld/configure.ac | 3 + ld/ld.texi | 4 +- ld/scripttempl/elf.sc | 2 + ld/testsuite/ld-aarch64/aarch64-elf.exp | 2 + ld/testsuite/ld-aarch64/ctf-frame-bar.s | 7 + ld/testsuite/ld-aarch64/ctf-frame-foo.s | 10 + ld/testsuite/ld-aarch64/ctf-frame-simple-1.d | 26 + ld/testsuite/ld-bootstrap/bootstrap.exp | 8 +- ld/testsuite/ld-ctf-frame/ctf-frame-empty.d | 10 + ld/testsuite/ld-ctf-frame/ctf-frame-empty.s | 2 + ld/testsuite/ld-ctf-frame/ctf-frame.exp | 47 ++ ld/testsuite/ld-ctf-frame/discard.d | 10 + ld/testsuite/ld-ctf-frame/discard.ld | 9 + ld/testsuite/ld-ctf-frame/discard.s | 13 + ld/testsuite/ld-x86-64/ctf-frame-bar.s | 31 ++ ld/testsuite/ld-x86-64/ctf-frame-foo.s | 37 ++ ld/testsuite/ld-x86-64/ctf-frame-plt-1.d | 29 + ld/testsuite/ld-x86-64/ctf-frame-simple-1.d | 35 ++ ld/testsuite/ld-x86-64/x86-64.exp | 2 + ld/testsuite/lib/ld-lib.exp | 45 ++ libctfframe/ctf-frame.c | 28 +- 43 files changed, 1577 insertions(+), 35 deletions(-) create mode 100644 bfd/elf-ctf-frame.c create mode 100644 ld/testsuite/ld-aarch64/ctf-frame-bar.s create mode 100644 ld/testsuite/ld-aarch64/ctf-frame-foo.s create mode 100644 ld/testsuite/ld-aarch64/ctf-frame-simple-1.d create mode 100644 ld/testsuite/ld-ctf-frame/ctf-frame-empty.d create mode 100644 ld/testsuite/ld-ctf-frame/ctf-frame-empty.s create mode 100644 ld/testsuite/ld-ctf-frame/ctf-frame.exp create mode 100644 ld/testsuite/ld-ctf-frame/discard.d create mode 100644 ld/testsuite/ld-ctf-frame/discard.ld create mode 100644 ld/testsuite/ld-ctf-frame/discard.s create mode 100644 ld/testsuite/ld-x86-64/ctf-frame-bar.s create mode 100644 ld/testsuite/ld-x86-64/ctf-frame-foo.s create mode 100644 ld/testsuite/ld-x86-64/ctf-frame-plt-1.d create mode 100644 ld/testsuite/ld-x86-64/ctf-frame-simple-1.d diff --git a/Makefile.def b/Makefile.def index a63c3966513..2aacfec6c81 100644 --- a/Makefile.def +++ b/Makefile.def @@ -458,11 +458,14 @@ dependencies = { module=all-gdbsupport; on=all-gnulib; }; dependencies = { module=all-gdbsupport; on=all-intl; }; // Host modules specific to binutils. +// build libctfframe before bfd for encoder/decoder support for linking +// CTF frame sections dependencies = { module=configure-bfd; on=configure-libiberty; hard=true; }; dependencies = { module=configure-bfd; on=configure-intl; }; dependencies = { module=all-bfd; on=all-libiberty; }; dependencies = { module=all-bfd; on=all-intl; }; dependencies = { module=all-bfd; on=all-zlib; }; +dependencies = { module=all-bfd; on=all-libctfframe; }; dependencies = { module=configure-opcodes; on=configure-libiberty; hard=true; }; dependencies = { module=all-opcodes; on=all-libiberty; }; @@ -479,7 +482,6 @@ dependencies = { module=all-binutils; on=all-intl; }; dependencies = { module=all-binutils; on=all-gas; }; dependencies = { module=all-binutils; on=all-libctf; }; dependencies = { module=all-ld; on=all-libctf; }; -dependencies = { module=all-binutils; on=all-libctfframe; }; // We put install-opcodes before install-binutils because the installed // binutils might be on PATH, and they might need the shared opcodes @@ -488,6 +490,7 @@ dependencies = { module=install-binutils; on=install-opcodes; }; dependencies = { module=install-strip-binutils; on=install-strip-opcodes; }; // Likewise for ld, libctf, and bfd. +dependencies = { module=install-bfd; on=install-libctfframe; }; dependencies = { module=install-libctf; on=install-bfd; }; dependencies = { module=install-ld; on=install-bfd; }; dependencies = { module=install-ld; on=install-libctf; }; diff --git a/Makefile.in b/Makefile.in index 7b93fd14ffb..08e32e13f24 100644 --- a/Makefile.in +++ b/Makefile.in @@ -64407,6 +64407,16 @@ all-stagetrain-bfd: maybe-all-stagetrain-zlib all-stagefeedback-bfd: maybe-all-stagefeedback-zlib all-stageautoprofile-bfd: maybe-all-stageautoprofile-zlib all-stageautofeedback-bfd: maybe-all-stageautofeedback-zlib +all-bfd: maybe-all-libctfframe +all-stage1-bfd: maybe-all-stage1-libctfframe +all-stage2-bfd: maybe-all-stage2-libctfframe +all-stage3-bfd: maybe-all-stage3-libctfframe +all-stage4-bfd: maybe-all-stage4-libctfframe +all-stageprofile-bfd: maybe-all-stageprofile-libctfframe +all-stagetrain-bfd: maybe-all-stagetrain-libctfframe +all-stagefeedback-bfd: maybe-all-stagefeedback-libctfframe +all-stageautoprofile-bfd: maybe-all-stageautoprofile-libctfframe +all-stageautofeedback-bfd: maybe-all-stageautofeedback-libctfframe configure-opcodes: configure-libiberty configure-stage1-opcodes: configure-stage1-libiberty configure-stage2-opcodes: configure-stage2-libiberty @@ -64527,18 +64537,9 @@ all-stagetrain-ld: maybe-all-stagetrain-libctf all-stagefeedback-ld: maybe-all-stagefeedback-libctf all-stageautoprofile-ld: maybe-all-stageautoprofile-libctf all-stageautofeedback-ld: maybe-all-stageautofeedback-libctf -all-binutils: maybe-all-libctfframe -all-stage1-binutils: maybe-all-stage1-libctfframe -all-stage2-binutils: maybe-all-stage2-libctfframe -all-stage3-binutils: maybe-all-stage3-libctfframe -all-stage4-binutils: maybe-all-stage4-libctfframe -all-stageprofile-binutils: maybe-all-stageprofile-libctfframe -all-stagetrain-binutils: maybe-all-stagetrain-libctfframe -all-stagefeedback-binutils: maybe-all-stagefeedback-libctfframe -all-stageautoprofile-binutils: maybe-all-stageautoprofile-libctfframe -all-stageautofeedback-binutils: maybe-all-stageautofeedback-libctfframe install-binutils: maybe-install-opcodes install-strip-binutils: maybe-install-strip-opcodes +install-bfd: maybe-install-libctfframe install-libctf: maybe-install-bfd install-ld: maybe-install-bfd install-ld: maybe-install-libctf diff --git a/bfd/Makefile.am b/bfd/Makefile.am index 670e0598f55..505d7290cf6 100644 --- a/bfd/Makefile.am +++ b/bfd/Makefile.am @@ -286,6 +286,7 @@ BFD32_BACKENDS = \ ecofflink.lo \ elf-attrs.lo \ elf-eh-frame.lo \ + elf-ctf-frame.lo \ elf-ifunc.lo \ elf-m10200.lo \ elf-m10300.lo \ @@ -418,6 +419,7 @@ BFD32_BACKENDS_CFILES = \ ecofflink.c \ elf-attrs.c \ elf-eh-frame.c \ + elf-ctf-frame.c \ elf-ifunc.c \ elf-m10200.c \ elf-m10300.c \ @@ -770,8 +772,8 @@ ofiles: stamp-ofiles ; @true # dependency tracking fragments are picked up in the Makefile. libbfd_la_SOURCES = $(BFD32_LIBS_CFILES) EXTRA_libbfd_la_SOURCES = $(CFILES) -libbfd_la_DEPENDENCIES = $(OFILES) ofiles -libbfd_la_LIBADD = `cat ofiles` @SHARED_LIBADD@ $(LIBDL) $(ZLIB) +libbfd_la_DEPENDENCIES = $(OFILES) ofiles ../libctfframe/libctfframe.la +libbfd_la_LIBADD = `cat ofiles` @SHARED_LIBADD@ $(LIBDL) $(ZLIB) ../libctfframe/libctfframe.la libbfd_la_LDFLAGS += -release `cat libtool-soversion` @SHARED_LDFLAGS@ # libtool will build .libs/libbfd.a. We create libbfd.a in the build diff --git a/bfd/Makefile.in b/bfd/Makefile.in index d3ef4c2524b..f22a1cdff96 100644 --- a/bfd/Makefile.in +++ b/bfd/Makefile.in @@ -749,6 +749,7 @@ BFD32_BACKENDS = \ ecofflink.lo \ elf-attrs.lo \ elf-eh-frame.lo \ + elf-ctf-frame.lo \ elf-ifunc.lo \ elf-m10200.lo \ elf-m10300.lo \ @@ -881,6 +882,7 @@ BFD32_BACKENDS_CFILES = \ ecofflink.c \ elf-attrs.c \ elf-eh-frame.c \ + elf-ctf-frame.c \ elf-ifunc.c \ elf-m10200.c \ elf-m10300.c \ @@ -1194,8 +1196,8 @@ OFILES = $(BFD_BACKENDS) $(BFD_MACHINES) @COREFILE@ @bfd64_libs@ # dependency tracking fragments are picked up in the Makefile. libbfd_la_SOURCES = $(BFD32_LIBS_CFILES) EXTRA_libbfd_la_SOURCES = $(CFILES) -libbfd_la_DEPENDENCIES = $(OFILES) ofiles -libbfd_la_LIBADD = `cat ofiles` @SHARED_LIBADD@ $(LIBDL) $(ZLIB) +libbfd_la_DEPENDENCIES = $(OFILES) ofiles ../libctfframe/libctfframe.la +libbfd_la_LIBADD = `cat ofiles` @SHARED_LIBADD@ $(LIBDL) $(ZLIB) ../libctfframe/libctfframe.la # libtool will build .libs/libbfd.a. We create libbfd.a in the build # directory so that we don't have to convert all the programs that use @@ -1555,6 +1557,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecoff.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecofflink.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-attrs.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-ctf-frame.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-eh-frame.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-ifunc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-m10200.Plo@am__quote@ diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 2d6e1bbc0b0..40ba24b9adb 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -999,6 +999,7 @@ typedef struct bfd_section #define SEC_INFO_TYPE_JUST_SYMS 4 #define SEC_INFO_TYPE_TARGET 5 #define SEC_INFO_TYPE_EH_FRAME_ENTRY 6 +#define SEC_INFO_TYPE_CTF_FRAME 7 /* Nonzero if this section uses RELA relocations, rather than REL. */ unsigned int use_rela_p:1; diff --git a/bfd/configure b/bfd/configure index 590986efb61..7d67eeab891 100755 --- a/bfd/configure +++ b/bfd/configure @@ -13311,7 +13311,7 @@ selarchs="$f" tb= elf="elf.lo elflink.lo elf-attrs.lo elf-strtab.lo elf-eh-frame.lo - dwarf1.lo dwarf2.lo" + elf-ctf-frame.lo dwarf1.lo dwarf2.lo" coffgen="coffgen.lo dwarf2.lo" coff="cofflink.lo $coffgen" ecoff="ecofflink.lo $coffgen" diff --git a/bfd/configure.ac b/bfd/configure.ac index aad4f3c83a5..30e58a2079a 100644 --- a/bfd/configure.ac +++ b/bfd/configure.ac @@ -389,7 +389,7 @@ selarchs="$f" tb= elf="elf.lo elflink.lo elf-attrs.lo elf-strtab.lo elf-eh-frame.lo - dwarf1.lo dwarf2.lo" + elf-ctf-frame.lo dwarf1.lo dwarf2.lo" coffgen="coffgen.lo dwarf2.lo" coff="cofflink.lo $coffgen" ecoff="ecofflink.lo $coffgen" diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 65bd1128263..9233c294e27 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -490,6 +490,40 @@ struct eh_frame_hdr_info u; }; +/* Additional information for each function (used at link time). */ +struct ctf_frame_func_bfdinfo +{ + /* Whether the function has been discarded from the final output. */ + bool func_deleted_p; + /* Relocation offset. */ + unsigned int func_r_offset; + /* Relocation index. */ + unsigned int func_reloc_index; +}; + +/* CTF Frame decoder info. + Contains all information for a decoded .ctf_frame section. */ +struct ctf_frame_dec_info +{ + /* Decoder context. */ + struct ctf_frame_decoder_ctx *cfd_ctx; + /* Number of function descriptor entries in this .ctf_frame. */ + unsigned int cfd_fde_count; + /* Additional information for linking. */ + struct ctf_frame_func_bfdinfo *cfd_func_bfdinfo; +}; + +/* CTF Frame encoder info. + Contains all information for an encoded .ctf_frame section to be + written out. */ +struct ctf_frame_enc_info +{ + /* Encoder context. */ + struct ctf_frame_encoder_ctx *cfe_ctx; + /* Output section. */ + asection *ctf_frame_section; +}; + /* Enum used to identify target specific extensions to the elf_obj_tdata and elf_link_hash_table structures. Note the enums deliberately start from 1 so that we can detect an uninitialized field. The generic value @@ -668,6 +702,9 @@ struct elf_link_hash_table /* Used by eh_frame code when editing .eh_frame. */ struct eh_frame_hdr_info eh_info; + /* Used to link unwind data in .ctf_frame sections. */ + struct ctf_frame_enc_info cfe_info; + /* A linked list of local symbols to be added to .dynsym. */ struct elf_link_local_dynamic_entry *dynlocal; @@ -1941,6 +1978,10 @@ struct output_elf_obj_tdata /* Segment flags for the PT_GNU_STACK segment. */ unsigned int stack_flags; + /* Used to determine if PT_GNU_CTF_FRAME segment header should be + created. */ + asection *ctf_frame; + /* Used to determine if the e_flags field has been initialized */ bool flags_init; }; @@ -2122,6 +2163,7 @@ struct elf_obj_tdata #define elf_link_info(bfd) (elf_tdata(bfd) -> o->link_info) #define elf_next_file_pos(bfd) (elf_tdata(bfd) -> o->next_file_pos) #define elf_stack_flags(bfd) (elf_tdata(bfd) -> o->stack_flags) +#define elf_ctf_frame(bfd) (elf_tdata(bfd) -> o->ctf_frame) #define elf_shstrtab(bfd) (elf_tdata(bfd) -> o->strtab_ptr) #define elf_onesymtab(bfd) (elf_tdata(bfd) -> symtab_section) #define elf_symtab_shndx_list(bfd) (elf_tdata(bfd) -> symtab_shndx_list) @@ -2433,6 +2475,19 @@ extern bool _bfd_elf_eh_frame_entry_present extern bool _bfd_elf_maybe_strip_eh_frame_hdr (struct bfd_link_info *); +extern bool _bfd_elf_ctf_frame_present + (struct bfd_link_info *); +extern void _bfd_elf_parse_ctf_frame + (bfd *, struct bfd_link_info *, asection *, struct elf_reloc_cookie *); +extern bool _bfd_elf_discard_section_ctf_frame + (bfd *, struct bfd_link_info *, asection *, + bool (*) (bfd_vma, void *), struct elf_reloc_cookie *); +extern bool _bfd_elf_merge_section_ctf_frame + (bfd *, struct bfd_link_info *, asection *, bfd_byte *); +extern bool _bfd_elf_write_section_ctf_frame + (bfd *, struct bfd_link_info *); +extern bool _bfd_elf_set_section_ctf_frame (bfd *, struct bfd_link_info *); + extern bool _bfd_elf_hash_symbol (struct elf_link_hash_entry *); extern long _bfd_elf_link_lookup_local_dynindx diff --git a/bfd/elf-ctf-frame.c b/bfd/elf-ctf-frame.c new file mode 100644 index 00000000000..243429fca45 --- /dev/null +++ b/bfd/elf-ctf-frame.c @@ -0,0 +1,529 @@ +/* .ctf_frame section processing. + Copyright (C) 2022 Free Software Foundation, Inc. + + This file is part of BFD, the Binary File Descriptor library. + + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "sysdep.h" +#include "bfd.h" +#include "libbfd.h" +#include "elf-bfd.h" +#include "ctf-frame-api.h" + +/* Return TRUE if the function has been marked for deletion during the linking + process. */ + +static bool +ctf_frame_decoder_func_deleted_p (struct ctf_frame_dec_info *cfd_info, + unsigned int func_idx) +{ + return cfd_info->cfd_func_bfdinfo[func_idx].func_deleted_p; +} + +/* Mark the function in the decoder info for deletion. */ + +static void +ctf_frame_decoder_mark_func_deleted (struct ctf_frame_dec_info *cfd_info, + unsigned int func_idx) +{ + BFD_ASSERT (func_idx < cfd_info->cfd_fde_count); + cfd_info->cfd_func_bfdinfo[func_idx].func_deleted_p = true; +} + +/* Get the relocation offset from the decoder info for the given function. */ + +static unsigned int +ctf_frame_decoder_get_func_r_offset (struct ctf_frame_dec_info *cfd_info, + unsigned int func_idx) +{ + BFD_ASSERT (func_idx < cfd_info->cfd_fde_count); + unsigned int func_r_offset + = cfd_info->cfd_func_bfdinfo[func_idx].func_r_offset; + /* There must have been a reloc. */ + BFD_ASSERT (func_r_offset); + return func_r_offset; +} + +/* Bookkeep the function relocation offset in the decoder info. */ + +static void +ctf_frame_decoder_set_func_r_offset (struct ctf_frame_dec_info *cfd_info, + unsigned int func_idx, + unsigned int r_offset) +{ + BFD_ASSERT (func_idx < cfd_info->cfd_fde_count); + cfd_info->cfd_func_bfdinfo[func_idx].func_r_offset = r_offset; +} + +/* Get the relocation index in the elf_reloc_cookie for the function. */ + +static unsigned int +ctf_frame_decoder_get_func_reloc_index (struct ctf_frame_dec_info *cfd_info, + unsigned int func_idx) +{ + BFD_ASSERT (func_idx < cfd_info->cfd_fde_count); + return cfd_info->cfd_func_bfdinfo[func_idx].func_reloc_index; +} + +/* Bookkeep the relocation index in the elf_reloc_cookie for the function. */ + +static void +ctf_frame_decoder_set_func_reloc_index (struct ctf_frame_dec_info *cfd_info, + unsigned int func_idx, + unsigned int reloc_index) +{ + BFD_ASSERT (func_idx < cfd_info->cfd_fde_count); + cfd_info->cfd_func_bfdinfo[func_idx].func_reloc_index = reloc_index; +} + +/* Initialize the set of additional information in CFD_INFO, + needed for linking SEC. Returns TRUE if setup is done successfully. */ + +static bool +ctf_frame_decoder_init_func_bfdinfo (asection *sec, + struct ctf_frame_dec_info *cfd_info, + struct elf_reloc_cookie *cookie) +{ + unsigned int fde_count; + unsigned int func_bfdinfo_size, i; + + fde_count = ctf_frame_decoder_get_num_fidx (cfd_info->cfd_ctx); + cfd_info->cfd_fde_count = fde_count; + + /* Allocate and clear the memory. */ + func_bfdinfo_size = (sizeof (struct ctf_frame_func_bfdinfo)) * fde_count; + cfd_info->cfd_func_bfdinfo + = (struct ctf_frame_func_bfdinfo*) bfd_malloc (func_bfdinfo_size); + if (cfd_info->cfd_func_bfdinfo == NULL) + return false; + memset (cfd_info->cfd_func_bfdinfo, 0, func_bfdinfo_size); + + /* For linker generated .ctf_frame sections, we have no relocs. Skip. */ + if ((sec->flags & SEC_LINKER_CREATED) && cookie->rels == NULL) + return true; + + for (i = 0; i < fde_count; i++) + { + cookie->rel = cookie->rels + i; + BFD_ASSERT (cookie->rel < cookie->relend); + /* Bookkeep the relocation offset and relocation index of each function + for later use. */ + ctf_frame_decoder_set_func_r_offset (cfd_info, i, cookie->rel->r_offset); + ctf_frame_decoder_set_func_reloc_index (cfd_info, i, + (cookie->rel - cookie->rels)); + + cookie->rel++; + } + BFD_ASSERT (cookie->rel == cookie->relend); + + return true; +} + +/* Read the value from CONTENTS at the specified OFFSET for the given ABFD. */ + +static bfd_vma +ctf_frame_read_value (bfd *abfd, bfd_byte *contents, unsigned int offset, + unsigned int width) +{ + BFD_ASSERT (contents && offset); + /* Supporting the usecase of reading only the 4-byte relocated + value (signed offset for func start addr) for now. */ + BFD_ASSERT (width == 4); + /* FIXME endianness ?? */ + unsigned char *buf = contents + offset; + bfd_vma value = bfd_get_signed_32 (abfd, buf); + return value; +} + +/* Return true if there is at least one non-empty .ctf_frame section in + input files. Can only be called after ld has mapped input to + output sections, and before sections are stripped. */ + +bool +_bfd_elf_ctf_frame_present (struct bfd_link_info *info) +{ + asection *ctff = bfd_get_section_by_name (info->output_bfd, ".ctf_frame"); + + if (ctff == NULL) + return false; + + /* Count only sections which have at least a single FDE. */ + for (ctff = ctff->map_head.s; ctff != NULL; ctff = ctff->map_head.s) + if (ctff->size > sizeof (ctf_frame_header)) + return true; + return false; +} + +/* Try to parse .ctf_frame section SEC, which belongs to ABFD. Store the + information in the section's sec_info field on success. COOKIE + describes the relocations in SEC. */ + +void +_bfd_elf_parse_ctf_frame (bfd *abfd, struct bfd_link_info *info, + asection *sec, struct elf_reloc_cookie *cookie) +{ + bfd_byte *ctfbuf = NULL; + struct ctf_frame_dec_info *cfd_info; + ctf_frame_decoder_ctx *cfd_ctx; + bfd_size_type cf_size; + int decerr = 0; + + if (sec->size == 0 + || sec->sec_info_type != SEC_INFO_TYPE_NONE) + { + /* This file does not contain .ctf_frame information. */ + return; + } + + if (bfd_is_abs_section (sec->output_section)) + { + /* At least one of the sections is being discarded from the + link, so we should just ignore them. */ + return; + } + + /* Read the ctf frame unwind information from abfd. */ + if (!bfd_malloc_and_get_section (abfd, sec, &ctfbuf)) + goto fail_no_free; + + /* Decode the buffer and keep decoded contents for later use. + Relocations are performed later, but are such that the section's + size is unaffected. */ + cfd_info = bfd_malloc (sizeof (struct ctf_frame_dec_info)); + cf_size = sec->size; + BFD_ASSERT (cf_size); + + cfd_info->cfd_ctx = ctf_frame_decode ((const char*)ctfbuf, cf_size, &decerr); + cfd_ctx = cfd_info->cfd_ctx; + if (!cfd_ctx) + /* Free'ing up any memory held by decoder context is done by + ctf_frame_decode in case of error. */ + goto fail_no_free; + + if (!ctf_frame_decoder_init_func_bfdinfo (sec, cfd_info, cookie)) + { + ctf_frame_decoder_free (&cfd_ctx); + goto fail_no_free; + } + + elf_section_data (sec)->sec_info = cfd_info; + sec->sec_info_type = SEC_INFO_TYPE_CTF_FRAME; + + BFD_ASSERT (abfd && info && cookie); + goto success; + +fail_no_free: + _bfd_error_handler + (_("error in %pB(%pA); no .ctf_frame will be created"), + abfd, sec); +success: + free (ctfbuf); +} + +/* This function is called for each input file before the .ctf_frame section + is relocated. It marks the CTF FDE for the discarded functions for + deletion. + + The function returns TRUE iff any entries have been deleted. */ + +bool +_bfd_elf_discard_section_ctf_frame + (bfd *abfd, struct bfd_link_info *info, asection *sec, + bool (*reloc_symbol_deleted_p) (bfd_vma, void *), + struct elf_reloc_cookie *cookie) +{ + struct ctf_frame_dec_info *cfd_info; + BFD_ASSERT (abfd && info); + BFD_ASSERT (reloc_symbol_deleted_p); + cfd_info = (struct ctf_frame_dec_info *) elf_section_data (sec)->sec_info; + + bool changed = false; + /* FIXME - if relocatable link and changed = true, how does the final + .rela.ctf_frame get updated ?. */ + bool keep = false; + unsigned int i = 0; + unsigned int func_desc_offset = 0; + unsigned int num_fidx = 0; + + /* Skip checking for the linker created .ctf_frame sections + (for PLT sections). */ + if ((sec->flags & SEC_LINKER_CREATED) == 0 || cookie->rels != NULL) + { + num_fidx = ctf_frame_decoder_get_num_fidx (cfd_info->cfd_ctx); + for (i = 0; i < num_fidx; i++) + { + func_desc_offset = ctf_frame_decoder_get_func_r_offset (cfd_info, i); + + cookie->rel = cookie->rels + + ctf_frame_decoder_get_func_reloc_index (cfd_info, i); + keep = !(*reloc_symbol_deleted_p) (func_desc_offset, cookie); + + if (!keep) + { + ctf_frame_decoder_mark_func_deleted (cfd_info, i); + changed = true; + } + } + } + return changed; +} + +/* Update the reference to the output .ctf_frame section in the output ELF + BFD ABFD. Returns true if no error. */ + +bool +_bfd_elf_set_section_ctf_frame (bfd *abfd, + struct bfd_link_info *info) +{ + asection *cfsec; + + cfsec = bfd_get_section_by_name (info->output_bfd, ".ctf_frame"); + if (!cfsec) + return false; + + elf_ctf_frame (abfd) = cfsec; + + return true; +} + +/* Merge .ctf_frame section SEC. This is called with the relocated + CONTENTS. */ + +bool +_bfd_elf_merge_section_ctf_frame (bfd *abfd, + struct bfd_link_info *info, + asection *sec, + bfd_byte *contents) +{ + struct ctf_frame_dec_info *cfd_info; + struct ctf_frame_enc_info *cfe_info; + ctf_frame_decoder_ctx *cfd_ctx; + ctf_frame_encoder_ctx *cfe_ctx; + unsigned char cfd_ctx_abi_arch = 0; + int encerr = 0; + + struct elf_link_hash_table *htab; + asection *cfsec; + + BFD_ASSERT (abfd && info && sec && contents); + + BFD_ASSERT (sec->sec_info_type == SEC_INFO_TYPE_CTF_FRAME); + + cfd_info = (struct ctf_frame_dec_info *) elf_section_data (sec)->sec_info; + cfd_ctx = cfd_info->cfd_ctx; + + htab = elf_hash_table (info); + cfe_info = &(htab->cfe_info); + cfe_ctx = cfe_info->cfe_ctx; + + /* All input bfds are expected to have a valid CTF Frame section. Even if + the CTF Frame section is empty with only a header, the section will have + been parsed and decoded by now. */ + BFD_ASSERT (cfd_info && cfd_ctx); + + BFD_ASSERT (htab); + BFD_ASSERT (cfe_info); + BFD_ASSERT (sec->output_section); + + if (htab->cfe_info.cfe_ctx == NULL) + { + cfd_ctx_abi_arch = ctf_frame_decoder_get_abi_arch (cfd_ctx); + BFD_ASSERT (cfd_ctx_abi_arch); /* Valid values are non-zero. */ + htab->cfe_info.cfe_ctx = ctf_frame_encode (CTF_FRAME_VERSION_1, + 0, /* CTF Frame flags. */ + cfd_ctx_abi_arch, + &encerr); + /* Handle errors from ctf_frame_encode. */ + if (htab->cfe_info.cfe_ctx == NULL) + return false; + } + cfe_ctx = cfe_info->cfe_ctx; + + if (cfe_info->ctf_frame_section == NULL) + { + /* Make sure things are set for an eventual write. + Size of the output section is not known until + _bfd_elf_write_section_ctf_frame is ready with the buffer + to write out. */ + cfsec = bfd_get_section_by_name (info->output_bfd, ".ctf_frame"); + if (cfsec) + { + cfe_info->ctf_frame_section = cfsec; + // elf_ctf_frame (abfd) = cfsec; + } + else + return false; + } + + /* Check that all .ctf_frame sections being linked have the same + ABI/arch. */ + if (ctf_frame_decoder_get_abi_arch (cfd_ctx) + != ctf_frame_encoder_get_abi_arch (cfe_ctx)) + { + _bfd_error_handler + (_("input CTF Frame sections with different abi prevent .ctf_frame" + " generation")); + return false; + } + + /* Iterate over the function descriptor entries and the FREs of the + function from the decoder context. Add each of them to the encoder + context, if suitable. */ + unsigned int i = 0, j = 0, cur_fidx = 0; + + unsigned int num_fidx = ctf_frame_decoder_get_num_fidx (cfd_ctx); + unsigned int num_enc_fidx = ctf_frame_encoder_get_num_fidx (cfe_ctx); + + for (i = 0; i < num_fidx; i++) + { + unsigned int num_fres = 0; + int32_t func_start_address; + bfd_vma address; + uint32_t func_size = 0; + unsigned char func_info = 0; + unsigned int r_offset = 0; + bool pltn_reloc_by_hand = false; + unsigned int pltn_r_offset = 0; + + if (!ctf_frame_decoder_get_funcdesc (cfd_ctx, i, &num_fres, &func_size, + &func_start_address, &func_info)) + { + /* If function belongs to a deleted section, skip editing the + function descriptor entry. */ + if (ctf_frame_decoder_func_deleted_p(cfd_info, i)) + continue; + + /* Don't edit function descriptor entries for relocatable link. */ + if (!bfd_link_relocatable (info)) + { + if (!(sec->flags & SEC_LINKER_CREATED)) + { + /* Get relocated contents by reading the value of the + relocated function start address at the beginning of the + function descriptor entry. */ + r_offset = ctf_frame_decoder_get_func_r_offset (cfd_info, i); + } + else + { + /* Expected to land here for CTF Frame unwind info as created + for the .plt* sections. These sections can have upto two + FDE entries. Although the code should work for > 2, + leaving this assert here for safety. */ + BFD_ASSERT (num_fidx <= 2); + /* For the first entry, we know the offset of the CTF FDE's + ctf_func_start_address. Side note: see how the value + of PLT_CTF_FRAME_FDE_START_OFFSET is also set to the + same. */ + r_offset = sizeof (ctf_frame_header); + /* For any further CTF FDEs, the generator has already put in + an offset in place of ctf_func_start_address of the + corresponding FDE. We will use it by hand to relocate. */ + if (i > 0) + { + pltn_r_offset + = r_offset + (i * sizeof (ctf_frame_func_desc_entry)); + pltn_reloc_by_hand = true; + } + } + + /* Get the CTF FDE function start address after relocation. */ + address = ctf_frame_read_value (abfd, contents, r_offset, 4); + if (pltn_reloc_by_hand) + address += ctf_frame_read_value (abfd, contents, + pltn_r_offset, 4); + address += (sec->output_offset + r_offset); + + /* FIXME For testing only. Cleanup later. */ + // address += (sec->output_section->vma); + + func_start_address = address; + } + + /* Update the encoder context with updated content. */ + int err = ctf_frame_encoder_add_funcdesc (cfe_ctx, func_start_address, + func_size, func_info, + num_fres); + cur_fidx++; + BFD_ASSERT (!err); + } + + for (j = 0; j < num_fres; j++) + { + ctf_frame_row_entry fre; + if (!ctf_frame_decoder_get_fre (cfd_ctx, i, j, &fre)) + { + int err = ctf_frame_encoder_add_fre (cfe_ctx, + cur_fidx-1+num_enc_fidx, + &fre); + BFD_ASSERT (!err); + } + } + } + /* Free the CTF Frame decoder context. */ + ctf_frame_decoder_free (&cfd_ctx); + + return true; +} + +/* Write out the .ctf_frame section. This must be called after + _bfd_elf_merge_section_ctf_frame has been called on all input + .ctf_frame sections. */ + +bool +_bfd_elf_write_section_ctf_frame (bfd *abfd, struct bfd_link_info *info) +{ + bool retval = true; + BFD_ASSERT (abfd && info); + + struct elf_link_hash_table *htab; + struct ctf_frame_enc_info *cfe_info; + ctf_frame_encoder_ctx *cfe_ctx; + asection *sec; + void *contents; + bfd_size_type sec_size; + int err = 0; + + htab = elf_hash_table (info); + cfe_info = &htab->cfe_info; + sec = cfe_info->ctf_frame_section; + cfe_ctx = cfe_info->cfe_ctx; + + // FIXME use assert + // BFD_ASSERT (sec); + if (sec == NULL) + return true; + + + contents = ctf_frame_write_encoder (cfe_ctx, &sec_size, &err); + sec->size = sec_size; + + if (!bfd_set_section_contents (abfd, sec->output_section, contents, + (file_ptr) sec->output_offset, + sec_size)) + retval = false; + else if (!bfd_link_relocatable (info)) + { + Elf_Internal_Shdr *hdr = &elf_section_data (sec)->this_hdr; + hdr->sh_size = sec_size; + } + /* For relocatable links, do not update the section size as the section + contents have not been relocated. */ + + ctf_frame_encoder_free (&cfe_ctx); + + return retval; +} diff --git a/bfd/elf.c b/bfd/elf.c index 89484ceb233..43b65117053 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -1646,6 +1646,7 @@ get_segment_type (unsigned int p_type) case PT_GNU_EH_FRAME: pt = "EH_FRAME"; break; case PT_GNU_STACK: pt = "STACK"; break; case PT_GNU_RELRO: pt = "RELRO"; break; + case PT_GNU_CTF_FRAME: pt = "CTF_FRAME"; break; default: pt = NULL; break; } return pt; @@ -3060,6 +3061,10 @@ bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int hdr_index) case PT_GNU_RELRO: return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "relro"); + case PT_GNU_CTF_FRAME: + return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, + "ctf_frame"); + default: /* Check for any processor-specific program segment types. */ bed = get_elf_backend_data (abfd); @@ -4408,6 +4413,12 @@ get_program_header_size (bfd *abfd, struct bfd_link_info *info) ++segs; } + if (elf_ctf_frame (abfd)) + { + /* We need a PT_GNU_CTF_FRAME segment. */ + ++segs; + } + s = bfd_get_section_by_name (abfd, NOTE_GNU_PROPERTY_SECTION_NAME); if (s != NULL && s->size != 0) @@ -4673,6 +4684,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, asection *first_tls = NULL; asection *first_mbind = NULL; asection *dynsec, *eh_frame_hdr; + asection *ctf_frame; size_t amt; bfd_vma addr_mask, wrap_to = 0; /* Bytes. */ bfd_size_type phdr_size; /* Octets/bytes. */ @@ -5190,6 +5202,26 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, pm = &m->next; } + /* If there is a .ctf_frame section, throw in a PT_GNU_CTF_FRAME + segment. */ + ctf_frame = elf_ctf_frame (abfd); + if (ctf_frame != NULL + && (ctf_frame->output_section->flags & SEC_LOAD) != 0 + && ctf_frame->size != 0) + { + amt = sizeof (struct elf_segment_map); + m = (struct elf_segment_map *) bfd_zalloc (abfd, amt); + if (m == NULL) + goto error_return; + m->next = NULL; + m->p_type = PT_GNU_CTF_FRAME; + m->count = 1; + m->sections[0] = ctf_frame->output_section; + + *pm = m; + pm = &m->next; + } + if (info != NULL && info->relro) { for (m = mfirst; m != NULL; m = m->next) diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 62a9a22317a..a73673b2b4b 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -22,6 +22,7 @@ #include "elfxx-x86.h" #include "dwarf2.h" #include "libiberty.h" +#include "ctf-frame.h" #include "opcode/i386.h" @@ -818,6 +819,87 @@ static const bfd_byte elf_x86_64_eh_frame_non_lazy_plt[] = DW_CFA_nop, DW_CFA_nop, DW_CFA_nop }; +static const ctf_frame_row_entry elf_x86_64_ctf_frame_null_fre = +{ + 0, + CTF_FRAME_V1_FRE_INFO (CTF_FRAME_BASE_REG_SP, 1, CTF_FRAME_FRE_OFFSET_1B), /* FRE info. */ + {16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* 12 bytes. */ +}; + +/* .ctf_frame FRE covering the .plt section entry. */ +static const ctf_frame_row_entry elf_x86_64_ctf_frame_plt0_fre1 = +{ + 0, /* CTF FRE start address. */ + CTF_FRAME_V1_FRE_INFO (CTF_FRAME_BASE_REG_SP, 1, CTF_FRAME_FRE_OFFSET_1B), /* FRE info. */ + {16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* 12 bytes. */ +}; + +/* .ctf_frame FRE covering the .plt section entry. */ +static const ctf_frame_row_entry elf_x86_64_ctf_frame_plt0_fre2 = +{ + 6, /* CTF FRE start address. */ + CTF_FRAME_V1_FRE_INFO (CTF_FRAME_BASE_REG_SP, 1, CTF_FRAME_FRE_OFFSET_1B), /* FRE info. */ + {24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* 12 bytes. */ +}; + +/* .ctf_frame FRE covering the .plt section entry. */ +static const ctf_frame_row_entry elf_x86_64_ctf_frame_pltn_fre1 = +{ + 0, /* CTF FRE start address. */ + CTF_FRAME_V1_FRE_INFO (CTF_FRAME_BASE_REG_SP, 1, CTF_FRAME_FRE_OFFSET_1B), /* FRE info. */ + {8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* 12 bytes. */ +}; + +/* .ctf_frame FRE covering the .plt section entry. */ +static const ctf_frame_row_entry elf_x86_64_ctf_frame_pltn_fre2 = +{ + 11, /* CTF FRE start address. */ + CTF_FRAME_V1_FRE_INFO (CTF_FRAME_BASE_REG_SP, 1, CTF_FRAME_FRE_OFFSET_1B), /* FRE info. */ + {16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* 12 bytes. */ +}; + +/* .ctf_frame FRE covering the second .plt section entry. */ +static const ctf_frame_row_entry elf_x86_64_ctf_frame_sec_pltn_fre1 = +{ + 0, /* CTF FRE start address. */ + CTF_FRAME_V1_FRE_INFO (CTF_FRAME_BASE_REG_SP, 1, CTF_FRAME_FRE_OFFSET_1B), /* FRE info. */ + {8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* 12 bytes. */ +}; + +/* CTF Frame helper object for non-lazy PLT. Also used for IBT enabled PLT. */ +static const struct elf_x86_ctf_frame_plt elf_x86_64_ctf_frame_non_lazy_plt = +{ + LAZY_PLT_ENTRY_SIZE, + 2, /* Number of FREs for PLT0. */ + /* Array of CTF Frame FREs for plt0. */ + { &elf_x86_64_ctf_frame_plt0_fre1, &elf_x86_64_ctf_frame_plt0_fre2 }, + LAZY_PLT_ENTRY_SIZE, + 1, /* Number of FREs for PLTn. */ + /* Array of CTF Frame FREs for plt. */ + { &elf_x86_64_ctf_frame_sec_pltn_fre1, &elf_x86_64_ctf_frame_null_fre }, + 0, + 0, /* There is no second PLT necessary. */ + { &elf_x86_64_ctf_frame_null_fre } +}; + +/* CTF Frame helper object for lazy PLT. Also used for IBT enabled PLT. */ +static const struct elf_x86_ctf_frame_plt elf_x86_64_ctf_frame_plt = +{ + LAZY_PLT_ENTRY_SIZE, + 2, /* Number of FREs for PLT0. */ + /* Array of CTF Frame FREs for plt0. */ + { &elf_x86_64_ctf_frame_plt0_fre1, &elf_x86_64_ctf_frame_plt0_fre2 }, + LAZY_PLT_ENTRY_SIZE, + 2, /* Number of FREs for PLTn. */ + /* Array of CTF Frame FREs for plt. */ + { &elf_x86_64_ctf_frame_pltn_fre1, &elf_x86_64_ctf_frame_pltn_fre2 }, + NON_LAZY_PLT_ENTRY_SIZE, + 1, /* Number of FREs for PLTn for second PLT. */ + /* FREs for second plt ( unwind info for .plt.got is + identical). Used when IBT or non-lazy PLT is in effect. */ + { &elf_x86_64_ctf_frame_sec_pltn_fre1 } +}; + /* These are the standard parameters. */ static const struct elf_x86_lazy_plt_layout elf_x86_64_lazy_plt = { @@ -971,7 +1053,6 @@ static const struct elf_x86_non_lazy_plt_layout elf_x32_non_lazy_ibt_plt = sizeof (elf_x86_64_eh_frame_non_lazy_plt) /* eh_frame_plt_size */ }; - static bool elf64_x86_64_elf_object_p (bfd *abfd) { @@ -5227,6 +5308,20 @@ elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info) init_table.non_lazy_ibt_plt = &elf_x32_non_lazy_ibt_plt; } + if (ABI_64_P (info->output_bfd)) + { + init_table.ctf_frame_lazy_plt = &elf_x86_64_ctf_frame_plt; + init_table.ctf_frame_non_lazy_plt = &elf_x86_64_ctf_frame_non_lazy_plt; + init_table.ctf_frame_lazy_ibt_plt = &elf_x86_64_ctf_frame_plt; + init_table.ctf_frame_non_lazy_ibt_plt = &elf_x86_64_ctf_frame_non_lazy_plt; + } + else + { + /* CTF Frame is not supported for non AMD64. */ + init_table.ctf_frame_lazy_plt = NULL; + init_table.ctf_frame_non_lazy_plt = NULL; + } + if (ABI_64_P (info->output_bfd)) { init_table.r_info = elf64_r_info; diff --git a/bfd/elflink.c b/bfd/elflink.c index 2b1450fa4e1..67bc6a32c9b 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -10899,6 +10899,7 @@ elf_section_ignore_discarded_relocs (asection *sec) case SEC_INFO_TYPE_STABS: case SEC_INFO_TYPE_EH_FRAME: case SEC_INFO_TYPE_EH_FRAME_ENTRY: + case SEC_INFO_TYPE_CTF_FRAME: return true; default: break; @@ -10930,6 +10931,9 @@ _bfd_elf_default_action_discarded (asection *sec) if (strcmp (".eh_frame", sec->name) == 0) return 0; + if (strcmp (".ctf_frame", sec->name) == 0) + return 0; + if (strcmp (".gcc_except_table", sec->name) == 0) return 0; @@ -11863,6 +11867,16 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) return false; } break; + case SEC_INFO_TYPE_CTF_FRAME: + { + /* Merge .ctf_frame sections into the ctf frame encoder + context of the output_bfd's section. The final .ctf_frame + output section will be written out later. */ + if (!_bfd_elf_merge_section_ctf_frame (output_bfd, flinfo->info, + o, contents)) + return false; + } + break; default: { if (! (o->flags & SEC_EXCLUDE)) @@ -13446,6 +13460,9 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (! _bfd_elf_write_section_eh_frame_hdr (abfd, info)) goto error_return; + if (! _bfd_elf_write_section_ctf_frame (abfd, info)) + goto error_return; + if (info->callbacks->emit_ctf) info->callbacks->emit_ctf (); @@ -14901,6 +14918,41 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) _bfd_elf_adjust_eh_frame_global_symbol, NULL); } + o = bfd_get_section_by_name (output_bfd, ".ctf_frame"); + if (o != NULL) + { + asection *i; + + for (i = o->map_head.s; i != NULL; i = i->map_head.s) + { + if (i->size == 0) + continue; + + abfd = i->owner; + if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) + continue; + + if (!init_reloc_cookie_for_section (&cookie, info, i)) + return -1; + + _bfd_elf_parse_ctf_frame (abfd, info, i, &cookie); + + if (_bfd_elf_discard_section_ctf_frame (abfd, info, i, + bfd_elf_reloc_symbol_deleted_p, + &cookie)) + { + if (i->size != i->rawsize) + changed = 1; + } + + fini_reloc_cookie_for_section (&cookie, i); + } + /* Update the reference to the output .ctf_frame section. Used to + determine later if PT_GNU_CTF_FRAME segment is to be generated. */ + if (!_bfd_elf_set_section_ctf_frame (output_bfd, info)) + return -1; + } + for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next) { const struct elf_backend_data *bed; diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c index 7fb972752b3..1ee2da5c413 100644 --- a/bfd/elfxx-x86.c +++ b/bfd/elfxx-x86.c @@ -1777,6 +1777,191 @@ elf_x86_relative_reloc_compare (const void *pa, const void *pb) return 0; } +enum dynobj_ctf_frame_plt_type +{ + CTF_FRAME_PLT = 1, + CTF_FRAME_PLT_SEC = 2 +}; + +/* Create CTF Frame unwind info for the plt entries in the .plt section + of type PLT_SEC_TYPE. */ + +static bool +_bfd_x86_elf_create_ctf_frame_plt (bfd *output_bfd, + struct bfd_link_info *info, + unsigned int plt_sec_type) +{ + struct elf_x86_link_hash_table *htab; + const struct elf_backend_data *bed; + + bool plt0_generated_p; + unsigned int plt0_entry_size; + unsigned char func_info; + unsigned int fre_type; + /* The dynamic plt section for which .ctf_frame unwind information is being + created. */ + asection *dpltsec; + + int err = 0; + + ctf_frame_encoder_ctx **ectx = NULL; + unsigned plt_entry_size = 0; + unsigned int num_pltn_fres = 0; + unsigned int num_pltn_entries = 0; + + bed = get_elf_backend_data (output_bfd); + htab = elf_x86_hash_table (info, bed->target_id); + /* Whether CTF Frame unwind info for plt0 is to be generated. */ + plt0_generated_p = htab->plt.has_plt0; + plt0_entry_size + = (plt0_generated_p) ? htab->ctf_frame_plt->plt0_entry_size : 0; + + switch (plt_sec_type) + { + case CTF_FRAME_PLT: + { + ectx = &htab->plt_cfe_ctx; + dpltsec = htab->elf.splt; + + plt_entry_size = htab->plt.plt_entry_size; + num_pltn_fres = htab->ctf_frame_plt->pltn_num_fres; + num_pltn_entries + = (htab->elf.splt->size - plt0_entry_size) / plt_entry_size; + + break; + } + case CTF_FRAME_PLT_SEC: + { + ectx = &htab->plt_second_cfe_ctx; + /* FIXME - this or htab->plt_second_ctf_frame ? */ + dpltsec = htab->plt_second_eh_frame; + + plt_entry_size = htab->ctf_frame_plt->sec_pltn_entry_size; + num_pltn_fres = htab->ctf_frame_plt->sec_pltn_num_fres; + num_pltn_entries + = htab->plt_second_eh_frame->size / plt_entry_size; + break; + } + default: + /* No other value is possible. */ + return false; + break; + } + + *ectx = ctf_frame_encode (CTF_FRAME_VERSION_1, + 0, + CTF_FRAME_ABI_AMD64_ENDIAN_LITTLE, + &err); + + /* FRE type is dependent on the size of the function. */ + fre_type = ctf_frame_calc_fre_type (dpltsec->size); + func_info = ctf_frame_fde_func_info (fre_type, + CTF_FRAME_FUNC_DESC_ENTRY_TYPE_PCINC); + + /* Add CTF FDE and the associated FREs for plt0 if plt0 has been + generated. */ + if (plt0_generated_p) + { + /* Add CTF FDE for plt0, the function start address is updated later + at _bfd_elf_merge_section_ctf_frame time. */ + ctf_frame_encoder_add_funcdesc (*ectx, + 0, /* func start addr. */ + plt0_entry_size, + func_info, + 0 /* Num FREs. */); + ctf_frame_row_entry plt0_fre; + unsigned int num_plt0_fres = htab->ctf_frame_plt->plt0_num_fres; + for (unsigned int j = 0; j < num_plt0_fres; j++) + { + plt0_fre = *(htab->ctf_frame_plt->plt0_fres[j]); + ctf_frame_encoder_add_fre (*ectx, 0, &plt0_fre); + } + } + + + if (num_pltn_entries) + { + /* pltn entries use a CTF FDE of type + CTF_FRAME_FUNC_DESC_ENTRY_TYPE_PCMASK to exploit the repetitive + pattern of the instructions in these entries. Using this CTF FDE + type helps in keeping the unwind information for pltn entries + compact. */ + func_info + = ctf_frame_fde_func_info (fre_type, + CTF_FRAME_FUNC_DESC_ENTRY_TYPE_PCMASK); + /* Add the CTF FDE for all PCs starting at the first pltn entry (hence, + function start address = plt0_entry_size. As usual, this will be + updated later at _bfd_elf_merge_section_ctf_frame, by when the + sections are relocated. */ + ctf_frame_encoder_add_funcdesc (*ectx, + plt0_entry_size, /* func start addr. */ + dpltsec->size - plt0_entry_size, + func_info, + 0 /* Num FREs. */); + + ctf_frame_row_entry pltn_fre; + /* Now add the FREs for pltn. Simply adding the two FREs suffices due + to the usage of CTF_FRAME_FUNC_DESC_ENTRY_TYPE_PCMASK above. */ + for (unsigned int j = 0; j < num_pltn_fres; j++) + { + pltn_fre = *(htab->ctf_frame_plt->pltn_fres[j]); + ctf_frame_encoder_add_fre (*ectx, 1, &pltn_fre); + } + } + + return true; +} + +/* Put contents of the .ctf_frame section corresponding to the specified + PLT_SEC_TYPE. */ + +static bool +_bfd_x86_elf_write_ctf_frame_plt (bfd *output_bfd, + struct bfd_link_info *info, + unsigned int plt_sec_type) +{ + struct elf_x86_link_hash_table *htab; + const struct elf_backend_data *bed; + ctf_frame_encoder_ctx *ectx; + bfd_size_type sec_size; + asection *sec; + bfd *dynobj; + + int err = 0; + + bed = get_elf_backend_data (output_bfd); + htab = elf_x86_hash_table (info, bed->target_id); + dynobj = htab->elf.dynobj; + + switch (plt_sec_type) + { + case CTF_FRAME_PLT: + ectx = htab->plt_cfe_ctx; + sec = htab->plt_ctf_frame; + break; + case CTF_FRAME_PLT_SEC: + ectx = htab->plt_second_cfe_ctx; + sec = htab->plt_second_ctf_frame; + break; + default: + /* No other value is possible. */ + return false; + break; + } + + BFD_ASSERT (ectx); + + void *contents = ctf_frame_write_encoder (ectx, &sec_size, &err); + + sec->size = sec_size; + sec->contents = (unsigned char *) bfd_zalloc (dynobj, sec->size); + memcpy (sec->contents, contents, sec_size); + + ctf_frame_encoder_free (&ectx); + + return true; +} + bool _bfd_elf_x86_size_relative_relocs (struct bfd_link_info *info, bool *need_layout) @@ -2267,6 +2452,42 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd, = htab->non_lazy_plt->eh_frame_plt_size; } + /* No need to size the .ctf_frame section explicitly because the write-out + mechanism is different. Simply prep up the FDE/FRE for the + .plt section. */ + if (_bfd_elf_ctf_frame_present (info)) + { + if (htab->plt_ctf_frame != NULL + && htab->elf.splt != NULL + && htab->elf.splt->size != 0 + && !bfd_is_abs_section (htab->elf.splt->output_section)) + { + _bfd_x86_elf_create_ctf_frame_plt (output_bfd, info, CTF_FRAME_PLT); + /* FIXME - Dirty Hack. Set the size to something non-zero for now, + so that the section does not get stripped out below. The precise + size of this section is known only when the contents are + serialized in _bfd_x86_elf_write_ctf_frame_plt. */ + htab->plt_ctf_frame->size = sizeof (ctf_frame_header) + 1; + } + + /* FIXME - generate for .got.plt ? */ + + /* Unwind info for the second PLT. */ + if (htab->plt_second_ctf_frame != NULL + && htab->plt_second != NULL + && htab->plt_second->size != 0 + && !bfd_is_abs_section (htab->plt_second->output_section)) + { + _bfd_x86_elf_create_ctf_frame_plt (output_bfd, info, + CTF_FRAME_PLT_SEC); + /* FIXME - Dirty Hack. Set the size to something non-zero for now, + so that the section does not get stripped out below. The precise + size of this section is known only when the contents are + serialized in _bfd_x86_elf_write_ctf_frame_plt. */ + htab->plt_second_ctf_frame->size = sizeof (ctf_frame_header) + 1; + } + } + /* We now have determined the sizes of the various dynamic sections. Allocate memory for them. */ relocs = false; @@ -2302,6 +2523,8 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd, || s == htab->plt_eh_frame || s == htab->plt_got_eh_frame || s == htab->plt_second_eh_frame + || s == htab->plt_ctf_frame + || s == htab->plt_second_ctf_frame || s == htab->elf.sdynbss || s == htab->elf.sdynrelro) { @@ -2344,6 +2567,11 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd, if ((s->flags & SEC_HAS_CONTENTS) == 0) continue; + /* Skip allocating contents for .ctf_frame section as it is written + out differently. See below. */ + if ((s == htab->plt_ctf_frame) || (s == htab->plt_second_ctf_frame)) + continue; + /* NB: Initially, the iplt section has minimal alignment to avoid moving dot of the following section backwards when it is empty. Update its section alignment now since it @@ -2393,6 +2621,21 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd, + PLT_FDE_LEN_OFFSET)); } + if (_bfd_elf_ctf_frame_present (info)) + { + if (htab->plt_ctf_frame != NULL + && htab->elf.splt != NULL + && htab->elf.splt->size != 0 + && htab->plt_ctf_frame->contents == NULL) + _bfd_x86_elf_write_ctf_frame_plt (output_bfd, info, CTF_FRAME_PLT); + + if (htab->plt_second_ctf_frame != NULL + && htab->elf.splt != NULL + && htab->elf.splt->size != 0 + && htab->plt_second_ctf_frame->contents == NULL) + _bfd_x86_elf_write_ctf_frame_plt (output_bfd, info, CTF_FRAME_PLT_SEC); + } + return _bfd_elf_maybe_vxworks_add_dynamic_tags (output_bfd, info, relocs); } @@ -2607,6 +2850,78 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd, } } + /* Make any adjustment if necessary and merge .ctf_frame section to + create the final .ctf_frame section for output_bfd. */ + if (htab->plt_ctf_frame != NULL + && htab->plt_ctf_frame->contents != NULL) + { + if (htab->elf.splt != NULL + && htab->elf.splt->size != 0 + && (htab->elf.splt->flags & SEC_EXCLUDE) == 0 + && htab->elf.splt->output_section != NULL + && htab->plt_ctf_frame->output_section != NULL) + { + bfd_vma plt_start = htab->elf.splt->output_section->vma; + bfd_vma ctf_frame_start = htab->plt_ctf_frame->output_section->vma + + htab->plt_ctf_frame->output_offset + + PLT_CTF_FRAME_FDE_START_OFFSET; +#if 0 /* FIXME Testing only. Remove before review. */ + bfd_vma test_value = (plt_start - ctf_frame_start) + + htab->plt_ctf_frame->output_section->vma + + htab->plt_ctf_frame->output_offset + + PLT_CTF_FRAME_FDE_START_OFFSET; + bfd_put_signed_32 (dynobj, test_value, +#endif + bfd_put_signed_32 (dynobj, plt_start - ctf_frame_start, + htab->plt_ctf_frame->contents + + PLT_CTF_FRAME_FDE_START_OFFSET); + } + if (htab->plt_ctf_frame->sec_info_type == SEC_INFO_TYPE_CTF_FRAME) + { + /* FIXME - contents need to be relocated for this call. Need to + reflect the relocated contents manually ? */ + if (! _bfd_elf_merge_section_ctf_frame (output_bfd, info, + htab->plt_ctf_frame, + htab->plt_ctf_frame->contents)) + return NULL; + } + } + + if (htab->plt_second_ctf_frame != NULL + && htab->plt_second_ctf_frame->contents != NULL) + { + if (htab->plt_second != NULL + && htab->plt_second->size != 0 + && (htab->plt_second->flags & SEC_EXCLUDE) == 0 + && htab->plt_second->output_section != NULL + && htab->plt_second_ctf_frame->output_section != NULL) + { + bfd_vma plt_start = htab->plt_second->output_section->vma; + bfd_vma ctf_frame_start + = (htab->plt_second_ctf_frame->output_section->vma + + htab->plt_second_ctf_frame->output_offset + + PLT_CTF_FRAME_FDE_START_OFFSET); +#if 0 /* FIXME Testing only. Remove before review. */ + bfd_vma test_value = (plt_start - ctf_frame_start) + + htab->plt_second_ctf_frame->output_section->vma + + htab->plt_second_ctf_frame->output_offset + + PLT_CTF_FRAME_FDE_START_OFFSET; + bfd_put_signed_32 (dynobj, test_value, +#endif + bfd_put_signed_32 (dynobj, plt_start - ctf_frame_start, + htab->plt_second_ctf_frame->contents + + PLT_CTF_FRAME_FDE_START_OFFSET); + } + if (htab->plt_second_ctf_frame->sec_info_type == SEC_INFO_TYPE_CTF_FRAME) + { + /* FIXME - contents need to be relocated for this call. Need to + reflect the relocated contents manually ? */ + if (! _bfd_elf_merge_section_ctf_frame (output_bfd, info, + htab->plt_second_ctf_frame, + htab->plt_second_ctf_frame->contents)) + return NULL; + } + } if (htab->elf.sgot && htab->elf.sgot->size > 0) elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = htab->got_entry_size; @@ -3949,12 +4264,36 @@ _bfd_x86_elf_link_setup_gnu_properties pltsec = htab->elf.splt; - /* If the non-lazy PLT is available, use it for all PLT entries if - there are no PLT0 or no .plt section. */ if (htab->non_lazy_plt != NULL && (!htab->plt.has_plt0 || pltsec == NULL)) + lazy_plt = false; + else + lazy_plt = true; + + if (normal_target) + { + if (use_ibt_plt) + { + if (lazy_plt) + htab->ctf_frame_plt = init_table->ctf_frame_lazy_ibt_plt; + else + htab->ctf_frame_plt = init_table->ctf_frame_non_lazy_ibt_plt; + } + else + { + if (lazy_plt) + htab->ctf_frame_plt = init_table->ctf_frame_lazy_plt; + else + htab->ctf_frame_plt = init_table->ctf_frame_non_lazy_plt; + } + } + else + htab->ctf_frame_plt = NULL; + + /* If the non-lazy PLT is available, use it for all PLT entries if + there are no PLT0 or no .plt section. */ + if (!lazy_plt) { - lazy_plt = false; if (bfd_link_pic (info)) htab->plt.plt_entry = htab->non_lazy_plt->pic_plt_entry; else @@ -3969,7 +4308,6 @@ _bfd_x86_elf_link_setup_gnu_properties } else { - lazy_plt = true; if (bfd_link_pic (info)) { htab->plt.plt0_entry = htab->lazy_plt->pic_plt0_entry; @@ -4145,6 +4483,39 @@ _bfd_x86_elf_link_setup_gnu_properties htab->plt_second_eh_frame = sec; } } + + /* .ctf_frame sections are emitted for AMD64 ABI only. */ + if (ABI_64_P (info->output_bfd) && !info->no_ld_generated_unwind_info) + { + flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY + | SEC_HAS_CONTENTS | SEC_IN_MEMORY + | SEC_LINKER_CREATED); + + sec = bfd_make_section_anyway_with_flags (dynobj, + ".ctf_frame", + flags); + if (sec == NULL) + info->callbacks->einfo (_("%F%P: failed to create PLT .ctf_frame section\n")); + + // FIXME check this + // if (!bfd_set_section_alignment (sec, class_align)) + // goto error_alignment; + + htab->plt_ctf_frame = sec; + + /* Second PLT is generated for Intel IBT / MPX Support + lazy plt. */ + if (htab->plt_second != NULL) + { + sec = bfd_make_section_anyway_with_flags (dynobj, + ".ctf_frame", + flags); + if (sec == NULL) + info->callbacks->einfo (_("%F%P: failed to create second PLT .ctf_frame section\n")); + + htab->plt_second_ctf_frame = sec; + } + /* FIXME - add later for plt_got. */ + } } /* The .iplt section is used for IFUNC symbols in static diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h index 7d23893938c..4ef118d8575 100644 --- a/bfd/elfxx-x86.h +++ b/bfd/elfxx-x86.h @@ -30,6 +30,7 @@ #include "elf-linker-x86.h" #include "elf/i386.h" #include "elf/x86-64.h" +#include "ctf-frame-api.h" #define X86_64_PCREL_TYPE_P(TYPE) \ ((TYPE) == R_X86_64_PC8 \ @@ -105,6 +106,8 @@ || (TYPE) == R_X86_64_PC32_BND \ || (TYPE) == R_X86_64_PC64) +#define PLT_CTF_FRAME_FDE_START_OFFSET sizeof (ctf_frame_header) + #define ABI_64_P(abfd) \ (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS64) @@ -388,6 +391,24 @@ struct elf_x86_link_hash_entry bfd_vma tlsdesc_got; }; +#define CTF_FRAME_PLT0_MAX_NUM_FRES 2 +#define CTF_FRAME_PLTN_MAX_NUM_FRES 2 + +struct elf_x86_ctf_frame_plt +{ + unsigned int plt0_entry_size; + unsigned int plt0_num_fres; + const ctf_frame_row_entry *plt0_fres[CTF_FRAME_PLT0_MAX_NUM_FRES]; + + unsigned int pltn_entry_size; + unsigned int pltn_num_fres; + const ctf_frame_row_entry *pltn_fres[CTF_FRAME_PLTN_MAX_NUM_FRES]; + + unsigned int sec_pltn_entry_size; + unsigned int sec_pltn_num_fres; + const ctf_frame_row_entry *sec_pltn_fres[CTF_FRAME_PLTN_MAX_NUM_FRES]; +}; + struct elf_x86_lazy_plt_layout { /* The first entry in a lazy procedure linkage table looks like this. */ @@ -584,6 +605,11 @@ struct elf_x86_link_hash_table asection *plt_got; asection *plt_got_eh_frame; + ctf_frame_encoder_ctx *plt_cfe_ctx; + asection *plt_ctf_frame; + ctf_frame_encoder_ctx *plt_second_cfe_ctx; + asection *plt_second_ctf_frame; + /* Parameters describing PLT generation, lazy or non-lazy. */ struct elf_x86_plt_layout plt; @@ -593,6 +619,10 @@ struct elf_x86_link_hash_table /* Parameters describing non-lazy PLT generation. */ const struct elf_x86_non_lazy_plt_layout *non_lazy_plt; + /* The .ctf_frame helper object for .plt section. + This is used for x86-64 only. */ + const struct elf_x86_ctf_frame_plt *ctf_frame_plt; + union { bfd_signed_vma refcount; @@ -682,6 +712,22 @@ struct elf_x86_init_table /* The non-lazy PLT layout for IBT. */ const struct elf_x86_non_lazy_plt_layout *non_lazy_ibt_plt; + /* The .ctf_frame helper object for lazy .plt section. + This is used for x86-64 only. */ + const struct elf_x86_ctf_frame_plt *ctf_frame_lazy_plt; + + /* The .ctf_frame helper object for non-lazy .plt section. + This is used for x86-64 only. */ + const struct elf_x86_ctf_frame_plt *ctf_frame_non_lazy_plt; + + /* The .ctf_frame helper object for lazy IBT .plt section. + This is used for x86-64 only. */ + const struct elf_x86_ctf_frame_plt *ctf_frame_lazy_ibt_plt; + + /* The .ctf_frame helper object for non-lazy IBT .plt section. + This is used for x86-64 only. */ + const struct elf_x86_ctf_frame_plt *ctf_frame_non_lazy_ibt_plt; + bfd_byte plt0_pad_byte; bfd_vma (*r_info) (bfd_vma, bfd_vma); diff --git a/bfd/section.c b/bfd/section.c index 5a487ce6c6f..fe65a22de57 100644 --- a/bfd/section.c +++ b/bfd/section.c @@ -408,6 +408,7 @@ CODE_FRAGMENT .#define SEC_INFO_TYPE_JUST_SYMS 4 .#define SEC_INFO_TYPE_TARGET 5 .#define SEC_INFO_TYPE_EH_FRAME_ENTRY 6 +.#define SEC_INFO_TYPE_CTF_FRAME 7 . . {* Nonzero if this section uses RELA relocations, rather than REL. *} . unsigned int use_rela_p:1; diff --git a/binutils/readelf.c b/binutils/readelf.c index 4a3e448e30d..f68147caea7 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -4648,6 +4648,7 @@ get_segment_type (Filedata * filedata, unsigned long p_type) case PT_GNU_STACK: return "GNU_STACK"; case PT_GNU_RELRO: return "GNU_RELRO"; case PT_GNU_PROPERTY: return "GNU_PROPERTY"; + case PT_GNU_CTF_FRAME: return "GNU_CTF_FRAME"; case PT_OPENBSD_RANDOMIZE: return "OPENBSD_RANDOMIZE"; case PT_OPENBSD_WXNEEDED: return "OPENBSD_WXNEEDED"; diff --git a/include/ctf-frame-api.h b/include/ctf-frame-api.h index 59c2abadf0e..c3a39ac0317 100644 --- a/include/ctf-frame-api.h +++ b/include/ctf-frame-api.h @@ -170,7 +170,7 @@ ctf_frame_encode (unsigned char ver, unsigned char flags, int abi, int *errp); /* Free the encoder context. */ extern void -ctf_free_encoder (ctf_frame_encoder_ctx *encoder); +ctf_frame_encoder_free (ctf_frame_encoder_ctx **encoder); /* Get the abi/arch info from the CTF Frame encoder context CTX. */ extern unsigned char diff --git a/include/elf/common.h b/include/elf/common.h index e4bc53e35b4..9dee53d7cd5 100644 --- a/include/elf/common.h +++ b/include/elf/common.h @@ -489,6 +489,7 @@ #define PT_GNU_STACK (PT_LOOS + 0x474e551) /* Stack flags */ #define PT_GNU_RELRO (PT_LOOS + 0x474e552) /* Read-only after relocation */ #define PT_GNU_PROPERTY (PT_LOOS + 0x474e553) /* GNU property */ +#define PT_GNU_CTF_FRAME (PT_LOOS + 0x474e554) /* CTF Frame unwind information */ /* OpenBSD segment types. */ #define PT_OPENBSD_RANDOMIZE (PT_LOOS + 0x5a3dbe6) /* Fill with random data. */ diff --git a/include/elf/internal.h b/include/elf/internal.h index 8affb3d9b2e..0988a66679f 100644 --- a/include/elf/internal.h +++ b/include/elf/internal.h @@ -339,6 +339,7 @@ struct elf_segment_map || (segment)->p_type == PT_GNU_EH_FRAME \ || (segment)->p_type == PT_GNU_STACK \ || (segment)->p_type == PT_GNU_RELRO \ + || (segment)->p_type == PT_GNU_CTF_FRAME \ || ((segment)->p_type >= PT_GNU_MBIND_LO \ && (segment)->p_type <= PT_GNU_MBIND_HI))) \ /* Any section besides one of type SHT_NOBITS must have file \ diff --git a/ld/Makefile.am b/ld/Makefile.am index d31021c13e2..502e754080a 100644 --- a/ld/Makefile.am +++ b/ld/Makefile.am @@ -967,6 +967,7 @@ EXTRA_ld_new_SOURCES += $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES) # This is the real libbfd.a and libctf.a created by libtool. TESTBFDLIB = @TESTBFDLIB@ TESTCTFLIB = @TESTCTFLIB@ +TESTCTFFRAMELIB = @TESTCTFFRAMELIB@ check-DEJAGNU: site.exp (cd .libs; test -e ldscripts || test ! -e ld-new || $(LN_S) ../ldscripts .) @@ -984,6 +985,7 @@ check-DEJAGNU: site.exp CXX_FOR_TARGET="$(CXX_FOR_TARGET)" \ CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" \ OFILES="$(OFILES)" BFDLIB="$(TESTBFDLIB)" CTFLIB="$(TESTCTFLIB) $(ZLIB)" \ + CTFFRAMELIB="$(TESTCTFFRAMELIB)" \ LIBIBERTY="$(LIBIBERTY) $(LIBINTL)" LIBS="$(LIBS)" \ DO_COMPARE="`echo '$(do_compare)' | sed -e 's,\\$$,,g'`" \ $(RUNTESTFLAGS); \ diff --git a/ld/Makefile.in b/ld/Makefile.in index ee0c98f65b0..65f9856aa52 100644 --- a/ld/Makefile.in +++ b/ld/Makefile.in @@ -468,6 +468,7 @@ TARGET_SYSTEM_ROOT_DEFINE = @TARGET_SYSTEM_ROOT_DEFINE@ # This is the real libbfd.a and libctf.a created by libtool. TESTBFDLIB = @TESTBFDLIB@ +TESTCTFFRAMELIB = @TESTCTFFRAMELIB@ TESTCTFLIB = @TESTCTFLIB@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ @@ -2631,6 +2632,7 @@ check-DEJAGNU: site.exp CXX_FOR_TARGET="$(CXX_FOR_TARGET)" \ CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" \ OFILES="$(OFILES)" BFDLIB="$(TESTBFDLIB)" CTFLIB="$(TESTCTFLIB) $(ZLIB)" \ + CTFFRAMELIB="$(TESTCTFFRAMELIB)" \ LIBIBERTY="$(LIBIBERTY) $(LIBINTL)" LIBS="$(LIBS)" \ DO_COMPARE="`echo '$(do_compare)' | sed -e 's,\\$$,,g'`" \ $(RUNTESTFLAGS); \ diff --git a/ld/configure b/ld/configure index 1c2b64870b1..4048d006852 100755 --- a/ld/configure +++ b/ld/configure @@ -634,6 +634,7 @@ ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS +TESTCTFFRAMELIB TESTCTFLIB TESTBFDLIB EMULATION_LIBPATH @@ -11491,7 +11492,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11494 "configure" +#line 11495 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11597,7 +11598,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11600 "configure" +#line 11601 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -17331,9 +17332,11 @@ EMULATION_LIBPATH=$all_libpath if test x${enable_static} = xno; then TESTBFDLIB="-Wl,--rpath,../bfd/.libs ../bfd/.libs/libbfd.so" TESTCTFLIB="-Wl,--rpath,../libctf/.libs ../libctf/.libs/libctf.so" + TESTCTFFRAMELIB="-Wl,--rpath,../libctfframe/.libs ../libctfframe/.libs/libctfframe.so" else TESTBFDLIB="../bfd/.libs/libbfd.a" TESTCTFLIB="../libctf/.libs/libctf.a" + TESTCTFFRAMELIB="../libctfframe/.libs/libctfframe.a" fi if test "${enable_libctf}" = no; then TESTCTFLIB= @@ -17341,6 +17344,7 @@ fi + target_vendor=${target_vendor=$host_vendor} case "$target_vendor" in hp) EXTRA_SHLIB_EXTENSION=".sl" ;; diff --git a/ld/configure.ac b/ld/configure.ac index eb55904c090..9ac5d75d6ad 100644 --- a/ld/configure.ac +++ b/ld/configure.ac @@ -623,15 +623,18 @@ AC_SUBST(EMULATION_LIBPATH) if test x${enable_static} = xno; then TESTBFDLIB="-Wl,--rpath,../bfd/.libs ../bfd/.libs/libbfd.so" TESTCTFLIB="-Wl,--rpath,../libctf/.libs ../libctf/.libs/libctf.so" + TESTCTFFRAMELIB="-Wl,--rpath,../libctfframe/.libs ../libctfframe/.libs/libctfframe.so" else TESTBFDLIB="../bfd/.libs/libbfd.a" TESTCTFLIB="../libctf/.libs/libctf.a" + TESTCTFFRAMELIB="../libctfframe/.libs/libctfframe.a" fi if test "${enable_libctf}" = no; then TESTCTFLIB= fi AC_SUBST(TESTBFDLIB) AC_SUBST(TESTCTFLIB) +AC_SUBST(TESTCTFFRAMELIB) target_vendor=${target_vendor=$host_vendor} case "$target_vendor" in diff --git a/ld/ld.texi b/ld/ld.texi index eabbec8faa9..bb349de3416 100644 --- a/ld/ld.texi +++ b/ld/ld.texi @@ -2828,7 +2828,9 @@ section and ELF @code{PT_GNU_EH_FRAME} segment header. @item --no-ld-generated-unwind-info Request creation of @code{.eh_frame} unwind info for linker generated code sections like PLT. This option is on by default -if linker generated unwind info is supported. +if linker generated unwind info is supported. This option also +controls the generation of @code{.ctf_frame} unwind info for linker +generated code sections like PLT. @kindex --enable-new-dtags @kindex --disable-new-dtags diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc index bf2268bb0ad..d8625d911a7 100644 --- a/ld/scripttempl/elf.sc +++ b/ld/scripttempl/elf.sc @@ -601,6 +601,7 @@ cat <cfe_funcdesc); - free (encoder->cfe_fres); - free (encoder->cfe_data); - free (encoder); + ctf_frame_encoder_ctx *ectx = *encoder; + if (ectx == NULL) + return; + + if (ectx->cfe_funcdesc != NULL) + { + free (ectx->cfe_funcdesc); + ectx->cfe_funcdesc = NULL; + } + if (ectx->cfe_fres != NULL) + { + free (ectx->cfe_fres); + ectx->cfe_fres = NULL; + } + if (ectx->cfe_data != NULL) + { + free (ectx->cfe_data); + ectx->cfe_data = NULL; + } + + free (*encoder); + *encoder = NULL; } } -- 2.37.1