From 488da6a764bcc1329733b962e8377406c3055bb0 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel <52407375+fabianbs96@users.noreply.github.com> Date: Thu, 25 Apr 2024 19:20:50 +0200 Subject: [PATCH] Resolver Injection (#717) * Add ctor to LLVMBasedICFG that allows injecting a CG resolver * Low-hanging fruits in resolvers * Remove out-commented code + unnecessary includes * Make the docker push pipeline work again --- .../PhasarLLVM/ControlFlow/LLVMBasedICFG.h | 10 ++++ .../ControlFlow/Resolver/OTFResolver.h | 4 +- .../ControlFlow/Resolver/Resolver.h | 8 +-- lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp | 58 ++++++++++++------- .../ControlFlow/Resolver/OTFResolver.cpp | 6 +- .../ControlFlow/Resolver/RTAResolver.cpp | 5 +- .../ControlFlow/Resolver/Resolver.cpp | 6 +- utils/InstallAptDependencies.sh | 2 +- 8 files changed, 59 insertions(+), 40 deletions(-) diff --git a/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h b/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h index 12bc78493..92e964e14 100644 --- a/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h +++ b/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h @@ -42,6 +42,7 @@ namespace psr { class LLVMTypeHierarchy; class LLVMProjectIRDB; +class Resolver; class LLVMBasedICFG; template <> struct CFGTraits : CFGTraits {}; @@ -87,6 +88,11 @@ class LLVMBasedICFG : public LLVMBasedCFG, public ICFGBase { LLVMAliasInfoRef PT = nullptr, Soundness S = Soundness::Soundy, bool IncludeGlobals = true); + explicit LLVMBasedICFG(LLVMProjectIRDB *IRDB, Resolver &CGResolver, + llvm::ArrayRef EntryPoints = {}, + LLVMTypeHierarchy *TH = nullptr, + Soundness S = Soundness::Soundy, + bool IncludeGlobals = true); /// Creates an ICFG with an already given call-graph explicit LLVMBasedICFG(CallGraph CG, LLVMProjectIRDB *IRDB, @@ -157,6 +163,10 @@ class LLVMBasedICFG : public LLVMBasedCFG, public ICFGBase { [[nodiscard]] llvm::Function *buildCRuntimeGlobalCtorsDtorsModel( llvm::Module &M, llvm::ArrayRef UserEntryPoints); + void initialize(LLVMProjectIRDB *IRDB, Resolver &CGResolver, + llvm::ArrayRef EntryPoints, + LLVMTypeHierarchy *TH, Soundness S, bool IncludeGlobals); + // --- CallGraph CG; diff --git a/include/phasar/PhasarLLVM/ControlFlow/Resolver/OTFResolver.h b/include/phasar/PhasarLLVM/ControlFlow/Resolver/OTFResolver.h index 5755c5207..13c75d8f3 100644 --- a/include/phasar/PhasarLLVM/ControlFlow/Resolver/OTFResolver.h +++ b/include/phasar/PhasarLLVM/ControlFlow/Resolver/OTFResolver.h @@ -35,16 +35,14 @@ class Value; namespace psr { -class LLVMBasedICFG; class LLVMTypeHierarchy; class OTFResolver : public Resolver { protected: - LLVMBasedICFG &ICF; LLVMAliasInfoRef PT; public: - OTFResolver(LLVMProjectIRDB &IRDB, LLVMTypeHierarchy &TH, LLVMBasedICFG &ICF, + OTFResolver(LLVMProjectIRDB &IRDB, LLVMTypeHierarchy &TH, LLVMAliasInfoRef PT); ~OTFResolver() override = default; diff --git a/include/phasar/PhasarLLVM/ControlFlow/Resolver/Resolver.h b/include/phasar/PhasarLLVM/ControlFlow/Resolver/Resolver.h index 58671342f..73adbd37e 100644 --- a/include/phasar/PhasarLLVM/ControlFlow/Resolver/Resolver.h +++ b/include/phasar/PhasarLLVM/ControlFlow/Resolver/Resolver.h @@ -36,7 +36,6 @@ namespace psr { class LLVMProjectIRDB; class LLVMTypeHierarchy; enum class CallGraphAnalysisType; -class LLVMBasedICFG; class LLVMPointsToInfo; [[nodiscard]] std::optional @@ -83,9 +82,10 @@ class Resolver { [[nodiscard]] virtual std::string str() const = 0; - static std::unique_ptr - create(CallGraphAnalysisType Ty, LLVMProjectIRDB *IRDB, LLVMTypeHierarchy *TH, - LLVMBasedICFG *ICF = nullptr, LLVMAliasInfoRef PT = nullptr); + static std::unique_ptr create(CallGraphAnalysisType Ty, + LLVMProjectIRDB *IRDB, + LLVMTypeHierarchy *TH, + LLVMAliasInfoRef PT = nullptr); }; } // namespace psr diff --git a/lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp b/lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp index 87b2279f2..eadc987db 100644 --- a/lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp +++ b/lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp @@ -9,7 +9,6 @@ #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" -#include "phasar/Config/Configuration.h" #include "phasar/ControlFlow/CallGraph.h" #include "phasar/ControlFlow/CallGraphAnalysisType.h" #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h" @@ -24,27 +23,22 @@ #include "phasar/Utils/MaybeUniquePtr.h" #include "phasar/Utils/PAMMMacros.h" #include "phasar/Utils/Soundness.h" -#include "phasar/Utils/TypeTraits.h" -#include "phasar/Utils/Utilities.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instruction.h" #include "llvm/Support/ErrorHandling.h" -#include #include namespace psr { struct LLVMBasedICFG::Builder { LLVMProjectIRDB *IRDB = nullptr; - LLVMAliasInfoRef PT{}; LLVMTypeHierarchy *TH{}; + Resolver *Res = nullptr; CallGraphBuilder CGBuilder{}; - std::unique_ptr Res = nullptr; llvm::DenseSet VisitedFunctions{}; llvm::SmallVector UserEntryPoints{}; @@ -321,6 +315,28 @@ bool LLVMBasedICFG::Builder::constructDynamicCall(const llvm::Instruction *CS) { return NewTargetsFound; } +void LLVMBasedICFG::initialize(LLVMProjectIRDB *IRDB, Resolver &CGResolver, + llvm::ArrayRef EntryPoints, + LLVMTypeHierarchy *TH, Soundness S, + bool IncludeGlobals) { + Builder B{IRDB, this->TH.get(), &CGResolver}; + + B.initEntryPoints(EntryPoints); + B.initGlobalsAndWorkList(this, IncludeGlobals); + + PHASAR_LOG_LEVEL_CAT( + INFO, "LLVMBasedICFG", + "Starting ICFG construction " + << std::chrono::steady_clock::now().time_since_epoch().count()); + + this->CG = B.buildCallGraph(S); + + PHASAR_LOG_LEVEL_CAT( + INFO, "LLVMBasedICFG", + "Finished ICFG construction " + << std::chrono::steady_clock::now().time_since_epoch().count()); +} + LLVMBasedICFG::LLVMBasedICFG(LLVMProjectIRDB *IRDB, CallGraphAnalysisType CGType, llvm::ArrayRef EntryPoints, @@ -333,29 +349,29 @@ LLVMBasedICFG::LLVMBasedICFG(LLVMProjectIRDB *IRDB, this->TH = std::make_unique(*IRDB); } - Builder B{IRDB, PT, this->TH.get()}; LLVMAliasInfo PTOwn; if (!PT && CGType == CallGraphAnalysisType::OTF) { PTOwn = std::make_unique(IRDB); - B.PT = PTOwn.asRef(); + PT = PTOwn.asRef(); } - B.Res = Resolver::create(CGType, IRDB, this->TH.get(), this, B.PT); - B.initEntryPoints(EntryPoints); - B.initGlobalsAndWorkList(this, IncludeGlobals); + auto CGRes = Resolver::create(CGType, IRDB, this->TH.get(), PT); + initialize(IRDB, *CGRes, EntryPoints, TH, S, IncludeGlobals); +} - PHASAR_LOG_LEVEL_CAT( - INFO, "LLVMBasedICFG", - "Starting ICFG construction " - << std::chrono::steady_clock::now().time_since_epoch().count()); +LLVMBasedICFG::LLVMBasedICFG(LLVMProjectIRDB *IRDB, Resolver &CGResolver, + llvm::ArrayRef EntryPoints, + LLVMTypeHierarchy *TH, Soundness S, + bool IncludeGlobals) + : IRDB(IRDB), TH(TH) { + assert(IRDB != nullptr); - this->CG = B.buildCallGraph(S); + if (!TH) { + this->TH = std::make_unique(*IRDB); + } - PHASAR_LOG_LEVEL_CAT( - INFO, "LLVMBasedICFG", - "Finished ICFG construction " - << std::chrono::steady_clock::now().time_since_epoch().count()); + initialize(IRDB, CGResolver, EntryPoints, TH, S, IncludeGlobals); } LLVMBasedICFG::LLVMBasedICFG(CallGraph CG, LLVMProjectIRDB *IRDB, diff --git a/lib/PhasarLLVM/ControlFlow/Resolver/OTFResolver.cpp b/lib/PhasarLLVM/ControlFlow/Resolver/OTFResolver.cpp index 556f53d2b..261ea90ed 100644 --- a/lib/PhasarLLVM/ControlFlow/Resolver/OTFResolver.cpp +++ b/lib/PhasarLLVM/ControlFlow/Resolver/OTFResolver.cpp @@ -31,8 +31,8 @@ using namespace psr; OTFResolver::OTFResolver(LLVMProjectIRDB &IRDB, LLVMTypeHierarchy &TH, - LLVMBasedICFG &ICF, LLVMAliasInfoRef PT) - : Resolver(IRDB, TH), ICF(ICF), PT(PT) {} + LLVMAliasInfoRef PT) + : Resolver(IRDB, TH), PT(PT) {} void OTFResolver::preCall(const llvm::Instruction *Inst) {} @@ -55,7 +55,7 @@ void OTFResolver::handlePossibleTargets(const llvm::CallBase *CallSite, } // handle return value if (CalleeTarget->getReturnType()->isPointerTy()) { - for (const auto &ExitPoint : ICF.getExitPointsOf(CalleeTarget)) { + for (const auto &ExitPoint : psr::getAllExitPoints(CalleeTarget)) { // get the function's return value if (const auto *Ret = llvm::dyn_cast(ExitPoint)) { // introduce alias to the returned value diff --git a/lib/PhasarLLVM/ControlFlow/Resolver/RTAResolver.cpp b/lib/PhasarLLVM/ControlFlow/Resolver/RTAResolver.cpp index 2f0b883e1..817f9a209 100644 --- a/lib/PhasarLLVM/ControlFlow/Resolver/RTAResolver.cpp +++ b/lib/PhasarLLVM/ControlFlow/Resolver/RTAResolver.cpp @@ -99,8 +99,6 @@ void RTAResolver::resolveAllocatedStructTypes() { } llvm::DenseSet AllocatedStructTypes; - const llvm::StringSet<> MemAllocatingFunctions = {"_Znwm", "_Znam", "malloc", - "calloc", "realloc"}; for (const auto *Fun : IRDB.getAllFunctions()) { for (const auto &Inst : llvm::instructions(Fun)) { @@ -114,8 +112,7 @@ void RTAResolver::resolveAllocatedStructTypes() { // check if an instance of a user-defined type is allocated on the // heap - if (!MemAllocatingFunctions.contains( - CallSite->getCalledFunction()->getName())) { + if (!isHeapAllocatingFunction(CallSite->getCalledFunction())) { continue; } /// TODO: Does this iteration over the users make sense? diff --git a/lib/PhasarLLVM/ControlFlow/Resolver/Resolver.cpp b/lib/PhasarLLVM/ControlFlow/Resolver/Resolver.cpp index fbb08a957..0beb6d174 100644 --- a/lib/PhasarLLVM/ControlFlow/Resolver/Resolver.cpp +++ b/lib/PhasarLLVM/ControlFlow/Resolver/Resolver.cpp @@ -145,7 +145,7 @@ auto Resolver::resolveFunctionPointer(const llvm::CallBase *CallSite) FunctionSetTy CalleeTargets; for (const auto *F : IRDB.getAllFunctions()) { - if (isConsistentCall(CallSite, F)) { + if (F->hasAddressTaken() && isConsistentCall(CallSite, F)) { CalleeTargets.insert(F); } } @@ -158,7 +158,6 @@ void Resolver::otherInst(const llvm::Instruction *Inst) {} std::unique_ptr Resolver::create(CallGraphAnalysisType Ty, LLVMProjectIRDB *IRDB, LLVMTypeHierarchy *TH, - LLVMBasedICFG *ICF, LLVMAliasInfoRef PT) { assert(IRDB != nullptr); @@ -179,9 +178,8 @@ std::unique_ptr Resolver::create(CallGraphAnalysisType Ty, "The VTA callgraph algorithm is not implemented yet"); case CallGraphAnalysisType::OTF: assert(TH != nullptr); - assert(ICF != nullptr); assert(PT); - return std::make_unique(*IRDB, *TH, *ICF, PT); + return std::make_unique(*IRDB, *TH, PT); case CallGraphAnalysisType::Invalid: llvm::report_fatal_error("Invalid callgraph algorithm specified"); } diff --git a/utils/InstallAptDependencies.sh b/utils/InstallAptDependencies.sh index f8d4f3a0a..8dba455bc 100755 --- a/utils/InstallAptDependencies.sh +++ b/utils/InstallAptDependencies.sh @@ -3,4 +3,4 @@ set -e sudo apt-get update sudo apt-get install git -y -sudo apt-get install zlib1g-dev python3 g++ ninja-build cmake -y +sudo apt-get install zlib1g-dev python3 python3-pip g++ ninja-build cmake -y