This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Refactor unknown attribute handling
- From: "Joseph S. Myers" <joseph at codesourcery dot com>
- To: binutils at sourceware dot org
- Date: Wed, 3 Nov 2010 17:05:20 +0000 (UTC)
- Subject: Refactor unknown attribute handling
The C6000 EABI requires the same handling of unknown object attributes
by the linker as the ARM EABI. There is enough code involved in that
handling that it seems desirable to share it between the
architectures; this patch refactors it into common functions in
elf-attrs.c with the bulk of the logic for unknown attributes, which
call back to per-architecture functions for the logic for which
attributes are in a range that must be understood (while the ranges
*are* the same for ARM and C6X, it seems best not to hard-code that)
and for giving associated warnings or errors.
This patch is not intended to change the behavior of binutils; a
subsequent patch once this is in will deal with making C6X use this
code and adding associated C6X testcases. Tested with no regressions
with cross to arm-eabi. OK to commit?
2010-11-03 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.
Index: elf-attrs.c
===================================================================
RCS file: /cvs/src/src/bfd/elf-attrs.c,v
retrieving revision 1.12
diff -u -p -r1.12 elf-attrs.c
--- elf-attrs.c 15 Jun 2010 23:10:10 -0000 1.12
+++ elf-attrs.c 3 Nov 2010 16:57:23 -0000
@@ -586,3 +586,114 @@ _bfd_elf_merge_object_attributes (bfd *i
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;
+}
Index: elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.312
diff -u -p -r1.312 elf-bfd.h
--- elf-bfd.h 25 Oct 2010 15:54:13 -0000 1.312
+++ elf-bfd.h 3 Nov 2010 16:57:24 -0000
@@ -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
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
Index: elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.247
diff -u -p -r1.247 elf32-arm.c
--- elf32-arm.c 25 Oct 2010 15:54:13 -0000 1.247
+++ elf32-arm.c 3 Nov 2010 16:57:25 -0000
@@ -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 *ib
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 *ib
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;
- }
- }
+ result &= _bfd_elf_merge_unknown_attribute_list (ibfd, obfd);
- 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_siz
#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"
Index: elfxx-target.h
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-target.h,v
retrieving revision 1.123
diff -u -p -r1.123 elfxx-target.h
--- elfxx-target.h 29 Oct 2010 12:10:24 -0000 1.123
+++ elfxx-target.h 3 Nov 2010 16:57:25 -0000
@@ -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,
--
Joseph S. Myers
joseph@codesourcery.com