diff --git a/include/phasar/PhasarLLVM/ControlFlow/Resolver/Resolver.h b/include/phasar/PhasarLLVM/ControlFlow/Resolver/Resolver.h index 156543886..7742ce262 100644 --- a/include/phasar/PhasarLLVM/ControlFlow/Resolver/Resolver.h +++ b/include/phasar/PhasarLLVM/ControlFlow/Resolver/Resolver.h @@ -38,14 +38,29 @@ class LLVMVFTableProvider; class LLVMTypeHierarchy; enum class CallGraphAnalysisType; +/// Assuming that `CallSite` is a virtual call through a vtable, retrieves the +/// index in the vtable of the virtual function called. [[nodiscard]] std::optional getVFTIndex(const llvm::CallBase *CallSite); +/// Assuming that `CallSite` is a vall to a non-static member function, +/// retrieves the type of the receiver. Returns nullptr, if the receiver-type +/// could not be extracted [[nodiscard]] const llvm::StructType * getReceiverType(const llvm::CallBase *CallSite); +/// Assuming that `CallSite` is a virtual call, where `Idx` is retrieved through +/// `getVFTIndex()` and `T` through `getReceiverType()` +[[nodiscard]] const llvm::Function * +getNonPureVirtualVFTEntry(const llvm::StructType *T, unsigned Idx, + const llvm::CallBase *CallSite, + const psr::LLVMVFTableProvider &VTP); + [[nodiscard]] std::string getReceiverTypeName(const llvm::CallBase *CallSite); +/// Checks whether the signature of `DestFun` matches the required withature of +/// `CallSite`, such that `DestFun` qualifies as callee-candidate, if `CallSite` +/// is an indirect/virtual call. [[nodiscard]] bool isConsistentCall(const llvm::CallBase *CallSite, const llvm::Function *DestFun); @@ -59,7 +74,12 @@ class Resolver { const llvm::Function * getNonPureVirtualVFTEntry(const llvm::StructType *T, unsigned Idx, - const llvm::CallBase *CallSite); + const llvm::CallBase *CallSite) { + if (!VTP) { + return nullptr; + } + return psr::getNonPureVirtualVFTEntry(T, Idx, CallSite, *VTP); + } public: using FunctionSetTy = llvm::SmallDenseSet; diff --git a/lib/PhasarLLVM/ControlFlow/Resolver/Resolver.cpp b/lib/PhasarLLVM/ControlFlow/Resolver/Resolver.cpp index e55edefce..06d5f3b6e 100644 --- a/lib/PhasarLLVM/ControlFlow/Resolver/Resolver.cpp +++ b/lib/PhasarLLVM/ControlFlow/Resolver/Resolver.cpp @@ -86,6 +86,22 @@ const llvm::StructType *psr::getReceiverType(const llvm::CallBase *CallSite) { return nullptr; } +const llvm::Function * +psr::getNonPureVirtualVFTEntry(const llvm::StructType *T, unsigned Idx, + const llvm::CallBase *CallSite, + const LLVMVFTableProvider &VTP) { + + if (const auto *VT = VTP.getVFTableOrNull(T)) { + const auto *Target = VT->getFunction(Idx); + if (Target && Target->getName() != LLVMTypeHierarchy::PureVirtualCallName && + isConsistentCall(CallSite, Target)) { + return Target; + } + } + + return nullptr; +} + std::string psr::getReceiverTypeName(const llvm::CallBase *CallSite) { const auto *RT = getReceiverType(CallSite); if (RT) { @@ -134,22 +150,6 @@ Resolver::Resolver(const LLVMProjectIRDB *IRDB, const LLVMVFTableProvider *VTP) assert(VTP != nullptr); } -const llvm::Function * -Resolver::getNonPureVirtualVFTEntry(const llvm::StructType *T, unsigned Idx, - const llvm::CallBase *CallSite) { - if (!VTP) { - return nullptr; - } - if (const auto *VT = VTP->getVFTableOrNull(T)) { - const auto *Target = VT->getFunction(Idx); - if (Target && Target->getName() != LLVMTypeHierarchy::PureVirtualCallName && - isConsistentCall(CallSite, Target)) { - return Target; - } - } - return nullptr; -} - void Resolver::preCall(const llvm::Instruction *Inst) {} void Resolver::handlePossibleTargets(const llvm::CallBase *CallSite,