xref: /netbsd-src/external/gpl3/gdb/dist/bfd/elf-sframe.c (revision 70f7362772ba52b749c976fb5e86e39a8b2c9afc)
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 
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->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 
237 fail_no_free:
238   _bfd_error_handler
239    (_("error in %pB(%pA); no .sframe will be created"),
240     abfd, sec);
241   return false;
242 success:
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 
253 bool
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 
299 bool
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 
317 bool
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 
505 bool
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