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 C02DF384B83E for ; Tue, 2 Aug 2022 08:07:51 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org C02DF384B83E 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 2726G9p5024575; Tue, 2 Aug 2022 08:07:51 GMT Received: from iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (iadpaimrmta02.appoci.oracle.com [147.154.18.20]) by mx0b-00069f02.pphosted.com (PPS) with ESMTPS id 3hmue2p39d-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 02 Aug 2022 08:07:50 +0000 Received: from pps.filterd (iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com [127.0.0.1]) by iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (8.17.1.5/8.17.1.5) with ESMTP id 2727cUtd030879; Tue, 2 Aug 2022 08:07:50 GMT Received: from nam12-dm6-obe.outbound.protection.outlook.com (mail-dm6nam12lp2177.outbound.protection.outlook.com [104.47.59.177]) by iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (PPS) with ESMTPS id 3hmu322w34-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 02 Aug 2022 08:07:49 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=FvqaNEWOq3C5bEcRjpRkhMGVycM7wntD8R5Qx0drPaWrbkJ32eOkK4qDkkqu9WVBOEzk6JzF55eQ84kDZ68MNdm54Ag04V+QoV64kcDB5nLVyVZMIwNNXiy0l30DWA38mO2m2EjVYaBaWmKcAUsnqaPw0QFCWmpU9JnqPCC80CbvnCzBeSv2R25npC1kS/N11B53Lwb5r7qlZUzsuCZOdb0rc4ddv7f1kc9x2jTJBwc0frEm+qXdVn5YNAvS+1keK/s8AQwQjGodzuA71pvSehRGKk0Z6MOvX+DVuOh7WYVnwSNjk5envkPnFoFP3k0/1EAp5SanQKPrXZ6EVeQc2Q== 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=2sTLb3EhS0NYYFl5hdy3YZqFZZce/NA9NZNRNtXVZCQ=; b=XTjnUf70U0jU1omXBAifECgwBvID2VwTGQFHWXrkZ7216ims6mmOLM+pyKmlpdaEh7fgyAIQMcszpYluHE8PO2LnpSJzXW/04COjua04WP8HOxntbJczpBhC/3M/7r21+g/F6ONbvdqQnvx783kJldEERjToybVbqSOzP+E09TMuYOthV7i1S/99XJ4NIKX9EOPsoWC5d9tMsAGvBLhiOZzDCE1zDNysbc9aaGK6VAg3NCzw2OWgM5+c3Yd9DWQMFv9Pp3dGTGiXc1mLRBm4kPEVOlrpG5ktKu5S2UuOEDcm//+xpwKIRMqQuNoQJQRYfBIG/Q61oPYFw8Y/0WVUeA== 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 BN8PR10MB3123.namprd10.prod.outlook.com (2603:10b6:408:c7::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5482.15; Tue, 2 Aug 2022 08:07:46 +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:46 +0000 From: Indu Bhagat To: binutils@sourceware.org Subject: [PATCH,V6 08/10] unwinder: generate backtrace using CTF Frame format Date: Tue, 2 Aug 2022 01:04:50 -0700 Message-Id: <20220802080452.1143351-9-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: quoted-printable 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: eca78757-b8ce-4065-1816-08da745e1590 X-MS-TrafficTypeDiagnostic: BN8PR10MB3123:EE_ X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 3O5Y2S7IEYHDzzTBcJOEUw4r7CVO4FD8DWteT/RmKY/MLlS8jPa558Kpi0VibxbOiyjN7opeiBv+jxxeFNyW3varRcmqoAhoZstFMzUsdOUhBGtKxs+jxerU0jc3JItzFUdI3/JcNKUcKEaPkNUydZ7c1LoxNbyIy20a1+5eCYYfMC9I3T357122SmoT4+/fXs0Z7EUiuLyd1Xri/aL6O3ie8i8CzN0SVUMz3tQHIN6yyWoQjctqUdARvEpiFU23PfXPvL+eGQC4qk2fedNHDVBHbV19+9SM4G3CGW4WoCM1riauVfiGuCXmDaKCs6HPApIo+39yX+te5qAc+3SNtX38KYXdCD7NFvMKV4+OHeBr76uZHeMXowtEhwz/j317kjAgoF6Zc9/L8kXNnkTUayA4pOphGJAmw1SodpKIjmViDgFwRVzAnuQfhYaF0kdg7Ohlqlq4JQ31KWN8/PErHD3lMUoillo/krk8vdDRmwKRdsG4a8+zcX9J9M5lSVx9GUuAQOTAT+2VIA6sALzvL2vLKIYCAl8IRXKaPxAbmlvS9mXkEd0aJIypTY3TnDl59NQZLh0yeSQ3SMZXF/eoiIGmH1MwsLNLRd7l1e2W+0Bl6h2kGEno6jzyEQ7aaWgaV1MjN3R4UGjC+CLrstgQKVcL2p6gttRTHHaLU7ci5RoiBd0/kLsZFI7RIc4rzzQD1VOQtfo28XX5DZDcqDnYPt4b8U+ndKR3jmCIHqxoc8yDl7n74Iod8ku6Pl0zRZOu4XusKhN7PBLg/PGwAiTG8VCggeYuwcYAkvgerQKeRR5EXFGKanDJPiF+7k2TcygI/V9JsyEwVQa6KWArIXvxPpaR4GqZs3xukwED64D9HJk= 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)(136003)(39860400002)(346002)(396003)(376002)(366004)(41300700001)(5660300002)(2906002)(36756003)(6666004)(83380400001)(30864003)(478600001)(6486002)(52116002)(2616005)(6506007)(8936002)(38100700002)(6916009)(44832011)(107886003)(1076003)(38350700002)(186003)(8676002)(316002)(4326008)(66476007)(66556008)(66946007)(26005)(6512007)(86362001)(2004002); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?ht6sNRF5h1kSO6Ml/TDvL8umwYTRxZaxuZuSvDPdij/cnPlnrtSGBryHlI75?= =?us-ascii?Q?I/uK8QBM0dfiM+n/w2hPnZAYQ64R8aW+kfcUtw9MDGXb0LE16nVWmbgDWrq0?= =?us-ascii?Q?RgIdPU0wN1Dmo5VA1fxFPKnJCuaVc/dRdmXByZlOsy+vN47YH3e9jkxJ1k+7?= =?us-ascii?Q?aJy2VUOUOhmkYznuCfP/Ndd2FaQf5MMUtpXagDD080sCA+8lqgiab2tVsd4a?= =?us-ascii?Q?xM6syK/ijYCdnefpG7N47/OGf+MPJJbMcImfwtchZW2htpjN/zIhgNfcEG8I?= =?us-ascii?Q?kZhys2n20l952uvatpytVWaYXAxw4EK0ctiejxZ69Zx3acLQnfSRx4KnVqO1?= =?us-ascii?Q?X1B917NVC36pEubEF7UmkMKhG5LrxtPHzAzNf5dcW5FnC7iWfTsU8+qR8eWP?= =?us-ascii?Q?j/1PceTFnKkCbLP+iC2lh7r+fLkYAqPxUgPklO1orSsNk3xyYeEvFrdGNJSm?= =?us-ascii?Q?xc7Ub9SnJ84KKpns2Qzfgu8m5g8FlYmMRLuinmaj+xjvBzi0aZRGV4MjzoTH?= =?us-ascii?Q?jm3sAcGldPCNRaV0AdSOqAGAZLDBW2mxuAr5yJeER9fnhpIjTSw/6JUdBRoM?= =?us-ascii?Q?npo7wRFYpc509/jcerJ28xSqEXSzZdzrB4dypA7PGjyVfG+dv2t9dlp37THZ?= =?us-ascii?Q?pP3WD/K526WaEJgsxpnA63SbysskqhBRSt/OLInFdOWfDP7DxiOzv8bunQOa?= =?us-ascii?Q?fh8n7N/AUdTcF0XQILmt6uF1tRIzW1YK/1v2I9WVLmGqvhG0bSPVjDw9V+Je?= =?us-ascii?Q?X4XL9o+MQj3AWUHMubL5R2GffU62nn94QN2u31c8V69p5XYbbUi22RPjLqDU?= =?us-ascii?Q?Dh1h5X0LYA9v0KmMcXW/UsAR+pIUiSdJy3RbkAVm3Ckuy7kirD7ZFC9rSA92?= =?us-ascii?Q?ExSpr+ud+HikjQyVz2BgYYP7faFE4iRiMHikHEsafe6YFi09yu7+WD4bSjFz?= =?us-ascii?Q?sIeK2sQbkbgnLdCDYdA4L5J3EmRNbXQDJexsOyGogNmwS6vGqrnrWKNGTiA9?= =?us-ascii?Q?glvVA4puBmRAQNhOxCGBFCdewev4A741/+BcNASpHI6a8iReAvKO4Kdg3rsU?= =?us-ascii?Q?HP3fAPugHsTWkZiCzB0ymBsrid+5OwN+eaXYVECNN+R1RT2/lOsE6Vb9UaFk?= =?us-ascii?Q?0rz8yCabQTRgUS2lzAO2yAKGe5DatQu0noAypogccREENXA9csfdWyvF0Rgs?= =?us-ascii?Q?TZJD6VjtQUj8O9M8gotUugLY7UYy8+eZ9G8b2Thw8fhZjDPH/mVzK2m8/QCH?= =?us-ascii?Q?anlG4qiKNXSUvmoiGqt+fy/9Yh8VhfHd0tZ9Xr923O8kNGN9vDzOXajDM9M4?= =?us-ascii?Q?bUiPEGsqHAceQ7pRnzz4xRM9EakT0wYA4PyQ1zMYAYR5DCW/bqVgGPlKA0u+?= =?us-ascii?Q?oUtmd6qcWfqUntjppm4643HCjDIt8jjOHljtQ52JRbPWdtoNYLYJRjabtId7?= =?us-ascii?Q?OWi9kR9LlsGG9ueb6pSW8RUmXDqCjMwPswlX1LeVNElOg89spx6ZZI3Uq36q?= =?us-ascii?Q?cIbNwQkR209U8X2KiE0l8aa1T6Bl6kdbXZqmlvuI5pNzyGdf+HsRTilarJnf?= =?us-ascii?Q?isewBXKuiF0UPKtyyINbFsTUK8u+RWD52zb00wEu?= X-OriginatorOrg: oracle.com X-MS-Exchange-CrossTenant-Network-Message-Id: eca78757-b8ce-4065-1816-08da745e1590 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:46.6827 (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: fEBNqGN9RKs6983seJy12iueqrxlqiKOa2y/syKsjwcmJfc4y1ojc+cA198uUBqEffqc7k8jRzy9flIs0Js8VQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN8PR10MB3123 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 mlxscore=0 malwarescore=0 spamscore=0 suspectscore=0 adultscore=0 mlxlogscore=999 bulkscore=0 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2206140000 definitions=main-2208020038 X-Proofpoint-ORIG-GUID: TApEl0WBHdKiGjkvo40lvDWLfFmfakk3 X-Proofpoint-GUID: TApEl0WBHdKiGjkvo40lvDWLfFmfakk3 X-Spam-Status: No, score=-13.3 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 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:08:00 -0000 From: Weimin Pan [Changes from V5] - fixed a memory leak in ctf_free_cfi. [End of changes from V5] [No changes from V4, V3] [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 | 13 +- libctfframe/Makefile.in | 69 +- libctfframe/aclocal.m4 | 1 + libctfframe/configure.ac | 7 + libctfframe/ctf-backtrace-err.c | 46 ++ libctfframe/ctf-backtrace.c | 619 ++++++++++++++++++ libctfframe/testsuite/Makefile.in | 1 + .../testsuite/libctfframe.decode/Makefile.in | 1 + .../testsuite/libctfframe.encode/Makefile.in | 1 + libctfframe/ttest.c | 78 +++ 12 files changed, 893 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 3a4182c19a6..80e382b101e 100644 --- a/libctfframe/Makefile.am +++ b/libctfframe/Makefile.am @@ -25,8 +25,6 @@ AUTOMAKE_OPTIONS =3D 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 @@ -41,3 +39,14 @@ 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 diff --git a/libctfframe/Makefile.in b/libctfframe/Makefile.in index e1f26aecbb4..c344067d961 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,8 +222,9 @@ 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) RECURSIVE_TARGETS =3D all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ @@ -219,8 +238,8 @@ am__can_run_installinfo =3D \ 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) RECURSIVE_CLEAN_TARGETS =3D mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive @@ -425,17 +444,20 @@ ACLOCAL_AMFLAGS =3D -I .. -I ../config AUTOMAKE_OPTIONS =3D 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 all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive =20 @@ -536,6 +558,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 @@ -545,6 +570,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@ @@ -570,6 +597,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 eafe7bea96a..a35bce4d142 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..9d865d185ba --- /dev/null +++ b/libctfframe/ctf-backtrace.c @@ -0,0 +1,619 @@ +/* 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); + } + + free (d_list->entry); +} + +/* 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/testsuite/Makefile.in b/libctfframe/testsuite/Make= file.in index 3a6accc9e53..ec9ba703268 100644 --- a/libctfframe/testsuite/Makefile.in +++ b/libctfframe/testsuite/Makefile.in @@ -91,6 +91,7 @@ subdir =3D testsuite 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 \ diff --git a/libctfframe/testsuite/libctfframe.decode/Makefile.in b/libctff= rame/testsuite/libctfframe.decode/Makefile.in index a34cb02191c..f8f84fc7b89 100644 --- a/libctfframe/testsuite/libctfframe.decode/Makefile.in +++ b/libctfframe/testsuite/libctfframe.decode/Makefile.in @@ -93,6 +93,7 @@ subdir =3D testsuite/libctfframe.decode 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 \ diff --git a/libctfframe/testsuite/libctfframe.encode/Makefile.in b/libctff= rame/testsuite/libctfframe.encode/Makefile.in index da8702d30c2..06b4052cb70 100644 --- a/libctfframe/testsuite/libctfframe.encode/Makefile.in +++ b/libctfframe/testsuite/libctfframe.encode/Makefile.in @@ -92,6 +92,7 @@ subdir =3D testsuite/libctfframe.encode 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 \ 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.37.1