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