1 /* ELF program property support.
2 Copyright (C) 2017-2019 Free Software Foundation, Inc.
4 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
21 /* GNU program property draft is at:
23 https://github.com/hjl-tools/linux-abi/wiki/property-draft.pdf
31 /* Get a property, allocate a new one if needed. */
34 _bfd_elf_get_property (bfd *abfd, unsigned int type, unsigned int datasz)
36 elf_property_list *p, **lastp;
38 if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
40 /* Never should happen. */
44 /* Keep the property list in order of type. */
45 lastp = &elf_properties (abfd);
46 for (p = *lastp; p; p = p->next)
48 /* Reuse the existing entry. */
49 if (type == p->property.pr_type)
51 if (datasz > p->property.pr_datasz)
53 /* This can happen when mixing 32-bit and 64-bit objects. */
54 p->property.pr_datasz = datasz;
58 else if (type < p->property.pr_type)
62 p = (elf_property_list *) bfd_alloc (abfd, sizeof (*p));
65 _bfd_error_handler (_("%pB: out of memory in _bfd_elf_get_property"),
69 memset (p, 0, sizeof (*p));
70 p->property.pr_type = type;
71 p->property.pr_datasz = datasz;
72 p->property.filename = abfd->filename;
78 /* Parse GNU properties. */
81 _bfd_elf_parse_gnu_properties (bfd *abfd, Elf_Internal_Note *note)
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;
88 if (note->descsz < 8 || (note->descsz % align_size) != 0)
92 (_("warning: %pB: corrupt GNU_PROPERTY_TYPE (%ld) size: %#lx"),
93 abfd, note->type, note->descsz);
97 while (ptr != ptr_end)
103 if ((size_t) (ptr_end - ptr) < 8)
106 type = bfd_h_get_32 (abfd, ptr);
107 datasz = bfd_h_get_32 (abfd, ptr + 4);
110 if (datasz > (size_t) (ptr_end - ptr))
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;
120 if (type >= GNU_PROPERTY_LOPROC)
122 if (bed->elf_machine_code == EM_NONE)
124 /* Ignore processor-specific properties with generic ELF
125 target vector. They should be handled by the matching
126 ELF target vector. */
129 else if (type < GNU_PROPERTY_LOUSER
130 && bed->parse_gnu_properties)
132 enum elf_property_kind kind
133 = bed->parse_gnu_properties (abfd, type, ptr, datasz);
134 if (kind == property_corrupt)
136 /* Clear all properties. */
137 elf_properties (abfd) = NULL;
140 else if (kind != property_ignored)
148 case GNU_PROPERTY_STACK_SIZE:
149 if (datasz != align_size)
152 (_("warning: %pB: corrupt stack size: 0x%x"),
154 /* Clear all properties. */
155 elf_properties (abfd) = NULL;
158 prop = _bfd_elf_get_property (abfd, type, datasz);
160 prop->u.number = bfd_h_get_64 (abfd, ptr);
162 prop->u.number = bfd_h_get_32 (abfd, ptr);
163 prop->pr_kind = property_number;
166 case GNU_PROPERTY_NO_COPY_ON_PROTECTED:
170 (_("warning: %pB: corrupt no copy on protected size: 0x%x"),
172 /* Clear all properties. */
173 elf_properties (abfd) = NULL;
176 prop = _bfd_elf_get_property (abfd, type, datasz);
177 elf_has_no_copy_on_protected (abfd) = TRUE;
178 prop->pr_kind = property_number;
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)))
186 (_("warning: %B: corrupt compiler flags: 0x%x\n"),
188 /* Clear all properties. */
189 elf_properties (abfd) = NULL;
192 prop = _bfd_elf_get_property (abfd, type, datasz);
194 prop->u.number = bfd_h_get_64 (abfd, ptr);
196 prop->u.number = bfd_h_get_32 (abfd, ptr);
198 prop->pr_kind = property_number;
207 (_("warning: %pB: unsupported GNU_PROPERTY_TYPE (%ld) type: 0x%x"),
208 abfd, note->type, type);
211 ptr += (datasz + (align_size - 1)) & ~ (align_size - 1);
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,
221 bfd_vma validation_bit_flag,
222 bfd_vma validation_bit)
224 if ((anum & validation_bit_flag) && (bnum & validation_bit_flag)
225 && ((anum & validation_bit) != (bnum & validation_bit)))
233 elf_validate_compiler_flags_properties (elf_property *aprop,
236 bfd_boolean is_flag_set;
238 /* Sanity check to verify correct usage. */
242 if (aprop->pr_type != bprop->pr_type)
245 BFD_ASSERT(aprop->pr_type == GNU_PROPERTY_COMPILER_FLAGS);
247 /* Return TRUE if compiler flags are identical (likely?). */
248 if (aprop->u.number == bprop->u.number)
251 if (!elf_gnu_property_validate_flag(aprop->u.number,
253 GNU_PROPERTY_SANITIZE_VALIDATION,
254 GNU_PROPERTY_SANITIZE_ADDRESS))
256 is_flag_set = bprop->u.number & GNU_PROPERTY_SANITIZE_ADDRESS;
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");
264 if (!elf_gnu_property_validate_flag(aprop->u.number,
266 GNU_PROPERTY_USECXX_VALIDATION,
267 GNU_PROPERTY_USECXX11_ABI))
269 is_flag_set = bprop->u.number & GNU_PROPERTY_USECXX11_ABI;
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");
281 /* Merge bprop into aprop according compiler-flags properties, return TRUE if */
282 /* aprop is updated. */
284 elf_merge_gnu_properties_compiler_flags (elf_property *aprop,
287 bfd_boolean is_updated = FALSE;
288 /* Likely that objects have the same properties. */
289 if (aprop->u.number == bprop->u.number) {
293 /* Validation bit + no-validation bit = validation bit. */
294 if ((aprop->u.number ^ bprop->u.number) & GNU_PROPERTY_SANITIZE_VALIDATION)
296 aprop->u.number |= GNU_PROPERTY_SANITIZE_VALIDATION;
299 /* Sanitized object + unsanitized results = sanitized final object. */
300 if ((aprop->u.number ^ bprop->u.number) & GNU_PROPERTY_SANITIZE_ADDRESS)
302 aprop->u.number |= GNU_PROPERTY_SANITIZE_ADDRESS;
306 if ((aprop->u.number ^ bprop->u.number) & GNU_PROPERTY_USECXX_VALIDATION)
308 aprop->u.number |= GNU_PROPERTY_USECXX_VALIDATION;
312 if ((aprop->u.number ^ bprop->u.number) & GNU_PROPERTY_USECXX11_ABI)
314 aprop->u.number |= GNU_PROPERTY_USECXX11_ABI;
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
326 elf_merge_gnu_properties (struct bfd_link_info *info, bfd *abfd, bfd *bbfd,
327 elf_property *aprop, elf_property *bprop)
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;
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);
339 case GNU_PROPERTY_STACK_SIZE:
340 if (aprop != NULL && bprop != NULL)
342 if (bprop->u.number > aprop->u.number)
344 aprop->u.number = bprop->u.number;
351 case GNU_PROPERTY_NO_COPY_ON_PROTECTED:
352 /* Return TRUE if APROP is NULL to indicate that BPROP should
354 return aprop == NULL;
357 case GNU_PROPERTY_COMPILER_FLAGS:
359 bfd_boolean is_updated;
360 if (aprop != NULL && bprop != NULL)
362 #ifdef ENABLE_ANNOBIN_VERIFICATION
363 if (!elf_validate_compiler_flags_properties (aprop, bprop))
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);
373 is_updated = elf_merge_gnu_properties_compiler_flags (aprop, bprop);
378 /* aprop or bprop is NULL, warn for missing GNU_PROPERTY_COMPILER_FLAGS.
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)
386 (_("WARNING: not found (generated by annobin gcc plugin), "
387 "runtime verification may be incomplete"),
388 NOTE_GNU_PROPERTY_SECTION_NAME); */
395 /* Never should happen. */
402 /* Return the property of TYPE on *LISTP and remove it from *LISTP if RM is
403 true. Return NULL if not found. */
405 static elf_property *
406 elf_find_and_remove_property (elf_property_list **listp,
407 unsigned int type, bfd_boolean rm)
409 elf_property_list *list;
411 for (list = *listp; list; list = list->next)
413 if (type == list->property.pr_type)
415 /* Remove this property. */
418 return &list->property;
420 else if (type < list->property.pr_type)
428 /* Merge GNU property list *LISTP in ABFD with FIRST_PBFD. */
431 elf_merge_gnu_property_list (struct bfd_link_info *info, bfd *first_pbfd,
432 bfd *abfd, elf_property_list **listp)
434 elf_property_list *p, **lastp;
436 bfd_boolean number_p;
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)
444 if (p->property.pr_kind == property_number)
447 number = p->property.u.number;
451 pr = elf_find_and_remove_property (listp, p->property.pr_type,
453 /* Pass NULL to elf_merge_gnu_properties for the property which
455 elf_merge_gnu_properties (info, first_pbfd, abfd, &p->property, pr);
456 if (p->property.pr_kind == property_remove)
458 if (info->has_map_file)
463 info->callbacks->minfo
464 (_("Removed property %W to merge %pB (0x%v) "
466 (bfd_vma) p->property.pr_type, first_pbfd,
467 number, abfd, pr->u.number);
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,
478 info->callbacks->minfo
479 (_("Removed property %W to merge %pB and %pB\n"),
480 (bfd_vma) p->property.pr_type, first_pbfd, abfd);
482 info->callbacks->minfo
483 (_("Removed property %W to merge %pB and %pB "
485 (bfd_vma) p->property.pr_type, first_pbfd, abfd);
489 /* Remove this property. */
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) "
502 (bfd_vma) p->property.pr_type, p->property.u.number,
503 first_pbfd, number, abfd, pr->u.number);
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);
518 /* Merge the remaining properties on *LISTP with FIRST_PBFD. */
519 for (p = *listp; p != NULL; p = p->next)
521 if (p->property.pr_kind == property_number)
524 number = p->property.u.number;
529 if (elf_merge_gnu_properties (info, first_pbfd, abfd, NULL, &p->property))
531 if (p->property.pr_type == GNU_PROPERTY_NO_COPY_ON_PROTECTED)
532 elf_has_no_copy_on_protected (first_pbfd) = TRUE;
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)
539 /* Add a new property. */
544 pr = elf_find_and_remove_property (&elf_properties (first_pbfd),
550 info->callbacks->minfo
551 (_("Removed property %W to merge %pB (not found) and "
553 (bfd_vma) p->property.pr_type, first_pbfd, abfd,
556 info->callbacks->minfo
557 (_("Removed property %W to merge %pB and %pB\n"),
558 (bfd_vma) p->property.pr_type, first_pbfd, abfd);
560 else if (pr->pr_kind != property_remove)
566 /* Get GNU property section size. */
569 elf_get_gnu_property_section_size (elf_property_list *list,
570 unsigned int align_size)
575 /* Compute the output section size. */
576 descsz = offsetof (Elf_External_Note, name[sizeof "GNU"]);
577 descsz = (descsz + 3) & -(unsigned int) 4;
579 for (; list != NULL; list = list->next)
582 /* Check if this property should be skipped. */
583 if (list->property.pr_kind == property_remove)
585 /* There are 4 byte type + 4 byte datasz for each property. */
586 if (list->property.pr_type == GNU_PROPERTY_STACK_SIZE)
589 datasz = list->property.pr_datasz;
590 size += 4 + 4 + datasz;
591 /* Align each property. */
592 size = (size + (align_size - 1)) & ~(align_size - 1);
598 /* Write GNU properties. */
601 elf_write_gnu_properties (bfd *abfd, bfd_byte *contents,
602 elf_property_list *list, unsigned int size,
603 unsigned int align_size)
607 Elf_External_Note *e_note;
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");
618 for (; list != NULL; list = list->next)
620 /* Check if this property should be skipped. */
621 if (list->property.pr_kind == property_remove)
623 /* There are 4 byte type + 4 byte datasz for each property. */
624 if (list->property.pr_type == GNU_PROPERTY_STACK_SIZE)
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);
632 /* Write out property value. */
633 switch (list->property.pr_kind)
635 case property_number:
639 /* Never should happen. */
646 bfd_h_put_32 (abfd, list->property.u.number,
651 bfd_h_put_64 (abfd, list->property.u.number,
658 /* Never should happen. */
663 /* Align each property. */
664 size = (size + (align_size - 1)) & ~ (align_size - 1);
668 /* Set up GNU properties. Return the first relocatable ELF input with
669 GNU properties if found. Otherwise, return NULL. */
672 _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info)
674 bfd *abfd, *first_pbfd = NULL;
675 elf_property_list *list;
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;
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)
689 has_properties = TRUE;
691 /* Ignore GNU properties from ELF objects with different machine
692 code or class. Also skip objects without a GNU_PROPERTY note
694 if ((elf_machine_code
695 == get_elf_backend_data (abfd)->elf_machine_code)
697 == get_elf_backend_data (abfd)->s->elfclass)
698 && bfd_get_section_by_name (abfd,
699 NOTE_GNU_PROPERTY_SECTION_NAME) != NULL
702 /* Keep .note.gnu.property section in FIRST_PBFD. */
708 /* Do nothing if there is no .note.gnu.property section. */
712 /* Merge .note.gnu.property sections. */
713 info->callbacks->minfo (_("\n"));
714 info->callbacks->minfo (_("Merging program properties\n"));
715 info->callbacks->minfo (_("\n"));
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)
721 elf_property_list *null_ptr = NULL;
722 elf_property_list **listp = &null_ptr;
724 /* Merge .note.gnu.property section in relocatable ELF input. */
725 if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
727 list = elf_properties (abfd);
729 /* Ignore GNU properties from ELF objects with different
733 == get_elf_backend_data (abfd)->elf_machine_code))
734 listp = &elf_properties (abfd);
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);
747 /* Discard the .note.gnu.property section in this bfd. */
748 sec = bfd_get_section_by_name (abfd,
749 NOTE_GNU_PROPERTY_SECTION_NAME);
751 sec->output_section = bfd_abs_section_ptr;
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)
761 unsigned int align_size = elfclass == ELFCLASS64 ? 8 : 4;
763 sec = bfd_get_section_by_name (first_pbfd,
764 NOTE_GNU_PROPERTY_SECTION_NAME);
765 BFD_ASSERT (sec != NULL);
770 /* Update stack size in .note.gnu.property with -z stack-size=N
772 if (info->stacksize > 0)
775 bfd_vma stacksize = info->stacksize;
777 p = _bfd_elf_get_property (first_pbfd, GNU_PROPERTY_STACK_SIZE,
779 if (p->pr_kind == property_unknown)
781 /* Create GNU_PROPERTY_STACK_SIZE. */
782 p->u.number = stacksize;
783 p->pr_kind = property_number;
785 else if (stacksize > p->u.number)
786 p->u.number = stacksize;
788 else if (elf_properties (first_pbfd) == NULL)
790 /* Discard .note.gnu.property section if all properties have
792 sec->output_section = bfd_abs_section_ptr;
796 /* Fix up GNU properties. */
797 if (bed->fixup_gnu_properties)
798 bed->fixup_gnu_properties (info, &elf_properties (first_pbfd));
800 if (elf_properties (first_pbfd) == NULL)
802 /* Discard .note.gnu.property section if all properties have
804 sec->output_section = bfd_abs_section_ptr;
808 /* Compute the section size. */
809 list = elf_properties (first_pbfd);
810 size = elf_get_gnu_property_section_size (list, align_size);
812 /* Update .note.gnu.property section now. */
814 contents = (bfd_byte *) bfd_zalloc (first_pbfd, size);
816 elf_write_gnu_properties (first_pbfd, contents, list, size,
819 /* Cache the section contents for elf_link_input_bfd. */
820 elf_section_data (sec)->this_hdr.contents = contents;
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;
831 /* Convert GNU property size. */
834 _bfd_elf_convert_gnu_property_size (bfd *ibfd, bfd *obfd)
836 unsigned int align_size;
837 const struct elf_backend_data *bed;
838 elf_property_list *list = elf_properties (ibfd);
840 bed = get_elf_backend_data (obfd);
841 align_size = bed->s->elfclass == ELFCLASS64 ? 8 : 4;
843 /* Get the output .note.gnu.property section size. */
844 return elf_get_gnu_property_section_size (list, align_size);
847 /* Convert GNU properties. */
850 _bfd_elf_convert_gnu_properties (bfd *ibfd, asection *isec,
851 bfd *obfd, bfd_byte **ptr,
852 bfd_size_type *ptr_size)
856 unsigned int align_shift;
857 const struct elf_backend_data *bed;
858 elf_property_list *list = elf_properties (ibfd);
860 bed = get_elf_backend_data (obfd);
861 align_shift = bed->s->elfclass == ELFCLASS64 ? 3 : 2;
863 /* Get the output .note.gnu.property section size. */
864 size = bfd_get_section_size (isec->output_section);
866 /* Update the output .note.gnu.property section alignment. */
867 bfd_set_section_alignment (obfd, isec->output_section, align_shift);
869 if (size > bfd_get_section_size (isec))
871 contents = (bfd_byte *) bfd_malloc (size);
880 /* Generate the output .note.gnu.property section. */
881 elf_write_gnu_properties (ibfd, contents, list, size, 1 << align_shift);