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.
This commit is contained in:
Pat Bernardi 2020-06-25 16:05:38 -04:00 committed by Alan Modra
parent ba9b3ef5ee
commit 85f7484a3a
23 changed files with 263 additions and 1 deletions

View 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> 2020-06-26 Alan Modra <amodra@gmail.com>
* elfxx-riscv.c (struct priv_spec_t, priv_specs), * elfxx-riscv.c (struct priv_spec_t, priv_specs),

View file

@ -1122,6 +1122,65 @@ elf32_m68k_set_private_flags (bfd *abfd, flagword flags)
return TRUE; 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 /* Merge backend specific data from an object file to the output
object file when linking. */ object file when linking. */
static bfd_boolean 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); 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; in_flags = elf_elfheader (ibfd)->e_flags;
if (!elf_flags_init (obfd)) if (!elf_flags_init (obfd))
{ {

View 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> 2020-06-23 H.J. Lu <hongjiu.lu@intel.com>
PR binutils/26160 PR binutils/26160

View file

@ -15367,6 +15367,44 @@ display_gnu_attribute (unsigned char * p,
return display_tag_value (tag, p, end); 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 * static unsigned char *
display_power_gnu_attribute (unsigned char * p, display_power_gnu_attribute (unsigned char * p,
unsigned int tag, unsigned int tag,
@ -19928,6 +19966,10 @@ process_arch_specific (Filedata * filedata)
case EM_NDS32: case EM_NDS32:
return process_nds32_specific (filedata); 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_PPC:
case EM_PPC64: case EM_PPC64:
return process_attributes (filedata, NULL, SHT_GNU_ATTRIBUTES, NULL, return process_attributes (filedata, NULL, SHT_GNU_ATTRIBUTES, NULL,

View 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> 2020-06-25 Nick Clifton <nickc@redhat.com>
PR 26141 PR 26141

View file

@ -30,6 +30,7 @@
#include "elf/m68k.h" #include "elf/m68k.h"
static void m68k_elf_cons (int); 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 /* This string holds the chars that always start a comment. If the
pre-processor is disabled, these aren't very useful. The macro 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}, {"arch", s_m68k_arch, 0},
{"cpu", s_m68k_cpu, 0}, {"cpu", s_m68k_cpu, 0},
{"gnu_attribute", m68k_elf_gnu_attribute, 0},
/* The following pseudo-ops are supported for MRI compatibility. */ /* The following pseudo-ops are supported for MRI compatibility. */
{"chip", s_chip, 0}, {"chip", s_chip, 0},
@ -7951,6 +7953,24 @@ m68k_elf_cons (int nbytes /* 4=.long */)
demand_empty_rest_of_line (); 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 int
tc_m68k_regname_to_dw2regnum (const char *regname) tc_m68k_regname_to_dw2regnum (const char *regname)
{ {

View 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. arrangement indicated by the flag value and the vendor name.
@end table @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 @subsection MIPS Attributes
@table @r @table @r

View 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> 2020-06-25 Nick Clifton <nickc@redhat.com>
* libiberty.h (bsearch_r): Remove use of the register keyword from * libiberty.h (bsearch_r): Remove use of the register keyword from

View file

@ -97,5 +97,17 @@ END_RELOC_NUMBERS (R_68K_max)
#define EF_M68K_CF_EMAC_B 0x30 /* EMAC_B */ #define EF_M68K_CF_EMAC_B 0x30 /* EMAC_B */
#define EF_M68K_CF_FLOAT 0x40 /* Has float insns */ #define EF_M68K_CF_FLOAT 0x40 /* Has float insns */
#define EF_M68K_CF_MASK 0xFF #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 #endif

View 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> 2020-06-24 H.J. Lu <hongjiu.lu@intel.com>
PR ld/26165 PR ld/26165

View file

@ -0,0 +1 @@
.gnu_attribute 4,0

View file

@ -0,0 +1,4 @@
#source: attr-gnu-4-0.s
#source: attr-gnu-4-0.s
#ld: -r
#readelf: -A

View file

@ -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

View file

@ -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

View file

@ -0,0 +1 @@
.gnu_attribute 4,1

View file

@ -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

View file

@ -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

View file

@ -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.*

View file

@ -0,0 +1 @@
.gnu_attribute 4,2

View file

@ -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

View file

@ -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.*

View file

@ -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

View file

@ -92,3 +92,13 @@ if { [istarget m68k-*-linux*] } then {
run_ld_link_tests $m68k_tls_tests 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"