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