GNU attribute output on errors
authorAlan Modra <amodra@gmail.com>
Tue, 3 Jul 2018 05:20:38 +0000 (14:50 +0930)
committerAlan Modra <amodra@gmail.com>
Tue, 3 Jul 2018 07:16:54 +0000 (16:46 +0930)
.gnu.attributes entries from linker input files are merged to the
output file, the output having the union of compatible input
attributes.  Incompatible attributes generally cause a linker error
and no output.  However in some cases only a warning is emitted, and
one of the incompatible input attributes is passed on to the output.

PowerPC tends to emit warnings rather than errors, and the output
takes the first input attribute.  For example, if we have two input
files with Tag_GNU_Power_ABI_FP, the first with a value signifying
"double-precision hard float, IBM long double", the second with a
value signifying "double-precision hard float, IEEE long double",
we'll get a warning about incompatible long double types and the
output will say "double-precision hard float, IBM long double".
The output attribute of course isn't correct.  It would be correct to
specify "IBM and IEEE long double", but we don't have a way to
represent that currently.  While it would be possible to extend the
encoding, there isn't much gain in doing so.  A shared library
providing support for both long double types should link against
objects using either long double type without warning or error.  That
is what you'd get if such a shared library had no Tag_GNU_Power_ABI_FP
attribute.

So this patch provides a way for the backend to omit .gnu.attributes
tags from the output.

* elf-bfd.h (ATTR_TYPE_FLAG_ERROR, ATTR_TYPE_HAS_ERROR): Define.
* elf-attrs.c (is_default_attr): Handle ATTR_TYPE_HAS_ERROR.
* elf32-ppc.c (_bfd_elf_ppc_merge_fp_attributes): Use
ATTR_TYPE_FLAG_INT_VAL.  Set ATTR_TYPE_HAS_ERROR on finding
incompatible attribute.
(ppc_elf_merge_obj_attributes): Likewise.  Return
_bfd_elf_merge_object_attributes result.
* elf64-ppc.c (ppc64_elf_merge_private_bfd_data): Return
_bfd_elf_merge_object_attributes result.

bfd/ChangeLog
bfd/elf-attrs.c
bfd/elf-bfd.h
bfd/elf32-ppc.c
bfd/elf64-ppc.c

index 8ed97651009548b88415e772ef53a718aa5abac6..b4dbd2eec6df984f2fb5784ec9ba1f07f47920ff 100644 (file)
@@ -1,3 +1,15 @@
+2018-07-03  Alan Modra  <amodra@gmail.com>
+
+       * elf-bfd.h (ATTR_TYPE_FLAG_ERROR, ATTR_TYPE_HAS_ERROR): Define.
+       * elf-attrs.c (is_default_attr): Handle ATTR_TYPE_HAS_ERROR.
+       * elf32-ppc.c (_bfd_elf_ppc_merge_fp_attributes): Use
+       ATTR_TYPE_FLAG_INT_VAL.  Set ATTR_TYPE_HAS_ERROR on finding
+       incompatible attribute.
+       (ppc_elf_merge_obj_attributes): Likewise.  Return
+       _bfd_elf_merge_object_attributes result.
+       * elf64-ppc.c (ppc64_elf_merge_private_bfd_data): Return
+       _bfd_elf_merge_object_attributes result.
+
 2018-07-03  Alan Modra  <amodra@gmail.com>
 
        PR 17550
index b3533095fff2ea4d53d7380c95663515435fde74..5c1b96092c2dad6f9baea975c969967a24837814 100644 (file)
@@ -42,6 +42,8 @@ uleb128_size (unsigned int i)
 static bfd_boolean
 is_default_attr (obj_attribute *attr)
 {
+  if (ATTR_TYPE_HAS_ERROR (attr->type))
+    return TRUE;
   if (ATTR_TYPE_HAS_INT_VAL (attr->type) && attr->i != 0)
     return FALSE;
   if (ATTR_TYPE_HAS_STR_VAL (attr->type) && attr->s && *attr->s)
index 788fdf8e3dc7365f698febfa9573174563913f1a..3ed16de89c4b47bd247a407177e8cdc9fec45397 100644 (file)
@@ -1699,17 +1699,20 @@ struct bfd_elf_section_data
 
 /* The value of an object attribute.  The type indicates whether the attribute
    holds and integer, a string, or both.  It can also indicate that there can
-   be no default (i.e. all values must be written to file, even zero).  */
+   be no default (i.e. all values must be written to file, even zero), or
+   that the value is in error and should not be written to file.  */
 
 typedef struct obj_attribute
 {
 #define ATTR_TYPE_FLAG_INT_VAL    (1 << 0)
 #define ATTR_TYPE_FLAG_STR_VAL    (1 << 1)
 #define ATTR_TYPE_FLAG_NO_DEFAULT (1 << 2)
+#define ATTR_TYPE_FLAG_ERROR     (1 << 3)
 
 #define ATTR_TYPE_HAS_INT_VAL(TYPE)    ((TYPE) & ATTR_TYPE_FLAG_INT_VAL)
 #define ATTR_TYPE_HAS_STR_VAL(TYPE)    ((TYPE) & ATTR_TYPE_FLAG_STR_VAL)
 #define ATTR_TYPE_HAS_NO_DEFAULT(TYPE) ((TYPE) & ATTR_TYPE_FLAG_NO_DEFAULT)
+#define ATTR_TYPE_HAS_ERROR(TYPE)      ((TYPE) & ATTR_TYPE_FLAG_ERROR)
 
   int type;
   unsigned int i;
index ea8dbed9819d8dcb461091e6d00becc07fa320f6..a97e127948525fc542f6f60b292d36c5435aed97 100644 (file)
@@ -4735,27 +4735,41 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info)
        ;
       else if (out_fp == 0)
        {
-         out_attr->type = 1;
+         out_attr->type = ATTR_TYPE_FLAG_INT_VAL;
          out_attr->i ^= in_fp;
        }
       else if (out_fp != 2 && in_fp == 2)
-       _bfd_error_handler
-         /* xgettext:c-format */
-         (_("warning: %pB uses hard float, %pB uses soft float"), obfd, ibfd);
+       {
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("warning: %pB uses hard float, %pB uses soft float"),
+            obfd, ibfd);
+         out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR;
+       }
       else if (out_fp == 2 && in_fp != 2)
-       _bfd_error_handler
-         /* xgettext:c-format */
-         (_("warning: %pB uses hard float, %pB uses soft float"), ibfd, obfd);
+       {
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("warning: %pB uses hard float, %pB uses soft float"),
+            ibfd, obfd);
+         out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR;
+       }
       else if (out_fp == 1 && in_fp == 3)
-       _bfd_error_handler
-         /* xgettext:c-format */
-         (_("warning: %pB uses double-precision hard float, "
-            "%pB uses single-precision hard float"), obfd, ibfd);
+       {
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("warning: %pB uses double-precision hard float, "
+              "%pB uses single-precision hard float"), obfd, ibfd);
+         out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR;
+       }
       else if (out_fp == 3 && in_fp == 1)
-       _bfd_error_handler
-         /* xgettext:c-format */
-         (_("warning: %pB uses double-precision hard float, "
-            "%pB uses single-precision hard float"), ibfd, obfd);
+       {
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("warning: %pB uses double-precision hard float, "
+              "%pB uses single-precision hard float"), ibfd, obfd);
+         out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR;
+       }
 
       in_fp = in_attr->i & 0xc;
       out_fp = out_attr->i & 0xc;
@@ -4763,29 +4777,41 @@ _bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, struct bfd_link_info *info)
        ;
       else if (out_fp == 0)
        {
-         out_attr->type = 1;
+         out_attr->type = ATTR_TYPE_FLAG_INT_VAL;
          out_attr->i ^= in_fp;
        }
       else if (out_fp != 2 * 4 && in_fp == 2 * 4)
-       _bfd_error_handler
-         /* xgettext:c-format */
-         (_("warning: %pB uses 64-bit long double, "
-            "%pB uses 128-bit long double"), ibfd, obfd);
+       {
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("warning: %pB uses 64-bit long double, "
+              "%pB uses 128-bit long double"), ibfd, obfd);
+         out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR;
+       }
       else if (in_fp != 2 * 4 && out_fp == 2 * 4)
-       _bfd_error_handler
-         /* xgettext:c-format */
-         (_("warning: %pB uses 64-bit long double, "
-            "%pB uses 128-bit long double"), obfd, ibfd);
+       {
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("warning: %pB uses 64-bit long double, "
+              "%pB uses 128-bit long double"), obfd, ibfd);
+         out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR;
+       }
       else if (out_fp == 1 * 4 && in_fp == 3 * 4)
-       _bfd_error_handler
-         /* xgettext:c-format */
-         (_("warning: %pB uses IBM long double, "
-            "%pB uses IEEE long double"), obfd, ibfd);
+       {
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("warning: %pB uses IBM long double, "
+              "%pB uses IEEE long double"), obfd, ibfd);
+         out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR;
+       }
       else if (out_fp == 3 * 4 && in_fp == 1 * 4)
-       _bfd_error_handler
-         /* xgettext:c-format */
-         (_("warning: %pB uses IBM long double, "
-            "%pB uses IEEE long double"), ibfd, obfd);
+       {
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("warning: %pB uses IBM long double, "
+              "%pB uses IEEE long double"), ibfd, obfd);
+         out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR;
+       }
     }
 }
 
@@ -4817,7 +4843,7 @@ ppc_elf_merge_obj_attributes (bfd *ibfd, struct bfd_link_info *info)
        ;
       else if (out_vec == 0)
        {
-         out_attr->type = 1;
+         out_attr->type = ATTR_TYPE_FLAG_INT_VAL;
          out_attr->i = in_vec;
        }
       /* For now, allow generic to transition to AltiVec or SPE
@@ -4829,19 +4855,25 @@ ppc_elf_merge_obj_attributes (bfd *ibfd, struct bfd_link_info *info)
        ;
       else if (out_vec == 1)
        {
-         out_attr->type = 1;
+         out_attr->type = ATTR_TYPE_FLAG_INT_VAL;
          out_attr->i = in_vec;
        }
       else if (out_vec < in_vec)
-       _bfd_error_handler
-         /* xgettext:c-format */
-         (_("warning: %pB uses AltiVec vector ABI, %pB uses SPE vector ABI"),
-          obfd, ibfd);
+       {
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("warning: %pB uses AltiVec vector ABI, %pB uses SPE vector ABI"),
+            obfd, ibfd);
+         out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR;
+       }
       else if (out_vec > in_vec)
-       _bfd_error_handler
-         /* xgettext:c-format */
-         (_("warning: %pB uses AltiVec vector ABI, %pB uses SPE vector ABI"),
-          ibfd, obfd);
+       {
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("warning: %pB uses AltiVec vector ABI, %pB uses SPE vector ABI"),
+            ibfd, obfd);
+         out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR;
+       }
     }
 
   /* Check for conflicting Tag_GNU_Power_ABI_Struct_Return attributes
@@ -4857,25 +4889,29 @@ ppc_elf_merge_obj_attributes (bfd *ibfd, struct bfd_link_info *info)
        ;
       else if (out_struct == 0)
        {
-         out_attr->type = 1;
+         out_attr->type = ATTR_TYPE_FLAG_INT_VAL;
          out_attr->i = in_struct;
        }
       else if (out_struct < in_struct)
-       _bfd_error_handler
-         /* xgettext:c-format */
-         (_("warning: %pB uses r3/r4 for small structure returns, "
-            "%pB uses memory"), obfd, ibfd);
+       {
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("warning: %pB uses r3/r4 for small structure returns, "
+              "%pB uses memory"), obfd, ibfd);
+         out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR;
+       }
       else if (out_struct > in_struct)
-       _bfd_error_handler
-         /* xgettext:c-format */
-         (_("warning: %pB uses r3/r4 for small structure returns, "
-            "%pB uses memory"), ibfd, obfd);
+       {
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("warning: %pB uses r3/r4 for small structure returns, "
+              "%pB uses memory"), ibfd, obfd);
+         out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR;
+       }
     }
 
   /* Merge Tag_compatibility attributes and any common GNU ones.  */
-  _bfd_elf_merge_object_attributes (ibfd, info);
-
-  return TRUE;
+  return _bfd_elf_merge_object_attributes (ibfd, info);
 }
 
 /* Merge backend specific data from an object file to the output
index 16199fbe3ed4295affbd9aafa2e15f0ce9086be7..894a3b7d1ac833d8b09965f47b13154a8535c267 100644 (file)
@@ -6180,9 +6180,7 @@ ppc64_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
   _bfd_elf_ppc_merge_fp_attributes (ibfd, info);
 
   /* Merge Tag_compatibility attributes and any common GNU ones.  */
-  _bfd_elf_merge_object_attributes (ibfd, info);
-
-  return TRUE;
+  return _bfd_elf_merge_object_attributes (ibfd, info);
 }
 
 static bfd_boolean