[v6,1/4] gas: ld: libsframe: Support for SFrame FDEs without any FREs

Message ID 20250915110551.759931-2-jremus@linux.ibm.com
State New
Headers
Series sframe: Represent .cfi_undefined RA |

Commit Message

Jens Remus Sept. 15, 2025, 11:05 a.m. UTC
  Allow SFrame sections without any FREs, that can occur if they solely
contain FDEs without any FREs.  For FDEs without and FREs set the
offset to the first FRE to zero.

libsframe/
	* sframe.c (sframe_encoder_write_sframe): Allow SFrame sections
	without any FREs.  For FDEs without any FREs set the offset to
	the first FRE to zero.

gas/
	* gen-sframe.c (output_sframe_funcdesc): For FDEs without any
	FREs set the offset to the first FRE to zero.

Signed-off-by: Jens Remus <jremus@linux.ibm.com>
---

Notes (jremus):
    Changes in V5:
    - Reword comments setting sfde_func_start_fre_off to zero. (Indu)
    
    Changes in V4:
    - Use ehp->sfh_num_fres instead of adding a new API to get the total
      number of FREs. (Indu)
    - Squash related assembler change from V3.
    - Reword commit subject and message.
    
    Changes in V3:
    - New patch.

 gas/gen-sframe.c   | 18 ++++++++++++------
 libsframe/sframe.c |  9 ++++++++-
 2 files changed, 20 insertions(+), 7 deletions(-)
  

Patch

diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
index ac1427856fab..bbc817b04328 100644
--- a/gas/gen-sframe.c
+++ b/gas/gen-sframe.c
@@ -651,12 +651,18 @@  output_sframe_funcdesc (symbolS *start_of_fre_section,
 				  sfde_func_size));
 
   /* Offset to the first frame row entry.  */
-  exp.X_op = O_subtract;
-  exp.X_add_symbol = fre_symbol; /* Minuend.  */
-  exp.X_op_symbol = start_of_fre_section; /* Subtrahend.  */
-  exp.X_add_number = 0;
-  emit_expr (&exp, sizeof_member (sframe_func_desc_entry,
-				  sfde_func_start_fre_off));
+  if (sframe_fde->num_fres == 0)
+    /* For FDEs without any FREs, set sfde_func_start_fre_off to zero.  */
+    out_four (0);
+  else
+    {
+      exp.X_op = O_subtract;
+      exp.X_add_symbol = fre_symbol; /* Minuend.  */
+      exp.X_op_symbol = start_of_fre_section; /* Subtrahend.  */
+      exp.X_add_number = 0;
+      emit_expr (&exp, sizeof_member (sframe_func_desc_entry,
+				      sfde_func_start_fre_off));
+    }
 
   /* Number of FREs.  */
   out_four (sframe_fde->num_fres);
diff --git a/libsframe/sframe.c b/libsframe/sframe.c
index 85500791f8ac..b70b0e880c9b 100644
--- a/libsframe/sframe.c
+++ b/libsframe/sframe.c
@@ -1882,7 +1882,7 @@  sframe_encoder_write_sframe (sframe_encoder_ctx *encoder)
      - buffers must be malloc'd by the caller.  */
   if ((contents == NULL) || (buf_size < hdr_size))
     return sframe_set_errno (&err, SFRAME_ERR_BUF_INVAL);
-  if (fr_info == NULL)
+  if (ehp->sfh_num_fres > 0 && fr_info == NULL)
     return sframe_set_errno (&err, SFRAME_ERR_FRE_INVAL);
 
   /* Write out the FRE table first.
@@ -1905,6 +1905,13 @@  sframe_encoder_write_sframe (sframe_encoder_ctx *encoder)
       fre_type = sframe_get_fre_type (fdep);
       num_fres = fdep->sfde_func_num_fres;
 
+      /* For FDEs without any FREs, set sfde_func_start_fre_off to zero.  */
+      if (num_fres == 0)
+	fdep->sfde_func_start_fre_off = 0;
+
+      if (num_fres > 0 && fr_info == NULL)
+	return sframe_set_errno (&err, SFRAME_ERR_FRE_INVAL);
+
       for (j = 0; j < num_fres; j++)
 	{
 	  fre_index = global + j;