[WORKAROUND][BOLT][AArch64] Static binary patching for ELF.
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
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 @@
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 @@
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.