]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
libsframe: implement an internal-only SFrame FDE representation
authorIndu Bhagat <indu.bhagat@oracle.com>
Wed, 22 Oct 2025 23:29:48 +0000 (16:29 -0700)
committerIndu Bhagat <indu.bhagat@oracle.com>
Tue, 9 Dec 2025 08:26:11 +0000 (00:26 -0800)
Up until now, libsframe has used the same SFrame FDE representation as
the on-disk representation (sframe_func_desc_entry).  The choice made by
the author of the libary, back when it was first contributed, perhaps
sufficed the needs then.  But looking forward, we need to be able to
allow reading and dumping out of not just sections with version
SFRAME_VERSION_2 but also future supported versions.

Note that libsframe did not expose the SFrame FDE representation in any
public APIs;  doing so is not recommended.

For the path forward, create an internal-only SFrame FDE representation
(sframe_func_desc_entry_int).  libsframe now keeps all in-memory FDEs of
type sframe_func_desc_entry_int.  Doing so means instead of memcpy, we
need to resort to member-by-member mapping.  This can be seen in
sframe_fde_tbl_init (read time) and the new function
sframe_encoder_write_fde (write time).

Other than that, replace out the previous direct interaction with
on-disk format when:
  - flipping SFrame contents before decoding them in sframe_decode.
  - flipping SFrame contents before writing them out in sframe_encode.

libsframe/sframe.c

index 66810f93f353c05c939ead8a309e3795b011c386..8c4159e27b5335a1a08c6463acd42092937001b6 100644 (file)
 #include "sframe-impl.h"
 #include "swap.h"
 
-typedef sframe_func_desc_entry_v2 sframe_func_desc_entry;
+/* Representation of SFrame FDE internal to libsframe.  */
+typedef struct sframe_func_desc_entry_int
+{
+  int64_t func_start_addr;
+  uint32_t func_size;
+  uint32_t func_start_fre_off;
+  uint32_t func_num_fres;
+  uint8_t func_info;
+  uint8_t func_rep_size;
+} ATTRIBUTE_PACKED sframe_func_desc_entry_int;
 
 struct sf_fde_tbl
 {
   unsigned int count;
   unsigned int alloced;
-  sframe_func_desc_entry entry[1];
+  sframe_func_desc_entry_int entry[1];
 };
 
 struct sf_fre_tbl
@@ -106,13 +115,13 @@ sframe_ret_set_errno (int *errp, int error)
 }
 
 /* Allocate space for NUM_FDES number of SFrame FDEs of type
-   sframe_func_desc_entry.  This is version-unaware because this pertains to
-   libsframe's internal in-memory representation of SFrame FDE.  */
+   sframe_func_desc_entry_int.  This is version-unaware because this pertains
+   to libsframe's internal in-memory representation of SFrame FDE.  */
 
 static int
 sframe_fde_tbl_alloc (sf_fde_tbl **fde_tbl, unsigned int num_fdes)
 {
-  size_t fidx_size = num_fdes * sizeof (sframe_func_desc_entry);
+  size_t fidx_size = num_fdes * sizeof (sframe_func_desc_entry_int);
   size_t fd_tbl_sz = (sizeof (sf_fde_tbl) + fidx_size);
 
   *fde_tbl = malloc (fd_tbl_sz);
@@ -130,12 +139,21 @@ static int
 sframe_fde_tbl_init (sf_fde_tbl *fde_tbl, const char *fde_buf,
                     size_t *fidx_size, unsigned int num_fdes, uint8_t ver)
 {
-  /* sframe_func_desc_entry is the same type as the latest SFrame FDE V2
-     definition (currently sframe_func_desc_entry_v2).  */
+  sframe_func_desc_entry_v2 *fdep = NULL;
+
   if (ver == SFRAME_VERSION_2 && SFRAME_VERSION == SFRAME_VERSION_2)
     {
-      *fidx_size = num_fdes * sizeof (sframe_func_desc_entry_v2);
-      memcpy (fde_tbl->entry, fde_buf, *fidx_size);
+      *fidx_size = num_fdes * sizeof (sframe_func_desc_entry_int);
+      for (unsigned int i = 0; i < num_fdes; i++)
+       {
+         fdep = (sframe_func_desc_entry_v2 *)fde_buf + i;
+         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_info = fdep->sfde_func_info;
+         fde_tbl->entry[i].func_rep_size = fdep->sfde_func_rep_size;
+       }
       fde_tbl->count = num_fdes;
     }
   /* If ver is not the latest, read buffer manually and upgrade from
@@ -187,20 +205,20 @@ sframe_get_fre_ra_undefined_p (uint8_t fre_info)
 /* Access functions for info from function descriptor entry.  */
 
 static uint32_t
-sframe_get_fre_type (sframe_func_desc_entry *fdep)
+sframe_get_fre_type (sframe_func_desc_entry_int *fdep)
 {
   uint32_t fre_type = 0;
   if (fdep)
-    fre_type = SFRAME_V1_FUNC_FRE_TYPE (fdep->sfde_func_info);
+    fre_type = SFRAME_V1_FUNC_FRE_TYPE (fdep->func_info);
   return fre_type;
 }
 
 static uint32_t
-sframe_get_fde_type (sframe_func_desc_entry *fdep)
+sframe_get_fde_type (sframe_func_desc_entry_int *fdep)
 {
   uint32_t fde_type = 0;
   if (fdep)
-    fde_type = SFRAME_V1_FUNC_FDE_TYPE (fdep->sfde_func_info);
+    fde_type = SFRAME_V1_FUNC_FDE_TYPE (fdep->func_info);
   return fde_type;
 }
 
@@ -436,11 +454,11 @@ sframe_fre_entry_size (sframe_frame_row_entry *frep, uint32_t fre_type)
 /* Get the function descriptor entry at index FUNC_IDX in the decoder
    context CTX.  */
 
-static sframe_func_desc_entry *
+static sframe_func_desc_entry_int *
 sframe_decoder_get_funcdesc_at_index (sframe_decoder_ctx *ctx,
                                      uint32_t func_idx)
 {
-  sframe_func_desc_entry *fdep;
+  sframe_func_desc_entry_int *fdep;
   uint32_t num_fdes;
   int err;
 
@@ -473,8 +491,8 @@ sframe_decoder_get_secrel_func_start_addr (sframe_decoder_ctx *dctx,
   if (err)
     return 0;
 
-  const sframe_func_desc_entry *fdep = &dctx->sfd_funcdesc->entry[func_idx];
-  int32_t func_start_addr = fdep->sfde_func_start_address;
+  const sframe_func_desc_entry_int *fdep = &dctx->sfd_funcdesc->entry[func_idx];
+  int32_t func_start_addr = fdep->func_start_addr;
 
   return func_start_addr + offsetof_fde_in_sec;
 }
@@ -488,7 +506,7 @@ sframe_fre_check_range_p (sframe_decoder_ctx *dctx, uint32_t func_idx,
                          uint32_t start_ip_offset, uint32_t end_ip_offset,
                          int32_t pc)
 {
-  sframe_func_desc_entry *fdep;
+  sframe_func_desc_entry_int *fdep;
   int32_t func_start_addr;
   uint8_t rep_block_size;
   uint32_t fde_type;
@@ -499,7 +517,7 @@ sframe_fre_check_range_p (sframe_decoder_ctx *dctx, uint32_t func_idx,
   func_start_addr = sframe_decoder_get_secrel_func_start_addr (dctx, func_idx);
   fde_type = sframe_get_fde_type (fdep);
   mask_p = (fde_type == SFRAME_FDE_TYPE_PCMASK);
-  rep_block_size = fdep->sfde_func_rep_size;
+  rep_block_size = fdep->func_rep_size;
 
   if (func_start_addr > pc)
     return false;
@@ -532,7 +550,7 @@ sframe_decode_fde (const char *buf, size_t buf_size, uint8_t ver,
 
       sframe_func_desc_entry_v2 *fdep = (sframe_func_desc_entry_v2 *) buf;
       *num_fres = fdep->sfde_func_num_fres;
-      *fre_type = sframe_get_fre_type (fdep);
+      *fre_type = SFRAME_V1_FUNC_FRE_TYPE (fdep->sfde_func_info);
       *fre_offset = fdep->sfde_func_start_fre_off;
 
       *fde_size = sizeof (sframe_func_desc_entry_v2);
@@ -697,12 +715,12 @@ sframe_decoder_get_header (sframe_decoder_ctx *dctx)
 static int
 fde_func (const void *p1, const void *p2)
 {
-  const sframe_func_desc_entry *aa = p1;
-  const sframe_func_desc_entry *bb = p2;
+  const sframe_func_desc_entry_int *aa = p1;
+  const sframe_func_desc_entry_int *bb = p2;
 
-  if (aa->sfde_func_start_address < bb->sfde_func_start_address)
+  if (aa->func_start_addr < bb->func_start_addr)
     return -1;
-  else if (aa->sfde_func_start_address > bb->sfde_func_start_address)
+  else if (aa->func_start_addr > bb->func_start_addr)
     return 1;
   return 0;
 }
@@ -1224,18 +1242,18 @@ sframe_decoder_get_offsetof_fde_start_addr (sframe_decoder_ctx *dctx,
     *errp = 0;
 
   return (sframe_decoder_get_hdr_size (dctx)
-         + func_idx * sizeof (sframe_func_desc_entry)
-         + offsetof (sframe_func_desc_entry, sfde_func_start_address));
+         + func_idx * sizeof (sframe_func_desc_entry_v2)
+         + offsetof (sframe_func_desc_entry_v2, sfde_func_start_address));
 }
 
 /* Find the function descriptor entry starting which contains the specified
    address ADDR.  */
 
-static sframe_func_desc_entry *
+static sframe_func_desc_entry_int *
 sframe_get_funcdesc_with_addr_internal (sframe_decoder_ctx *ctx, int32_t addr,
                                        int *errp, uint32_t *func_idx)
 {
-  sframe_func_desc_entry *fdp;
+  sframe_func_desc_entry_int *fdp;
   int low, high;
 
   if (ctx == NULL)
@@ -1251,19 +1269,19 @@ sframe_get_funcdesc_with_addr_internal (sframe_decoder_ctx *ctx, int32_t addr,
     return sframe_ret_set_errno (errp, SFRAME_ERR_FDE_NOTSORTED);
 
   /* Do the binary search.  */
-  fdp = (sframe_func_desc_entry *) ctx->sfd_funcdesc->entry;
+  fdp = (sframe_func_desc_entry_int *) ctx->sfd_funcdesc->entry;
   low = 0;
   high = dhp->sfh_num_fdes - 1;
   while (low <= high)
     {
       int mid = low + (high - low) / 2;
 
-      /* Given sfde_func_start_address <= addr,
-        addr - sfde_func_start_address must be positive.  */
+      /* Given func_start_addr <= addr,
+        addr - func_start_addr must be positive.  */
       if (sframe_decoder_get_secrel_func_start_addr (ctx, mid) <= addr
          && ((uint32_t)(addr - sframe_decoder_get_secrel_func_start_addr (ctx,
                                                                           mid))
-             < fdp[mid].sfde_func_size))
+             < fdp[mid].func_size))
        {
          *func_idx = mid;
          return fdp + mid;
@@ -1282,7 +1300,7 @@ sframe_get_funcdesc_with_addr_internal (sframe_decoder_ctx *ctx, int32_t addr,
    is the starting location for the FRE.  */
 
 static uint32_t
-sframe_fre_get_end_ip_offset (sframe_func_desc_entry *fdep, unsigned int i,
+sframe_fre_get_end_ip_offset (sframe_func_desc_entry_int *fdep, unsigned int i,
                              const char *fres)
 {
   uint32_t end_ip_offset;
@@ -1291,7 +1309,7 @@ sframe_fre_get_end_ip_offset (sframe_func_desc_entry *fdep, unsigned int i,
   fre_type = sframe_get_fre_type (fdep);
 
   /* Get the start address of the next FRE in sequence.  */
-  if (i < fdep->sfde_func_num_fres - 1)
+  if (i < fdep->func_num_fres - 1)
     {
       sframe_decode_fre_start_address (fres, &end_ip_offset, fre_type);
       end_ip_offset -= 1;
@@ -1299,7 +1317,7 @@ sframe_fre_get_end_ip_offset (sframe_func_desc_entry *fdep, unsigned int i,
   else
     /* The end IP offset for the FRE needs to be deduced from the function
        size.  */
-    end_ip_offset = fdep->sfde_func_size - 1;
+    end_ip_offset = fdep->func_size - 1;
 
   return end_ip_offset;
 }
@@ -1312,7 +1330,7 @@ sframe_find_fre (sframe_decoder_ctx *ctx, int32_t pc,
                 sframe_frame_row_entry *frep)
 {
   sframe_frame_row_entry cur_fre;
-  sframe_func_desc_entry *fdep;
+  sframe_func_desc_entry_int *fdep;
   uint32_t func_idx;
   uint32_t fre_type, i;
   int32_t func_start_addr;
@@ -1331,10 +1349,10 @@ sframe_find_fre (sframe_decoder_ctx *ctx, int32_t pc,
 
   fre_type = sframe_get_fre_type (fdep);
 
-  fres = ctx->sfd_fres + fdep->sfde_func_start_fre_off;
+  fres = ctx->sfd_fres + fdep->func_start_fre_off;
   func_start_addr = sframe_decoder_get_secrel_func_start_addr (ctx, func_idx);
 
-  for (i = 0; i < fdep->sfde_func_num_fres; i++)
+  for (i = 0; i < fdep->func_num_fres; i++)
    {
      err = sframe_decode_fre (fres, &cur_fre, fre_type, &size);
      if (err)
@@ -1386,7 +1404,7 @@ sframe_decoder_get_funcdesc (sframe_decoder_ctx *ctx,
                             int32_t *func_start_address,
                             unsigned char *func_info)
 {
-  sframe_func_desc_entry *fdp;
+  sframe_func_desc_entry_int *fdp;
   int err = 0;
 
   if (ctx == NULL || func_start_address == NULL || num_fres == NULL
@@ -1398,10 +1416,10 @@ sframe_decoder_get_funcdesc (sframe_decoder_ctx *ctx,
   if (fdp == NULL)
     return sframe_set_errno (&err, SFRAME_ERR_FDE_NOTFOUND);
 
-  *num_fres = fdp->sfde_func_num_fres;
-  *func_start_address = fdp->sfde_func_start_address;
-  *func_size = fdp->sfde_func_size;
-  *func_info = fdp->sfde_func_info;
+  *num_fres = fdp->func_num_fres;
+  *func_start_address = fdp->func_start_addr;
+  *func_size = fdp->func_size;
+  *func_info = fdp->func_info;
 
   return 0;
 }
@@ -1415,7 +1433,7 @@ sframe_decoder_get_funcdesc_v2 (sframe_decoder_ctx *dctx,
                                unsigned char *func_info,
                                uint8_t *rep_block_size)
 {
-  sframe_func_desc_entry *fdp;
+  sframe_func_desc_entry_int *fdp;
   int err = 0;
 
   if (dctx == NULL || func_start_address == NULL
@@ -1428,11 +1446,11 @@ sframe_decoder_get_funcdesc_v2 (sframe_decoder_ctx *dctx,
   if (fdp == NULL)
     return sframe_set_errno (&err, SFRAME_ERR_FDE_NOTFOUND);
 
-  *num_fres = fdp->sfde_func_num_fres;
-  *func_start_address = fdp->sfde_func_start_address;
-  *func_size = fdp->sfde_func_size;
-  *func_info = fdp->sfde_func_info;
-  *rep_block_size = fdp->sfde_func_rep_size;
+  *num_fres = fdp->func_num_fres;
+  *func_start_address = (int32_t) fdp->func_start_addr;
+  *func_size = fdp->func_size;
+  *func_info = fdp->func_info;
+  *rep_block_size = fdp->func_rep_size;
 
   return 0;
 }
@@ -1446,7 +1464,7 @@ sframe_decoder_get_fre (sframe_decoder_ctx *ctx,
                        unsigned int fre_idx,
                        sframe_frame_row_entry *fre)
 {
-  sframe_func_desc_entry *fdep;
+  sframe_func_desc_entry_int *fdep;
   sframe_frame_row_entry ifre;
   const char *fres;
   uint32_t i;
@@ -1465,8 +1483,8 @@ sframe_decoder_get_fre (sframe_decoder_ctx *ctx,
 
   fre_type = sframe_get_fre_type (fdep);
   /* Now scan the FRE entries.  */
-  fres = ctx->sfd_fres + fdep->sfde_func_start_fre_off;
-  for (i = 0; i < fdep->sfde_func_num_fres; i++)
+  fres = ctx->sfd_fres + fdep->func_start_fre_off;
+  for (i = 0; i < fdep->func_num_fres; i++)
    {
      /* Decode the FRE at the current position.  Return it if valid.  */
      err = sframe_decode_fre (fres, &ifre, fre_type, &esz);
@@ -1476,11 +1494,11 @@ sframe_decoder_get_fre (sframe_decoder_ctx *ctx,
           return sframe_set_errno (&err, SFRAME_ERR_FRE_INVAL);
 
          /* Although a stricter sanity check on fre_start_addr like:
-              if (fdep->sfde_func_size)
-                sframe_assert (frep->fre_start_addr < fdep->sfde_func_size);
+              if (fdep->func_size)
+                sframe_assert (frep->fre_start_addr < fdep->func_size);
             is more suitable, some code has been seen to not abide by it.  See
             PR libsframe/33131.  */
-         sframe_assert (ifre.fre_start_addr <= fdep->sfde_func_size);
+         sframe_assert (ifre.fre_start_addr <= fdep->func_size);
 
         sframe_frame_row_entry_copy (fre, &ifre);
 
@@ -1507,11 +1525,11 @@ sframe_encoder_get_header (sframe_encoder_ctx *ectx)
   return hp;
 }
 
-static sframe_func_desc_entry *
+static sframe_func_desc_entry_int *
 sframe_encoder_get_funcdesc_at_index (sframe_encoder_ctx *ectx,
                                      uint32_t func_idx)
 {
-  sframe_func_desc_entry *fde = NULL;
+  sframe_func_desc_entry_int *fde = NULL;
   if (func_idx < sframe_encoder_get_num_fidx (ectx))
     {
       sf_fde_tbl *func_tbl = ectx->sfe_funcdesc;
@@ -1661,8 +1679,8 @@ sframe_encoder_get_offsetof_fde_start_addr (sframe_encoder_ctx *ectx,
     *errp = 0;
 
   return (sframe_encoder_get_hdr_size (ectx)
-         + func_idx * sizeof (sframe_func_desc_entry)
-         + offsetof (sframe_func_desc_entry, sfde_func_start_address));
+         + func_idx * sizeof (sframe_func_desc_entry_v2)
+         + offsetof (sframe_func_desc_entry_v2, sfde_func_start_address));
 }
 
 /* Add an SFrame FRE to function at FUNC_IDX'th function descriptor entry in
@@ -1674,7 +1692,7 @@ sframe_encoder_add_fre (sframe_encoder_ctx *ectx,
                        sframe_frame_row_entry *frep)
 {
   sframe_header *ehp;
-  sframe_func_desc_entry *fdep;
+  sframe_func_desc_entry_int *fdep;
   sframe_frame_row_entry *ectx_frep;
   size_t offsets_sz, esz;
   uint32_t fre_type;
@@ -1732,11 +1750,11 @@ sframe_encoder_add_fre (sframe_encoder_ctx *ectx,
   ectx_frep->fre_info = frep->fre_info;
 
   /* Although a stricter sanity check on fre_start_addr like:
-       if (fdep->sfde_func_size)
-        sframe_assert (frep->fre_start_addr < fdep->sfde_func_size);
+       if (fdep->func_size)
+        sframe_assert (frep->fre_start_addr < fdep->func_size);
      is more suitable, some code has been seen to not abide by it.  See PR
      libsframe/33131.  */
-  sframe_assert (frep->fre_start_addr <= fdep->sfde_func_size);
+  sframe_assert (frep->fre_start_addr <= fdep->func_size);
 
   /* frep has already been sanity check'd.  Get offsets size.  */
   offsets_sz = sframe_fre_offset_bytes_size (frep->fre_info);
@@ -1752,7 +1770,7 @@ sframe_encoder_add_fre (sframe_encoder_ctx *ectx,
   ehp->sfh_num_fres = fre_tbl->count;
 
   /* Update the value of the number of FREs for the function.  */
-  fdep->sfde_func_num_fres++;
+  fdep->func_num_fres++;
 
   return 0;
 
@@ -1789,7 +1807,7 @@ sframe_encoder_add_funcdesc (sframe_encoder_ctx *ectx,
   if (fd_info == NULL)
     {
       fd_tbl_sz = (sizeof (sf_fde_tbl)
-                  + (number_of_entries * sizeof (sframe_func_desc_entry)));
+                  + (number_of_entries * sizeof (sframe_func_desc_entry_int)));
       fd_info = malloc (fd_tbl_sz);
       if (fd_info == NULL)
        {
@@ -1803,7 +1821,7 @@ sframe_encoder_add_funcdesc (sframe_encoder_ctx *ectx,
     {
       fd_tbl_sz = (sizeof (sf_fde_tbl)
                   + ((fd_info->alloced + number_of_entries)
-                     * sizeof (sframe_func_desc_entry)));
+                     * sizeof (sframe_func_desc_entry_int)));
       fd_info = realloc (fd_info, fd_tbl_sz);
       if (fd_info == NULL)
        {
@@ -1812,16 +1830,15 @@ sframe_encoder_add_funcdesc (sframe_encoder_ctx *ectx,
        }
 
       memset (&fd_info->entry[fd_info->alloced], 0,
-             number_of_entries * sizeof (sframe_func_desc_entry));
+             number_of_entries * sizeof (sframe_func_desc_entry_int));
       fd_info->alloced += number_of_entries;
     }
 
-  fd_info->entry[fd_info->count].sfde_func_start_address = start_addr;
+  fd_info->entry[fd_info->count].func_start_addr = start_addr;
   /* Num FREs is updated as FREs are added for the function later via
      sframe_encoder_add_fre.  */
-  fd_info->entry[fd_info->count].sfde_func_size = func_size;
-  fd_info->entry[fd_info->count].sfde_func_start_fre_off
-    = ectx->sfe_fre_nbytes;
+  fd_info->entry[fd_info->count].func_size = func_size;
+  fd_info->entry[fd_info->count].func_start_fre_off = ectx->sfe_fre_nbytes;
 #if 0
   // Linker optimization test code cleanup later ibhagat TODO FIXME
   uint32_t fre_type = sframe_calc_fre_type (func_size);
@@ -1829,7 +1846,7 @@ sframe_encoder_add_funcdesc (sframe_encoder_ctx *ectx,
   fd_info->entry[fd_info->count].sfde_func_info
     = sframe_fde_func_info (fre_type);
 #endif
-  fd_info->entry[fd_info->count].sfde_func_info = func_info;
+  fd_info->entry[fd_info->count].func_info = func_info;
   fd_info->count++;
   ectx->sfe_funcdesc = fd_info;
   ehp->sfh_num_fdes++;
@@ -1867,7 +1884,7 @@ sframe_encoder_add_funcdesc_v2 (sframe_encoder_ctx *ectx,
     return SFRAME_ERR;
 
   fd_info = ectx->sfe_funcdesc;
-  fd_info->entry[fd_info->count-1].sfde_func_rep_size = rep_block_size;
+  fd_info->entry[fd_info->count-1].func_rep_size = rep_block_size;
 
   return 0;
 }
@@ -1887,14 +1904,14 @@ sframe_sort_funcdesc (sframe_encoder_ctx *ectx)
         FIXME - qsort_r may be more optimal.  */
 
       for (unsigned int i = 0; i < fd_info->count; i++)
-       fd_info->entry[i].sfde_func_start_address
+       fd_info->entry[i].func_start_addr
          += sframe_encoder_get_offsetof_fde_start_addr (ectx, i, NULL);
 
       qsort (fd_info->entry, fd_info->count,
-            sizeof (sframe_func_desc_entry), fde_func);
+            sizeof (sframe_func_desc_entry_int), fde_func);
 
       for (unsigned int i = 0; i < fd_info->count; i++)
-       fd_info->entry[i].sfde_func_start_address
+       fd_info->entry[i].func_start_addr
          -= sframe_encoder_get_offsetof_fde_start_addr (ectx, i, NULL);
 
       /* Update preamble's flags.  */
@@ -1984,6 +2001,26 @@ sframe_encoder_write_fre (char *contents, sframe_frame_row_entry *frep,
   return 0;
 }
 
+static int
+sframe_encoder_write_fde (const sframe_header *sfhp ATTRIBUTE_UNUSED,
+                         char *contents, sframe_func_desc_entry_int *fde,
+                         size_t *fde_write_size)
+{
+  sframe_func_desc_entry_v2 *fdep = (sframe_func_desc_entry_v2 *)contents;
+
+  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_info = fde->func_info;
+  fdep->sfde_func_rep_size = fde->func_rep_size;
+  fdep->sfde_func_padding2 = 0;
+
+  *fde_write_size = sizeof (sframe_func_desc_entry_v2);
+
+  return 0;
+}
+
 /* Serialize the core contents of the SFrame section and write out to the
    output buffer held in the encoder context ECTX.  Return SFRAME_ERR if
    failure.  */
@@ -1994,7 +2031,7 @@ sframe_encoder_write_sframe (sframe_encoder_ctx *ectx)
   char *contents;
   size_t buf_size;
   size_t hdr_size;
-  size_t all_fdes_size;
+  size_t fde_write_size, all_fdes_size;
   size_t fre_size;
   size_t esz = 0;
   sframe_header *ehp;
@@ -2002,7 +2039,7 @@ sframe_encoder_write_sframe (sframe_encoder_ctx *ectx)
   sf_fre_tbl *fr_info;
   uint32_t i, num_fdes;
   uint32_t j, num_fres;
-  sframe_func_desc_entry *fdep;
+  sframe_func_desc_entry_int *fdep;
   sframe_frame_row_entry *frep;
 
   uint32_t fre_type;
@@ -2011,7 +2048,7 @@ sframe_encoder_write_sframe (sframe_encoder_ctx *ectx)
   contents = ectx->sfe_data;
   buf_size = ectx->sfe_data_size;
   num_fdes = sframe_encoder_get_num_fidx (ectx);
-  all_fdes_size = num_fdes * sizeof (sframe_func_desc_entry);
+  all_fdes_size = num_fdes * sizeof (sframe_func_desc_entry_v2);
   ehp = sframe_encoder_get_header (ectx);
   hdr_size = sframe_get_hdr_size (ehp);
 
@@ -2043,11 +2080,11 @@ sframe_encoder_write_sframe (sframe_encoder_ctx *ectx)
     {
       fdep = &fd_info->entry[i];
       fre_type = sframe_get_fre_type (fdep);
-      num_fres = fdep->sfde_func_num_fres;
+      num_fres = fdep->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;
+       fdep->func_start_fre_off = 0;
 
       if (num_fres > 0 && fr_info == NULL)
        return sframe_set_errno (&err, SFRAME_ERR_FRE_INVAL);
@@ -2085,8 +2122,12 @@ sframe_encoder_write_sframe (sframe_encoder_ctx *ectx)
   contents += hdr_size;
 
   /* Write out the FDE table sorted on funtion start address.  */
-  memcpy (contents, fd_info->entry, all_fdes_size);
-  contents += all_fdes_size;
+  for (i = 0; i < num_fdes; i++)
+    {
+      sframe_encoder_write_fde (ehp, contents, &fd_info->entry[i],
+                               &fde_write_size);
+      contents += fde_write_size;
+    }
 
   return 0;
 }
@@ -2113,7 +2154,7 @@ sframe_encoder_write (sframe_encoder_ctx *ectx,
 
   ehp = sframe_encoder_get_header (ectx);
   hdrsize = sframe_get_hdr_size (ehp);
-  fsz = sframe_encoder_get_num_fidx (ectx) * sizeof (sframe_func_desc_entry);
+  fsz = sframe_encoder_get_num_fidx (ectx) * sizeof (sframe_func_desc_entry_v2);
   fresz = ectx->sfe_fre_nbytes;
 
   /* Encoder writes out data in the latest SFrame format version.  */