diff options
author | Pat Bernardi <bernardi@adacore.com> | 2020-06-25 16:05:38 -0400 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2020-06-26 14:42:19 +0930 |
commit | 85f7484a3a1921649029c4a4fcf3247c3f3bc13c (patch) | |
tree | d8cec9b624c9984936c00c9f3389d0c3a757750d /bfd/elf32-m68k.c | |
parent | ba9b3ef5ee666467b67780e81f868c432f4fc56d (diff) | |
download | binutils-gdb-85f7484a3a1921649029c4a4fcf3247c3f3bc13c.tar.gz |
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.
Diffstat (limited to 'bfd/elf32-m68k.c')
-rw-r--r-- | bfd/elf32-m68k.c | 62 |
1 files changed, 62 insertions, 0 deletions
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)) { |