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 DC361385041B for ; Tue, 14 Jun 2022 07:07:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org DC361385041B Received: from pps.filterd (m0246631.ppops.net [127.0.0.1]) by mx0b-00069f02.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 25E71qXQ004110 for ; Tue, 14 Jun 2022 07:07:20 GMT Received: from iadpaimrmta01.imrmtpd1.prodappiadaev1.oraclevcn.com (iadpaimrmta01.appoci.oracle.com [130.35.100.223]) by mx0b-00069f02.pphosted.com (PPS) with ESMTPS id 3gmhu2n1kk-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Tue, 14 Jun 2022 07:07:20 +0000 Received: from pps.filterd (iadpaimrmta01.imrmtpd1.prodappiadaev1.oraclevcn.com [127.0.0.1]) by iadpaimrmta01.imrmtpd1.prodappiadaev1.oraclevcn.com (8.16.1.2/8.16.1.2) with SMTP id 25E768iY020197 for ; Tue, 14 Jun 2022 07:07:19 GMT Received: from nam02-bn1-obe.outbound.protection.outlook.com (mail-bn1nam07lp2046.outbound.protection.outlook.com [104.47.51.46]) by iadpaimrmta01.imrmtpd1.prodappiadaev1.oraclevcn.com with ESMTP id 3gpn2ms03t-3 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Tue, 14 Jun 2022 07:07:19 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=lR1loYRLITJ5HVYcwqTPCToBC1LFN/1PpbjBmrUYJyExgiLE5KNXh6J3TQvwnZyCuWkoaRQ77m5REm5o2d2WjDyB+MPWIiqWWsXepMaYjrOwfbnDElVwEOkrAmKsuXc8b8wlNDKoOdf2IZ7pv2ORaWH5LoxUhW4XLoqD60bo7c5BMqBzy6epXrwgkT26LfMPv0Rt8LQ85gQatPBYB5k63Ok4Cp1NJgSCmNOBVmbxihuiTWBXvooH1/7TU716mA4vp+Pvf5wExv4u5iWlJPqM9ES7qiDaz04IavcgAdIbHYgf94TjCSrI7JvNxf6w+h5vYRTEs4HtsvdM6kl6LCKNWA== 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=xQGB+H6BP3Wgvw74F3CNn6F9UUmlUO3KMLQQhiwP78o=; b=gidJ1jEiVTqdrmulHR3j1Wip6Xxy6Sv3YIqIXlsEyJmom0f241akxlU5UdJpCK3cujUkeOAI/mfX2Xr1TR7KYYsb57xRXKhPTYChSpPy5GaHuPPbDTFqfnCKooWAAniiZKahSRYjKyIwbFqT5XW4CDM4vqFQkpqh6Q67XmaYV+dJq5A87ey0klzjFSQtVsAfaL/4Tg9FEWEnRElOjXFqeWlZlzPFX2LNJ+4ttmLvq8cSAn3JXVMyFMwYPTdMyLjVFgeDO1FaQz3WYqssoHmQWVvj/FiumrqzfFsdrhYaFzlluRz+cN1vQyPiKYZzRYdE7sm03bHa8wlFo+/0bqCHFg== 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 DM5PR1001MB2091.namprd10.prod.outlook.com (2603:10b6:4:2c::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5332.20; Tue, 14 Jun 2022 07:07:17 +0000 Received: from MWHPR1001MB2158.namprd10.prod.outlook.com ([fe80::8862:60b0:854d:7251]) by MWHPR1001MB2158.namprd10.prod.outlook.com ([fe80::8862:60b0:854d:7251%6]) with mapi id 15.20.5332.020; Tue, 14 Jun 2022 07:07:17 +0000 From: Indu Bhagat To: binutils@sourceware.org Subject: [PATCH, RFC, V3 7/8] unwinder: generate backtrace using CTF Frame format Date: Tue, 14 Jun 2022 00:06:51 -0700 Message-Id: <20220614070652.1608873-8-indu.bhagat@oracle.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220614070652.1608873-1-indu.bhagat@oracle.com> References: <20220614070652.1608873-1-indu.bhagat@oracle.com> Content-Transfer-Encoding: quoted-printable Content-Type: text/plain X-ClientProxiedBy: MW4PR04CA0370.namprd04.prod.outlook.com (2603:10b6:303:81::15) 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: 91638523-9b72-4f85-770b-08da4dd48362 X-MS-TrafficTypeDiagnostic: DM5PR1001MB2091:EE_ X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: Ygk6nu9WLJN6uK3ifnLKebbMs0PkEX/Hj03oFfdA/654giNOhX8vYqM9r8Bu1O3rXlQmyjn4ewyrGUoHBGgcyteLVdEdbUpi+FIV1sRYfbWqjyAqRFGN7GUkPti2ml7iuTwCEnet+uOzJHVmZUjYCYrsKZqinxcLwK3hQ8Hk242AA/AK4mKFa1MTkWG0+stJMCcvmxV9WEAdoVPFkJ+K0wksVZEVtJpNqD0RjxvxTH9d0WmbVr4w8AK0A1/RhPE2htFX2x23boiA4y9U629kznsIwFIVWZc+wtyLK+96rWhXCKPeXfvo8IL5vTC2FSV2S52FGoT90S5CG1V2pCwjASXm0ypIdQ7O2n4/VNBt1MavMKCho9MiO24OdJWZ8sXcOpJaVa1+DA7L+AyCjiG2QoBXGTUn0Pv4pWRCzOGq7r7LK6/t3jOVaH662GypgLIsnvyIABGe1DN3c7+3DpmrKfXzT5QzuQR8gtK1EPVbzJqGPwiXiZ5+hCIyO4kvt5eqnquNQda9LX6t2Or+9rK1JZ8yjYq0jWz0fjgvYw1FBucSukAvakxBpZGyWT9062XmMJ4+NEBFPOEK9bEl9s7iGuNPDULYW7Lq6OjDs1RZJxoj2VULWEKYw0XONL0/RFdcdQWDj9LmeucjTh+CcxlLSzExvCS8wH2IgGOKDteMyNL7rvF6x+iqCGi1YOhiYNWB7+lC7QQPGWerggDcRNMbFit6unC/OSShkIoXF6lR5xs3E4pZ1/qSr0i1GTdXSv7PiVdkoLUu4ZXZIkemhbUI0LuBVw7fWotggLQXhblGHsinL60SCywh+NlhwMAXc6ME 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)(366004)(6506007)(38100700002)(26005)(6666004)(6512007)(66946007)(66476007)(6916009)(316002)(38350700002)(36756003)(83380400001)(6486002)(8936002)(8676002)(66556008)(508600001)(30864003)(44832011)(5660300002)(1076003)(2616005)(52116002)(186003)(2906002)(86362001)(2004002); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?yX4+SFxUaH+d6lKIVCdz6sYb7klubf2kTjUtyZquq8eXLLizykZDSocWZuoO?= =?us-ascii?Q?KkC9aPWmWx+lpIBspicTbwaEzQM3SrDgqgl6mSO+6V5tVC/g2W/biMY52DAv?= =?us-ascii?Q?Tis4g++d2HGtqXUO+6qxyEWZ/EUy3wN/eh/cw3GVeBeVYuY1/wuLplDnce+y?= =?us-ascii?Q?Q+oSDz2jcnF37rPNaK4DLrdegU1bshLgTYWDw3sYHGYHF1PJ4r3z9tOLHKVh?= =?us-ascii?Q?FqYBSTvon/LnH2gkRpvz3GQ36srIKD0ePez+8Bwrm8kCDUhjr7prcixEItyr?= =?us-ascii?Q?LpXXnH1sl+u9xgyj4BbJNZb/BI+0xlgcnqJyvO+zgqTxFPCUdyJ8saHgxEKT?= =?us-ascii?Q?gKq7+43OswtdIpdpWmAxN84jqNggjjG9be3FdjlwdkIjI54otKJlxQLx5Cju?= =?us-ascii?Q?j3j8SLtRxmc1kaXLIaMxdP0uj8rvggOq5r9O2oHOGS0M71y51J7SFTKGp1HJ?= =?us-ascii?Q?gztyf04yuMzh2x8/8G5uOkjMaAGFdopIO9ApkI2me+p2XVCGz8MGUlimtsd6?= =?us-ascii?Q?6NU6pJ1pJ61oLx4zk3NrBcHgvFqzr022HlUccSabxJhAhHZ9OqmIih1+ogv1?= =?us-ascii?Q?8AA1wdvePcL3eYWph2av5vgF3DHUhgR/F8CCWH8ITCmNsrvIcS6/sWYgCo4p?= =?us-ascii?Q?iolvwkQWvD4xBeGZ+AM6Pi6CCxH4qauvo6o8E+lN8o539IiZy9GSXhskXGpB?= =?us-ascii?Q?vESEjWeTcJFNiV6UiAcs3PTAARJIy7PFDj9TZC63FSq53XECv4AMOPTn2Xlk?= =?us-ascii?Q?zwVEbFl7DmvFNmGcEKr011bNBR5CmHjQC+YjeWm5GqBTyazKsVecSYop84AG?= =?us-ascii?Q?QRtSL9wUAjaV6zt+iDrwsWCyiTfX/QBKSy8dd6HGxeLR7A1DGVCO2akML77b?= =?us-ascii?Q?Ocucjfr9m/Ud9czGk92hkyPtenIzBqU4pO9yZp4tjDQg45LOJKSQKLPSSx5N?= =?us-ascii?Q?RVX0l9avf4r9Ju0IBxdb2L16SNk3jrErQamy0bt5iQiCYggrpikW7eIvV9cH?= =?us-ascii?Q?dWPaKQhx+wsDzX+9lgqidBQmDhwW1/xEbgFGRsCkAt9QWrgrgOBmmnNZoX8I?= =?us-ascii?Q?v1fuyPyl5eD+aIH4CJmHmANtXP0GObf8yAA1CsmfAaFQeWbMiN4BlxUTFjqM?= =?us-ascii?Q?kJImRDj6ylAW36JeSfHPjCE/rMkzLsHGT7aCKnCRedfnCSbAFGcv0k63SP/N?= =?us-ascii?Q?Bz/Vr6Opkw1+F7pRrzTFG5RyXG0k1fANvwLp362MChbwrD6kF0dZbV+tW2U4?= =?us-ascii?Q?bPC7SKmn2vnnOVYFC4d8k7p9bZ/bq7zb1Y6Axczwvqmje8lrADanIH8SNBXr?= =?us-ascii?Q?w7uRr/OoVzRfpr33as92F28t9DUY1+PIwfoi4N6Nw3vlanTnEis8CY2WG72g?= =?us-ascii?Q?U0jgSAhTrQ5w7eep5odiN0i4eFiBkJuNUUzSqLzJ/IvfCPdRL0fZddolfJH5?= =?us-ascii?Q?p7DMl13jb/tHMbVuuwIHY35wtsLemKLaKhNB0dRTdEy3z1yvyU0qVuDhNeMh?= =?us-ascii?Q?xwMw5IhU+zMVFBmN73lA8i2S6ZLoQ2pVxbFMSOxlXgdCh4ULAfPHwbrc93oq?= =?us-ascii?Q?HoiA0SvnZXUWvNGacZH//J0ONQ8ul8XpZ3zIxW5ig5TAi6HIIgPWH/ACpXxz?= =?us-ascii?Q?tX4Hq81z+Ft3LrtIqfxZXNpIJ4TIlX8qxdmjMidI8MEzvGTrhZglFoQAdVnb?= =?us-ascii?Q?85yCjVCS/8xu4MRQLmuaZjgQmaIZu2cw2Gn9jflPA8G14cxNAzQ1RsAyHQW8?= =?us-ascii?Q?jh6cXLj5czkj6UTp/JzWNWJ3RWKtHvI=3D?= X-OriginatorOrg: oracle.com X-MS-Exchange-CrossTenant-Network-Message-Id: 91638523-9b72-4f85-770b-08da4dd48362 X-MS-Exchange-CrossTenant-AuthSource: MWHPR1001MB2158.namprd10.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 14 Jun 2022 07:07:16.1363 (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: UgpWNyd1sc6mbC7x6hEg/NCJw2ryy1usrKayjLAMticZXQqRccpJ5kHjc8KiwNb5nTvdLZSB+XFCXN7qmHNxnA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR1001MB2091 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.517, 18.0.874 definitions=2022-06-14_02:2022-06-13, 2022-06-14 signatures=0 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 spamscore=0 bulkscore=0 malwarescore=0 mlxscore=0 suspectscore=0 adultscore=0 mlxlogscore=999 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2204290000 definitions=main-2206140027 X-Proofpoint-GUID: gqqG9zC6NTLzwCAo3FiQW9ovZExQI9st X-Proofpoint-ORIG-GUID: gqqG9zC6NTLzwCAo3FiQW9ovZExQI9st X-Spam-Status: No, score=-13.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE 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, 14 Jun 2022 07:07:26 -0000 From: Weimin Pan [Changes from V2] - consistent use of terminology around CTF Frame and its components. [End of changes from V2] [Changes from V1] - buildsystem: changes have been made to build libctfbacktrace only when --gctf-frame support is available in the assembler. These buildsystem changes are necessary because the CTF Frame based unwinder needs the CTF Frame unwind info for itself to work. [End of changes from V1] A simple unwinder based on CTF Frame format. PS: libctfframe/configure has NOT been included in the patch. Please regenerate. config/ChangeLog: * ctf-frame.m4: New file. include/ChangeLog: * ctf-backtrace-api.h: New file. ChangeLog: * libctfframe/Makefile.am: Build backtrace functionality in its own library. Install libctfbacktrace conditionally. * libctfframe/Makefile.in: Regenerate. * libctfframe/aclocal.m4: Regenerate. * libctfframe/configure: Regenerate. <-- [REMOVED FROM THE PATCH. PLEASE REGENERATE. ] * libctfframe/configure.ac: Check if gas supports --gctf-frame command line option. * libctfframe/ctf-backtrace-err.c: New file. * libctfframe/ctf-backtrace.c: New file. * libctfframe/ttest.c: New file. --- config/ctf-frame.m4 | 16 + include/ctf-backtrace-api.h | 57 +++ libctfframe/Makefile.am | 14 +- libctfframe/Makefile.in | 69 +++- libctfframe/aclocal.m4 | 1 + libctfframe/configure.ac | 7 + libctfframe/ctf-backtrace-err.c | 46 +++ libctfframe/ctf-backtrace.c | 617 ++++++++++++++++++++++++++++++++ libctfframe/ttest.c | 78 ++++ 9 files changed, 889 insertions(+), 16 deletions(-) create mode 100644 config/ctf-frame.m4 create mode 100644 include/ctf-backtrace-api.h create mode 100644 libctfframe/ctf-backtrace-err.c create mode 100644 libctfframe/ctf-backtrace.c create mode 100644 libctfframe/ttest.c diff --git a/config/ctf-frame.m4 b/config/ctf-frame.m4 new file mode 100644 index 00000000000..100840b805f --- /dev/null +++ b/config/ctf-frame.m4 @@ -0,0 +1,16 @@ +# CTF_CHECK_AS_CTF_FRAME +# ---------------------- +# Check whether the assembler supports generation of CTF Frame +# unwind information. +# +# Defines: +# ac_cv_have_ctfframe + +AC_DEFUN([CTF_CHECK_AS_CTF_FRAME],[ + ac_save_CFLAGS=3D"$CFLAGS" + CFLAGS=3D"$CFLAGS -Wa,--gctf-frame" + AC_MSG_CHECKING([for as that supports --gctf-frame]) + AC_TRY_COMPILE([], [return 0;], [ac_cv_have_ctfframe=3Dyes], [ac_cv_have= _ctfframe=3Dno]) + AC_MSG_RESULT($ac_cv_have_ctfframe) + CFLAGS=3D"$ac_save_CFLAGS" +]) diff --git a/include/ctf-backtrace-api.h b/include/ctf-backtrace-api.h new file mode 100644 index 00000000000..7b3463d88a3 --- /dev/null +++ b/include/ctf-backtrace-api.h @@ -0,0 +1,57 @@ +/* Public API to CTF backtrace.=0D +=0D + Copyright (C) 2022 Free Software Foundation, Inc.=0D +=0D + This file is part of xxxxxx. (FIXME)=0D +=0D + This program is free software; you can redistribute it and/or modify=0D + it under the terms of the GNU General Public License as published by=0D + the Free Software Foundation; either version 3 of the License, or=0D + (at your option) any later version.=0D +=0D + This program is distributed in the hope that it will be useful,=0D + but WITHOUT ANY WARRANTY; without even the implied warranty of=0D + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the=0D + GNU General Public License for more details.=0D +=0D + You should have received a copy of the GNU General Public License=0D + along with this program. If not, see . = */=0D +=0D +#ifndef _CTF_BACKTRACE_API_H=0D +#define _CTF_BACKTRACE_API_H=0D +=0D +#ifdef __cplusplus=0D +extern "C"=0D +{=0D +#endif=0D +=0D +enum ctf_bt_errcode=0D +{=0D + CTF_BT_OK,=0D + CTF_BT_ERR_NOCTF,=0D + CTF_BT_ERR_PHDR,=0D + CTF_BT_ERR_ARG,=0D + CTF_BT_ERR_MALLOC,=0D + CTF_BT_ERR_REALLOC,=0D + CTF_BT_ERR_OPEN,=0D + CTF_BT_ERR_READLINK,=0D + CTF_BT_ERR_LSEEK,=0D + CTF_BT_ERR_READ,=0D + CTF_BT_ERR_GETCONTEXT,=0D + CTF_BT_ERR_DECODE,=0D + CTF_BT_ERR_CFA_OFFSET,=0D +};=0D +=0D +/* Get the backtrace of the calling program by storing return addresses=0D + in BUFFER. The SIZE argument specifies the maximum number of addresses= =0D + that can be stored in the buffer. Return the number of return addresses= =0D + collected or -1 if there is any error. */=0D +extern int ctf_backtrace (void **buffer, int size, int *errp);=0D +=0D +extern const char *ctf_bt_errmsg (enum ctf_bt_errcode ecode);=0D +=0D +#ifdef __cplusplus=0D +}=0D +#endif=0D +=0D +#endif /* _CTF_BACKTRACE_API_H */=0D diff --git a/libctfframe/Makefile.am b/libctfframe/Makefile.am index 712b5b8e773..f745b24dce1 100644 --- a/libctfframe/Makefile.am +++ b/libctfframe/Makefile.am @@ -23,8 +23,6 @@ AUTOMAKE_OPTIONS =3D dejagnu foreign no-texinfo.tex =20 BASEDIR =3D $(srcdir)/.. INCDIR =3D $(srcdir)/../include -# include libctf for swap.h -AM_CPPFLAGS =3D -D_GNU_SOURCE -I$(srcdir) -I$(srcdir)/../include -I$(srcdi= r)/../libctf AM_CFLAGS =3D -std=3Dgnu99 @ac_libctfframe_warn_cflags@ @warn@ @c_warn@ @W= ARN_PEDANTIC@ @WERROR@ =20 if INSTALL_LIBBFD @@ -39,6 +37,18 @@ libctfframe_la_SOURCES =3D ctf-frame.c ctf-frame-dump.c = ctf-frame-error.c libctfframe_la_CPPFLAGS =3D -D_GNU_SOURCE -I$(srcdir) -I$(srcdir)/../inclu= de \ -I$(srcdir)/../libctf =20 +if HAVE_CTF_FRAME_AS + libctfbacktrace_la_SOURCES =3D ctf-backtrace.c ctf-backtrace-err.c + libctfbacktrace_la_CPPFLAGS =3D -I$(srcdir) -I$(srcdir)/../include + libctfbacktrace_la_CFLAGS =3D -Wa,--gctf-frame +if INSTALL_LIBBFD + lib_LTLIBRARIES +=3D libctfbacktrace.la + include_HEADERS +=3D $(INCDIR)/ctf-backtrace-api.h +else + noinst_LTLIBRARIES +=3D libctfbacktrace.la +endif +endif + # Setup the testing framework EXPECT =3D expect RUNTEST =3D runtest diff --git a/libctfframe/Makefile.in b/libctfframe/Makefile.in index 2fe55ad39d4..cbf014412cd 100644 --- a/libctfframe/Makefile.in +++ b/libctfframe/Makefile.in @@ -107,10 +107,14 @@ PRE_UNINSTALL =3D : POST_UNINSTALL =3D : build_triplet =3D @build@ host_triplet =3D @host@ +@HAVE_CTF_FRAME_AS_TRUE@@INSTALL_LIBBFD_TRUE@am__append_1 =3D libctfbacktr= ace.la +@HAVE_CTF_FRAME_AS_TRUE@@INSTALL_LIBBFD_TRUE@am__append_2 =3D $(INCDIR)/ct= f-backtrace-api.h +@HAVE_CTF_FRAME_AS_TRUE@@INSTALL_LIBBFD_FALSE@am__append_3 =3D libctfbackt= race.la subdir =3D . ACLOCAL_M4 =3D $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps =3D $(top_srcdir)/../bfd/acinclude.m4 \ $(top_srcdir)/../config/acx.m4 \ + $(top_srcdir)/../config/ctf-frame.m4 \ $(top_srcdir)/../config/depstand.m4 \ $(top_srcdir)/../config/jobserver.m4 \ $(top_srcdir)/../config/lead-dot.m4 \ @@ -159,15 +163,29 @@ am__uninstall_files_from_dir =3D { \ } am__installdirs =3D "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)" LTLIBRARIES =3D $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) +libctfbacktrace_la_LIBADD =3D +am__libctfbacktrace_la_SOURCES_DIST =3D ctf-backtrace.c \ + ctf-backtrace-err.c +@HAVE_CTF_FRAME_AS_TRUE@am_libctfbacktrace_la_OBJECTS =3D \ +@HAVE_CTF_FRAME_AS_TRUE@ libctfbacktrace_la-ctf-backtrace.lo \ +@HAVE_CTF_FRAME_AS_TRUE@ libctfbacktrace_la-ctf-backtrace-err.lo +libctfbacktrace_la_OBJECTS =3D $(am_libctfbacktrace_la_OBJECTS) +AM_V_lt =3D $(am__v_lt_@AM_V@) +am__v_lt_ =3D $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 =3D --silent +am__v_lt_1 =3D=20 +libctfbacktrace_la_LINK =3D $(LIBTOOL) $(AM_V_lt) --tag=3DCC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=3Dlink $(CCLD) \ + $(libctfbacktrace_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +@HAVE_CTF_FRAME_AS_TRUE@@INSTALL_LIBBFD_FALSE@am_libctfbacktrace_la_rpath = =3D +@HAVE_CTF_FRAME_AS_TRUE@@INSTALL_LIBBFD_TRUE@am_libctfbacktrace_la_rpath = =3D \ +@HAVE_CTF_FRAME_AS_TRUE@@INSTALL_LIBBFD_TRUE@ -rpath $(libdir) libctfframe_la_LIBADD =3D am_libctfframe_la_OBJECTS =3D libctfframe_la-ctf-frame.lo \ libctfframe_la-ctf-frame-dump.lo \ libctfframe_la-ctf-frame-error.lo libctfframe_la_OBJECTS =3D $(am_libctfframe_la_OBJECTS) -AM_V_lt =3D $(am__v_lt_@AM_V@) -am__v_lt_ =3D $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 =3D --silent -am__v_lt_1 =3D=20 @INSTALL_LIBBFD_FALSE@am_libctfframe_la_rpath =3D @INSTALL_LIBBFD_TRUE@am_libctfframe_la_rpath =3D -rpath $(libdir) AM_V_P =3D $(am__v_P_@AM_V@) @@ -204,15 +222,16 @@ AM_V_CCLD =3D $(am__v_CCLD_@AM_V@) am__v_CCLD_ =3D $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 =3D @echo " CCLD " $@; am__v_CCLD_1 =3D=20 -SOURCES =3D $(libctfframe_la_SOURCES) -DIST_SOURCES =3D $(libctfframe_la_SOURCES) +SOURCES =3D $(libctfbacktrace_la_SOURCES) $(libctfframe_la_SOURCES) +DIST_SOURCES =3D $(am__libctfbacktrace_la_SOURCES_DIST) \ + $(libctfframe_la_SOURCES) am__can_run_installinfo =3D \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac -am__include_HEADERS_DIST =3D $(INCDIR)/ctf-frame.h \ - $(INCDIR)/ctf-frame-api.h +am__include_HEADERS_DIST =3D $(INCDIR)/ctf-backtrace-api.h \ + $(INCDIR)/ctf-frame.h $(INCDIR)/ctf-frame-api.h HEADERS =3D $(include_HEADERS) am__tagged_files =3D $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)config.h.in @@ -385,17 +404,20 @@ ACLOCAL_AMFLAGS =3D -I .. -I ../config AUTOMAKE_OPTIONS =3D dejagnu foreign no-texinfo.tex BASEDIR =3D $(srcdir)/.. INCDIR =3D $(srcdir)/../include -# include libctf for swap.h -AM_CPPFLAGS =3D -D_GNU_SOURCE -I$(srcdir) -I$(srcdir)/../include -I$(srcdi= r)/../libctf AM_CFLAGS =3D -std=3Dgnu99 @ac_libctfframe_warn_cflags@ @warn@ @c_warn@ @W= ARN_PEDANTIC@ @WERROR@ -@INSTALL_LIBBFD_TRUE@lib_LTLIBRARIES =3D libctfframe.la -@INSTALL_LIBBFD_FALSE@include_HEADERS =3D=20 -@INSTALL_LIBBFD_TRUE@include_HEADERS =3D $(INCDIR)/ctf-frame.h $(INCDIR)/c= tf-frame-api.h -@INSTALL_LIBBFD_FALSE@noinst_LTLIBRARIES =3D libctfframe.la +@INSTALL_LIBBFD_TRUE@lib_LTLIBRARIES =3D libctfframe.la $(am__append_1) +@INSTALL_LIBBFD_FALSE@include_HEADERS =3D $(am__append_2) +@INSTALL_LIBBFD_TRUE@include_HEADERS =3D $(INCDIR)/ctf-frame.h \ +@INSTALL_LIBBFD_TRUE@ $(INCDIR)/ctf-frame-api.h $(am__append_2) +@INSTALL_LIBBFD_FALSE@noinst_LTLIBRARIES =3D libctfframe.la \ +@INSTALL_LIBBFD_FALSE@ $(am__append_3) libctfframe_la_SOURCES =3D ctf-frame.c ctf-frame-dump.c ctf-frame-error.c libctfframe_la_CPPFLAGS =3D -D_GNU_SOURCE -I$(srcdir) -I$(srcdir)/../inclu= de \ -I$(srcdir)/../libctf =20 +@HAVE_CTF_FRAME_AS_TRUE@libctfbacktrace_la_SOURCES =3D ctf-backtrace.c ctf= -backtrace-err.c +@HAVE_CTF_FRAME_AS_TRUE@libctfbacktrace_la_CPPFLAGS =3D -I$(srcdir) -I$(sr= cdir)/../include +@HAVE_CTF_FRAME_AS_TRUE@libctfbacktrace_la_CFLAGS =3D -Wa,--gctf-frame =20 # Setup the testing framework EXPECT =3D expect @@ -516,6 +538,9 @@ clean-noinstLTLIBRARIES: rm -f $${locs}; \ } =20 +libctfbacktrace.la: $(libctfbacktrace_la_OBJECTS) $(libctfbacktrace_la_DEP= ENDENCIES) $(EXTRA_libctfbacktrace_la_DEPENDENCIES)=20 + $(AM_V_CCLD)$(libctfbacktrace_la_LINK) $(am_libctfbacktrace_la_rpath) $(l= ibctfbacktrace_la_OBJECTS) $(libctfbacktrace_la_LIBADD) $(LIBS) + libctfframe.la: $(libctfframe_la_OBJECTS) $(libctfframe_la_DEPENDENCIES) $= (EXTRA_libctfframe_la_DEPENDENCIES)=20 $(AM_V_CCLD)$(LINK) $(am_libctfframe_la_rpath) $(libctfframe_la_OBJECTS) = $(libctfframe_la_LIBADD) $(LIBS) =20 @@ -525,6 +550,8 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c =20 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libctfbacktrace_la-ctf-ba= cktrace-err.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libctfbacktrace_la-ctf-ba= cktrace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libctfframe_la-ctf-frame-= dump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libctfframe_la-ctf-frame-= error.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libctfframe_la-ctf-frame.= Plo@am__quote@ @@ -550,6 +577,20 @@ distclean-compile: @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=3D$(DEPDIR) $(CCDEPMODE) $(depcom= p) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< =20 +libctfbacktrace_la-ctf-backtrace.lo: ctf-backtrace.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=3DCC $(AM_LIBTO= OLFLAGS) $(LIBTOOLFLAGS) --mode=3Dcompile $(CC) $(DEFS) $(DEFAULT_INCLUDES)= $(INCLUDES) $(libctfbacktrace_la_CPPFLAGS) $(CPPFLAGS) $(libctfbacktrace_l= a_CFLAGS) $(CFLAGS) -MT libctfbacktrace_la-ctf-backtrace.lo -MD -MP -MF $(D= EPDIR)/libctfbacktrace_la-ctf-backtrace.Tpo -c -o libctfbacktrace_la-ctf-ba= cktrace.lo `test -f 'ctf-backtrace.c' || echo '$(srcdir)/'`ctf-backtrace.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libctfbacktrace_la-ctf-= backtrace.Tpo $(DEPDIR)/libctfbacktrace_la-ctf-backtrace.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source=3D'ctf-backtrace.c' obj= ect=3D'libctfbacktrace_la-ctf-backtrace.lo' libtool=3Dyes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=3D$(DEPDIR) $(CCDEPMODE) $(depcom= p) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=3DC= C $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=3Dcompile $(CC) $(DEFS) $(DEFAU= LT_INCLUDES) $(INCLUDES) $(libctfbacktrace_la_CPPFLAGS) $(CPPFLAGS) $(libct= fbacktrace_la_CFLAGS) $(CFLAGS) -c -o libctfbacktrace_la-ctf-backtrace.lo `= test -f 'ctf-backtrace.c' || echo '$(srcdir)/'`ctf-backtrace.c + +libctfbacktrace_la-ctf-backtrace-err.lo: ctf-backtrace-err.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=3DCC $(AM_LIBTO= OLFLAGS) $(LIBTOOLFLAGS) --mode=3Dcompile $(CC) $(DEFS) $(DEFAULT_INCLUDES)= $(INCLUDES) $(libctfbacktrace_la_CPPFLAGS) $(CPPFLAGS) $(libctfbacktrace_l= a_CFLAGS) $(CFLAGS) -MT libctfbacktrace_la-ctf-backtrace-err.lo -MD -MP -MF= $(DEPDIR)/libctfbacktrace_la-ctf-backtrace-err.Tpo -c -o libctfbacktrace_l= a-ctf-backtrace-err.lo `test -f 'ctf-backtrace-err.c' || echo '$(srcdir)/'`= ctf-backtrace-err.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libctfbacktrace_la-ctf-= backtrace-err.Tpo $(DEPDIR)/libctfbacktrace_la-ctf-backtrace-err.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source=3D'ctf-backtrace-err.c'= object=3D'libctfbacktrace_la-ctf-backtrace-err.lo' libtool=3Dyes @AMDEPBAC= KSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=3D$(DEPDIR) $(CCDEPMODE) $(depcom= p) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=3DC= C $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=3Dcompile $(CC) $(DEFS) $(DEFAU= LT_INCLUDES) $(INCLUDES) $(libctfbacktrace_la_CPPFLAGS) $(CPPFLAGS) $(libct= fbacktrace_la_CFLAGS) $(CFLAGS) -c -o libctfbacktrace_la-ctf-backtrace-err.= lo `test -f 'ctf-backtrace-err.c' || echo '$(srcdir)/'`ctf-backtrace-err.c + libctfframe_la-ctf-frame.lo: ctf-frame.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=3DCC $(AM_LIBTO= OLFLAGS) $(LIBTOOLFLAGS) --mode=3Dcompile $(CC) $(DEFS) $(DEFAULT_INCLUDES)= $(INCLUDES) $(libctfframe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) = -MT libctfframe_la-ctf-frame.lo -MD -MP -MF $(DEPDIR)/libctfframe_la-ctf-fr= ame.Tpo -c -o libctfframe_la-ctf-frame.lo `test -f 'ctf-frame.c' || echo '$= (srcdir)/'`ctf-frame.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libctfframe_la-ctf-fram= e.Tpo $(DEPDIR)/libctfframe_la-ctf-frame.Plo diff --git a/libctfframe/aclocal.m4 b/libctfframe/aclocal.m4 index 3a0b3426ebc..bda656c049c 100644 --- a/libctfframe/aclocal.m4 +++ b/libctfframe/aclocal.m4 @@ -1229,6 +1229,7 @@ AC_SUBST([am__untar]) =20 m4_include([../bfd/acinclude.m4]) m4_include([../config/acx.m4]) +m4_include([../config/ctf-frame.m4]) m4_include([../config/depstand.m4]) m4_include([../config/jobserver.m4]) m4_include([../config/lead-dot.m4]) diff --git a/libctfframe/configure.ac b/libctfframe/configure.ac index d5e5db3c416..cd7ed5f7cdb 100644 --- a/libctfframe/configure.ac +++ b/libctfframe/configure.ac @@ -57,6 +57,13 @@ ACX_PROG_CC_WARNING_ALMOST_PEDANTIC([-Wno-long-long]) # corrected. ACX_PROG_CC_WARNINGS_ARE_ERRORS([manual]) =20 +dnl The libctfbacktrace library needs to be built with CTF Frame info. +dnl If the build assembler is not capable of generate CTF Frame then +dnl the library is not built. + +CTF_CHECK_AS_CTF_FRAME +AM_CONDITIONAL([HAVE_CTF_FRAME_AS], [test "x$ac_cv_have_ctfframe" =3D "xye= s"]) + AM_MAINTAINER_MODE AM_INSTALL_LIBBFD ACX_PROG_CC_WARNING_OPTS([-Wall], [ac_libctfframe_warn_cflags]) diff --git a/libctfframe/ctf-backtrace-err.c b/libctfframe/ctf-backtrace-er= r.c new file mode 100644 index 00000000000..374ceaf3266 --- /dev/null +++ b/libctfframe/ctf-backtrace-err.c @@ -0,0 +1,46 @@ +/* ctf-backtrace-err.c - CTF Backtrace Error table. + + Copyright (C) 2022 Free Software Foundation, Inc. + + This file is part of libctfbacktrace. + + 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 . = */ + +#include "config.h" +#include "ctf-backtrace-api.h" + +/* CTF backtrace error messages. */ +static const char *const ctf_bt_errlist[] =3D +{ + "", + "File does not contain CTF Frame data", + "Iterating shared object reading error", + "Failed to malloc memory space", + "Failed to realloc memory space", + "Failed to open file", + "Failed on resolve canonical file name", + "Failed to reposition file offset", + "Failed to read from a file descriptor", + "Failed to get the user context", + "Failed to set up decode data", + "Illegal CFA offset" +}; + +/* ctf_bt_perror -Return the error message associated with the error code.= */ + +const char * +ctf_bt_errmsg (enum ctf_bt_errcode ecode) +{ + return ctf_bt_errlist[ecode]; +} diff --git a/libctfframe/ctf-backtrace.c b/libctfframe/ctf-backtrace.c new file mode 100644 index 00000000000..652877e26d0 --- /dev/null +++ b/libctfframe/ctf-backtrace.c @@ -0,0 +1,617 @@ +/* ctf-backtrace.c - The CTF Frame unwinder. + + Copyright (C) 2022 Free Software Foundation, Inc. + + This file is part of libctfbacktrace. + + 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 . = */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ansidecl.h" +#include "ctf-frame-api.h" +#include "ctf-backtrace-api.h" + +#ifndef PT_CTF_FRAME +#define PT_CTF_FRAME 0x6474e554 /* FIXME. */ +#endif + +#define _cf_printflike_(string_index,first_to_check) \ + __attribute__ ((__format__ (__printf__, (string_index), (first_to_chec= k)))) + +static int _ctf_unwind_debug; /* Control for printing out debug info. */ +static int no_of_entries =3D 32; + +/* CTF decode data for the main module or a DSO. */ +struct ctf_decode_data +{ + char *cdd_data; /* CTF decode data. */ + int cdd_data_size; /* CTF decode data size. */ + uint64_t cdd_text_vma; /* Text segment's virtual address. */ + int cdd_text_size; /* Text segment's size. */ + uint64_t cdd_ctf_vma; /* CTF segment's virtual address. */=09 + ctf_frame_decoder_ctx *cdd_ctf_ctx; /* CTF decoder context. */ +}; + +/* List that holds CTF Frame info for the shared libraries. */ +struct dso_cfi_list +{ + int alloced; /* Entries allocated. */ + int used; /* Entries used. */ + struct ctf_decode_data *entry; /* DSO's decode data. */ +}; + +/* Data that's passed through ctf_frame_callback. */ +struct ctf_unwind_info +{ + int cui_fd; /* File descriptor. */ + struct ctf_decode_data cui_ctx; /* The decode data. */ + struct dso_cfi_list cui_dsos; /* The DSO list. */ +}; + +static void +ctf_unwind_init_debug (void) +{ + static int inited; + + if (!inited) + { + _ctf_unwind_debug =3D getenv ("CTF_UNWIND_DEBUG") !=3D NULL; + inited =3D 1; + } +} + +_cf_printflike_ (1, 2) +static void +debug_printf (const char *format, ...) +{ + if (_ctf_unwind_debug) + { + va_list args; + + va_start (args, format); + __builtin_vprintf (format, args); + va_end (args); + } +} + +/* ctf_bt_errno - Check if there is error code in ERRP. */ + +static int +ctf_bt_errno (int *errp) +{ + if (errp =3D=3D NULL) + return 0; + + return (*errp !=3D CTF_BT_OK); +} + +/* ctf_bt_set_errno - Store the specified error code ERROR into ERRP if + it is non-NULL. */ + +static void +ctf_bt_set_errno (int *errp, int error) +{ + if (errp !=3D NULL) + *errp =3D error; +} + +/* ctf_add_dso - Add .ctf_frame info in D_DATA, which is associated with + a dynamic shared object, to D_LIST. */ + +static void +ctf_add_dso (struct dso_cfi_list *d_list, + struct ctf_decode_data d_data, + int *errp) +{ + if (d_list->alloced =3D=3D 0) + { + d_list->entry =3D malloc (no_of_entries * sizeof (struct ctf_decode_= data)); + if (d_list->entry =3D=3D NULL) + { + ctf_bt_set_errno (errp, CTF_BT_ERR_MALLOC); + return; + } + memset (d_list->entry, 0, + no_of_entries * sizeof (struct ctf_decode_data)); + d_list->alloced =3D no_of_entries; + } + else if (d_list->used =3D=3D d_list->alloced) + { + d_list->entry =3D realloc (d_list->entry, + (d_list->alloced + no_of_entries) * + sizeof (struct ctf_decode_data)); + if (d_list->entry =3D=3D NULL) + { + ctf_bt_set_errno (errp, CTF_BT_ERR_REALLOC); + return; + } + + memset (&d_list->entry[d_list->alloced], 0, + no_of_entries * sizeof (struct ctf_decode_data)); + d_list->alloced +=3D no_of_entries; + } + + ctf_bt_set_errno (errp, CTF_BT_OK); + d_list->entry[d_list->used++] =3D d_data; +} + +/* ctf_free_cfi - Free up space allocated for .ctf_frame info for CF. */ + +static void +ctf_free_cfi (struct ctf_unwind_info *cf) +{ + struct dso_cfi_list *d_list; + int i; + + if (cf =3D=3D NULL) + return; + + free (cf->cui_ctx.cdd_data); + ctf_frame_decoder_free (&cf->cui_ctx.cdd_ctf_ctx); + close (cf->cui_fd); + + d_list =3D &cf-> cui_dsos; + if (d_list =3D=3D NULL) + return; + + for (i =3D 0; i < d_list->used; ++i) + { + free (d_list->entry[i].cdd_data); + ctf_frame_decoder_free (&d_list->entry[i].cdd_ctf_ctx); + } +} + +/* ctf_find_context - Find the decode data that contains ADDR from CF. + Return the pointer to the decode data or NULL. */ + +static struct ctf_decode_data * +ctf_find_context (struct ctf_unwind_info *cf, uint64_t addr) +{ + struct dso_cfi_list *d_list; + int i; + + if (cf =3D=3D NULL) + return NULL; + + if (cf->cui_ctx.cdd_text_vma < addr + && cf->cui_ctx.cdd_text_vma + cf->cui_ctx.cdd_text_size > addr) + return &cf->cui_ctx; + + d_list =3D &cf->cui_dsos; + for (i =3D 0; i < cf->cui_dsos.used; ++i) + { + if (d_list->entry[i].cdd_text_vma <=3D addr && + d_list->entry[i].cdd_text_vma + + d_list->entry[i].cdd_text_size >=3D addr) + return &d_list->entry[i]; + } + + return NULL; +} + +/* ctf_valid_addr - Check if ADDR is valid in CF. The address is considered + invalid, with regards to CTF, if it's not in any address range of the m= ain + module or any of its DSO's. Return 1 if valid, 0 otherwise. */ + +static int +ctf_valid_addr (struct ctf_unwind_info *cf, uint64_t addr) +{ + struct ctf_decode_data *cdp; + + if (cf =3D=3D NULL) + return 0; + + cdp =3D ctf_find_context (cf, addr); + return cdp ? 1 : 0; +} + +/* ctf_load_ctx - Call decoder to create and set up the ctf frame info for + either the main module or one of the DSOs from CF, based on the input + RADDR argument. Return the newly created decode context or NULL. */ + +static ctf_frame_decoder_ctx * +ctf_load_ctx (struct ctf_unwind_info *cf, uint64_t raddr) +{ + ctf_frame_decoder_ctx *nctx; + struct ctf_decode_data *cdp; + + if (cf =3D=3D NULL) + return NULL; + + cdp =3D ctf_find_context (cf, raddr); + if (cdp =3D=3D NULL) + return NULL; + + if (cdp->cdd_ctf_ctx =3D=3D NULL) + { + int err;=20 + nctx =3D ctf_frame_decode (cdp->cdd_data, cdp->cdd_data_size, &err); + if (nctx =3D=3D NULL) + return NULL; + cdp->cdd_ctf_ctx =3D nctx; + return nctx; + } + + return NULL; +} + +/* ctf_update_ctx - Check if need to do a decode context switch, based on + the input RADDR argument, from CF. A new decode context will be created + and set up if it isn't already done so. Return the new decode context in + CTX and vma in CFI_VMA. */ + +static void +ctf_update_ctx (struct ctf_unwind_info *cf, uint64_t raddr, + ctf_frame_decoder_ctx **ctx, uint64_t *cfi_vma) +{ + ctf_frame_decoder_ctx *nctx; + struct ctf_decode_data *cdp; + + cdp =3D ctf_find_context (cf, raddr); + if (cdp !=3D NULL) + { + if (cdp->cdd_ctf_ctx =3D=3D NULL) + { + int err;=20 + nctx =3D ctf_frame_decode (cdp->cdd_data, cdp->cdd_data_size, &err); + if (nctx =3D=3D NULL) + { + *ctx =3D NULL; + return; + } + cdp->cdd_ctf_ctx =3D nctx; + } + *ctx =3D cdp->cdd_ctf_ctx; + *cfi_vma =3D cdp->cdd_ctf_vma; + } +} + +/* get_contents - Return contents at ADDR from file descriptor FD. */ + +static uint64_t +get_contents (int fd, uint64_t addr, int *errp) +{ + uint64_t data; + size_t sz; + + ctf_bt_set_errno (errp, CTF_BT_OK); + if (lseek (fd, addr, SEEK_SET) =3D=3D -1) + { + ctf_bt_set_errno (errp, CTF_BT_ERR_LSEEK); + return 0; + } + sz =3D read (fd, &data, sizeof (uint64_t)); + if (sz !=3D sizeof (uint64_t)) + { + ctf_bt_set_errno (errp, CTF_BT_ERR_READ); + return 0; + } + + return data; +} + +/* ctf_fd_open - Open /proc image associated with the process id and return + the file descriptor. */ + +static int +ctf_fd_open (int *errp) +{ + char filename[PATH_MAX]; + pid_t pid; + int fd; + + pid =3D getpid (); + snprintf (filename, sizeof filename, "/proc/%d/task/%d/mem", pid, pid); + if ((fd =3D open (filename, O_RDONLY)) =3D=3D -1) + { + ctf_bt_set_errno (errp, CTF_BT_ERR_OPEN); + return -1; + } + + return fd; +} + +/* ctf_frame_callback - The callback from dl_iterate_phdr with header info + in INFO. + Return CTF Frame info for either the main module or a DSO in DATA. */ + +static int +ctf_frame_callback (struct dl_phdr_info *info, + size_t size ATTRIBUTE_UNUSED, + void *data) +{ + struct ctf_unwind_info *cf =3D (struct ctf_unwind_info *) data; + int p_type, i, fd, ctf_err; + ssize_t len; + uint64_t text_vma =3D 0; + int text_size =3D 0; + + if (data =3D=3D NULL || info =3D=3D NULL) + return 1; + + debug_printf ("-- name: %s %14p\n", info->dlpi_name, (void *)info->dlpi_= addr); + + for (i =3D 0; i < info->dlpi_phnum; i++) + { + debug_printf(" %2d: [%14p; memsz:%7lx] flags: 0x%x; \n", i, + (void *) info->dlpi_phdr[i].p_vaddr, + info->dlpi_phdr[i].p_memsz, + info->dlpi_phdr[i].p_flags); + + p_type =3D info->dlpi_phdr[i].p_type; + if (p_type =3D=3D PT_LOAD && info->dlpi_phdr[i].p_flags & PF_X) + { + text_vma =3D info->dlpi_addr + info->dlpi_phdr[i].p_vaddr; + text_size =3D info->dlpi_phdr[i].p_memsz; + continue; + } + if (p_type !=3D PT_CTF_FRAME) + continue; + + if (info->dlpi_name[0] =3D=3D '\0') /* the main module. */ + { + fd =3D ctf_fd_open (&ctf_err); + if (fd =3D=3D -1) + return 1; + if (lseek (fd, info->dlpi_addr + info->dlpi_phdr[i].p_vaddr, + SEEK_SET) =3D=3D -1) + { + ctf_bt_set_errno (&ctf_err, CTF_BT_ERR_LSEEK); + return 1; + } + + cf->cui_ctx.cdd_data =3D (char *) malloc (info->dlpi_phdr[i].p_memsz); + if (cf->cui_ctx.cdd_data =3D=3D NULL) + { + ctf_bt_set_errno (&ctf_err, CTF_BT_ERR_MALLOC); + return 1; + } + + len =3D read (fd, cf->cui_ctx.cdd_data, info->dlpi_phdr[i].p_memsz); + if (len =3D=3D -1 || len !=3D (ssize_t) info->dlpi_phdr[i].p_memsz) + { + ctf_bt_set_errno (&ctf_err, CTF_BT_ERR_READ); + return 1; + } + + assert (text_vma); + cf->cui_ctx.cdd_data_size =3D len; + cf->cui_ctx.cdd_ctf_vma =3D info->dlpi_addr + info->dlpi_phdr[i].p_vadd= r; + cf->cui_fd =3D fd; + cf->cui_ctx.cdd_text_vma =3D text_vma; + cf->cui_ctx.cdd_text_size =3D text_size; + text_vma =3D 0; + return 0; + } + else + { /* a dynamic shared object. */ + struct ctf_decode_data dt; + memset (&dt, 0, sizeof (struct ctf_decode_data)); + assert (cf->cui_fd); + if (lseek (cf->cui_fd, info->dlpi_addr + info->dlpi_phdr[i].p_vaddr, + SEEK_SET) =3D=3D -1) + { + ctf_bt_set_errno (&ctf_err, CTF_BT_ERR_LSEEK); + return 1; + } + + dt.cdd_data =3D (char *) malloc (info->dlpi_phdr[i].p_memsz); + if (dt.cdd_data =3D=3D NULL) + { + ctf_bt_set_errno (&ctf_err, CTF_BT_ERR_MALLOC); + return 1; + } + + len =3D read (cf->cui_fd, dt.cdd_data, info->dlpi_phdr[i].p_memsz); + if (len =3D=3D -1 || len !=3D (ssize_t) info->dlpi_phdr[i].p_memsz) + { + ctf_bt_set_errno (&ctf_err, CTF_BT_ERR_READ); + return 1; + } + + assert (text_vma); + dt.cdd_data_size =3D len; + dt.cdd_ctf_vma =3D info->dlpi_addr + info->dlpi_phdr[i].p_vaddr; + dt.cdd_text_vma =3D text_vma; + dt.cdd_text_size =3D text_size; + text_vma =3D 0; + ctf_add_dso (&cf->cui_dsos, dt, &ctf_err); + if (ctf_err !=3D CTF_BT_OK) + return 1; + return 0; + } + } + + return 0; +} + +/* ctf_frame_unwind - Unwind the stack backtrace for CF. If successful, + store the return addresses in RA_LST. The RA_SIZE argument specifies + the maximum number of return addresses that can be stored in RA_LST + and contains the number of the addresses collected. */ + +static void +ctf_frame_unwind (struct ctf_unwind_info *cf, void **ra_lst, + int *ra_size, int *errp) +{ + uint64_t cfa, return_addr, ra_stack_loc, rfp_stack_loc; + ctf_frame_decoder_ctx *ctx; + int cfa_offset, rfp_offset, errnum, i, count; + ctf_frame_row_entry fred, *frep =3D &fred; + uint64_t pc, rfp, rsp, cfi_vma; + ucontext_t context, *cp =3D &context; + + if (cf =3D=3D NULL || ra_lst =3D=3D NULL || ra_size =3D=3D NULL) + { + ctf_bt_set_errno (errp, CTF_BT_ERR_ARG); + return; + } + + /* Get the user context for its registers. */ + if (getcontext (cp) !=3D 0) + { + ctf_bt_set_errno (errp, CTF_BT_ERR_GETCONTEXT); + return; + } + ctf_bt_set_errno (errp, CTF_BT_OK); + +#ifdef __x86_64__ + pc =3D cp->uc_mcontext.gregs[REG_RIP]; + rsp =3D cp->uc_mcontext.gregs[REG_RSP]; + rfp =3D cp->uc_mcontext.gregs[REG_RBP]; +#else +#ifdef __aarch64__ +#define UNWIND_AARCH64_X29 29 /* 64-bit frame pointer. */ +#define UNWIND_AARCH64_X30 30 /* 64-bit link pointer. */ + pc =3D cp->uc_mcontext.pc; + rsp =3D cp->uc_mcontext.sp; + rfp =3D cp->uc_mcontext.regs[UNWIND_AARCH64_X29]; + uint64_t ra =3D cp->uc_mcontext.regs[UNWIND_AARCH64_X30]; +#endif +#endif + + /* Load and set up the decoder. */ + ctx =3D ctf_load_ctx (cf, pc); + if (ctx =3D=3D NULL) + { + ctf_bt_set_errno (errp, CTF_BT_ERR_DECODE); + return; + } + cfi_vma =3D cf->cui_ctx.cdd_ctf_vma; + count =3D *ra_size; + + for (i =3D 0; i < count; ++i) + { + pc -=3D cfi_vma; + errnum =3D ctf_frame_find_fre (ctx, pc, frep); + if (errnum =3D=3D 0) + { + cfa_offset =3D ctf_frame_fre_get_cfa_offset (frep, &errnum); + if (errnum =3D=3D ECTF_FRAME_FREOFFSET_NOPRESENT) + { + ctf_bt_set_errno (errp, CTF_BT_ERR_CFA_OFFSET); + return; + } + + cfa =3D ((frep->fre_info & 0x1) =3D=3D CTF_FRAME_BASE_REG_SP + ? rsp : rfp) + cfa_offset; + +#ifdef __x86_64__ + /* For x86, read the return address from cfa - 8. */ + ra_stack_loc =3D cfa - 8; + return_addr =3D get_contents (cf->cui_fd, ra_stack_loc, errp); + if (ctf_bt_errno (errp)) + return; +#else +#ifdef __aarch64__ + int ra_offset =3D ctf_frame_fre_get_ra_offset (frep, &errnum); + if (errnum =3D=3D 0) + { + ra_stack_loc =3D cfa + ra_offset; + return_addr =3D get_contents (cf->cui_fd, ra_stack_loc, errp); + if (ctf_bt_errno (errp)) + return; + } + else + return_addr =3D ra; +#endif +#endif + + /* Validate and add return address to the list. */ + if (ctf_valid_addr (cf, return_addr) =3D=3D 0) + { + i -=3D 1; + goto find_fre_ra_err; + } + if (i !=3D 0) /* exclude self. */ + ra_lst[i-1] =3D (void *)return_addr; + + /* Set up for the next frame. */ + rfp_offset =3D ctf_frame_fre_get_fp_offset (frep, &errnum); + if (errnum =3D=3D 0) + { + rfp_stack_loc =3D cfa + rfp_offset; + rfp =3D get_contents (cf->cui_fd, rfp_stack_loc, errp); + if (ctf_bt_errno (errp)) + return; + } + rsp =3D cfa; + pc =3D return_addr; + + /* Check if need to update the decoder context and vma. */ + ctf_update_ctx (cf, return_addr, &ctx, &cfi_vma); + if (ctx =3D=3D NULL) + { + ctf_bt_set_errno (errp, CTF_BT_ERR_DECODE); + return; + } + } + else + { + i -=3D 1; + goto find_fre_ra_err; + } + } + +find_fre_ra_err: + *ra_size =3D i; +} + +/* ctf_backtrace - Main API that user program calls to get a backtrace. + The BUFFER argument provides space for the list of the return addresses + and the SIZE argument specifies the maximum number of addresses that + can be stored in the buffer. Return the number of return addresses + collected or -1 if there is any error. */ + +int +ctf_backtrace (void **buffer, int size, int *errp) +{ + struct ctf_unwind_info ctfinfo; + + ctf_unwind_init_debug (); + + memset (&ctfinfo, 0, sizeof (struct ctf_unwind_info)); + + /* find and set up the .ctf_frame sections. */ + (void) dl_iterate_phdr (ctf_frame_callback, (void *)&ctfinfo); + if (ctfinfo.cui_fd =3D=3D 0) + { + ctf_bt_set_errno (errp, CTF_BT_ERR_NOCTF); + return -1; + } + + /* Do the stack unwinding. */ + ctf_frame_unwind (&ctfinfo, buffer, &size, errp); + if (ctf_bt_errno (errp)) + return -1; + + ctf_free_cfi (&ctfinfo); + + return size; +} diff --git a/libctfframe/ttest.c b/libctfframe/ttest.c new file mode 100644 index 00000000000..c0b8434aad5 --- /dev/null +++ b/libctfframe/ttest.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +#include "ctf-backtrace-api.h" + +#define BT_BUF_SIZE 100 + +/* funclist for running "ttest.x 3". */ +static const char *const func_list[] =3D +{ + "myfunc3", + "()", + "myfunc", + "myfunc", + "myfunc", + "main" +}; + +void +myfunc3 (void) +{ + void *buffer[BT_BUF_SIZE]; + int j, nptrs, err; + char **strings; + + /* Call the unwinder to get an array of return addresses. */ + nptrs =3D ctf_backtrace (buffer, BT_BUF_SIZE, &err); + if (nptrs =3D=3D -1 || nptrs !=3D 6) + { + printf ("CTF error: %s\n", ctf_bt_errmsg (err)); + return; + } + + /* Get these addresses symbolically. */ + strings =3D backtrace_symbols (buffer, nptrs); + if (strings =3D=3D NULL) { + perror("backtrace_symbols"); + exit(EXIT_FAILURE); + } + + /* Verify the results. */ + for (j =3D 0; j < nptrs; j++) + if (!strstr (strings[j], func_list[j])) + break; + + free(strings); + + printf ("%s\n", j =3D=3D nptrs ? "PASS" : "FAIL"); +} + +static void /* "static" means don't export the symbol... */ +myfunc2 (void) +{ + myfunc3 (); +} + +void +myfunc (int ncalls) +{ + if (ncalls > 1) + myfunc (ncalls - 1); + else + myfunc2 (); +} + +int +main (int argc, char *argv[]) +{ + if (argc !=3D 2) { + fprintf (stderr, "%s num-calls\n", argv[0]); + exit (EXIT_FAILURE); + } + + myfunc (atoi(argv[1])); + exit (EXIT_SUCCESS); +} --=20 2.31.1