(root)/
binutils-2.41/
bfd/
elf-sframe.c
       1  /* .sframe section processing.
       2     Copyright (C) 2022-2023 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  }