summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2010-11-04 11:35:01 +0000
committerJoseph Myers <joseph@codesourcery.com>2010-11-04 11:35:01 +0000
commite8b36cd1e57055ea2eb1e2ba2692f1ec520b34db (patch)
tree317666abafb1d4aa2ff281b3b31f9d8c59ecd8a8
parent608bcef2676e2019d046ff7a485c47fd0b8606bd (diff)
downloadbinutils-gdb-e8b36cd1e57055ea2eb1e2ba2692f1ec520b34db.tar.gz
* elf-attrs.c (_bfd_elf_merge_unknown_attribute_low,
_bfd_elf_merge_unknown_attribute_list): New. * elf-bfd.h (struct elf_backend_data): Add obj_attrs_handle_unknown. (_bfd_elf_merge_unknown_attribute_low, _bfd_elf_merge_unknown_attribute_list): Declare. * elf32-arm.c (elf32_arm_obj_attrs_handle_unknown): New. Split out from elf32_arm_merge_eabi_attributes. (elf32_arm_merge_eabi_attributes): Use _bfd_elf_merge_unknown_attribute_low and _bfd_elf_merge_unknown_attribute_list. (elf_backend_obj_attrs_handle_unknown): Define. * elfxx-target.h (elf_backend_obj_attrs_handle_unknown): Define. (elfNN_bed): Update initializer.
-rw-r--r--bfd/ChangeLog17
-rw-r--r--bfd/elf-attrs.c111
-rw-r--r--bfd/elf-bfd.h6
-rw-r--r--bfd/elf32-arm.c131
-rw-r--r--bfd/elfxx-target.h4
5 files changed, 163 insertions, 106 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 24d096b4674..2a14bc6f668 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,20 @@
+2010-11-04 Joseph Myers <joseph@codesourcery.com>
+
+ * elf-attrs.c (_bfd_elf_merge_unknown_attribute_low,
+ _bfd_elf_merge_unknown_attribute_list): New.
+ * elf-bfd.h (struct elf_backend_data): Add
+ obj_attrs_handle_unknown.
+ (_bfd_elf_merge_unknown_attribute_low,
+ _bfd_elf_merge_unknown_attribute_list): Declare.
+ * elf32-arm.c (elf32_arm_obj_attrs_handle_unknown): New. Split
+ out from elf32_arm_merge_eabi_attributes.
+ (elf32_arm_merge_eabi_attributes): Use
+ _bfd_elf_merge_unknown_attribute_low and
+ _bfd_elf_merge_unknown_attribute_list.
+ (elf_backend_obj_attrs_handle_unknown): Define.
+ * elfxx-target.h (elf_backend_obj_attrs_handle_unknown): Define.
+ (elfNN_bed): Update initializer.
+
2010-11-02 H.J. Lu <hongjiu.lu@intel.com>
* bfd.c (BFD_FLAGS_FOR_BFD_USE_MASK): New.
diff --git a/bfd/elf-attrs.c b/bfd/elf-attrs.c
index b9d3bf2fe4e..e1893d38d94 100644
--- a/bfd/elf-attrs.c
+++ b/bfd/elf-attrs.c
@@ -586,3 +586,114 @@ _bfd_elf_merge_object_attributes (bfd *ibfd, bfd *obfd)
return TRUE;
}
+
+/* Merge an unknown processor-specific attribute TAG, within the range
+ of known attributes, from IBFD into OBFD; return TRUE if the link
+ is OK, FALSE if it must fail. */
+
+bfd_boolean
+_bfd_elf_merge_unknown_attribute_low (bfd *ibfd, bfd *obfd, int tag)
+{
+ obj_attribute *in_attr;
+ obj_attribute *out_attr;
+ bfd *err_bfd = NULL;
+ bfd_boolean result = TRUE;
+
+ in_attr = elf_known_obj_attributes_proc (ibfd);
+ out_attr = elf_known_obj_attributes_proc (obfd);
+
+ if (out_attr[tag].i != 0 || out_attr[tag].s != NULL)
+ err_bfd = obfd;
+ else if (in_attr[tag].i != 0 || in_attr[tag].s != NULL)
+ err_bfd = ibfd;
+
+ if (err_bfd != NULL)
+ result
+ = get_elf_backend_data (err_bfd)->obj_attrs_handle_unknown (err_bfd, tag);
+
+ /* Only pass on attributes that match in both inputs. */
+ if (in_attr[tag].i != out_attr[tag].i
+ || in_attr[tag].s != out_attr[tag].s
+ || (in_attr[tag].s != NULL && out_attr[tag].s != NULL
+ && strcmp (in_attr[tag].s, out_attr[tag].s) != 0))
+ {
+ out_attr[tag].i = 0;
+ out_attr[tag].s = NULL;
+ }
+
+ return result;
+}
+
+/* Merge the lists of unknown processor-specific attributes, outside
+ the known range, from IBFD into OBFD; return TRUE if the link is
+ OK, FALSE if it must fail. */
+
+bfd_boolean
+_bfd_elf_merge_unknown_attribute_list (bfd *ibfd, bfd *obfd)
+{
+ obj_attribute_list *in_list;
+ obj_attribute_list *out_list;
+ obj_attribute_list **out_listp;
+ bfd_boolean result = TRUE;
+
+ 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)
+ result = result
+ && get_elf_backend_data (err_bfd)->obj_attrs_handle_unknown (err_bfd,
+ err_tag);
+ }
+
+ return result;
+}
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index e306f8d5657..2e607f8ee66 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -1256,6 +1256,10 @@ struct elf_backend_data
actual tag number to place in the input position. */
int (*obj_attrs_order) (int);
+ /* Handle merging unknown attributes; either warn and return TRUE,
+ or give an error and return FALSE. */
+ bfd_boolean (*obj_attrs_handle_unknown) (bfd *, int);
+
/* This is non-zero if static TLS segments require a special alignment. */
unsigned static_tls_alignment;
@@ -2235,6 +2239,8 @@ extern void _bfd_elf_copy_obj_attributes (bfd *, bfd *);
extern int _bfd_elf_obj_attrs_arg_type (bfd *, int, int);
extern void _bfd_elf_parse_attributes (bfd *, Elf_Internal_Shdr *);
extern bfd_boolean _bfd_elf_merge_object_attributes (bfd *, bfd *);
+extern bfd_boolean _bfd_elf_merge_unknown_attribute_low (bfd *, bfd *, int);
+extern bfd_boolean _bfd_elf_merge_unknown_attribute_list (bfd *, bfd *);
extern Elf_Internal_Shdr *_bfd_elf_single_rel_hdr (asection *sec);
/* The linker may needs to keep track of the number of relocs that it
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 24a50a3d44e..577060b57e7 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -9653,6 +9653,27 @@ elf32_arm_obj_attrs_order (int num)
return num;
}
+/* Attribute numbers >=64 (mod 128) can be safely ignored. */
+static bfd_boolean
+elf32_arm_obj_attrs_handle_unknown (bfd *abfd, int tag)
+{
+ if ((tag & 127) < 64)
+ {
+ _bfd_error_handler
+ (_("%B: Unknown mandatory EABI object attribute %d"),
+ abfd, tag);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+ else
+ {
+ _bfd_error_handler
+ (_("Warning: %B: Unknown EABI object attribute %d"),
+ abfd, tag);
+ return TRUE;
+ }
+}
+
/* Read the architecture from the Tag_also_compatible_with attribute, if any.
Returns -1 if no architecture could be read. */
@@ -10382,45 +10403,8 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
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;
- }
- }
+ result
+ = result && _bfd_elf_merge_unknown_attribute_low (ibfd, obfd, i);
}
/* If out_attr was copied from in_attr then it won't have a type yet. */
@@ -10437,74 +10421,8 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
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;
+ result &= _bfd_elf_merge_unknown_attribute_list (ibfd, obfd);
- /* 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;
}
@@ -13977,6 +13895,7 @@ const struct elf_size_info elf32_arm_size_info =
#undef elf_backend_obj_attrs_section_type
#define elf_backend_obj_attrs_section_type SHT_ARM_ATTRIBUTES
#define elf_backend_obj_attrs_order elf32_arm_obj_attrs_order
+#define elf_backend_obj_attrs_handle_unknown elf32_arm_obj_attrs_handle_unknown
#include "elf32-target.h"
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index 6695afcc63f..fab1b04ec33 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -477,6 +477,9 @@
#ifndef elf_backend_obj_attrs_order
#define elf_backend_obj_attrs_order NULL
#endif
+#ifndef elf_backend_obj_attrs_handle_unknown
+#define elf_backend_obj_attrs_handle_unknown NULL
+#endif
#ifndef elf_backend_static_tls_alignment
#define elf_backend_static_tls_alignment 1
#endif
@@ -741,6 +744,7 @@ static struct elf_backend_data elfNN_bed =
elf_backend_obj_attrs_arg_type,
elf_backend_obj_attrs_section_type,
elf_backend_obj_attrs_order,
+ elf_backend_obj_attrs_handle_unknown,
elf_backend_static_tls_alignment,
elf_backend_collect,
elf_backend_type_change_ok,