This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]