1414#include " bolt/Core/HashUtilities.h"
1515#include " bolt/Core/ParallelUtilities.h"
1616#include " llvm/ADT/BitVector.h"
17+ #include " llvm/ADT/DenseSet.h"
18+ #include " llvm/ADT/DenseMap.h"
1719#include " llvm/ADT/SmallVector.h"
1820#include " llvm/Support/CommandLine.h"
1921#include " llvm/Support/ThreadPool.h"
@@ -354,94 +356,51 @@ typedef std::unordered_map<BinaryFunction *, std::vector<BinaryFunction *>,
354356
355357namespace llvm {
356358namespace bolt {
357- // / Scans symbol table and creates a bit vector of memory addresses of vtables.
358- void IdenticalCodeFolding::processSymbolTable (const BinaryContext &BC) {
359- for (auto &[Address, Data] : BC.getBinaryData ()) {
359+ // / Scans symbol table and creates a bit vector of memory addresses of vtable symbols.
360+ void IdenticalCodeFolding::initVTableReferences (const BinaryContext &BC) {
361+ initVtable ();
362+ for (const auto &[Address, Data] : BC.getBinaryData ()) {
360363 // Filter out all symbols that are not vtables.
361364 if (!Data->getName ().starts_with (" _ZTV" ))
362365 continue ;
363- for (uint64_t I = Address / 8 , End = I + (Data->getSize () / 8 ); I < End;
364- ++I)
365- VtableBitVector.set (I);
366+ for (uint64_t I = Address, End = I + Data->getSize (); I < End; I += 8 )
367+ setAddressUsedInVTable (I);
366368 }
367369}
368- Error IdenticalCodeFolding::processDataRelocations (
369- BinaryContext &BC, const SectionRef &SecRefRelData,
370- const bool HasAddressTaken) {
371- for (const RelocationRef &Rel : SecRefRelData.relocations ()) {
372- if (isInVTable (Rel.getOffset ()))
370+ void IdenticalCodeFolding::analyzeDataRelocations (BinaryContext &BC) {
371+ initVTableReferences (BC);
372+ for (const BinarySection &Sec : BC.sections ()) {
373+ if (!Sec.hasSectionRef () || !Sec.isData ())
373374 continue ;
374- symbol_iterator SymbolIter = Rel.getSymbol ();
375- const ObjectFile *OwningObj = Rel.getObject ();
376- assert (SymbolIter != OwningObj->symbol_end () &&
377- " relocation Symbol expected" );
378- const SymbolRef &Symbol = *SymbolIter;
379- const uint64_t SymbolAddress = cantFail (Symbol.getAddress ());
380- const ELFObjectFileBase *ELFObj = dyn_cast<ELFObjectFileBase>(OwningObj);
381- if (!ELFObj)
382- return createFatalBOLTError (
383- Twine (" BOLT-ERROR: Only ELFObjectFileBase is supported" ));
384- const int64_t Addend = getRelocationAddend (ELFObj, Rel);
385- BinaryFunction *BF = BC.getBinaryFunctionAtAddress (SymbolAddress + Addend);
386- if (!BF)
387- continue ;
388- BF->setHasAddressTaken (HasAddressTaken);
375+ for (const auto &Rel : Sec.relocations ()) {
376+ const uint64_t RelAddr = Rel.Offset + Sec.getAddress ();
377+ if (isAddressInVTable (RelAddr))
378+ continue ;
379+ BinaryFunction *BF = BC.getFunctionForSymbol (Rel.Symbol );
380+ if (!BF)
381+ continue ;
382+ BF->setHasAddressTaken (true );
383+ }
384+ for (const auto &Rel : Sec.dynamicRelocations ()) {
385+ const uint64_t RelAddr = Rel.Offset + Sec.getAddress ();
386+ if (isAddressInVTable (RelAddr))
387+ continue ;
388+ BinaryFunction *BF =
389+ BC.getBinaryFunctionContainingAddress (Rel.Addend ,
390+ /* CheckPastEnd*/ false ,
391+ /* UseMaxSize*/ true );
392+ if (!BF)
393+ continue ;
394+ BF->setHasAddressTaken (true );
395+ }
389396 }
390- return Error::success ();
391397}
392-
393- Error IdenticalCodeFolding::markFunctionsUnsafeToFold (BinaryContext &BC) {
394- if (!BC.isX86 ())
395- BC.outs () << " BOLT-WARNING: safe ICF is only supported for x86\n " ;
396- processSymbolTable (BC);
397- for (const auto &Sec : BC.sections ()) {
398- if (!Sec.hasSectionRef () || !Sec.isRela ())
399- continue ;
400- const SectionRef &SecRef = Sec.getSectionRef ();
401- section_iterator RelocatedSecIter = cantFail (SecRef.getRelocatedSection ());
402- assert (RelocatedSecIter != SecRef.getObject ()->section_end () &&
403- " Relocation section exists without corresponding relocated section" );
404- const SectionRef &RelocatedSecRef = *RelocatedSecIter;
405- const StringRef RelocatedSectionName = cantFail (RelocatedSecRef.getName ());
406- const bool SkipRelocs =
407- StringSwitch<bool >(RelocatedSectionName)
408- .Cases (" .plt" , " .got.plt" , " .eh_frame" , " .gcc_except_table" ,
409- " .fini_array" , " .init_array" , true )
410- .Default (false );
411- if (!RelocatedSecRef.isData () || SkipRelocs)
412- continue ;
413-
414- Error ErrorStatus =
415- processDataRelocations (BC, SecRef, /* HasAddressTaken */ true );
416- if (ErrorStatus)
417- return ErrorStatus;
418- }
419- ErrorOr<BinarySection &> SecRelDataIA =
420- BC.getUniqueSectionByName (" .rela.init_array" );
421- if (SecRelDataIA) {
422- const SectionRef SecRefRelData = SecRelDataIA->getSectionRef ();
423- Error ErrorStatus =
424- processDataRelocations (BC, SecRefRelData, /* !HasAddressTaken */ false );
425- if (ErrorStatus)
426- return ErrorStatus;
427- }
428- ErrorOr<BinarySection &> SecRelDataFIA =
429- BC.getUniqueSectionByName (" .rela.fini_array" );
430- if (SecRelDataFIA) {
431- const SectionRef SecRefRelData = SecRelDataFIA->getSectionRef ();
432- Error ErrorStatus =
433- processDataRelocations (BC, SecRefRelData, /* !HasAddressTaken */ false );
434- if (ErrorStatus)
435- return ErrorStatus;
436- }
437-
398+ void IdenticalCodeFolding::analyzeFunctions (BinaryContext &BC) {
438399 ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
439- for (const BinaryBasicBlock *BB : BF.getLayout ().blocks ()) {
440- for (const MCInst &Inst : *BB) {
400+ for (const BinaryBasicBlock *BB : BF.getLayout ().blocks ())
401+ for (const MCInst &Inst : *BB)
441402 if (!(BC.MIB ->isCall (Inst) || BC.MIB ->isBranch (Inst)))
442403 BF.processInstructionForFuncReferences (BC, Inst);
443- }
444- }
445404 };
446405 ParallelUtilities::PredicateTy SkipFunc =
447406 [&](const BinaryFunction &BF) -> bool {
@@ -459,7 +418,15 @@ Error IdenticalCodeFolding::markFunctionsUnsafeToFold(BinaryContext &BC) {
459418 << ' \n ' ;
460419 }
461420 });
462- return Error::success ();
421+ }
422+ void IdenticalCodeFolding::markFunctionsUnsafeToFold (BinaryContext &BC) {
423+ NamedRegionTimer MarkFunctionsUnsafeToFoldTimer (
424+ " markFunctionsUnsafeToFold" , " markFunctionsUnsafeToFold" , " ICF breakdown" ,
425+ " ICF breakdown" , opts::TimeICF);
426+ if (!BC.isX86 ())
427+ BC.outs () << " BOLT-WARNING: safe ICF is only supported for x86\n " ;
428+ analyzeDataRelocations (BC);
429+ analyzeFunctions (BC);
463430}
464431
465432Error IdenticalCodeFolding::runOnFunctions (BinaryContext &BC) {
@@ -597,8 +564,7 @@ Error IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) {
597564 LLVM_DEBUG (SinglePass.stopTimer ());
598565 };
599566 if (opts::ICF == ICFLevel::Safe)
600- if (Error Err = markFunctionsUnsafeToFold (BC))
601- return Err;
567+ markFunctionsUnsafeToFold (BC);
602568 hashFunctions ();
603569 createCongruentBuckets ();
604570
0 commit comments