From 85f7484a3a1921649029c4a4fcf3247c3f3bc13c Mon Sep 17 00:00:00 2001 From: Pat Bernardi Date: Thu, 25 Jun 2020 16:05:38 -0400 Subject: [PATCH] m68k: tag floating-point ABI used 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. --- bfd/ChangeLog | 5 +++ bfd/elf32-m68k.c | 62 ++++++++++++++++++++++++++++ binutils/ChangeLog | 5 +++ binutils/readelf.c | 42 +++++++++++++++++++ gas/ChangeLog | 6 +++ gas/config/tc-m68k.c | 20 +++++++++ gas/doc/as.texi | 16 +++++++ include/ChangeLog | 5 +++ include/elf/m68k.h | 14 ++++++- ld/ChangeLog | 16 +++++++ ld/testsuite/ld-m68k/attr-gnu-4-0.s | 1 + ld/testsuite/ld-m68k/attr-gnu-4-00.d | 4 ++ ld/testsuite/ld-m68k/attr-gnu-4-01.d | 8 ++++ ld/testsuite/ld-m68k/attr-gnu-4-02.d | 8 ++++ ld/testsuite/ld-m68k/attr-gnu-4-1.s | 1 + ld/testsuite/ld-m68k/attr-gnu-4-10.d | 8 ++++ ld/testsuite/ld-m68k/attr-gnu-4-11.d | 8 ++++ ld/testsuite/ld-m68k/attr-gnu-4-12.d | 4 ++ ld/testsuite/ld-m68k/attr-gnu-4-2.s | 1 + ld/testsuite/ld-m68k/attr-gnu-4-20.d | 8 ++++ ld/testsuite/ld-m68k/attr-gnu-4-21.d | 4 ++ ld/testsuite/ld-m68k/attr-gnu-4-22.d | 8 ++++ ld/testsuite/ld-m68k/m68k.exp | 10 +++++ 23 files changed, 263 insertions(+), 1 deletion(-) create mode 100644 ld/testsuite/ld-m68k/attr-gnu-4-0.s create mode 100644 ld/testsuite/ld-m68k/attr-gnu-4-00.d create mode 100644 ld/testsuite/ld-m68k/attr-gnu-4-01.d create mode 100644 ld/testsuite/ld-m68k/attr-gnu-4-02.d create mode 100644 ld/testsuite/ld-m68k/attr-gnu-4-1.s create mode 100644 ld/testsuite/ld-m68k/attr-gnu-4-10.d create mode 100644 ld/testsuite/ld-m68k/attr-gnu-4-11.d create mode 100644 ld/testsuite/ld-m68k/attr-gnu-4-12.d create mode 100644 ld/testsuite/ld-m68k/attr-gnu-4-2.s create mode 100644 ld/testsuite/ld-m68k/attr-gnu-4-20.d create mode 100644 ld/testsuite/ld-m68k/attr-gnu-4-21.d create mode 100644 ld/testsuite/ld-m68k/attr-gnu-4-22.d diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 2d9f1ec4cb0..7b6375a0f71 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +2020-06-26 Pat Bernardi + + * elf32-m68k.c (m68k_elf_merge_obj_attributes): New function. + (elf32_m68k_merge_private_bfd_data): Merge GNU attributes. + 2020-06-26 Alan Modra * elfxx-riscv.c (struct priv_spec_t, priv_specs), diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c index 39c5e1c2cc9..7ccdaabbb6d 100644 --- a/bfd/elf32-m68k.c +++ b/bfd/elf32-m68k.c @@ -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)) { diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 722e563039c..2009fc12586 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,8 @@ +2020-06-26 Pat Bernardi + + * 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 PR binutils/26160 diff --git a/binutils/readelf.c b/binutils/readelf.c index 9e4fa3327b1..25f0e2354c3 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -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 (_("\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, diff --git a/gas/ChangeLog b/gas/ChangeLog index 038ae0c47b4..f60fde6e7e6 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,9 @@ +2020-06-26 Pat Bernardi + + * 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 PR 26141 diff --git a/gas/config/tc-m68k.c b/gas/config/tc-m68k.c index cbb227a333d..6ffc9432855 100644 --- a/gas/config/tc-m68k.c +++ b/gas/config/tc-m68k.c @@ -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) { diff --git a/gas/doc/as.texi b/gas/doc/as.texi index f8d892eaa5c..ac4a073eab6 100644 --- a/gas/doc/as.texi +++ b/gas/doc/as.texi @@ -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 diff --git a/include/ChangeLog b/include/ChangeLog index 8e06abff340..ab6d753ab5f 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,8 @@ +2020-06-26 Pat Bernardi + + * elf/m68k.h: Add enum for GNU object attribute with floating point + tag name and values. + 2020-06-25 Nick Clifton * libiberty.h (bsearch_r): Remove use of the register keyword from diff --git a/include/elf/m68k.h b/include/elf/m68k.h index 2d3c12e0503..e5b05920426 100644 --- a/include/elf/m68k.h +++ b/include/elf/m68k.h @@ -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 diff --git a/ld/ChangeLog b/ld/ChangeLog index 6f586506b13..4a38fa8e1b4 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,19 @@ +2020-06-26 Pat Bernardi + + * 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 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 index 00000000000..a1437461d04 --- /dev/null +++ b/ld/testsuite/ld-m68k/attr-gnu-4-0.s @@ -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 index 00000000000..467ad603cf7 --- /dev/null +++ b/ld/testsuite/ld-m68k/attr-gnu-4-00.d @@ -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 index 00000000000..1e7fef07419 --- /dev/null +++ b/ld/testsuite/ld-m68k/attr-gnu-4-01.d @@ -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 index 00000000000..cc3945a2159 --- /dev/null +++ b/ld/testsuite/ld-m68k/attr-gnu-4-02.d @@ -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 index 00000000000..e985a56f6b1 --- /dev/null +++ b/ld/testsuite/ld-m68k/attr-gnu-4-1.s @@ -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 index 00000000000..a6a798b4a40 --- /dev/null +++ b/ld/testsuite/ld-m68k/attr-gnu-4-10.d @@ -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 index 00000000000..ecc66a4925d --- /dev/null +++ b/ld/testsuite/ld-m68k/attr-gnu-4-11.d @@ -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 index 00000000000..49526b1750b --- /dev/null +++ b/ld/testsuite/ld-m68k/attr-gnu-4-12.d @@ -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 index 00000000000..54ebf4ed8dd --- /dev/null +++ b/ld/testsuite/ld-m68k/attr-gnu-4-2.s @@ -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 index 00000000000..92b410a3dfc --- /dev/null +++ b/ld/testsuite/ld-m68k/attr-gnu-4-20.d @@ -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 index 00000000000..390dada36cb --- /dev/null +++ b/ld/testsuite/ld-m68k/attr-gnu-4-21.d @@ -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 index 00000000000..cfa9b35a991 --- /dev/null +++ b/ld/testsuite/ld-m68k/attr-gnu-4-22.d @@ -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 diff --git a/ld/testsuite/ld-m68k/m68k.exp b/ld/testsuite/ld-m68k/m68k.exp index df859ba1fef..610b4352864 100644 --- a/ld/testsuite/ld-m68k/m68k.exp +++ b/ld/testsuite/ld-m68k/m68k.exp @@ -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" -- 2.30.2