Coverage Report

Created: 2025-07-08 11:15

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