Coverage Report

Created: 2023-08-28 06:25

/src/binutils-gdb/bfd/elf-properties.c
Line
Count
Source (jump to first uncovered line)
1
/* ELF program property support.
2
   Copyright (C) 2017-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
/* GNU program property draft is at:
22
23
   https://github.com/hjl-tools/linux-abi/wiki/property-draft.pdf
24
 */
25
26
#include "sysdep.h"
27
#include "bfd.h"
28
#include "libbfd.h"
29
#include "elf-bfd.h"
30
31
/* Get a property, allocate a new one if needed.  */
32
33
elf_property *
34
_bfd_elf_get_property (bfd *abfd, unsigned int type, unsigned int datasz)
35
0
{
36
0
  elf_property_list *p, **lastp;
37
38
0
  if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
39
0
    {
40
      /* Never should happen.  */
41
0
      abort ();
42
0
    }
43
44
  /* Keep the property list in order of type.  */
45
0
  lastp = &elf_properties (abfd);
46
0
  for (p = *lastp; p; p = p->next)
47
0
    {
48
      /* Reuse the existing entry.  */
49
0
      if (type == p->property.pr_type)
50
0
  {
51
0
    if (datasz > p->property.pr_datasz)
52
0
      {
53
        /* This can happen when mixing 32-bit and 64-bit objects.  */
54
0
        p->property.pr_datasz = datasz;
55
0
      }
56
0
    return &p->property;
57
0
  }
58
0
      else if (type < p->property.pr_type)
59
0
  break;
60
0
      lastp = &p->next;
61
0
    }
62
0
  p = (elf_property_list *) bfd_alloc (abfd, sizeof (*p));
63
0
  if (p == NULL)
64
0
    {
65
0
      _bfd_error_handler (_("%pB: out of memory in _bfd_elf_get_property"),
66
0
        abfd);
67
0
      _exit (EXIT_FAILURE);
68
0
    }
69
0
  memset (p, 0, sizeof (*p));
70
0
  p->property.pr_type = type;
71
0
  p->property.pr_datasz = datasz;
72
0
  p->next = *lastp;
73
0
  *lastp = p;
74
0
  return &p->property;
75
0
}
76
77
/* Parse GNU properties.  */
78
79
bool
80
_bfd_elf_parse_gnu_properties (bfd *abfd, Elf_Internal_Note *note)
81
0
{
82
0
  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
83
0
  unsigned int align_size = bed->s->elfclass == ELFCLASS64 ? 8 : 4;
84
0
  bfd_byte *ptr = (bfd_byte *) note->descdata;
85
0
  bfd_byte *ptr_end = ptr + note->descsz;
86
87
0
  if (note->descsz < 8 || (note->descsz % align_size) != 0)
88
0
    {
89
0
    bad_size:
90
0
      _bfd_error_handler
91
0
  (_("warning: %pB: corrupt GNU_PROPERTY_TYPE (%ld) size: %#lx"),
92
0
   abfd, note->type, note->descsz);
93
0
      return false;
94
0
    }
95
96
0
  while (ptr != ptr_end)
97
0
    {
98
0
      unsigned int type;
99
0
      unsigned int datasz;
100
0
      elf_property *prop;
101
102
0
      if ((size_t) (ptr_end - ptr) < 8)
103
0
  goto bad_size;
104
105
0
      type = bfd_h_get_32 (abfd, ptr);
106
0
      datasz = bfd_h_get_32 (abfd, ptr + 4);
107
0
      ptr += 8;
108
109
0
      if (datasz > (size_t) (ptr_end - ptr))
110
0
  {
111
0
    _bfd_error_handler
112
0
      (_("warning: %pB: corrupt GNU_PROPERTY_TYPE (%ld) type (0x%x) datasz: 0x%x"),
113
0
       abfd, note->type, type, datasz);
114
    /* Clear all properties.  */
115
0
    elf_properties (abfd) = NULL;
116
0
    return false;
117
0
  }
118
119
0
      if (type >= GNU_PROPERTY_LOPROC)
120
0
  {
121
0
    if (bed->elf_machine_code == EM_NONE)
122
0
      {
123
        /* Ignore processor-specific properties with generic ELF
124
     target vector.  They should be handled by the matching
125
     ELF target vector.  */
126
0
        goto next;
127
0
      }
128
0
    else if (type < GNU_PROPERTY_LOUSER
129
0
       && bed->parse_gnu_properties)
130
0
      {
131
0
        enum elf_property_kind kind
132
0
    = bed->parse_gnu_properties (abfd, type, ptr, datasz);
133
0
        if (kind == property_corrupt)
134
0
    {
135
      /* Clear all properties.  */
136
0
      elf_properties (abfd) = NULL;
137
0
      return false;
138
0
    }
139
0
        else if (kind != property_ignored)
140
0
    goto next;
141
0
      }
142
0
  }
143
0
      else
144
0
  {
145
0
    switch (type)
146
0
      {
147
0
      case GNU_PROPERTY_STACK_SIZE:
148
0
        if (datasz != align_size)
149
0
    {
150
0
      _bfd_error_handler
151
0
        (_("warning: %pB: corrupt stack size: 0x%x"),
152
0
         abfd, datasz);
153
      /* Clear all properties.  */
154
0
      elf_properties (abfd) = NULL;
155
0
      return false;
156
0
    }
157
0
        prop = _bfd_elf_get_property (abfd, type, datasz);
158
0
        if (datasz == 8)
159
0
    prop->u.number = bfd_h_get_64 (abfd, ptr);
160
0
        else
161
0
    prop->u.number = bfd_h_get_32 (abfd, ptr);
162
0
        prop->pr_kind = property_number;
163
0
        goto next;
164
165
0
      case GNU_PROPERTY_NO_COPY_ON_PROTECTED:
166
0
        if (datasz != 0)
167
0
    {
168
0
      _bfd_error_handler
169
0
        (_("warning: %pB: corrupt no copy on protected size: 0x%x"),
170
0
         abfd, datasz);
171
      /* Clear all properties.  */
172
0
      elf_properties (abfd) = NULL;
173
0
      return false;
174
0
    }
175
0
        prop = _bfd_elf_get_property (abfd, type, datasz);
176
0
        elf_has_no_copy_on_protected (abfd) = true;
177
0
        prop->pr_kind = property_number;
178
0
        goto next;
179
180
0
      default:
181
0
        if ((type >= GNU_PROPERTY_UINT32_AND_LO
182
0
       && type <= GNU_PROPERTY_UINT32_AND_HI)
183
0
      || (type >= GNU_PROPERTY_UINT32_OR_LO
184
0
          && type <= GNU_PROPERTY_UINT32_OR_HI))
185
0
    {
186
0
      if (datasz != 4)
187
0
        {
188
0
          _bfd_error_handler
189
0
      (_("error: %pB: <corrupt property (0x%x) size: 0x%x>"),
190
0
       abfd, type, datasz);
191
          /* Clear all properties.  */
192
0
          elf_properties (abfd) = NULL;
193
0
          return false;
194
0
        }
195
0
      prop = _bfd_elf_get_property (abfd, type, datasz);
196
0
      prop->u.number |= bfd_h_get_32 (abfd, ptr);
197
0
      prop->pr_kind = property_number;
198
0
      if (type == GNU_PROPERTY_1_NEEDED
199
0
          && ((prop->u.number
200
0
         & GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS)
201
0
        != 0))
202
0
        {
203
0
          elf_has_indirect_extern_access (abfd) = true;
204
          /* GNU_PROPERTY_NO_COPY_ON_PROTECTED is implied.  */
205
0
          elf_has_no_copy_on_protected (abfd) = true;
206
0
        }
207
0
      goto next;
208
0
    }
209
0
        break;
210
0
      }
211
0
  }
212
213
0
      _bfd_error_handler
214
0
  (_("warning: %pB: unsupported GNU_PROPERTY_TYPE (%ld) type: 0x%x"),
215
0
   abfd, note->type, type);
216
217
0
    next:
218
0
      ptr += (datasz + (align_size - 1)) & ~ (align_size - 1);
219
0
    }
220
221
0
  return true;
222
0
}
223
224
/* Merge GNU property BPROP with APROP.  If APROP isn't NULL, return TRUE
225
   if APROP is updated.  Otherwise, return TRUE if BPROP should be merged
226
   with ABFD.  */
227
228
static bool
229
elf_merge_gnu_properties (struct bfd_link_info *info, bfd *abfd, bfd *bbfd,
230
        elf_property *aprop, elf_property *bprop)
231
0
{
232
0
  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
233
0
  unsigned int pr_type = aprop != NULL ? aprop->pr_type : bprop->pr_type;
234
0
  unsigned int number;
235
0
  bool updated;
236
237
0
  if (bed->merge_gnu_properties != NULL
238
0
      && pr_type >= GNU_PROPERTY_LOPROC
239
0
      && pr_type < GNU_PROPERTY_LOUSER)
240
0
    return bed->merge_gnu_properties (info, abfd, bbfd, aprop, bprop);
241
242
0
  switch (pr_type)
243
0
    {
244
0
    case GNU_PROPERTY_STACK_SIZE:
245
0
      if (aprop != NULL && bprop != NULL)
246
0
  {
247
0
    if (bprop->u.number > aprop->u.number)
248
0
      {
249
0
        aprop->u.number = bprop->u.number;
250
0
        return true;
251
0
      }
252
0
    break;
253
0
  }
254
      /* FALLTHROUGH */
255
256
0
    case GNU_PROPERTY_NO_COPY_ON_PROTECTED:
257
      /* Return TRUE if APROP is NULL to indicate that BPROP should
258
   be added to ABFD.  */
259
0
      return aprop == NULL;
260
261
0
    default:
262
0
      updated = false;
263
0
      if (pr_type >= GNU_PROPERTY_UINT32_OR_LO
264
0
    && pr_type <= GNU_PROPERTY_UINT32_OR_HI)
265
0
  {
266
0
    if (aprop != NULL && bprop != NULL)
267
0
      {
268
0
        number = aprop->u.number;
269
0
        aprop->u.number = number | bprop->u.number;
270
        /* Remove the property if all bits are empty.  */
271
0
        if (aprop->u.number == 0)
272
0
    {
273
0
      aprop->pr_kind = property_remove;
274
0
      updated = true;
275
0
    }
276
0
        else
277
0
    updated = number != (unsigned int) aprop->u.number;
278
0
      }
279
0
    else
280
0
      {
281
        /* Only one of APROP and BPROP can be NULL.  */
282
0
        if (aprop != NULL)
283
0
    {
284
0
      if (aprop->u.number == 0)
285
0
        {
286
          /* Remove APROP if all bits are empty.  */
287
0
          aprop->pr_kind = property_remove;
288
0
          updated = true;
289
0
        }
290
0
    }
291
0
        else
292
0
    {
293
      /* Return TRUE if APROP is NULL and all bits of BPROP
294
         aren't empty to indicate that BPROP should be added
295
         to ABFD.  */
296
0
      updated = bprop->u.number != 0;
297
0
    }
298
0
      }
299
0
    return updated;
300
0
  }
301
0
      else if (pr_type >= GNU_PROPERTY_UINT32_AND_LO
302
0
         && pr_type <= GNU_PROPERTY_UINT32_AND_HI)
303
0
  {
304
    /* Only one of APROP and BPROP can be NULL:
305
       1. APROP & BPROP when both APROP and BPROP aren't NULL.
306
       2. If APROP is NULL, remove x86 feature.
307
       3. Otherwise, do nothing.
308
       */
309
0
    if (aprop != NULL && bprop != NULL)
310
0
      {
311
0
        number = aprop->u.number;
312
0
        aprop->u.number = number & bprop->u.number;
313
0
        updated = number != (unsigned int) aprop->u.number;
314
        /* Remove the property if all feature bits are cleared.  */
315
0
        if (aprop->u.number == 0)
316
0
    aprop->pr_kind = property_remove;
317
0
      }
318
0
    else
319
0
      {
320
        /* There should be no AND properties since some input
321
           doesn't have them.   */
322
0
        if (aprop != NULL)
323
0
    {
324
0
      aprop->pr_kind = property_remove;
325
0
      updated = true;
326
0
    }
327
0
      }
328
0
    return updated;
329
0
  }
330
331
      /* Never should happen.  */
332
0
      abort ();
333
0
    }
334
335
0
  return false;
336
0
}
337
338
/* Return the property of TYPE on *LISTP and remove it from *LISTP if RM is
339
   true.  Return NULL if not found.  */
340
341
static elf_property *
342
elf_find_and_remove_property (elf_property_list **listp,
343
            unsigned int type, bool rm)
344
0
{
345
0
  elf_property_list *list;
346
347
0
  for (list = *listp; list; list = list->next)
348
0
    {
349
0
      if (type == list->property.pr_type)
350
0
  {
351
    /* Remove this property.  */
352
0
    if (rm)
353
0
      *listp = list->next;
354
0
    return &list->property;
355
0
  }
356
0
      else if (type < list->property.pr_type)
357
0
  break;
358
0
      listp = &list->next;
359
0
    }
360
361
0
  return NULL;
362
0
}
363
364
/* Merge GNU property list *LISTP in ABFD with FIRST_PBFD.  */
365
366
static void
367
elf_merge_gnu_property_list (struct bfd_link_info *info, bfd *first_pbfd,
368
           bfd *abfd, elf_property_list **listp)
369
0
{
370
0
  elf_property_list *p, **lastp;
371
0
  elf_property *pr;
372
0
  bool number_p;
373
0
  bfd_vma number = 0;
374
375
  /* Merge each GNU property in FIRST_PBFD with the one on *LISTP.  */
376
0
  lastp = &elf_properties (first_pbfd);
377
0
  for (p = *lastp; p; p = p->next)
378
0
    if (p->property.pr_kind != property_remove)
379
0
      {
380
0
  if (p->property.pr_kind == property_number)
381
0
    {
382
0
      number_p = true;
383
0
      number = p->property.u.number;
384
0
    }
385
0
  else
386
0
    number_p = false;
387
0
  pr = elf_find_and_remove_property (listp, p->property.pr_type,
388
0
             true);
389
  /* Pass NULL to elf_merge_gnu_properties for the property which
390
     isn't on *LISTP.  */
391
0
  elf_merge_gnu_properties (info, first_pbfd, abfd, &p->property, pr);
392
0
  if (p->property.pr_kind == property_remove)
393
0
    {
394
0
      if (info->has_map_file)
395
0
        {
396
0
    if (number_p)
397
0
      {
398
0
        if (pr != NULL)
399
0
          info->callbacks->minfo
400
0
      (_("Removed property %W to merge %pB (0x%v) "
401
0
         "and %pB (0x%v)\n"),
402
0
       (bfd_vma) p->property.pr_type, first_pbfd,
403
0
       number, abfd, pr->u.number);
404
0
        else
405
0
          info->callbacks->minfo
406
0
      (_("Removed property %W to merge %pB (0x%v) "
407
0
         "and %pB (not found)\n"),
408
0
       (bfd_vma) p->property.pr_type, first_pbfd,
409
0
       number, abfd);
410
0
      }
411
0
    else
412
0
      {
413
0
        if (pr != NULL)
414
0
          info->callbacks->minfo
415
0
      (_("Removed property %W to merge %pB and %pB\n"),
416
0
       (bfd_vma) p->property.pr_type, first_pbfd, abfd);
417
0
        else
418
0
          info->callbacks->minfo
419
0
      (_("Removed property %W to merge %pB and %pB "
420
0
         "(not found)\n"),
421
0
       (bfd_vma) p->property.pr_type, first_pbfd, abfd);
422
0
      }
423
0
        }
424
425
      /* Remove this property.  */
426
0
      *lastp = p->next;
427
0
      continue;
428
0
    }
429
0
  else if (number_p)
430
0
    {
431
0
      if (pr != NULL)
432
0
        {
433
0
    if (p->property.u.number != number
434
0
        || p->property.u.number != pr->u.number)
435
0
      info->callbacks->minfo
436
0
        (_("Updated property %W (0x%v) to merge %pB (0x%v) "
437
0
           "and %pB (0x%v)\n"),
438
0
         (bfd_vma) p->property.pr_type, p->property.u.number,
439
0
         first_pbfd, number, abfd, pr->u.number);
440
0
        }
441
0
      else
442
0
        {
443
0
    if (p->property.u.number != number)
444
0
      info->callbacks->minfo
445
0
        (_("Updated property %W (%v) to merge %pB (0x%v) "
446
0
           "and %pB (not found)\n"),
447
0
         (bfd_vma) p->property.pr_type, p->property.u.number,
448
0
         first_pbfd, number, abfd);
449
0
        }
450
0
    }
451
0
  lastp = &p->next;
452
0
      }
453
454
  /* Merge the remaining properties on *LISTP with FIRST_PBFD.  */
455
0
  for (p = *listp; p != NULL; p = p->next)
456
0
    {
457
0
      if (p->property.pr_kind == property_number)
458
0
  {
459
0
    number_p = true;
460
0
    number = p->property.u.number;
461
0
  }
462
0
      else
463
0
  number_p = false;
464
465
0
      if (elf_merge_gnu_properties (info, first_pbfd, abfd, NULL, &p->property))
466
0
  {
467
0
    if (p->property.pr_type == GNU_PROPERTY_NO_COPY_ON_PROTECTED)
468
0
      elf_has_no_copy_on_protected (first_pbfd) = true;
469
470
0
    pr = _bfd_elf_get_property (first_pbfd, p->property.pr_type,
471
0
              p->property.pr_datasz);
472
    /* It must be a new property.  */
473
0
    if (pr->pr_kind != property_unknown)
474
0
      abort ();
475
    /* Add a new property.  */
476
0
    *pr = p->property;
477
0
  }
478
0
      else
479
0
  {
480
0
    pr = elf_find_and_remove_property (&elf_properties (first_pbfd),
481
0
               p->property.pr_type,
482
0
               false);
483
0
    if (pr == NULL)
484
0
      {
485
0
        if (number_p)
486
0
    info->callbacks->minfo
487
0
      (_("Removed property %W to merge %pB (not found) and "
488
0
         "%pB (0x%v)\n"),
489
0
       (bfd_vma) p->property.pr_type, first_pbfd, abfd,
490
0
       number);
491
0
        else
492
0
    info->callbacks->minfo
493
0
      (_("Removed property %W to merge %pB and %pB\n"),
494
0
       (bfd_vma) p->property.pr_type, first_pbfd, abfd);
495
0
      }
496
0
    else if (pr->pr_kind != property_remove)
497
0
      abort ();
498
0
  }
499
0
    }
500
0
}
501
502
/* Get GNU property section size.  */
503
504
static bfd_size_type
505
elf_get_gnu_property_section_size (elf_property_list *list,
506
           unsigned int align_size)
507
0
{
508
0
  bfd_size_type size;
509
0
  unsigned int descsz;
510
511
  /* Compute the output section size.  */
512
0
  descsz = offsetof (Elf_External_Note, name[sizeof "GNU"]);
513
0
  descsz = (descsz + 3) & -(unsigned int) 4;
514
0
  size = descsz;
515
0
  for (; list != NULL; list = list->next)
516
0
    {
517
0
      unsigned int datasz;
518
      /* Check if this property should be skipped.  */
519
0
      if (list->property.pr_kind == property_remove)
520
0
  continue;
521
      /* There are 4 byte type + 4 byte datasz for each property.  */
522
0
      if (list->property.pr_type == GNU_PROPERTY_STACK_SIZE)
523
0
  datasz = align_size;
524
0
      else
525
0
  datasz = list->property.pr_datasz;
526
0
      size += 4 + 4 + datasz;
527
      /* Align each property.  */
528
0
      size = (size + (align_size - 1)) & ~(align_size - 1);
529
0
    }
530
531
0
  return size;
532
0
}
533
534
/* Write GNU properties.  */
535
536
static void
537
elf_write_gnu_properties (struct bfd_link_info *info,
538
        bfd *abfd, bfd_byte *contents,
539
        elf_property_list *list, unsigned int size,
540
        unsigned int align_size)
541
0
{
542
0
  unsigned int descsz;
543
0
  unsigned int datasz;
544
0
  Elf_External_Note *e_note;
545
546
0
  e_note = (Elf_External_Note *) contents;
547
0
  descsz = offsetof (Elf_External_Note, name[sizeof "GNU"]);
548
0
  descsz = (descsz + 3) & -(unsigned int) 4;
549
0
  bfd_h_put_32 (abfd, sizeof "GNU", &e_note->namesz);
550
0
  bfd_h_put_32 (abfd, size - descsz, &e_note->descsz);
551
0
  bfd_h_put_32 (abfd, NT_GNU_PROPERTY_TYPE_0, &e_note->type);
552
0
  memcpy (e_note->name, "GNU", sizeof "GNU");
553
554
0
  size = descsz;
555
0
  for (; list != NULL; list = list->next)
556
0
    {
557
      /* Check if this property should be skipped.  */
558
0
      if (list->property.pr_kind == property_remove)
559
0
  continue;
560
      /* There are 4 byte type + 4 byte datasz for each property.  */
561
0
      if (list->property.pr_type == GNU_PROPERTY_STACK_SIZE)
562
0
  datasz = align_size;
563
0
      else
564
0
  datasz = list->property.pr_datasz;
565
0
      bfd_h_put_32 (abfd, list->property.pr_type, contents + size);
566
0
      bfd_h_put_32 (abfd, datasz, contents + size + 4);
567
0
      size += 4 + 4;
568
569
      /* Write out property value.  */
570
0
      switch (list->property.pr_kind)
571
0
  {
572
0
  case property_number:
573
0
    switch (datasz)
574
0
      {
575
0
      default:
576
        /* Never should happen.  */
577
0
        abort ();
578
579
0
      case 0:
580
0
        break;
581
582
0
      case 4:
583
        /* Save the pointer to GNU_PROPERTY_1_NEEDED so that it
584
     can be updated later if needed.  */
585
0
        if (info != NULL
586
0
      && list->property.pr_type == GNU_PROPERTY_1_NEEDED)
587
0
    info->needed_1_p = contents + size;
588
0
        bfd_h_put_32 (abfd, list->property.u.number,
589
0
          contents + size);
590
0
        break;
591
592
0
      case 8:
593
0
        bfd_h_put_64 (abfd, list->property.u.number,
594
0
          contents + size);
595
0
        break;
596
0
      }
597
0
    break;
598
599
0
  default:
600
    /* Never should happen.  */
601
0
    abort ();
602
0
  }
603
0
      size += datasz;
604
605
      /* Align each property.  */
606
0
      size = (size + (align_size - 1)) & ~ (align_size - 1);
607
0
    }
608
0
}
609
610
/* Set up GNU properties.  Return the first relocatable ELF input with
611
   GNU properties if found.  Otherwise, return NULL.  */
612
613
bfd *
614
_bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info)
615
0
{
616
0
  bfd *abfd, *first_pbfd = NULL, *elf_bfd = NULL;
617
0
  elf_property_list *list;
618
0
  asection *sec;
619
0
  bool has_properties = false;
620
0
  const struct elf_backend_data *bed
621
0
    = get_elf_backend_data (info->output_bfd);
622
0
  unsigned int elfclass = bed->s->elfclass;
623
0
  int elf_machine_code = bed->elf_machine_code;
624
0
  elf_property *p;
625
626
  /* Find the first relocatable ELF input with GNU properties.  */
627
0
  for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)
628
0
    if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
629
0
  && (abfd->flags & DYNAMIC) == 0
630
0
  && (elf_machine_code
631
0
      == get_elf_backend_data (abfd)->elf_machine_code)
632
0
  && (elfclass == get_elf_backend_data (abfd)->s->elfclass))
633
0
      {
634
  /* Ignore GNU properties from ELF objects with different machine
635
     code or class.  Also skip objects without a GNU_PROPERTY note
636
     section.  */
637
0
  elf_bfd = abfd;
638
639
0
  if (elf_properties (abfd) != NULL)
640
0
    {
641
0
      has_properties = true;
642
643
0
      if (bfd_get_section_by_name (abfd,
644
0
           NOTE_GNU_PROPERTY_SECTION_NAME)
645
0
    != NULL)
646
0
        {
647
    /* Keep .note.gnu.property section in FIRST_PBFD.  */
648
0
    first_pbfd = abfd;
649
0
    break;
650
0
        }
651
0
    }
652
0
      }
653
654
0
  if (info->indirect_extern_access > 0 && elf_bfd != NULL)
655
0
    {
656
      /* Support -z indirect-extern-access.  */
657
0
      if (first_pbfd == NULL)
658
0
  {
659
0
    sec = bfd_make_section_with_flags (elf_bfd,
660
0
               NOTE_GNU_PROPERTY_SECTION_NAME,
661
0
               (SEC_ALLOC
662
0
                | SEC_LOAD
663
0
                | SEC_IN_MEMORY
664
0
                | SEC_READONLY
665
0
                | SEC_HAS_CONTENTS
666
0
                | SEC_DATA));
667
0
    if (sec == NULL)
668
0
      info->callbacks->einfo (_("%F%P: failed to create GNU property section\n"));
669
670
0
    if (!bfd_set_section_alignment (sec,
671
0
            elfclass == ELFCLASS64 ? 3 : 2))
672
0
      info->callbacks->einfo (_("%F%pA: failed to align section\n"),
673
0
            sec);
674
675
0
    elf_section_type (sec) = SHT_NOTE;
676
0
    first_pbfd = elf_bfd;
677
0
    has_properties = true;
678
0
  }
679
680
0
      p = _bfd_elf_get_property (first_pbfd, GNU_PROPERTY_1_NEEDED, 4);
681
0
      if (p->pr_kind == property_unknown)
682
0
  {
683
    /* Create GNU_PROPERTY_1_NEEDED.  */
684
0
    p->u.number
685
0
      = GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS;
686
0
    p->pr_kind = property_number;
687
0
  }
688
0
      else
689
0
  p->u.number
690
0
    |= GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS;
691
0
    }
692
693
  /* Do nothing if there is no .note.gnu.property section.  */
694
0
  if (!has_properties)
695
0
    return NULL;
696
697
  /* Merge .note.gnu.property sections.  */
698
0
  info->callbacks->minfo (_("\n"));
699
0
  info->callbacks->minfo (_("Merging program properties\n"));
700
0
  info->callbacks->minfo (_("\n"));
701
702
0
  for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)
703
0
    if (abfd != first_pbfd
704
0
  && (abfd->flags & (DYNAMIC | BFD_PLUGIN | BFD_LINKER_CREATED)) == 0)
705
0
      {
706
0
  elf_property_list *null_ptr = NULL;
707
0
  elf_property_list **listp = &null_ptr;
708
709
  /* Merge .note.gnu.property section in relocatable ELF input.  */
710
0
  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
711
0
    {
712
0
      list = elf_properties (abfd);
713
714
      /* Ignore GNU properties from ELF objects with different
715
         machine code.  */
716
0
      if (list != NULL
717
0
    && (elf_machine_code
718
0
        == get_elf_backend_data (abfd)->elf_machine_code))
719
0
        listp = &elf_properties (abfd);
720
0
    }
721
0
  else
722
0
    list = NULL;
723
724
  /* Merge properties with FIRST_PBFD.  FIRST_PBFD can be NULL
725
     when all properties are from ELF objects with different
726
     machine code or class.  */
727
0
  if (first_pbfd != NULL)
728
0
    elf_merge_gnu_property_list (info, first_pbfd, abfd, listp);
729
730
0
  if (list != NULL)
731
0
    {
732
      /* Discard the .note.gnu.property section in this bfd.  */
733
0
      sec = bfd_get_section_by_name (abfd,
734
0
             NOTE_GNU_PROPERTY_SECTION_NAME);
735
0
      if (sec != NULL)
736
0
        sec->output_section = bfd_abs_section_ptr;
737
0
    }
738
0
      }
739
740
  /* Rewrite .note.gnu.property section so that GNU properties are
741
     always sorted by type even if input GNU properties aren't sorted.  */
742
0
  if (first_pbfd != NULL)
743
0
    {
744
0
      bfd_size_type size;
745
0
      bfd_byte *contents;
746
0
      unsigned int align_size = elfclass == ELFCLASS64 ? 8 : 4;
747
748
0
      sec = bfd_get_section_by_name (first_pbfd,
749
0
             NOTE_GNU_PROPERTY_SECTION_NAME);
750
0
      BFD_ASSERT (sec != NULL);
751
752
      /* Update stack size in .note.gnu.property with -z stack-size=N
753
   if N > 0.  */
754
0
      if (info->stacksize > 0)
755
0
  {
756
0
    bfd_vma stacksize = info->stacksize;
757
758
0
    p = _bfd_elf_get_property (first_pbfd, GNU_PROPERTY_STACK_SIZE,
759
0
             align_size);
760
0
    if (p->pr_kind == property_unknown)
761
0
      {
762
        /* Create GNU_PROPERTY_STACK_SIZE.  */
763
0
        p->u.number = stacksize;
764
0
        p->pr_kind = property_number;
765
0
      }
766
0
    else if (stacksize > p->u.number)
767
0
      p->u.number = stacksize;
768
0
  }
769
0
      else if (elf_properties (first_pbfd) == NULL)
770
0
  {
771
    /* Discard .note.gnu.property section if all properties have
772
       been removed.  */
773
0
    sec->output_section = bfd_abs_section_ptr;
774
0
    return NULL;
775
0
  }
776
777
      /* Fix up GNU properties.  */
778
0
      if (bed->fixup_gnu_properties)
779
0
  bed->fixup_gnu_properties (info, &elf_properties (first_pbfd));
780
781
0
      if (elf_properties (first_pbfd) == NULL)
782
0
  {
783
    /* Discard .note.gnu.property section if all properties have
784
       been removed.  */
785
0
    sec->output_section = bfd_abs_section_ptr;
786
0
    return NULL;
787
0
  }
788
789
      /* Compute the section size.  */
790
0
      list = elf_properties (first_pbfd);
791
0
      size = elf_get_gnu_property_section_size (list, align_size);
792
793
      /* Update .note.gnu.property section now.  */
794
0
      sec->size = size;
795
0
      contents = (bfd_byte *) bfd_zalloc (first_pbfd, size);
796
797
0
      if (info->indirect_extern_access <= 0)
798
0
  {
799
    /* Get GNU_PROPERTY_1_NEEDED properties.  */
800
0
    p = elf_find_and_remove_property (&elf_properties (first_pbfd),
801
0
              GNU_PROPERTY_1_NEEDED, false);
802
0
    if (p != NULL)
803
0
      {
804
0
        if (info->indirect_extern_access < 0)
805
0
    {
806
      /* Set indirect_extern_access to 1 to indicate that
807
         it is turned on by input properties.  */
808
0
      if ((p->u.number
809
0
           & GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS)
810
0
          != 0)
811
0
        info->indirect_extern_access = 1;
812
0
    }
813
0
        else
814
    /* Turn off indirect external access.  */
815
0
    p->u.number
816
0
      &= ~GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS;
817
0
      }
818
0
  }
819
820
0
      elf_write_gnu_properties (info, first_pbfd, contents, list, size,
821
0
        align_size);
822
823
      /* Cache the section contents for elf_link_input_bfd.  */
824
0
      elf_section_data (sec)->this_hdr.contents = contents;
825
826
      /* If GNU_PROPERTY_NO_COPY_ON_PROTECTED is set, protected data
827
   symbol is defined in the shared object.  */
828
0
      if (elf_has_no_copy_on_protected (first_pbfd))
829
0
  info->extern_protected_data = false;
830
831
0
      if (info->indirect_extern_access > 0)
832
0
  {
833
    /* For indirect external access, don't generate copy
834
       relocations.  NB: Set to nocopyreloc to 2 to indicate
835
       that it is implied by indirect_extern_access.  */
836
0
    info->nocopyreloc = 2;
837
0
    info->extern_protected_data = false;
838
0
  }
839
0
    }
840
841
0
  return first_pbfd;
842
0
}
843
844
/* Convert GNU property size.  */
845
846
bfd_size_type
847
_bfd_elf_convert_gnu_property_size (bfd *ibfd, bfd *obfd)
848
0
{
849
0
  unsigned int align_size;
850
0
  const struct elf_backend_data *bed;
851
0
  elf_property_list *list = elf_properties (ibfd);
852
853
0
  bed = get_elf_backend_data (obfd);
854
0
  align_size = bed->s->elfclass == ELFCLASS64 ? 8 : 4;
855
856
  /* Get the output .note.gnu.property section size.  */
857
0
  return elf_get_gnu_property_section_size (list, align_size);
858
0
}
859
860
/* Convert GNU properties.  */
861
862
bool
863
_bfd_elf_convert_gnu_properties (bfd *ibfd, asection *isec,
864
         bfd *obfd, bfd_byte **ptr,
865
         bfd_size_type *ptr_size)
866
0
{
867
0
  unsigned int size;
868
0
  bfd_byte *contents;
869
0
  unsigned int align_shift;
870
0
  const struct elf_backend_data *bed;
871
0
  elf_property_list *list = elf_properties (ibfd);
872
873
0
  bed = get_elf_backend_data (obfd);
874
0
  align_shift = bed->s->elfclass == ELFCLASS64 ? 3 : 2;
875
876
  /* Get the output .note.gnu.property section size.  */
877
0
  size = bfd_section_size (isec->output_section);
878
879
  /* Update the output .note.gnu.property section alignment.  */
880
0
  bfd_set_section_alignment (isec->output_section, align_shift);
881
882
0
  if (size > bfd_section_size (isec))
883
0
    {
884
0
      contents = (bfd_byte *) bfd_malloc (size);
885
0
      if (contents == NULL)
886
0
  return false;
887
0
      free (*ptr);
888
0
      *ptr = contents;
889
0
    }
890
0
  else
891
0
    contents = *ptr;
892
893
0
  *ptr_size = size;
894
895
  /* Generate the output .note.gnu.property section.  */
896
0
  elf_write_gnu_properties (NULL, ibfd, contents, list, size,
897
0
          1 << align_shift);
898
899
0
  return true;
900
0
}