From 24aebc79b16a82faef4736f4abdc7e4d95d4cc67 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Wed, 28 Apr 2021 11:49:09 +0100 Subject: [PATCH] Stop the BFD library from treating annobin symbols as potential function symbols. bfd * elf.c (_bfd_elf_maybe_function_sym): Do not accept annobin symbols as potential function symbols. * elfnn-aarch64.c (elfNN_aarch64_maybe_function_sym): Likewise. * elf64-ppc.c (ppc64_elf_maybe_function_sym): Likewise. * elf32-arm.c (elf32_arm_maybe_function_sym): Likewise. ld * testsuite/ld-elf/anno-sym.s: New test source file. * testsuite/ld-elf/anno-sym.d: New test driver. * testsuite/ld-elf/anno-sym.l: New test error output. --- bfd/ChangeLog | 8 ++++++++ bfd/elf.c | 23 +++++++++++++++++------ bfd/elf32-arm.c | 27 ++++++++++++++++++--------- bfd/elf64-ppc.c | 23 +++++++++++++++++------ bfd/elfnn-aarch64.c | 26 +++++++++++++++++--------- ld/ChangeLog | 6 ++++++ ld/testsuite/ld-elf/anno-sym.d | 5 +++++ ld/testsuite/ld-elf/anno-sym.l | 4 ++++ ld/testsuite/ld-elf/anno-sym.s | 13 +++++++++++++ 9 files changed, 105 insertions(+), 30 deletions(-) create mode 100644 ld/testsuite/ld-elf/anno-sym.d create mode 100644 ld/testsuite/ld-elf/anno-sym.l create mode 100644 ld/testsuite/ld-elf/anno-sym.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 721fddc935d..47b9c913581 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2021-04-28 Nick Clifton + + * elf.c (_bfd_elf_maybe_function_sym): Do not accept annobin + symbols as potential function symbols. + * elfnn-aarch64.c (elfNN_aarch64_maybe_function_sym): Likewise. + * elf64-ppc.c (ppc64_elf_maybe_function_sym): Likewise. + * elf32-arm.c (elf32_arm_maybe_function_sym): Likewise. + 2021-04-26 Mike Frysinger * elf-bfd.h: Include stdlib.h. diff --git a/bfd/elf.c b/bfd/elf.c index 4846b7bd47f..851440b7652 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -12618,19 +12618,30 @@ _bfd_elf_maybe_function_sym (const asymbol *sym, asection *sec, bfd_vma *code_off) { bfd_size_type size; + elf_symbol_type * elf_sym = (elf_symbol_type *) sym; if ((sym->flags & (BSF_SECTION_SYM | BSF_FILE | BSF_OBJECT | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0 || sym->section != sec) return 0; + size = (sym->flags & BSF_SYNTHETIC) ? 0 : elf_sym->internal_elf_sym.st_size; + + /* In theory we should check that the symbol's type satisfies + _bfd_elf_is_function_type(), but there are some function-like + symbols which would fail this test. (eg _start). Instead + we check for hidden, local, notype symbols with zero size. + This type of symbol is generated by the annobin plugin for gcc + and clang, and should not be considered to be a function symbol. */ + if (size == 0 + && ((sym->flags & (BSF_SYNTHETIC | BSF_LOCAL)) == BSF_LOCAL) + && ELF_ST_TYPE (elf_sym->internal_elf_sym.st_info) == STT_NOTYPE + && ELF_ST_VISIBILITY (elf_sym->internal_elf_sym.st_other) == STV_HIDDEN) + return 0; + *code_off = sym->value; - size = 0; - if (!(sym->flags & BSF_SYNTHETIC)) - size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size; - if (size == 0) - size = 1; - return size; + /* Do not return 0 for the function's size. */ + return size ? size : 1; } /* Set to non-zero to enable some debug messages. */ diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 81667ea090d..79b94e836fc 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -15898,35 +15898,44 @@ elf32_arm_maybe_function_sym (const asymbol *sym, asection *sec, bfd_vma *code_off) { bfd_size_type size; + elf_symbol_type * elf_sym = (elf_symbol_type *) sym; if ((sym->flags & (BSF_SECTION_SYM | BSF_FILE | BSF_OBJECT | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0 || sym->section != sec) return 0; + size = (sym->flags & BSF_SYNTHETIC) ? 0 : elf_sym->internal_elf_sym.st_size; + if (!(sym->flags & BSF_SYNTHETIC)) - switch (ELF_ST_TYPE (((elf_symbol_type *) sym)->internal_elf_sym.st_info)) + switch (ELF_ST_TYPE (elf_sym->internal_elf_sym.st_info)) { + case STT_NOTYPE: + /* Ignore symbols created by the annobin plugin for gcc and clang. + These symbols are hidden, local, notype and have a size of 0. */ + if (size == 0 + && sym->flags & BSF_LOCAL + && ELF_ST_VISIBILITY (elf_sym->internal_elf_sym.st_other) == STV_HIDDEN) + return 0; + /* Fall through. */ case STT_FUNC: case STT_ARM_TFUNC: - case STT_NOTYPE: + /* FIXME: Allow STT_GNU_IFUNC as well ? */ break; default: return 0; } - + if ((sym->flags & BSF_LOCAL) && bfd_is_arm_special_symbol_name (sym->name, BFD_ARM_SPECIAL_SYM_TYPE_ANY)) return 0; *code_off = sym->value; - size = 0; - if (!(sym->flags & BSF_SYNTHETIC)) - size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size; - if (size == 0) - size = 1; - return size; + + /* Do not return 0 for the function's size. */ + return size ? size : 1; + } static bool diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 08227f0e43a..ed72de27507 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -5534,14 +5534,25 @@ ppc64_elf_maybe_function_sym (const asymbol *sym, asection *sec, bfd_vma *code_off) { bfd_size_type size; + elf_symbol_type * elf_sym = (elf_symbol_type *) sym; if ((sym->flags & (BSF_SECTION_SYM | BSF_FILE | BSF_OBJECT | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0) return 0; - size = 0; - if (!(sym->flags & BSF_SYNTHETIC)) - size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size; + size = (sym->flags & BSF_SYNTHETIC) ? 0 : elf_sym->internal_elf_sym.st_size; + + /* In theory we should check that the symbol's type satisfies + _bfd_elf_is_function_type(), but there are some function-like + symbols which would fail this test. (eg _start). Instead + we check for hidden, local, notype symbols with zero size. + This type of symbol is generated by the annobin plugin for gcc + and clang, and should not be considered to be a function symbol. */ + if (size == 0 + && ((sym->flags & (BSF_SYNTHETIC | BSF_LOCAL)) == BSF_LOCAL) + && ELF_ST_TYPE (elf_sym->internal_elf_sym.st_info) == STT_NOTYPE + && ELF_ST_VISIBILITY (elf_sym->internal_elf_sym.st_other) == STV_HIDDEN) + return 0; if (strcmp (sym->section->name, ".opd") == 0) { @@ -5585,9 +5596,9 @@ ppc64_elf_maybe_function_sym (const asymbol *sym, asection *sec, return 0; *code_off = sym->value; } - if (size == 0) - size = 1; - return size; + + /* Do not return 0 for the function's size. */ + return size ? size : 1; } /* Return true if symbol is a strong function defined in an ELFv2 diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index 0a1d7a617c8..b6f083e430b 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -8012,34 +8012,42 @@ elfNN_aarch64_maybe_function_sym (const asymbol *sym, asection *sec, bfd_vma *code_off) { bfd_size_type size; + elf_symbol_type * elf_sym = (elf_symbol_type *) sym; if ((sym->flags & (BSF_SECTION_SYM | BSF_FILE | BSF_OBJECT | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0 || sym->section != sec) return 0; + size = (sym->flags & BSF_SYNTHETIC) ? 0 : elf_sym->internal_elf_sym.st_size; + if (!(sym->flags & BSF_SYNTHETIC)) - switch (ELF_ST_TYPE (((elf_symbol_type *) sym)->internal_elf_sym.st_info)) + switch (ELF_ST_TYPE (elf_sym->internal_elf_sym.st_info)) { - case STT_FUNC: case STT_NOTYPE: + /* Ignore symbols created by the annobin plugin for gcc and clang. + These symbols are hidden, local, notype and have a size of 0. */ + if (size == 0 + && sym->flags & BSF_LOCAL + && ELF_ST_VISIBILITY (elf_sym->internal_elf_sym.st_other) == STV_HIDDEN) + return 0; + /* Fall through. */ + case STT_FUNC: + /* FIXME: Allow STT_GNU_IFUNC as well ? */ break; default: return 0; } - + if ((sym->flags & BSF_LOCAL) && bfd_is_aarch64_special_symbol_name (sym->name, BFD_AARCH64_SPECIAL_SYM_TYPE_ANY)) return 0; *code_off = sym->value; - size = 0; - if (!(sym->flags & BSF_SYNTHETIC)) - size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size; - if (size == 0) - size = 1; - return size; + + /* Do not return 0 for the function's size. */ + return size ? size : 1; } static bool diff --git a/ld/ChangeLog b/ld/ChangeLog index 9bb178e4248..3c4bec58949 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,9 @@ +2021-04-28 Nick Clifton + + * testsuite/ld-elf/anno-sym.s: New test source file. + * testsuite/ld-elf/anno-sym.d: New test driver. + * testsuite/ld-elf/anno-sym.l: New test error output. + 2021-04-26 Jan Beulich * testsuite/ld-i386/pcrel16-2.s, testsuite/ld-i386/pcrel16-2.d, diff --git a/ld/testsuite/ld-elf/anno-sym.d b/ld/testsuite/ld-elf/anno-sym.d new file mode 100644 index 00000000000..9e53c4a9c16 --- /dev/null +++ b/ld/testsuite/ld-elf/anno-sym.d @@ -0,0 +1,5 @@ +# Check that linking anno-sym.o produces an undefined reference message referring to '_start' and not 'annobin_hello.c' +#ld: -e _start +#error_output: anno-sym.l +# The mips-irix6 target fails this test because it does not find any function symbols. Not sure why. +#skip: *-*-irix* diff --git a/ld/testsuite/ld-elf/anno-sym.l b/ld/testsuite/ld-elf/anno-sym.l new file mode 100644 index 00000000000..ee9611aef4e --- /dev/null +++ b/ld/testsuite/ld-elf/anno-sym.l @@ -0,0 +1,4 @@ +#... +.*: in function `(|_)start': +.*: undefined reference to `foo' +#pass diff --git a/ld/testsuite/ld-elf/anno-sym.s b/ld/testsuite/ld-elf/anno-sym.s new file mode 100644 index 00000000000..0e4b5aa79c3 --- /dev/null +++ b/ld/testsuite/ld-elf/anno-sym.s @@ -0,0 +1,13 @@ + .text + + .hidden .annobin_hello.c + .type .annobin_hello.c, STT_NOTYPE + .equiv .annobin_hello.c, . + .size .annobin_hello.c, 0 + + .global _start +_start: + .nop + .align 4 + .dc.a foo + -- 2.30.2