Stop the BFD library from treating annobin symbols as potential function symbols.
authorNick Clifton <nickc@redhat.com>
Wed, 28 Apr 2021 10:49:09 +0000 (11:49 +0100)
committerNick Clifton <nickc@redhat.com>
Wed, 28 Apr 2021 10:49:09 +0000 (11:49 +0100)
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
bfd/elf.c
bfd/elf32-arm.c
bfd/elf64-ppc.c
bfd/elfnn-aarch64.c
ld/ChangeLog
ld/testsuite/ld-elf/anno-sym.d [new file with mode: 0644]
ld/testsuite/ld-elf/anno-sym.l [new file with mode: 0644]
ld/testsuite/ld-elf/anno-sym.s [new file with mode: 0644]

index 721fddc935d23652aca9cc7931c240da0dfc29e4..47b9c9135819b2d3a0f19b14ee5e640c5153511d 100644 (file)
@@ -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.
index 4846b7bd47f98fd52a2aee86bdc6486bd9a7964f..851440b765284763b373739444073f732d31f60b 100644 (file)
--- 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.  */
index 81667ea090d51e505368b4299f1bf5d0fa7d1509..79b94e836fc82296a8b48e7baeecf040bc6c86ae 100644 (file)
@@ -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
index 08227f0e43ab5b2e98aaff5ac56822970bfed162..ed72de27507f835bc789c01cffffccf7e1f32b9e 100644 (file)
@@ -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
index 0a1d7a617c83c4c8c9dcc33fe2ac7fd7722d7f0b..b6f083e430bb51e6930d4663f60362079101511c 100644 (file)
@@ -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
index 9bb178e42485aeef2d80e17580f2daac57be6e22..3c4bec58949b1dea6463c35bbcb3acecfaf0eddf 100644 (file)
@@ -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 (file)
index 0000000..9e53c4a
--- /dev/null
@@ -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 (file)
index 0000000..ee9611a
--- /dev/null
@@ -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 (file)
index 0000000..0e4b5aa
--- /dev/null
@@ -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
+