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