From: Andrew Stubbs Date: Thu, 15 Jan 2009 18:00:49 +0000 (+0000) Subject: 2009-01-15 Andrew Stubbs X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=91e22acdfab8ca330673117a7634ce8e09cd9992;p=binutils-gdb.git 2009-01-15 Andrew Stubbs Julian Brown 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. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 84426d6a7fd..75c36933a9a 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,25 @@ +2009-01-15 Andrew Stubbs + Julian Brown + + * 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. + 2009-01-15 Andrew Stubbs * elf-attrs.c (bfd_elf_add_obj_attr_compat): Rename to diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 5e13a653d1b..14825a45cd6 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -1369,7 +1369,7 @@ struct elf_find_verdep_info }; /* The maximum number of known object attributes for any target. */ -#define NUM_KNOWN_OBJ_ATTRIBUTES 33 +#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 diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 705d4fc3882..ece1a56ccfc 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -8147,31 +8147,207 @@ elf32_arm_obj_attrs_arg_type (int tag) 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 -elf32_arm_copy_one_eabi_other_attribute (bfd *ibfd, bfd *obfd, obj_attribute_list *in_list) +set_secondary_compatible_arch (bfd *abfd, int arch) { - 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; + obj_attribute *attr = + &elf_known_obj_attributes_proc (abfd)[Tag_also_compatible_with]; - default: - if ((in_list->tag & 127) < 64) - { - _bfd_error_handler - (_("Warning: %B: Unknown EABI object attribute %d"), ibfd, in_list->tag); - break; - } + 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'; } -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); +/* 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 @@ -8184,12 +8360,14 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) 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_312[3] = {3, 1, 2}; + 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) { @@ -8216,7 +8394,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) _bfd_error_handler (_("ERROR: %B uses VFP register arguments, %B does not"), ibfd, obfd); - return FALSE; + result = FALSE; } } @@ -8227,12 +8405,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) { 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); + /* These are merged after Tag_CPU_arch. */ break; case Tag_ABI_optimization_goals: @@ -8241,38 +8414,148 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) 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_NEON_arch: - /* ??? Do NEON and WMMX conflict? */ + case Tag_Advanced_SIMD_arch: + /* ??? Do Advanced_SIMD (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: + 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_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) + 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: Conflicting architecture profiles %c/%c"), - ibfd, in_attr[i].i, out_attr[i].i); - return FALSE; + (_("ERROR: %B: 8-byte data alignment conflicts with %B"), + obfd, ibfd); + result = FALSE; */ } - if (in_attr[i].i) + /* 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: - if (in_attr[i].i > 4 || out_attr[i].i > 4 - || order_01243[in_attr[i].i] > order_01243[out_attr[i].i]) + /* 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: @@ -8293,7 +8576,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) { _bfd_error_handler (_("ERROR: %B: Conflicting use of R9"), ibfd); - return FALSE; + result = FALSE; } if (out_attr[i].i == AEABI_R9_unused) out_attr[i].i = in_attr[i].i; @@ -8306,22 +8589,12 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) _bfd_error_handler (_("ERROR: %B: SB relative addressing conflicts with use of R9"), ibfd); - return FALSE; + 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_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) @@ -8333,12 +8606,6 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) 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) { @@ -8353,12 +8620,19 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) && out_attr[i].i != in_attr[i].i && !elf_arm_tdata (obfd)->no_enum_size_warning) { - const char *aeabi_enum_names[] = + 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] + : ""; + const char *out_name = + out_attr[i].i < ARRAY_SIZE(aeabi_enum_names) + ? aeabi_enum_names[out_attr[i].i] + : ""; _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]); + ibfd, in_name, out_name); } } break; @@ -8371,34 +8645,98 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) _bfd_error_handler (_("ERROR: %B uses iWMMXt register arguments, %B does not"), ibfd, obfd); - return FALSE; + 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; - default: /* All known attributes should be explicitly covered. */ - abort (); - } + 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; - if (in_attr[i].type && !out_attr[i].type) - switch (in_attr[i].type) + default: { - case 1: - if (out_attr[i].i) - out_attr[i].type = 1; - break; + bfd *err_bfd = NULL; - case 2: - if (out_attr[i].s) - out_attr[i].type = 2; - break; + /* 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; - default: - abort (); + 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. */ @@ -8406,67 +8744,78 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) /* Check for any attributes not known on ARM. */ in_list = elf_other_obj_attributes_proc (ibfd); - out_list = elf_other_obj_attributes_proc (obfd); + out_listp = &elf_other_obj_attributes_proc (obfd); + out_list = *out_listp; - for (; in_list != NULL; ) + for (; in_list || out_list; ) { - if (out_list == NULL) - { - elf32_arm_copy_eabi_other_attribute_list (ibfd, obfd, in_list); - return TRUE; - } + 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 (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) + if (out_list && (!in_list || 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); + /* 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; } - if (in_list->tag <= out_list->tag) + 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; - if (in_list == NULL) - continue; } - while (out_list && out_list->tag < in_list->tag) - out_list = out_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 TRUE; + return result; } diff --git a/gas/ChangeLog b/gas/ChangeLog index 7740294e9da..db2c7724f1f 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,8 @@ +2009-01-15 Andrew Stubbs + Julian Brown + + * config/tc-arm.c (cpu_arch): Change ARM_ARCH_V6M to 11. + 2009-01-15 Andrew Stubbs * read.c (s_vendor_attribute): bfd_elf_add_obj_attr_compat -> diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 5998e5555ba..a8aca804750 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -20719,7 +20719,7 @@ static const cpu_arch_ver_table cpu_arch_ver[] = {6, ARM_ARCH_V6}, {7, ARM_ARCH_V6Z}, {9, ARM_ARCH_V6K}, - {9, ARM_ARCH_V6M}, + {11, ARM_ARCH_V6M}, {8, ARM_ARCH_V6T2}, {10, ARM_ARCH_V7A}, {10, ARM_ARCH_V7R}, diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog index 367702b4a83..3faff0d2e4a 100644 --- a/include/elf/ChangeLog +++ b/include/elf/ChangeLog @@ -1,3 +1,15 @@ +2009-01-15 Andrew Stubbs + Julian Brown + + * 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. + 2009-01-15 Douglas B Rupp * ia64.h (SHT_IA_64_VMS_DISPLAY_NAME_INFO, EF_IA_64_ARCHVER_1): diff --git a/include/elf/arm.h b/include/elf/arm.h index ade479c92f9..ed8a26ee4b9 100644 --- a/include/elf/arm.h +++ b/include/elf/arm.h @@ -85,17 +85,23 @@ #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_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. */ @@ -251,7 +257,7 @@ enum Tag_THUMB_ISA_use, Tag_VFP_arch, Tag_WMMX_arch, - Tag_NEON_arch, + Tag_Advanced_SIMD_arch, Tag_PCS_config, Tag_ABI_PCS_R9_use, Tag_ABI_PCS_RW_data, @@ -271,13 +277,21 @@ enum Tag_ABI_WMMX_args, Tag_ABI_optimization_goals, Tag_ABI_FP_optimization_goals, - /* 32 is generic. */ + /* 32 is generic (Tag_compatibility). */ Tag_undefined33 = 33, Tag_CPU_unaligned_access, - Tag_undefined35, + Tag_undefined35, Tag_VFP_HP_extension, Tag_undefined37, - Tag_ABI_FP_16bit_format = 38, + 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