aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog8
-rw-r--r--bfd/elf.c23
-rw-r--r--bfd/elf32-arm.c27
-rw-r--r--bfd/elf64-ppc.c23
-rw-r--r--bfd/elfnn-aarch64.c26
-rw-r--r--ld/ChangeLog6
-rw-r--r--ld/testsuite/ld-elf/anno-sym.d5
-rw-r--r--ld/testsuite/ld-elf/anno-sym.l4
-rw-r--r--ld/testsuite/ld-elf/anno-sym.s13
9 files changed, 105 insertions, 30 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 721fddc..47b9c91 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,11 @@
+2021-04-28 Nick Clifton <nickc@redhat.com>
+
+ * 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 <vapier@gentoo.org>
* elf-bfd.h: Include stdlib.h.
diff --git a/bfd/elf.c b/bfd/elf.c
index 4846b7b..851440b 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 81667ea..79b94e8 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 08227f0..ed72de2 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 0a1d7a6..b6f083e 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 9bb178e..3c4bec5 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,9 @@
+2021-04-28 Nick Clifton <nickc@redhat.com>
+
+ * 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 <jbeulich@suse.com>
* 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 0000000..9e53c4a
--- /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 0000000..ee9611a
--- /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 0000000..0e4b5aa
--- /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
+