]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
[SFrame-V3] sframe: gas: libsframe: use uint16_t for num_fres of FDE
authorIndu Bhagat <indu.bhagat@oracle.com>
Fri, 28 Nov 2025 19:50:14 +0000 (11:50 -0800)
committerIndu Bhagat <indu.bhagat@oracle.com>
Tue, 9 Dec 2025 08:26:13 +0000 (00:26 -0800)
Reduce the size of the num_fres field in the Function Descriptor Entry
(FDE) from 32 bits to 16 bits.

The number of Frame Row Entries (FREs) for a single function is extremely
unlikely to exceed 65,535 in real-world scenarios. Reducing this field
saves 2 bytes per FDE, contributing to a smaller overall SFrame section size.

(BTW, these savings will be eaten up by a later commit which adds
support for text > 2 GiB by increasing an offset from int32_t to
int64_t).

Safety checks are added to the assembler to warn and skip SFrame FDE
generation if a function's FRE count exceeds UINT16_MAX.

include/
* sframe.h (sframe_func_desc_entry_v3): Change sfde_func_num_fres
type to uint16_t.
gas/
* gen-sframe.c (output_sframe_funcdesc): Write 2 bytes for num_fres
and assert it fits in uint16_t.
(sframe_do_fde): Add check to skip FDE emission if num_fres exceeds
UINT16_MAX.
libsframe/
* sframe.c (sframe_fde_tbl_init): Cast num_fres to uint16_t.
(sframe_decode_fde): Likewise.
(sframe_encoder_write_fde): Likewise.
* testsuite/libsframe.decode/DATA2: Update binary test data.

gas/gen-sframe.c
include/sframe.h
libsframe/sframe.c
libsframe/testsuite/libsframe.decode/DATA2

index 46e5fa2c92adfa45e70f411ad1a88a8d14186fce..56c0c95c940bb78cb276482eb7b6bc7662754a60 100644 (file)
@@ -724,8 +724,9 @@ output_sframe_funcdesc (symbolS *start_of_fre_section,
                                      sfde_func_start_fre_off));
     }
 
-  /* Number of FREs.  */
-  out_four (sframe_fde->num_fres);
+  /* Number of FREs must fit uint16_t.  */
+  gas_assert (sframe_fde->num_fres <= UINT16_MAX);
+  out_two (sframe_fde->num_fres);
 
   /* SFrame FDE function info.  */
   unsigned char func_info;
@@ -2032,6 +2033,20 @@ sframe_do_fde (struct sframe_xlate_ctx *xlate_ctx,
        = get_dw_fde_end_addrS (xlate_ctx->dw_fde);
     }
 
+  /* Number of FREs must fit uint16_t.  Check now, and do not emit the SFrame
+     FDE if it doesnt fit (although, it is not expected to happen for
+     real-world, useful programs).  The approach of truncating the FDE and
+     emitting multiple SFrame FDEs instead, is not a clearly preferable
+     handling either.  Its a divergence from the model where an SFrame FDE
+     encodes stack trace data between a .cfi_startproc and .cfi_endproc pair.
+     Further, some components (linkers, stack tracers) want to associate the
+     Start PC of a function to a known symbol in the file?  */
+  if (xlate_ctx->num_xlate_fres > UINT16_MAX)
+    {
+      as_warn (_("no SFrame FDE emitted; Number of FREs exceeds UINT16_MAX"));
+      return SFRAME_XLATE_ERR_NOTREPRESENTED;
+    }
+
   /* ABI/arch except s390x cannot represent FP without RA saved.  */
   if (sframe_ra_tracking_p ()
       && sframe_get_abi_arch () != SFRAME_ABI_S390X_ENDIAN_BIG)
index 8d08aefcc0413b2a414cf2b1d129ca5932d8b5ef..50dee8ebb96b0bd21aa29e04f766b0dbc40ee94c 100644 (file)
@@ -251,7 +251,7 @@ typedef struct sframe_func_desc_entry_v3
      beginning of the SFrame Frame Row Entry sub-section.  */
   uint32_t sfde_func_start_fre_off;
   /* Number of frame row entries for the function.  */
-  uint32_t sfde_func_num_fres;
+  uint16_t sfde_func_num_fres;
   /* Additional information for stack tracing from the function:
      - 4-bits: Identify the FRE type used for the function.
      - 1-bit: Identify the FDE type of the function - mask or inc.
index afa8923b733b478840b10328406a841c8f656928..b0da92afb6b31069fd3b67bf9bf6cecfc1490173 100644 (file)
@@ -151,7 +151,7 @@ sframe_fde_tbl_init (sf_fde_tbl *fde_tbl, const char *fde_buf,
          fde_tbl->entry[i].func_start_addr = fdep->sfde_func_start_address;
          fde_tbl->entry[i].func_size = fdep->sfde_func_size;
          fde_tbl->entry[i].func_start_fre_off = fdep->sfde_func_start_fre_off;
-         fde_tbl->entry[i].func_num_fres = fdep->sfde_func_num_fres;
+         fde_tbl->entry[i].func_num_fres = (uint16_t)fdep->sfde_func_num_fres;
          fde_tbl->entry[i].func_info = fdep->sfde_func_info;
          fde_tbl->entry[i].func_rep_size = fdep->sfde_func_rep_size;
        }
@@ -576,7 +576,7 @@ sframe_decode_fde (const char *buf, size_t buf_size, uint8_t ver,
        return SFRAME_ERR;
 
       sframe_func_desc_entry_v3 *fdep = (sframe_func_desc_entry_v3 *) buf;
-      *num_fres = fdep->sfde_func_num_fres;
+      *num_fres = (uint16_t)fdep->sfde_func_num_fres;
       *fre_type = SFRAME_V1_FUNC_FRE_TYPE (fdep->sfde_func_info);
       *fre_offset = fdep->sfde_func_start_fre_off;
 
@@ -2131,7 +2131,7 @@ sframe_encoder_write_fde (const sframe_header *sfhp ATTRIBUTE_UNUSED,
   fdep->sfde_func_start_address = (int32_t)fde->func_start_addr;
   fdep->sfde_func_size = fde->func_size;
   fdep->sfde_func_start_fre_off = fde->func_start_fre_off;
-  fdep->sfde_func_num_fres = fde->func_num_fres;
+  fdep->sfde_func_num_fres = (uint16_t)fde->func_num_fres;
   fdep->sfde_func_info = fde->func_info;
   fdep->sfde_func_rep_size = fde->func_rep_size;
   fdep->sfde_func_padding2 = 0;
index aa62398b2ca115660338a00b76b4bcb351cedf3d..7a218f86bcce9e3a6e3446c7c725dfedbd6d687b 100644 (file)
Binary files a/libsframe/testsuite/libsframe.decode/DATA2 and b/libsframe/testsuite/libsframe.decode/DATA2 differ