]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/elf-sframe.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / bfd / elf-sframe.c
CommitLineData
cf0e0a0b 1/* .sframe section processing.
d87bef3a 2 Copyright (C) 2022-2023 Free Software Foundation, Inc.
cf0e0a0b
IB
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}