Skip to content

Commit

Permalink
Merge branch 'development' into f-OpaquePointers
Browse files Browse the repository at this point in the history
  • Loading branch information
fabianbs96 authored Sep 21, 2023
2 parents 6febeae + 06da95b commit 3a9d930
Show file tree
Hide file tree
Showing 26 changed files with 530 additions and 170 deletions.
9 changes: 1 addition & 8 deletions include/phasar/ControlFlow/ICFGBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,7 @@ template <typename Derived> class ICFGBase {
n_t>);
return self().getReturnSitesOfCallAtImpl(Inst);
}
/// Returns an iterable range of all global initializer functions
[[nodiscard]] decltype(auto)
getGlobalInitializers(ByConstRef<f_t> Fun) const {
static_assert(
is_iterable_over_v<decltype(self().getGlobalInitializersImpl(Fun)),
f_t>);
return self().getGlobalInitializersImpl(Fun);
}

/// Prints the underlying call-graph as DOT to the given output-stream
void print(llvm::raw_ostream &OS = llvm::outs()) const {
self().printImpl(OS);
Expand Down
13 changes: 13 additions & 0 deletions include/phasar/DataFlow/IfdsIde/FlowFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,19 @@ class FlowFunctions
virtual FlowFunctionPtrType getRetFlowFunction(n_t CallSite, f_t CalleeFun,
n_t ExitInst, n_t RetSite) = 0;

// Performs any side-effects of a return-flow-function
//
// In case of unbalanced returns (if the option `followReturnsPastSeeds` is
// activated in the IfdsIdeSolverConfig), we will eventually reach a function
// that is not called from other functions. Still, we may want to apply a
// return-flow-function -- just for its side-effects, such as registering a
// taint
virtual void applyUnbalancedRetFlowFunctionSideEffects(f_t CalleeFun,
n_t ExitInst,
d_t Source) {
// By default, do nothing
}

//
// Describes the data-flows alongsite a CallSite.
//
Expand Down
33 changes: 33 additions & 0 deletions include/phasar/DataFlow/IfdsIde/Solver/FlowEdgeFunctionCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "phasar/Utils/EquivalenceClassMap.h"
#include "phasar/Utils/Logger.h"
#include "phasar/Utils/PAMMMacros.h"
#include "phasar/Utils/Utilities.h"

#include "llvm/ADT/DenseMap.h"

Expand Down Expand Up @@ -185,6 +186,8 @@ class FlowEdgeFunctionCache {
operator=(FlowEdgeFunctionCache &&FEFC) noexcept = default;

FlowFunctionPtrType getNormalFlowFunction(n_t Curr, n_t Succ) {
assertNotNull(Curr);
assertNotNull(Succ);
PAMM_GET_INSTANCE;
IF_LOG_ENABLED(
PHASAR_LOG_LEVEL(DEBUG, "Normal flow function factory call");
Expand Down Expand Up @@ -217,6 +220,8 @@ class FlowEdgeFunctionCache {
}

FlowFunctionPtrType getCallFlowFunction(n_t CallSite, f_t DestFun) {
assertNotNull(CallSite);
assertNotNull(DestFun);
PAMM_GET_INSTANCE;
IF_LOG_ENABLED(
PHASAR_LOG_LEVEL(DEBUG, "Call flow function factory call");
Expand All @@ -241,6 +246,10 @@ class FlowEdgeFunctionCache {

FlowFunctionPtrType getRetFlowFunction(n_t CallSite, f_t CalleeFun,
n_t ExitInst, n_t RetSite) {
assertNotNull(CallSite);
assertNotNull(CalleeFun);
assertNotNull(ExitInst);
assertNotNull(RetSite);
PAMM_GET_INSTANCE;
IF_LOG_ENABLED(
PHASAR_LOG_LEVEL(DEBUG, "Return flow function factory call");
Expand Down Expand Up @@ -270,6 +279,9 @@ class FlowEdgeFunctionCache {

FlowFunctionPtrType getCallToRetFlowFunction(n_t CallSite, n_t RetSite,
llvm::ArrayRef<f_t> Callees) {
assertNotNull(CallSite);
assertNotNull(RetSite);
assertAllNotNull(Callees);
PAMM_GET_INSTANCE;
IF_LOG_ENABLED(
PHASAR_LOG_LEVEL(DEBUG, "Call-to-Return flow function factory call");
Expand Down Expand Up @@ -300,6 +312,8 @@ class FlowEdgeFunctionCache {
}

FlowFunctionPtrType getSummaryFlowFunction(n_t CallSite, f_t DestFun) {
assertNotNull(CallSite);
assertNotNull(DestFun);
// PAMM_GET_INSTANCE;
// INC_COUNTER("Summary-FF Construction", 1, Full);
IF_LOG_ENABLED(
Expand All @@ -313,6 +327,9 @@ class FlowEdgeFunctionCache {

EdgeFunction<l_t> getNormalEdgeFunction(n_t Curr, d_t CurrNode, n_t Succ,
d_t SuccNode) {
assertNotNull(Curr);
assertNotNull(Succ);

PAMM_GET_INSTANCE;
IF_LOG_ENABLED(
PHASAR_LOG_LEVEL(DEBUG, "Normal edge function factory call");
Expand Down Expand Up @@ -357,6 +374,10 @@ class FlowEdgeFunctionCache {

EdgeFunction<l_t> getCallEdgeFunction(n_t CallSite, d_t SrcNode,
f_t DestinationFunction, d_t DestNode) {

assertNotNull(CallSite);
assertNotNull(DestinationFunction);

PAMM_GET_INSTANCE;
IF_LOG_ENABLED(
PHASAR_LOG_LEVEL(DEBUG, "Call edge function factory call");
Expand Down Expand Up @@ -387,6 +408,11 @@ class FlowEdgeFunctionCache {
EdgeFunction<l_t> getReturnEdgeFunction(n_t CallSite, f_t CalleeFunction,
n_t ExitInst, d_t ExitNode,
n_t RetSite, d_t RetNode) {
assertNotNull(CallSite);
assertNotNull(CalleeFunction);
assertNotNull(ExitInst);
assertNotNull(RetSite);

PAMM_GET_INSTANCE;
IF_LOG_ENABLED(
PHASAR_LOG_LEVEL(DEBUG, "Return edge function factory call");
Expand Down Expand Up @@ -419,6 +445,10 @@ class FlowEdgeFunctionCache {
EdgeFunction<l_t> getCallToRetEdgeFunction(n_t CallSite, d_t CallNode,
n_t RetSite, d_t RetSiteNode,
llvm::ArrayRef<f_t> Callees) {
assertNotNull(CallSite);
assertNotNull(RetSite);
assertAllNotNull(Callees);

PAMM_GET_INSTANCE;
IF_LOG_ENABLED(
PHASAR_LOG_LEVEL(DEBUG, "Call-to-Return edge function factory call");
Expand Down Expand Up @@ -472,6 +502,9 @@ class FlowEdgeFunctionCache {

EdgeFunction<l_t> getSummaryEdgeFunction(n_t CallSite, d_t CallNode,
n_t RetSite, d_t RetSiteNode) {
assertNotNull(CallSite);
assertNotNull(RetSite);

PAMM_GET_INSTANCE;
IF_LOG_ENABLED(
PHASAR_LOG_LEVEL(DEBUG, "Summary edge function factory call");
Expand Down
12 changes: 5 additions & 7 deletions include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -886,8 +886,9 @@ class IDESolver
// conditionally generated values should only
// be propagated into callers that have an incoming edge for this
// condition
if (SolverConfig.followReturnsPastSeeds() && Inc.empty() &&
IDEProblem.isZeroValue(d1)) {
/// TODO: Add a check for "d1 is seed in functionOf(n)"
if (SolverConfig.followReturnsPastSeeds() && Inc.empty() /*&&
IDEProblem.isZeroValue(d1)*/) {
const auto &Callers = ICF->getCallersOf(FunctionThatNeedsSummary);
for (n_t Caller : Callers) {
for (n_t RetSiteC : ICF->getReturnSitesOfCallAt(Caller)) {
Expand Down Expand Up @@ -922,11 +923,8 @@ class IDESolver
// the flow function has a side effect such as registering a taint;
// instead we thus call the return flow function will a null caller
if (Callers.empty()) {
FlowFunctionPtrType RetFunction =
CachedFlowEdgeFunctions.getRetFlowFunction(
nullptr, FunctionThatNeedsSummary, n, nullptr);
INC_COUNTER("FF Queries", 1, Full);
RetFunction->computeTargets(d2);
IDEProblem.applyUnbalancedRetFlowFunctionSideEffects(
FunctionThatNeedsSummary, n, d2);
}
}
}
Expand Down
10 changes: 9 additions & 1 deletion include/phasar/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,14 @@
namespace psr {

class LLVMBasedICFG;
class LLVMBasedBackwardICFG;
template <typename N, typename F> class CallGraph;

template <>
struct CFGTraits<LLVMBasedBackwardICFG> : CFGTraits<LLVMBasedBackwardCFG> {};

class LLVMBasedBackwardICFG : public LLVMBasedBackwardCFG,
public ICFGBase<LLVMBasedBackwardCFG> {
public ICFGBase<LLVMBasedBackwardICFG> {
friend ICFGBase;

class LLVMBackwardRet {
Expand Down Expand Up @@ -60,6 +65,7 @@ class LLVMBasedBackwardICFG : public LLVMBasedBackwardCFG,
getReturnSitesOfCallAtImpl(n_t Inst) const;
void printImpl(llvm::raw_ostream &OS) const;
[[nodiscard]] nlohmann::json getAsJsonImpl() const;
[[nodiscard]] const CallGraph<n_t, f_t> &getCallGraphImpl() const noexcept;

llvm::LLVMContext BackwardRetsCtx;
llvm::DenseMap<const llvm::Function *, LLVMBackwardRet> BackwardRets;
Expand All @@ -68,6 +74,8 @@ class LLVMBasedBackwardICFG : public LLVMBasedBackwardCFG,

LLVMBasedICFG *ForwardICFG{};
};

extern template class ICFGBase<LLVMBasedBackwardICFG>;
} // namespace psr

#endif
14 changes: 14 additions & 0 deletions include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ class LLVMBasedICFG : public LLVMBasedCFG, public ICFGBase<LLVMBasedICFG> {
static constexpr llvm::StringLiteral GlobalCRuntimeModelName =
"__psrCRuntimeGlobalCtorsModel";

static constexpr llvm::StringLiteral GlobalCRuntimeDtorModelName =
"__psrCRuntimeGlobalDtorsModel";

static constexpr llvm::StringLiteral GlobalCRuntimeDtorsCallerName =
"__psrGlobalDtorsCaller";

static constexpr llvm::StringLiteral GlobalCRuntimeUserEntrySelectorName =
"__psrCRuntimeUserEntrySelector";

/// Constructs the ICFG based on the given IRDB and the entry-points using a
/// fixpoint iteration. This may take a long time.
///
Expand Down Expand Up @@ -119,6 +128,9 @@ class LLVMBasedICFG : public LLVMBasedCFG, public ICFGBase<LLVMBasedICFG> {
/// Gets the underlying IRDB
[[nodiscard]] LLVMProjectIRDB *getIRDB() const noexcept { return IRDB; }

/// Returns true, if a function was generated by phasar.
[[nodiscard]] static bool isPhasarGenerated(const llvm::Function &) noexcept;

using CFGBase::print;
using ICFGBase::print;

Expand Down Expand Up @@ -150,6 +162,8 @@ class LLVMBasedICFG : public LLVMBasedCFG, public ICFGBase<LLVMBasedICFG> {
LLVMProjectIRDB *IRDB = nullptr;
MaybeUniquePtr<LLVMTypeHierarchy, true> TH;
};

extern template class ICFGBase<LLVMBasedICFG>;
} // namespace psr

#endif
21 changes: 15 additions & 6 deletions include/phasar/PhasarLLVM/DB/LLVMProjectIRDB.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,23 @@ class LLVMProjectIRDB : public ProjectIRDBBase<LLVMProjectIRDB> {
friend ProjectIRDBBase;

public:
/// Reads and parses the given LLVM IR file and owns the resulting IR Module
/// Reads and parses the given LLVM IR file and owns the resulting IR Module.
/// If an error occurs, an error message is written to stderr and subsequent
/// calls to isValid() return false.
explicit LLVMProjectIRDB(const llvm::Twine &IRFileName);
/// Initializes the new ProjectIRDB with the given IR Module _without_ taking
/// ownership. The module is not being preprocessed.
/// ownership. The module is optionally being preprocessed.
///
/// CAUTION: Do not manage the same LLVM Module with multiple LLVMProjectIRDB
/// instances at the same time! This will confuse the ModulesToSlotTracker
explicit LLVMProjectIRDB(llvm::Module *Mod);
explicit LLVMProjectIRDB(llvm::Module *Mod, bool DoPreprocessing = true);
/// Initializes the new ProjectIRDB with the given IR Module and takes
/// ownership of it
/// ownership of it. The module is optionally being preprocessed.
explicit LLVMProjectIRDB(std::unique_ptr<llvm::Module> Mod,
bool DoPreprocessing = true);
/// Parses the given LLVM IR file and owns the resulting IR Module
/// Parses the given LLVM IR file and owns the resulting IR Module.
/// If an error occurs, an error message is written to stderr and subsequent
/// calls to isValid() return false.
explicit LLVMProjectIRDB(llvm::MemoryBufferRef Buf);

LLVMProjectIRDB(const LLVMProjectIRDB &) = delete;
Expand All @@ -64,6 +68,9 @@ class LLVMProjectIRDB : public ProjectIRDBBase<LLVMProjectIRDB> {
[[nodiscard]] static std::unique_ptr<llvm::Module>
getParsedIRModuleOrNull(const llvm::Twine &IRFileName,
llvm::LLVMContext &Ctx) noexcept;
[[nodiscard]] static std::unique_ptr<llvm::Module>
getParsedIRModuleOrNull(llvm::MemoryBufferRef IRFileContent,
llvm::LLVMContext &Ctx) noexcept;

/// Also use the const overload
using ProjectIRDBBase::getFunction;
Expand All @@ -81,7 +88,7 @@ class LLVMProjectIRDB : public ProjectIRDBBase<LLVMProjectIRDB> {
/// Also use the const overload
using ProjectIRDBBase::getModule;
/// Non-const overload
[[nodiscard]] llvm::Module *getModule() { return Mod.get(); }
[[nodiscard]] llvm::Module *getModule() noexcept { return Mod.get(); }

/// Similar to getInstruction(size_t), but is also able to return global
/// variables by id
Expand All @@ -96,6 +103,8 @@ class LLVMProjectIRDB : public ProjectIRDBBase<LLVMProjectIRDB> {
/// called twice for the same function. Use with care!
void insertFunction(llvm::Function *F, bool DoPreprocessing = true);

explicit operator bool() const noexcept { return isValid(); }

private:
[[nodiscard]] m_t getModuleImpl() const noexcept { return Mod.get(); }
[[nodiscard]] bool debugInfoAvailableImpl() const;
Expand Down
46 changes: 25 additions & 21 deletions include/phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMFlowFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,8 @@ mapFactsToCallee(const llvm::CallBase *CallSite, const llvm::Function *DestFun,
///
/// Propagates the return value back to the call-site and based on the
/// PropagateParameter predicate propagates back parameters holding as dataflow
/// facts.
/// facts. The resulting out-set of dataflow facts can be post-processed if
/// necessary.
///
/// Let a call-site cs: r = fun(..., ax, ...) a function prototype fun(...,
/// px, ...) and an exit statement exit: return rv.
Expand All @@ -252,30 +253,30 @@ mapFactsToCallee(const llvm::CallBase *CallSite, const llvm::Function *DestFun,
/// f(x) = ({ax} if PropagateParameter(ax, x) else {}) union ({r} if
/// PropagateRet(rv, x) else {}).
///
template <typename D = const llvm::Value *, typename Container = std::set<D>,
typename FnParam = std::equal_to<D>,
typename FnRet = std::equal_to<D>,
typename DCtor = DefaultConstruct<D>,
typename = std::enable_if_t<
std::is_invocable_r_v<bool, FnParam, const llvm::Value *, D> &&
std::is_invocable_r_v<bool, FnRet, const llvm::Value *, D>>>
FlowFunctionPtrType<D, Container>
mapFactsToCaller(const llvm::CallBase *CallSite,
const llvm::Instruction *ExitInst,
FnParam &&PropagateParameter = {}, FnRet &&PropagateRet = {},
DCtor &&FactConstructor = {}, bool PropagateGlobals = true,
bool PropagateZeroToCaller = true) {
template <
typename D = const llvm::Value *, typename Container = std::set<D>,
typename FnParam = std::equal_to<D>, typename FnRet = std::equal_to<D>,
typename DCtor = DefaultConstruct<D>, typename PostProcessFn = IgnoreArgs,
typename = std::enable_if_t<
std::is_invocable_r_v<bool, FnParam, const llvm::Value *, D> &&
std::is_invocable_r_v<bool, FnRet, const llvm::Value *, D>>>
FlowFunctionPtrType<D, Container> mapFactsToCaller(
const llvm::CallBase *CallSite, const llvm::Instruction *ExitInst,
FnParam &&PropagateParameter = {}, FnRet &&PropagateRet = {},
DCtor &&FactConstructor = {}, bool PropagateGlobals = true,
bool PropagateZeroToCaller = true, PostProcessFn &&PostProcess = {}) {

struct Mapper : public FlowFunction<D, Container> {
Mapper(const llvm::CallBase *CallSite, const llvm::Instruction *ExitInst,
bool PropagateGlobals, FnParam &&PropagateParameter,
FnRet &&PropagateRet, DCtor &&FactConstructor,
bool PropagateZeroToCaller)
bool PropagateZeroToCaller, PostProcessFn &&PostProcess)
: CSAndPropGlob(CallSite, PropagateGlobals),
ExitInstAndPropZero(ExitInst, PropagateZeroToCaller),
PropArg(std::forward<FnParam>(PropagateParameter)),
PropRet(std::forward<FnRet>(PropagateRet)),
FactConstructor(std::forward<DCtor>(FactConstructor)) {}
FactConstructor(std::forward<DCtor>(FactConstructor)),
PostProcess(std::forward<PostProcessFn>(PostProcess)) {}

Container computeTargets(D Source) override {
Container Res;
Expand Down Expand Up @@ -337,6 +338,8 @@ mapFactsToCaller(const llvm::CallBase *CallSite,
}
}

std::invoke(PostProcess, Res);

return Res;
}

Expand All @@ -346,13 +349,14 @@ mapFactsToCaller(const llvm::CallBase *CallSite,
[[no_unique_address]] std::decay_t<FnParam> PropArg;
[[no_unique_address]] std::decay_t<FnRet> PropRet;
[[no_unique_address]] std::decay_t<DCtor> FactConstructor;
[[no_unique_address]] std::decay_t<PostProcessFn> PostProcess;
};

return std::make_shared<Mapper>(CallSite, ExitInst, PropagateGlobals,
std::forward<FnParam>(PropagateParameter),
std::forward<FnRet>(PropagateRet),
std::forward<DCtor>(FactConstructor),
PropagateZeroToCaller);
return std::make_shared<Mapper>(
CallSite, ExitInst, PropagateGlobals,
std::forward<FnParam>(PropagateParameter),
std::forward<FnRet>(PropagateRet), std::forward<DCtor>(FactConstructor),
PropagateZeroToCaller, std::forward<PostProcessFn>(PostProcess));
}

//===----------------------------------------------------------------------===//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,9 @@ class IDEInstInteractionAnalysisT
n_t /* RetSite */) override {
// Map return value back to the caller. If pointer parameters hold at the
// end of a callee function generate all of those in the caller context.

if (CallSite == nullptr) {
return this->killAllFlows();
}
auto MapFactsToCallerFF =
mapFactsToCaller<d_t>(llvm::cast<llvm::CallBase>(CallSite), ExitInst,
{}, [](const llvm::Value *RetVal, d_t Src) {
Expand Down
Loading

0 comments on commit 3a9d930

Please sign in to comment.