Coverage Report

Created: 2023-08-28 06:31

/src/binutils-gdb/bfd/elf-sframe.c
Line
Count
Source (jump to first uncovered line)
1
/* .sframe section processing.
2
   Copyright (C) 2022-2023 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 (asection *sec,
101
          struct sframe_dec_info *sfd_info,
102
          struct elf_reloc_cookie *cookie)
103
0
{
104
0
  unsigned int fde_count;
105
0
  unsigned int func_bfdinfo_size, i;
106
107
0
  fde_count = sframe_decoder_get_num_fidx (sfd_info->sfd_ctx);
108
0
  sfd_info->sfd_fde_count = fde_count;
109
110
  /* Allocate and clear the memory.  */
111
0
  func_bfdinfo_size = (sizeof (struct sframe_func_bfdinfo)) * fde_count;
112
0
  sfd_info->sfd_func_bfdinfo
113
0
    = (struct sframe_func_bfdinfo*) bfd_malloc (func_bfdinfo_size);
114
0
  if (sfd_info->sfd_func_bfdinfo == NULL)
115
0
    return false;
116
0
  memset (sfd_info->sfd_func_bfdinfo, 0, func_bfdinfo_size);
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
  for (i = 0; i < fde_count; i++)
123
0
    {
124
0
      cookie->rel = cookie->rels + i;
125
0
      BFD_ASSERT (cookie->rel < cookie->relend);
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, cookie->rel->r_offset);
129
0
      sframe_decoder_set_func_reloc_index (sfd_info, i,
130
0
             (cookie->rel - cookie->rels));
131
132
0
      cookie->rel++;
133
0
    }
134
0
  BFD_ASSERT (cookie->rel == cookie->relend);
135
136
0
  return true;
137
0
}
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
0
{
145
0
  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
0
  BFD_ASSERT (width == 4);
149
  /* FIXME endianness ?? */
150
0
  unsigned char *buf = contents + offset;
151
0
  bfd_vma value = bfd_get_signed_32 (abfd, buf);
152
0
  return value;
153
0
}
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
0
{
162
0
  asection *sframe = bfd_get_section_by_name (info->output_bfd, ".sframe");
163
164
0
  if (sframe == NULL)
165
0
    return false;
166
167
  /* Count only sections which have at least a single FDE.  */
168
0
  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
0
    if (sframe->size > sizeof (sframe_header))
174
0
      return true;
175
0
  return false;
176
0
}
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
0
{
189
0
  bfd_byte *sfbuf = NULL;
190
0
  struct sframe_dec_info *sfd_info;
191
0
  sframe_decoder_ctx *sfd_ctx;
192
0
  bfd_size_type sf_size;
193
0
  int decerr = 0;
194
195
0
  if (sec->size == 0
196
0
      || (sec->flags & SEC_HAS_CONTENTS) == 0
197
0
      || sec->sec_info_type != SEC_INFO_TYPE_NONE)
198
0
    {
199
      /* This file does not contain .sframe information.  */
200
0
      return false;
201
0
    }
202
203
0
  if (bfd_is_abs_section (sec->output_section))
204
0
    {
205
      /* At least one of the sections is being discarded from the
206
   link, so we should just ignore them.  */
207
0
      return false;
208
0
    }
209
210
  /* Read the SFrame stack trace information from abfd.  */
211
0
  if (!bfd_malloc_and_get_section (abfd, sec, &sfbuf))
212
0
    goto fail_no_free;
213
214
  /* Decode the buffer and keep decoded contents for later use.
215
     Relocations are performed later, but are such that the section's
216
     size is unaffected.  */
217
0
  sfd_info = bfd_malloc (sizeof (struct sframe_dec_info));
218
0
  sf_size = sec->size;
219
220
0
  sfd_info->sfd_ctx = sframe_decode ((const char*)sfbuf, sf_size, &decerr);
221
0
  sfd_ctx = sfd_info->sfd_ctx;
222
0
  if (!sfd_ctx)
223
    /* Free'ing up any memory held by decoder context is done by
224
       sframe_decode in case of error.  */
225
0
    goto fail_no_free;
226
227
0
  if (!sframe_decoder_init_func_bfdinfo (sec, sfd_info, cookie))
228
0
    {
229
0
      sframe_decoder_free (&sfd_ctx);
230
0
      goto fail_no_free;
231
0
    }
232
233
0
  elf_section_data (sec)->sec_info = sfd_info;
234
0
  sec->sec_info_type = SEC_INFO_TYPE_SFRAME;
235
236
0
  goto success;
237
238
0
fail_no_free:
239
0
  _bfd_error_handler
240
0
   (_("error in %pB(%pA); no .sframe will be created"),
241
0
    abfd, sec);
242
0
  return false;
243
0
success:
244
0
  free (sfbuf);
245
0
  return true;
246
0
}
247
248
/* This function is called for each input file before the .sframe section
249
   is relocated.  It marks the SFrame FDE for the discarded functions for
250
   deletion.
251
252
   The function returns TRUE iff any entries have been deleted.  */
253
254
bool
255
_bfd_elf_discard_section_sframe
256
   (asection *sec,
257
    bool (*reloc_symbol_deleted_p) (bfd_vma, void *),
258
    struct elf_reloc_cookie *cookie)
259
0
{
260
0
  bool changed;
261
0
  bool keep;
262
0
  unsigned int i;
263
0
  unsigned int func_desc_offset;
264
0
  unsigned int num_fidx;
265
0
  struct sframe_dec_info *sfd_info;
266
267
0
  changed = false;
268
  /* FIXME - if relocatable link and changed = true, how does the final
269
     .rela.sframe get updated ?.  */
270
0
  keep = false;
271
272
0
  sfd_info = (struct sframe_dec_info *) elf_section_data (sec)->sec_info;
273
274
  /* Skip checking for the linker created .sframe sections
275
     (for PLT sections).  */
276
0
  if ((sec->flags & SEC_LINKER_CREATED) == 0 || cookie->rels != NULL)
277
0
    {
278
0
      num_fidx = sframe_decoder_get_num_fidx (sfd_info->sfd_ctx);
279
0
      for (i = 0; i < num_fidx; i++)
280
0
  {
281
0
    func_desc_offset = sframe_decoder_get_func_r_offset (sfd_info, i);
282
283
0
    cookie->rel = cookie->rels
284
0
      + sframe_decoder_get_func_reloc_index (sfd_info, i);
285
0
    keep = !(*reloc_symbol_deleted_p) (func_desc_offset, cookie);
286
287
0
    if (!keep)
288
0
      {
289
0
        sframe_decoder_mark_func_deleted (sfd_info, i);
290
0
        changed = true;
291
0
      }
292
0
  }
293
0
    }
294
0
  return changed;
295
0
}
296
297
/* Update the reference to the output .sframe section in the output ELF
298
   BFD ABFD.  Returns true if no error.  */
299
300
bool
301
_bfd_elf_set_section_sframe (bfd *abfd,
302
        struct bfd_link_info *info)
303
0
{
304
0
  asection *cfsec;
305
306
0
  cfsec = bfd_get_section_by_name (info->output_bfd, ".sframe");
307
0
  if (!cfsec)
308
0
    return false;
309
310
0
  elf_sframe (abfd) = cfsec;
311
312
0
  return true;
313
0
}
314
315
/* Merge .sframe section SEC.  This is called with the relocated
316
   CONTENTS.  */
317
318
bool
319
_bfd_elf_merge_section_sframe (bfd *abfd,
320
             struct bfd_link_info *info,
321
             asection *sec,
322
             bfd_byte *contents)
323
0
{
324
0
  struct sframe_dec_info *sfd_info;
325
0
  struct sframe_enc_info *sfe_info;
326
0
  sframe_decoder_ctx *sfd_ctx;
327
0
  sframe_encoder_ctx *sfe_ctx;
328
0
  uint8_t sfd_ctx_abi_arch;
329
0
  int8_t sfd_ctx_fixed_fp_offset;
330
0
  int8_t sfd_ctx_fixed_ra_offset;
331
0
  uint8_t dctx_version;
332
0
  uint8_t ectx_version;
333
0
  int encerr = 0;
334
335
0
  struct elf_link_hash_table *htab;
336
0
  asection *cfsec;
337
338
  /* Sanity check - handle SFrame sections only.  */
339
0
  if (sec->sec_info_type != SEC_INFO_TYPE_SFRAME)
340
0
    return false;
341
342
0
  sfd_info = (struct sframe_dec_info *) elf_section_data (sec)->sec_info;
343
0
  sfd_ctx = sfd_info->sfd_ctx;
344
345
0
  htab = elf_hash_table (info);
346
0
  sfe_info = &(htab->sfe_info);
347
0
  sfe_ctx = sfe_info->sfe_ctx;
348
349
  /* All input bfds are expected to have a valid SFrame section.  Even if
350
     the SFrame section is empty with only a header, there must be a valid
351
     SFrame decoder context by now.  The SFrame encoder context, however,
352
     will get set later here, if this is the first call to the function.  */
353
0
  if (sfd_ctx == NULL || sfe_info == NULL)
354
0
    return false;
355
356
0
  if (htab->sfe_info.sfe_ctx == NULL)
357
0
    {
358
0
      sfd_ctx_abi_arch = sframe_decoder_get_abi_arch (sfd_ctx);
359
0
      sfd_ctx_fixed_fp_offset = sframe_decoder_get_fixed_fp_offset (sfd_ctx);
360
0
      sfd_ctx_fixed_ra_offset = sframe_decoder_get_fixed_ra_offset (sfd_ctx);
361
362
      /* Valid values are non-zero.  */
363
0
      if (!sfd_ctx_abi_arch)
364
0
  return false;
365
366
0
      htab->sfe_info.sfe_ctx = sframe_encode (SFRAME_VERSION_2,
367
0
                0, /* SFrame flags.  */
368
0
                sfd_ctx_abi_arch,
369
0
                sfd_ctx_fixed_fp_offset,
370
0
                sfd_ctx_fixed_ra_offset,
371
0
                &encerr);
372
      /* Handle errors from sframe_encode.  */
373
0
      if (htab->sfe_info.sfe_ctx == NULL)
374
0
  return false;
375
0
    }
376
0
  sfe_ctx = sfe_info->sfe_ctx;
377
378
0
  if (sfe_info->sframe_section == NULL)
379
0
    {
380
      /* Make sure things are set for an eventual write.
381
   Size of the output section is not known until
382
   _bfd_elf_write_section_sframe is ready with the buffer
383
   to write out.  */
384
0
      cfsec = bfd_get_section_by_name (info->output_bfd, ".sframe");
385
0
      if (cfsec)
386
0
  {
387
0
    sfe_info->sframe_section = cfsec;
388
    // elf_sframe (abfd) = cfsec;
389
0
  }
390
0
      else
391
0
  return false;
392
0
    }
393
394
  /* Check that all .sframe sections being linked have the same
395
     ABI/arch.  */
396
0
  if (sframe_decoder_get_abi_arch (sfd_ctx)
397
0
      != sframe_encoder_get_abi_arch (sfe_ctx))
398
0
    {
399
0
      _bfd_error_handler
400
0
  (_("input SFrame sections with different abi prevent .sframe"
401
0
    " generation"));
402
0
      return false;
403
0
    }
404
405
  /* Check that all .sframe sections being linked have the same version.  */
406
0
  dctx_version = sframe_decoder_get_version (sfd_ctx);
407
0
  ectx_version = sframe_encoder_get_version (sfe_ctx);
408
0
  if (dctx_version != SFRAME_VERSION_2 || dctx_version != ectx_version)
409
0
    {
410
0
      _bfd_error_handler
411
0
  (_("input SFrame sections with different format versions prevent"
412
0
    " .sframe generation"));
413
0
      return false;
414
0
    }
415
416
417
  /* Iterate over the function descriptor entries and the FREs of the
418
     function from the decoder context.  Add each of them to the encoder
419
     context, if suitable.  */
420
0
  uint32_t i = 0, j = 0, cur_fidx = 0;
421
422
0
  uint32_t num_fidx = sframe_decoder_get_num_fidx (sfd_ctx);
423
0
  uint32_t num_enc_fidx = sframe_encoder_get_num_fidx (sfe_ctx);
424
425
0
  for (i = 0; i < num_fidx; i++)
426
0
    {
427
0
      unsigned int num_fres = 0;
428
0
      int32_t func_start_addr;
429
0
      bfd_vma address;
430
0
      uint32_t func_size = 0;
431
0
      unsigned char func_info = 0;
432
0
      unsigned int r_offset = 0;
433
0
      bool pltn_reloc_by_hand = false;
434
0
      unsigned int pltn_r_offset = 0;
435
0
      uint8_t rep_block_size = 0;
436
437
0
      if (!sframe_decoder_get_funcdesc_v2 (sfd_ctx, i, &num_fres, &func_size,
438
0
             &func_start_addr, &func_info,
439
0
             &rep_block_size))
440
0
  {
441
    /* If function belongs to a deleted section, skip editing the
442
       function descriptor entry.  */
443
0
    if (sframe_decoder_func_deleted_p(sfd_info, i))
444
0
      continue;
445
446
    /* Don't edit function descriptor entries for relocatable link.  */
447
0
    if (!bfd_link_relocatable (info))
448
0
      {
449
0
        if (!(sec->flags & SEC_LINKER_CREATED))
450
0
    {
451
      /* Get relocated contents by reading the value of the
452
         relocated function start address at the beginning of the
453
         function descriptor entry.  */
454
0
      r_offset = sframe_decoder_get_func_r_offset (sfd_info, i);
455
0
    }
456
0
        else
457
0
    {
458
      /* Expected to land here when SFrame stack trace info is
459
         created dynamically for the .plt* sections.  These
460
         sections are expected to have upto two SFrame FDE entries.
461
         Although the code should work for > 2,  leaving this
462
         assert here for safety.  */
463
0
      BFD_ASSERT (num_fidx <= 2);
464
      /* For the first entry, we know the offset of the SFrame FDE's
465
         sfde_func_start_address.  Side note: see how the value
466
         of PLT_SFRAME_FDE_START_OFFSET is also set to the
467
         same.  */
468
0
      r_offset = sframe_decoder_get_hdr_size (sfd_ctx);
469
      /* For any further SFrame FDEs, the generator has already put
470
         in an offset in place of sfde_func_start_address of the
471
         corresponding FDE.  We will use it by hand to relocate.  */
472
0
      if (i > 0)
473
0
        {
474
0
          pltn_r_offset
475
0
      = r_offset + (i * sizeof (sframe_func_desc_entry));
476
0
          pltn_reloc_by_hand = true;
477
0
        }
478
0
    }
479
480
        /* Get the SFrame FDE function start address after relocation.  */
481
0
        address = sframe_read_value (abfd, contents, r_offset, 4);
482
0
        if (pltn_reloc_by_hand)
483
0
    address += sframe_read_value (abfd, contents,
484
0
                pltn_r_offset, 4);
485
0
        address += (sec->output_offset + r_offset);
486
487
        /* FIXME For testing only. Cleanup later.  */
488
        // address += (sec->output_section->vma);
489
490
0
        func_start_addr = address;
491
0
      }
492
493
    /* Update the encoder context with updated content.  */
494
0
    int err = sframe_encoder_add_funcdesc_v2 (sfe_ctx, func_start_addr,
495
0
                func_size, func_info,
496
0
                rep_block_size, num_fres);
497
0
    cur_fidx++;
498
0
    BFD_ASSERT (!err);
499
0
  }
500
501
0
      for (j = 0; j < num_fres; j++)
502
0
  {
503
0
    sframe_frame_row_entry fre;
504
0
    if (!sframe_decoder_get_fre (sfd_ctx, i, j, &fre))
505
0
      {
506
0
        int err = sframe_encoder_add_fre (sfe_ctx,
507
0
            cur_fidx-1+num_enc_fidx,
508
0
            &fre);
509
0
        BFD_ASSERT (!err);
510
0
      }
511
0
  }
512
0
    }
513
  /* Free the SFrame decoder context.  */
514
0
  sframe_decoder_free (&sfd_ctx);
515
516
0
  return true;
517
0
}
518
519
/* Write out the .sframe section.  This must be called after
520
   _bfd_elf_merge_section_sframe has been called on all input
521
   .sframe sections.  */
522
523
bool
524
_bfd_elf_write_section_sframe (bfd *abfd, struct bfd_link_info *info)
525
0
{
526
0
  bool retval = true;
527
528
0
  struct elf_link_hash_table *htab;
529
0
  struct sframe_enc_info *sfe_info;
530
0
  sframe_encoder_ctx *sfe_ctx;
531
0
  asection *sec;
532
0
  void *contents;
533
0
  size_t sec_size;
534
0
  int err = 0;
535
536
0
  htab = elf_hash_table (info);
537
0
  sfe_info = &htab->sfe_info;
538
0
  sec = sfe_info->sframe_section;
539
0
  sfe_ctx = sfe_info->sfe_ctx;
540
541
0
  if (sec == NULL)
542
0
    return true;
543
544
0
  contents = sframe_encoder_write (sfe_ctx, &sec_size, &err);
545
0
  sec->size = (bfd_size_type) sec_size;
546
547
0
  if (!bfd_set_section_contents (abfd, sec->output_section, contents,
548
0
         (file_ptr) sec->output_offset,
549
0
         sec->size))
550
0
    retval = false;
551
0
  else if (!bfd_link_relocatable (info))
552
0
    {
553
0
      Elf_Internal_Shdr *hdr = &elf_section_data (sec)->this_hdr;
554
0
      hdr->sh_size = sec->size;
555
0
    }
556
  /* For relocatable links, do not update the section size as the section
557
     contents have not been relocated.  */
558
559
0
  sframe_encoder_free (&sfe_ctx);
560
561
0
  return retval;
562
0
}