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; +}