Home | History | Annotate | Line # | Download | only in bfd
      1 /* .sframe section processing.
      2    Copyright (C) 2022-2026 Free Software Foundation, Inc.
      3 
      4    This file is part of BFD, the Binary File Descriptor library.
      5 
      6    This program is free software; you can redistribute it and/or modify
      7    it under the terms of the GNU General Public License as published by
      8    the Free Software Foundation; either version 3 of the License, or
      9    (at your option) any later version.
     10 
     11    This program is distributed in the hope that it will be useful,
     12    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14    GNU General Public License for more details.
     15 
     16    You should have received a copy of the GNU General Public License
     17    along with this program; if not, write to the Free Software
     18    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     19    MA 02110-1301, USA.  */
     20 
     21 #include "sysdep.h"
     22 #include "bfd.h"
     23 #include "libbfd.h"
     24 #include "elf-bfd.h"
     25 #include "sframe-api.h"
     26 #include "sframe-internal.h"
     27 
     28 typedef sframe_func_desc_idx_v3 sframe_func_desc_entry;
     29 
     30 /* Return TRUE if the function has been marked for deletion during the linking
     31    process.  */
     32 
     33 static bool
     34 sframe_decoder_func_deleted_p (struct sframe_dec_info *sfd_info,
     35 			       unsigned int func_idx)
     36 {
     37   if (func_idx < sfd_info->sfd_fde_count)
     38     return sfd_info->sfd_func_bfdinfo[func_idx].func_deleted_p;
     39 
     40   return false;
     41 }
     42 
     43 /* Mark the function in the decoder info for deletion.  */
     44 
     45 static void
     46 sframe_decoder_mark_func_deleted (struct sframe_dec_info *sfd_info,
     47 				  unsigned int func_idx)
     48 {
     49   if (func_idx < sfd_info->sfd_fde_count)
     50     sfd_info->sfd_func_bfdinfo[func_idx].func_deleted_p = true;
     51 }
     52 
     53 /* Get the relocation offset from the decoder info for the given function.  */
     54 
     55 static unsigned int
     56 sframe_decoder_get_func_r_offset (struct sframe_dec_info *sfd_info,
     57 				  unsigned int func_idx)
     58 {
     59   BFD_ASSERT (func_idx < sfd_info->sfd_fde_count);
     60   unsigned int func_r_offset
     61     = sfd_info->sfd_func_bfdinfo[func_idx].func_r_offset;
     62   /* There must have been a reloc.  */
     63   BFD_ASSERT (func_r_offset);
     64   return func_r_offset;
     65 }
     66 
     67 /* Bookkeep the function relocation offset in the decoder info.  */
     68 
     69 static void
     70 sframe_decoder_set_func_r_offset (struct sframe_dec_info *sfd_info,
     71 				  unsigned int func_idx,
     72 				  unsigned int r_offset)
     73 {
     74   if (func_idx < sfd_info->sfd_fde_count)
     75     sfd_info->sfd_func_bfdinfo[func_idx].func_r_offset = r_offset;
     76 }
     77 
     78 /* Get the relocation index in the elf_reloc_cookie for the function.  */
     79 
     80 static unsigned int
     81 sframe_decoder_get_func_reloc_index (struct sframe_dec_info *sfd_info,
     82 				     unsigned int func_idx)
     83 {
     84   BFD_ASSERT (func_idx < sfd_info->sfd_fde_count);
     85   return sfd_info->sfd_func_bfdinfo[func_idx].func_reloc_index;
     86 }
     87 
     88 /* Bookkeep the relocation index in the elf_reloc_cookie for the function.  */
     89 
     90 static void
     91 sframe_decoder_set_func_reloc_index (struct sframe_dec_info *sfd_info,
     92 				     unsigned int func_idx,
     93 				     unsigned int reloc_index)
     94 {
     95   if (func_idx < sfd_info->sfd_fde_count)
     96     sfd_info->sfd_func_bfdinfo[func_idx].func_reloc_index = reloc_index;
     97 }
     98 
     99 /* Initialize the set of additional information in CFD_INFO,
    100    needed for linking SEC.  Returns TRUE if setup is done successfully.  */
    101 
    102 static bool
    103 sframe_decoder_init_func_bfdinfo (bfd *abfd,
    104 				  const asection *sec,
    105 				  struct sframe_dec_info *sfd_info,
    106 				  const struct elf_reloc_cookie *cookie)
    107 {
    108   unsigned int fde_count;
    109   unsigned int func_bfdinfo_size, i;
    110   const Elf_Internal_Rela *rel;
    111 
    112   fde_count = sframe_decoder_get_num_fidx (sfd_info->sfd_ctx);
    113   sfd_info->sfd_fde_count = fde_count;
    114 
    115   /* Allocate and clear the memory.  */
    116   func_bfdinfo_size = (sizeof (struct sframe_func_bfdinfo)) * fde_count;
    117   sfd_info->sfd_func_bfdinfo = bfd_zalloc (abfd, func_bfdinfo_size);
    118   if (sfd_info->sfd_func_bfdinfo == NULL)
    119     return false;
    120 
    121   /* For linker generated .sframe sections, we have no relocs.  Skip.  */
    122   if ((sec->flags & SEC_LINKER_CREATED) && cookie->rels == NULL)
    123     return true;
    124 
    125   rel = cookie->rels;
    126   unsigned int reloc_index = 0;
    127   for (i = 0; i < fde_count; i++)
    128     {
    129       /* Bookkeep the relocation offset and relocation index of each function
    130 	 for later use.  There may be some R_*_NONE relocations intermingled
    131 	 (see PR ld/33401).  Skip over those.  */
    132       while (rel->r_info == 0)
    133 	{
    134 	  reloc_index++;
    135 	  rel++;
    136 	}
    137 
    138       BFD_ASSERT (reloc_index < sec->reloc_count);
    139 
    140       sframe_decoder_set_func_r_offset (sfd_info, i, rel->r_offset);
    141       sframe_decoder_set_func_reloc_index (sfd_info, i, reloc_index);
    142 
    143       reloc_index++;
    144       rel++;
    145     }
    146 
    147   /* If there are more relocation entries, they must be R_*_NONE which
    148      may be generated from relocations against discarded sections by
    149      ld -r.  */
    150   for (; rel < cookie->relend; rel++)
    151    if (rel->r_info != 0)
    152      break;
    153   BFD_ASSERT (rel == cookie->relend);
    154 
    155   return true;
    156 }
    157 
    158 /* Read the value from CONTENTS at the specified OFFSET for the given ABFD.  */
    159 
    160 static bfd_vma
    161 sframe_read_value (bfd *abfd, bfd_byte *contents, unsigned int offset,
    162 		   unsigned int width)
    163 {
    164   BFD_ASSERT (contents && offset);
    165   /* ATM, for SFrame, the sole usecase is of reading only the 8-byte relocated
    166      value (signed offset for func start addr).  */
    167   BFD_ASSERT (width == 8);
    168   /* FIXME endianness ?? */
    169   unsigned char *buf = contents + offset;
    170   bfd_vma value = bfd_get_signed_64 (abfd, buf);
    171   return value;
    172 }
    173 
    174 /* Return true if any of the input BFDs contains at least one .sframe
    175    section.  */
    176 
    177 bool
    178 _bfd_elf_sframe_present_input_bfds (struct bfd_link_info *info)
    179 {
    180   /* Find if any input file has an .sframe section.  */
    181   for (bfd *pbfd = info->input_bfds; pbfd != NULL; pbfd = pbfd->link.next)
    182     if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour
    183 	&& bfd_count_sections (pbfd) != 0)
    184       {
    185 	asection *sec = bfd_get_section_by_name (pbfd, ".sframe");
    186 	if (sec != NULL)
    187 	  return true;
    188       }
    189   return false;
    190 }
    191 
    192 /* Return true if there is at least one non-empty .sframe section in
    193    input files.  Can only be called after ld has mapped input to
    194    output sections, and before sections are stripped.  */
    195 
    196 bool
    197 _bfd_elf_sframe_present (struct bfd_link_info *info)
    198 {
    199   asection *sframe = bfd_get_section_by_name (info->output_bfd, ".sframe");
    200 
    201   if (sframe == NULL)
    202     return false;
    203 
    204   /* Count only sections which have at least a single FDE.  */
    205   for (sframe = sframe->map_head.s; sframe != NULL; sframe = sframe->map_head.s)
    206     /* Note that this may become an approximate check in the future when
    207        some ABI/arch begin to use the sfh_auxhdr_len.  When sfh_auxhdr_len has
    208        non-zero value, it will need to be accounted for in the calculation of
    209        the SFrame header size.  */
    210     if (sframe->size > sizeof (sframe_header))
    211       return true;
    212   return false;
    213 }
    214 
    215 /* Try to parse .sframe section SEC, which belongs to ABFD.  Store the
    216    information in the section's sec_info field on success.  COOKIE
    217    describes the relocations in SEC.
    218 
    219    Returns TRUE if success, FALSE if any error or failure.  */
    220 
    221 bool
    222 _bfd_elf_parse_sframe (bfd *abfd,
    223 		       struct bfd_link_info *info ATTRIBUTE_UNUSED,
    224 		       asection *sec, struct elf_reloc_cookie *cookie)
    225 {
    226   bfd_byte *sfbuf = NULL;
    227   struct sframe_dec_info *sfd_info;
    228   sframe_decoder_ctx *sfd_ctx;
    229   bfd_size_type sf_size;
    230   int decerr = 0;
    231 
    232   if (info->discard_sframe)
    233     sec->flags |= SEC_EXCLUDE;
    234 
    235   /* Prior versions of assembler and ld were generating SFrame sections with
    236      section type SHT_PROGBITS.  Issue an error for lack of support for such
    237      objects now.  Even if section size is zero, a valid section type is
    238      expected.  */
    239   if (elf_section_type (sec) != SHT_GNU_SFRAME)
    240     {
    241       _bfd_error_handler
    242 	(_("error in %pB(%pA); unexpected SFrame section type"),
    243 	 abfd, sec);
    244       return false;
    245     }
    246 
    247   if (sec->size == 0
    248       || (sec->flags & SEC_HAS_CONTENTS) == 0)
    249     {
    250       /* This file does not contain .sframe information.  */
    251       return false;
    252     }
    253 
    254   /* Check if this section was already parsed.  */
    255   if (sec->sec_info_type == SEC_INFO_TYPE_SFRAME)
    256     return true;
    257 
    258   if (bfd_is_abs_section (sec->output_section))
    259     {
    260       /* At least one of the sections is being discarded from the
    261 	 link, so we should just ignore them.  */
    262       return false;
    263     }
    264 
    265   /* Read the SFrame stack trace information from abfd.  */
    266   if (!_bfd_elf_mmap_section_contents (abfd, sec, &sfbuf))
    267     goto fail_no_free;
    268 
    269   /* Decode the buffer and keep decoded contents for later use.
    270      Relocations are performed later, but are such that the section's
    271      size is unaffected.  */
    272   sfd_info = bfd_zalloc (abfd, sizeof (*sfd_info));
    273   sf_size = sec->size;
    274 
    275   sfd_info->sfd_ctx = sframe_decode ((const char*)sfbuf, sf_size, &decerr);
    276   sfd_info->sfd_state = SFRAME_SEC_DECODED;
    277   sfd_ctx = sfd_info->sfd_ctx;
    278   if (!sfd_ctx)
    279     /* Free'ing up any memory held by decoder context is done by
    280        sframe_decode in case of error.  */
    281     goto fail_no_free;
    282 
    283   if (!sframe_decoder_init_func_bfdinfo (abfd, sec, sfd_info, cookie))
    284     {
    285       sframe_decoder_free (&sfd_ctx);
    286       goto fail_no_free;
    287     }
    288 
    289   sec->sec_info = sfd_info;
    290   sec->sec_info_type = SEC_INFO_TYPE_SFRAME;
    291 
    292   goto success;
    293 
    294 fail_no_free:
    295   _bfd_error_handler
    296    (_("error in %pB(%pA); no .sframe will be created"),
    297     abfd, sec);
    298   return false;
    299 success:
    300   _bfd_elf_munmap_section_contents (sec, sfbuf);
    301   return true;
    302 }
    303 
    304 /* This function is called for each input file before the .sframe section
    305    is relocated.  It marks the SFrame FDE for the discarded functions for
    306    deletion.
    307 
    308    The function returns TRUE iff any entries have been deleted.  */
    309 
    310 bool
    311 _bfd_elf_discard_section_sframe
    312    (asection *sec,
    313     bool (*reloc_symbol_deleted_p) (bfd_vma, void *),
    314     struct elf_reloc_cookie *cookie)
    315 {
    316   bool changed;
    317   bool keep;
    318   unsigned int i;
    319   unsigned int func_desc_offset;
    320   unsigned int num_fidx;
    321   struct sframe_dec_info *sfd_info;
    322 
    323   changed = false;
    324   /* FIXME - if relocatable link and changed = true, how does the final
    325      .rela.sframe get updated ?.  */
    326   keep = false;
    327 
    328   sfd_info = sec->sec_info;
    329 
    330   /* Skip checking for the linker created .sframe sections
    331      (for PLT sections).  */
    332   if ((sec->flags & SEC_LINKER_CREATED) == 0 || cookie->rels != NULL)
    333     {
    334       num_fidx = sframe_decoder_get_num_fidx (sfd_info->sfd_ctx);
    335       for (i = 0; i < num_fidx; i++)
    336 	{
    337 	  func_desc_offset = sframe_decoder_get_func_r_offset (sfd_info, i);
    338 
    339 	  cookie->rel = cookie->rels
    340 	    + sframe_decoder_get_func_reloc_index (sfd_info, i);
    341 	  keep = !(*reloc_symbol_deleted_p) (func_desc_offset, cookie);
    342 
    343 	  if (!keep)
    344 	    {
    345 	      sframe_decoder_mark_func_deleted (sfd_info, i);
    346 	      changed = true;
    347 	    }
    348 	}
    349     }
    350   return changed;
    351 }
    352 
    353 /* Update the reference to the output .sframe section in the output ELF
    354    BFD ABFD.  Returns true if no error.  */
    355 
    356 bool
    357 _bfd_elf_set_section_sframe (bfd *abfd, struct bfd_link_info *info)
    358 {
    359   asection *cfsec;
    360 
    361   cfsec = bfd_get_section_by_name (info->output_bfd, ".sframe");
    362   if (!cfsec)
    363     return false;
    364 
    365   elf_section_type (cfsec) = SHT_GNU_SFRAME;
    366   elf_sframe (abfd) = cfsec;
    367 
    368   return true;
    369 }
    370 
    371 /* Merge .sframe section SEC.  This is called with the relocated
    372    CONTENTS.  */
    373 
    374 bool
    375 _bfd_elf_merge_section_sframe (bfd *abfd,
    376 			       struct bfd_link_info *info,
    377 			       asection *sec,
    378 			       bfd_byte *contents)
    379 {
    380   struct sframe_dec_info *sfd_info;
    381   struct sframe_enc_info *sfe_info;
    382   sframe_decoder_ctx *sfd_ctx;
    383   sframe_encoder_ctx *sfe_ctx;
    384   uint8_t sfd_ctx_abi_arch;
    385   int8_t sfd_ctx_fixed_fp_offset;
    386   int8_t sfd_ctx_fixed_ra_offset;
    387   uint8_t dctx_version;
    388   uint8_t ectx_version;
    389   uint8_t dctx_flags;
    390   uint8_t ectx_flags;
    391   int encerr = 0;
    392 
    393   struct elf_link_hash_table *htab;
    394   asection *cfsec;
    395 
    396   /* Sanity check - handle SFrame sections only.  */
    397   if (sec->sec_info_type != SEC_INFO_TYPE_SFRAME)
    398     return false;
    399 
    400   sfd_info = sec->sec_info;
    401   sfd_ctx = sfd_info->sfd_ctx;
    402 
    403   htab = elf_hash_table (info);
    404   sfe_info = &(htab->sfe_info);
    405   sfe_ctx = sfe_info->sfe_ctx;
    406 
    407   /* All input bfds are expected to have a valid SFrame section.  Even if
    408      the SFrame section is empty with only a header, there must be a valid
    409      SFrame decoder context by now.  The SFrame encoder context, however,
    410      will get set later here, if this is the first call to the function.  */
    411   if (sfd_ctx == NULL || sfe_info == NULL)
    412     return false;
    413 
    414   dctx_flags = sframe_decoder_get_flags (sfd_ctx);
    415 
    416   if (htab->sfe_info.sfe_ctx == NULL)
    417     {
    418       sfd_ctx_abi_arch = sframe_decoder_get_abi_arch (sfd_ctx);
    419       sfd_ctx_fixed_fp_offset = sframe_decoder_get_fixed_fp_offset (sfd_ctx);
    420       sfd_ctx_fixed_ra_offset = sframe_decoder_get_fixed_ra_offset (sfd_ctx);
    421 
    422       /* Valid values are non-zero.  */
    423       if (!sfd_ctx_abi_arch)
    424 	return false;
    425 
    426       /* In-memory FDEs in the encoder object are unsorted during linking and
    427 	 will be sorted before emission.  Reset SFRAME_F_FDE_SORTED to aptly
    428 	 reflect that (doing so has no other functional value at this time
    429 	 though).  */
    430       uint8_t tflags = dctx_flags & ~SFRAME_F_FDE_SORTED;
    431       /* ld always generates an output section with
    432 	 SFRAME_F_FDE_FUNC_START_PCREL flag set.  Later using
    433 	 SFRAME_V2_GNU_AS_LD_ENCODING_FLAGS, it is enforced that the provided
    434 	 input sections also have this flag set.  */
    435       tflags |= SFRAME_F_FDE_FUNC_START_PCREL;
    436       htab->sfe_info.sfe_ctx = sframe_encode (SFRAME_VERSION_3,
    437 					      tflags, /* SFrame flags.  */
    438 					      sfd_ctx_abi_arch,
    439 					      sfd_ctx_fixed_fp_offset,
    440 					      sfd_ctx_fixed_ra_offset,
    441 					      &encerr);
    442       /* Handle errors from sframe_encode.  */
    443       if (htab->sfe_info.sfe_ctx == NULL)
    444 	return false;
    445     }
    446   sfe_ctx = sfe_info->sfe_ctx;
    447 
    448   if (sfe_info->sframe_section == NULL)
    449     {
    450       /* Make sure things are set for an eventual write.
    451 	 Size of the output section is not known until
    452 	 _bfd_elf_write_section_sframe is ready with the buffer
    453 	 to write out.  */
    454       cfsec = bfd_get_section_by_name (info->output_bfd, ".sframe");
    455       if (cfsec)
    456 	{
    457 	  sfe_info->sframe_section = cfsec;
    458 	  // elf_sframe (abfd) = cfsec;
    459 	}
    460       else
    461 	return false;
    462     }
    463 
    464   /* Check that all .sframe sections being linked have the same
    465      ABI/arch.  */
    466   if (sframe_decoder_get_abi_arch (sfd_ctx)
    467       != sframe_encoder_get_abi_arch (sfe_ctx))
    468     {
    469       _bfd_error_handler
    470 	(_("error in %pB (%pA); unexpected ABI in SFrame section"),
    471 	 sec->owner, sec);
    472       return false;
    473     }
    474 
    475   /* Check that all .sframe sections being linked have the same version.  */
    476   dctx_version = sframe_decoder_get_version (sfd_ctx);
    477   ectx_version = sframe_encoder_get_version (sfe_ctx);
    478   if (dctx_version != SFRAME_VERSION_3 || dctx_version != ectx_version)
    479     {
    480       _bfd_error_handler
    481 	(_("error in %pB (%pA); unexpected SFrame format version %" PRIu8),
    482 	 sec->owner, sec, dctx_version);
    483       return false;
    484     }
    485 
    486   /* Check that all SFrame sections being linked have the 'data encoding'
    487      related flags set.  The implementation does not support updating these
    488      data encodings on the fly; confirm by checking the ectx_flags.  */
    489   ectx_flags = sframe_encoder_get_flags (sfe_ctx);
    490   if ((dctx_flags & ectx_flags & SFRAME_V2_GNU_AS_LD_ENCODING_FLAGS)
    491       != SFRAME_V2_GNU_AS_LD_ENCODING_FLAGS)
    492     {
    493       _bfd_error_handler
    494 	(_("error in %pB (%pA); unexpected SFrame data encoding"),
    495 	 sec->owner, sec);
    496       return false;
    497     }
    498 
    499   /* Iterate over the function descriptor entries and the FREs of the
    500      function from the decoder context.  Add each of them to the encoder
    501      context, if suitable.  */
    502   uint32_t i = 0, cur_fidx = 0;
    503 
    504   uint32_t num_fidx = sframe_decoder_get_num_fidx (sfd_ctx);
    505   uint32_t num_enc_fidx = sframe_encoder_get_num_fidx (sfe_ctx);
    506   uint8_t reloc_size = 8;
    507 
    508   for (i = 0; i < num_fidx; i++)
    509     {
    510       unsigned int num_fres = 0;
    511       int64_t func_start_addr;
    512       bfd_vma address;
    513       uint32_t func_size = 0;
    514       unsigned int r_offset = 0;
    515       bool pltn_reloc_by_hand = false;
    516       unsigned int pltn_r_offset = 0;
    517 
    518       if (!sframe_decoder_get_funcdesc_v3 (sfd_ctx, i, &num_fres, &func_size,
    519 					   &func_start_addr, NULL, NULL, NULL))
    520 	{
    521 	  /* If function belongs to a deleted section, skip editing the
    522 	     function descriptor entry.  */
    523 	  if (sframe_decoder_func_deleted_p(sfd_info, i))
    524 	    continue;
    525 
    526 	  /* Don't edit function descriptor entries for relocatable link.  */
    527 	  if (!bfd_link_relocatable (info))
    528 	    {
    529 	      if (!(sec->flags & SEC_LINKER_CREATED))
    530 		{
    531 		  /* Get relocated contents by reading the value of the
    532 		     relocated function start address at the beginning of the
    533 		     function descriptor entry.  */
    534 		  r_offset = sframe_decoder_get_func_r_offset (sfd_info, i);
    535 		}
    536 	      else
    537 		{
    538 		  /* Expected to land here when SFrame stack trace info is
    539 		     created dynamically for the .plt* sections.  These
    540 		     sections are expected to have upto two SFrame FDE entries.
    541 		     Although the code should work for > 2,  leaving this
    542 		     assert here for safety.  */
    543 		  BFD_ASSERT (num_fidx <= 2);
    544 		  /* For the first entry, we know the offset of the SFrame FDE's
    545 		     sfde_func_start_address.  Side note: see how the value
    546 		     of PLT_SFRAME_FDE_START_OFFSET is also set to the
    547 		     same.  */
    548 		  r_offset = sframe_decoder_get_hdr_size (sfd_ctx);
    549 		  /* For any further SFrame FDEs, the generator has already put
    550 		     in an offset in place of sfde_func_start_address of the
    551 		     corresponding FDE.  We will use it by hand to relocate.  */
    552 		  if (i > 0)
    553 		    {
    554 		      pltn_r_offset
    555 			= r_offset + (i * sizeof (sframe_func_desc_entry));
    556 		      pltn_reloc_by_hand = true;
    557 		    }
    558 		}
    559 
    560 	      /* Get the SFrame FDE function start address after relocation.  */
    561 	      address = sframe_read_value (abfd, contents, r_offset,
    562 					   reloc_size);
    563 	      if (pltn_reloc_by_hand)
    564 		address += sframe_read_value (abfd, contents, pltn_r_offset,
    565 					      reloc_size);
    566 	      address += (sec->output_offset + r_offset);
    567 	      /* SFrame FDE function start address is an offset from the
    568 		 sfde_func_start_address field to the start PC.  The
    569 		 calculation below is the distance of sfde_func_start_address
    570 		 field from the start of the output SFrame section.  */
    571 	      uint32_t offsetof_fde_in_sec
    572 		= sframe_encoder_get_offsetof_fde_start_addr (sfe_ctx,
    573 							      cur_fidx + num_enc_fidx,
    574 							      NULL);
    575 	      address -= offsetof_fde_in_sec;
    576 
    577 	      /* FIXME For testing only. Cleanup later.  */
    578 	      // address += (sec->output_section->vma);
    579 
    580 	      func_start_addr = address;
    581 	    }
    582 
    583 	  /* Update the encoder context with FDE index entry.  */
    584 	  int err = sframe_encoder_add_funcdesc (sfe_ctx, func_start_addr,
    585 						 func_size);
    586 	  cur_fidx++;
    587 	  BFD_ASSERT (!err);
    588 	}
    589 
    590       uint32_t fde_num_fres = 0;
    591       char *fres_buf = NULL;
    592       size_t fres_buf_size = 0;
    593 
    594       int err = sframe_decoder_get_fres_buf (sfd_ctx, i, &fres_buf,
    595 					     &fres_buf_size, &fde_num_fres);
    596       BFD_ASSERT (!err && fde_num_fres == num_fres);
    597       err = sframe_encoder_add_fres_buf (sfe_ctx, cur_fidx - 1 + num_enc_fidx,
    598 					 num_fres, fres_buf, fres_buf_size);
    599       BFD_ASSERT (!err);
    600     }
    601 
    602   sfd_info->sfd_state = SFRAME_SEC_MERGED;
    603   /* Free the SFrame decoder context.  */
    604   sframe_decoder_free (&sfd_ctx);
    605 
    606   return true;
    607 }
    608 
    609 /* Adjust an address in the .sframe section.  Given OFFSET within
    610    SEC, this returns the new offset in the merged .sframe section,
    611    or -1 if the address refers to an FDE which has been removed.
    612 
    613    PS: This function assumes that _bfd_elf_merge_section_sframe has
    614    not been called on the input section SEC yet.  Note how it uses
    615    sframe_encoder_get_num_fidx () to figure out the offset of FDE
    616    in the output section.  */
    617 
    618 bfd_vma
    619 _bfd_elf_sframe_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED,
    620 				struct bfd_link_info *info,
    621 				asection *sec,
    622 				bfd_vma offset)
    623 {
    624   struct sframe_dec_info *sfd_info;
    625   struct sframe_enc_info *sfe_info;
    626   sframe_decoder_ctx *sfd_ctx;
    627   sframe_encoder_ctx *sfe_ctx;
    628   struct elf_link_hash_table *htab;
    629 
    630   unsigned int sec_fde_idx, out_num_fdes;
    631   unsigned int sfd_num_fdes, sfe_num_fdes;
    632   uint32_t sfd_fde_offset;
    633   bfd_vma new_offset;
    634 
    635   if (sec->sec_info_type != SEC_INFO_TYPE_SFRAME)
    636     return offset;
    637 
    638   sfd_info = sec->sec_info;
    639   sfd_ctx = sfd_info->sfd_ctx;
    640   sfd_num_fdes = sframe_decoder_get_num_fidx (sfd_ctx);
    641 
    642   BFD_ASSERT (sfd_info->sfd_state == SFRAME_SEC_DECODED);
    643 
    644   htab = elf_hash_table (info);
    645   sfe_info = &(htab->sfe_info);
    646   sfe_ctx = sfe_info->sfe_ctx;
    647   sfe_num_fdes = sframe_encoder_get_num_fidx (sfe_ctx);
    648 
    649   /* The index of this FDE in the output section depends on number of deleted
    650      functions (between index 0 and sec_fde_idx), if any.  */
    651   out_num_fdes = 0;
    652   sec_fde_idx = 0;
    653   for (unsigned int i = 0; i < sfd_num_fdes; i++)
    654     {
    655       sfd_fde_offset = sframe_decoder_get_offsetof_fde_start_addr (sfd_ctx,
    656 								   i, NULL);
    657       if (!sframe_decoder_func_deleted_p (sfd_info, i))
    658 	out_num_fdes++;
    659 
    660       if (sfd_fde_offset == offset)
    661 	{
    662 	  /* Found the index of the FDE (at OFFSET) in the input section.  */
    663 	  sec_fde_idx = i;
    664 	  break;
    665 	}
    666     }
    667 
    668   if (sframe_decoder_func_deleted_p (sfd_info, sec_fde_idx))
    669     return (bfd_vma) -1;
    670 
    671   /* The number of FDEs in the output SFrame section.  Note that the output
    672      index of the FDE of interest will be (out_num_fdes - 1).  */
    673   out_num_fdes += sfe_num_fdes;
    674 
    675   new_offset = sframe_decoder_get_offsetof_fde_start_addr (sfd_ctx,
    676 							   out_num_fdes - 1,
    677 							   NULL);
    678   /* Recall that SFrame section merging has distinct requirements: All SFrame
    679      FDEs from input sections are clubbed together in the beginning of the
    680      output section.  So, at this point in the current function, the new_offset
    681      is the correct offset in the merged output SFrame section.  Note, however,
    682      that the default mechanism in the _elf_link_input_bfd will do the
    683      following adjustment:
    684        irela->r_offset += o->output_offset;
    685      for all section types.  However, such an adjustment in the RELA offset is
    686      _not_ needed for SFrame sections.  Perform the reverse adjustment here so
    687      that the default mechanism does not need additional SFrame specific
    688      checks.  */
    689   new_offset -= sec->output_offset;
    690 
    691   return new_offset;
    692 }
    693 
    694 /* Write out the .sframe section.  This must be called after
    695    _bfd_elf_merge_section_sframe has been called on all input
    696    .sframe sections.  */
    697 
    698 bool
    699 _bfd_elf_write_section_sframe (bfd *abfd, struct bfd_link_info *info)
    700 {
    701   bool retval = true;
    702 
    703   struct elf_link_hash_table *htab;
    704   struct sframe_enc_info *sfe_info;
    705   sframe_encoder_ctx *sfe_ctx;
    706   asection *sec;
    707   void *contents;
    708   size_t sec_size;
    709   int err = 0;
    710 
    711   htab = elf_hash_table (info);
    712   sfe_info = &htab->sfe_info;
    713   sec = sfe_info->sframe_section;
    714   sfe_ctx = sfe_info->sfe_ctx;
    715 
    716   if (sec == NULL)
    717     return true;
    718 
    719   bool sort_p = !bfd_link_relocatable (info);
    720   contents = sframe_encoder_write (sfe_ctx, &sec_size, sort_p, &err);
    721   sec->size = (bfd_size_type) sec_size;
    722 
    723   if (!bfd_set_section_contents (abfd, sec->output_section, contents,
    724 				 (file_ptr) sec->output_offset,
    725 				 sec->size))
    726     retval = false;
    727   else
    728     {
    729       Elf_Internal_Shdr *hdr = &elf_section_data (sec)->this_hdr;
    730       hdr->sh_size = sec->size;
    731     }
    732 
    733   sframe_encoder_free (&sfe_ctx);
    734 
    735   return retval;
    736 }
    737