From patchwork Wed Jul 23 14:23:45 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Remus X-Patchwork-Id: 116834 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 66A7C3858C78 for ; Wed, 23 Jul 2025 14:26:01 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 66A7C3858C78 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=ibm.com header.i=@ibm.com header.a=rsa-sha256 header.s=pp1 header.b=JFmmJ57H X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) by sourceware.org (Postfix) with ESMTPS id 61C0D3858C2A for ; Wed, 23 Jul 2025 14:24:05 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 61C0D3858C2A Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linux.ibm.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 61C0D3858C2A Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=148.163.158.5 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1753280645; cv=none; b=ddCz361135c28QCuK1aDg58b9/Kp9DfM+UkYsiH5T7C6YueECtX8c4KIJJxYOWWlXUsoIZNNut4aMArQxbhJH/N1qpGP2NFo/XxTDe0H1bWWZsvvW9vp0dv31j2zPu7cmhV7X9He2lgh+DxR0GubpffKaVBe4Hy4kOrSs0eqk4A= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1753280645; c=relaxed/simple; bh=0ZHdEBcKehZV7f6w/+mVvWJdNKoSLrvwgEsYCd1H2xA=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=DxSm2QpCVB/wUtE0Ir+63TVYD+xTWGxhKH3S4pzDUmc51E4/Rc96wquEgBdC+C338cuvT8/wCWFVEmuBWsRQQcIcxiuWOq3k7lKrDZNqws2lM+MuFnZFpWpY+mT3YR7ZkXbi2lI5VBSfLtRmSpQc9FV8p2NFyHLhElM2ifvp7fE= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 61C0D3858C2A Received: from pps.filterd (m0353725.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 56N5mLht005176; Wed, 23 Jul 2025 14:24:01 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=VT9qp+pHsX+Tiz7I5 SIzEYs0ES0BzBkYSBkwhRKAIc0=; b=JFmmJ57H07ZjNp8UqR6RCpIi15Vm9LNal jHoeP6C+rP8V/YRZZWcFJ0LWV4+ClMslTKwcfCr1gMQGJwwdrQVDHN6yPkLKEBKd 6BqrEoMcT40NLdvCRirf0OUMFD0TzsCm7n3WvTDix+r9HeEsWeR4YsKVi9lNbunt hlv0LuHUjk7nRqaYGaPRPSrYV06pSZeuRRwPEKOU1m+WScP742HXk+zWsSpIqFVw T3XDXTR1r0B9g2a9fFYN8ughalgFIQ9j5QkE79XAq91+HmIVulgbnGtzdYyyXsYN 0HMKaXNge340m0tZkf0NK2WeJ9fC6uSiJfN0aqbR2z0Xdi8CD3PSg== Received: from ppma22.wdc07v.mail.ibm.com (5c.69.3da9.ip4.static.sl-reverse.com [169.61.105.92]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 482ff4w9bd-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 23 Jul 2025 14:24:00 +0000 (GMT) Received: from pps.filterd (ppma22.wdc07v.mail.ibm.com [127.0.0.1]) by ppma22.wdc07v.mail.ibm.com (8.18.1.2/8.18.1.2) with ESMTP id 56NBNfSP012867; Wed, 23 Jul 2025 14:24:00 GMT Received: from smtprelay05.fra02v.mail.ibm.com ([9.218.2.225]) by ppma22.wdc07v.mail.ibm.com (PPS) with ESMTPS id 480p308aug-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 23 Jul 2025 14:24:00 +0000 Received: from smtpav02.fra02v.mail.ibm.com (smtpav02.fra02v.mail.ibm.com [10.20.54.101]) by smtprelay05.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 56NENuPv46727606 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 23 Jul 2025 14:23:56 GMT Received: from smtpav02.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1E2732004E; Wed, 23 Jul 2025 14:23:56 +0000 (GMT) Received: from smtpav02.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id E85D22004F; Wed, 23 Jul 2025 14:23:55 +0000 (GMT) Received: from tuxmaker.lnxne.boe (unknown [9.152.85.9]) by smtpav02.fra02v.mail.ibm.com (Postfix) with ESMTP; Wed, 23 Jul 2025 14:23:55 +0000 (GMT) From: Jens Remus To: libc-alpha@sourceware.org, Stefan Liebler , Claudiu Zissulescu-Ianculescu Cc: Jens Remus , Indu Bhagat , Elena Zannoni , Adhemerval Zanella , Florian Weimer Subject: [RFC PATCH v3 1/3] sframe: Support for RA undefined as indication for outermost frame Date: Wed, 23 Jul 2025 16:23:45 +0200 Message-ID: <20250723142347.2159793-2-jremus@linux.ibm.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250723142347.2159793-1-jremus@linux.ibm.com> References: <20250723142347.2159793-1-jremus@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: WB1dHyt0t2Ivng9CiuZihbIvl0CBYE64 X-Proofpoint-ORIG-GUID: WB1dHyt0t2Ivng9CiuZihbIvl0CBYE64 X-Authority-Analysis: v=2.4 cv=Ae2xH2XG c=1 sm=1 tr=0 ts=6880f080 cx=c_pps a=5BHTudwdYE3Te8bg5FgnPg==:117 a=5BHTudwdYE3Te8bg5FgnPg==:17 a=Wb1JkmetP80A:10 a=VnNF1IyMAAAA:8 a=c5rbQTjCflaalalGhagA:9 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNzIzMDEyMiBTYWx0ZWRfX03S8vvtox3GJ jNqpQIItsunyXIzQDCY4Ro6ssHRqpLN9nuoJDgnDczRbAwiJzkYanpRktozUZl6UPgI5wMT1TMh X0Upitx9FctHGQ4p0TE5J16VqOgD7pBb756o1KEnk0gmuqaNhqq3Swe1/5vNNDiDA+S24wfqYOu 9xwxFsZ4tWyCfwgwwToAH6ez7ZQKseebhRbnmv1nYFjz5EjS8Wyk5MGdzvjt7SBToKFswo4Ggmk V+4ktmLXlItg6ruq6LAFHp3f5+BhFZbqKaHfwTSJTwdBWLzJ7SFtaXmaWqjs1kyPA8Yy9zOIGlb d6uxu4MiCRb20NTwgAOGBg7gdVfyrFJkrR0OF1X0+gh3fy656LJOumjkDbtAWe+gXcmXVdmwlGT J/DTh/2dedMDhBf5WiEYuoFc6PB5EoSUSOpCZAWICkwd0huo6E/PhvhbFkJaJHit9H0ucUs2 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.1.9,FMLib:17.12.80.40 definitions=2025-07-23_02,2025-07-23_01,2025-03-28_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxlogscore=999 lowpriorityscore=0 adultscore=0 malwarescore=0 bulkscore=0 clxscore=1015 phishscore=0 impostorscore=0 suspectscore=0 priorityscore=1501 spamscore=0 mlxscore=0 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2505280000 definitions=main-2507230122 X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, GIT_PATCH_0, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_NONE, SPF_PASS, 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: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patchwork=sourceware.org@sourceware.org SFrame V2 has been enhanced to represent return address (RA) undefined as a SFrame FDE without any FREs and the FDE info word flag "RA undefined" set. This is backward compatible, as the flag was previously unused and therefore unset. In sense of DWARF an undefined rule for the RA indicates that there is no return address and the stack trace is complete because an explicitly as such marked outermost frame has been reached. Use a SFrame FDE without any FREs and "RA undefined" flag set as indication that an outermost frame has been reached and the stack trace is complete. sysdeps/generic/ * sframe.h (FDE info word): New flag "RA undefined". (SFRAME_V2_FUNC_RA_UNDEF, SFRAME_V2_FUNC_INFO_UPDATE_RA_UNDEF): New macros to test and set the "RA undefined" flag. * sframe-read.h (__sframe_find_fre): Return _URC_NORMAL_STOP if outermost frame reached. * sframe-read.c (__sframe_find_fre): Likewise, if FDE without any FREs and RA undefined set. * sframe.c (__stacktrace_sframe): Stop stack trace if outermost frame reached. Signed-off-by: Jens Remus --- Notes: Changes in v3: - New patch. sysdeps/generic/sframe-read.c | 11 +++++++++-- sysdeps/generic/sframe-read.h | 3 ++- sysdeps/generic/sframe.c | 9 ++++++++- sysdeps/generic/sframe.h | 17 ++++++++++++----- 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/sysdeps/generic/sframe-read.c b/sysdeps/generic/sframe-read.c index a6ebc42d6689..5a8573214d0c 100644 --- a/sysdeps/generic/sframe-read.c +++ b/sysdeps/generic/sframe-read.c @@ -570,8 +570,9 @@ __sframe_decode (sframe_decoder_ctx *dctx, const char *sf_buf) return _URC_NO_REASON; } -/* Find the SFrame Row Entry which contains the PC. Returns - _URC_END_OF_STACK if failure. */ +/* Find the SFrame Frame Row Entry which contains the PC. Returns + _URC_END_OF_STACK if failure, _URC_NORMAL_STOP if outermost + frame reached, or _URC_NO_REASON otherwise. */ _Unwind_Reason_Code __sframe_find_fre (sframe_decoder_ctx *ctx, int32_t pc, @@ -595,6 +596,12 @@ __sframe_find_fre (sframe_decoder_ctx *ctx, int32_t pc, if (fdep == NULL || ctx->sfd_fres == NULL) return _URC_END_OF_STACK; + /* A FDE without any FREs and RA undefined flag set indicates an + outermost frame. */ + if (fdep->sfde_func_num_fres == 0 + && SFRAME_V2_FUNC_RA_UNDEF (fdep->sfde_func_info)) + return _URC_NORMAL_STOP; + fre_type = sframe_get_fre_type (fdep); fres = ctx->sfd_fres + fdep->sfde_func_start_fre_off; diff --git a/sysdeps/generic/sframe-read.h b/sysdeps/generic/sframe-read.h index 146142143c6b..79a2b0f83bd2 100644 --- a/sysdeps/generic/sframe-read.h +++ b/sysdeps/generic/sframe-read.h @@ -64,7 +64,8 @@ extern _Unwind_Reason_Code __sframe_decode (sframe_decoder_ctx *dctx, const char *cf_buf); /* Find the SFrame Frame Row Entry which contains the PC. Returns - _URC_END_OF_STACK if failure. */ + _URC_END_OF_STACK if failure, _URC_NORMAL_STOP if outermost + frame reached, or _URC_NO_REASON otherwise. */ extern _Unwind_Reason_Code __sframe_find_fre (sframe_decoder_ctx *ctx, int32_t pc, diff --git a/sysdeps/generic/sframe.c b/sysdeps/generic/sframe.c index ba0830da3d30..0dff78a9cacc 100644 --- a/sysdeps/generic/sframe.c +++ b/sysdeps/generic/sframe.c @@ -56,6 +56,7 @@ __stacktrace_sframe (void **ra_lst, int count, frame *frame) frame_ptr; int cfa_offset, fp_offset, ra_offset, i; sframe_frame_row_entry fred, *frep = &fred; + _Unwind_Reason_Code rc; if (!ra_lst || !count) return 0; @@ -98,7 +99,8 @@ __stacktrace_sframe (void **ra_lst, int count, frame *frame) pc = frame->pc - sframe_vma; /* Find the SFrame Row Entry which contains the PC. */ - if (__sframe_find_fre (dctx, pc, frep) == _URC_END_OF_STACK) + rc = __sframe_find_fre (dctx, pc, frep); + if (rc == _URC_END_OF_STACK) { #ifdef MD_DECODE_SIGNAL_FRAME /* If there are no valid FREs, check if it is a signal @@ -116,6 +118,11 @@ __stacktrace_sframe (void **ra_lst, int count, frame *frame) /* Force fallback to DWARF stacktracer. */ return 0; } + else if (rc == _URC_NORMAL_STOP) + { + /* Outermost frame reached. Stack trace is complete. */ + return i; + } /* Get the CFA offset from the FRE. If offset is unavailable, sets err. */ diff --git a/sysdeps/generic/sframe.h b/sysdeps/generic/sframe.h index e38adcfe1769..6225eda5d6dc 100644 --- a/sysdeps/generic/sframe.h +++ b/sysdeps/generic/sframe.h @@ -196,12 +196,13 @@ typedef struct sframe_func_desc_entry - 4-bits: Identify the FRE type used for the function. - 1-bit: Identify the FDE type of the function - mask or inc. - 1-bit: PAC authorization A/B key (aarch64). - - 2-bits: Unused. + - 1-bit: Identify whether the RA is undefined (i.e. outermost frame). + - 1-bit: Unused. ------------------------------------------------------------------------ - | Unused | PAC auth A/B key (aarch64) | FDE type | FRE type | - | | Unused (amd64) | | | + | Unused| RA | PAC auth A/B key (aarch64) | FDE type | FRE type | + | | undef.| Unused (amd64) | | | ------------------------------------------------------------------------ - 8 6 5 4 0 */ + 8 7 6 5 4 0 */ uint8_t sfde_func_info; /* Size of the block of repeating insns. Used for SFrame FDEs of type SFRAME_FDE_TYPE_PCMASK. */ @@ -211,7 +212,8 @@ typedef struct sframe_func_desc_entry /* Macros to compose and decompose function info in FDE. */ -/* Note: Set PAC auth key to SFRAME_AARCH64_PAUTH_KEY_A by default. */ +/* Note: Set PAC auth key to SFRAME_AARCH64_PAUTH_KEY_A and RA undefined to + 0 by default. */ #define SFRAME_V1_FUNC_INFO(fde_type, fre_enc_type) \ (((SFRAME_AARCH64_PAUTH_KEY_A & 0x1) << 5) | \ (((fde_type) & 0x1) << 4) | ((fre_enc_type) & 0xf)) @@ -219,11 +221,16 @@ typedef struct sframe_func_desc_entry #define SFRAME_V1_FUNC_FRE_TYPE(data) ((data) & 0xf) #define SFRAME_V1_FUNC_FDE_TYPE(data) (((data) >> 4) & 0x1) #define SFRAME_V1_FUNC_PAUTH_KEY(data) (((data) >> 5) & 0x1) +#define SFRAME_V2_FUNC_RA_UNDEF(data) (((data) >> 6) & 0x1) /* Set the pauth key as indicated. */ #define SFRAME_V1_FUNC_INFO_UPDATE_PAUTH_KEY(pauth_key, fde_info) \ ((((pauth_key) & 0x1) << 5) | ((fde_info) & 0xdf)) +/* Set the RA undefined flag as indicated. */ +#define SFRAME_V2_FUNC_INFO_UPDATE_RA_UNDEF(ra_undef, fde_info) \ + ((((ra_undef) & 0x1) << 6) | ((fde_info) & 0xbf)) + /* Size of stack frame offsets in an SFrame Frame Row Entry. A single SFrame FRE has all offsets of the same size. Offset size may vary across frame row entries. */ From patchwork Wed Jul 23 14:23:46 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Remus X-Patchwork-Id: 116836 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6EB303858C78 for ; Wed, 23 Jul 2025 14:30:14 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6EB303858C78 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=ibm.com header.i=@ibm.com header.a=rsa-sha256 header.s=pp1 header.b=Dlox6JQW X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) by sourceware.org (Postfix) with ESMTPS id 954003858C41 for ; Wed, 23 Jul 2025 14:24:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 954003858C41 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linux.ibm.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 954003858C41 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1753280647; cv=none; b=DnwiWj/2uwt8cQClOup0v6RpIQZ5qA2wgw/cHT1jaPg2wlXr2jsSQ0mTi7wsnLLfoJt0IkoHg/BGS++xO+yMFNtDlEXMptUkSsGgl2/3uQngFqujre0+KGHuVPUgOkPYs0KxBQ2qma20eoNL5af8W7/EJGBdnDN4TWbcbfv0KaQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1753280647; c=relaxed/simple; bh=omIkEHZwDKw+SpfKscW7Lsize80Qtor+NzP7LERQ8DU=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=a9Y8ls4jyTOdc540PN8M5gGKudi/DQOHg8dfRoCLFQKdmAJURulgq8Pvcb/1/Hcex1FQmqBP/hridNEUNR1MtCJX2Huq7rRamoKmon05COwcEPGPcy/1iv3FXByblsP8VPwYIPN2x3tZi9xkGC9zvAB/VGO8cbL99CgPU3//rH4= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 954003858C41 Received: from pps.filterd (m0360083.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 56NDTBBF021834; Wed, 23 Jul 2025 14:24:01 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=TaE/8Tn9/5JkIbHd5 PuKyMd5rKmaQy8sfi8CzSN47yk=; b=Dlox6JQWfQvv0stpaGib0ZglRTesf06IQ 5/Ljbs87HVhacxR4TnmxOEFQN3vz/LSj/GTS9nPNstSZyWyv04yOiQ653MnyVnLw jEwyzaP1h9d01Yy7sAL2PYzZSgEsC8wOgZlwUulZtF8RS0O8vN+z17AXmKj6xcxB Qk+2lPtbJttxZkEHVqZM4szFlkTk64lM+FMPFI+bEbRm5tUKLA6kxm0ZVaiclyPg UhQxV2Z1+jOvqptsedaL6PmZ1yhepRiXB3KSHTtdHiVazcqYtf6RDmuVblshmJj3 dcBa4N6qfM3fykcoVpHZlUClXxoPYoUj4PYyN1qW4GFJSIzmUbhDg== Received: from ppma13.dal12v.mail.ibm.com (dd.9e.1632.ip4.static.sl-reverse.com [50.22.158.221]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 482ffbdaq4-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 23 Jul 2025 14:24:00 +0000 (GMT) Received: from pps.filterd (ppma13.dal12v.mail.ibm.com [127.0.0.1]) by ppma13.dal12v.mail.ibm.com (8.18.1.2/8.18.1.2) with ESMTP id 56NC9G55005486; Wed, 23 Jul 2025 14:24:00 GMT Received: from smtprelay05.fra02v.mail.ibm.com ([9.218.2.225]) by ppma13.dal12v.mail.ibm.com (PPS) with ESMTPS id 480tvqyd7c-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 23 Jul 2025 14:23:59 +0000 Received: from smtpav02.fra02v.mail.ibm.com (smtpav02.fra02v.mail.ibm.com [10.20.54.101]) by smtprelay05.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 56NENuKl45547994 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 23 Jul 2025 14:23:56 GMT Received: from smtpav02.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5858F20043; Wed, 23 Jul 2025 14:23:56 +0000 (GMT) Received: from smtpav02.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 256D42005A; Wed, 23 Jul 2025 14:23:56 +0000 (GMT) Received: from tuxmaker.lnxne.boe (unknown [9.152.85.9]) by smtpav02.fra02v.mail.ibm.com (Postfix) with ESMTP; Wed, 23 Jul 2025 14:23:56 +0000 (GMT) From: Jens Remus To: libc-alpha@sourceware.org, Stefan Liebler , Claudiu Zissulescu-Ianculescu Cc: Jens Remus , Indu Bhagat , Elena Zannoni , Adhemerval Zanella , Florian Weimer , Ulrich Weigand Subject: [RFC PATCH v3 2/3] sframe: Start stack trace from PC and CFA Date: Wed, 23 Jul 2025 16:23:46 +0200 Message-ID: <20250723142347.2159793-3-jremus@linux.ibm.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250723142347.2159793-1-jremus@linux.ibm.com> References: <20250723142347.2159793-1-jremus@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: uCYPKRH2H7crkBTlSB0D5uEU2YgKhvib X-Authority-Analysis: v=2.4 cv=De8XqutW c=1 sm=1 tr=0 ts=6880f081 cx=c_pps a=AfN7/Ok6k8XGzOShvHwTGQ==:117 a=AfN7/Ok6k8XGzOShvHwTGQ==:17 a=Wb1JkmetP80A:10 a=CCpqsmhAAAAA:8 a=KKAkSRfTAAAA:8 a=VnNF1IyMAAAA:8 a=uiZiMkIqLlmwgNZYY4MA:9 a=ul9cdbp4aOFLsgKbc677:22 a=cvBusfyB2V15izCimMoJ:22 X-Proofpoint-GUID: uCYPKRH2H7crkBTlSB0D5uEU2YgKhvib X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNzIzMDEyMiBTYWx0ZWRfXyjGYXMlxEjbq TCrt8VYsr5zT7NGWuIKOJbC3G6fKbBF/pG1zuQ8k2Q2ireobF5/0KGvqC7el1uok87kUxQoUrSa cGdEbOEqYvBu103JGIhnoNXjyfw9MrFllwGS+FWwt/We5x6I7qK43o0oLGiQ1Q+npKdtnHVrnKE Ue1N+j41C+5+gCptmlBV6ocpLU2vpyFMxRBGuijNNv59/fGRtkp4BGmw1Yak9W/H0L5mWgIT3cw nSMcGhrygRf4xg7OB7NhJq8rrWvqDy+zrZJuPfZLq2FTeml/SBvKvp3xSvAHCEso59xcSTVfV9O sAJFp1nlvfkbr5ZGjCxIJC9fTEZ6JoATp7aPCMoFBTPp1YkHzInfvWwX6VCfR+qRm/K0A6nLXNS Mi/qJpFikw0jkvIYmqRq2rTb+1XPVSjQwTEVsQxpl8WkcgZwbVsfFY5PLvFRfGlOI33R1W7g X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.1.9,FMLib:17.12.80.40 definitions=2025-07-23_02,2025-07-23_01,2025-03-28_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 bulkscore=0 lowpriorityscore=0 mlxscore=0 mlxlogscore=999 suspectscore=0 priorityscore=1501 clxscore=1015 phishscore=0 adultscore=0 malwarescore=0 impostorscore=0 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2505280000 definitions=main-2507230122 X-Spam-Status: No, score=-12.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_NONE, SPF_PASS, 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: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patchwork=sourceware.org@sourceware.org Stack tracing in backtrace using SFrame stack trace information starts with a PC (program counter) in backtrace and the related SP (stack pointer) and FP (frame pointer) values. The following are then derived using SFrame information: - CFA (Canonical Frame Address): Using the tracked CFA base register (SP or FP) and tracked CFA offset from CFA base register - SP: Using the CFA (the CFA is defined as SP at call site on most architectures) - RA (return address): Using the CFA and the tracked RA stack slot offset from CFA - FP: Using CFA and the tracked FP stack slot offset from CFA, otherwise it remains unchanged If the CFA is based on the FP or if the FP is not saved then the initial value of the FP is important. Either because it is required to determine the CFA (and from that the SP, FP, and RA) or because is not restored from its stack slot and thus needs to be known. On x86-64 and Aarch64 the initial FP (in backtrace) can be obtained using __builtin_frame_address (0). On s390-64 (s390x) this does not work as __builtin_frame_address (0) does not return the FP register value, even if a FP register is used (e.g. due to dynamic stack allocation). Instead __builtin_frame_address (0) always returns the SP register value at function entry. This is because GCC and Clang on s390x setup a FP register only as late as possible, for instance after static stack allocation, which makes the FP register value meaningless for FP-based stack tracing purposes. Stack tracing in backtrace always starts in backtrace itself. Therefore use __builtin_unwind_init to enforce saving of FP and RA, obtain the CFA using __builtin_dwarf_cfa, and determine the caller's SP, FP, and RA using that CFA and the SFrame FP and RA stack slot offsets, as those are now guaranteed to be saved. This avoids the need to obtain the initial SP and FP values at all. debug/ * backtrace.c (do_sframe_backtrace): Call __builtin_unwind_init, obtain the CFA using __builtin_dwarf_cfa, and initialize SP and FP with NULL. sysdeps/generic/ * sframe.h (struct cframe): Add field cfa, used for startup of SFrame stack trace. (__getSP): Remove helper. * sframe.c (__stacktrace_sframe): Use CFA from frame in topmost frame to startup SFrame stack trace. Treat FP not saved in topmost frame as error. Update CFA in frame. (__getSP): Remove helper. Suggested-by: Ulrich Weigand Signed-off-by: Jens Remus --- Notes: Changes in v3: - Rebase on top of Adhemerval's series "[PATCH v2 0/2] sframe: Disable by default and support SFRAME_F_FDE_FUNC_START_PCREL": https://inbox.sourceware.org/libc-alpha/20250721234236.1434590-1-adhemerval.zanella@linaro.org/ - Reword commit subject and GNU ChangeLog. Following are two options to resolve the SFrame strack trace startup issue on s390 64-bit (s390x): Option A: Introduce a helper macro that returns the FP value. The generic implementation (used on e.g. x86-64 and AArch64) would resolve to __builtin_frame_address (0). This is why is needs to be a macro. The s390 implementation would resolve to a new inline helper function s390_getFP (), that uses inline assembly to return the preferred FP register r11 value. Option B: Use __builtin_unwind_init to enforce saving of SP and FP at function entry and use __builtin_dwarf_cfa instead of SFrame information to obtain the initial CFA in the topmost frame (i.e. backtrace). This no longer requires the initial SP and FP values. The SP, FP, and RA of the caller are then obtained using the CFA (SP) and SFrame information from the stack register save slots (FP and RA). This patch implements Option B. debug/backtrace.c | 9 +++++--- sysdeps/generic/sframe.c | 47 +++++++++++++++++++++------------------- sysdeps/generic/sframe.h | 5 +---- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/debug/backtrace.c b/debug/backtrace.c index ea7ac4ddf0a4..d72f725d7da9 100644 --- a/debug/backtrace.c +++ b/debug/backtrace.c @@ -55,16 +55,19 @@ struct trace_arg backtracer can fall back to using the DWARF unwinder. This function must be always inline. Otherwise the - __builtin_frame_address and the __getXX helper functions will not + __builtin_dwarf_cfa and the __getPC helper functions will not return the right addresses. */ static inline int __attribute__ ((always_inline)) do_sframe_backtrace (void **array, int size) { frame frame; + /* Force saving of FP and RA on stack. */ + __builtin_unwind_init (); frame.pc = __getPC (); - frame.sp = __getSP (); - frame.fp = (_Unwind_Ptr) __builtin_frame_address (0); + frame.cfa = (_Unwind_Ptr) __builtin_dwarf_cfa (); + frame.sp = (_Unwind_Ptr) NULL; + frame.fp = (_Unwind_Ptr) NULL; return __stacktrace_sframe (array, size, &frame); } #endif diff --git a/sysdeps/generic/sframe.c b/sysdeps/generic/sframe.c index 0dff78a9cacc..67e019e3e773 100644 --- a/sysdeps/generic/sframe.c +++ b/sysdeps/generic/sframe.c @@ -124,16 +124,24 @@ __stacktrace_sframe (void **ra_lst, int count, frame *frame) return i; } - /* Get the CFA offset from the FRE. If offset is unavailable, - sets err. */ - cfa_offset = __sframe_fre_get_cfa_offset (dctx, frep, &err); - if (err != _URC_NO_REASON) - /* Force fallback to DWARF stacktracer. */ - return 0; - - /* Get CFA using base reg id from the FRE info. */ - cfa = ((__sframe_fre_get_base_reg_id (frep) - == SFRAME_BASE_REG_SP) ? frame->sp : frame->fp) + cfa_offset; + if (i == 0) + /* The caller (i.e. backtrace) provided its CFA value and ensured + to save its FP and RA at entry, so that the caller's SP, FP, and + RA at entry can be determined using the CFA. */ + cfa = frame->cfa; + else + { + /* Get the CFA offset from the FRE. If offset is unavailable, + sets err. */ + cfa_offset = __sframe_fre_get_cfa_offset (dctx, frep, &err); + if (err != _URC_NO_REASON) + /* Force fallback to DWARF stacktracer. */ + return 0; + + /* Get CFA using base reg id from the FRE info. */ + cfa = ((__sframe_fre_get_base_reg_id (frep) == SFRAME_BASE_REG_SP) + ? frame->sp : frame->fp) + cfa_offset; + } /* Get the RA offset from the FRE. If the offset is unavailable, sets err. */ @@ -153,7 +161,12 @@ __stacktrace_sframe (void **ra_lst, int count, frame *frame) unavailable, sets err. */ fp_offset = __sframe_fre_get_fp_offset (dctx, frep, &err); frame_ptr = frame->fp; - if (err == _URC_NO_REASON) + /* The FP must be saved in the topmost frame, as backtrace called + __builtin_unwind_init, which guarantees this. */ + if (i == 0 && err != _URC_NO_REASON) + /* Force fallback to DWARF stacktracer. */ + return 0; + else if (err == _URC_NO_REASON) { /* FP offset is available, get the value stored in the stack location. */ @@ -162,6 +175,7 @@ __stacktrace_sframe (void **ra_lst, int count, frame *frame) } /* Set up for the next frame. */ + frame->cfa = cfa; frame->fp = frame_ptr; frame->sp = cfa + SFRAME_SP_VAL_OFFSET; frame->pc = return_addr; @@ -181,14 +195,3 @@ __getPC (void) } libc_hidden_def (__getPC); - -/* A noinline helper used to obtain the caller's current SP. It - mimics gcc14's __builtin_stack_address() functionality. */ - -_Unwind_Ptr __attribute__ ((noinline)) -__getSP (void) -{ - return (_Unwind_Ptr) __builtin_dwarf_cfa() + SFRAME_SP_VAL_OFFSET; -} - -libc_hidden_def (__getSP); diff --git a/sysdeps/generic/sframe.h b/sysdeps/generic/sframe.h index 6225eda5d6dc..9cedcad257a2 100644 --- a/sysdeps/generic/sframe.h +++ b/sysdeps/generic/sframe.h @@ -362,6 +362,7 @@ typedef struct sframe_frame_row_entry_addr4 typedef struct cframe { _Unwind_Ptr pc; + _Unwind_Ptr cfa; _Unwind_Ptr sp; _Unwind_Ptr fp; } frame; @@ -374,10 +375,6 @@ libc_hidden_proto (__stacktrace_sframe); _Unwind_Ptr __getPC (void); libc_hidden_proto (__getPC); -/* Helper used by SFrame tracing algorithm. */ -_Unwind_Ptr __getSP (void); -libc_hidden_proto (__getSP); - #ifdef __cplusplus } #endif From patchwork Wed Jul 23 14:23:47 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Remus X-Patchwork-Id: 116835 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 57BB5385840F for ; Wed, 23 Jul 2025 14:27:51 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 57BB5385840F Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=ibm.com header.i=@ibm.com header.a=rsa-sha256 header.s=pp1 header.b=MvAOiIuT X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) by sourceware.org (Postfix) with ESMTPS id 2EC753858CD1 for ; Wed, 23 Jul 2025 14:24:11 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2EC753858CD1 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linux.ibm.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 2EC753858CD1 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1753280651; cv=none; b=hhED7qETykpH9x1UIaWQfb/lxjSbWsWFSR2g7Rkh02zkvhrnIKRHSeLSNomvZ3/4G2vOEj+5xgmHmfWv4CTERBduukm0qzeA8eU+y2auWLLcHiJHi7gynnsc69r880WsFLF7XR0qZRWpD8PHtoXJMIrxT3lz3XQOX7f00WNqx/o= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1753280651; c=relaxed/simple; bh=5zBNpmnHyon/MEK6yE8Wd6rXuXG4/z2VEdX0HiTbmII=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=w9mOB5/hnaUv+jXpTRaDFZUWZYPryzLCBH8k83MSA4IaPvQNzQttYO9F5IspiWqUUBrU3yB6lY8icnYnlKZt6CdL3FXpTgzSFcMUm37jLE3Tz/HchaYqf835YkAjDI6ff/w9haEaZ29kn+4CVt5O7QsYpu80UWrDisWKbFVmyS4= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2EC753858CD1 Received: from pps.filterd (m0353729.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 56N9bkrS028669; Wed, 23 Jul 2025 14:24:02 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=fYwnR9/XhOTKGXTKG zk8YTetX1lnULlhoWp9Idp2J3o=; b=MvAOiIuTH8W6UUOQ5eYlFhHGKkVMa0ie4 jB1qEC1htcWGxtCiO8hQtmZ2noWBDn7TWDl++fQp40nvXBH5bmNK9FlCZWTFv1dd NSsiIwhgCvsZs+ZJQ/UkwFkeY5eeoSuIDEA0CXDS97ahFXQHEXZeP54kfwj0FP6u /9oVtcxVgxMuXyPuy3cS0DKbsRCplvVHjUaZPbq1T4XpIKWn/ImCZtbyUmFVkps1 fj97LZYkmoILAha1O5WcjzlVn3zo4SmXKC8ld9ESj+JwlOcYt59uWsVJnwW4cEAy aKGHq2re4XDliyCiwQZkH/T2o1PtqhrWt4DQu4HPrtR9ZbIL0AwSg== Received: from ppma22.wdc07v.mail.ibm.com (5c.69.3da9.ip4.static.sl-reverse.com [169.61.105.92]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 482kdym28e-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 23 Jul 2025 14:24:01 +0000 (GMT) Received: from pps.filterd (ppma22.wdc07v.mail.ibm.com [127.0.0.1]) by ppma22.wdc07v.mail.ibm.com (8.18.1.2/8.18.1.2) with ESMTP id 56NCIZ29012462; Wed, 23 Jul 2025 14:24:00 GMT Received: from smtprelay05.fra02v.mail.ibm.com ([9.218.2.225]) by ppma22.wdc07v.mail.ibm.com (PPS) with ESMTPS id 480p308auj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 23 Jul 2025 14:24:00 +0000 Received: from smtpav02.fra02v.mail.ibm.com (smtpav02.fra02v.mail.ibm.com [10.20.54.101]) by smtprelay05.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 56NENuda45547998 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 23 Jul 2025 14:23:56 GMT Received: from smtpav02.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 975E720043; Wed, 23 Jul 2025 14:23:56 +0000 (GMT) Received: from smtpav02.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5E77B2004B; Wed, 23 Jul 2025 14:23:56 +0000 (GMT) Received: from tuxmaker.lnxne.boe (unknown [9.152.85.9]) by smtpav02.fra02v.mail.ibm.com (Postfix) with ESMTP; Wed, 23 Jul 2025 14:23:56 +0000 (GMT) From: Jens Remus To: libc-alpha@sourceware.org, Stefan Liebler , Claudiu Zissulescu-Ianculescu Cc: Jens Remus , Indu Bhagat , Elena Zannoni , Adhemerval Zanella , Florian Weimer Subject: [RFC PATCH v3 3/3] s390: Add SFrame support for s390 64-bit (s390x) architecture Date: Wed, 23 Jul 2025 16:23:47 +0200 Message-ID: <20250723142347.2159793-4-jremus@linux.ibm.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250723142347.2159793-1-jremus@linux.ibm.com> References: <20250723142347.2159793-1-jremus@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: zmjRscm0BGGcZbH6QQfUdtECc58h8Dl2 X-Authority-Analysis: v=2.4 cv=XP0wSRhE c=1 sm=1 tr=0 ts=6880f082 cx=c_pps a=5BHTudwdYE3Te8bg5FgnPg==:117 a=5BHTudwdYE3Te8bg5FgnPg==:17 a=Wb1JkmetP80A:10 a=CCpqsmhAAAAA:8 a=KKAkSRfTAAAA:8 a=VnNF1IyMAAAA:8 a=mDV3o1hIAAAA:8 a=mG_WnP-UJfz4uaYneOYA:9 a=ul9cdbp4aOFLsgKbc677:22 a=cvBusfyB2V15izCimMoJ:22 X-Proofpoint-GUID: zmjRscm0BGGcZbH6QQfUdtECc58h8Dl2 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNzIzMDEyMiBTYWx0ZWRfX4E/SLwv6efGE p7wxFEmDz5RtxkHo9HDZJfvowDt7pN8lmqvYROAC0enJS6sYi9IeYM+bzb4OgiG4Yr+TqpG6tEU 7P04W1tQBLgME+kopBd3yvpSalosVnss6hM7tdC8deXkgwJFVBCKsctpTzqy5BAFH594qq6uyir sKrgqdIHb2zzOW9XK3cbiw59uyF1xLk9K0IzzQ6rvFLTt5gbMYc/Vzpph0Q5Tt2B+pO6AsMkPx8 5z4nTK+mt8gAZB2vYmB8k7YlrgnOGxmLTZdTxR2rnZILyma8WxIgL+p9yOE8yfpqSYK03J42iJo /5TaS3IAldc9uUYUiIsn4IAKgUnLTKRLwqREoTiGCDyG//HaBQygF1Z9zvhxkLlEOM65kDB39dF D1mqJUxMVV9pmB1YwtJAEV6vdfUC97bvjUyaLZXOXEtuIh9r88c5G6tQAnsOBrFfcZ1ytAva X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.1.9,FMLib:17.12.80.40 definitions=2025-07-23_02,2025-07-23_01,2025-03-28_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 bulkscore=0 priorityscore=1501 mlxlogscore=999 spamscore=0 suspectscore=0 clxscore=1015 malwarescore=0 impostorscore=0 lowpriorityscore=0 adultscore=0 phishscore=0 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2505280000 definitions=main-2507230122 X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, GIT_PATCH_0, KAM_ASCII_DIVIDERS, KAM_SHORT, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_NONE, SPF_PASS, 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: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patchwork=sourceware.org@sourceware.org Generation of SFrame stack trace information is supported on s390 64-bit (s390x) architecture. Enable stack tracing using SFrame on s390 64-bit too. Based on Claudiu Zissulescu's AArch64 patch "aarch64: Add SFrame support for aarch64 architecture". Add support for s390 64-bit (s390x) specific SFrame stack trace format extensions: 1. The CFA offset is stored adjusted by an offset originating from the definition of the CFA and scaled down by an alignment factor to enable and improve the use of signed 8-bit SFrame offsets. 2. FP without RA saved (on stack or in a register) is represented using a padding RA offset value of zero (SFRAME_FRE_RA_OFFSET_INVALID). This may not occur in backtrace, as it is not a leaf function. Treat as error and fallback to DWARF stack tracer. 3. FP and RA may be saved in registers instead of on the stack in the topmost frame when in a leaf function. This may not occur in backtrace, as it is not a leaf function. Treat as error and fallback to DWARF stack tracer. Add support to unwind SP, FP, and RA from (RT) signal frames on s390 64-bit (s390x). sysdeps/generic/ * sframe.h (SFRAME_ABI_S390X_ENDIAN_BIG, SFRAME_FRE_RA_OFFSET_INVALID, SFRAME_S390X_CFA_OFFSET_ADJUSTMENT, SFRAME_S390X_CFA_OFFSET_ALIGNMENT_FACTOR, SFRAME_V2_S390X_CFA_OFFSET_ENCODE, SFRAME_V2_S390X_CFA_OFFSET_DECODE, SFRAME_S390X_SP_VAL_OFFSET, SFRAME_V2_S390X_OFFSET_IS_REGNUM, SFRAME_V2_S390X_OFFSET_ENCODE_REGNUM, SFRAME_V2_S390X_OFFSET_DECODE_REGNUM): Define. Based on Binutils include/sframe.h. * sframe.c (SFRAME_CFA_OFFSET_DECODE, SFRAME_OFFSET_IS_REGNUM): New defines that architectures such as s390 64-bit (s390x) may overwrite. (__stacktrace_sframe): Add support for s390 64-bit (s390x) specific SFrame extensions. sysdeps/s390/ * s390-64/sframe.h (SFRAME_SP_VAL_OFFSET): Define s390 64-bit (s390x) specific SP value offset from CFA. (SFRAME_CFA_OFFSET_DECODE): Define s390 64-bit (s390x) specific decoding of SFrame CFA offset. (SFRAME_OFFSET_IS_REGNUM): Define s390 64-bit (s390x) specific test whether SFrame FP/RA offset is a register number. * s390-64/configure.ac (libc_cv_support_sframe): Enable SFrame support on s390 64-bit (s390x). * s390-64/configure: Regenerate. sysdeps/unix/sysv/linux/s390/ * s390-64/uw-sigframe.h (s390_decode_signal_frame): New function. Unwind SP, FP, and RA if in a (RT) signal frame. (MD_DECODE_SIGNAL_FRAME): Wire up s390_decode_signal_frame. Signed-off-by: Jens Remus --- Notes: Changes in v3: - Rebase on top of Adhemerval's series "[PATCH v2 0/2] sframe: Disable by default and support SFRAME_F_FDE_FUNC_START_PCREL": https://inbox.sourceware.org/libc-alpha/20250721234236.1434590-1-adhemerval.zanella@linaro.org/ - Set libc_cv_support_sframe=yes on s390 64-bit (s390x). - Remove MD_DETECT_OUTERMOST_FRAME, as the s390x ELF ABI does not provide any mean to detect an outermost frame. Instead rely on SFrame enhancement to represent RA undefined. See separate patch. - Update SFRAME_*_S390X_* macro names to Binutils 2.45. - Reword GNU ChangeLog. Changes in v2: - Sync sframe.h to latest Binutils s390 SFrame support patch series. - Use macros SFRAME_CFA_OFFSET_DECODE and SFRAME_OFFSET_IS_REGNUM that s390 64-bit (s390x) overwrites instead of ifdefs. - Use s390x/S390X, as done in Binutils. (Indu) - When in doubt fallback to DWARF stack tracer instead of stopping. - Implement MD_DETECT_OUTERMOST_FRAME for s390 64-bit (s390x). The s390 64-bit (s390x) support to generate SFrame in GNU assembler is still under review: Binutils patch series "[PATCH v3 00/11] s390: Support to generate .sframe in assembler and linker", https://inbox.sourceware.org/binutils/20250627110849.1198336-1-jremus@linux.ibm.com/ Note that the definitions in sysdeps/generic/sframe.h originate from Binutils include/sframe.h and should therefore only be modified if absolutely necessary. @Stefan: struct kernel_sigframe and struct kernel_rt_sigframe are based on Kernel arch/s390/kernel/signal.c. From the Glibc test suite I can see that the tests debug/tst-backtrace4 and debug/tst-backtrace5 use sigreturn while debug/tst-backtrace6 uses rt_sigreturn. AArch64 and MIPS both have a separate Glibc header file for struct kernel_rt_sigframe: - sysdeps/unix/sysv/linux/mips/kernel_rt_sigframe.h - sysdeps/unix/sysv/linux/mips/kernel_rt_sigframe.h 1. Should we do the same and introduce sysdeps/unix/sysv/linux/s390/s390-64/kernel_rt_sigframe.h for struct kernel_rt_sigframe? If we do, should we then also introduce sysdeps/unix/sysv/linux/s390/s390-64/kernel_sigframe.h for struct kernel_sigframe? 2. The Kernel struct rt_sigframe contains a struct ucontext_extended instead of a struct ucontext, which currently only differs in an added _sigregs_ext uc_mcontext_ext field. Should we introduce struct ucontext_extended (and ucontext_ext[ended]_t?) in sysdeps/unix/sysv/linux/s390/sys/ucontext.h to align more closely to the Kernel structures? sysdeps/generic/sframe.c | 39 +++++++++ sysdeps/generic/sframe.h | 59 ++++++++++++- sysdeps/s390/configure | 0 sysdeps/s390/s390-64/configure | 4 + sysdeps/s390/s390-64/configure.ac | 4 + sysdeps/s390/s390-64/sframe.h | 50 +++++++++++ .../sysv/linux/s390/s390-64/uw-sigframe.h | 86 +++++++++++++++++++ 7 files changed, 239 insertions(+), 3 deletions(-) mode change 100644 => 100755 sysdeps/s390/configure mode change 100644 => 100755 sysdeps/s390/s390-64/configure create mode 100644 sysdeps/s390/s390-64/sframe.h create mode 100644 sysdeps/unix/sysv/linux/s390/s390-64/uw-sigframe.h diff --git a/sysdeps/generic/sframe.c b/sysdeps/generic/sframe.c index 67e019e3e773..e3f82c6ddb8b 100644 --- a/sysdeps/generic/sframe.c +++ b/sysdeps/generic/sframe.c @@ -27,6 +27,18 @@ #define SFRAME_SP_VAL_OFFSET 0 #endif +/* Some arches like s390x store the CFA offset encoded, such as + adjusted and/or scaled down. */ +#ifndef SFRAME_CFA_OFFSET_DECODE +#define SFRAME_CFA_OFFSET_DECODE(offset) (offset) +#endif + +/* Some arches like s390x may save FP/RA in another register. In + SFrame this is only supported for the topmost frame. */ +#ifndef SFRAME_OFFSET_IS_REGNUM +#define SFRAME_OFFSET_IS_REGNUM(offset) false +#endif + static inline _Unwind_Ptr read_stack_value (_Unwind_Ptr loc) { @@ -137,6 +149,9 @@ __stacktrace_sframe (void **ra_lst, int count, frame *frame) if (err != _URC_NO_REASON) /* Force fallback to DWARF stacktracer. */ return 0; + /* Arches such as s390x may store the CFA offset encoded, + for example adjusted and/or scaled down. */ + cfa_offset = SFRAME_CFA_OFFSET_DECODE (cfa_offset); /* Get CFA using base reg id from the FRE info. */ cfa = ((__sframe_fre_get_base_reg_id (frep) == SFRAME_BASE_REG_SP) @@ -150,6 +165,22 @@ __stacktrace_sframe (void **ra_lst, int count, frame *frame) /* Force fallback to DWARF stacktracer. */ return 0; + /* Arches such as s390x may represent FP without RA saved using + an invalid RA offset value as padding. This may not occur in + backtrace, as the RA must have been saved prior to calling + getRA. */ + if (ra_offset == SFRAME_FRE_RA_OFFSET_INVALID) + /* Force fallback to DWARF stacktracer. */ + return 0; + + /* Arches such as s390x may save RA in another register instead + of on the stack. In SFrame this is only supported for the + topmost frame. This may not occur in backtrace, as its caller + is not topmost. */ + if (SFRAME_OFFSET_IS_REGNUM (ra_offset)) + /* Force fallback to DWARF stacktracer. */ + return 0; + /* RA offset is available, get the value stored in the stack location. */ ra_stack_loc = cfa + ra_offset; @@ -168,6 +199,14 @@ __stacktrace_sframe (void **ra_lst, int count, frame *frame) return 0; else if (err == _URC_NO_REASON) { + /* Arches such as s390x may save FP in another register instead + of on the stack. In SFrame this is only supported for the + topmost frame. This may not occur in backtrace, as its caller + is not topmost. */ + if (SFRAME_OFFSET_IS_REGNUM (fp_offset)) + /* Force fallback to DWARF stacktracer. */ + return 0; + /* FP offset is available, get the value stored in the stack location. */ fp_stack_loc = cfa + fp_offset; diff --git a/sysdeps/generic/sframe.h b/sysdeps/generic/sframe.h index 9cedcad257a2..3271c229be8b 100644 --- a/sysdeps/generic/sframe.h +++ b/sysdeps/generic/sframe.h @@ -102,6 +102,7 @@ extern "C" #define SFRAME_ABI_AARCH64_ENDIAN_BIG 1 /* AARCH64 big endian. */ #define SFRAME_ABI_AARCH64_ENDIAN_LITTLE 2 /* AARCH64 little endian. */ #define SFRAME_ABI_AMD64_ENDIAN_LITTLE 3 /* AMD64 little endian. */ +#define SFRAME_ABI_S390X_ENDIAN_BIG 4 /* s390x big endian. */ /* SFrame FRE types. */ #define SFRAME_FRE_TYPE_ADDR1 0 @@ -200,7 +201,7 @@ typedef struct sframe_func_desc_entry - 1-bit: Unused. ------------------------------------------------------------------------ | Unused| RA | PAC auth A/B key (aarch64) | FDE type | FRE type | - | | undef.| Unused (amd64) | | | + | | undef.| Unused (amd64, s390x) | | | ------------------------------------------------------------------------ 8 7 6 5 4 0 */ uint8_t sfde_func_info; @@ -252,6 +253,10 @@ typedef struct sframe_func_desc_entry may or may not be tracked. */ #define SFRAME_FRE_FP_OFFSET_IDX 2 +/* Invalid RA offset. Currently used for s390x as padding to represent FP + without RA saved. */ +#define SFRAME_FRE_RA_OFFSET_INVALID 0 + typedef struct sframe_fre_info { /* Information about @@ -264,7 +269,7 @@ typedef struct sframe_fre_info - 1 bit: Mangled RA state bit (aarch64 only). ---------------------------------------------------------------------------------- | Mangled-RA (aarch64) | Size of offsets | Number of offsets | base_reg | - | Unused (amd64) | | | | + | Unused (amd64, s390x)| | | | ---------------------------------------------------------------------------------- 8 7 5 1 0 @@ -290,7 +295,7 @@ typedef struct sframe_fre_info /* SFrame Frame Row Entry definitions. - Used for both AMD64 and AARCH64. + Used for AMD64, AARCH64, and s390x. An SFrame Frame Row Entry is a self-sufficient record which contains information on how to generate the stack trace for the specified range of @@ -314,6 +319,24 @@ typedef struct sframe_fre_info fi Note that in AAPCS64, a frame record, if created, will save both FP and LR on stack. + + s390x: + offset1 (interpreted as CFA = BASE_REG + offset1) + if RA is being tracked + offset2 (interpreted as RA = CFA + offset2; an offset value of + SFRAME_FRE_RA_OFFSET_INVALID indicates a dummy padding RA offset + to represent FP without RA saved on stack) + if FP is being tracked + offset3 (intrepreted as FP = CFA + offset3) + fi + else + if FP is being tracked + offset2 (intrepreted as FP = CFA + offset2) + fi + fi + Note that in s390x, if a FP/RA offset2/offset3 value has the least- + significant bit set it represents a DWARF register number shifted to the + left by 1 to restore the FP/RA value from. */ /* Used when SFRAME_FRE_TYPE_ADDR1 is specified as FRE type. */ @@ -358,6 +381,36 @@ typedef struct sframe_frame_row_entry_addr4 #define SFRAME_FRE_TYPE_ADDR4_LIMIT \ (1ULL << ((SFRAME_FRE_TYPE_ADDR4 * 2) * 8)) +/* On s390x, the CFA offset from CFA base register is by definition a minimum + of 160. Store it adjusted by -160 to enable use of 8-bit SFrame offsets. + Additionally scale by an alignment factor of 8, as the SP and thus CFA + offset on s390x is always 8-byte aligned. */ +#define SFRAME_S390X_CFA_OFFSET_ADJUSTMENT SFRAME_S390X_SP_VAL_OFFSET +#define SFRAME_S390X_CFA_OFFSET_ALIGNMENT_FACTOR 8 +#define SFRAME_V2_S390X_CFA_OFFSET_ENCODE(offset) \ + (((offset) + SFRAME_S390X_CFA_OFFSET_ADJUSTMENT) \ + / SFRAME_S390X_CFA_OFFSET_ALIGNMENT_FACTOR) +#define SFRAME_V2_S390X_CFA_OFFSET_DECODE(offset) \ + (((offset) * SFRAME_S390X_CFA_OFFSET_ALIGNMENT_FACTOR) \ + - SFRAME_S390X_CFA_OFFSET_ADJUSTMENT) + +/* On s390x, the CFA is defined as SP at call site + 160. Therefore the + SP value offset from CFA is -160. */ +#define SFRAME_S390X_SP_VAL_OFFSET (-160) + +/* On s390x, the FP and RA registers can be saved either on the stack or, + in case of leaf functions, in registers. Store DWARF register numbers + encoded as offset by using the least-significant bit (LSB) as indicator: + - LSB=0: Stack offset. The s390x ELF ABI mandates that stack register + slots must be 8-byte aligned. + - LSB=1: DWARF register number shifted to the left by one. */ +#define SFRAME_V2_S390X_OFFSET_IS_REGNUM(offset) \ + ((offset) & 1) +#define SFRAME_V2_S390X_OFFSET_ENCODE_REGNUM(regnum) \ + (((regnum) << 1) | 1) +#define SFRAME_V2_S390X_OFFSET_DECODE_REGNUM(offset) \ + ((offset) >> 1) + /* Used to pass frame information to stack trace routine. */ typedef struct cframe { diff --git a/sysdeps/s390/configure b/sysdeps/s390/configure old mode 100644 new mode 100755 diff --git a/sysdeps/s390/s390-64/configure b/sysdeps/s390/s390-64/configure old mode 100644 new mode 100755 index 9ea6940c8597..29a7367ea5da --- a/sysdeps/s390/s390-64/configure +++ b/sysdeps/s390/s390-64/configure @@ -93,3 +93,7 @@ if test $libc_cv_s390x_staticpie_req_runtime = yes; then fi + +# Stack tracing using SFrame is supported on s390 64-bit (s390x) +libc_cv_support_sframe=yes + diff --git a/sysdeps/s390/s390-64/configure.ac b/sysdeps/s390/s390-64/configure.ac index aaf71eabb187..d2ce42782db2 100644 --- a/sysdeps/s390/s390-64/configure.ac +++ b/sysdeps/s390/s390-64/configure.ac @@ -55,3 +55,7 @@ if test $libc_cv_s390x_staticpie_req_runtime = yes; then # test it. AC_DEFINE(SUPPORT_STATIC_PIE) fi + + +# Stack tracing using SFrame is supported on s390 64-bit (s390x) +libc_cv_support_sframe=yes diff --git a/sysdeps/s390/s390-64/sframe.h b/sysdeps/s390/s390-64/sframe.h new file mode 100644 index 000000000000..ebe07663ee09 --- /dev/null +++ b/sysdeps/s390/s390-64/sframe.h @@ -0,0 +1,50 @@ +/* SFrame format description. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not see + . */ + +#ifndef _S390_SFRAME_H +#define _S390_SFRAME_H + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* SP value offset from CFA. On s390 64-bit (s390x) the CFA is defined + as SP at call site + 160. */ +#define SFRAME_SP_VAL_OFFSET SFRAME_S390X_SP_VAL_OFFSET + +/* Decode SFrame CFA offset. On s390 64-bit (s390x) the CFA offset + is stored adjusted and scaled down to enable use of 8-bit offsets. */ +#define SFRAME_CFA_OFFSET_DECODE(offset) \ + SFRAME_V2_S390X_CFA_OFFSET_DECODE (offset) + +/* Test whether SFrame FP/RA offset is a register number. On s390 + 64-bit (s390x) FP/RA may be saved in a register, but only when + in a leaf function. In SFrame this is only supported for the + topmost frame. */ +#define SFRAME_OFFSET_IS_REGNUM(offset) \ + SFRAME_V2_S390X_OFFSET_IS_REGNUM (offset) + +#ifdef __cplusplus +} +#endif + +#endif /* _S390_SFRAME_H */ + diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/uw-sigframe.h b/sysdeps/unix/sysv/linux/s390/s390-64/uw-sigframe.h new file mode 100644 index 000000000000..29acec9115c5 --- /dev/null +++ b/sysdeps/unix/sysv/linux/s390/s390-64/uw-sigframe.h @@ -0,0 +1,86 @@ +/* Signal frame backtracing support for SFrame on s390-64. + Copyright (C) 2025 Free Software Foundation, Inc. + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + The GNU C Library 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* This code is inspired from libgcc's MD_FALLBACK_FRAME_STATE_FOR + implementation. See libgcc/config/s390/linux-unwind.h */ + +#include +#include +#include + +#define MD_DECODE_SIGNAL_FRAME s390_decode_signal_frame + +static _Unwind_Reason_Code +s390_decode_signal_frame (frame *frame) +{ + /* Linux kernel's sigframe structure. */ + struct kernel_sigframe + { + unsigned char callee_used_stack[__SIGNAL_FRAMESIZE]; + struct sigcontext sc; + _sigregs sregs; + int signo; + _sigregs_ext sregs_ext; + unsigned short svc_insn; /* Offset of svc_insn is NOT fixed! */ + }; + + /* Linux kernel's rt_sigframe structure. */ + struct kernel_rt_sigframe + { + unsigned char callee_used_stack[__SIGNAL_FRAMESIZE]; + unsigned short svc_insn; + siginfo_t info; + ucontext_t uc; + }; + + unsigned char *pc = (unsigned char *) frame->pc; + _sigregs *sr; + +#define SVC_OPCODE 0x0a + + /* A signal frame will have a return address pointing to: + svc $__NR_sigreturn or svc $__NR_rt_sigreturn */ + if (pc[0] != SVC_OPCODE + || (pc[1] != __NR_sigreturn && pc[1] != __NR_rt_sigreturn)) + return _URC_END_OF_STACK; + + if (pc[1] == __NR_rt_sigreturn) + { + /* New-style RT frame. */ + struct kernel_rt_sigframe *rt_; + rt_ = (struct kernel_rt_sigframe *) frame->sp; + sr = (_sigregs *) &rt_->uc.uc_mcontext; + } + else + { + /* New-style non-RT frame. */ + struct kernel_sigframe *sf; + sf = (struct kernel_sigframe *) frame->sp; + sr = sf->sc.sregs; + } + +#define SP_REGNUM 15 +#define FP_REGNUM 11 + + frame->pc = (_Unwind_Ptr) sr->regs.psw.addr; + frame->sp = (_Unwind_Ptr) sr->regs.gprs[SP_REGNUM]; + frame->fp = (_Unwind_Ptr) sr->regs.gprs[FP_REGNUM]; + + return _URC_NO_REASON; +}