]> Git Repo - binutils.git/blob - bfd/elf-sframe.c
Automatic date update in version.in
[binutils.git] / bfd / elf-sframe.c
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 }
This page took 0.053908 seconds and 4 git commands to generate.