aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-ppc.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2016-09-26 18:04:57 +0930
committerAlan Modra <amodra@gmail.com>2016-09-26 18:04:57 +0930
commit005d79fd6101dae0aaf62a1b0cee399efcbd0e21 (patch)
tree4035e4a8d7549d7b66bd522e41b9f238202b8131 /bfd/elf32-ppc.c
parent153679d55f9e74c369ca67444bdbaad82855cc6e (diff)
PowerPC .gnu.attributes
This patch extends Tag_GNU_Power_ABI_FP to cover long double ABIs, makes the assembler warn about undefined tag values, and removes similar warnings from the linker. I think it is better to not warn in the linker about undefined tag values as future extensions to the tags then won't result in likely bogus warnings. This is consistent with the fact that an older linker won't warn on an entirely new tag. include/ * elf/ppc.h (Tag_GNU_Power_ABI_FP): Comment. bfd/ * elf-bfd.h (_bfd_elf_ppc_merge_fp_attributes): Declare. * elf32-ppc.c (_bfd_elf_ppc_merge_fp_attributes): New function. (ppc_elf_merge_obj_attributes): Use it. Don't copy first file attributes, merge them. Don't warn about undefined tag bits, or copy unknown values to output. * elf64-ppc.c (ppc64_elf_merge_private_bfd_data): Call _bfd_elf_ppc_merge_fp_attributes. binutils/ * readelf.c (display_power_gnu_attribute): Catch truncated section for all powerpc attributes. Display long double ABI. Don't capitalize words, except for names. Show known bits of tag values when some unknown bits are present. Whitespace fixes. gas/ * config/tc-ppc.c (ppc_elf_gnu_attribute): New function. (md_pseudo_table <ELF>): Handle "gnu_attribute". ld/ * testsuite/ld-powerpc/attr-gnu-4-4.s: Delete. * testsuite/ld-powerpc/attr-gnu-4-14.d: Delete. * testsuite/ld-powerpc/attr-gnu-4-24.d: Delete. * testsuite/ld-powerpc/attr-gnu-4-34.d: Delete. * testsuite/ld-powerpc/attr-gnu-4-41.d: Delete. * testsuite/ld-powerpc/attr-gnu-4-32.d: Adjust expected warning. * testsuite/ld-powerpc/attr-gnu-8-23.d: Likewise. * testsuite/ld-powerpc/attr-gnu-4-01.d: Adjust expected output. * testsuite/ld-powerpc/attr-gnu-4-02.d: Likewise. * testsuite/ld-powerpc/attr-gnu-4-03.d: Likewise. * testsuite/ld-powerpc/attr-gnu-4-10.d: Likewise. * testsuite/ld-powerpc/attr-gnu-4-11.d: Likewise. * testsuite/ld-powerpc/attr-gnu-4-20.d: Likewise. * testsuite/ld-powerpc/attr-gnu-4-22.d: Likewise. * testsuite/ld-powerpc/attr-gnu-4-33.d: Likewise. * testsuite/ld-powerpc/attr-gnu-8-11.d: Likewise. * testsuite/ld-powerpc/powerpc.exp: Don't run deleted tests.
Diffstat (limited to 'bfd/elf32-ppc.c')
-rw-r--r--bfd/elf32-ppc.c186
1 files changed, 96 insertions, 90 deletions
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index e808cb523f..dd56a95bf8 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -4653,68 +4653,87 @@ ppc_elf_check_relocs (bfd *abfd,
return TRUE;
}
-
-/* Merge object attributes from IBFD into OBFD. Raise an error if
- there are conflicting attributes. */
-static bfd_boolean
-ppc_elf_merge_obj_attributes (bfd *ibfd, bfd *obfd)
+/* Warn for conflicting Tag_GNU_Power_ABI_FP attributes between IBFD
+ and OBFD, and merge non-conflicting ones. */
+void
+_bfd_elf_ppc_merge_fp_attributes (bfd *ibfd, bfd *obfd)
{
obj_attribute *in_attr, *in_attrs;
obj_attribute *out_attr, *out_attrs;
- if (!elf_known_obj_attributes_proc (obfd)[0].i)
- {
- /* This is the first object. Copy the attributes. */
- _bfd_elf_copy_obj_attributes (ibfd, obfd);
-
- /* Use the Tag_null value to indicate the attributes have been
- initialized. */
- elf_known_obj_attributes_proc (obfd)[0].i = 1;
-
- return TRUE;
- }
-
in_attrs = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU];
out_attrs = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU];
- /* Check for conflicting Tag_GNU_Power_ABI_FP attributes and merge
- non-conflicting ones. */
in_attr = &in_attrs[Tag_GNU_Power_ABI_FP];
out_attr = &out_attrs[Tag_GNU_Power_ABI_FP];
+
if (in_attr->i != out_attr->i)
{
- out_attr->type = 1;
- if (out_attr->i == 0)
- out_attr->i = in_attr->i;
- else if (in_attr->i == 0)
+ int in_fp = in_attr->i & 3;
+ int out_fp = out_attr->i & 3;
+
+ if (in_fp == 0)
;
- else if (out_attr->i == 1 && in_attr->i == 2)
+ else if (out_fp == 0)
+ {
+ out_attr->type = 1;
+ out_attr->i ^= in_fp;
+ }
+ else if (out_fp != 2 && in_fp == 2)
_bfd_error_handler
(_("Warning: %B uses hard float, %B uses soft float"), obfd, ibfd);
- else if (out_attr->i == 1 && in_attr->i == 3)
+ else if (out_fp == 2 && in_fp != 2)
_bfd_error_handler
- (_("Warning: %B uses double-precision hard float, %B uses single-precision hard float"),
- obfd, ibfd);
- else if (out_attr->i == 3 && in_attr->i == 1)
+ (_("Warning: %B uses hard float, %B uses soft float"), ibfd, obfd);
+ else if (out_fp == 1 && in_fp == 3)
_bfd_error_handler
- (_("Warning: %B uses double-precision hard float, %B uses single-precision hard float"),
- ibfd, obfd);
- else if (out_attr->i == 3 && in_attr->i == 2)
+ (_("Warning: %B uses double-precision hard float, "
+ "%B uses single-precision hard float"), obfd, ibfd);
+ else if (out_fp == 3 && in_fp == 1)
_bfd_error_handler
- (_("Warning: %B uses soft float, %B uses single-precision hard float"),
- ibfd, obfd);
- else if (out_attr->i == 2 && (in_attr->i == 1 || in_attr->i == 3))
+ (_("Warning: %B uses double-precision hard float, "
+ "%B uses single-precision hard float"), ibfd, obfd);
+
+ in_fp = in_attr->i & 0xc;
+ out_fp = out_attr->i & 0xc;
+ if (in_fp == 0)
+ ;
+ else if (out_fp == 0)
+ {
+ out_attr->type = 1;
+ out_attr->i ^= in_fp;
+ }
+ else if (out_fp != 2 * 4 && in_fp == 2 * 4)
_bfd_error_handler
- (_("Warning: %B uses hard float, %B uses soft float"), ibfd, obfd);
- else if (in_attr->i > 3)
+ (_("Warning: %B uses 64-bit long double, "
+ "%B uses 128-bit long double"), ibfd, obfd);
+ else if (in_fp != 2 * 4 && out_fp == 2 * 4)
_bfd_error_handler
- (_("Warning: %B uses unknown floating point ABI %d"), ibfd,
- in_attr->i);
- else
+ (_("Warning: %B uses 64-bit long double, "
+ "%B uses 128-bit long double"), obfd, ibfd);
+ else if (out_fp == 1 * 4 && in_fp == 3 * 4)
+ _bfd_error_handler
+ (_("Warning: %B uses IBM long double, "
+ "%B uses IEEE long double"), ibfd, obfd);
+ else if (out_fp == 3 * 4 && in_fp == 1 * 4)
_bfd_error_handler
- (_("Warning: %B uses unknown floating point ABI %d"), obfd,
- out_attr->i);
+ (_("Warning: %B uses IBM long double, "
+ "%B uses IEEE long double"), obfd, ibfd);
}
+}
+
+/* Merge object attributes from IBFD into OBFD. Warn if
+ there are conflicting attributes. */
+static bfd_boolean
+ppc_elf_merge_obj_attributes (bfd *ibfd, bfd *obfd)
+{
+ obj_attribute *in_attr, *in_attrs;
+ obj_attribute *out_attr, *out_attrs;
+
+ _bfd_elf_ppc_merge_fp_attributes (ibfd, obfd);
+
+ in_attrs = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU];
+ out_attrs = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU];
/* Check for conflicting Tag_GNU_Power_ABI_Vector attributes and
merge non-conflicting ones. */
@@ -4722,48 +4741,36 @@ ppc_elf_merge_obj_attributes (bfd *ibfd, bfd *obfd)
out_attr = &out_attrs[Tag_GNU_Power_ABI_Vector];
if (in_attr->i != out_attr->i)
{
- const char *in_abi = NULL, *out_abi = NULL;
-
- switch (in_attr->i)
- {
- case 1: in_abi = "generic"; break;
- case 2: in_abi = "AltiVec"; break;
- case 3: in_abi = "SPE"; break;
- }
+ int in_vec = in_attr->i & 3;
+ int out_vec = out_attr->i & 3;
- switch (out_attr->i)
+ if (in_vec == 0)
+ ;
+ else if (out_vec == 0)
{
- case 1: out_abi = "generic"; break;
- case 2: out_abi = "AltiVec"; break;
- case 3: out_abi = "SPE"; break;
+ out_attr->type = 1;
+ out_attr->i = in_vec;
}
-
- out_attr->type = 1;
- if (out_attr->i == 0)
- out_attr->i = in_attr->i;
- else if (in_attr->i == 0)
- ;
/* For now, allow generic to transition to AltiVec or SPE
without a warning. If GCC marked files with their stack
alignment and used don't-care markings for files which are
not affected by the vector ABI, we could warn about this
case too. */
- else if (out_attr->i == 1)
- out_attr->i = in_attr->i;
- else if (in_attr->i == 1)
+ else if (in_vec == 1)
;
- else if (in_abi == NULL)
- _bfd_error_handler
- (_("Warning: %B uses unknown vector ABI %d"), ibfd,
- in_attr->i);
- else if (out_abi == NULL)
+ else if (out_vec == 1)
+ {
+ out_attr->type = 1;
+ out_attr->i = in_vec;
+ }
+ else if (out_vec < in_vec)
_bfd_error_handler
- (_("Warning: %B uses unknown vector ABI %d"), obfd,
- in_attr->i);
- else
+ (_("Warning: %B uses AltiVec vector ABI, %B uses SPE vector ABI"),
+ obfd, ibfd);
+ else if (out_vec > in_vec)
_bfd_error_handler
- (_("Warning: %B uses vector ABI \"%s\", %B uses \"%s\""),
- ibfd, obfd, in_abi, out_abi);
+ (_("Warning: %B uses AltiVec vector ABI, %B uses SPE vector ABI"),
+ ibfd, obfd);
}
/* Check for conflicting Tag_GNU_Power_ABI_Struct_Return attributes
@@ -4772,25 +4779,24 @@ ppc_elf_merge_obj_attributes (bfd *ibfd, bfd *obfd)
out_attr = &out_attrs[Tag_GNU_Power_ABI_Struct_Return];
if (in_attr->i != out_attr->i)
{
- out_attr->type = 1;
- if (out_attr->i == 0)
- out_attr->i = in_attr->i;
- else if (in_attr->i == 0)
+ int in_struct = in_attr->i & 3;
+ int out_struct = out_attr->i & 3;
+
+ if (in_struct == 0 || in_struct == 3)
;
- else if (out_attr->i == 1 && in_attr->i == 2)
- _bfd_error_handler
- (_("Warning: %B uses r3/r4 for small structure returns, %B uses memory"), obfd, ibfd);
- else if (out_attr->i == 2 && in_attr->i == 1)
- _bfd_error_handler
- (_("Warning: %B uses r3/r4 for small structure returns, %B uses memory"), ibfd, obfd);
- else if (in_attr->i > 2)
- _bfd_error_handler
- (_("Warning: %B uses unknown small structure return convention %d"), ibfd,
- in_attr->i);
- else
- _bfd_error_handler
- (_("Warning: %B uses unknown small structure return convention %d"), obfd,
- out_attr->i);
+ else if (out_struct == 0)
+ {
+ out_attr->type = 1;
+ out_attr->i = in_struct;
+ }
+ else if (out_struct < in_struct)
+ _bfd_error_handler
+ (_("Warning: %B uses r3/r4 for small structure returns, "
+ "%B uses memory"), obfd, ibfd);
+ else if (out_struct > in_struct)
+ _bfd_error_handler
+ (_("Warning: %B uses r3/r4 for small structure returns, "
+ "%B uses memory"), ibfd, obfd);
}
/* Merge Tag_compatibility attributes and any common GNU ones. */