binutils: assertion failure bfd/elfxx-mips.c:3860
authorHauke Mehrtens <hauke@hauke-m.de>
Sat, 27 Jan 2018 21:51:59 +0000 (22:51 +0100)
committerHauke Mehrtens <hauke@hauke-m.de>
Sat, 27 Jan 2018 21:51:59 +0000 (22:51 +0100)
With forced PIE and SSP support I ran into this assertion failure.
backport two patches to fix this problem from the binutils 2.28 branch.
This fix is already included in binutils 2.28.1 and 2.29.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
toolchain/binutils/patches/2.28/001-ELF-BFD-Limit-_bfd_elf_link_renumber_dynsyms-call-in.patch [new file with mode: 0644]
toolchain/binutils/patches/2.28/002-PR-ld-21334-Always-call-_bfd_elf_link_renumber_dynsy.patch [new file with mode: 0644]

diff --git a/toolchain/binutils/patches/2.28/001-ELF-BFD-Limit-_bfd_elf_link_renumber_dynsyms-call-in.patch b/toolchain/binutils/patches/2.28/001-ELF-BFD-Limit-_bfd_elf_link_renumber_dynsyms-call-in.patch
new file mode 100644 (file)
index 0000000..e2587b8
--- /dev/null
@@ -0,0 +1,52 @@
+From 2424aef3a744bc6ca4099a655065c70a63f0fb49 Mon Sep 17 00:00:00 2001
+From: "Maciej W. Rozycki" <macro@imgtec.com>
+Date: Wed, 26 Apr 2017 22:18:13 +0100
+Subject: ELF/BFD: Limit `_bfd_elf_link_renumber_dynsyms' call in section GC
+
+Consistently call `_bfd_elf_link_renumber_dynsyms' only if linking a
+dynamic binary, complementing code in `bfd_elf_size_dynsym_hash_dynstr'
+and commit ccabcbe51e85 ("New attempt at fixing MIPS --gc-sections et
+al."), <https://sourceware.org/ml/binutils/2005-08/msg00258.html>.
+
+       bfd/
+       * elflink.c (elf_gc_sweep): Only call
+       `_bfd_elf_link_renumber_dynsyms' if dynamic sections have been
+       created.
+
+(backported from commit c46cec3a8cfe02fbe0f6c67ba53abc5369c5c659)
+---
+ bfd/ChangeLog | 6 ++++++
+ bfd/elflink.c | 3 ++-
+ 2 files changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/bfd/ChangeLog b/bfd/ChangeLog
+index 85c6a817e5..537ebb5e2c 100644
+--- a/bfd/ChangeLog
++++ b/bfd/ChangeLog
+@@ -1,3 +1,9 @@
++2017-04-26  Maciej W. Rozycki  <macro@imgtec.com>
++
++      * elflink.c (elf_gc_sweep): Only call
++      `_bfd_elf_link_renumber_dynsyms' if dynamic sections have been
++      created.
++
+ 2017-03-02  Tristan Gingold  <gingold@adacore.com>
+       * version.m4: Bump version to 2.28
+diff --git a/bfd/elflink.c b/bfd/elflink.c
+index 69b66f2831..75d6543dcc 100644
+--- a/bfd/elflink.c
++++ b/bfd/elflink.c
+@@ -12986,7 +12986,8 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info)
+   elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol,
+                         &sweep_info);
+-  _bfd_elf_link_renumber_dynsyms (abfd, info, &section_sym_count);
++  if (elf_hash_table (info)->dynamic_sections_created)
++    _bfd_elf_link_renumber_dynsyms (abfd, info, &section_sym_count);
+   return TRUE;
+ }
+-- 
+2.11.0
+
diff --git a/toolchain/binutils/patches/2.28/002-PR-ld-21334-Always-call-_bfd_elf_link_renumber_dynsy.patch b/toolchain/binutils/patches/2.28/002-PR-ld-21334-Always-call-_bfd_elf_link_renumber_dynsy.patch
new file mode 100644 (file)
index 0000000..7cfbaa6
--- /dev/null
@@ -0,0 +1,184 @@
+From 51ffcfc2c67b4c4aa1620fb4c9834c38d150e1c5 Mon Sep 17 00:00:00 2001
+From: "Maciej W. Rozycki" <macro@imgtec.com>
+Date: Wed, 26 Apr 2017 22:23:44 +0100
+Subject: PR ld/21334: Always call `_bfd_elf_link_renumber_dynsyms' if required
+
+Complement commit e17b0c351f0b ("MIPS/BFD: Respect the ELF gABI dynamic
+symbol table sort requirement") and correct an inconsistency in dynamic
+symbol accounting data causing an assertion failure in the MIPS backend:
+
+ld: BFD (GNU Binutils) 2.28.51.20170330 assertion fail
+../../binutils-gdb/bfd/elfxx-mips.c:3860
+
+in the course of making a GOT entry in a static binary to satisfy a GOT
+relocation present in input, due to the local dynamic symbol count not
+having been established.
+
+To do so let backends request `_bfd_elf_link_renumber_dynsyms' to be
+always called, rather than where a dynamic binary is linked only, and
+then make this request in the MIPS backend.
+
+       bfd/
+       PR ld/21334
+       * elf-bfd.h (elf_backend_data): Add `always_renumber_dynsyms'
+       member.
+       * elfxx-target.h [!elf_backend_always_renumber_dynsyms]
+       (elf_backend_always_renumber_dynsyms): Define.
+       (elfNN_bed): Initialize `always_renumber_dynsyms' member.
+       * elfxx-mips.h (elf_backend_always_renumber_dynsyms): Define.
+       * elflink.c (bfd_elf_size_dynsym_hash_dynstr): Also call
+       `_bfd_elf_link_renumber_dynsyms' if the backend has requested
+       it.
+       (elf_gc_sweep): Likewise.
+
+(backported from commit 23ec1e32b1ab714649a7c25e49b5d721fe3bd3db)
+---
+ bfd/ChangeLog      | 14 ++++++++++++++
+ bfd/elf-bfd.h      |  4 ++++
+ bfd/elflink.c      | 34 +++++++++++++++++++++++-----------
+ bfd/elfxx-mips.h   |  1 +
+ bfd/elfxx-target.h |  6 +++++-
+ 5 files changed, 47 insertions(+), 12 deletions(-)
+
+diff --git a/bfd/ChangeLog b/bfd/ChangeLog
+index 537ebb5e2c..3f10bc55f2 100644
+--- a/bfd/ChangeLog
++++ b/bfd/ChangeLog
+@@ -1,5 +1,19 @@
+ 2017-04-26  Maciej W. Rozycki  <macro@imgtec.com>
++      PR ld/21334
++      * elf-bfd.h (elf_backend_data): Add `always_renumber_dynsyms'
++      member.
++      * elfxx-target.h [!elf_backend_always_renumber_dynsyms]
++      (elf_backend_always_renumber_dynsyms): Define.
++      (elfNN_bed): Initialize `always_renumber_dynsyms' member.
++      * elfxx-mips.h (elf_backend_always_renumber_dynsyms): Define.
++      * elflink.c (bfd_elf_size_dynsym_hash_dynstr): Also call
++      `_bfd_elf_link_renumber_dynsyms' if the backend has requested
++      it.
++      (elf_gc_sweep): Likewise.
++
++2017-04-26  Maciej W. Rozycki  <macro@imgtec.com>
++
+       * elflink.c (elf_gc_sweep): Only call
+       `_bfd_elf_link_renumber_dynsyms' if dynamic sections have been
+       created.
+diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
+index 5de9ab6ca6..dc4bd87f89 100644
+--- a/bfd/elf-bfd.h
++++ b/bfd/elf-bfd.h
+@@ -1478,6 +1478,10 @@ struct elf_backend_data
+   /* Address of protected data defined in the shared library may be
+      external, i.e., due to copy relocation.   */
+   unsigned extern_protected_data : 1;
++
++  /* True if `_bfd_elf_link_renumber_dynsyms' must be called even for
++     static binaries.  */
++  unsigned always_renumber_dynsyms : 1;
+ };
+ /* Information about reloc sections associated with a bfd_elf_section_data
+diff --git a/bfd/elflink.c b/bfd/elflink.c
+index 75d6543dcc..507f2b6259 100644
+--- a/bfd/elflink.c
++++ b/bfd/elflink.c
+@@ -6710,6 +6710,8 @@ bfd_boolean
+ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   const struct elf_backend_data *bed;
++  unsigned long section_sym_count;
++  bfd_size_type dynsymcount;
+   if (!is_elf_hash_table (info->hash))
+     return TRUE;
+@@ -6717,24 +6719,30 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
+   bed = get_elf_backend_data (output_bfd);
+   (*bed->elf_backend_init_index_section) (output_bfd, info);
++  /* Assign dynsym indices.  In a shared library we generate a section
++     symbol for each output section, which come first.  Next come all
++     of the back-end allocated local dynamic syms, followed by the rest
++     of the global symbols.
++
++     This is usually not needed for static binaries, however backends
++     can request to always do it, e.g. the MIPS backend uses dynamic
++     symbol counts to lay out GOT, which will be produced in the
++     presence of GOT relocations even in static binaries (holding fixed
++     data in that case, to satisfy those relocations).  */
++
++  if (elf_hash_table (info)->dynamic_sections_created
++      || bed->always_renumber_dynsyms)
++    dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info,
++                                                &section_sym_count);
++
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+       bfd *dynobj;
+       asection *s;
+-      bfd_size_type dynsymcount;
+-      unsigned long section_sym_count;
+       unsigned int dtagcount;
+       dynobj = elf_hash_table (info)->dynobj;
+-      /* Assign dynsym indicies.  In a shared library we generate a
+-       section symbol for each output section, which come first.
+-       Next come all of the back-end allocated local dynamic syms,
+-       followed by the rest of the global symbols.  */
+-
+-      dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info,
+-                                                  &section_sym_count);
+-
+       /* Work out the size of the symbol version section.  */
+       s = bfd_get_linker_section (dynobj, ".gnu.version");
+       BFD_ASSERT (s != NULL);
+@@ -12986,7 +12994,11 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info)
+   elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol,
+                         &sweep_info);
+-  if (elf_hash_table (info)->dynamic_sections_created)
++  /* We need to reassign dynsym indices now that symbols may have
++     been removed.  See the call in `bfd_elf_size_dynsym_hash_dynstr'
++     for the details of the conditions used here.  */
++  if (elf_hash_table (info)->dynamic_sections_created
++      || bed->always_renumber_dynsyms)
+     _bfd_elf_link_renumber_dynsyms (abfd, info, &section_sym_count);
+   return TRUE;
+ }
+diff --git a/bfd/elfxx-mips.h b/bfd/elfxx-mips.h
+index fa5b5d2de9..274129b2e5 100644
+--- a/bfd/elfxx-mips.h
++++ b/bfd/elfxx-mips.h
+@@ -196,3 +196,4 @@ literal_reloc_p (int r_type)
+ #define elf_backend_post_process_headers _bfd_mips_post_process_headers
+ #define elf_backend_compact_eh_encoding _bfd_mips_elf_compact_eh_encoding
+ #define elf_backend_cant_unwind_opcode _bfd_mips_elf_cant_unwind_opcode
++#define elf_backend_always_renumber_dynsyms TRUE
+diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
+index d063fb7f1b..d07600c15d 100644
+--- a/bfd/elfxx-target.h
++++ b/bfd/elfxx-target.h
+@@ -126,6 +126,9 @@
+ #ifndef elf_backend_extern_protected_data
+ #define elf_backend_extern_protected_data 0
+ #endif
++#ifndef elf_backend_always_renumber_dynsyms
++#define elf_backend_always_renumber_dynsyms FALSE
++#endif
+ #ifndef elf_backend_stack_align
+ #define elf_backend_stack_align 16
+ #endif
+@@ -866,7 +869,8 @@ static struct elf_backend_data elfNN_bed =
+   elf_backend_no_page_alias,
+   elf_backend_default_execstack,
+   elf_backend_caches_rawsize,
+-  elf_backend_extern_protected_data
++  elf_backend_extern_protected_data,
++  elf_backend_always_renumber_dynsyms
+ };
+ /* Forward declaration for use when initialising alternative_target field.  */
+-- 
+2.11.0
+