m68k: tag floating-point ABI used
authorPat Bernardi <bernardi@adacore.com>
Thu, 25 Jun 2020 20:05:38 +0000 (16:05 -0400)
committerAlan Modra <amodra@gmail.com>
Fri, 26 Jun 2020 05:12:19 +0000 (14:42 +0930)
This patch adds GNU attribute support to m68k and utilises it to tag the
floating-point calling convention used (hard-float or soft-float). It enables
the linker to ensure linked objects use a consistent floating-point ABI and
allows tools like GDB to infer the ABI used from the ELF file. It is based on
similar work done for PowerPC.

bfd/
* elf32-m68k.c (m68k_elf_merge_obj_attributes): New function.
(elf32_m68k_merge_private_bfd_data): Merge GNU attributes.
binutils/
* readelf.c (display_m68k_gnu_attribute): New function.
(process_arch_specific): Call display_m68k_gnu_attribute for EM_68K.
gas/
* config/tc-m68k.c (m68k_elf_gnu_attribute): New function.
(md_pseudo_table): Handle "gnu_attribute".
* doc/as.texi: Document GNU attribute for M68K.
include/
* elf/m68k.h: Add enum for GNU object attribute with floating point
tag name and values.
ld/
* testsuite/ld-m68k/attr-gnu-4-0.s: New file.
* testsuite/ld-m68k/attr-gnu-4-1.s: Likewise.
* testsuite/ld-m68k/attr-gnu-4-2.s: Likewise.
* testsuite/ld-m68k/attr-gnu-4-00.d: Likewise.
* testsuite/ld-m68k/attr-gnu-4-01.d: Likewise.
* testsuite/ld-m68k/attr-gnu-4-02.d: Likewise.
* testsuite/ld-m68k/attr-gnu-4-10.d: Likewise.
* testsuite/ld-m68k/attr-gnu-4-11.d: Likewise.
* testsuite/ld-m68k/attr-gnu-4-12.d: Likewise.
* testsuite/ld-m68k/attr-gnu-4-20.d: Likewise.
* testsuite/ld-m68k/attr-gnu-4-21.d: Likewise.
* testsuite/ld-m68k/attr-gnu-4-22.d: Likewise.
* testsuite/ld-m68k/m68k.exp: Run the new tests.

23 files changed:
bfd/ChangeLog
bfd/elf32-m68k.c
binutils/ChangeLog
binutils/readelf.c
gas/ChangeLog
gas/config/tc-m68k.c
gas/doc/as.texi
include/ChangeLog
include/elf/m68k.h
ld/ChangeLog
ld/testsuite/ld-m68k/attr-gnu-4-0.s [new file with mode: 0644]
ld/testsuite/ld-m68k/attr-gnu-4-00.d [new file with mode: 0644]
ld/testsuite/ld-m68k/attr-gnu-4-01.d [new file with mode: 0644]
ld/testsuite/ld-m68k/attr-gnu-4-02.d [new file with mode: 0644]
ld/testsuite/ld-m68k/attr-gnu-4-1.s [new file with mode: 0644]
ld/testsuite/ld-m68k/attr-gnu-4-10.d [new file with mode: 0644]
ld/testsuite/ld-m68k/attr-gnu-4-11.d [new file with mode: 0644]
ld/testsuite/ld-m68k/attr-gnu-4-12.d [new file with mode: 0644]
ld/testsuite/ld-m68k/attr-gnu-4-2.s [new file with mode: 0644]
ld/testsuite/ld-m68k/attr-gnu-4-20.d [new file with mode: 0644]
ld/testsuite/ld-m68k/attr-gnu-4-21.d [new file with mode: 0644]
ld/testsuite/ld-m68k/attr-gnu-4-22.d [new file with mode: 0644]
ld/testsuite/ld-m68k/m68k.exp

index 2d9f1ec4cb06bbabd511f67680687925c1eec017..7b6375a0f712142b3cbf9cd1ca018721b58718c7 100644 (file)
@@ -1,3 +1,8 @@
+2020-06-26  Pat Bernardi  <bernardi@adacore.com>
+
+       * elf32-m68k.c (m68k_elf_merge_obj_attributes): New function.
+       (elf32_m68k_merge_private_bfd_data): Merge GNU attributes.
+
 2020-06-26  Alan Modra  <amodra@gmail.com>
 
        * elfxx-riscv.c (struct priv_spec_t, priv_specs),
index 39c5e1c2cc9a0fd9388a3491c29177b811642de9..7ccdaabbb6d3c6b5e019ac83b07c246f37e648a3 100644 (file)
@@ -1122,6 +1122,65 @@ elf32_m68k_set_private_flags (bfd *abfd, flagword flags)
   return TRUE;
 }
 
+/* Merge object attributes from IBFD into OBFD.  Warn if
+   there are conflicting attributes. */
+static bfd_boolean
+m68k_elf_merge_obj_attributes (bfd *ibfd, struct bfd_link_info *info)
+{
+  bfd *obfd = info->output_bfd;
+  obj_attribute *in_attr, *in_attrs;
+  obj_attribute *out_attr, *out_attrs;
+  bfd_boolean ret = TRUE;
+
+  in_attrs = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU];
+  out_attrs = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU];
+
+  in_attr = &in_attrs[Tag_GNU_M68K_ABI_FP];
+  out_attr = &out_attrs[Tag_GNU_M68K_ABI_FP];
+
+  if (in_attr->i != out_attr->i)
+    {
+      int in_fp = in_attr->i & 3;
+      int out_fp = out_attr->i & 3;
+      static bfd *last_fp;
+
+      if (in_fp == 0)
+       ;
+      else if (out_fp == 0)
+       {
+         out_attr->type = ATTR_TYPE_FLAG_INT_VAL;
+         out_attr->i ^= in_fp;
+         last_fp = ibfd;
+       }
+      else if (out_fp == 1 && in_fp == 2)
+       {
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("%pB uses hard float, %pB uses soft float"),
+            last_fp, ibfd);
+         ret = FALSE;
+       }
+      else if (out_fp == 2 && in_fp == 1)
+       {
+         _bfd_error_handler
+           /* xgettext:c-format */
+           (_("%pB uses hard float, %pB uses soft float"),
+            ibfd, last_fp);
+         ret = FALSE;
+       }
+    }
+
+  if (!ret)
+    {
+      out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR;
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
+
+  /* Merge Tag_compatibility attributes and any common GNU ones.  */
+  return _bfd_elf_merge_object_attributes (ibfd, info);
+}
+
 /* Merge backend specific data from an object file to the output
    object file when linking.  */
 static bfd_boolean
@@ -1149,6 +1208,9 @@ elf32_m68k_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
 
   bfd_set_arch_mach (obfd, bfd_arch_m68k, arch_info->mach);
 
+  if (!m68k_elf_merge_obj_attributes (ibfd, info))
+    return FALSE;
+
   in_flags = elf_elfheader (ibfd)->e_flags;
   if (!elf_flags_init (obfd))
     {
index 722e563039cff7c093cd7fb14d8cdb3c211f4904..2009fc12586f41f28fe4dab7568bc1c5117b40a7 100644 (file)
@@ -1,3 +1,8 @@
+2020-06-26  Pat Bernardi  <bernardi@adacore.com>
+
+       * readelf.c (display_m68k_gnu_attribute): New function.
+       (process_arch_specific): Call display_m68k_gnu_attribute for EM_68K.
+
 2020-06-23  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR binutils/26160
index 9e4fa3327b175b43c034d41bd82a76f526264613..25f0e2354c3642b85ea10e6fa151d1a747596feb 100644 (file)
@@ -15367,6 +15367,44 @@ display_gnu_attribute (unsigned char * p,
   return display_tag_value (tag, p, end);
 }
 
+static unsigned char *
+display_m68k_gnu_attribute (unsigned char * p,
+                           unsigned int tag,
+                           const unsigned char * const end)
+{
+  unsigned int val;
+
+  if (tag == Tag_GNU_M68K_ABI_FP)
+    {
+      printf ("  Tag_GNU_M68K_ABI_FP: ");
+      if (p == end)
+       {
+         printf (_("<corrupt>\n"));
+         return p;
+       }
+      READ_ULEB (val, p, end);
+
+      if (val > 3)
+       printf ("(%#x), ", val);
+
+      switch (val & 3)
+       {
+       case 0:
+         printf (_("unspecified hard/soft float\n"));
+         break;
+       case 1:
+         printf (_("hard float\n"));
+         break;
+       case 2:
+         printf (_("soft float\n"));
+         break;
+       }
+      return p;
+    }
+
+  return display_tag_value (tag & 1, p, end);
+}
+
 static unsigned char *
 display_power_gnu_attribute (unsigned char * p,
                             unsigned int tag,
@@ -19928,6 +19966,10 @@ process_arch_specific (Filedata * filedata)
     case EM_NDS32:
       return process_nds32_specific (filedata);
 
+    case EM_68K:
+      return process_attributes (filedata, NULL, SHT_GNU_ATTRIBUTES, NULL,
+                                display_m68k_gnu_attribute);
+
     case EM_PPC:
     case EM_PPC64:
       return process_attributes (filedata, NULL, SHT_GNU_ATTRIBUTES, NULL,
index 038ae0c47b4f709cf06c3cac637d65a9429ef7d7..f60fde6e7e6c0d5170987e1ea140c18ab451297f 100644 (file)
@@ -1,3 +1,9 @@
+2020-06-26  Pat Bernardi  <bernardi@adacore.com>
+
+       * config/tc-m68k.c (m68k_elf_gnu_attribute): New function.
+       (md_pseudo_table): Handle "gnu_attribute".
+       * doc/as.texi: Document GNU attribute for M68K.
+
 2020-06-25  Nick Clifton  <nickc@redhat.com>
 
        PR 26141
index cbb227a333dfa930cb31e535e2b8e64272b1d8ff..6ffc9432855ec080606b182eb40e3d4c09355bc5 100644 (file)
@@ -30,6 +30,7 @@
 #include "elf/m68k.h"
 
 static void m68k_elf_cons (int);
+static void m68k_elf_gnu_attribute (int);
 
 /* This string holds the chars that always start a comment.  If the
    pre-processor is disabled, these aren't very useful.  The macro
@@ -889,6 +890,7 @@ const pseudo_typeS md_pseudo_table[] =
 
   {"arch", s_m68k_arch, 0},
   {"cpu", s_m68k_cpu, 0},
+  {"gnu_attribute", m68k_elf_gnu_attribute, 0},
 
   /* The following pseudo-ops are supported for MRI compatibility.  */
   {"chip", s_chip, 0},
@@ -7951,6 +7953,24 @@ m68k_elf_cons (int nbytes /* 4=.long */)
   demand_empty_rest_of_line ();
 }
 
+/* Parse a .gnu_attribute directive.  */
+static void
+m68k_elf_gnu_attribute (int ignored ATTRIBUTE_UNUSED)
+{
+  int tag = obj_elf_vendor_attribute (OBJ_ATTR_GNU);
+
+  /* Check validity of defined m68k tags.  */
+  if (tag == Tag_GNU_M68K_ABI_FP)
+    {
+      unsigned int val;
+
+      val = bfd_elf_get_obj_attr_int (stdoutput, OBJ_ATTR_GNU, tag);
+
+      if (tag == Tag_GNU_M68K_ABI_FP && val > 2)
+       as_warn (_("unknown .gnu_attribute value"));
+    }
+}
+
 int
 tc_m68k_regname_to_dw2regnum (const char *regname)
 {
index f8d892eaa5c1771237189a6963285fb60e6a3197..ac4a073eab6e5e41d6575c597309a08ff44cf2f7 100644 (file)
@@ -7583,6 +7583,22 @@ than 1, the file can only be processed by other toolchains under some private
 arrangement indicated by the flag value and the vendor name.
 @end table
 
+@subsection M680x0 Attributes
+
+@table @r
+@item Tag_GNU_M68K_ABI_FP (4)
+The floating-point ABI used by this object file.  The value will be:
+
+@itemize @bullet
+@item
+0 for files not affected by the floating-point ABI.
+@item
+1 for files using double-precision hardware floating-point ABI.
+@item
+2 for files using the software floating-point ABI.
+@end itemize
+@end table
+
 @subsection MIPS Attributes
 
 @table @r
index 8e06abff3403534c296db15fded764ef43d7e7b3..ab6d753ab5f1ef8460ae0e5fffedf7387a327630 100644 (file)
@@ -1,3 +1,8 @@
+2020-06-26  Pat Bernardi  <bernardi@adacore.com>
+
+       * elf/m68k.h: Add enum for GNU object attribute with floating point
+       tag name and values.
+
 2020-06-25  Nick Clifton  <nickc@redhat.com>
 
        * libiberty.h (bsearch_r): Remove use of the register keyword from
index 2d3c12e050327f7b9e423421158d847b311a535f..e5b0592042674f6d2251f8309044b6d2f852870b 100644 (file)
@@ -97,5 +97,17 @@ END_RELOC_NUMBERS (R_68K_max)
 #define EF_M68K_CF_EMAC_B      0x30  /* EMAC_B */
 #define EF_M68K_CF_FLOAT       0x40  /* Has float insns */
 #define EF_M68K_CF_MASK                0xFF
-     
+
+/* GNU object attribute tags.  */
+enum
+{
+  /* 0-3 are generic.  */
+
+  /* FP ABI, low 2 bits:
+     1 for double precision hard-float,
+     2 for soft-float,
+     0 for not tagged or not using any ABIs affected by the differences. */
+  Tag_GNU_M68K_ABI_FP = 4,
+};
+
 #endif
index 6f586506b13d8de038407ebd6f20ababa0fd2c6f..4a38fa8e1b4d65da2b1d020065e5aa8a8ab23925 100644 (file)
@@ -1,3 +1,19 @@
+2020-06-26  Pat Bernardi  <bernardi@adacore.com>
+
+       * testsuite/ld-m68k/attr-gnu-4-0.s: New file.
+       * testsuite/ld-m68k/attr-gnu-4-1.s: Likewise.
+       * testsuite/ld-m68k/attr-gnu-4-2.s: Likewise.
+       * testsuite/ld-m68k/attr-gnu-4-00.d: Likewise.
+       * testsuite/ld-m68k/attr-gnu-4-01.d: Likewise.
+       * testsuite/ld-m68k/attr-gnu-4-02.d: Likewise.
+       * testsuite/ld-m68k/attr-gnu-4-10.d: Likewise.
+       * testsuite/ld-m68k/attr-gnu-4-11.d: Likewise.
+       * testsuite/ld-m68k/attr-gnu-4-12.d: Likewise.
+       * testsuite/ld-m68k/attr-gnu-4-20.d: Likewise.
+       * testsuite/ld-m68k/attr-gnu-4-21.d: Likewise.
+       * testsuite/ld-m68k/attr-gnu-4-22.d: Likewise.
+       * testsuite/ld-m68k/m68k.exp: Run the new tests.
+
 2020-06-24  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/26165
diff --git a/ld/testsuite/ld-m68k/attr-gnu-4-0.s b/ld/testsuite/ld-m68k/attr-gnu-4-0.s
new file mode 100644 (file)
index 0000000..a143746
--- /dev/null
@@ -0,0 +1 @@
+.gnu_attribute 4,0
diff --git a/ld/testsuite/ld-m68k/attr-gnu-4-00.d b/ld/testsuite/ld-m68k/attr-gnu-4-00.d
new file mode 100644 (file)
index 0000000..467ad60
--- /dev/null
@@ -0,0 +1,4 @@
+#source: attr-gnu-4-0.s
+#source: attr-gnu-4-0.s
+#ld: -r
+#readelf: -A
diff --git a/ld/testsuite/ld-m68k/attr-gnu-4-01.d b/ld/testsuite/ld-m68k/attr-gnu-4-01.d
new file mode 100644 (file)
index 0000000..1e7fef0
--- /dev/null
@@ -0,0 +1,8 @@
+#source: attr-gnu-4-0.s
+#source: attr-gnu-4-1.s
+#ld: -r
+#readelf: -A
+
+Attribute Section: gnu
+File Attributes
+  Tag_GNU_M68K_ABI_FP: hard float
diff --git a/ld/testsuite/ld-m68k/attr-gnu-4-02.d b/ld/testsuite/ld-m68k/attr-gnu-4-02.d
new file mode 100644 (file)
index 0000000..cc3945a
--- /dev/null
@@ -0,0 +1,8 @@
+#source: attr-gnu-4-0.s
+#source: attr-gnu-4-2.s
+#ld: -r
+#readelf: -A
+
+Attribute Section: gnu
+File Attributes
+  Tag_GNU_M68K_ABI_FP: soft float
diff --git a/ld/testsuite/ld-m68k/attr-gnu-4-1.s b/ld/testsuite/ld-m68k/attr-gnu-4-1.s
new file mode 100644 (file)
index 0000000..e985a56
--- /dev/null
@@ -0,0 +1 @@
+.gnu_attribute 4,1
diff --git a/ld/testsuite/ld-m68k/attr-gnu-4-10.d b/ld/testsuite/ld-m68k/attr-gnu-4-10.d
new file mode 100644 (file)
index 0000000..a6a798b
--- /dev/null
@@ -0,0 +1,8 @@
+#source: attr-gnu-4-1.s
+#source: attr-gnu-4-0.s
+#ld: -r
+#readelf: -A
+
+Attribute Section: gnu
+File Attributes
+  Tag_GNU_M68K_ABI_FP: hard float
diff --git a/ld/testsuite/ld-m68k/attr-gnu-4-11.d b/ld/testsuite/ld-m68k/attr-gnu-4-11.d
new file mode 100644 (file)
index 0000000..ecc66a4
--- /dev/null
@@ -0,0 +1,8 @@
+#source: attr-gnu-4-1.s
+#source: attr-gnu-4-1.s
+#ld: -r
+#readelf: -A
+
+Attribute Section: gnu
+File Attributes
+  Tag_GNU_M68K_ABI_FP: hard float
diff --git a/ld/testsuite/ld-m68k/attr-gnu-4-12.d b/ld/testsuite/ld-m68k/attr-gnu-4-12.d
new file mode 100644 (file)
index 0000000..49526b1
--- /dev/null
@@ -0,0 +1,4 @@
+#source: attr-gnu-4-1.s
+#source: attr-gnu-4-2.s
+#ld: -r
+#error: .* uses hard float, .* uses soft float.*
diff --git a/ld/testsuite/ld-m68k/attr-gnu-4-2.s b/ld/testsuite/ld-m68k/attr-gnu-4-2.s
new file mode 100644 (file)
index 0000000..54ebf4e
--- /dev/null
@@ -0,0 +1 @@
+.gnu_attribute 4,2
diff --git a/ld/testsuite/ld-m68k/attr-gnu-4-20.d b/ld/testsuite/ld-m68k/attr-gnu-4-20.d
new file mode 100644 (file)
index 0000000..92b410a
--- /dev/null
@@ -0,0 +1,8 @@
+#source: attr-gnu-4-2.s
+#source: attr-gnu-4-0.s
+#ld: -r
+#readelf: -A
+
+Attribute Section: gnu
+File Attributes
+  Tag_GNU_M68K_ABI_FP: soft float
diff --git a/ld/testsuite/ld-m68k/attr-gnu-4-21.d b/ld/testsuite/ld-m68k/attr-gnu-4-21.d
new file mode 100644 (file)
index 0000000..390dada
--- /dev/null
@@ -0,0 +1,4 @@
+#source: attr-gnu-4-2.s
+#source: attr-gnu-4-1.s
+#ld: -r
+#error: .* uses hard float, .* uses soft float.*
diff --git a/ld/testsuite/ld-m68k/attr-gnu-4-22.d b/ld/testsuite/ld-m68k/attr-gnu-4-22.d
new file mode 100644 (file)
index 0000000..cfa9b35
--- /dev/null
@@ -0,0 +1,8 @@
+#source: attr-gnu-4-2.s
+#source: attr-gnu-4-2.s
+#ld: -r
+#readelf: -A
+
+Attribute Section: gnu
+File Attributes
+  Tag_GNU_M68K_ABI_FP: soft float
index df859ba1fef8fc2ccf9d79c0e2a92a30ba780212..610b43528641d880e92a9907614e47bb5e884b28 100644 (file)
@@ -92,3 +92,13 @@ if { [istarget m68k-*-linux*] } then {
 
     run_ld_link_tests $m68k_tls_tests
 }
+
+run_dump_test "attr-gnu-4-00"
+run_dump_test "attr-gnu-4-01"
+run_dump_test "attr-gnu-4-02"
+run_dump_test "attr-gnu-4-10"
+run_dump_test "attr-gnu-4-11"
+run_dump_test "attr-gnu-4-12"
+run_dump_test "attr-gnu-4-20"
+run_dump_test "attr-gnu-4-21"
+run_dump_test "attr-gnu-4-22"