diff options
author | Paschalis Mpeis <Paschalis.Mpeis@arm.com> | 2024-07-08 16:36:54 +0100 |
---|---|---|
committer | Paschalis Mpeis <Paschalis.Mpeis@arm.com> | 2024-08-19 14:45:54 +0100 |
commit | fe4d176f261536c948bc8164be967944fc9f25fd (patch) | |
tree | 2a807401df0fb54762f4c75d0187859438acff28 | |
parent | a9962ed5890f1ae0b374b4e8113cb0c6092cb9ec (diff) | |
download | llvm-users/paschalis-mpeis/bolt-static-binary-patchelf-fix.zip llvm-users/paschalis-mpeis/bolt-static-binary-patchelf-fix.tar.gz llvm-users/paschalis-mpeis/bolt-static-binary-patchelf-fix.tar.bz2 |
[WORKAROUND][BOLT][AArch64] Static binary patching for ELF.users/paschalis-mpeis/bolt-static-binary-patchelf-fix
When patching statically linked binaries, avoid patching GOT entries
that did not belong to the original text section and had an alias.
One such special case is the '_init' function that belongs to the '.init'
section. It has '.init' as an alias, which points to the same address of
'_init' in the original binary.
This was observed with GNU linker. BOLT normally rejects these cases.
See issue:
https://github.com/llvm/llvm-project/issues/100096
-rw-r--r-- | bolt/lib/Rewrite/RewriteInstance.cpp | 28 | ||||
-rw-r--r-- | bolt/test/AArch64/patch-elfstatic-libc.test | 5 |
2 files changed, 31 insertions, 2 deletions
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index ded2f57..0ded964 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -5265,6 +5265,34 @@ void RewriteInstance::patchELFGOT(ELFObjectFile<ELFT> *File) { GOTContents.size()); ++GOTEntry) { if (uint64_t NewAddress = getNewFunctionAddress(*GOTEntry)) { + auto *Function = BC->getBinaryFunctionAtAddress(*GOTEntry); + + // WORKAROUND: + // Background: + // Static binaries generated with GNU linker have GOT entries, which is + // wrong. LLD does not suffer from this. See related discussion: + // https://github.com/llvm/llvm-project/issues/100096 + // + // The current approach is for BOLT to abort when a static binary contains + // such entries. However, this patch may serve as a 'Workaround' in case + // someone has encountered such a binary. ATTOW it is unclear if/when GNU + // linker will have this fixed. + // + // The workaround: + // On static binaries, avoid patching the "_init" got entry. It also + // checks that it does not belong to the original text section and that it + // an alias. This function actually aliases '.init', belongs to the + // '.init' section, and points to the same address of '_init' in the + // original binary. + if (BC->IsStaticExecutable && !Function->Aliases.empty() && + Function->getOriginSectionName() != ".bolt.org.text" && + (Function->getOneName() == "_init")) { + LLVM_DEBUG(dbgs() << "BOLT-DEBUG: ignoring GOT entry 0x" + << Twine::utohexstr(*GOTEntry) << " for '" + << Function->getOneName() << "'" << '\n'); + continue; + } + LLVM_DEBUG(dbgs() << "BOLT-DEBUG: patching GOT entry 0x" << Twine::utohexstr(*GOTEntry) << " with 0x" << Twine::utohexstr(NewAddress) << '\n'); diff --git a/bolt/test/AArch64/patch-elfstatic-libc.test b/bolt/test/AArch64/patch-elfstatic-libc.test index 07dc13a..66c8be8 100644 --- a/bolt/test/AArch64/patch-elfstatic-libc.test +++ b/bolt/test/AArch64/patch-elfstatic-libc.test @@ -11,5 +11,6 @@ REQUIRES: system-linux RUN: %clang %p/../Inputs/main.c -o %t -Wl,-q -static RUN: llvm-bolt %t -o %t.bolt > /dev/null 2>&1 -RUN: not --crash %t.bolt 2>&1 | FileCheck %s -CHECK: Unexpected reloc type in static binary. +RUN: not %t.bolt 2>&1 | FileCheck %s --allow-empty + +CHECK-NOT: Unexpected reloc type in static binary. |