From patchwork Fri Jun 27 13:38:13 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Remus X-Patchwork-Id: 115200 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 E46B2385AC3B for ; Fri, 27 Jun 2025 13:45:41 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E46B2385AC3B 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=Yy/Tj4W0 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 EFA983856DFD for ; Fri, 27 Jun 2025 13:38:34 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org EFA983856DFD 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 EFA983856DFD 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=1751031515; cv=none; b=txJwNHHAjhOdWt6OJzMcytS2PNC25vQEdyoYanZ6b/fCM2o+CvQ36c5EjMjLPioy0Wf8vRTD0PJ5YxeJ2vq6Q/QRWl2Ip3FarIxJQLa6u0mDMPXh3HFmROx4tyHaeM2rKtEoNarRCpOMZ8YO6CFyxm8AAIhM6d7/CpKMafchKEs= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1751031515; c=relaxed/simple; bh=uZtzDpdVaBHrBPlr6uYcACWvkMz/wT4xMiiterY+ejw=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=iBZEwfSGjrx/xKI3ZQ6jEa/X1aN7cJhq0H+t+1Ky7/7YJ1Iwf6bKpBkpyRc004pGlJACFMfzguVr1aX73whbP/hCS1rnnBpQqPgYiR5N3EgXWHuAMA4it08SYmsUub28q/yAS8U5XWqB/HxFGs5oM7iFupDQIIU+ZWNTvK0UNyI= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org EFA983856DFD 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 55RCZdM5030891; Fri, 27 Jun 2025 13:38:30 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=y8ic+nOPATV3FdtBr WRzydV0KN8scAIk2TFsC37OHLA=; b=Yy/Tj4W0wMLxGLZikGYBiq816gky5GMYs lh/WFXq6/sKDHpfD4MPqAqdfG5ekO3zQ0xvx4pIhalmamMT3HFJF/OmWeGupCYg9 o/0KXrGjx7lwV6ju3YBfshAFipf0pfVduEI7seo1jcvZs/alqdQWeGr2r5OHnv9P DWsZBSPL+gbGaYloklPk2ZRtBz3WzqSJO2TwR1Kj4/gNrr0zywK70qj89WN5aCOQ QmDtuRJxXoNqaCVh9m2TsAXkHc5xi8zGozMTo5W9UFIrbET8cSHvaO3jP8z/gDsm +dkC34iv3dRBafXyZeDIakb0eGeaHdfLvuszBJ5DGYn9A7xgoBeTg== Received: from ppma12.dal12v.mail.ibm.com (dc.9e.1632.ip4.static.sl-reverse.com [50.22.158.220]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 47dk64d76t-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 27 Jun 2025 13:38:29 +0000 (GMT) Received: from pps.filterd (ppma12.dal12v.mail.ibm.com [127.0.0.1]) by ppma12.dal12v.mail.ibm.com (8.18.1.2/8.18.1.2) with ESMTP id 55RBYJkc014988; Fri, 27 Jun 2025 13:38:29 GMT Received: from smtprelay07.fra02v.mail.ibm.com ([9.218.2.229]) by ppma12.dal12v.mail.ibm.com (PPS) with ESMTPS id 47e72u4hx5-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 27 Jun 2025 13:38:28 +0000 Received: from smtpav04.fra02v.mail.ibm.com (smtpav04.fra02v.mail.ibm.com [10.20.54.103]) by smtprelay07.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 55RDcPln47448534 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 27 Jun 2025 13:38:25 GMT Received: from smtpav04.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3A62B20040; Fri, 27 Jun 2025 13:38:25 +0000 (GMT) Received: from smtpav04.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 07AE320043; Fri, 27 Jun 2025 13:38:25 +0000 (GMT) Received: from tuxmaker.lnxne.boe (unknown [9.152.85.9]) by smtpav04.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 27 Jun 2025 13:38:24 +0000 (GMT) From: Jens Remus To: libc-alpha@sourceware.org, Stefan Liebler , Claudiu Zissulescu-Ianculescu , Florian Weimer Cc: Jens Remus , Ulrich Weigand , Indu Bhagat , Elena Zannoni Subject: [RFC PATCH v2 2/2] s390: Add SFrame support for s390 64-bit (s390x) architecture Date: Fri, 27 Jun 2025 15:38:13 +0200 Message-ID: <20250627133813.2198784-3-jremus@linux.ibm.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250627133813.2198784-1-jremus@linux.ibm.com> References: <20250627133813.2198784-1-jremus@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNjI3MDExMCBTYWx0ZWRfX87mcKzhWOJkV PDkrm2vSQILV2C5WLp5+NylV6YE7T9nQ6yUkVNU9Z2ni+mPVpqy8EfoaOvkXod2Y1mJX1LMP6jH xb2f7As8IwznNrhEP3dzj6fQHpSZwOrBGLgftR/dm9PjfjE2XHhhUNEmuDYOlMPa2P5efAV1mnX 92fPjHpR6LE3ABmgvTrgPvLgzG3QMncW2hOaDHH5OJq6WpWk2oZbbWVduoPbaelQvdylRdujNqc hk2PmjcY5tphhRhmyAPllOPBs+61PptcxQRgLwVAonS9/yySr+IAQ4aBZwzWKFUkGUlwYyTPbaK qUWmm93Kh2FAh1sAKzjgxSI+94pTi3YjAN8rO0T9ITNWqff5n0p129UNxV36YzPp5Sg0D56T2f5 hyVql2qIt/qUWo9F8rFY5p2vjhumWA3u8omuSVbRSTK+XDaLpwYR3QVSsg0OfGwWk/ivR/Ve X-Proofpoint-ORIG-GUID: m9vDPHAiNHQh1AtyZqISdMbsIpH41gHl X-Proofpoint-GUID: m9vDPHAiNHQh1AtyZqISdMbsIpH41gHl X-Authority-Analysis: v=2.4 cv=BfvY0qt2 c=1 sm=1 tr=0 ts=685e9ed6 cx=c_pps a=bLidbwmWQ0KltjZqbj+ezA==:117 a=bLidbwmWQ0KltjZqbj+ezA==:17 a=6IFa9wvqVegA:10 a=CCpqsmhAAAAA:8 a=VnNF1IyMAAAA:8 a=mDV3o1hIAAAA:8 a=gGaoscKgT_vU5drUmSEA:9 a=ul9cdbp4aOFLsgKbc677:22 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.1.7,FMLib:17.12.80.40 definitions=2025-06-27_04,2025-06-26_05,2025-03-28_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 priorityscore=1501 lowpriorityscore=0 clxscore=1011 suspectscore=0 adultscore=0 spamscore=0 impostorscore=0 mlxlogscore=999 malwarescore=0 phishscore=0 bulkscore=0 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2505280000 definitions=main-2506270110 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). Add support to detect outermost frame 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_FRE_S390X_CFA_OFFSET_ENCODE, SFRAME_V2_FRE_S390X_CFA_OFFSET_DECODE, SFRAME_S390X_SP_VAL_OFFSET, SFRAME_S390X_OFFSET_IS_REGNUM, SFRAME_S390X_OFFSET_ENCODE_REGNUM, SFRAME_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. 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. (s390_detect_outermost_frame): New function. Detect outermost frame on s390 64-bit (s390x). (MD_DETECT_OUTERMOST_FRAME): Wire up s390_detect_outermost_frame. Signed-off-by: Jens Remus --- Notes: 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/s390-64/sframe.h | 50 +++++++++ .../sysv/linux/s390/s390-64/uw-sigframe.h | 101 ++++++++++++++++++ 4 files changed, 246 insertions(+), 3 deletions(-) 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 e3d0cee27d6b..dc64d9fe357f 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) { @@ -130,6 +142,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) @@ -143,6 +158,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; @@ -161,6 +192,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 198045539542..89bb20eea3a0 100644 --- a/sysdeps/generic/sframe.h +++ b/sysdeps/generic/sframe.h @@ -91,6 +91,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 @@ -188,7 +189,7 @@ typedef struct sframe_func_desc_entry - 2-bits: Unused. ------------------------------------------------------------------------ | Unused | PAC auth A/B key (aarch64) | FDE type | FRE type | - | | Unused (amd64) | | | + | | Unused (amd64, s390x) | | | ------------------------------------------------------------------------ 8 6 5 4 0 */ uint8_t sfde_func_info; @@ -234,6 +235,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 @@ -246,7 +251,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 @@ -272,7 +277,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 @@ -296,6 +301,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. */ @@ -340,6 +363,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_FRE_S390X_CFA_OFFSET_ENCODE(offset) \ + (((offset) + SFRAME_S390X_CFA_OFFSET_ADJUSTMENT) \ + / SFRAME_S390X_CFA_OFFSET_ALIGNMENT_FACTOR) +#define SFRAME_V2_FRE_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_S390X_OFFSET_IS_REGNUM(offset) \ + ((offset) & 1) +#define SFRAME_S390X_OFFSET_ENCODE_REGNUM(regnum) \ + (((regnum) << 1) | 1) +#define SFRAME_S390X_OFFSET_DECODE_REGNUM(offset) \ + ((offset) >> 1) + /* Used to pass frame information to stack trace routine. */ typedef struct cframe { diff --git a/sysdeps/s390/s390-64/sframe.h b/sysdeps/s390/s390-64/sframe.h new file mode 100644 index 000000000000..fbeac5217baa --- /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_FRE_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_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..57d363502c60 --- /dev/null +++ b/sysdeps/unix/sysv/linux/s390/s390-64/uw-sigframe.h @@ -0,0 +1,101 @@ +/* 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; +} + +#define MD_DETECT_OUTERMOST_FRAME s390_detect_outermost_frame + +static _Unwind_Reason_Code +s390_detect_outermost_frame (frame *frame) +{ + const char *pc = (const char *) frame->pc; + + /* Outermost frame's PC points to the unreachable invalid instruction + 0x0000 in _start. */ + if (pc[0] == 0x00 && pc[1] == 0x00) + return _URC_END_OF_STACK; + + return _URC_NO_REASON; +}