aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaschalis Mpeis <Paschalis.Mpeis@arm.com>2024-07-08 16:36:54 +0100
committerPaschalis Mpeis <Paschalis.Mpeis@arm.com>2024-08-19 14:45:54 +0100
commitfe4d176f261536c948bc8164be967944fc9f25fd (patch)
tree2a807401df0fb54762f4c75d0187859438acff28
parenta9962ed5890f1ae0b374b4e8113cb0c6092cb9ec (diff)
downloadllvm-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.cpp28
-rw-r--r--bolt/test/AArch64/patch-elfstatic-libc.test5
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.