summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIgor Kudrin <ikudrin.dev@gmail.com>2015-11-12 04:08:12 +0000
committerIgor Kudrin <ikudrin.dev@gmail.com>2015-11-12 04:08:12 +0000
commitf4cdfe88eefa10906efdb86b6d80aa9fcf841925 (patch)
treeb3f7723bb48e9b202cae2706816c9396f360e4f4
parent6003443b8e04407d5497301b1cd9b3511b9b4343 (diff)
downloadbcm5719-llvm-f4cdfe88eefa10906efdb86b6d80aa9fcf841925.tar.gz
bcm5719-llvm-f4cdfe88eefa10906efdb86b6d80aa9fcf841925.zip
[ELF2] Sort dynamic symbols according to the MIPS requirements.
The MIPS ABI has requirements to sort the entries in the .dyn.sym section. Symbols which are not in the GOT have to precede the symbols which are added to the GOT. The latter must have the same order as the corresponding GOT entries. Since these sorting requirements contradict those of the GNU hash section, they cannot be used together. Differential revision: http://reviews.llvm.org/D14281 llvm-svn: 252854
-rw-r--r--lld/ELF/Driver.cpp3
-rw-r--r--lld/ELF/OutputSections.cpp13
-rw-r--r--lld/test/elf2/mips-dynsym-sort.s43
-rw-r--r--lld/test/elf2/mips-gnu-hash.s15
4 files changed, 74 insertions, 0 deletions
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 6087a2142cc..0d78830bf43 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -220,6 +220,9 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) {
if (Files.empty())
error("no input files.");
+
+ if (Config->GnuHash && Config->EMachine == EM_MIPS)
+ error("The .gnu.hash section is not compatible with the MIPS target.");
}
template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index 21ab5a115df..f1eba00145f 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -1081,6 +1081,17 @@ SymbolTableSection<ELFT>::SymbolTableSection(
Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
}
+// Orders symbols according to their positions in the GOT,
+// in compliance with MIPS ABI rules.
+// See "Global Offset Table" in Chapter 5 in the following document
+// for detailed description:
+// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+static bool sortMipsSymbols(SymbolBody *L, SymbolBody *R) {
+ if (!L->isInGot() || !R->isInGot())
+ return R->isInGot();
+ return L->GotIndex < R->GotIndex;
+}
+
template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
if (this->Header.sh_size)
return; // Already finalized.
@@ -1100,6 +1111,8 @@ template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
if (Out<ELFT>::GnuHashTab)
// NB: It also sorts Symbols to meet the GNU hash table requirements.
Out<ELFT>::GnuHashTab->addSymbols(Symbols);
+ else if (Config->EMachine == EM_MIPS)
+ std::stable_sort(Symbols.begin(), Symbols.end(), sortMipsSymbols);
size_t I = 0;
for (SymbolBody *B : Symbols)
B->setDynamicSymbolTableIndex(++I);
diff --git a/lld/test/elf2/mips-dynsym-sort.s b/lld/test/elf2/mips-dynsym-sort.s
new file mode 100644
index 00000000000..bbd3282364c
--- /dev/null
+++ b/lld/test/elf2/mips-dynsym-sort.s
@@ -0,0 +1,43 @@
+# Check the order of dynamic symbols for the MIPS target.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t-be.o
+# RUN: ld.lld2 -shared %t-be.o -o %t-be.so
+# RUN: llvm-readobj -symbols -dyn-symbols %t-be.so | FileCheck %s
+
+# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %t-el.o
+# RUN: ld.lld2 -shared %t-el.o -o %t-el.so
+# RUN: llvm-readobj -symbols -dyn-symbols %t-el.so | FileCheck %s
+
+# REQUIRES: mips
+
+ .data
+ .globl v1,v2,v3
+v1:
+ .space 4
+v2:
+ .space 4
+v3:
+ .space 4
+
+ .text
+ .globl __start
+__start:
+ lui $2, %got(v3) # v3 will precede v1 in the GOT
+ lui $2, %got(v1)
+
+# Since all these symbols have global binding,
+# the Symbols section contains them in the original order.
+# CHECK: Symbols [
+# CHECK: Name: v1
+# CHECK: Name: v2
+# CHECK: Name: v3
+# CHECK: ]
+
+# The symbols in the DynamicSymbols section are sorted in compliance with
+# the MIPS rules. v2 comes first as it is not in the GOT.
+# v1 and v3 are sorted according to their order in the GOT.
+# CHECK: DynamicSymbols [
+# CHECK: Name: v2@
+# CHECK: Name: v3@
+# CHECK: Name: v1@
+# CHECK: ]
diff --git a/lld/test/elf2/mips-gnu-hash.s b/lld/test/elf2/mips-gnu-hash.s
new file mode 100644
index 00000000000..f42acaf6e8b
--- /dev/null
+++ b/lld/test/elf2/mips-gnu-hash.s
@@ -0,0 +1,15 @@
+# Shouldn't allow the GNU hash style to be selected with the MIPS target.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t-be.o
+# RUN: not ld.lld2 -shared -hash-style=gnu %t-be.o -o %t-be.so 2>&1 | FileCheck %s
+
+# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %t-el.o
+# RUN: not ld.lld2 -shared -hash-style=gnu %t-el.o -o %t-el.so 2>&1 | FileCheck %s
+
+# CHECK: The .gnu.hash section is not compatible with the MIPS target.
+
+# REQUIRES: mips
+
+ .globl __start
+__start:
+ nop
OpenPOWER on IntegriCloud