diff --git a/bolt/CMakeLists.txt b/bolt/CMakeLists.txt --- a/bolt/CMakeLists.txt +++ b/bolt/CMakeLists.txt @@ -73,6 +73,8 @@ endif() endif() +find_program(GNU_LD_EXECUTABLE NAMES ${LLVM_DEFAULT_TARGET_TRIPLE}-ld.bfd ld.bfd DOC "GNU ld") + # If we can't find a revision, set it to "". if (NOT BOLT_REVISION) set(BOLT_REVISION "") diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h --- a/bolt/include/bolt/Core/BinaryContext.h +++ b/bolt/include/bolt/Core/BinaryContext.h @@ -774,6 +774,22 @@ return Itr != GlobalSymbols.end() ? Itr->second : nullptr; } + /// Return registered PLT entry BinaryData with the given \p Name + /// or nullptr if no global PLT symbol with that name exists. + const BinaryData *getPLTBinaryDataByName(StringRef Name) const { + if (const BinaryData *Data = getBinaryDataByName(Name.str() + "@PLT")) + return Data; + + // The symbol name might contain versioning information e.g + // memcpy@@GLIBC_2.17. Remove it and try to locate binary data + // without it. + size_t At = Name.find("@"); + if (At != std::string::npos) + return getBinaryDataByName(Name.str().substr(0, At) + "@PLT"); + + return nullptr; + } + /// Return true if \p SymbolName was generated internally and was not present /// in the input binary. bool isInternalSymbolName(const StringRef Name) { diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -1884,7 +1884,7 @@ IsSectionRelocation = (cantFail(Symbol.getType()) == SymbolRef::ST_Debug); // Check for PLT entry registered with symbol name if (!SymbolAddress && IsAArch64) { - BinaryData *BD = BC->getBinaryDataByName(SymbolName + "@PLT"); + const BinaryData *BD = BC->getPLTBinaryDataByName(SymbolName); SymbolAddress = BD ? BD->getAddress() : 0; } } @@ -3035,7 +3035,7 @@ std::string SymName = Symbol.str(); LLVM_DEBUG(dbgs() << "BOLT: looking for " << SymName << "\n"); // Resolve to a PLT entry if possible - if (BinaryData *I = BC.getBinaryDataByName(SymName + "@PLT")) { + if (const BinaryData *I = BC.getPLTBinaryDataByName(SymName)) { AllResults[Symbol] = JITEvaluatedSymbol(I->getAddress(), JITSymbolFlags()); continue; diff --git a/bolt/test/lit.cfg.py b/bolt/test/lit.cfg.py --- a/bolt/test/lit.cfg.py +++ b/bolt/test/lit.cfg.py @@ -53,6 +53,9 @@ if config.bolt_enable_runtime: config.available_features.add("bolt-runtime") +if config.gnu_ld: + config.available_features.add("gnu_ld") + llvm_config.use_default_substitutions() llvm_config.config.environment['CLANG'] = config.bolt_clang diff --git a/bolt/test/lit.site.cfg.py.in b/bolt/test/lit.site.cfg.py.in --- a/bolt/test/lit.site.cfg.py.in +++ b/bolt/test/lit.site.cfg.py.in @@ -21,6 +21,7 @@ config.python_executable = "@PYTHON_EXECUTABLE@" config.bolt_clang = "@BOLT_CLANG_EXE@" config.bolt_lld = "@BOLT_LLD_EXE@" +config.gnu_ld = "@GNU_LD_EXECUTABLE@" import lit.llvm lit.llvm.initialize(lit_config, config) diff --git a/bolt/test/runtime/AArch64/plt.c b/bolt/test/runtime/Inputs/plt.c rename from bolt/test/runtime/AArch64/plt.c rename to bolt/test/runtime/Inputs/plt.c --- a/bolt/test/runtime/AArch64/plt.c +++ b/bolt/test/runtime/Inputs/plt.c @@ -1,11 +1,5 @@ -// This test checks that the pointers to PLT are properly updated. - -// RUN: %clang %cflags %s -fuse-ld=lld \ -// RUN: -o %t.exe -Wl,-q -// RUN: llvm-bolt %t.exe -o %t.bolt.exe -use-old-text=0 -lite=0 -// RUN: %t.bolt.exe - #include +#include void *(*memcpy_p)(void *dest, const void *src, size_t n); void *(*memset_p)(void *dest, int c, size_t n); @@ -22,4 +16,6 @@ memset_p(&a, 0, sizeof(a)); if (a != 0) return 1; + + printf("Test completed\n"); } diff --git a/bolt/test/runtime/AArch64/iplt.c b/bolt/test/runtime/iplt.c rename from bolt/test/runtime/AArch64/iplt.c rename to bolt/test/runtime/iplt.c --- a/bolt/test/runtime/AArch64/iplt.c +++ b/bolt/test/runtime/iplt.c @@ -23,7 +23,9 @@ int main() { int a = 0xdeadbeef, b = 0; - ifoo(); imemcpy(&b, &a, sizeof(b)); - return a != b; + if (a != b) + return -1; + + ifoo(); } diff --git a/bolt/test/runtime/plt_gnu_ld.test b/bolt/test/runtime/plt_gnu_ld.test new file mode 100644 --- /dev/null +++ b/bolt/test/runtime/plt_gnu_ld.test @@ -0,0 +1,12 @@ +// This test checks that the pointers to PLT are properly updated. +// The test is using bfd linker, since it may add versioning string +// to the symbol name e.g. memcpy@@GLIBC_2.17 + +// REQUIRES: gnu_ld + +// RUN: %clang %cflags %p/Inputs/plt.c -fuse-ld=bfd \ +// RUN: -o %t.bfd.exe -Wl,-q +// RUN: llvm-bolt %t.bfd.exe -o %t.bfd.bolt.exe -use-old-text=0 -lite=0 +// RUN: %t.bfd.bolt.exe | FileCheck %s + +// CHECK: Test completed diff --git a/bolt/test/runtime/plt_lld.test b/bolt/test/runtime/plt_lld.test new file mode 100644 --- /dev/null +++ b/bolt/test/runtime/plt_lld.test @@ -0,0 +1,10 @@ +// This test checks that the pointers to PLT are properly updated. +// The test is using lld linker. + +// Test with lld linker: +// RUN: %clang %cflags %p/Inputs/plt.c -fuse-ld=lld \ +// RUN: -o %t.lld.exe -Wl,-q +// RUN: llvm-bolt %t.lld.exe -o %t.lld.bolt.exe -use-old-text=0 -lite=0 +// RUN: %t.lld.bolt.exe | FileCheck %s + +// CHECK: Test completed