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/AArch64/Inputs/plt_gnu_ld.yaml b/bolt/test/AArch64/Inputs/plt_gnu_ld.yaml new file mode 100644 --- /dev/null +++ b/bolt/test/AArch64/Inputs/plt_gnu_ld.yaml @@ -0,0 +1,364 @@ +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_AARCH64 + Entry: 0x400510 +ProgramHeaders: + - Type: PT_PHDR + Flags: [ PF_R ] + VAddr: 0x400040 + Align: 0x8 + - Type: PT_LOAD + Flags: [ PF_X, PF_R ] + VAddr: 0x400000 + Align: 0x10000 + - Type: PT_DYNAMIC + Flags: [ PF_W, PF_R ] + FirstSec: .dynamic + LastSec: .dynamic + VAddr: 0x410E08 + Align: 0x8 +Sections: + - Name: .dynsym + Type: SHT_DYNSYM + Flags: [ SHF_ALLOC ] + Address: 0x4002A0 + Link: .dynstr + AddressAlign: 0x8 + - Name: .dynstr + Type: SHT_STRTAB + Flags: [ SHF_ALLOC ] + Address: 0x400348 + AddressAlign: 0x1 + - Name: .rela.dyn + Type: SHT_RELA + Flags: [ SHF_ALLOC ] + Address: 0x4003C8 + Link: .dynsym + AddressAlign: 0x8 + - Name: .rela.plt + Type: SHT_RELA + Flags: [ SHF_ALLOC, SHF_INFO_LINK ] + Address: 0x4003E0 + Link: .dynsym + AddressAlign: 0x8 + Info: .got.plt + Relocations: + - Offset: 0x411000 + Symbol: memcpy + Type: R_AARCH64_JUMP_SLOT + - Offset: 0x411008 + Symbol: __libc_start_main + Type: R_AARCH64_JUMP_SLOT + - Offset: 0x411010 + Symbol: memset + Type: R_AARCH64_JUMP_SLOT + - Offset: 0x411020 + Symbol: abort + Type: R_AARCH64_JUMP_SLOT + - Offset: 0x411028 + Symbol: printf + Type: R_AARCH64_JUMP_SLOT + - Name: .plt + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x400490 + AddressAlign: 0x10 + EntSize: 0x10 + Content: F07BBFA99000009011FE47F910E23F9120021FD61F2003D51F2003D51F2003D5900000B0110240F91002009120021FD6900000B0110640F91022009120021FD6900000B0110A40F91042009120021FD6900000B0110E40F91062009120021FD6900000B0111240F91082009120021FD6900000B0111640F910A2009120021FD6 + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x400510 + AddressAlign: 0x8 + Content: 1D0080D21E0080D2E50300AAE10340F9E2230091E603009100000090002015910300009063201B910400009084201D91E0FFFF97EBFFFF972F0000148000009000F047F9400000B4E2FFFF17C0035FD6800000B000000191810000B0210001913F0000EBC00000540100009021B443F9610000B4F00301AA00021FD6C0035FD6800000B000000191810000B021000191210000CB22FC7FD3410C818BFF0781EB21FC4193C00000540200009042B843F9620000B4F00302AA00021FD6C0035FD6FD7BBEA9FD030091F30B00F9930000B06002413980000035DEFFFF972000805260020139F30B40F9FD7BC2A8C0035FD6E4FFFF17FF8300D1FD7B01A9FD430091BFC31FB8E1230091E8DD9752A8D5BB72E80300B9E80B00B9E0130091FF0700B9880000B00900009029C11291092500F9082540F9820080D200013FD6E90340B9E80740B90801096BA00000540100001428008052A8C31FB814000014880000B00900009029411391092900F9082940F9E0230091E1031F2A820080D200013FD6E80B40B9A80000340100001428008052A8C31FB8050000140000009000E01D9194FFFF9701000014A0C35FB8FD7B41A9FF830091C0035FD6FD7BBCA9FD030091F35301A99400009094023891F55B02A995000090B5E23791940215CBF603002AF76303A9F70301AAF80302AA5DFFFF97FF0F94EB6001005494FE4393130080D2A37A73F8E20318AA73060091E10317AAE003162A60003FD69F0213EB21FFFF54F35341A9F55B42A9F76343A9FD7BC4A8C0035FD61F2003D5C0035FD6 + - Name: .dynamic + Type: SHT_DYNAMIC + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x410E08 + Link: .dynstr + AddressAlign: 0x8 + Entries: + - Tag: DT_NEEDED + Value: 0x1 + - Tag: DT_STRTAB + Value: 0x400348 + - Tag: DT_SYMTAB + Value: 0x4002A0 + - Tag: DT_STRSZ + Value: 0x52 + - Tag: DT_SYMENT + Value: 0x18 + - Tag: DT_PLTGOT + Value: 0x410FE8 + - Tag: DT_PLTRELSZ + Value: 0x90 + - Tag: DT_PLTREL + Value: 0x7 + - Tag: DT_JMPREL + Value: 0x4003E0 + - Tag: DT_RELA + Value: 0x4003C8 + - Tag: DT_RELASZ + Value: 0x18 + - Tag: DT_RELAENT + Value: 0x18 + - Tag: DT_NULL + Value: 0x0 + - Name: .got + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x410FD8 + AddressAlign: 0x8 + EntSize: 0x8 + Content: '080E4100000000000000000000000000' + - Name: .got.plt + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x410FE8 + AddressAlign: 0x8 + EntSize: 0x8 + Content: '000000000000000000000000000000000000000000000000900440000000000090044000000000009004400000000000900440000000000090044000000000009004400000000000' + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x411030 + AddressAlign: 0x8 + Content: '00000000000000000000000000000000' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x411040 + AddressAlign: 0x8 + Size: 0x18 + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x8 + Info: .text + Relocations: + - Offset: 0x400528 + Symbol: .text + Type: R_AARCH64_ADR_PREL_PG_HI21 + Addend: 56 + - Offset: 0x40052C + Symbol: .text + Type: R_AARCH64_ADD_ABS_LO12_NC + Addend: 56 + - Offset: 0x400544 + Symbol: 'abort@@GLIBC_2.17' + Type: R_AARCH64_CALL26 + - Offset: 0x400548 + Symbol: main + Type: R_AARCH64_JUMP26 + - Offset: 0x4005DC + Symbol: .bss + Type: R_AARCH64_ADR_PREL_PG_HI21 + - Offset: 0x4005E0 + Symbol: .bss + Type: R_AARCH64_LDST8_ABS_LO12_NC + - Offset: 0x4005F0 + Symbol: .bss + Type: R_AARCH64_LDST8_ABS_LO12_NC + - Offset: 0x400630 + Symbol: memcpy_p + Type: R_AARCH64_ADR_PREL_PG_HI21 + - Offset: 0x400634 + Symbol: 'memcpy@@GLIBC_2.17' + Type: R_AARCH64_ADR_PREL_PG_HI21 + - Offset: 0x400638 + Symbol: 'memcpy@@GLIBC_2.17' + Type: R_AARCH64_ADD_ABS_LO12_NC + - Offset: 0x40063C + Symbol: memcpy_p + Type: R_AARCH64_LDST64_ABS_LO12_NC + - Offset: 0x400640 + Symbol: memcpy_p + Type: R_AARCH64_LDST64_ABS_LO12_NC + - Offset: 0x40066C + Symbol: memset_p + Type: R_AARCH64_ADR_PREL_PG_HI21 + - Offset: 0x400670 + Symbol: 'memset@@GLIBC_2.17' + Type: R_AARCH64_ADR_PREL_PG_HI21 + - Offset: 0x400674 + Symbol: 'memset@@GLIBC_2.17' + Type: R_AARCH64_ADD_ABS_LO12_NC + - Offset: 0x400678 + Symbol: memset_p + Type: R_AARCH64_LDST64_ABS_LO12_NC + - Offset: 0x40067C + Symbol: memset_p + Type: R_AARCH64_LDST64_ABS_LO12_NC + - Offset: 0x4006B0 + Symbol: 'printf@@GLIBC_2.17' + Type: R_AARCH64_CALL26 + - Type: SectionHeaderTable + Sections: + - Name: .dynsym + - Name: .dynstr + - Name: .rela.dyn + - Name: .rela.plt + - Name: .plt + - Name: .text + - Name: .rela.text + - Name: .dynamic + - Name: .got + - Name: .got.plt + - Name: .data + - Name: .bss + - Name: .symtab + - Name: .strtab + - Name: .shstrtab +Symbols: + - Name: .dynsym + Type: STT_SECTION + Section: .dynsym + Value: 0x4002A0 + - Name: .dynstr + Type: STT_SECTION + Section: .dynstr + Value: 0x400348 + - Name: .rela.dyn + Type: STT_SECTION + Section: .rela.dyn + Value: 0x4003C8 + - Name: .rela.plt + Type: STT_SECTION + Section: .rela.plt + Value: 0x4003E0 + - Name: .plt + Type: STT_SECTION + Section: .plt + Value: 0x400490 + - Name: .text + Type: STT_SECTION + Section: .text + Value: 0x400510 + - Name: .dynamic + Type: STT_SECTION + Section: .dynamic + Value: 0x410E08 + - Name: .got + Type: STT_SECTION + Section: .got + Value: 0x410FD8 + - Name: .got.plt + Type: STT_SECTION + Section: .got.plt + Value: 0x410FE8 + - Name: .data + Type: STT_SECTION + Section: .data + Value: 0x411030 + - Name: .bss + Type: STT_SECTION + Section: .bss + Value: 0x411040 + - Name: _DYNAMIC + Type: STT_OBJECT + Section: .dynamic + Value: 0x410E08 + - Name: _GLOBAL_OFFSET_TABLE_ + Type: STT_OBJECT + Section: .got + Value: 0x410FD8 + - Name: 'memcpy@@GLIBC_2.17' + Type: STT_FUNC + Binding: STB_GLOBAL + Value: 0x4004B0 + - Name: data_start + Section: .data + Binding: STB_WEAK + Value: 0x411030 + - Name: __bss_start__ + Section: .bss + Binding: STB_GLOBAL + Value: 0x411040 + - Name: memcpy_p + Type: STT_OBJECT + Section: .bss + Binding: STB_GLOBAL + Value: 0x411048 + Size: 0x8 + - Name: _bss_end__ + Section: .bss + Binding: STB_GLOBAL + Value: 0x411058 + - Name: __bss_end__ + Section: .bss + Binding: STB_GLOBAL + Value: 0x411058 + - Name: '__libc_start_main@@GLIBC_2.17' + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: 'memset@@GLIBC_2.17' + Type: STT_FUNC + Binding: STB_GLOBAL + Value: 0x4004D0 + - Name: __data_start + Section: .data + Binding: STB_GLOBAL + Value: 0x411030 + - Name: memset_p + Type: STT_OBJECT + Section: .bss + Binding: STB_GLOBAL + Value: 0x411050 + Size: 0x8 + - Name: __dso_handle + Type: STT_OBJECT + Section: .data + Binding: STB_GLOBAL + Value: 0x411038 + Other: [ STV_HIDDEN ] + - Name: 'abort@@GLIBC_2.17' + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: _end + Section: .bss + Binding: STB_GLOBAL + Value: 0x411058 + - Name: _start + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x400510 + - Name: __end__ + Section: .bss + Binding: STB_GLOBAL + Value: 0x411058 + - Name: __bss_start + Section: .bss + Binding: STB_GLOBAL + Value: 0x411040 + - Name: main + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x400604 + Size: 0xC4 + - Name: 'printf@@GLIBC_2.17' + Type: STT_FUNC + Binding: STB_GLOBAL +DynamicSymbols: + - Name: __libc_start_main + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: abort + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: printf + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: memcpy + Type: STT_FUNC + Binding: STB_GLOBAL + Value: 0x4004B0 + - Name: memset + Type: STT_FUNC + Binding: STB_GLOBAL + Value: 0x4004D0 diff --git a/bolt/test/AArch64/plt_gnu_ld.test b/bolt/test/AArch64/plt_gnu_ld.test new file mode 100644 --- /dev/null +++ b/bolt/test/AArch64/plt_gnu_ld.test @@ -0,0 +1,12 @@ +// This test checks that the PLT symbols are properly recognized +// by the BOLT tool. +// The test is using bfd linker, since it may add versioning string +// to the symbol name e.g. memcpy@@GLIBC_2.17 + +// RUN: yaml2obj %p/Inputs/plt_gnu_ld.yaml &> %t.exe +// RUN: llvm-bolt %t.bfd.exe -o %t.bolt.exe -use-old-text=0 -lite=0 \ +// RUN: -print-cfg -print-only=main | FileCheck %s + +// CHECK: memcpy@PLT +// CHECK: memset@PLT +// CHECK: printf@PLT diff --git a/bolt/test/AArch64/plt_lld.test b/bolt/test/AArch64/plt_lld.test new file mode 100644 --- /dev/null +++ b/bolt/test/AArch64/plt_lld.test @@ -0,0 +1,11 @@ +// This test checks that the PLT symbols are properly recognized +// by the BOLT tool. + +// 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: -print-cfg -print-only=main | FileCheck %s + +// CHECK: memcpy@PLT +// CHECK: memset@PLT +// CHECK: printf@PLT diff --git a/bolt/test/runtime/AArch64/plt.c b/bolt/test/Inputs/plt.c rename from bolt/test/runtime/AArch64/plt.c rename to bolt/test/Inputs/plt.c --- a/bolt/test/runtime/AArch64/plt.c +++ b/bolt/test/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/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/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,9 @@ +// This test checks that the pointers to PLT are properly updated. +// The test is using 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