{
elf_property *prop;
- switch (type)
+ if (type == GNU_PROPERTY_X86_COMPAT_ISA_1_USED
+ || type == GNU_PROPERTY_X86_COMPAT_ISA_1_NEEDED
+ || (type >= GNU_PROPERTY_X86_UINT32_AND_LO
+ && type <= GNU_PROPERTY_X86_UINT32_AND_HI)
+ || (type >= GNU_PROPERTY_X86_UINT32_OR_LO
+ && type <= GNU_PROPERTY_X86_UINT32_OR_HI)
+ || (type >= GNU_PROPERTY_X86_UINT32_OR_AND_LO
+ && type <= GNU_PROPERTY_X86_UINT32_OR_AND_HI))
{
- case GNU_PROPERTY_X86_ISA_1_USED:
- case GNU_PROPERTY_X86_ISA_1_NEEDED:
- case GNU_PROPERTY_X86_FEATURE_1_AND:
if (datasz != 4)
{
_bfd_error_handler
- ((type == GNU_PROPERTY_X86_ISA_1_USED
- ? _("error: %pB: <corrupt x86 ISA used size: 0x%x>")
- : (type == GNU_PROPERTY_X86_ISA_1_NEEDED
- ? _("error: %pB: <corrupt x86 ISA needed size: 0x%x>")
- : _("error: %pB: <corrupt x86 feature size: 0x%x>"))),
- abfd, datasz);
+ (_("error: %pB: <corrupt x86 property (0x%x) size: 0x%x>"),
+ abfd, type, datasz);
return property_corrupt;
}
prop = _bfd_elf_get_property (abfd, type, datasz);
- /* Combine properties of the same type. */
prop->u.number |= bfd_h_get_32 (abfd, ptr);
prop->pr_kind = property_number;
- break;
-
- default:
- return property_ignored;
+ return property_number;
}
- return property_number;
+ return property_ignored;
}
/* Merge x86 GNU property BPROP with APROP. If APROP isn't NULL,
bfd_boolean updated = FALSE;
unsigned int pr_type = aprop != NULL ? aprop->pr_type : bprop->pr_type;
- switch (pr_type)
+ if (pr_type == GNU_PROPERTY_X86_COMPAT_ISA_1_USED
+ || (pr_type >= GNU_PROPERTY_X86_UINT32_OR_AND_LO
+ && pr_type <= GNU_PROPERTY_X86_UINT32_OR_AND_HI))
+ {
+ if (aprop == NULL || bprop == NULL)
+ {
+ /* Only one of APROP and BPROP can be NULL. */
+ if (aprop != NULL)
+ {
+ /* Remove this property since the other input file doesn't
+ have it. */
+ aprop->pr_kind = property_remove;
+ updated = TRUE;
+ }
+ return updated;
+ }
+ goto or_property;
+ }
+ else if (pr_type == GNU_PROPERTY_X86_COMPAT_ISA_1_NEEDED
+ || (pr_type >= GNU_PROPERTY_X86_UINT32_OR_LO
+ && pr_type <= GNU_PROPERTY_X86_UINT32_OR_HI))
{
- case GNU_PROPERTY_X86_ISA_1_USED:
- case GNU_PROPERTY_X86_ISA_1_NEEDED:
if (aprop != NULL && bprop != NULL)
{
+or_property:
number = aprop->u.number;
aprop->u.number = number | bprop->u.number;
- updated = number != (unsigned int) aprop->u.number;
+ /* Remove the property if all bits are empty. */
+ if (aprop->u.number == 0)
+ {
+ aprop->pr_kind = property_remove;
+ updated = TRUE;
+ }
+ else
+ updated = number != (unsigned int) aprop->u.number;
}
else
{
- /* Return TRUE if APROP is NULL to indicate that BPROP should
- be added to ABFD. */
- updated = aprop == NULL;
+ /* Only one of APROP and BPROP can be NULL. */
+ if (aprop != NULL)
+ {
+ if (aprop->u.number == 0)
+ {
+ /* Remove APROP if all bits are empty. */
+ aprop->pr_kind = property_remove;
+ updated = TRUE;
+ }
+ }
+ else
+ {
+ /* Return TRUE if APROP is NULL and all bits of BPROP
+ aren't empty to indicate that BPROP should be added
+ to ABFD. */
+ updated = bprop->u.number != 0;
+ }
}
- break;
-
- case GNU_PROPERTY_X86_FEATURE_1_AND:
+ return updated;
+ }
+ else if (pr_type >= GNU_PROPERTY_X86_UINT32_AND_LO
+ && pr_type <= GNU_PROPERTY_X86_UINT32_AND_HI)
+ {
/* Only one of APROP and BPROP can be NULL:
1. APROP & BPROP when both APROP and BPROP aren't NULL.
2. If APROP is NULL, remove x86 feature.
updated = TRUE;
}
}
- break;
-
- default:
+ return updated;
+ }
+ else
+ {
/* Never should happen. */
abort ();
}
const struct elf_backend_data *bed;
unsigned int class_align = ABI_64_P (info->output_bfd) ? 3 : 2;
unsigned int got_align;
+ bfd_boolean has_text = FALSE;
features = 0;
if (info->ibt)
if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour
&& bfd_count_sections (pbfd) != 0)
{
+ if (!has_text)
+ {
+ /* Check if there is no non-empty text section. */
+ sec = bfd_get_section_by_name (pbfd, ".text");
+ if (sec != NULL && sec->size != 0)
+ has_text = TRUE;
+ }
+
ebfd = pbfd;
if (elf_properties (pbfd) != NULL)
break;
}
- if (ebfd != NULL && features)
+ bed = get_elf_backend_data (info->output_bfd);
+
+ htab = elf_x86_hash_table (info, bed->target_id);
+ if (htab == NULL)
+ return pbfd;
+
+ if (ebfd != NULL)
{
- /* If features is set, add GNU_PROPERTY_X86_FEATURE_1_IBT and
- GNU_PROPERTY_X86_FEATURE_1_SHSTK. */
- prop = _bfd_elf_get_property (ebfd,
- GNU_PROPERTY_X86_FEATURE_1_AND,
- 4);
- prop->u.number |= features;
- prop->pr_kind = property_number;
+ prop = NULL;
+ if (features)
+ {
+ /* If features is set, add GNU_PROPERTY_X86_FEATURE_1_IBT and
+ GNU_PROPERTY_X86_FEATURE_1_SHSTK. */
+ prop = _bfd_elf_get_property (ebfd,
+ GNU_PROPERTY_X86_FEATURE_1_AND,
+ 4);
+ prop->u.number |= features;
+ prop->pr_kind = property_number;
+ }
+ else if (has_text
+ && elf_tdata (info->output_bfd)->o->build_id.sec == NULL
+ && !htab->elf.dynamic_sections_created
+ && !info->traditional_format
+ && (info->output_bfd->flags & D_PAGED) != 0
+ && info->separate_code)
+ {
+ /* If the separate code program header is needed, make sure
+ that the first read-only PT_LOAD segment has no code by
+ adding a GNU_PROPERTY_X86_FEATURE_2_NEEDED note. */
+ elf_property_list *list;
+ bfd_boolean need_property = TRUE;
+
+ for (list = elf_properties (ebfd); list; list = list->next)
+ {
+ unsigned int pr_type = list->property.pr_type;
+ if (pr_type == GNU_PROPERTY_STACK_SIZE
+ || pr_type == GNU_PROPERTY_NO_COPY_ON_PROTECTED
+ || pr_type == GNU_PROPERTY_X86_COMPAT_ISA_1_NEEDED
+ || (pr_type >= GNU_PROPERTY_X86_UINT32_OR_LO
+ && pr_type <= GNU_PROPERTY_X86_UINT32_OR_HI))
+ {
+ /* These properties won't be removed during merging. */
+ need_property = FALSE;
+ break;
+ }
+ }
+
+ if (need_property)
+ {
+ prop = _bfd_elf_get_property
+ (ebfd, GNU_PROPERTY_X86_FEATURE_2_NEEDED, 4);
+ prop->u.number = GNU_PROPERTY_X86_FEATURE_2_X86;
+ prop->pr_kind = property_number;
+ }
+ }
/* Create the GNU property note section if needed. */
- if (pbfd == NULL)
+ if (prop != NULL && pbfd == NULL)
{
sec = bfd_make_section_with_flags (ebfd,
NOTE_GNU_PROPERTY_SECTION_NAME,
pbfd = _bfd_elf_link_setup_gnu_properties (info);
- bed = get_elf_backend_data (info->output_bfd);
-
- htab = elf_x86_hash_table (info, bed->target_id);
- if (htab == NULL)
- return pbfd;
-
htab->r_info = init_table->r_info;
htab->r_sym = init_table->r_sym;
return pbfd;
}
+
+/* Fix up x86 GNU properties. */
+
+void
+_bfd_x86_elf_link_fixup_gnu_properties (struct bfd_link_info *info,
+ elf_property_list **listp)
+{
+ elf_property_list *p;
+
+ for (p = *listp; p; p = p->next)
+ {
+ unsigned int type = p->property.pr_type;
+ if (type == GNU_PROPERTY_X86_COMPAT_ISA_1_USED
+ || type == GNU_PROPERTY_X86_COMPAT_ISA_1_NEEDED
+ || (type >= GNU_PROPERTY_X86_UINT32_AND_LO
+ && type <= GNU_PROPERTY_X86_UINT32_AND_HI)
+ || (type >= GNU_PROPERTY_X86_UINT32_OR_LO
+ && type <= GNU_PROPERTY_X86_UINT32_OR_HI)
+ || (type >= GNU_PROPERTY_X86_UINT32_OR_AND_LO
+ && type <= GNU_PROPERTY_X86_UINT32_OR_AND_HI))
+ {
+ if (p->property.u.number == 0)
+ {
+ /* Remove empty property. */
+ *listp = p->next;
+ continue;
+ }
+
+ /* Mark x86-specific properties with X86_UINT32_VALID for
+ non-relocatable output. */
+ if (!bfd_link_relocatable (info))
+ p->property.u.number |= GNU_PROPERTY_X86_UINT32_VALID;
+
+ listp = &p->next;
+ }
+ else if (type > GNU_PROPERTY_HIPROC)
+ {
+ /* The property list is sorted in order of type. */
+ break;
+ }
+ }
+}