[llvm] [BOLT] Add support for safe-icf (PR #116275)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 14 12:15:10 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-bolt
Author: Alexander Yermolovich (ayermolo)
<details>
<summary>Changes</summary>
Identical Code Folding (ICF) folds functions that are "identical" into one function, and updates symbol addresses to the new address. This reduces the size of a binary, but can lead to problems. For example when function pointers are compared. Either explicitly in the code or generated code by optimization passes like Indirect Call Promotion (ICP). After ICF what used to be two different addresses become the same address. This can lead to a different code path being taken.
This is where Safe ICF comes in. Linker (LLD) does it using address significant section generated by clang. If symbol is in it, or an object doesn't have this section symbols are not folded.
BOLT does not have the information regarding which objects do not have this section, so can't re-use this mechanism.
This implementation scans .text section and conservatively marks functions which symbols, and are not used in the control flow instructions, as unsafe. It also scans through the .rela.data section and does the same for relocations that reference functions. The latter handles the case when function pointer is stored in a local or global variable.
---
Patch is 86.39 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/116275.diff
25 Files Affected:
- (modified) bolt/include/bolt/Core/BinaryContext.h (+9)
- (modified) bolt/include/bolt/Core/BinaryFunction.h (+9)
- (modified) bolt/include/bolt/Passes/IdenticalCodeFolding.h (+12-2)
- (modified) bolt/lib/Core/BinaryContext.cpp (+86)
- (modified) bolt/lib/Core/BinaryFunction.cpp (+2)
- (modified) bolt/lib/Passes/IdenticalCodeFolding.cpp (+82-3)
- (modified) bolt/lib/Rewrite/BinaryPassManager.cpp (+8-7)
- (modified) bolt/lib/Rewrite/BoltDiff.cpp (+2-1)
- (modified) bolt/lib/Rewrite/RewriteInstance.cpp (+3-61)
- (added) bolt/test/X86/Inputs/helperSafeICF.s (+39)
- (added) bolt/test/X86/Inputs/helperSafeICFICPTest.s (+40)
- (added) bolt/test/X86/Inputs/mainSafeICFICPTest.s (+331)
- (added) bolt/test/X86/Inputs/mainSafeICFTest1.s (+345)
- (added) bolt/test/X86/Inputs/mainSafeICFTest2GlobalVarO0.s (+363)
- (added) bolt/test/X86/Inputs/mainSafeICFTest2GlobalVarO3.s (+293)
- (added) bolt/test/X86/Inputs/mainSafeICFTest3LocalVarO0.s (+359)
- (added) bolt/test/X86/Inputs/mainSafeICFTest3LocalVarO3.s (+286)
- (added) bolt/test/X86/icf-safe-icp.test (+20)
- (added) bolt/test/X86/icf-safe-test1-no-cfg.test (+21)
- (added) bolt/test/X86/icf-safe-test1-no-relocs.test (+16)
- (added) bolt/test/X86/icf-safe-test1.test (+21)
- (added) bolt/test/X86/icf-safe-test2GlobalVarO0.test (+21)
- (added) bolt/test/X86/icf-safe-test2GlobalVarO3.test (+21)
- (added) bolt/test/X86/icf-safe-test3LocalVarO0.test (+21)
- (added) bolt/test/X86/icf-safe-test3LocalVarO3.test (+21)
``````````diff
diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h
index 08ce892054874c..92889ffe162ae1 100644
--- a/bolt/include/bolt/Core/BinaryContext.h
+++ b/bolt/include/bolt/Core/BinaryContext.h
@@ -282,6 +282,12 @@ class BinaryContext {
std::unique_ptr<DWARFContext> DwCtx,
JournalingStreams Logger);
+ /// Returns addend of a relocation.
+ static int64_t getRelocationAddend(const ELFObjectFileBase *Obj,
+ const RelocationRef &Rel);
+ /// Returns symbol of a relocation.
+ static uint32_t getRelocationSymbol(const ELFObjectFileBase *Obj,
+ const RelocationRef &Rel);
/// Superset of compiler units that will contain overwritten code that needs
/// new debug info. In a few cases, functions may end up not being
/// overwritten, but it is okay to re-generate debug info for them.
@@ -1350,6 +1356,9 @@ class BinaryContext {
return Code.size();
}
+ /// Processes .text section to identify function references.
+ void processInstructionForFuncReferences(const MCInst &Inst);
+
/// Compute the native code size for a range of instructions.
/// Note: this can be imprecise wrt the final binary since happening prior to
/// relaxation, as well as wrt the original binary because of opcode
diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h
index 0b3682353f736e..5e1ddcc6bff9a2 100644
--- a/bolt/include/bolt/Core/BinaryFunction.h
+++ b/bolt/include/bolt/Core/BinaryFunction.h
@@ -428,6 +428,9 @@ class BinaryFunction {
/// Function order for streaming into the destination binary.
uint32_t Index{-1U};
+ /// Indicates if the function is safe to fold.
+ bool IsSafeToICF{true};
+
/// Get basic block index assuming it belongs to this function.
unsigned getIndex(const BinaryBasicBlock *BB) const {
assert(BB->getIndex() < BasicBlocks.size());
@@ -817,6 +820,12 @@ class BinaryFunction {
return nullptr;
}
+ /// Indicates if the function is safe to fold.
+ bool isSafeToICF() const { return IsSafeToICF; }
+
+ /// Sets the function is not safe to fold.
+ void setUnsetToICF() { IsSafeToICF = false; }
+
/// Returns the raw binary encoding of this function.
ErrorOr<ArrayRef<uint8_t>> getData() const;
diff --git a/bolt/include/bolt/Passes/IdenticalCodeFolding.h b/bolt/include/bolt/Passes/IdenticalCodeFolding.h
index b4206fa3607445..75d5f19ddfc7be 100644
--- a/bolt/include/bolt/Passes/IdenticalCodeFolding.h
+++ b/bolt/include/bolt/Passes/IdenticalCodeFolding.h
@@ -31,11 +31,21 @@ class IdenticalCodeFolding : public BinaryFunctionPass {
}
public:
- explicit IdenticalCodeFolding(const cl::opt<bool> &PrintPass)
- : BinaryFunctionPass(PrintPass) {}
+ explicit IdenticalCodeFolding(const cl::opt<bool> &PrintPass, bool IsSafeICF)
+ : BinaryFunctionPass(PrintPass), IsSafeICF(IsSafeICF) {}
const char *getName() const override { return "identical-code-folding"; }
Error runOnFunctions(BinaryContext &BC) override;
+
+private:
+ /// Create a skip list of functions that should not be folded.
+ Error createFoldSkipList(BinaryContext &BC);
+ /// Processes relocations in the .data section to identify function
+ /// references.
+ void processDataRelocations(BinaryContext &BC,
+ const SectionRef &SecRefRelData);
+
+ bool IsSafeICF;
};
} // namespace bolt
diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp
index f246750209d6c4..31352bed6fdab7 100644
--- a/bolt/lib/Core/BinaryContext.cpp
+++ b/bolt/lib/Core/BinaryContext.cpp
@@ -75,8 +75,63 @@ cl::opt<std::string> CompDirOverride(
"location, which is used with DW_AT_dwo_name to construct a path "
"to *.dwo files."),
cl::Hidden, cl::init(""), cl::cat(BoltCategory));
+
+cl::opt<bool> ICF("icf", cl::desc("fold functions with identical code"),
+ cl::cat(BoltOptCategory));
+
+cl::opt<bool> SafeICF("safe-icf",
+ cl::desc("Enable safe identical code folding"),
+ cl::cat(BoltOptCategory));
} // namespace opts
+namespace {
+template <typename ELFT>
+int64_t getRelocationAddend(const ELFObjectFile<ELFT> *Obj,
+ const RelocationRef &RelRef) {
+ using ELFShdrTy = typename ELFT::Shdr;
+ using Elf_Rela = typename ELFT::Rela;
+ int64_t Addend = 0;
+ const ELFFile<ELFT> &EF = Obj->getELFFile();
+ DataRefImpl Rel = RelRef.getRawDataRefImpl();
+ const ELFShdrTy *RelocationSection = cantFail(EF.getSection(Rel.d.a));
+ switch (RelocationSection->sh_type) {
+ default:
+ llvm_unreachable("unexpected relocation section type");
+ case ELF::SHT_REL:
+ break;
+ case ELF::SHT_RELA: {
+ const Elf_Rela *RelA = Obj->getRela(Rel);
+ Addend = RelA->r_addend;
+ break;
+ }
+ }
+
+ return Addend;
+}
+
+template <typename ELFT>
+uint32_t getRelocationSymbol(const ELFObjectFile<ELFT> *Obj,
+ const RelocationRef &RelRef) {
+ using ELFShdrTy = typename ELFT::Shdr;
+ uint32_t Symbol = 0;
+ const ELFFile<ELFT> &EF = Obj->getELFFile();
+ DataRefImpl Rel = RelRef.getRawDataRefImpl();
+ const ELFShdrTy *RelocationSection = cantFail(EF.getSection(Rel.d.a));
+ switch (RelocationSection->sh_type) {
+ default:
+ llvm_unreachable("unexpected relocation section type");
+ case ELF::SHT_REL:
+ Symbol = Obj->getRel(Rel)->getSymbol(EF.isMips64EL());
+ break;
+ case ELF::SHT_RELA:
+ Symbol = Obj->getRela(Rel)->getSymbol(EF.isMips64EL());
+ break;
+ }
+
+ return Symbol;
+}
+} // anonymous namespace
+
namespace llvm {
namespace bolt {
@@ -156,6 +211,16 @@ BinaryContext::~BinaryContext() {
clearBinaryData();
}
+uint32_t BinaryContext::getRelocationSymbol(const ELFObjectFileBase *Obj,
+ const RelocationRef &Rel) {
+ return ::getRelocationSymbol(cast<ELF64LEObjectFile>(Obj), Rel);
+}
+
+int64_t BinaryContext::getRelocationAddend(const ELFObjectFileBase *Obj,
+ const RelocationRef &Rel) {
+ return ::getRelocationAddend(cast<ELF64LEObjectFile>(Obj), Rel);
+}
+
/// Create BinaryContext for a given architecture \p ArchName and
/// triple \p TripleName.
Expected<std::unique_ptr<BinaryContext>> BinaryContext::createBinaryContext(
@@ -1945,6 +2010,27 @@ static void printDebugInfo(raw_ostream &OS, const MCInst &Instruction,
OS << " discriminator:" << Row.Discriminator;
}
+static bool skipInstruction(const MCInst &Inst, const BinaryContext &BC) {
+ const bool IsX86 = BC.isX86();
+ return (BC.MIB->isPseudo(Inst) || BC.MIB->isUnconditionalBranch(Inst) ||
+ (IsX86 && BC.MIB->isConditionalBranch(Inst)) ||
+ BC.MIB->isCall(Inst) || BC.MIB->isBranch(Inst));
+}
+void BinaryContext::processInstructionForFuncReferences(const MCInst &Inst) {
+ if (!opts::SafeICF || skipInstruction(Inst, *this))
+ return;
+ for (const MCOperand &Op : MCPlus::primeOperands(Inst)) {
+ if (Op.isExpr()) {
+ const MCExpr &Expr = *Op.getExpr();
+ if (Expr.getKind() == MCExpr::SymbolRef) {
+ const MCSymbol &Symbol = cast<MCSymbolRefExpr>(Expr).getSymbol();
+ if (BinaryFunction *BF = getFunctionForSymbol(&Symbol))
+ BF->setUnsetToICF();
+ }
+ }
+ }
+}
+
void BinaryContext::printInstruction(raw_ostream &OS, const MCInst &Instruction,
uint64_t Offset,
const BinaryFunction *Function,
diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp
index c12217d549479b..07d386efb26ec5 100644
--- a/bolt/lib/Core/BinaryFunction.cpp
+++ b/bolt/lib/Core/BinaryFunction.cpp
@@ -1626,6 +1626,8 @@ bool BinaryFunction::scanExternalRefs() {
if (!BC.HasRelocations)
continue;
+ BC.processInstructionForFuncReferences(Instruction);
+
if (BranchTargetSymbol) {
BC.MIB->replaceBranchTarget(Instruction, BranchTargetSymbol,
Emitter.LocalCtx.get());
diff --git a/bolt/lib/Passes/IdenticalCodeFolding.cpp b/bolt/lib/Passes/IdenticalCodeFolding.cpp
index 38e080c9dd6213..f09482dc08c212 100644
--- a/bolt/lib/Passes/IdenticalCodeFolding.cpp
+++ b/bolt/lib/Passes/IdenticalCodeFolding.cpp
@@ -11,8 +11,10 @@
//===----------------------------------------------------------------------===//
#include "bolt/Passes/IdenticalCodeFolding.h"
+#include "bolt/Core/BinaryContext.h"
#include "bolt/Core/HashUtilities.h"
#include "bolt/Core/ParallelUtilities.h"
+#include "bolt/Rewrite/RewriteInstance.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ThreadPool.h"
@@ -31,6 +33,7 @@ using namespace bolt;
namespace opts {
extern cl::OptionCategory BoltOptCategory;
+extern cl::opt<unsigned> Verbosity;
static cl::opt<bool>
ICFUseDFS("icf-dfs", cl::desc("use DFS ordering when using -icf option"),
@@ -341,6 +344,75 @@ typedef std::unordered_map<BinaryFunction *, std::vector<BinaryFunction *>,
namespace llvm {
namespace bolt {
+void IdenticalCodeFolding::processDataRelocations(
+ BinaryContext &BC, const SectionRef &SecRefRelData) {
+ for (const RelocationRef &Rel : SecRefRelData.relocations()) {
+ symbol_iterator SymbolIter = Rel.getSymbol();
+ const ObjectFile *OwningObj = Rel.getObject();
+ assert(SymbolIter != OwningObj->symbol_end() &&
+ "relocation Symbol expected");
+ const SymbolRef &Symbol = *SymbolIter;
+ const uint64_t SymbolAddress = cantFail(Symbol.getAddress());
+ const ELFObjectFileBase *ELFObj = dyn_cast<ELFObjectFileBase>(OwningObj);
+ if (!ELFObj)
+ assert(false && "Only ELFObjectFileBase is supported");
+ const int64_t Addend = BinaryContext::getRelocationAddend(ELFObj, Rel);
+ BinaryFunction *BF = BC.getBinaryFunctionAtAddress(SymbolAddress + Addend);
+ if (!BF)
+ continue;
+ BF->setUnsetToICF();
+ }
+}
+
+Error IdenticalCodeFolding::createFoldSkipList(BinaryContext &BC) {
+ Error ErrorStatus = Error::success();
+ ErrorOr<BinarySection &> SecRelData = BC.getUniqueSectionByName(".rela.data");
+ if (!BC.HasRelocations)
+ ErrorStatus = joinErrors(
+ std::move(ErrorStatus),
+ createFatalBOLTError(Twine("BOLT-ERROR: Binary built without "
+ "relocations. Safe ICF is not supported")));
+ if (ErrorStatus)
+ return ErrorStatus;
+ if (SecRelData) {
+ SectionRef SecRefRelData = SecRelData->getSectionRef();
+ processDataRelocations(BC, SecRefRelData);
+ }
+
+ ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
+ if (BF.getState() == BinaryFunction::State::CFG) {
+ for (const BinaryBasicBlock *BB : BF.getLayout().blocks())
+ for (const MCInst &Inst : *BB)
+ BC.processInstructionForFuncReferences(Inst);
+ }
+ };
+ ParallelUtilities::PredicateTy SkipFunc =
+ [&](const BinaryFunction &BF) -> bool { return (bool)ErrorStatus; };
+ ParallelUtilities::runOnEachFunction(
+ BC, ParallelUtilities::SchedulingPolicy::SP_TRIVIAL, WorkFun, SkipFunc,
+ "markUnsafe", /*ForceSequential*/ false, 2);
+
+ LLVM_DEBUG({
+ std::vector<StringRef> Vect;
+ std::mutex PrintMutex;
+ ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
+ if (BF.isSafeToICF())
+ return;
+ std::lock_guard<std::mutex> Lock(PrintMutex);
+ Vect.push_back(BF.getOneName());
+ };
+ ParallelUtilities::PredicateTy SkipFunc =
+ [&](const BinaryFunction &BF) -> bool { return false; };
+ ParallelUtilities::runOnEachFunction(
+ BC, ParallelUtilities::SchedulingPolicy::SP_TRIVIAL, WorkFun, SkipFunc,
+ "markUnsafe", /*ForceSequential*/ false, 2);
+ llvm::sort(Vect);
+ for (const auto &FuncName : Vect)
+ dbgs() << "BOLT-DEBUG: skipping function " << FuncName << '\n';
+ });
+ return ErrorStatus;
+}
+
Error IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
const size_t OriginalFunctionCount = BC.getBinaryFunctions().size();
uint64_t NumFunctionsFolded = 0;
@@ -350,6 +422,9 @@ Error IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
std::atomic<uint64_t> NumFoldedLastIteration{0};
CongruentBucketsMap CongruentBuckets;
+ auto SkipFuncShared = [&](const BinaryFunction &BF) {
+ return !shouldOptimize(BF) || !BF.isSafeToICF();
+ };
// Hash all the functions
auto hashFunctions = [&]() {
NamedRegionTimer HashFunctionsTimer("hashing", "hashing", "ICF breakdown",
@@ -369,7 +444,7 @@ Error IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
};
ParallelUtilities::PredicateTy SkipFunc = [&](const BinaryFunction &BF) {
- return !shouldOptimize(BF);
+ return SkipFuncShared(BF);
};
ParallelUtilities::runOnEachFunction(
@@ -385,7 +460,7 @@ Error IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
"ICF breakdown", opts::TimeICF);
for (auto &BFI : BC.getBinaryFunctions()) {
BinaryFunction &BF = BFI.second;
- if (!this->shouldOptimize(BF))
+ if (SkipFuncShared(BF))
continue;
CongruentBuckets[&BF].emplace(&BF);
}
@@ -475,7 +550,11 @@ Error IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
LLVM_DEBUG(SinglePass.stopTimer());
};
-
+ if (IsSafeICF) {
+ if (Error Err = createFoldSkipList(BC)) {
+ return Err;
+ }
+ }
hashFunctions();
createCongruentBuckets();
diff --git a/bolt/lib/Rewrite/BinaryPassManager.cpp b/bolt/lib/Rewrite/BinaryPassManager.cpp
index b0906041833484..df612c0a8f2e51 100644
--- a/bolt/lib/Rewrite/BinaryPassManager.cpp
+++ b/bolt/lib/Rewrite/BinaryPassManager.cpp
@@ -54,6 +54,8 @@ extern cl::opt<bool> PrintDynoStats;
extern cl::opt<bool> DumpDotAll;
extern cl::opt<std::string> AsmDump;
extern cl::opt<bolt::PLTCall::OptType> PLT;
+extern cl::opt<bool> ICF;
+extern cl::opt<bool> SafeICF;
static cl::opt<bool>
DynoStatsAll("dyno-stats-all",
@@ -65,9 +67,6 @@ static cl::opt<bool>
cl::desc("eliminate unreachable code"), cl::init(true),
cl::cat(BoltOptCategory));
-cl::opt<bool> ICF("icf", cl::desc("fold functions with identical code"),
- cl::cat(BoltOptCategory));
-
static cl::opt<bool> JTFootprintReductionFlag(
"jt-footprint-reduction",
cl::desc("make jump tables size smaller at the cost of using more "
@@ -397,8 +396,9 @@ Error BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) {
Manager.registerPass(std::make_unique<StripRepRet>(NeverPrint),
opts::StripRepRet);
- Manager.registerPass(std::make_unique<IdenticalCodeFolding>(PrintICF),
- opts::ICF);
+ Manager.registerPass(
+ std::make_unique<IdenticalCodeFolding>(PrintICF, opts::SafeICF),
+ opts::ICF || opts::SafeICF);
Manager.registerPass(
std::make_unique<SpecializeMemcpy1>(NeverPrint, opts::SpecializeMemcpy1),
@@ -422,8 +422,9 @@ Error BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) {
Manager.registerPass(std::make_unique<Inliner>(PrintInline));
- Manager.registerPass(std::make_unique<IdenticalCodeFolding>(PrintICF),
- opts::ICF);
+ Manager.registerPass(
+ std::make_unique<IdenticalCodeFolding>(PrintICF, opts::SafeICF),
+ opts::ICF || opts::SafeICF);
Manager.registerPass(std::make_unique<PLTCall>(PrintPLT));
diff --git a/bolt/lib/Rewrite/BoltDiff.cpp b/bolt/lib/Rewrite/BoltDiff.cpp
index 74b5ca18abce42..1a8eb5cd2ce39d 100644
--- a/bolt/lib/Rewrite/BoltDiff.cpp
+++ b/bolt/lib/Rewrite/BoltDiff.cpp
@@ -29,6 +29,7 @@ namespace opts {
extern cl::OptionCategory BoltDiffCategory;
extern cl::opt<bool> NeverPrint;
extern cl::opt<bool> ICF;
+extern cl::opt<bool> SafeICF;
static cl::opt<bool> IgnoreLTOSuffix(
"ignore-lto-suffix",
@@ -698,7 +699,7 @@ void RewriteInstance::compare(RewriteInstance &RI2) {
// Pre-pass ICF
if (opts::ICF) {
- IdenticalCodeFolding ICF(opts::NeverPrint);
+ IdenticalCodeFolding ICF(opts::NeverPrint, opts::SafeICF);
outs() << "BOLT-DIFF: Starting ICF pass for binary 1";
BC->logBOLTErrorsAndQuitOnFatal(ICF.runOnFunctions(*BC));
outs() << "BOLT-DIFF: Starting ICF pass for binary 2";
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index a4c50cbc3e2bbf..70c9eeef3cdc57 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -2111,64 +2111,6 @@ void RewriteInstance::adjustCommandLineOptions() {
}
}
-namespace {
-template <typename ELFT>
-int64_t getRelocationAddend(const ELFObjectFile<ELFT> *Obj,
- const RelocationRef &RelRef) {
- using ELFShdrTy = typename ELFT::Shdr;
- using Elf_Rela = typename ELFT::Rela;
- int64_t Addend = 0;
- const ELFFile<ELFT> &EF = Obj->getELFFile();
- DataRefImpl Rel = RelRef.getRawDataRefImpl();
- const ELFShdrTy *RelocationSection = cantFail(EF.getSection(Rel.d.a));
- switch (RelocationSection->sh_type) {
- default:
- llvm_unreachable("unexpected relocation section type");
- case ELF::SHT_REL:
- break;
- case ELF::SHT_RELA: {
- const Elf_Rela *RelA = Obj->getRela(Rel);
- Addend = RelA->r_addend;
- break;
- }
- }
-
- return Addend;
-}
-
-int64_t getRelocationAddend(const ELFObjectFileBase *Obj,
- const RelocationRef &Rel) {
- return getRelocationAddend(cast<ELF64LEObjectFile>(Obj), Rel);
-}
-
-template <typename ELFT>
-uint32_t getRelocationSymbol(const ELFObjectFile<ELFT> *Obj,
- const RelocationRef &RelRef) {
- using ELFShdrTy = typename ELFT::Shdr;
- uint32_t Symbol = 0;
- const ELFFile<ELFT> &EF = Obj->getELFFile();
- DataRefImpl Rel = RelRef.getRawDataRefImpl();
- const ELFShdrTy *RelocationSection = cantFail(EF.getSection(Rel.d.a));
- switch (RelocationSection->sh_type) {
- default:
- llvm_unreachable("unexpected relocation section type");
- case ELF::SHT_REL:
- Symbol = Obj->getRel(Rel)->getSymbol(EF.isMips64EL());
- break;
- case ELF::SHT_RELA:
- Symbol = Obj->getRela(Rel)->getSymbol(EF.isMips64EL());
- break;
- }
-
- return Symbol;
-}
-
-uint32_t getRelocationSymbol(const ELFObjectFileBase *Obj,
- const RelocationRef &Rel) {
- return getRelocationSymbol(cast<ELF64LEObjectFile>(Obj), Rel);
-}
-} // anonymous namespace
-
bool RewriteInstance::analyzeRelocation(
const RelocationRef &Rel, uint64_t &RType, std::string &SymbolName,
bool &IsSectionRelocation, uint64_t &SymbolAddress, int64_t &Addend,
@@ -2196,7 +2138,7 @@ bool RewriteInstance::analyzeRelocation(
return true;
ExtractedValue = Relocation::extractValue(RType, *Value, Rel.getOffset());
- Addend = getRelocationAddend(InputFile, Rel);
+ Addend = BinaryContext::getRelocationAddend(InputFile, Rel);
const bool IsPCRelative = Relocation::isPCRelative(RType);
const uint64_t PCRelOffset = IsPCRelative && !IsAArch64 ? Rel.getOffset() : 0;
@@ -2396,7 +2338,7 @@ void RewriteInstance::readDynamicRelocations(const SectionRef &Section,
StringRef SymbolName = "<none>";
MCSymbol *Symbol = nullptr;
uint64_t SymbolAddress = 0;
- const uint64_t Addend = getRelocationAddend(InputFile, Rel);
+ const uint64_t Addend = BinaryContext::getRelocationAddend(InputFile, Rel);
symbol_iterator SymbolIter = Rel.getSymbol();
if (SymbolIter != InputFile->symbol_end()) {
@@ -2421,7 +2363,7 @@ void RewriteInstance::readDynamicRelocations(const SectionRef &Section,
IsJmpRelocation[RType] = true;
if (Symbol)
- SymbolIndex[Symbol] = getRelocationSymbol(InputFile, Rel);
+ SymbolIndex[Symbol] = BinaryContext::getRelocationSymbol(InputFile, Rel);
BC->addDynamicRelocation(Rel.getOffset(), Symbol, RType, Addend);
}
diff --git a/bolt/test/X86/Inputs/helperSafeICF.s b/bolt/test/X86/Inputs/helperSafeICF.s
new file mode 100644
index 00000000000000..8ab47324454cbc
--- /dev/null
+++ b/bolt/test/X86/Inputs/helperSafeICF.s
@@ -0,0 +1,39 @@
+# clang++ -c helper.cpp -o helper.o
+# int FooVar = 1;
+# int BarVar = 2;
+#
+# int fooGlobalFuncHelper(int a, int b) {
+# return 5;
+# }
+ .text
+ .file "helper.cpp"
+ .globl _Z19fooGlobalFuncHelperii # -- Begin function _Z1...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/116275
More information about the llvm-commits
mailing list