[V2 13/36] [SFrame-V3] include: sframe: s390x: keep unused bits when possible

Indu Bhagat indu.bhagat@oracle.com
Wed Jan 7 08:42:04 GMT 2026


TBD:
  - This is a backwards incompatible change.  But its better to keep unused
    bits for future extensibility.  Discuss with s390x SFrame maintainer.
  - Depending on what way forward we chose for s390x - i.e. whether we
    use the current SFrame V2 mechanism of encoding FP/RA recovery from
    register or we switch to using flex FDE in SFrame V3, this patch may
    not be necessary.

gas/
	* gen-sframe.c (s390_sframe_xlate_do_register):
libsframe/
	* sframe-dump.c (sframe_s390x_offset_regnum_p):
	(sframe_s390x_offset_decode_regnum):
	(dump_sframe_func_with_fres):
include/
	* sframe.h (SFRAME_V3_S390X_OFFSET_IS_REGNUM): New macro for V3.
	(SFRAME_V3_S390X_OFFSET_ENCODE_REGNUM): Keep lower 3 bits aside,
	instead of 1.
	(SFRAME_V3_S390X_OFFSET_DECODE_REGNUM): Likewise.

---
[Changes in V1]
 - Use sframe_s390x_offset_regnum_p consistently. [Jens]
[End of changes in V1]

[No changes in V2]
---
 gas/gen-sframe.c        |  4 ++--
 include/sframe.h        | 13 +++++++++++++
 libsframe/sframe-dump.c | 34 ++++++++++++++++++++++++++++++----
 3 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
index 2bef91e60c9..2e05c444642 100644
--- a/gas/gen-sframe.c
+++ b/gas/gen-sframe.c
@@ -1322,11 +1322,11 @@ s390_sframe_xlate_do_register (struct sframe_xlate_ctx *xlate_ctx,
      numbers, as offsets from CFA are always a multiple of -8 on s390x.  */
   if (cfi_insn->u.rr.reg1 == SFRAME_CFA_FP_REG)
     sframe_fre_set_fp_track (cur_fre,
-			     SFRAME_V2_S390X_OFFSET_ENCODE_REGNUM (cfi_insn->u.rr.reg2));
+			     SFRAME_V3_S390X_OFFSET_ENCODE_REGNUM (cfi_insn->u.rr.reg2));
   else if (sframe_ra_tracking_p ()
 	   && cfi_insn->u.rr.reg1 == SFRAME_CFA_RA_REG)
     sframe_fre_set_ra_track (cur_fre,
-			     SFRAME_V2_S390X_OFFSET_ENCODE_REGNUM (cfi_insn->u.rr.reg2));
+			     SFRAME_V3_S390X_OFFSET_ENCODE_REGNUM (cfi_insn->u.rr.reg2));
 
   return SFRAME_XLATE_OK;
 }
diff --git a/include/sframe.h b/include/sframe.h
index 8e3510fdd86..c1ee8c9d813 100644
--- a/include/sframe.h
+++ b/include/sframe.h
@@ -468,6 +468,19 @@ typedef struct sframe_frame_row_entry_addr4
 #define SFRAME_V2_S390X_OFFSET_DECODE_REGNUM(offset) \
   ((offset) >> 1)
 
+/* In SFrame V3, change the encoding of register numbers in the SFrame offsets
+   on s390x by keeping the lower 3 bits aside.
+   - 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 three.
+   Bits 1 and 2 are currently unused.  */
+#define SFRAME_V3_S390X_OFFSET_IS_REGNUM(offset) \
+  ((offset) & 1)
+#define SFRAME_V3_S390X_OFFSET_ENCODE_REGNUM(regnum) \
+  (((regnum) << 3) | 1)
+#define SFRAME_V3_S390X_OFFSET_DECODE_REGNUM(offset) \
+  ((offset) >> 3)
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/libsframe/sframe-dump.c b/libsframe/sframe-dump.c
index 394dbdc9158..63611fbf6f4 100644
--- a/libsframe/sframe-dump.c
+++ b/libsframe/sframe-dump.c
@@ -46,6 +46,30 @@ is_sframe_abi_arch_s390x (const sframe_decoder_ctx *sfd_ctx)
   return sframe_decoder_get_abi_arch (sfd_ctx) == SFRAME_ABI_S390X_ENDIAN_BIG;
 }
 
+static bool
+sframe_s390x_offset_regnum_p (int32_t offset, uint8_t ver)
+{
+  if (ver == SFRAME_VERSION_2)
+    return SFRAME_V2_S390X_OFFSET_IS_REGNUM (offset);
+  else if (ver == SFRAME_VERSION_3)
+    return SFRAME_V3_S390X_OFFSET_IS_REGNUM (offset);
+  else
+    /* No other version is supported yet.  */
+    sframe_assert (false);
+}
+
+static int
+sframe_s390x_offset_decode_regnum (int32_t offset, uint8_t ver)
+{
+  if (ver == SFRAME_VERSION_2)
+    return SFRAME_V2_S390X_OFFSET_DECODE_REGNUM (offset);
+  else if (ver == SFRAME_VERSION_3)
+    return SFRAME_V3_S390X_OFFSET_DECODE_REGNUM (offset);
+  else
+    /* No other version is supported yet.  */
+    sframe_assert (false);
+}
+
 static void
 dump_sframe_header_flags (const sframe_decoder_ctx *sfd_ctx)
 {
@@ -230,8 +254,9 @@ dump_sframe_func_with_fres (const sframe_decoder_ctx *sfd_ctx,
       if (err[1] == 0)
 	{
 	  if (is_sframe_abi_arch_s390x (sfd_ctx)
-	      && SFRAME_V2_S390X_OFFSET_IS_REGNUM (fp_offset))
-	    sprintf (temp, "r%d", SFRAME_V2_S390X_OFFSET_DECODE_REGNUM (fp_offset));
+	      && sframe_s390x_offset_regnum_p (fp_offset, ver))
+	    sprintf (temp, "r%d",
+		     sframe_s390x_offset_decode_regnum (fp_offset, ver));
 	  else
 	    sprintf (temp, "c%+d", fp_offset);
 	}
@@ -252,8 +277,9 @@ dump_sframe_func_with_fres (const sframe_decoder_ctx *sfd_ctx,
       else if (err[2] == 0)
 	{
 	  if (is_sframe_abi_arch_s390x (sfd_ctx)
-	      && SFRAME_V2_S390X_OFFSET_IS_REGNUM (ra_offset))
-	    sprintf (temp, "r%d", SFRAME_V2_S390X_OFFSET_DECODE_REGNUM (ra_offset));
+	      && sframe_s390x_offset_regnum_p (ra_offset, ver))
+	    sprintf (temp, "r%d",
+		     sframe_s390x_offset_decode_regnum (ra_offset, ver));
 	  else
 	    sprintf (temp, "c%+d", ra_offset);
 	}
-- 
2.43.0



More information about the Binutils mailing list