xref: /netbsd-src/external/gpl3/binutils/dist/bfd/elf-sframe.c (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
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
sframe_decoder_func_deleted_p(struct sframe_dec_info * sfd_info,unsigned int func_idx)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
sframe_decoder_mark_func_deleted(struct sframe_dec_info * sfd_info,unsigned int func_idx)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
sframe_decoder_get_func_r_offset(struct sframe_dec_info * sfd_info,unsigned int func_idx)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
sframe_decoder_set_func_r_offset(struct sframe_dec_info * sfd_info,unsigned int func_idx,unsigned int r_offset)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
sframe_decoder_get_func_reloc_index(struct sframe_dec_info * sfd_info,unsigned int func_idx)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
sframe_decoder_set_func_reloc_index(struct sframe_dec_info * sfd_info,unsigned int func_idx,unsigned int reloc_index)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
sframe_decoder_init_func_bfdinfo(asection * sec,struct sframe_dec_info * sfd_info,struct elf_reloc_cookie * cookie)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
sframe_read_value(bfd * abfd,bfd_byte * contents,unsigned int offset,unsigned int width)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
_bfd_elf_sframe_present(struct bfd_link_info * info)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
_bfd_elf_parse_sframe(bfd * abfd,struct bfd_link_info * info ATTRIBUTE_UNUSED,asection * sec,struct elf_reloc_cookie * cookie)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
_bfd_elf_discard_section_sframe(asection * sec,bool (* reloc_symbol_deleted_p)(bfd_vma,void *),struct elf_reloc_cookie * cookie)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
_bfd_elf_set_section_sframe(bfd * abfd,struct bfd_link_info * info)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
_bfd_elf_merge_section_sframe(bfd * abfd,struct bfd_link_info * info,asection * sec,bfd_byte * contents)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
_bfd_elf_write_section_sframe(bfd * abfd,struct bfd_link_info * info)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