elf-sframe.c revision 1.1.1.2 1 /* .sframe section processing.
2 Copyright (C) 2022-2025 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 #include "sframe-internal.h"
27
28 /* Return TRUE if the function has been marked for deletion during the linking
29 process. */
30
31 static bool
32 sframe_decoder_func_deleted_p (struct sframe_dec_info *sfd_info,
33 unsigned int func_idx)
34 {
35 if (func_idx < sfd_info->sfd_fde_count)
36 return sfd_info->sfd_func_bfdinfo[func_idx].func_deleted_p;
37
38 return false;
39 }
40
41 /* Mark the function in the decoder info for deletion. */
42
43 static void
44 sframe_decoder_mark_func_deleted (struct sframe_dec_info *sfd_info,
45 unsigned int func_idx)
46 {
47 if (func_idx < sfd_info->sfd_fde_count)
48 sfd_info->sfd_func_bfdinfo[func_idx].func_deleted_p = true;
49 }
50
51 /* Get the relocation offset from the decoder info for the given function. */
52
53 static unsigned int
54 sframe_decoder_get_func_r_offset (struct sframe_dec_info *sfd_info,
55 unsigned int func_idx)
56 {
57 BFD_ASSERT (func_idx < sfd_info->sfd_fde_count);
58 unsigned int func_r_offset
59 = sfd_info->sfd_func_bfdinfo[func_idx].func_r_offset;
60 /* There must have been a reloc. */
61 BFD_ASSERT (func_r_offset);
62 return func_r_offset;
63 }
64
65 /* Bookkeep the function relocation offset in the decoder info. */
66
67 static void
68 sframe_decoder_set_func_r_offset (struct sframe_dec_info *sfd_info,
69 unsigned int func_idx,
70 unsigned int r_offset)
71 {
72 if (func_idx < sfd_info->sfd_fde_count)
73 sfd_info->sfd_func_bfdinfo[func_idx].func_r_offset = r_offset;
74 }
75
76 /* Get the relocation index in the elf_reloc_cookie for the function. */
77
78 static unsigned int
79 sframe_decoder_get_func_reloc_index (struct sframe_dec_info *sfd_info,
80 unsigned int func_idx)
81 {
82 BFD_ASSERT (func_idx < sfd_info->sfd_fde_count);
83 return sfd_info->sfd_func_bfdinfo[func_idx].func_reloc_index;
84 }
85
86 /* Bookkeep the relocation index in the elf_reloc_cookie for the function. */
87
88 static void
89 sframe_decoder_set_func_reloc_index (struct sframe_dec_info *sfd_info,
90 unsigned int func_idx,
91 unsigned int reloc_index)
92 {
93 if (func_idx < sfd_info->sfd_fde_count)
94 sfd_info->sfd_func_bfdinfo[func_idx].func_reloc_index = reloc_index;
95 }
96
97 /* Initialize the set of additional information in CFD_INFO,
98 needed for linking SEC. Returns TRUE if setup is done successfully. */
99
100 static bool
101 sframe_decoder_init_func_bfdinfo (bfd *abfd,
102 const asection *sec,
103 struct sframe_dec_info *sfd_info,
104 const struct elf_reloc_cookie *cookie)
105 {
106 unsigned int fde_count;
107 unsigned int func_bfdinfo_size, i;
108 const Elf_Internal_Rela *rel;
109
110 fde_count = sframe_decoder_get_num_fidx (sfd_info->sfd_ctx);
111 sfd_info->sfd_fde_count = fde_count;
112
113 /* Allocate and clear the memory. */
114 func_bfdinfo_size = (sizeof (struct sframe_func_bfdinfo)) * fde_count;
115 sfd_info->sfd_func_bfdinfo = bfd_zalloc (abfd, func_bfdinfo_size);
116 if (sfd_info->sfd_func_bfdinfo == NULL)
117 return false;
118
119 /* For linker generated .sframe sections, we have no relocs. Skip. */
120 if ((sec->flags & SEC_LINKER_CREATED) && cookie->rels == NULL)
121 return true;
122
123 rel = cookie->rels;
124 for (i = 0; i < fde_count; i++)
125 {
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, rel->r_offset);
129 sframe_decoder_set_func_reloc_index (sfd_info, i, i);
130
131 rel++;
132 }
133
134 /* If there are more relocation entries, they must be R_*_NONE which
135 may be generated from relocations against discarded sections by
136 ld -r. */
137 for (; rel < cookie->relend; rel++)
138 if (rel->r_info != 0)
139 break;
140 BFD_ASSERT (rel == cookie->relend);
141
142 return true;
143 }
144
145 /* Read the value from CONTENTS at the specified OFFSET for the given ABFD. */
146
147 static bfd_vma
148 sframe_read_value (bfd *abfd, bfd_byte *contents, unsigned int offset,
149 unsigned int width)
150 {
151 BFD_ASSERT (contents && offset);
152 /* Supporting the usecase of reading only the 4-byte relocated
153 value (signed offset for func start addr) for now. */
154 BFD_ASSERT (width == 4);
155 /* FIXME endianness ?? */
156 unsigned char *buf = contents + offset;
157 bfd_vma value = bfd_get_signed_32 (abfd, buf);
158 return value;
159 }
160
161 /* Return true if there is at least one non-empty .sframe section in
162 input files. Can only be called after ld has mapped input to
163 output sections, and before sections are stripped. */
164
165 bool
166 _bfd_elf_sframe_present (struct bfd_link_info *info)
167 {
168 asection *sframe = bfd_get_section_by_name (info->output_bfd, ".sframe");
169
170 if (sframe == NULL)
171 return false;
172
173 /* Count only sections which have at least a single FDE. */
174 for (sframe = sframe->map_head.s; sframe != NULL; sframe = sframe->map_head.s)
175 /* Note that this may become an approximate check in the future when
176 some ABI/arch begin to use the sfh_auxhdr_len. When sfh_auxhdr_len has
177 non-zero value, it will need to be accounted for in the calculation of
178 the SFrame header size. */
179 if (sframe->size > sizeof (sframe_header))
180 return true;
181 return false;
182 }
183
184 /* Try to parse .sframe section SEC, which belongs to ABFD. Store the
185 information in the section's sec_info field on success. COOKIE
186 describes the relocations in SEC.
187
188 Returns TRUE if success, FALSE if any error or failure. */
189
190 bool
191 _bfd_elf_parse_sframe (bfd *abfd,
192 struct bfd_link_info *info ATTRIBUTE_UNUSED,
193 asection *sec, struct elf_reloc_cookie *cookie)
194 {
195 bfd_byte *sfbuf = NULL;
196 struct sframe_dec_info *sfd_info;
197 sframe_decoder_ctx *sfd_ctx;
198 bfd_size_type sf_size;
199 int decerr = 0;
200
201 /* Prior versions of assembler and ld were generating SFrame sections with
202 section type SHT_PROGBITS. Issue an error for lack of support for such
203 objects now. Even if section size is zero, a valid section type is
204 expected. */
205 if (elf_section_type (sec) != SHT_GNU_SFRAME)
206 {
207 _bfd_error_handler
208 (_("error in %pB(%pA); unexpected SFrame section type"),
209 abfd, sec);
210 return false;
211 }
212
213 if (sec->size == 0
214 || (sec->flags & SEC_HAS_CONTENTS) == 0
215 || sec->sec_info_type != SEC_INFO_TYPE_NONE)
216 {
217 /* This file does not contain .sframe information. */
218 return false;
219 }
220
221 if (bfd_is_abs_section (sec->output_section))
222 {
223 /* At least one of the sections is being discarded from the
224 link, so we should just ignore them. */
225 return false;
226 }
227
228 /* Read the SFrame stack trace information from abfd. */
229 if (!_bfd_elf_mmap_section_contents (abfd, sec, &sfbuf))
230 goto fail_no_free;
231
232 /* Decode the buffer and keep decoded contents for later use.
233 Relocations are performed later, but are such that the section's
234 size is unaffected. */
235 sfd_info = bfd_zalloc (abfd, sizeof (*sfd_info));
236 sf_size = sec->size;
237
238 sfd_info->sfd_ctx = sframe_decode ((const char*)sfbuf, sf_size, &decerr);
239 sfd_info->sfd_state = SFRAME_SEC_DECODED;
240 sfd_ctx = sfd_info->sfd_ctx;
241 if (!sfd_ctx)
242 /* Free'ing up any memory held by decoder context is done by
243 sframe_decode in case of error. */
244 goto fail_no_free;
245
246 if (!sframe_decoder_init_func_bfdinfo (abfd, sec, sfd_info, cookie))
247 {
248 sframe_decoder_free (&sfd_ctx);
249 goto fail_no_free;
250 }
251
252 elf_section_data (sec)->sec_info = sfd_info;
253 sec->sec_info_type = SEC_INFO_TYPE_SFRAME;
254
255 goto success;
256
257 fail_no_free:
258 _bfd_error_handler
259 (_("error in %pB(%pA); no .sframe will be created"),
260 abfd, sec);
261 return false;
262 success:
263 _bfd_elf_munmap_section_contents (sec, sfbuf);
264 return true;
265 }
266
267 /* This function is called for each input file before the .sframe section
268 is relocated. It marks the SFrame FDE for the discarded functions for
269 deletion.
270
271 The function returns TRUE iff any entries have been deleted. */
272
273 bool
274 _bfd_elf_discard_section_sframe
275 (asection *sec,
276 bool (*reloc_symbol_deleted_p) (bfd_vma, void *),
277 struct elf_reloc_cookie *cookie)
278 {
279 bool changed;
280 bool keep;
281 unsigned int i;
282 unsigned int func_desc_offset;
283 unsigned int num_fidx;
284 struct sframe_dec_info *sfd_info;
285
286 changed = false;
287 /* FIXME - if relocatable link and changed = true, how does the final
288 .rela.sframe get updated ?. */
289 keep = false;
290
291 sfd_info = (struct sframe_dec_info *) elf_section_data (sec)->sec_info;
292
293 /* Skip checking for the linker created .sframe sections
294 (for PLT sections). */
295 if ((sec->flags & SEC_LINKER_CREATED) == 0 || cookie->rels != NULL)
296 {
297 num_fidx = sframe_decoder_get_num_fidx (sfd_info->sfd_ctx);
298 for (i = 0; i < num_fidx; i++)
299 {
300 func_desc_offset = sframe_decoder_get_func_r_offset (sfd_info, i);
301
302 cookie->rel = cookie->rels
303 + sframe_decoder_get_func_reloc_index (sfd_info, i);
304 keep = !(*reloc_symbol_deleted_p) (func_desc_offset, cookie);
305
306 if (!keep)
307 {
308 sframe_decoder_mark_func_deleted (sfd_info, i);
309 changed = true;
310 }
311 }
312 }
313 return changed;
314 }
315
316 /* Update the reference to the output .sframe section in the output ELF
317 BFD ABFD. Returns true if no error. */
318
319 bool
320 _bfd_elf_set_section_sframe (bfd *abfd, struct bfd_link_info *info)
321 {
322 asection *cfsec;
323
324 cfsec = bfd_get_section_by_name (info->output_bfd, ".sframe");
325 if (!cfsec)
326 return false;
327
328 elf_section_type (cfsec) = SHT_GNU_SFRAME;
329 elf_sframe (abfd) = cfsec;
330
331 return true;
332 }
333
334 /* Merge .sframe section SEC. This is called with the relocated
335 CONTENTS. */
336
337 bool
338 _bfd_elf_merge_section_sframe (bfd *abfd,
339 struct bfd_link_info *info,
340 asection *sec,
341 bfd_byte *contents)
342 {
343 struct sframe_dec_info *sfd_info;
344 struct sframe_enc_info *sfe_info;
345 sframe_decoder_ctx *sfd_ctx;
346 sframe_encoder_ctx *sfe_ctx;
347 uint8_t sfd_ctx_abi_arch;
348 int8_t sfd_ctx_fixed_fp_offset;
349 int8_t sfd_ctx_fixed_ra_offset;
350 uint8_t dctx_version;
351 uint8_t ectx_version;
352 uint8_t dctx_flags;
353 uint8_t ectx_flags;
354 int encerr = 0;
355
356 struct elf_link_hash_table *htab;
357 asection *cfsec;
358
359 /* Sanity check - handle SFrame sections only. */
360 if (sec->sec_info_type != SEC_INFO_TYPE_SFRAME)
361 return false;
362
363 sfd_info = (struct sframe_dec_info *) elf_section_data (sec)->sec_info;
364 sfd_ctx = sfd_info->sfd_ctx;
365
366 htab = elf_hash_table (info);
367 sfe_info = &(htab->sfe_info);
368 sfe_ctx = sfe_info->sfe_ctx;
369
370 /* All input bfds are expected to have a valid SFrame section. Even if
371 the SFrame section is empty with only a header, there must be a valid
372 SFrame decoder context by now. The SFrame encoder context, however,
373 will get set later here, if this is the first call to the function. */
374 if (sfd_ctx == NULL || sfe_info == NULL)
375 return false;
376
377 dctx_flags = sframe_decoder_get_flags (sfd_ctx);
378
379 if (htab->sfe_info.sfe_ctx == NULL)
380 {
381 sfd_ctx_abi_arch = sframe_decoder_get_abi_arch (sfd_ctx);
382 sfd_ctx_fixed_fp_offset = sframe_decoder_get_fixed_fp_offset (sfd_ctx);
383 sfd_ctx_fixed_ra_offset = sframe_decoder_get_fixed_ra_offset (sfd_ctx);
384
385 /* Valid values are non-zero. */
386 if (!sfd_ctx_abi_arch)
387 return false;
388
389 /* In-memory FDEs in the encoder object are unsorted during linking and
390 will be sorted before emission. Reset SFRAME_F_FDE_SORTED to aptly
391 reflect that (doing so has no other functional value at this time
392 though). */
393 uint8_t tflags = dctx_flags & ~SFRAME_F_FDE_SORTED;
394 /* ld always generates an output section with
395 SFRAME_F_FDE_FUNC_START_PCREL flag set. Later using
396 SFRAME_V2_GNU_AS_LD_ENCODING_FLAGS, it is enforced that the provided
397 input sections also have this flag set. */
398 tflags |= SFRAME_F_FDE_FUNC_START_PCREL;
399 htab->sfe_info.sfe_ctx = sframe_encode (SFRAME_VERSION_2,
400 tflags, /* SFrame flags. */
401 sfd_ctx_abi_arch,
402 sfd_ctx_fixed_fp_offset,
403 sfd_ctx_fixed_ra_offset,
404 &encerr);
405 /* Handle errors from sframe_encode. */
406 if (htab->sfe_info.sfe_ctx == NULL)
407 return false;
408 }
409 sfe_ctx = sfe_info->sfe_ctx;
410
411 if (sfe_info->sframe_section == NULL)
412 {
413 /* Make sure things are set for an eventual write.
414 Size of the output section is not known until
415 _bfd_elf_write_section_sframe is ready with the buffer
416 to write out. */
417 cfsec = bfd_get_section_by_name (info->output_bfd, ".sframe");
418 if (cfsec)
419 {
420 sfe_info->sframe_section = cfsec;
421 // elf_sframe (abfd) = cfsec;
422 }
423 else
424 return false;
425 }
426
427 /* Check that all .sframe sections being linked have the same
428 ABI/arch. */
429 if (sframe_decoder_get_abi_arch (sfd_ctx)
430 != sframe_encoder_get_abi_arch (sfe_ctx))
431 {
432 _bfd_error_handler
433 (_("input SFrame sections with different abi prevent .sframe"
434 " generation"));
435 return false;
436 }
437
438 /* Check that all .sframe sections being linked have the same version. */
439 dctx_version = sframe_decoder_get_version (sfd_ctx);
440 ectx_version = sframe_encoder_get_version (sfe_ctx);
441 if (dctx_version != SFRAME_VERSION_2 || dctx_version != ectx_version)
442 {
443 _bfd_error_handler
444 (_("input SFrame sections with different format versions prevent"
445 " .sframe generation"));
446 return false;
447 }
448
449 /* Check that all SFrame sections being linked have the 'data encoding'
450 related flags set. The implementation does not support updating these
451 data encodings on the fly; confirm by checking the ectx_flags. */
452 ectx_flags = sframe_encoder_get_flags (sfe_ctx);
453 if ((dctx_flags & ectx_flags & SFRAME_V2_GNU_AS_LD_ENCODING_FLAGS)
454 != SFRAME_V2_GNU_AS_LD_ENCODING_FLAGS)
455 {
456 _bfd_error_handler
457 (_("SFrame sections with unexpected data encoding prevent"
458 " .sframe generation"));
459 return false;
460 }
461
462 /* Iterate over the function descriptor entries and the FREs of the
463 function from the decoder context. Add each of them to the encoder
464 context, if suitable. */
465 uint32_t i = 0, j = 0, cur_fidx = 0;
466
467 uint32_t num_fidx = sframe_decoder_get_num_fidx (sfd_ctx);
468 uint32_t num_enc_fidx = sframe_encoder_get_num_fidx (sfe_ctx);
469
470 for (i = 0; i < num_fidx; i++)
471 {
472 unsigned int num_fres = 0;
473 int32_t func_start_addr;
474 bfd_vma address;
475 uint32_t func_size = 0;
476 unsigned char func_info = 0;
477 unsigned int r_offset = 0;
478 bool pltn_reloc_by_hand = false;
479 unsigned int pltn_r_offset = 0;
480 uint8_t rep_block_size = 0;
481
482 if (!sframe_decoder_get_funcdesc_v2 (sfd_ctx, i, &num_fres, &func_size,
483 &func_start_addr, &func_info,
484 &rep_block_size))
485 {
486 /* If function belongs to a deleted section, skip editing the
487 function descriptor entry. */
488 if (sframe_decoder_func_deleted_p(sfd_info, i))
489 continue;
490
491 /* Don't edit function descriptor entries for relocatable link. */
492 if (!bfd_link_relocatable (info))
493 {
494 if (!(sec->flags & SEC_LINKER_CREATED))
495 {
496 /* Get relocated contents by reading the value of the
497 relocated function start address at the beginning of the
498 function descriptor entry. */
499 r_offset = sframe_decoder_get_func_r_offset (sfd_info, i);
500 }
501 else
502 {
503 /* Expected to land here when SFrame stack trace info is
504 created dynamically for the .plt* sections. These
505 sections are expected to have upto two SFrame FDE entries.
506 Although the code should work for > 2, leaving this
507 assert here for safety. */
508 BFD_ASSERT (num_fidx <= 2);
509 /* For the first entry, we know the offset of the SFrame FDE's
510 sfde_func_start_address. Side note: see how the value
511 of PLT_SFRAME_FDE_START_OFFSET is also set to the
512 same. */
513 r_offset = sframe_decoder_get_hdr_size (sfd_ctx);
514 /* For any further SFrame FDEs, the generator has already put
515 in an offset in place of sfde_func_start_address of the
516 corresponding FDE. We will use it by hand to relocate. */
517 if (i > 0)
518 {
519 pltn_r_offset
520 = r_offset + (i * sizeof (sframe_func_desc_entry));
521 pltn_reloc_by_hand = true;
522 }
523 }
524
525 /* Get the SFrame FDE function start address after relocation. */
526 address = sframe_read_value (abfd, contents, r_offset, 4);
527 if (pltn_reloc_by_hand)
528 address += sframe_read_value (abfd, contents,
529 pltn_r_offset, 4);
530 address += (sec->output_offset + r_offset);
531 /* SFrame FDE function start address is an offset from the
532 sfde_func_start_address field to the start PC. The
533 calculation below is the distance of sfde_func_start_address
534 field from the start of the output SFrame section. */
535 uint32_t offsetof_fde_in_sec
536 = sframe_encoder_get_offsetof_fde_start_addr (sfe_ctx,
537 cur_fidx + num_enc_fidx,
538 NULL);
539 address -= offsetof_fde_in_sec;
540
541 /* FIXME For testing only. Cleanup later. */
542 // address += (sec->output_section->vma);
543
544 func_start_addr = address;
545 }
546
547 /* Update the encoder context with updated content. */
548 int err = sframe_encoder_add_funcdesc_v2 (sfe_ctx, func_start_addr,
549 func_size, func_info,
550 rep_block_size, num_fres);
551 cur_fidx++;
552 BFD_ASSERT (!err);
553 }
554
555 for (j = 0; j < num_fres; j++)
556 {
557 sframe_frame_row_entry fre;
558 if (!sframe_decoder_get_fre (sfd_ctx, i, j, &fre))
559 {
560 int err = sframe_encoder_add_fre (sfe_ctx,
561 cur_fidx-1+num_enc_fidx,
562 &fre);
563 BFD_ASSERT (!err);
564 }
565 }
566 }
567 sfd_info->sfd_state = SFRAME_SEC_MERGED;
568 /* Free the SFrame decoder context. */
569 sframe_decoder_free (&sfd_ctx);
570
571 return true;
572 }
573
574 /* Adjust an address in the .sframe section. Given OFFSET within
575 SEC, this returns the new offset in the merged .sframe section,
576 or -1 if the address refers to an FDE which has been removed.
577
578 PS: This function assumes that _bfd_elf_merge_section_sframe has
579 not been called on the input section SEC yet. Note how it uses
580 sframe_encoder_get_num_fidx () to figure out the offset of FDE
581 in the output section. */
582
583 bfd_vma
584 _bfd_elf_sframe_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED,
585 struct bfd_link_info *info,
586 asection *sec,
587 bfd_vma offset)
588 {
589 struct sframe_dec_info *sfd_info;
590 struct sframe_enc_info *sfe_info;
591 sframe_decoder_ctx *sfd_ctx;
592 sframe_encoder_ctx *sfe_ctx;
593 struct elf_link_hash_table *htab;
594
595 unsigned int sec_fde_idx, out_num_fdes;
596 unsigned int sfd_num_fdes, sfe_num_fdes;
597 uint32_t sfd_fde_offset;
598 bfd_vma new_offset;
599
600 if (sec->sec_info_type != SEC_INFO_TYPE_SFRAME)
601 return offset;
602
603 sfd_info = elf_section_data (sec)->sec_info;
604 sfd_ctx = sfd_info->sfd_ctx;
605 sfd_num_fdes = sframe_decoder_get_num_fidx (sfd_ctx);
606
607 BFD_ASSERT (sfd_info->sfd_state == SFRAME_SEC_DECODED);
608
609 htab = elf_hash_table (info);
610 sfe_info = &(htab->sfe_info);
611 sfe_ctx = sfe_info->sfe_ctx;
612 sfe_num_fdes = sframe_encoder_get_num_fidx (sfe_ctx);
613
614 /* The index of this FDE in the output section depends on number of deleted
615 functions (between index 0 and sec_fde_idx), if any. */
616 out_num_fdes = 0;
617 sec_fde_idx = 0;
618 for (unsigned int i = 0; i < sfd_num_fdes; i++)
619 {
620 sfd_fde_offset = sframe_decoder_get_offsetof_fde_start_addr (sfd_ctx,
621 i, NULL);
622 if (!sframe_decoder_func_deleted_p (sfd_info, i))
623 out_num_fdes++;
624
625 if (sfd_fde_offset == offset)
626 {
627 /* Found the index of the FDE (at OFFSET) in the input section. */
628 sec_fde_idx = i;
629 break;
630 }
631 }
632
633 if (sframe_decoder_func_deleted_p (sfd_info, sec_fde_idx))
634 return (bfd_vma) -1;
635
636 /* The number of FDEs in the output SFrame section. Note that the output
637 index of the FDE of interest will be (out_num_fdes - 1). */
638 out_num_fdes += sfe_num_fdes;
639
640 new_offset = sframe_decoder_get_offsetof_fde_start_addr (sfd_ctx,
641 out_num_fdes - 1,
642 NULL);
643 /* Recall that SFrame section merging has distinct requirements: All SFrame
644 FDEs from input sections are clubbed together in the beginning of the
645 output section. So, at this point in the current function, the new_offset
646 is the correct offset in the merged output SFrame section. Note, however,
647 that the default mechanism in the _elf_link_input_bfd will do the
648 following adjustment:
649 irela->r_offset += o->output_offset;
650 for all section types. However, such an adjustment in the RELA offset is
651 _not_ needed for SFrame sections. Perform the reverse adjustment here so
652 that the default mechanism does not need additional SFrame specific
653 checks. */
654 new_offset -= sec->output_offset;
655
656 return new_offset;
657 }
658
659 /* Write out the .sframe section. This must be called after
660 _bfd_elf_merge_section_sframe has been called on all input
661 .sframe sections. */
662
663 bool
664 _bfd_elf_write_section_sframe (bfd *abfd, struct bfd_link_info *info)
665 {
666 bool retval = true;
667
668 struct elf_link_hash_table *htab;
669 struct sframe_enc_info *sfe_info;
670 sframe_encoder_ctx *sfe_ctx;
671 asection *sec;
672 void *contents;
673 size_t sec_size;
674 int err = 0;
675
676 htab = elf_hash_table (info);
677 sfe_info = &htab->sfe_info;
678 sec = sfe_info->sframe_section;
679 sfe_ctx = sfe_info->sfe_ctx;
680
681 if (sec == NULL)
682 return true;
683
684 contents = sframe_encoder_write (sfe_ctx, &sec_size, &err);
685 sec->size = (bfd_size_type) sec_size;
686
687 if (!bfd_set_section_contents (abfd, sec->output_section, contents,
688 (file_ptr) sec->output_offset,
689 sec->size))
690 retval = false;
691 else
692 {
693 Elf_Internal_Shdr *hdr = &elf_section_data (sec)->this_hdr;
694 hdr->sh_size = sec->size;
695 }
696
697 sframe_encoder_free (&sfe_ctx);
698
699 return retval;
700 }
701