summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Richardson <arichardson.kde@gmail.com>2017-10-05 23:28:29 +0000
committerAlexander Richardson <arichardson.kde@gmail.com>2017-10-05 23:28:29 +0000
commit57f089775b23cabdbafd5a84eebd78d830bf8d9d (patch)
tree1425fd877f99c2a92bdb7dfeedccd658b8229c43
parentb4e77d98ed9ccf8593667220b5bd022853691fad (diff)
downloadbcm5719-llvm-57f089775b23cabdbafd5a84eebd78d830bf8d9d.tar.gz
bcm5719-llvm-57f089775b23cabdbafd5a84eebd78d830bf8d9d.zip
[ELF] Don't crash when parsing a file with external version definition references
Summary: We were crashing when linking telnetd in FreeBSD because lld was emitting corrupted output files for --norosegment. In this file the version index of some symbols was set to 9 but lld only found 8 version definitions. I am not sure how to create a minimal .so file that also exposes this behaviour so I just added the one that initially caused the error to Inputs/ This partially addresses https://bugs.llvm.org/show_bug.cgi?id=34705 Reviewers: ruiu, rafael, pcc, grimar Reviewed By: ruiu Subscribers: emaste, krytarowski Tags: #lld Differential Revision: https://reviews.llvm.org/D38397 llvm-svn: 315035
-rw-r--r--lld/ELF/InputFiles.cpp15
-rw-r--r--lld/test/ELF/Inputs/corrupt-version-reference.sobin0 -> 134272 bytes
-rw-r--r--lld/test/ELF/corrupted-version-reference.s10
3 files changed, 22 insertions, 3 deletions
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index cfe8ae74ffa..a0a38de0d8a 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -775,9 +775,18 @@ template <class ELFT> void SharedFile<ELFT>::parseRest() {
// Ignore local symbols.
if (Versym && VersymIndex == VER_NDX_LOCAL)
continue;
-
- const Elf_Verdef *V =
- VersymIndex == VER_NDX_GLOBAL ? nullptr : Verdefs[VersymIndex];
+ const Elf_Verdef *V = nullptr;
+ if (VersymIndex != VER_NDX_GLOBAL) {
+ if (VersymIndex >= Verdefs.size()) {
+ error("corrupt input file: version definition index " +
+ Twine(VersymIndex) + " for symbol " + Name +
+ " is greater than the maximum value " +
+ Twine(Verdefs.size() - 1) + "\n>>> symbol is defined in " +
+ toString(this));
+ continue;
+ }
+ V = Verdefs[VersymIndex];
+ }
if (!Hidden)
Symtab->addShared(Name, this, Sym, V);
diff --git a/lld/test/ELF/Inputs/corrupt-version-reference.so b/lld/test/ELF/Inputs/corrupt-version-reference.so
new file mode 100644
index 00000000000..ef6adc6a026
--- /dev/null
+++ b/lld/test/ELF/Inputs/corrupt-version-reference.so
Binary files differ
diff --git a/lld/test/ELF/corrupted-version-reference.s b/lld/test/ELF/corrupted-version-reference.s
new file mode 100644
index 00000000000..15fbbeeaa14
--- /dev/null
+++ b/lld/test/ELF/corrupted-version-reference.s
@@ -0,0 +1,10 @@
+# RUN: llvm-mc -triple=mips64-unknown-freebsd %s -filetype=obj -o %t.o
+# RUN: not ld.lld %t.o %S/Inputs/corrupt-version-reference.so -o %t.exe 2>&1 | FileCheck %s
+
+# CHECK: error: corrupt input file: version definition index 9 for symbol __cxa_finalize is greater than the maximum value 8
+# CHECK: >>> symbol is defined in {{.+}}/corrupt-version-reference.so
+
+.globl __start
+__start:
+ dla $a0, __cxa_finalize
+ nop
OpenPOWER on IntegriCloud