This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[Patch 2/6] ARM attributes: merging files
- From: Andrew Stubbs <ams at codesourcery dot com>
- To: binutils at sourceware dot org
- Date: Tue, 13 Jan 2009 10:01:38 +0000
- Subject: [Patch 2/6] ARM attributes: merging files
When files with attributes are linked, the attributes must be checked
for compatibility, and the attributes on the output file should be set
according to the inputs - i.e. merged.
This patch should bring the ARM attribute support up to ABI 2.07. It is
intended to be applied on top of my previous Tag_compatibility patch.
I've added support for all the new attributes, and changed the way old
attributes are merged, where they were broken or out-of-date.
The test cases are included in part 6 of the patch series.
OK?
Andrew
2009-01-12 Andrew Stubbs <ams@codesourcery.com>
Julian Brown <julian@codesourcery.com>
bfd/
* elf-bfd.h (NUM_KNOWN_OBJ_ATTRIBUTES): Set to 71 to include all known
ARM attributes in ABI 2.07.
* elf32-arm.c (get_secondary_compatible_arch): New function.
(set_secondary_compatible_arch): New function.
(tag_cpu_arch_combine): New function.
(elf32_arm_copy_one_eabi_other_attribute): Delete function.
(elf32_arm_copy_eabi_other_attribute_list): Delete function.
(elf32_arm_merge_eabi_attributes): Rename order_312 to order_021 to
make it fit with order_01243.
Add support for Tag_also_compatible_with,
Tag_CPU_unaligned_access, Tag_T2EE_use, Tag_Virtualization_use,
Tag_MPextension_use, Tag_nodefaults and Tag_conformance.
Improve/tidy up support for Tag_CPU_raw_name, Tag_CPU_name,
Tag_CPU_arch, Tag_ABI_HardFP_use, Tag_VFP_HP_extension,
Tag_ABI_FP_denormal, Tag_ABI_PCS_GOT_use, Tag_ABI_align8_needed,
Tag_VFP_arch and Tag_ABI_FP_16bit_format.
Rework the way unknown attributes are handled.
Defer errors until all attributes have been processed.
gas/
* config/tc-arm.c (cpu_arch): Change ARM_ARCH_V6M to 11.
include/elf/
* arm.h (TAG_CPU_ARCH_V6_M, TAG_CPU_ARCH_V6S_M): New defines.
(MAX_TAG_CPU_ARCH, TAG_CPU_ARCH_V4T_PLUS_V6_M): New defines.
(Tag_NEON_arch): Rename to Tag_Advanced_SIMD_arch to match ARM ABI
version 2.07.
(Tag_undefined39, Tag_nodefaults): New enum values.
(Tag_also_compatible_with, Tag_T2EE_use): Likewise.
(Tag_conformance, Tag_Virtualization_use): Likewise.
(Tag_undefined69, Tag_MPextension_use): Likewise.
---
bfd/elf-bfd.h | 2
bfd/elf32-arm.c | 607 +++++++++++++--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
gas/config/tc-arm.c | 2
include/elf/arm.h | 44 !!!
4 files changed, 156 insertions(+), 20 deletions(-), 479 modifications(!)
Index: bfd/elf-bfd.h
===================================================================
*** bfd/elf-bfd.h.orig
--- bfd/elf-bfd.h
*************** struct elf_find_verdep_info
*** 1371,1377 ****
};
/* The maximum number of known object attributes for any target. */
! #define NUM_KNOWN_OBJ_ATTRIBUTES 33
/* The value of an object attribute. type & 1 indicates whether there
is an integer value; type & 2 indicates whether there is a string
--- 1371,1377 ----
};
/* The maximum number of known object attributes for any target. */
! #define NUM_KNOWN_OBJ_ATTRIBUTES 71
/* The value of an object attribute. type & 1 indicates whether there
is an integer value; type & 2 indicates whether there is a string
Index: bfd/elf32-arm.c
===================================================================
*** bfd/elf32-arm.c.orig
--- bfd/elf32-arm.c
*************** elf32_arm_obj_attrs_arg_type (int tag)
*** 8143,8173 ****
return (tag & 1) != 0 ? 2 : 1;
}
static void
! elf32_arm_copy_one_eabi_other_attribute (bfd *ibfd, bfd *obfd, obj_attribute_list *in_list)
{
! switch (in_list->tag)
! {
! case Tag_VFP_HP_extension:
! case Tag_ABI_FP_16bit_format:
! bfd_elf_add_obj_attr_int (obfd, OBJ_ATTR_PROC, in_list->tag, in_list->attr.i);
! break;
! default:
! if ((in_list->tag & 127) < 64)
! {
! _bfd_error_handler
! (_("Warning: %B: Unknown EABI object attribute %d"), ibfd, in_list->tag);
! break;
! }
}
}
! static void
! elf32_arm_copy_eabi_other_attribute_list (bfd *ibfd, bfd *obfd, obj_attribute_list *in_list)
{
! for (; in_list; in_list = in_list->next )
! elf32_arm_copy_one_eabi_other_attribute (ibfd, obfd, in_list);
}
/* Merge EABI object attributes from IBFD into OBFD. Raise an error if there
--- 8143,8349 ----
return (tag & 1) != 0 ? 2 : 1;
}
+ /* Read the architecture from the Tag_also_compatible_with attribute, if any.
+ Returns -1 if no architecture could be read. */
+
+ static int
+ get_secondary_compatible_arch (bfd *abfd)
+ {
+ obj_attribute *attr =
+ &elf_known_obj_attributes_proc (abfd)[Tag_also_compatible_with];
+
+ /* Note: the tag and its argument below are uleb128 values, though
+ currently-defined values fit in one byte for each. */
+ if (attr->s
+ && attr->s[0] == Tag_CPU_arch
+ && (attr->s[1] & 128) != 128
+ && attr->s[2] == 0)
+ return attr->s[1];
+
+ /* This tag is "safely ignorable", so don't complain if it looks funny. */
+ return -1;
+ }
+
+ /* Set, or unset, the architecture of the Tag_also_compatible_with attribute.
+ The tag is removed if ARCH is -1. */
+
static void
! set_secondary_compatible_arch (bfd *abfd, int arch)
{
! obj_attribute *attr =
! &elf_known_obj_attributes_proc (abfd)[Tag_also_compatible_with];
! if (arch == -1)
! {
! attr->s = NULL;
! return;
}
+
+ /* Note: the tag and its argument below are uleb128 values, though
+ currently-defined values fit in one byte for each. */
+ if (!attr->s)
+ attr->s = bfd_alloc (abfd, 3);
+ attr->s[0] = Tag_CPU_arch;
+ attr->s[1] = arch;
+ attr->s[2] = '\0';
}
! /* Combine two values for Tag_CPU_arch, taking secondary compatibility tags
! into account. */
!
! static int
! tag_cpu_arch_combine (bfd *ibfd, int oldtag, int *secondary_compat_out,
! int newtag, int secondary_compat)
{
! #define T(X) TAG_CPU_ARCH_##X
! int tagl, tagh, result;
! const int v6t2[] =
! {
! T(V6T2), /* PRE_V4. */
! T(V6T2), /* V4. */
! T(V6T2), /* V4T. */
! T(V6T2), /* V5T. */
! T(V6T2), /* V5TE. */
! T(V6T2), /* V5TEJ. */
! T(V6T2), /* V6. */
! T(V7), /* V6KZ. */
! T(V6T2) /* V6T2. */
! };
! const int v6k[] =
! {
! T(V6K), /* PRE_V4. */
! T(V6K), /* V4. */
! T(V6K), /* V4T. */
! T(V6K), /* V5T. */
! T(V6K), /* V5TE. */
! T(V6K), /* V5TEJ. */
! T(V6K), /* V6. */
! T(V6KZ), /* V6KZ. */
! T(V7), /* V6T2. */
! T(V6K) /* V6K. */
! };
! const int v7[] =
! {
! T(V7), /* PRE_V4. */
! T(V7), /* V4. */
! T(V7), /* V4T. */
! T(V7), /* V5T. */
! T(V7), /* V5TE. */
! T(V7), /* V5TEJ. */
! T(V7), /* V6. */
! T(V7), /* V6KZ. */
! T(V7), /* V6T2. */
! T(V7), /* V6K. */
! T(V7) /* V7. */
! };
! const int v6_m[] =
! {
! -1, /* PRE_V4. */
! -1, /* V4. */
! T(V6K), /* V4T. */
! T(V6K), /* V5T. */
! T(V6K), /* V5TE. */
! T(V6K), /* V5TEJ. */
! T(V6K), /* V6. */
! T(V6KZ), /* V6KZ. */
! T(V7), /* V6T2. */
! T(V6K), /* V6K. */
! T(V7), /* V7. */
! T(V6_M) /* V6_M. */
! };
! const int v6s_m[] =
! {
! -1, /* PRE_V4. */
! -1, /* V4. */
! T(V6K), /* V4T. */
! T(V6K), /* V5T. */
! T(V6K), /* V5TE. */
! T(V6K), /* V5TEJ. */
! T(V6K), /* V6. */
! T(V6KZ), /* V6KZ. */
! T(V7), /* V6T2. */
! T(V6K), /* V6K. */
! T(V7), /* V7. */
! T(V6S_M), /* V6_M. */
! T(V6S_M) /* V6S_M. */
! };
! const int v4t_plus_v6_m[] =
! {
! -1, /* PRE_V4. */
! -1, /* V4. */
! T(V4T), /* V4T. */
! T(V5T), /* V5T. */
! T(V5TE), /* V5TE. */
! T(V5TEJ), /* V5TEJ. */
! T(V6), /* V6. */
! T(V6KZ), /* V6KZ. */
! T(V6T2), /* V6T2. */
! T(V6K), /* V6K. */
! T(V7), /* V7. */
! T(V6_M), /* V6_M. */
! T(V6S_M), /* V6S_M. */
! T(V4T_PLUS_V6_M) /* V4T plus V6_M. */
! };
! const int *comb[] =
! {
! v6t2,
! v6k,
! v7,
! v6_m,
! v6s_m,
! /* Pseudo-architecture. */
! v4t_plus_v6_m
! };
!
! /* Check we've not got a higher architecture than we know about. */
!
! if (oldtag >= MAX_TAG_CPU_ARCH || newtag >= MAX_TAG_CPU_ARCH)
! {
! _bfd_error_handler (_("ERROR: %B: Unknown CPU architecture"), ibfd);
! return -1;
! }
!
! /* Override old tag if we have a Tag_also_compatible_with on the output. */
!
! if ((oldtag == T(V6_M) && *secondary_compat_out == T(V4T))
! || (oldtag == T(V4T) && *secondary_compat_out == T(V6_M)))
! oldtag = T(V4T_PLUS_V6_M);
!
! /* And override the new tag if we have a Tag_also_compatible_with on the
! input. */
!
! if ((newtag == T(V6_M) && secondary_compat == T(V4T))
! || (newtag == T(V4T) && secondary_compat == T(V6_M)))
! newtag = T(V4T_PLUS_V6_M);
!
! tagl = (oldtag < newtag) ? oldtag : newtag;
! result = tagh = (oldtag > newtag) ? oldtag : newtag;
!
! /* Architectures before V6KZ add features monotonically. */
! if (tagh <= TAG_CPU_ARCH_V6KZ)
! return result;
!
! result = comb[tagh - T(V6T2)][tagl];
!
! /* Use Tag_CPU_arch == V4T and Tag_also_compatible_with (Tag_CPU_arch V6_M)
! as the canonical version. */
! if (result == T(V4T_PLUS_V6_M))
! {
! result = T(V4T);
! *secondary_compat_out = T(V6_M);
! }
! else
! *secondary_compat_out = -1;
!
! if (result == -1)
! {
! _bfd_error_handler (_("ERROR: %B: Conflicting CPU architectures %d/%d"),
! ibfd, oldtag, newtag);
! return -1;
! }
!
! return result;
! #undef T
}
/* Merge EABI object attributes from IBFD into OBFD. Raise an error if there
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8180,8191 ****
obj_attribute *out_attr;
obj_attribute_list *in_list;
obj_attribute_list *out_list;
/* Some tags have 0 = don't care, 1 = strong requirement,
2 = weak requirement. */
! static const int order_312[3] = {3, 1, 2};
/* For use with Tag_VFP_arch. */
static const int order_01243[5] = {0, 1, 2, 4, 3};
int i;
if (!elf_known_obj_attributes_proc (obfd)[0].i)
{
--- 8356,8369 ----
obj_attribute *out_attr;
obj_attribute_list *in_list;
obj_attribute_list *out_list;
+ obj_attribute_list **out_listp;
/* Some tags have 0 = don't care, 1 = strong requirement,
2 = weak requirement. */
! static const int order_021[3] = {0, 2, 1};
/* For use with Tag_VFP_arch. */
static const int order_01243[5] = {0, 1, 2, 4, 3};
int i;
+ bfd_boolean result = TRUE;
if (!elf_known_obj_attributes_proc (obfd)[0].i)
{
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8212,8218 ****
_bfd_error_handler
(_("ERROR: %B uses VFP register arguments, %B does not"),
ibfd, obfd);
! return FALSE;
}
}
--- 8390,8396 ----
_bfd_error_handler
(_("ERROR: %B uses VFP register arguments, %B does not"),
ibfd, obfd);
! result = FALSE;
}
}
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8223,8234 ****
{
case Tag_CPU_raw_name:
case Tag_CPU_name:
! /* Use whichever has the greatest architecture requirements. We
! won't necessarily have both the above tags, so make sure input
! name is non-NULL. */
! if (in_attr[Tag_CPU_arch].i > out_attr[Tag_CPU_arch].i
! && in_attr[i].s)
! out_attr[i].s = _bfd_elf_attr_strdup (obfd, in_attr[i].s);
break;
case Tag_ABI_optimization_goals:
--- 8401,8407 ----
{
case Tag_CPU_raw_name:
case Tag_CPU_name:
! /* These are merged after Tag_CPU_arch. */
break;
case Tag_ABI_optimization_goals:
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8237,8274 ****
break;
case Tag_CPU_arch:
case Tag_ARM_ISA_use:
case Tag_THUMB_ISA_use:
case Tag_WMMX_arch:
! case Tag_NEON_arch:
! /* ??? Do NEON and WMMX conflict? */
case Tag_ABI_FP_rounding:
- case Tag_ABI_FP_denormal:
case Tag_ABI_FP_exceptions:
case Tag_ABI_FP_user_exceptions:
case Tag_ABI_FP_number_model:
! case Tag_ABI_align8_preserved:
! case Tag_ABI_HardFP_use:
/* Use the largest value specified. */
if (in_attr[i].i > out_attr[i].i)
out_attr[i].i = in_attr[i].i;
break;
! case Tag_CPU_arch_profile:
! /* Warn if conflicting architecture profiles used. */
! if (out_attr[i].i && in_attr[i].i && in_attr[i].i != out_attr[i].i)
! {
_bfd_error_handler
! (_("ERROR: %B: Conflicting architecture profiles %c/%c"),
! ibfd, in_attr[i].i, out_attr[i].i);
! return FALSE;
}
! if (in_attr[i].i)
out_attr[i].i = in_attr[i].i;
break;
case Tag_VFP_arch:
! if (in_attr[i].i > 4 || out_attr[i].i > 4
! || order_01243[in_attr[i].i] > order_01243[out_attr[i].i])
out_attr[i].i = in_attr[i].i;
break;
case Tag_PCS_config:
--- 8410,8557 ----
break;
case Tag_CPU_arch:
+ {
+ int secondary_compat = -1, secondary_compat_out = -1;
+ unsigned int saved_out_attr = out_attr[i].i;
+ static const char *name_table[] = {
+ /* These aren't real CPU names, but we can't guess
+ that from the architecture version alone. */
+ "Pre v4",
+ "ARM v4",
+ "ARM v4T",
+ "ARM v5T",
+ "ARM v5TE",
+ "ARM v5TEJ",
+ "ARM v6",
+ "ARM v6KZ",
+ "ARM v6T2",
+ "ARM v6K",
+ "ARM v7",
+ "ARM v6-M",
+ "ARM v6S-M"
+ };
+
+ /* Merge Tag_CPU_arch and Tag_also_compatible_with. */
+ secondary_compat = get_secondary_compatible_arch (ibfd);
+ secondary_compat_out = get_secondary_compatible_arch (obfd);
+ out_attr[i].i = tag_cpu_arch_combine (ibfd, out_attr[i].i,
+ &secondary_compat_out,
+ in_attr[i].i,
+ secondary_compat);
+ set_secondary_compatible_arch (obfd, secondary_compat_out);
+
+ /* Merge Tag_CPU_name and Tag_CPU_raw_name. */
+ if (out_attr[i].i == saved_out_attr)
+ ; /* Leave the names alone. */
+ else if (out_attr[i].i == in_attr[i].i)
+ {
+ /* The output architecture has been changed to match the
+ input architecture. Use the input names. */
+ out_attr[Tag_CPU_name].s = in_attr[Tag_CPU_name].s
+ ? _bfd_elf_attr_strdup (obfd, in_attr[Tag_CPU_name].s)
+ : NULL;
+ out_attr[Tag_CPU_raw_name].s = in_attr[Tag_CPU_raw_name].s
+ ? _bfd_elf_attr_strdup (obfd, in_attr[Tag_CPU_raw_name].s)
+ : NULL;
+ }
+ else
+ {
+ out_attr[Tag_CPU_name].s = NULL;
+ out_attr[Tag_CPU_raw_name].s = NULL;
+ }
+
+ /* If we still don't have a value for Tag_CPU_name,
+ make one up now. Tag_CPU_raw_name remains blank. */
+ if (out_attr[Tag_CPU_name].s == NULL
+ && out_attr[i].i < ARRAY_SIZE (name_table))
+ out_attr[Tag_CPU_name].s =
+ _bfd_elf_attr_strdup (obfd, name_table[out_attr[i].i]);
+ }
+ break;
+
case Tag_ARM_ISA_use:
case Tag_THUMB_ISA_use:
case Tag_WMMX_arch:
! case Tag_Advanced_SIMD_arch:
! /* ??? Do Advanced_SIMD (NEON) and WMMX conflict? */
case Tag_ABI_FP_rounding:
case Tag_ABI_FP_exceptions:
case Tag_ABI_FP_user_exceptions:
case Tag_ABI_FP_number_model:
! case Tag_VFP_HP_extension:
! case Tag_CPU_unaligned_access:
! case Tag_T2EE_use:
! case Tag_Virtualization_use:
! case Tag_MPextension_use:
/* Use the largest value specified. */
if (in_attr[i].i > out_attr[i].i)
out_attr[i].i = in_attr[i].i;
break;
! case Tag_ABI_align8_preserved:
! case Tag_ABI_PCS_RO_data:
! /* Use the smallest value specified. */
! if (in_attr[i].i < out_attr[i].i)
! out_attr[i].i = in_attr[i].i;
! break;
!
! case Tag_ABI_align8_needed:
! if ((in_attr[i].i > 0 || out_attr[i].i > 0)
! && (in_attr[Tag_ABI_align8_preserved].i == 0
! || out_attr[Tag_ABI_align8_preserved].i == 0))
! {
! /* This error message should be enabled once all non-conformant
! binaries in the toolchain have had the attributes set
! properly.
_bfd_error_handler
! (_("ERROR: %B: 8-byte data alignment conflicts with %B"),
! obfd, ibfd);
! result = FALSE; */
}
! /* Fall through. */
! case Tag_ABI_FP_denormal:
! case Tag_ABI_PCS_GOT_use:
! /* Use the "greatest" from the sequence 0, 2, 1, or the largest
! value if greater than 2 (for future-proofing). */
! if ((in_attr[i].i > 2 && in_attr[i].i > out_attr[i].i)
! || (in_attr[i].i <= 2 && out_attr[i].i <= 2
! && order_021[in_attr[i].i] > order_021[out_attr[i].i]))
out_attr[i].i = in_attr[i].i;
break;
+
+
+ case Tag_CPU_arch_profile:
+ if (out_attr[i].i != in_attr[i].i)
+ {
+ /* 0 will merge with anything.
+ 'A' and 'S' merge to 'A'.
+ 'R' and 'S' merge to 'R'.
+ 'M' and 'A|R|S' is an error. */
+ if (out_attr[i].i == 0
+ || (out_attr[i].i == 'S'
+ && (in_attr[i].i == 'A' || in_attr[i].i == 'R')))
+ out_attr[i].i = in_attr[i].i;
+ else if (in_attr[i].i == 0
+ || (in_attr[i].i == 'S'
+ && (out_attr[i].i == 'A' || out_attr[i].i == 'R')))
+ ; /* Do nothing. */
+ else
+ {
+ _bfd_error_handler
+ (_("ERROR: %B: Conflicting architecture profiles %c/%c"),
+ ibfd,
+ in_attr[i].i ? in_attr[i].i : '0',
+ out_attr[i].i ? out_attr[i].i : '0');
+ result = FALSE;
+ }
+ }
+ break;
case Tag_VFP_arch:
! /* Use the "greatest" from the sequence 0, 1, 2, 4, 3, or the
! largest value if greater than 4 (for future-proofing). */
! if ((in_attr[i].i > 4 && in_attr[i].i > out_attr[i].i)
! || (in_attr[i].i <= 4 && out_attr[i].i <= 4
! && order_01243[in_attr[i].i] > order_01243[out_attr[i].i]))
out_attr[i].i = in_attr[i].i;
break;
case Tag_PCS_config:
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8289,8295 ****
{
_bfd_error_handler
(_("ERROR: %B: Conflicting use of R9"), ibfd);
! return FALSE;
}
if (out_attr[i].i == AEABI_R9_unused)
out_attr[i].i = in_attr[i].i;
--- 8572,8578 ----
{
_bfd_error_handler
(_("ERROR: %B: Conflicting use of R9"), ibfd);
! result = FALSE;
}
if (out_attr[i].i == AEABI_R9_unused)
out_attr[i].i = in_attr[i].i;
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8302,8323 ****
_bfd_error_handler
(_("ERROR: %B: SB relative addressing conflicts with use of R9"),
ibfd);
! return FALSE;
}
/* Use the smallest value specified. */
if (in_attr[i].i < out_attr[i].i)
out_attr[i].i = in_attr[i].i;
break;
- case Tag_ABI_PCS_RO_data:
- /* Use the smallest value specified. */
- if (in_attr[i].i < out_attr[i].i)
- out_attr[i].i = in_attr[i].i;
- break;
- case Tag_ABI_PCS_GOT_use:
- if (in_attr[i].i > 2 || out_attr[i].i > 2
- || order_312[in_attr[i].i] < order_312[out_attr[i].i])
- out_attr[i].i = in_attr[i].i;
- break;
case Tag_ABI_PCS_wchar_t:
if (out_attr[i].i && in_attr[i].i && out_attr[i].i != in_attr[i].i
&& !elf_arm_tdata (obfd)->no_wchar_size_warning)
--- 8585,8596 ----
_bfd_error_handler
(_("ERROR: %B: SB relative addressing conflicts with use of R9"),
ibfd);
! result = FALSE;
}
/* Use the smallest value specified. */
if (in_attr[i].i < out_attr[i].i)
out_attr[i].i = in_attr[i].i;
break;
case Tag_ABI_PCS_wchar_t:
if (out_attr[i].i && in_attr[i].i && out_attr[i].i != in_attr[i].i
&& !elf_arm_tdata (obfd)->no_wchar_size_warning)
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8329,8340 ****
else if (in_attr[i].i && !out_attr[i].i)
out_attr[i].i = in_attr[i].i;
break;
- case Tag_ABI_align8_needed:
- /* ??? Check against Tag_ABI_align8_preserved. */
- if (in_attr[i].i > 2 || out_attr[i].i > 2
- || order_312[in_attr[i].i] < order_312[out_attr[i].i])
- out_attr[i].i = in_attr[i].i;
- break;
case Tag_ABI_enum_size:
if (in_attr[i].i != AEABI_enum_unused)
{
--- 8602,8607 ----
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8349,8360 ****
&& out_attr[i].i != in_attr[i].i
&& !elf_arm_tdata (obfd)->no_enum_size_warning)
{
! const char *aeabi_enum_names[] =
{ "", "variable-size", "32-bit", "" };
_bfd_error_handler
(_("warning: %B uses %s enums yet the output is to use %s enums; use of enum values across objects may fail"),
! ibfd, aeabi_enum_names[in_attr[i].i],
! aeabi_enum_names[out_attr[i].i]);
}
}
break;
--- 8616,8634 ----
&& out_attr[i].i != in_attr[i].i
&& !elf_arm_tdata (obfd)->no_enum_size_warning)
{
! static const char *aeabi_enum_names[] =
{ "", "variable-size", "32-bit", "" };
+ const char *in_name =
+ in_attr[i].i < ARRAY_SIZE(aeabi_enum_names)
+ ? aeabi_enum_names[in_attr[i].i]
+ : "<unknown>";
+ const char *out_name =
+ out_attr[i].i < ARRAY_SIZE(aeabi_enum_names)
+ ? aeabi_enum_names[out_attr[i].i]
+ : "<unknown>";
_bfd_error_handler
(_("warning: %B uses %s enums yet the output is to use %s enums; use of enum values across objects may fail"),
! ibfd, in_name, out_name);
}
}
break;
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8367,8400 ****
_bfd_error_handler
(_("ERROR: %B uses iWMMXt register arguments, %B does not"),
ibfd, obfd);
! return FALSE;
}
break;
-
case Tag_compatibility:
/* Merged in target-independent code. */
break;
! default: /* All known attributes should be explicitly covered. */
! abort ();
! }
! if (in_attr[i].type && !out_attr[i].type)
! switch (in_attr[i].type)
{
! case 1:
! if (out_attr[i].i)
! out_attr[i].type = 1;
! break;
! case 2:
! if (out_attr[i].s)
! out_attr[i].type = 2;
! break;
! default:
! abort ();
}
}
/* Merge Tag_compatibility attributes and any common GNU ones. */
--- 8641,8738 ----
_bfd_error_handler
(_("ERROR: %B uses iWMMXt register arguments, %B does not"),
ibfd, obfd);
! result = FALSE;
}
break;
case Tag_compatibility:
/* Merged in target-independent code. */
break;
+ case Tag_ABI_HardFP_use:
+ /* 1 (SP) and 2 (DP) conflict, so combine to 3 (SP & DP). */
+ if ((in_attr[i].i == 1 && out_attr[i].i == 2)
+ || (in_attr[i].i == 2 && out_attr[i].i == 1))
+ out_attr[i].i = 3;
+ else if (in_attr[i].i > out_attr[i].i)
+ out_attr[i].i = in_attr[i].i;
+ break;
+ case Tag_ABI_FP_16bit_format:
+ if (in_attr[i].i != 0 && out_attr[i].i != 0)
+ {
+ if (in_attr[i].i != out_attr[i].i)
+ {
+ _bfd_error_handler
+ (_("ERROR: fp16 format mismatch between %B and %B"),
+ ibfd, obfd);
+ result = FALSE;
+ }
+ }
+ if (in_attr[i].i != 0)
+ out_attr[i].i = in_attr[i].i;
+ break;
! case Tag_nodefaults:
! /* This tag is set if it exists, but the value is unused.
! Unfortunately, we don't record whether each attribute is zero
! initialized, or read from the file, so the information has been
! lost. In any case, we don't write attributes with zero values.
! Do nothing. */
! break;
! case Tag_also_compatible_with:
! /* Already done in Tag_CPU_arch. */
! break;
! case Tag_conformance:
! /* Keep the attribute if it matches. Throw it away otherwise.
! No attribute means no claim to conform. */
! if (!in_attr[i].s || !out_attr[i].s
! || strcmp (in_attr[i].s, out_attr[i].s) != 0)
! out_attr[i].s = NULL;
! break;
! default:
{
! bfd *err_bfd = NULL;
! /* The "known_obj_attributes" table does contain some undefined
! attributes. Ensure that there are unused. */
! if (out_attr[i].i != 0 || out_attr[i].s != NULL)
! err_bfd = obfd;
! else if (in_attr[i].i != 0 || in_attr[i].s != NULL)
! err_bfd = ibfd;
! if (err_bfd != NULL)
! {
! /* Attribute numbers >=64 (mod 128) can be safely ignored. */
! if ((i & 127) < 64)
! {
! _bfd_error_handler
! (_("%B: Unknown mandatory EABI object attribute %d"),
! err_bfd, i);
! bfd_set_error (bfd_error_bad_value);
! result = FALSE;
! }
! else
! {
! _bfd_error_handler
! (_("Warning: %B: Unknown EABI object attribute %d"),
! err_bfd, i);
! }
! }
!
! /* Only pass on attributes that match in both inputs. */
! if (in_attr[i].i != out_attr[i].i
! || in_attr[i].s != out_attr[i].s
! || (in_attr[i].s != NULL && out_attr[i].s != NULL
! && strcmp (in_attr[i].s, out_attr[i].s) != 0))
! {
! out_attr[i].i = 0;
! out_attr[i].s = NULL;
! }
}
+ }
+
+ /* If out_attr was copied from in_attr then it won't have a type yet. */
+ if (in_attr[i].type && !out_attr[i].type)
+ out_attr[i].type = in_attr[i].type;
}
/* Merge Tag_compatibility attributes and any common GNU ones. */
*************** elf32_arm_merge_eabi_attributes (bfd *ib
*** 8402,8468 ****
/* Check for any attributes not known on ARM. */
in_list = elf_other_obj_attributes_proc (ibfd);
! out_list = elf_other_obj_attributes_proc (obfd);
! for (; in_list != NULL; )
{
! if (out_list == NULL)
! {
! elf32_arm_copy_eabi_other_attribute_list (ibfd, obfd, in_list);
! return TRUE;
! }
/* The tags for each list are in numerical order. */
/* If the tags are equal, then merge. */
! if (in_list->tag == out_list->tag)
! {
! switch (in_list->tag)
! {
! case Tag_VFP_HP_extension:
! if (out_list->attr.i == 0)
! out_list->attr.i = in_list->attr.i;
! break;
!
! case Tag_ABI_FP_16bit_format:
! if (in_list->attr.i != 0 && out_list->attr.i != 0)
! {
! if (in_list->attr.i != out_list->attr.i)
! {
! _bfd_error_handler
! (_("ERROR: fp16 format mismatch between %B and %B"),
! ibfd, obfd);
! return FALSE;
! }
! }
! if (in_list->attr.i != 0)
! out_list->attr.i = in_list->attr.i;
! break;
!
! default:
! if ((in_list->tag & 127) < 64)
! {
! _bfd_error_handler
! (_("Warning: %B: Unknown EABI object attribute %d"), ibfd, in_list->tag);
! break;
! }
! }
}
! else if (in_list->tag < out_list->tag)
{
! /* This attribute is in ibfd, but not obfd. Copy to obfd and advance to
! next input attribute. */
! elf32_arm_copy_one_eabi_other_attribute (ibfd, obfd, in_list);
}
! if (in_list->tag <= out_list->tag)
{
! in_list = in_list->next;
! if (in_list == NULL)
! continue;
}
- while (out_list && out_list->tag < in_list->tag)
- out_list = out_list->next;
}
! return TRUE;
}
--- 8740,8817 ----
/* Check for any attributes not known on ARM. */
in_list = elf_other_obj_attributes_proc (ibfd);
! out_listp = &elf_other_obj_attributes_proc (obfd);
! out_list = *out_listp;
! for (; in_list || out_list; )
{
! bfd *err_bfd = NULL;
! int err_tag = 0;
/* The tags for each list are in numerical order. */
/* If the tags are equal, then merge. */
! if (out_list && (!in_list || in_list->tag > out_list->tag))
! {
! /* This attribute only exists in obfd. We can't merge, and we don't
! know what the tag means, so delete it. */
! err_bfd = obfd;
! err_tag = out_list->tag;
! *out_listp = out_list->next;
! out_list = *out_listp;
! }
! else if (in_list && (!out_list || in_list->tag < out_list->tag))
! {
! /* This attribute only exists in ibfd. We can't merge, and we don't
! know what the tag means, so ignore it. */
! err_bfd = ibfd;
! err_tag = in_list->tag;
! in_list = in_list->next;
}
! else /* The tags are equal. */
{
! /* As present, all attributes in the list are unknown, and
! therefore can't be merged meaningfully. */
! err_bfd = obfd;
! err_tag = out_list->tag;
!
! /* Only pass on attributes that match in both inputs. */
! if (in_list->attr.i != out_list->attr.i
! || in_list->attr.s != out_list->attr.s
! || (in_list->attr.s && out_list->attr.s
! && strcmp (in_list->attr.s, out_list->attr.s) != 0))
! {
! /* No match. Delete the attribute. */
! *out_listp = out_list->next;
! out_list = *out_listp;
! }
! else
! {
! /* Matched. Keep the attribute and move to the next. */
! out_list = out_list->next;
! in_list = in_list->next;
! }
}
!
! if (err_bfd)
{
! /* Attribute numbers >=64 (mod 128) can be safely ignored. */
! if ((err_tag & 127) < 64)
! {
! _bfd_error_handler
! (_("%B: Unknown mandatory EABI object attribute %d"),
! err_bfd, err_tag);
! bfd_set_error (bfd_error_bad_value);
! result = FALSE;
! }
! else
! {
! _bfd_error_handler
! (_("Warning: %B: Unknown EABI object attribute %d"),
! err_bfd, err_tag);
! }
}
}
! return result;
}
Index: gas/config/tc-arm.c
===================================================================
*** gas/config/tc-arm.c.orig
--- gas/config/tc-arm.c
*************** static const cpu_arch_ver_table cpu_arch
*** 20712,20718 ****
{6, ARM_ARCH_V6},
{7, ARM_ARCH_V6Z},
{9, ARM_ARCH_V6K},
! {9, ARM_ARCH_V6M},
{8, ARM_ARCH_V6T2},
{10, ARM_ARCH_V7A},
{10, ARM_ARCH_V7R},
--- 20712,20718 ----
{6, ARM_ARCH_V6},
{7, ARM_ARCH_V6Z},
{9, ARM_ARCH_V6K},
! {11, ARM_ARCH_V6M},
{8, ARM_ARCH_V6T2},
{10, ARM_ARCH_V7A},
{10, ARM_ARCH_V7R},
Index: include/elf/arm.h
===================================================================
*** include/elf/arm.h.orig
--- include/elf/arm.h
***************
*** 85,101 ****
#define PF_ARM_ABS 0x40000000 /* Segment must be loaded at its base address. */
/* Values for the Tag_CPU_arch EABI attribute. */
! #define TAG_CPU_ARCH_PRE_V4 0
! #define TAG_CPU_ARCH_V4 1
! #define TAG_CPU_ARCH_V4T 2
! #define TAG_CPU_ARCH_V5T 3
! #define TAG_CPU_ARCH_V5TE 4
! #define TAG_CPU_ARCH_V5TEJ 5
! #define TAG_CPU_ARCH_V6 6
! #define TAG_CPU_ARCH_V6KZ 7
! #define TAG_CPU_ARCH_V6T2 8
! #define TAG_CPU_ARCH_V6K 9
! #define TAG_CPU_ARCH_V7 10
/* Relocation types. */
--- 85,107 ----
#define PF_ARM_ABS 0x40000000 /* Segment must be loaded at its base address. */
/* Values for the Tag_CPU_arch EABI attribute. */
! #define TAG_CPU_ARCH_PRE_V4 0
! #define TAG_CPU_ARCH_V4 1
! #define TAG_CPU_ARCH_V4T 2
! #define TAG_CPU_ARCH_V5T 3
! #define TAG_CPU_ARCH_V5TE 4
! #define TAG_CPU_ARCH_V5TEJ 5
! #define TAG_CPU_ARCH_V6 6
! #define TAG_CPU_ARCH_V6KZ 7
! #define TAG_CPU_ARCH_V6T2 8
! #define TAG_CPU_ARCH_V6K 9
! #define TAG_CPU_ARCH_V7 10
! #define TAG_CPU_ARCH_V6_M 11
! #define TAG_CPU_ARCH_V6S_M 12
! #define MAX_TAG_CPU_ARCH 12
! /* Pseudo-architecture to allow objects to be compatible with the subset of
! armv4t and armv6-m. This value should never be stored in object files. */
! #define TAG_CPU_ARCH_V4T_PLUS_V6_M (MAX_TAG_CPU_ARCH + 1)
/* Relocation types. */
*************** enum
*** 251,257 ****
Tag_THUMB_ISA_use,
Tag_VFP_arch,
Tag_WMMX_arch,
! Tag_NEON_arch,
Tag_PCS_config,
Tag_ABI_PCS_R9_use,
Tag_ABI_PCS_RW_data,
--- 257,263 ----
Tag_THUMB_ISA_use,
Tag_VFP_arch,
Tag_WMMX_arch,
! Tag_Advanced_SIMD_arch,
Tag_PCS_config,
Tag_ABI_PCS_R9_use,
Tag_ABI_PCS_RW_data,
*************** enum
*** 271,283 ****
Tag_ABI_WMMX_args,
Tag_ABI_optimization_goals,
Tag_ABI_FP_optimization_goals,
! /* 32 is generic. */
Tag_undefined33 = 33,
Tag_CPU_unaligned_access,
! Tag_undefined35,
Tag_VFP_HP_extension,
Tag_undefined37,
! Tag_ABI_FP_16bit_format = 38,
};
#endif
--- 277,297 ----
Tag_ABI_WMMX_args,
Tag_ABI_optimization_goals,
Tag_ABI_FP_optimization_goals,
! /* 32 is generic (Tag_compatibility). */
Tag_undefined33 = 33,
Tag_CPU_unaligned_access,
! Tag_undefined35,
Tag_VFP_HP_extension,
Tag_undefined37,
! Tag_ABI_FP_16bit_format,
! Tag_undefined39,
! Tag_nodefaults = 64,
! Tag_also_compatible_with,
! Tag_T2EE_use,
! Tag_conformance,
! Tag_Virtualization_use,
! Tag_undefined69,
! Tag_MPextension_use
};
#endif