From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx0a-00069f02.pphosted.com (mx0a-00069f02.pphosted.com [205.220.165.32]) by sourceware.org (Postfix) with ESMTPS id D17453857C4D for ; Sat, 7 May 2022 00:52:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org D17453857C4D Received: from pps.filterd (m0246629.ppops.net [127.0.0.1]) by mx0b-00069f02.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 246MxSPw019152 for ; Sat, 7 May 2022 00:52:45 GMT Received: from iadpaimrmta03.imrmtpd1.prodappiadaev1.oraclevcn.com (iadpaimrmta03.appoci.oracle.com [130.35.103.27]) by mx0b-00069f02.pphosted.com (PPS) with ESMTPS id 3frw0axy0m-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Sat, 07 May 2022 00:52:44 +0000 Received: from pps.filterd (iadpaimrmta03.imrmtpd1.prodappiadaev1.oraclevcn.com [127.0.0.1]) by iadpaimrmta03.imrmtpd1.prodappiadaev1.oraclevcn.com (8.16.1.2/8.16.1.2) with SMTP id 2470po54039630 for ; Sat, 7 May 2022 00:52:42 GMT Received: from nam04-mw2-obe.outbound.protection.outlook.com (mail-mw2nam08lp2177.outbound.protection.outlook.com [104.47.73.177]) by iadpaimrmta03.imrmtpd1.prodappiadaev1.oraclevcn.com with ESMTP id 3fusajhtqh-5 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Sat, 07 May 2022 00:52:42 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=nppyQJOHTb+4jIPIS/8N8t5nZjHp4QXSFV+TCK/Bkb7GepbgMubnvUSLBEzlSS4T5rOTtoaXRX0nJsKwgyeDZ6ruW5CvC9/79i5/WYeingOpf77P1Tkb5m2qK+a0cC3QJbmqMIMcw0b1843weIHFKFeyyv6gZ0+Dr7yM4a1EoCdGveCA87NLJ8OhLKV8qertl386tLXKAdMM/Grpmz+GpP4J15cAGXrHTIHOvipROQUZkEG9nAYw1SX+dSCRQuMFIwABOCQfXT0G/FhsaiMDfEOidWDUvd6cxOMgesN09+N8SP1iv8lfSpe8UTszcMyklxU+yL72K8RWaCAXANxl+w== 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=WIkVSPcPrdqgdJ4FTIZDm36vJjbnZIcW7LjwB+y4SY0=; b=kFE4lQEhHsNItljxpjMVPQjnfQz96SRBf9nSLGlW66eGfIvqih4oaUjZ7MS5cdFQnZp1+BjNuj0zt3uVR1tGPE2O8hJaZ82z/q+vB/cUUv+gSOx1C2SagPlBA9lq0zxEgkglZ9JAiHfFR93TePhl95DpBKTevKk1P5kV47eJ++4HCWGzE2ddHvkhSlpTl0VTvA4tNRyjk8974dILa9sD+eCuk33o27TRzwafwmEg8F4y/J4gJRvieVfU2JxHERqLLkRdcF3S07Yz+uUo85BvNVi3lKut5kojnzf6whHYiIeupv93id6eViQRIo0xKm0RsFQZsL7mbkuMfBAoJllTMQ== 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 MWHPR10MB1517.namprd10.prod.outlook.com (2603:10b6:300:23::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5206.27; Sat, 7 May 2022 00:52:40 +0000 Received: from MWHPR1001MB2158.namprd10.prod.outlook.com ([fe80::c1ba:b4c:fe6f:d171]) by MWHPR1001MB2158.namprd10.prod.outlook.com ([fe80::c1ba:b4c:fe6f:d171%7]) with mapi id 15.20.5206.025; Sat, 7 May 2022 00:52:40 +0000 From: Indu Bhagat To: binutils@sourceware.org Subject: [PATCH,RFC 6/7] unwinder: generate backtrace using CTF Frame format Date: Fri, 6 May 2022 17:52:22 -0700 Message-Id: <20220507005223.3093035-7-indu.bhagat@oracle.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220507005223.3093035-1-indu.bhagat@oracle.com> References: <20220507005223.3093035-1-indu.bhagat@oracle.com> Content-Transfer-Encoding: quoted-printable Content-Type: text/plain X-ClientProxiedBy: MW2PR16CA0066.namprd16.prod.outlook.com (2603:10b6:907:1::43) 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: 72c1913f-18dd-4e35-b206-08da2fc3e30e X-MS-TrafficTypeDiagnostic: MWHPR10MB1517: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: ol3iDw2UhFWXNfffAa0iaYII0CGfhygF49SZi+zY9kYRUcyVQQGB/yJGDxKl1Sy4b2Wtkeu2+5TQW7EWsBeC8Y62dN1cFvfZDQXH3wsAWm+bxPCSeMocqdb9HEYLPc0G7Lz2sbA3m1wN/dfgJD9BvOE/w5hbdv+U52eqM2VK776P/zjQNoEIg/CnQFBKiglH475/wNx/trxXUynPfOjGyeLnLIUI99D/bODalD17H6qJ0oyBOuTgtXvh6JV1KdY7h2jWw8mw87WRv1HNSSx5xWzftpPbbJU1Jles0+D9l48tm/e4MUK0TlMoYIDegSp99h89rIrJ+kAsSxG46ti77zwwzgQFR45PTzf2BrUR+xizk/+ZgO9F31of8E1vjNroZVtmrh6RTmlUtgKRZ6CesATDbl/jgXZbVCbRerLvnKNQ09apQOSCZT+bmJSMVGP5h2fB5Qpjx1NFc65VuLVSbmPQKMGzZsfV3QvT8iebUtD9KoAaCyn44n5Qz/bbuHbpNB2Da9GF+ucEkSvtmy9XEeVm8L1ahYPqk2TuWgDzS0qcmmtsb96xY0KjNvioQiq8xfRKLgCci9tWs6Rmb3KHl474gk2hHlTPZE06aOKGAzd3RvVfZO+0ss+Rsora7BV0i6UjddQTf7U3q4JBuNg4Xa/sfUWrdhEj4jZAucgNSMLMLFN7mfW6DxtI1t1ELWwwUBTg4EsZGmuunbGvQmUDhoNRWVqhLoQdgV1WTgdPmYcYNRMGzaDYfHkHia0rUJB72X194XBDojPtYQrF2rLIV0E6fZegTot4VodERMq57wuxexdv56MlUYWXhqmlNLFn 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:(13230001)(366004)(186003)(2906002)(316002)(8936002)(38350700002)(2616005)(26005)(1076003)(38100700002)(6486002)(52116002)(6666004)(5660300002)(66946007)(66556008)(6506007)(36756003)(8676002)(83380400001)(44832011)(66476007)(508600001)(30864003)(86362001)(6916009)(6512007)(2004002); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?kVsfeViBsEV+9QWCgmzOrXraqpxkL65jav9YkmwuxhBzzOOstMGITy5IxhsO?= =?us-ascii?Q?4ol9a9vcWL9eCf3+nO2VCuy4iq7nm9FTN2LC1qQpCxFbLhj+yDF9O31yLm0K?= =?us-ascii?Q?zLHiY+leTDGszCFkWcOU7+fNeofisv9MTyM78zKOSy1WLO2OsplT8zJaBDn2?= =?us-ascii?Q?0xcSHqJQY29Le//NZHqd3pRWMp1b48Ogf0myP59nNIribF/MWC+ZH3OlltTu?= =?us-ascii?Q?ckZiEdCtpNRY8Y8W6KoTUrUfR153iA3HAL6b8pv25IguQ9KSAJ5oCPtHGsAD?= =?us-ascii?Q?BPWD30qbEFNEpqvwYW7OeBt45KgUE3hG4Zo4Vv1CN+F3pLj/9pJMMaTcOZjB?= =?us-ascii?Q?f3r2mQS0xprhiYB3A61aFxqKP57CtuewA+C1Bt9vrqU7d6FAvRCs94D28MG0?= =?us-ascii?Q?jO6Bbd+whfwxdQB/WD2yK8RdKIjcmOKU1w8Ypvo4000u0waD0wiX7FCjTFJ2?= =?us-ascii?Q?auKIT00DfybRoITQfFook0RZqD+vXqtQDhyr50Zq3DSZfXGwDJh+7TXlF4dz?= =?us-ascii?Q?e6PnhFVquvXpS/0aaWwpl9ku1khMr9TO/9EOUZZ3XIIIBNCzPKF56REYwUWZ?= =?us-ascii?Q?Z1pnks38QQRvUwaZ4gaKTheDmiyEXbXDaF++8Ua1zeg1lnEagiwPonYQ5KUZ?= =?us-ascii?Q?aqWY8yJJJR3OUyGt5yTMn0F5OiST7EcQujOiXBRbsVkt8KJhD/Vy4SrLaJd5?= =?us-ascii?Q?XeU9GR103M56bR+ONWSPyS6Wg98M/0lEj9TvTpQSrG/HDmTMEnYR3tuZc47o?= =?us-ascii?Q?OHhkhZpmGBoYC4K6eT+HpkfZMsEPoGWBCB3lgx2mo1pR3niRRq86+/Wry+P8?= =?us-ascii?Q?5chgRNe1Bj3U+r8iJ8SGgfjd8tbMKUS/SA1cXFMOylZi4+mf8+AtmgcU6Hxh?= =?us-ascii?Q?nsygRN/iQ+JYvwJgVurF7hkkq1gcdrixC+VTKbi6YXBLl8SEkwe+fvxq2AyQ?= =?us-ascii?Q?xheNrm5phfoT+GJi5hGBiAp+QHbFP1spjw+Ryvn+XImEzq/fFC/Othu3hQkZ?= =?us-ascii?Q?ZLE14P1tw4NSiQIwZd2C7O1Mi/y03xvas4sf9Z7rtGRv8KWScUA3ZAmvtVrq?= =?us-ascii?Q?89lsfMWqUh2ufd/4KaA1OvvV06LYTVyWF3/7HN6qUpjHxnvlsuVk6tJd2nnP?= =?us-ascii?Q?o55bM97DVFudSEfvhv6P6KqsYtfU0POzFkYLGmNWUfylQWjvnXHiCml9CANJ?= =?us-ascii?Q?tPXsQWC+XxAz1sHgYuERmd+A1IDMALiWMaSiZ1S+wXbcZ4UHer+Qek7ecCNc?= =?us-ascii?Q?PA6pPF9IT0JKnBPpEXTPbMj4D/R7y4Jwnj9CiIhMJYxUiSJfs+Kf2krvFEKk?= =?us-ascii?Q?B3L1OvbGcFuqds+daZ65e9AuIjHMBPvIU+Sr9lWC966exhhpy8KosH8FM3gT?= =?us-ascii?Q?Aa/rlrAaX9YWXHsFcKXEYpiov0AnbN4kiXU95MJTvFJrITQ7OtneTwkCbV2T?= =?us-ascii?Q?k/q1URWUSNiqANa0TyeO/AAXdU4DJRcvGvISbNF7zwma5VvoC2fzf0FeHOCw?= =?us-ascii?Q?B0DxMDZ5zwzg0t5Caicltnno43jv8cpxqD+z5CDh6RxWH0xgpGUSamJO51Yw?= =?us-ascii?Q?SDiW1FbTJs8GEKyZy4T2D4L+6rMfMW1urttj/PUWOfB3JT87YGmZ49CU6njS?= =?us-ascii?Q?Panm9xVNP/SpFgeNlgdo1CxiLbmlxiVm4B+inKpnW9OypyGWxFg4mVbg2EsO?= =?us-ascii?Q?6lbaxYw1iekcS6h2S334butZ53qywOAqZqopA5CWTQFVnz4Y8vxPz3/1et6m?= =?us-ascii?Q?Y7R726FdWQ=3D=3D?= X-OriginatorOrg: oracle.com X-MS-Exchange-CrossTenant-Network-Message-Id: 72c1913f-18dd-4e35-b206-08da2fc3e30e X-MS-Exchange-CrossTenant-AuthSource: MWHPR1001MB2158.namprd10.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 May 2022 00:52:40.4303 (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: mcho6sXY8zI1KJNPUftIx6i5vxSo3L7I1M0AqLptfFFxhV4ZqvMyoBbqWSy0VFUbao8suyjJQUTKRvMqw0Tkow== X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR10MB1517 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.486, 18.0.858 definitions=2022-05-06_07:2022-05-05, 2022-05-06 signatures=0 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 spamscore=0 suspectscore=0 adultscore=0 bulkscore=0 phishscore=0 mlxlogscore=999 mlxscore=0 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2202240000 definitions=main-2205070003 X-Proofpoint-GUID: 4DbNajfgbottri1iAd9jkJIjXbV8kQFg X-Proofpoint-ORIG-GUID: 4DbNajfgbottri1iAd9jkJIjXbV8kQFg X-Spam-Status: No, score=-13.2 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, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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: Sat, 07 May 2022 00:52:51 -0000 From: Weimin Pan A simple unwinder based on CTF Frame format. Changelog: * include/ctf-backtrace-api.h: New file. * libctfframe/ctf-backtrace-err.c: Likewise. * libctfframe/ctf-backtrace.c: Likewise. * libctfframe/ttest.c: Likewise. * libctfframe/Makefile.am: Build backtrace functionality in its own library. * libctfframe/Makefile.in: Regenerated. --- include/ctf-backtrace-api.h | 57 +++ libctfframe/Makefile.am | 13 +- libctfframe/Makefile.in | 81 ++++- libctfframe/ctf-backtrace-err.c | 46 +++ libctfframe/ctf-backtrace.c | 617 ++++++++++++++++++++++++++++++++ libctfframe/ttest.c | 78 ++++ 6 files changed, 871 insertions(+), 21 deletions(-) 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/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 e321e071517..7af718d68b3 100644 --- a/libctfframe/Makefile.am +++ b/libctfframe/Makefile.am @@ -23,16 +23,19 @@ 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 -lib_LTLIBRARIES =3D libctfframe.la -include_HEADERS =3D $(INCDIR)/ctf-frame.h $(INCDIR)/ctf-frame-api.h +lib_LTLIBRARIES =3D libctfframe.la libctfbacktrace.la +include_HEADERS =3D $(INCDIR)/ctf-frame.h $(INCDIR)/ctf-frame-api.h $(INCD= IR)/ctf-backtrace-api.h else include_HEADERS =3D -noinst_LTLIBRARIES =3D libctfframe.la +noinst_LTLIBRARIES =3D libctfframe.la libctfbacktrace.la endif =20 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 + +libctfbacktrace_la_SOURCES =3D ctf-backtrace.c ctf-backtrace-err.c +libctfbacktrace_la_CPPFLAGS =3D -I$(srcdir) -I$(srcdir)/../include diff --git a/libctfframe/Makefile.in b/libctfframe/Makefile.in index 50a720c8a99..dfba303ffe7 100644 --- a/libctfframe/Makefile.in +++ b/libctfframe/Makefile.in @@ -159,14 +159,21 @@ am__uninstall_files_from_dir =3D { \ } am__installdirs =3D "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)" LTLIBRARIES =3D $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) -libctfframe_la_LIBADD =3D -am_libctfframe_la_OBJECTS =3D ctf-frame.lo ctf-frame-dump.lo \ - ctf-frame-error.lo -libctfframe_la_OBJECTS =3D $(am_libctfframe_la_OBJECTS) +libctfbacktrace_la_LIBADD =3D +am_libctfbacktrace_la_OBJECTS =3D libctfbacktrace_la-ctf-backtrace.lo \ + 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 +@INSTALL_LIBBFD_FALSE@am_libctfbacktrace_la_rpath =3D +@INSTALL_LIBBFD_TRUE@am_libctfbacktrace_la_rpath =3D -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) @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@) @@ -203,15 +210,15 @@ 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 $(libctfbacktrace_la_SOURCES) $(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 + $(INCDIR)/ctf-frame-api.h $(INCDIR)/ctf-backtrace-api.h HEADERS =3D $(include_HEADERS) am__tagged_files =3D $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)config.h.in @@ -368,7 +375,6 @@ pdfdir =3D @pdfdir@ prefix =3D @prefix@ program_transform_name =3D @program_transform_name@ psdir =3D @psdir@ -runstatedir =3D @runstatedir@ sbindir =3D @sbindir@ sharedstatedir =3D @sharedstatedir@ srcdir =3D @srcdir@ @@ -383,14 +389,17 @@ 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_TRUE@lib_LTLIBRARIES =3D libctfframe.la libctfbacktrace.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@include_HEADERS =3D $(INCDIR)/ctf-frame.h $(INCDIR)/c= tf-frame-api.h $(INCDIR)/ctf-backtrace-api.h +@INSTALL_LIBBFD_FALSE@noinst_LTLIBRARIES =3D libctfframe.la libctfbacktrac= e.la 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 + +libctfbacktrace_la_SOURCES =3D ctf-backtrace.c ctf-backtrace-err.c +libctfbacktrace_la_CPPFLAGS =3D -I$(srcdir) -I$(srcdir)/../include all: config.h $(MAKE) $(AM_MAKEFLAGS) all-am =20 @@ -491,6 +500,9 @@ clean-noinstLTLIBRARIES: rm -f $${locs}; \ } =20 +libctfbacktrace.la: $(libctfbacktrace_la_OBJECTS) $(libctfbacktrace_la_DEP= ENDENCIES) $(EXTRA_libctfbacktrace_la_DEPENDENCIES)=20 + $(AM_V_CCLD)$(LINK) $(am_libctfbacktrace_la_rpath) $(libctfbacktrace_la_O= BJECTS) $(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 @@ -500,9 +512,11 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c =20 -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctf-frame-dump.Plo@am__qu= ote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctf-frame-error.Plo@am__q= uote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctf-frame.Plo@am__quote@ +@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@ =20 .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.= Tpo -c -o $@ $< @@ -525,6 +539,41 @@ 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) $(AM_CFLAGS) $(CFLA= GS) -MT libctfbacktrace_la-ctf-backtrace.lo -MD -MP -MF $(DEPDIR)/libctfbac= ktrace_la-ctf-backtrace.Tpo -c -o libctfbacktrace_la-ctf-backtrace.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) $(AM_CF= LAGS) $(CFLAGS) -c -o libctfbacktrace_la-ctf-backtrace.lo `test -f 'ctf-bac= ktrace.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) $(AM_CFLAGS) $(CFLA= GS) -MT libctfbacktrace_la-ctf-backtrace-err.lo -MD -MP -MF $(DEPDIR)/libct= fbacktrace_la-ctf-backtrace-err.Tpo -c -o libctfbacktrace_la-ctf-backtrace-= err.lo `test -f 'ctf-backtrace-err.c' || echo '$(srcdir)/'`ctf-backtrace-er= r.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) $(AM_CF= LAGS) $(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 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source=3D'ctf-frame.c' object= =3D'libctfframe_la-ctf-frame.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) $(libctfframe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS= ) $(CFLAGS) -c -o libctfframe_la-ctf-frame.lo `test -f 'ctf-frame.c' || ech= o '$(srcdir)/'`ctf-frame.c + +libctfframe_la-ctf-frame-dump.lo: ctf-frame-dump.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-dump.lo -MD -MP -MF $(DEPDIR)/libctfframe_la-c= tf-frame-dump.Tpo -c -o libctfframe_la-ctf-frame-dump.lo `test -f 'ctf-fram= e-dump.c' || echo '$(srcdir)/'`ctf-frame-dump.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libctfframe_la-ctf-fram= e-dump.Tpo $(DEPDIR)/libctfframe_la-ctf-frame-dump.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source=3D'ctf-frame-dump.c' ob= ject=3D'libctfframe_la-ctf-frame-dump.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) $(libctfframe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS= ) $(CFLAGS) -c -o libctfframe_la-ctf-frame-dump.lo `test -f 'ctf-frame-dump= .c' || echo '$(srcdir)/'`ctf-frame-dump.c + +libctfframe_la-ctf-frame-error.lo: ctf-frame-error.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-error.lo -MD -MP -MF $(DEPDIR)/libctfframe_la-= ctf-frame-error.Tpo -c -o libctfframe_la-ctf-frame-error.lo `test -f 'ctf-f= rame-error.c' || echo '$(srcdir)/'`ctf-frame-error.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libctfframe_la-ctf-fram= e-error.Tpo $(DEPDIR)/libctfframe_la-ctf-frame-error.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source=3D'ctf-frame-error.c' o= bject=3D'libctfframe_la-ctf-frame-error.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) $(libctfframe_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS= ) $(CFLAGS) -c -o libctfframe_la-ctf-frame-error.lo `test -f 'ctf-frame-err= or.c' || echo '$(srcdir)/'`ctf-frame-error.c + mostlyclean-libtool: -rm -f *.lo =20 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..c17a8dcfffd --- /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_free_decoder (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_free_decoder (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