1/* .sframe section processing.
2   Copyright (C) 2022 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
30static bool
31sframe_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
42static void
43sframe_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
52static unsigned int
53sframe_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
66static void
67sframe_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
77static unsigned int
78sframe_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
87static void
88sframe_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
99static bool
100sframe_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
141static bfd_vma
142sframe_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
159bool
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
184bool
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->sec_info_type != SEC_INFO_TYPE_NONE)
197    {
198      /* This file does not contain .sframe information.  */
199      return false;
200    }
201
202  if (bfd_is_abs_section (sec->output_section))
203    {
204      /* At least one of the sections is being discarded from the
205	 link, so we should just ignore them.  */
206      return false;
207    }
208
209  /* Read the SFrame unwind information from abfd.  */
210  if (!bfd_malloc_and_get_section (abfd, sec, &sfbuf))
211    goto fail_no_free;
212
213  /* Decode the buffer and keep decoded contents for later use.
214     Relocations are performed later, but are such that the section's
215     size is unaffected.  */
216  sfd_info = bfd_malloc (sizeof (struct sframe_dec_info));
217  sf_size = sec->size;
218
219  sfd_info->sfd_ctx = sframe_decode ((const char*)sfbuf, sf_size, &decerr);
220  sfd_ctx = sfd_info->sfd_ctx;
221  if (!sfd_ctx)
222    /* Free'ing up any memory held by decoder context is done by
223       sframe_decode in case of error.  */
224    goto fail_no_free;
225
226  if (!sframe_decoder_init_func_bfdinfo (sec, sfd_info, cookie))
227    {
228      sframe_decoder_free (&sfd_ctx);
229      goto fail_no_free;
230    }
231
232  elf_section_data (sec)->sec_info = sfd_info;
233  sec->sec_info_type = SEC_INFO_TYPE_SFRAME;
234
235  goto success;
236
237fail_no_free:
238  _bfd_error_handler
239   (_("error in %pB(%pA); no .sframe will be created"),
240    abfd, sec);
241  return false;
242success:
243  free (sfbuf);
244  return true;
245}
246
247/* This function is called for each input file before the .sframe section
248   is relocated.  It marks the SFrame FDE for the discarded functions for
249   deletion.
250
251   The function returns TRUE iff any entries have been deleted.  */
252
253bool
254_bfd_elf_discard_section_sframe
255   (asection *sec,
256    bool (*reloc_symbol_deleted_p) (bfd_vma, void *),
257    struct elf_reloc_cookie *cookie)
258{
259  bool changed;
260  bool keep;
261  unsigned int i;
262  unsigned int func_desc_offset;
263  unsigned int num_fidx;
264  struct sframe_dec_info *sfd_info;
265
266  changed = false;
267  /* FIXME - if relocatable link and changed = true, how does the final
268     .rela.sframe get updated ?.  */
269  keep = false;
270
271  sfd_info = (struct sframe_dec_info *) elf_section_data (sec)->sec_info;
272
273  /* Skip checking for the linker created .sframe sections
274     (for PLT sections).  */
275  if ((sec->flags & SEC_LINKER_CREATED) == 0 || cookie->rels != NULL)
276    {
277      num_fidx = sframe_decoder_get_num_fidx (sfd_info->sfd_ctx);
278      for (i = 0; i < num_fidx; i++)
279	{
280	  func_desc_offset = sframe_decoder_get_func_r_offset (sfd_info, i);
281
282	  cookie->rel = cookie->rels
283	    + sframe_decoder_get_func_reloc_index (sfd_info, i);
284	  keep = !(*reloc_symbol_deleted_p) (func_desc_offset, cookie);
285
286	  if (!keep)
287	    {
288	      sframe_decoder_mark_func_deleted (sfd_info, i);
289	      changed = true;
290	    }
291	}
292    }
293  return changed;
294}
295
296/* Update the reference to the output .sframe section in the output ELF
297   BFD ABFD.  Returns true if no error.  */
298
299bool
300_bfd_elf_set_section_sframe (bfd *abfd,
301				struct bfd_link_info *info)
302{
303  asection *cfsec;
304
305  cfsec = bfd_get_section_by_name (info->output_bfd, ".sframe");
306  if (!cfsec)
307    return false;
308
309  elf_sframe (abfd) = cfsec;
310
311  return true;
312}
313
314/* Merge .sframe section SEC.  This is called with the relocated
315   CONTENTS.  */
316
317bool
318_bfd_elf_merge_section_sframe (bfd *abfd,
319			       struct bfd_link_info *info,
320			       asection *sec,
321			       bfd_byte *contents)
322{
323  struct sframe_dec_info *sfd_info;
324  struct sframe_enc_info *sfe_info;
325  sframe_decoder_ctx *sfd_ctx;
326  sframe_encoder_ctx *sfe_ctx;
327  unsigned char sfd_ctx_abi_arch;
328  int8_t sfd_ctx_fixed_fp_offset;
329  int8_t sfd_ctx_fixed_ra_offset;
330  int encerr = 0;
331
332  struct elf_link_hash_table *htab;
333  asection *cfsec;
334
335  /* Sanity check - handle SFrame sections only.  */
336  if (sec->sec_info_type != SEC_INFO_TYPE_SFRAME)
337    return false;
338
339  sfd_info = (struct sframe_dec_info *) elf_section_data (sec)->sec_info;
340  sfd_ctx = sfd_info->sfd_ctx;
341
342  htab = elf_hash_table (info);
343  sfe_info = &(htab->sfe_info);
344  sfe_ctx = sfe_info->sfe_ctx;
345
346  /* All input bfds are expected to have a valid SFrame section.  Even if
347     the SFrame section is empty with only a header, there must be a valid
348     SFrame decoder context by now.  The SFrame encoder context, however,
349     will get set later here, if this is the first call to the function.  */
350  if (sfd_ctx == NULL || sfe_info == NULL)
351    return false;
352
353  if (htab->sfe_info.sfe_ctx == NULL)
354    {
355      sfd_ctx_abi_arch = sframe_decoder_get_abi_arch (sfd_ctx);
356      sfd_ctx_fixed_fp_offset = sframe_decoder_get_fixed_fp_offset (sfd_ctx);
357      sfd_ctx_fixed_ra_offset = sframe_decoder_get_fixed_ra_offset (sfd_ctx);
358
359      /* Valid values are non-zero.  */
360      if (!sfd_ctx_abi_arch)
361	return false;
362
363      htab->sfe_info.sfe_ctx = sframe_encode (SFRAME_VERSION_1,
364					      0, /* SFrame flags.  */
365					      sfd_ctx_abi_arch,
366					      sfd_ctx_fixed_fp_offset,
367					      sfd_ctx_fixed_ra_offset,
368					      &encerr);
369      /* Handle errors from sframe_encode.  */
370      if (htab->sfe_info.sfe_ctx == NULL)
371	return false;
372    }
373  sfe_ctx = sfe_info->sfe_ctx;
374
375  if (sfe_info->sframe_section == NULL)
376    {
377      /* Make sure things are set for an eventual write.
378	 Size of the output section is not known until
379	 _bfd_elf_write_section_sframe is ready with the buffer
380	 to write out.  */
381      cfsec = bfd_get_section_by_name (info->output_bfd, ".sframe");
382      if (cfsec)
383	{
384	  sfe_info->sframe_section = cfsec;
385	  // elf_sframe (abfd) = cfsec;
386	}
387      else
388	return false;
389    }
390
391  /* Check that all .sframe sections being linked have the same
392     ABI/arch.  */
393  if (sframe_decoder_get_abi_arch (sfd_ctx)
394      != sframe_encoder_get_abi_arch (sfe_ctx))
395    {
396      _bfd_error_handler
397	(_("input SFrame sections with different abi prevent .sframe"
398	  " generation"));
399      return false;
400    }
401
402  /* Iterate over the function descriptor entries and the FREs of the
403     function from the decoder context.  Add each of them to the encoder
404     context, if suitable.  */
405  unsigned int i = 0, j = 0, cur_fidx = 0;
406
407  unsigned int num_fidx = sframe_decoder_get_num_fidx (sfd_ctx);
408  unsigned int num_enc_fidx = sframe_encoder_get_num_fidx (sfe_ctx);
409
410  for (i = 0; i < num_fidx; i++)
411    {
412      unsigned int num_fres = 0;
413      int32_t func_start_address;
414      bfd_vma address;
415      uint32_t func_size = 0;
416      unsigned char func_info = 0;
417      unsigned int r_offset = 0;
418      bool pltn_reloc_by_hand = false;
419      unsigned int pltn_r_offset = 0;
420
421      if (!sframe_decoder_get_funcdesc (sfd_ctx, i, &num_fres, &func_size,
422					&func_start_address, &func_info))
423	{
424	  /* If function belongs to a deleted section, skip editing the
425	     function descriptor entry.  */
426	  if (sframe_decoder_func_deleted_p(sfd_info, i))
427	    continue;
428
429	  /* Don't edit function descriptor entries for relocatable link.  */
430	  if (!bfd_link_relocatable (info))
431	    {
432	      if (!(sec->flags & SEC_LINKER_CREATED))
433		{
434		  /* Get relocated contents by reading the value of the
435		     relocated function start address at the beginning of the
436		     function descriptor entry.  */
437		  r_offset = sframe_decoder_get_func_r_offset (sfd_info, i);
438		}
439	      else
440		{
441		  /* Expected to land here for SFrame unwind info as created
442		     for the .plt* sections.  These sections can have upto two
443		     FDE entries.  Although the code should work for > 2,
444		     leaving this assert here for safety.  */
445		  BFD_ASSERT (num_fidx <= 2);
446		  /* For the first entry, we know the offset of the SFrame FDE's
447		     sfde_func_start_address.  Side note: see how the value
448		     of PLT_SFRAME_FDE_START_OFFSET is also set to the
449		     same.  */
450		  r_offset = sframe_decoder_get_hdr_size (sfd_ctx);
451		  /* For any further SFrame FDEs, the generator has already put
452		     in an offset in place of sfde_func_start_address of the
453		     corresponding FDE.  We will use it by hand to relocate.  */
454		  if (i > 0)
455		    {
456		      pltn_r_offset
457			= r_offset + (i * sizeof (sframe_func_desc_entry));
458		      pltn_reloc_by_hand = true;
459		    }
460		}
461
462	      /* Get the SFrame FDE function start address after relocation.  */
463	      address = sframe_read_value (abfd, contents, r_offset, 4);
464	      if (pltn_reloc_by_hand)
465		address += sframe_read_value (abfd, contents,
466					      pltn_r_offset, 4);
467	      address += (sec->output_offset + r_offset);
468
469	      /* FIXME For testing only. Cleanup later.  */
470	      // address += (sec->output_section->vma);
471
472	      func_start_address = address;
473	    }
474
475	  /* Update the encoder context with updated content.  */
476	  int err = sframe_encoder_add_funcdesc (sfe_ctx, func_start_address,
477						 func_size, func_info,
478						 num_fres);
479	  cur_fidx++;
480	  BFD_ASSERT (!err);
481	}
482
483      for (j = 0; j < num_fres; j++)
484	{
485	  sframe_frame_row_entry fre;
486	  if (!sframe_decoder_get_fre (sfd_ctx, i, j, &fre))
487	    {
488	      int err = sframe_encoder_add_fre (sfe_ctx,
489						cur_fidx-1+num_enc_fidx,
490						&fre);
491	      BFD_ASSERT (!err);
492	    }
493	}
494    }
495  /* Free the SFrame decoder context.  */
496  sframe_decoder_free (&sfd_ctx);
497
498  return true;
499}
500
501/* Write out the .sframe section.  This must be called after
502   _bfd_elf_merge_section_sframe has been called on all input
503   .sframe sections.  */
504
505bool
506_bfd_elf_write_section_sframe (bfd *abfd, struct bfd_link_info *info)
507{
508  bool retval = true;
509
510  struct elf_link_hash_table *htab;
511  struct sframe_enc_info *sfe_info;
512  sframe_encoder_ctx *sfe_ctx;
513  asection *sec;
514  void *contents;
515  size_t sec_size;
516  int err = 0;
517
518  htab = elf_hash_table (info);
519  sfe_info = &htab->sfe_info;
520  sec = sfe_info->sframe_section;
521  sfe_ctx = sfe_info->sfe_ctx;
522
523  if (sec == NULL)
524    return true;
525
526  contents = sframe_encoder_write (sfe_ctx, &sec_size, &err);
527  sec->size = (bfd_size_type) sec_size;
528
529  if (!bfd_set_section_contents (abfd, sec->output_section, contents,
530				 (file_ptr) sec->output_offset,
531				 sec->size))
532    retval = false;
533  else if (!bfd_link_relocatable (info))
534    {
535      Elf_Internal_Shdr *hdr = &elf_section_data (sec)->this_hdr;
536      hdr->sh_size = sec->size;
537    }
538  /* For relocatable links, do not update the section size as the section
539     contents have not been relocated.  */
540
541  sframe_encoder_free (&sfe_ctx);
542
543  return retval;
544}
545