Home | History | Annotate | Line # | Download | only in bfd
elf-sframe.c revision 1.1
      1  1.1  christos /* .sframe section processing.
      2  1.1  christos    Copyright (C) 2022 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  christos 
     27  1.1  christos /* Return TRUE if the function has been marked for deletion during the linking
     28  1.1  christos    process.  */
     29  1.1  christos 
     30  1.1  christos static bool
     31  1.1  christos sframe_decoder_func_deleted_p (struct sframe_dec_info *sfd_info,
     32  1.1  christos 			       unsigned int func_idx)
     33  1.1  christos {
     34  1.1  christos   if (func_idx < sfd_info->sfd_fde_count)
     35  1.1  christos     return sfd_info->sfd_func_bfdinfo[func_idx].func_deleted_p;
     36  1.1  christos 
     37  1.1  christos   return false;
     38  1.1  christos }
     39  1.1  christos 
     40  1.1  christos /* Mark the function in the decoder info for deletion.  */
     41  1.1  christos 
     42  1.1  christos static void
     43  1.1  christos sframe_decoder_mark_func_deleted (struct sframe_dec_info *sfd_info,
     44  1.1  christos 				  unsigned int func_idx)
     45  1.1  christos {
     46  1.1  christos   if (func_idx < sfd_info->sfd_fde_count)
     47  1.1  christos     sfd_info->sfd_func_bfdinfo[func_idx].func_deleted_p = true;
     48  1.1  christos }
     49  1.1  christos 
     50  1.1  christos /* Get the relocation offset from the decoder info for the given function.  */
     51  1.1  christos 
     52  1.1  christos static unsigned int
     53  1.1  christos sframe_decoder_get_func_r_offset (struct sframe_dec_info *sfd_info,
     54  1.1  christos 				  unsigned int func_idx)
     55  1.1  christos {
     56  1.1  christos   BFD_ASSERT (func_idx < sfd_info->sfd_fde_count);
     57  1.1  christos   unsigned int func_r_offset
     58  1.1  christos     = sfd_info->sfd_func_bfdinfo[func_idx].func_r_offset;
     59  1.1  christos   /* There must have been a reloc.  */
     60  1.1  christos   BFD_ASSERT (func_r_offset);
     61  1.1  christos   return func_r_offset;
     62  1.1  christos }
     63  1.1  christos 
     64  1.1  christos /* Bookkeep the function relocation offset in the decoder info.  */
     65  1.1  christos 
     66  1.1  christos static void
     67  1.1  christos sframe_decoder_set_func_r_offset (struct sframe_dec_info *sfd_info,
     68  1.1  christos 				  unsigned int func_idx,
     69  1.1  christos 				  unsigned int r_offset)
     70  1.1  christos {
     71  1.1  christos   if (func_idx < sfd_info->sfd_fde_count)
     72  1.1  christos     sfd_info->sfd_func_bfdinfo[func_idx].func_r_offset = r_offset;
     73  1.1  christos }
     74  1.1  christos 
     75  1.1  christos /* Get the relocation index in the elf_reloc_cookie for the function.  */
     76  1.1  christos 
     77  1.1  christos static unsigned int
     78  1.1  christos sframe_decoder_get_func_reloc_index (struct sframe_dec_info *sfd_info,
     79  1.1  christos 				     unsigned int func_idx)
     80  1.1  christos {
     81  1.1  christos   BFD_ASSERT (func_idx < sfd_info->sfd_fde_count);
     82  1.1  christos   return sfd_info->sfd_func_bfdinfo[func_idx].func_reloc_index;
     83  1.1  christos }
     84  1.1  christos 
     85  1.1  christos /* Bookkeep the relocation index in the elf_reloc_cookie for the function.  */
     86  1.1  christos 
     87  1.1  christos static void
     88  1.1  christos sframe_decoder_set_func_reloc_index (struct sframe_dec_info *sfd_info,
     89  1.1  christos 				     unsigned int func_idx,
     90  1.1  christos 				     unsigned int reloc_index)
     91  1.1  christos {
     92  1.1  christos   if (func_idx < sfd_info->sfd_fde_count)
     93  1.1  christos     sfd_info->sfd_func_bfdinfo[func_idx].func_reloc_index = reloc_index;
     94  1.1  christos }
     95  1.1  christos 
     96  1.1  christos /* Initialize the set of additional information in CFD_INFO,
     97  1.1  christos    needed for linking SEC.  Returns TRUE if setup is done successfully.  */
     98  1.1  christos 
     99  1.1  christos static bool
    100  1.1  christos sframe_decoder_init_func_bfdinfo (asection *sec,
    101  1.1  christos 				  struct sframe_dec_info *sfd_info,
    102  1.1  christos 				  struct elf_reloc_cookie *cookie)
    103  1.1  christos {
    104  1.1  christos   unsigned int fde_count;
    105  1.1  christos   unsigned int func_bfdinfo_size, i;
    106  1.1  christos 
    107  1.1  christos   fde_count = sframe_decoder_get_num_fidx (sfd_info->sfd_ctx);
    108  1.1  christos   sfd_info->sfd_fde_count = fde_count;
    109  1.1  christos 
    110  1.1  christos   /* Allocate and clear the memory.  */
    111  1.1  christos   func_bfdinfo_size = (sizeof (struct sframe_func_bfdinfo)) * fde_count;
    112  1.1  christos   sfd_info->sfd_func_bfdinfo
    113  1.1  christos     = (struct sframe_func_bfdinfo*) bfd_malloc (func_bfdinfo_size);
    114  1.1  christos   if (sfd_info->sfd_func_bfdinfo == NULL)
    115  1.1  christos     return false;
    116  1.1  christos   memset (sfd_info->sfd_func_bfdinfo, 0, func_bfdinfo_size);
    117  1.1  christos 
    118  1.1  christos   /* For linker generated .sframe sections, we have no relocs.  Skip.  */
    119  1.1  christos   if ((sec->flags & SEC_LINKER_CREATED) && cookie->rels == NULL)
    120  1.1  christos     return true;
    121  1.1  christos 
    122  1.1  christos   for (i = 0; i < fde_count; i++)
    123  1.1  christos     {
    124  1.1  christos       cookie->rel = cookie->rels + i;
    125  1.1  christos       BFD_ASSERT (cookie->rel < cookie->relend);
    126  1.1  christos       /* Bookkeep the relocation offset and relocation index of each function
    127  1.1  christos 	 for later use.  */
    128  1.1  christos       sframe_decoder_set_func_r_offset (sfd_info, i, cookie->rel->r_offset);
    129  1.1  christos       sframe_decoder_set_func_reloc_index (sfd_info, i,
    130  1.1  christos 					   (cookie->rel - cookie->rels));
    131  1.1  christos 
    132  1.1  christos       cookie->rel++;
    133  1.1  christos     }
    134  1.1  christos   BFD_ASSERT (cookie->rel == cookie->relend);
    135  1.1  christos 
    136  1.1  christos   return true;
    137  1.1  christos }
    138  1.1  christos 
    139  1.1  christos /* Read the value from CONTENTS at the specified OFFSET for the given ABFD.  */
    140  1.1  christos 
    141  1.1  christos static bfd_vma
    142  1.1  christos sframe_read_value (bfd *abfd, bfd_byte *contents, unsigned int offset,
    143  1.1  christos 		   unsigned int width)
    144  1.1  christos {
    145  1.1  christos   BFD_ASSERT (contents && offset);
    146  1.1  christos   /* Supporting the usecase of reading only the 4-byte relocated
    147  1.1  christos      value (signed offset for func start addr) for now.  */
    148  1.1  christos   BFD_ASSERT (width == 4);
    149  1.1  christos   /* FIXME endianness ?? */
    150  1.1  christos   unsigned char *buf = contents + offset;
    151  1.1  christos   bfd_vma value = bfd_get_signed_32 (abfd, buf);
    152  1.1  christos   return value;
    153  1.1  christos }
    154  1.1  christos 
    155  1.1  christos /* Return true if there is at least one non-empty .sframe section in
    156  1.1  christos    input files.  Can only be called after ld has mapped input to
    157  1.1  christos    output sections, and before sections are stripped.  */
    158  1.1  christos 
    159  1.1  christos bool
    160  1.1  christos _bfd_elf_sframe_present (struct bfd_link_info *info)
    161  1.1  christos {
    162  1.1  christos   asection *sframe = bfd_get_section_by_name (info->output_bfd, ".sframe");
    163  1.1  christos 
    164  1.1  christos   if (sframe == NULL)
    165  1.1  christos     return false;
    166  1.1  christos 
    167  1.1  christos   /* Count only sections which have at least a single FDE.  */
    168  1.1  christos   for (sframe = sframe->map_head.s; sframe != NULL; sframe = sframe->map_head.s)
    169  1.1  christos     /* Note that this may become an approximate check in the future when
    170  1.1  christos        some ABI/arch begin to use the sfh_auxhdr_len.  When sfh_auxhdr_len has
    171  1.1  christos        non-zero value, it will need to be accounted for in the calculation of
    172  1.1  christos        the SFrame header size.  */
    173  1.1  christos     if (sframe->size > sizeof (sframe_header))
    174  1.1  christos       return true;
    175  1.1  christos   return false;
    176  1.1  christos }
    177  1.1  christos 
    178  1.1  christos /* Try to parse .sframe section SEC, which belongs to ABFD.  Store the
    179  1.1  christos    information in the section's sec_info field on success.  COOKIE
    180  1.1  christos    describes the relocations in SEC.
    181  1.1  christos 
    182  1.1  christos    Returns TRUE if success, FALSE if any error or failure.  */
    183  1.1  christos 
    184  1.1  christos bool
    185  1.1  christos _bfd_elf_parse_sframe (bfd *abfd,
    186  1.1  christos 		       struct bfd_link_info *info ATTRIBUTE_UNUSED,
    187  1.1  christos 		       asection *sec, struct elf_reloc_cookie *cookie)
    188  1.1  christos {
    189  1.1  christos   bfd_byte *sfbuf = NULL;
    190  1.1  christos   struct sframe_dec_info *sfd_info;
    191  1.1  christos   sframe_decoder_ctx *sfd_ctx;
    192  1.1  christos   bfd_size_type sf_size;
    193  1.1  christos   int decerr = 0;
    194  1.1  christos 
    195  1.1  christos   if (sec->size == 0
    196  1.1  christos       || sec->sec_info_type != SEC_INFO_TYPE_NONE)
    197  1.1  christos     {
    198  1.1  christos       /* This file does not contain .sframe information.  */
    199  1.1  christos       return false;
    200  1.1  christos     }
    201  1.1  christos 
    202  1.1  christos   if (bfd_is_abs_section (sec->output_section))
    203  1.1  christos     {
    204  1.1  christos       /* At least one of the sections is being discarded from the
    205  1.1  christos 	 link, so we should just ignore them.  */
    206  1.1  christos       return false;
    207  1.1  christos     }
    208  1.1  christos 
    209  1.1  christos   /* Read the SFrame unwind information from abfd.  */
    210  1.1  christos   if (!bfd_malloc_and_get_section (abfd, sec, &sfbuf))
    211  1.1  christos     goto fail_no_free;
    212  1.1  christos 
    213  1.1  christos   /* Decode the buffer and keep decoded contents for later use.
    214  1.1  christos      Relocations are performed later, but are such that the section's
    215  1.1  christos      size is unaffected.  */
    216  1.1  christos   sfd_info = bfd_malloc (sizeof (struct sframe_dec_info));
    217  1.1  christos   sf_size = sec->size;
    218  1.1  christos 
    219  1.1  christos   sfd_info->sfd_ctx = sframe_decode ((const char*)sfbuf, sf_size, &decerr);
    220  1.1  christos   sfd_ctx = sfd_info->sfd_ctx;
    221  1.1  christos   if (!sfd_ctx)
    222  1.1  christos     /* Free'ing up any memory held by decoder context is done by
    223  1.1  christos        sframe_decode in case of error.  */
    224  1.1  christos     goto fail_no_free;
    225  1.1  christos 
    226  1.1  christos   if (!sframe_decoder_init_func_bfdinfo (sec, sfd_info, cookie))
    227  1.1  christos     {
    228  1.1  christos       sframe_decoder_free (&sfd_ctx);
    229  1.1  christos       goto fail_no_free;
    230  1.1  christos     }
    231  1.1  christos 
    232  1.1  christos   elf_section_data (sec)->sec_info = sfd_info;
    233  1.1  christos   sec->sec_info_type = SEC_INFO_TYPE_SFRAME;
    234  1.1  christos 
    235  1.1  christos   goto success;
    236  1.1  christos 
    237  1.1  christos fail_no_free:
    238  1.1  christos   _bfd_error_handler
    239  1.1  christos    (_("error in %pB(%pA); no .sframe will be created"),
    240  1.1  christos     abfd, sec);
    241  1.1  christos   return false;
    242  1.1  christos success:
    243  1.1  christos   free (sfbuf);
    244  1.1  christos   return true;
    245  1.1  christos }
    246  1.1  christos 
    247  1.1  christos /* This function is called for each input file before the .sframe section
    248  1.1  christos    is relocated.  It marks the SFrame FDE for the discarded functions for
    249  1.1  christos    deletion.
    250  1.1  christos 
    251  1.1  christos    The function returns TRUE iff any entries have been deleted.  */
    252  1.1  christos 
    253  1.1  christos bool
    254  1.1  christos _bfd_elf_discard_section_sframe
    255  1.1  christos    (asection *sec,
    256  1.1  christos     bool (*reloc_symbol_deleted_p) (bfd_vma, void *),
    257  1.1  christos     struct elf_reloc_cookie *cookie)
    258  1.1  christos {
    259  1.1  christos   bool changed;
    260  1.1  christos   bool keep;
    261  1.1  christos   unsigned int i;
    262  1.1  christos   unsigned int func_desc_offset;
    263  1.1  christos   unsigned int num_fidx;
    264  1.1  christos   struct sframe_dec_info *sfd_info;
    265  1.1  christos 
    266  1.1  christos   changed = false;
    267  1.1  christos   /* FIXME - if relocatable link and changed = true, how does the final
    268  1.1  christos      .rela.sframe get updated ?.  */
    269  1.1  christos   keep = false;
    270  1.1  christos 
    271  1.1  christos   sfd_info = (struct sframe_dec_info *) elf_section_data (sec)->sec_info;
    272  1.1  christos 
    273  1.1  christos   /* Skip checking for the linker created .sframe sections
    274  1.1  christos      (for PLT sections).  */
    275  1.1  christos   if ((sec->flags & SEC_LINKER_CREATED) == 0 || cookie->rels != NULL)
    276  1.1  christos     {
    277  1.1  christos       num_fidx = sframe_decoder_get_num_fidx (sfd_info->sfd_ctx);
    278  1.1  christos       for (i = 0; i < num_fidx; i++)
    279  1.1  christos 	{
    280  1.1  christos 	  func_desc_offset = sframe_decoder_get_func_r_offset (sfd_info, i);
    281  1.1  christos 
    282  1.1  christos 	  cookie->rel = cookie->rels
    283  1.1  christos 	    + sframe_decoder_get_func_reloc_index (sfd_info, i);
    284  1.1  christos 	  keep = !(*reloc_symbol_deleted_p) (func_desc_offset, cookie);
    285  1.1  christos 
    286  1.1  christos 	  if (!keep)
    287  1.1  christos 	    {
    288  1.1  christos 	      sframe_decoder_mark_func_deleted (sfd_info, i);
    289  1.1  christos 	      changed = true;
    290  1.1  christos 	    }
    291  1.1  christos 	}
    292  1.1  christos     }
    293  1.1  christos   return changed;
    294  1.1  christos }
    295  1.1  christos 
    296  1.1  christos /* Update the reference to the output .sframe section in the output ELF
    297  1.1  christos    BFD ABFD.  Returns true if no error.  */
    298  1.1  christos 
    299  1.1  christos bool
    300  1.1  christos _bfd_elf_set_section_sframe (bfd *abfd,
    301  1.1  christos 				struct bfd_link_info *info)
    302  1.1  christos {
    303  1.1  christos   asection *cfsec;
    304  1.1  christos 
    305  1.1  christos   cfsec = bfd_get_section_by_name (info->output_bfd, ".sframe");
    306  1.1  christos   if (!cfsec)
    307  1.1  christos     return false;
    308  1.1  christos 
    309  1.1  christos   elf_sframe (abfd) = cfsec;
    310  1.1  christos 
    311  1.1  christos   return true;
    312  1.1  christos }
    313  1.1  christos 
    314  1.1  christos /* Merge .sframe section SEC.  This is called with the relocated
    315  1.1  christos    CONTENTS.  */
    316  1.1  christos 
    317  1.1  christos bool
    318  1.1  christos _bfd_elf_merge_section_sframe (bfd *abfd,
    319  1.1  christos 			       struct bfd_link_info *info,
    320  1.1  christos 			       asection *sec,
    321  1.1  christos 			       bfd_byte *contents)
    322  1.1  christos {
    323  1.1  christos   struct sframe_dec_info *sfd_info;
    324  1.1  christos   struct sframe_enc_info *sfe_info;
    325  1.1  christos   sframe_decoder_ctx *sfd_ctx;
    326  1.1  christos   sframe_encoder_ctx *sfe_ctx;
    327  1.1  christos   unsigned char sfd_ctx_abi_arch;
    328  1.1  christos   int8_t sfd_ctx_fixed_fp_offset;
    329  1.1  christos   int8_t sfd_ctx_fixed_ra_offset;
    330  1.1  christos   int encerr = 0;
    331  1.1  christos 
    332  1.1  christos   struct elf_link_hash_table *htab;
    333  1.1  christos   asection *cfsec;
    334  1.1  christos 
    335  1.1  christos   /* Sanity check - handle SFrame sections only.  */
    336  1.1  christos   if (sec->sec_info_type != SEC_INFO_TYPE_SFRAME)
    337  1.1  christos     return false;
    338  1.1  christos 
    339  1.1  christos   sfd_info = (struct sframe_dec_info *) elf_section_data (sec)->sec_info;
    340  1.1  christos   sfd_ctx = sfd_info->sfd_ctx;
    341  1.1  christos 
    342  1.1  christos   htab = elf_hash_table (info);
    343  1.1  christos   sfe_info = &(htab->sfe_info);
    344  1.1  christos   sfe_ctx = sfe_info->sfe_ctx;
    345  1.1  christos 
    346  1.1  christos   /* All input bfds are expected to have a valid SFrame section.  Even if
    347  1.1  christos      the SFrame section is empty with only a header, there must be a valid
    348  1.1  christos      SFrame decoder context by now.  The SFrame encoder context, however,
    349  1.1  christos      will get set later here, if this is the first call to the function.  */
    350  1.1  christos   if (sfd_ctx == NULL || sfe_info == NULL)
    351  1.1  christos     return false;
    352  1.1  christos 
    353  1.1  christos   if (htab->sfe_info.sfe_ctx == NULL)
    354  1.1  christos     {
    355  1.1  christos       sfd_ctx_abi_arch = sframe_decoder_get_abi_arch (sfd_ctx);
    356  1.1  christos       sfd_ctx_fixed_fp_offset = sframe_decoder_get_fixed_fp_offset (sfd_ctx);
    357  1.1  christos       sfd_ctx_fixed_ra_offset = sframe_decoder_get_fixed_ra_offset (sfd_ctx);
    358  1.1  christos 
    359  1.1  christos       /* Valid values are non-zero.  */
    360  1.1  christos       if (!sfd_ctx_abi_arch)
    361  1.1  christos 	return false;
    362  1.1  christos 
    363  1.1  christos       htab->sfe_info.sfe_ctx = sframe_encode (SFRAME_VERSION_1,
    364  1.1  christos 					      0, /* SFrame flags.  */
    365  1.1  christos 					      sfd_ctx_abi_arch,
    366  1.1  christos 					      sfd_ctx_fixed_fp_offset,
    367  1.1  christos 					      sfd_ctx_fixed_ra_offset,
    368  1.1  christos 					      &encerr);
    369  1.1  christos       /* Handle errors from sframe_encode.  */
    370  1.1  christos       if (htab->sfe_info.sfe_ctx == NULL)
    371  1.1  christos 	return false;
    372  1.1  christos     }
    373  1.1  christos   sfe_ctx = sfe_info->sfe_ctx;
    374  1.1  christos 
    375  1.1  christos   if (sfe_info->sframe_section == NULL)
    376  1.1  christos     {
    377  1.1  christos       /* Make sure things are set for an eventual write.
    378  1.1  christos 	 Size of the output section is not known until
    379  1.1  christos 	 _bfd_elf_write_section_sframe is ready with the buffer
    380  1.1  christos 	 to write out.  */
    381  1.1  christos       cfsec = bfd_get_section_by_name (info->output_bfd, ".sframe");
    382  1.1  christos       if (cfsec)
    383  1.1  christos 	{
    384  1.1  christos 	  sfe_info->sframe_section = cfsec;
    385  1.1  christos 	  // elf_sframe (abfd) = cfsec;
    386  1.1  christos 	}
    387  1.1  christos       else
    388  1.1  christos 	return false;
    389  1.1  christos     }
    390  1.1  christos 
    391  1.1  christos   /* Check that all .sframe sections being linked have the same
    392  1.1  christos      ABI/arch.  */
    393  1.1  christos   if (sframe_decoder_get_abi_arch (sfd_ctx)
    394  1.1  christos       != sframe_encoder_get_abi_arch (sfe_ctx))
    395  1.1  christos     {
    396  1.1  christos       _bfd_error_handler
    397  1.1  christos 	(_("input SFrame sections with different abi prevent .sframe"
    398  1.1  christos 	  " generation"));
    399  1.1  christos       return false;
    400  1.1  christos     }
    401  1.1  christos 
    402  1.1  christos   /* Iterate over the function descriptor entries and the FREs of the
    403  1.1  christos      function from the decoder context.  Add each of them to the encoder
    404  1.1  christos      context, if suitable.  */
    405  1.1  christos   unsigned int i = 0, j = 0, cur_fidx = 0;
    406  1.1  christos 
    407  1.1  christos   unsigned int num_fidx = sframe_decoder_get_num_fidx (sfd_ctx);
    408  1.1  christos   unsigned int num_enc_fidx = sframe_encoder_get_num_fidx (sfe_ctx);
    409  1.1  christos 
    410  1.1  christos   for (i = 0; i < num_fidx; i++)
    411  1.1  christos     {
    412  1.1  christos       unsigned int num_fres = 0;
    413  1.1  christos       int32_t func_start_address;
    414  1.1  christos       bfd_vma address;
    415  1.1  christos       uint32_t func_size = 0;
    416  1.1  christos       unsigned char func_info = 0;
    417  1.1  christos       unsigned int r_offset = 0;
    418  1.1  christos       bool pltn_reloc_by_hand = false;
    419  1.1  christos       unsigned int pltn_r_offset = 0;
    420  1.1  christos 
    421  1.1  christos       if (!sframe_decoder_get_funcdesc (sfd_ctx, i, &num_fres, &func_size,
    422  1.1  christos 					&func_start_address, &func_info))
    423  1.1  christos 	{
    424  1.1  christos 	  /* If function belongs to a deleted section, skip editing the
    425  1.1  christos 	     function descriptor entry.  */
    426  1.1  christos 	  if (sframe_decoder_func_deleted_p(sfd_info, i))
    427  1.1  christos 	    continue;
    428  1.1  christos 
    429  1.1  christos 	  /* Don't edit function descriptor entries for relocatable link.  */
    430  1.1  christos 	  if (!bfd_link_relocatable (info))
    431  1.1  christos 	    {
    432  1.1  christos 	      if (!(sec->flags & SEC_LINKER_CREATED))
    433  1.1  christos 		{
    434  1.1  christos 		  /* Get relocated contents by reading the value of the
    435  1.1  christos 		     relocated function start address at the beginning of the
    436  1.1  christos 		     function descriptor entry.  */
    437  1.1  christos 		  r_offset = sframe_decoder_get_func_r_offset (sfd_info, i);
    438  1.1  christos 		}
    439  1.1  christos 	      else
    440  1.1  christos 		{
    441  1.1  christos 		  /* Expected to land here for SFrame unwind info as created
    442  1.1  christos 		     for the .plt* sections.  These sections can have upto two
    443  1.1  christos 		     FDE entries.  Although the code should work for > 2,
    444  1.1  christos 		     leaving this assert here for safety.  */
    445  1.1  christos 		  BFD_ASSERT (num_fidx <= 2);
    446  1.1  christos 		  /* For the first entry, we know the offset of the SFrame FDE's
    447  1.1  christos 		     sfde_func_start_address.  Side note: see how the value
    448  1.1  christos 		     of PLT_SFRAME_FDE_START_OFFSET is also set to the
    449  1.1  christos 		     same.  */
    450  1.1  christos 		  r_offset = sframe_decoder_get_hdr_size (sfd_ctx);
    451  1.1  christos 		  /* For any further SFrame FDEs, the generator has already put
    452  1.1  christos 		     in an offset in place of sfde_func_start_address of the
    453  1.1  christos 		     corresponding FDE.  We will use it by hand to relocate.  */
    454  1.1  christos 		  if (i > 0)
    455  1.1  christos 		    {
    456  1.1  christos 		      pltn_r_offset
    457  1.1  christos 			= r_offset + (i * sizeof (sframe_func_desc_entry));
    458  1.1  christos 		      pltn_reloc_by_hand = true;
    459  1.1  christos 		    }
    460  1.1  christos 		}
    461  1.1  christos 
    462  1.1  christos 	      /* Get the SFrame FDE function start address after relocation.  */
    463  1.1  christos 	      address = sframe_read_value (abfd, contents, r_offset, 4);
    464  1.1  christos 	      if (pltn_reloc_by_hand)
    465  1.1  christos 		address += sframe_read_value (abfd, contents,
    466  1.1  christos 					      pltn_r_offset, 4);
    467  1.1  christos 	      address += (sec->output_offset + r_offset);
    468  1.1  christos 
    469  1.1  christos 	      /* FIXME For testing only. Cleanup later.  */
    470  1.1  christos 	      // address += (sec->output_section->vma);
    471  1.1  christos 
    472  1.1  christos 	      func_start_address = address;
    473  1.1  christos 	    }
    474  1.1  christos 
    475  1.1  christos 	  /* Update the encoder context with updated content.  */
    476  1.1  christos 	  int err = sframe_encoder_add_funcdesc (sfe_ctx, func_start_address,
    477  1.1  christos 						 func_size, func_info,
    478  1.1  christos 						 num_fres);
    479  1.1  christos 	  cur_fidx++;
    480  1.1  christos 	  BFD_ASSERT (!err);
    481  1.1  christos 	}
    482  1.1  christos 
    483  1.1  christos       for (j = 0; j < num_fres; j++)
    484  1.1  christos 	{
    485  1.1  christos 	  sframe_frame_row_entry fre;
    486  1.1  christos 	  if (!sframe_decoder_get_fre (sfd_ctx, i, j, &fre))
    487  1.1  christos 	    {
    488  1.1  christos 	      int err = sframe_encoder_add_fre (sfe_ctx,
    489  1.1  christos 						cur_fidx-1+num_enc_fidx,
    490  1.1  christos 						&fre);
    491  1.1  christos 	      BFD_ASSERT (!err);
    492  1.1  christos 	    }
    493  1.1  christos 	}
    494  1.1  christos     }
    495  1.1  christos   /* Free the SFrame decoder context.  */
    496  1.1  christos   sframe_decoder_free (&sfd_ctx);
    497  1.1  christos 
    498  1.1  christos   return true;
    499  1.1  christos }
    500  1.1  christos 
    501  1.1  christos /* Write out the .sframe section.  This must be called after
    502  1.1  christos    _bfd_elf_merge_section_sframe has been called on all input
    503  1.1  christos    .sframe sections.  */
    504  1.1  christos 
    505  1.1  christos bool
    506  1.1  christos _bfd_elf_write_section_sframe (bfd *abfd, struct bfd_link_info *info)
    507  1.1  christos {
    508  1.1  christos   bool retval = true;
    509  1.1  christos 
    510  1.1  christos   struct elf_link_hash_table *htab;
    511  1.1  christos   struct sframe_enc_info *sfe_info;
    512  1.1  christos   sframe_encoder_ctx *sfe_ctx;
    513  1.1  christos   asection *sec;
    514  1.1  christos   void *contents;
    515  1.1  christos   size_t sec_size;
    516  1.1  christos   int err = 0;
    517  1.1  christos 
    518  1.1  christos   htab = elf_hash_table (info);
    519  1.1  christos   sfe_info = &htab->sfe_info;
    520  1.1  christos   sec = sfe_info->sframe_section;
    521  1.1  christos   sfe_ctx = sfe_info->sfe_ctx;
    522  1.1  christos 
    523  1.1  christos   if (sec == NULL)
    524  1.1  christos     return true;
    525  1.1  christos 
    526  1.1  christos   contents = sframe_encoder_write (sfe_ctx, &sec_size, &err);
    527  1.1  christos   sec->size = (bfd_size_type) sec_size;
    528  1.1  christos 
    529  1.1  christos   if (!bfd_set_section_contents (abfd, sec->output_section, contents,
    530  1.1  christos 				 (file_ptr) sec->output_offset,
    531  1.1  christos 				 sec->size))
    532  1.1  christos     retval = false;
    533  1.1  christos   else if (!bfd_link_relocatable (info))
    534  1.1  christos     {
    535  1.1  christos       Elf_Internal_Shdr *hdr = &elf_section_data (sec)->this_hdr;
    536  1.1  christos       hdr->sh_size = sec->size;
    537  1.1  christos     }
    538  1.1  christos   /* For relocatable links, do not update the section size as the section
    539  1.1  christos      contents have not been relocated.  */
    540  1.1  christos 
    541  1.1  christos   sframe_encoder_free (&sfe_ctx);
    542  1.1  christos 
    543  1.1  christos   return retval;
    544  1.1  christos }
    545