diff options
author | Jan Beulich <jbeulich@suse.com> | 2019-07-04 10:35:47 +0200 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2019-07-04 10:35:47 +0200 |
commit | f2d4ba38f5723a207c40a288036af2f38b70e837 (patch) | |
tree | 4f864465aad8dfadd14c3ee62cc9f0ca7c743045 /gas/config/obj-elf.c | |
parent | db7fbcbeb749c0d4ea19284438d62b253648c58a (diff) | |
download | fsf-binutils-gdb-f2d4ba38f5723a207c40a288036af2f38b70e837.zip fsf-binutils-gdb-f2d4ba38f5723a207c40a288036af2f38b70e837.tar.gz fsf-binutils-gdb-f2d4ba38f5723a207c40a288036af2f38b70e837.tar.bz2 |
gas/ELF: don't accumulate .type settings
Recently a patch was submitted for a Xen Project test harness binary to
override the compiler specified @object to @func (see [1]). In a reply I
suggested we shouldn't make ourselves dependent on currently unspecified
behavior of gas here: It accumulates all requests, and then
bfd/elf.c:swap_out_syms(), in an apparently ad hoc manner, prioritizes
certain flags over others.
Make the behavior predictable: Generally the last .type is what counts.
Exceptions are directives which set multiple bits (TLS, IFUNC, and
UNIQUE): Subsequent directives requesting just the more generic bit
(i.e. FUNC following IFUNC) won't clear the more specific one. Warn
about incompatible changes, except from/to STT_NOTYPE.
Also add a new target hook, which hppa wants to use right away afaict.
In the course of adding the warning I ran into two ld testsuite
failures. I can only assume that it was a copy-and-paste mistake that
lead to the same symbol having its type set twice.
[1] https://lists.xenproject.org/archives/html/xen-devel/2019-05/msg01980.html
Diffstat (limited to 'gas/config/obj-elf.c')
-rw-r--r-- | gas/config/obj-elf.c | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index 318e27d..224d4c2 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -2069,7 +2069,38 @@ obj_elf_type (int ignore ATTRIBUTE_UNUSED) if (*input_line_pointer == '"') ++input_line_pointer; - elfsym->symbol.flags |= type; +#ifdef md_elf_symbol_type_change + if (!md_elf_symbol_type_change (sym, elfsym, type)) +#endif + { + flagword mask = BSF_FUNCTION | BSF_OBJECT; + + if (type != BSF_FUNCTION) + mask |= BSF_GNU_INDIRECT_FUNCTION; + if (type != BSF_OBJECT) + { + mask |= BSF_GNU_UNIQUE | BSF_THREAD_LOCAL; + + if (S_IS_COMMON (sym)) + { + as_bad (_("cannot change type of common symbol '%s'"), + S_GET_NAME (sym)); + mask = type = 0; + } + } + + /* Don't warn when changing to STT_NOTYPE. */ + if (type) + { + flagword new = (elfsym->symbol.flags & ~mask) | type; + + if (new != (elfsym->symbol.flags | type)) + as_warn (_("symbol '%s' already has its type set"), S_GET_NAME (sym)); + elfsym->symbol.flags = new; + } + else + elfsym->symbol.flags &= ~mask; + } demand_empty_rest_of_line (); } |