From 0c7b9794530151054959fbb5df2ea20911e487b0 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel <52407375+fabianbs96@users.noreply.github.com> Date: Thu, 8 Aug 2024 17:30:35 +0200 Subject: [PATCH 1/2] EF SemiRing in Problem (#722) * Tie the EF semi-ring to the problem + integrate into solver * Incorporate combine and extend into IIA * minor * Fix IIA * apply review comment --- .../DataFlow/IfdsIde/EdgeFunctionUtils.h | 37 ++++ .../DataFlow/IfdsIde/IDETabulationProblem.h | 2 + .../DataFlow/IfdsIde/Solver/IDESolver.h | 21 ++- .../Problems/IDEInstInteractionAnalysis.h | 173 ++++++++---------- include/phasar/Utils/BitVectorSet.h | 10 +- include/phasar/Utils/SemiRing.h | 34 ++++ 6 files changed, 163 insertions(+), 114 deletions(-) create mode 100644 include/phasar/Utils/SemiRing.h diff --git a/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h b/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h index de9db609a..bfbc9d233 100644 --- a/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h +++ b/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h @@ -132,6 +132,23 @@ defaultComposeOrNull(EdgeFunctionRef This, return nullptr; } +template +EdgeFunction +defaultComposeOrNull(const EdgeFunction &This, + const EdgeFunction &SecondFunction) noexcept { + if (llvm::isa>(SecondFunction)) { + return This; + } + if (SecondFunction.isConstant() || llvm::isa>(This) || + llvm::isa>(This)) { + return SecondFunction; + } + if (llvm::isa>(This)) { + return This; + } + return nullptr; +} + template struct ConstantEdgeFunction { using l_t = L; using JLattice = JoinLatticeTraits; @@ -409,6 +426,26 @@ EdgeFunction defaultJoinOrNull(EdgeFunctionRef This, return nullptr; } +template +EdgeFunction defaultJoinOrNull(const EdgeFunction &This, + const EdgeFunction &OtherFunction) { + if (llvm::isa>(OtherFunction) || llvm::isa>(This)) { + return OtherFunction; + } + if (llvm::isa>(OtherFunction) || OtherFunction == This || + llvm::isa>(This)) { + return This; + } + if (llvm::isa>(OtherFunction)) { + if constexpr (N > 0) { + return JoinEdgeFunction::create(This, OtherFunction); + } else if constexpr (HasJoinLatticeTraits) { + return AllBottom{}; + } + } + return nullptr; +} + template EdgeFunction EdgeIdentity::join(EdgeFunctionRef This, const EdgeFunction &OtherFunction) { diff --git a/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h b/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h index 4cdc3610f..5d3dc71f6 100644 --- a/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h +++ b/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h @@ -22,6 +22,7 @@ #include "phasar/Utils/JoinLattice.h" #include "phasar/Utils/NullAnalysisPrinter.h" #include "phasar/Utils/Printer.h" +#include "phasar/Utils/SemiRing.h" #include "phasar/Utils/Soundness.h" #include "llvm/ADT/StringRef.h" @@ -62,6 +63,7 @@ template , public EdgeFunctions, public JoinLattice, + public SemiRing, public AllTopFnProvider { public: using ProblemAnalysisDomain = AnalysisDomainTy; diff --git a/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h b/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h index 3274ced1a..9f10b10e2 100644 --- a/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h +++ b/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h @@ -406,7 +406,7 @@ class IDESolver PHASAR_LOG_LEVEL(DEBUG, "Compose: " << SumEdgFnE << " * " << f << '\n'); WorkList.emplace_back(PathEdge(d1, ReturnSiteN, std::move(d3)), - f.composeWith(SumEdgFnE)); + IDEProblem.extend(f, SumEdgFnE)); } } } else { @@ -498,15 +498,15 @@ class IDESolver << f4); PHASAR_LOG_LEVEL(DEBUG, " (return * calleeSummary * call)"); - EdgeFunction fPrime = - f4.composeWith(fCalleeSummary).composeWith(f5); + EdgeFunction fPrime = IDEProblem.extend( + IDEProblem.extend(f4, fCalleeSummary), f5); PHASAR_LOG_LEVEL(DEBUG, " = " << fPrime); d_t d5_restoredCtx = restoreContextOnReturnedFact(n, d2, d5); // propagte the effects of the entire call PHASAR_LOG_LEVEL(DEBUG, "Compose: " << fPrime << " * " << f); WorkList.emplace_back( PathEdge(d1, RetSiteN, std::move(d5_restoredCtx)), - f.composeWith(fPrime)); + IDEProblem.extend(f, fPrime)); } } } @@ -538,7 +538,7 @@ class IDESolver .push_back(EdgeFnE); } INC_COUNTER("EF Queries", 1, Full); - auto fPrime = f.composeWith(EdgeFnE); + auto fPrime = IDEProblem.extend(f, EdgeFnE); PHASAR_LOG_LEVEL(DEBUG, "Compose: " << EdgeFnE << " * " << f << " = " << fPrime); WorkList.emplace_back(PathEdge(d1, ReturnSiteN, std::move(d3)), @@ -570,7 +570,7 @@ class IDESolver EdgeFunction g = CachedFlowEdgeFunctions.getNormalEdgeFunction(n, d2, nPrime, d3); PHASAR_LOG_LEVEL(DEBUG, "Queried Normal Edge Function: " << g); - EdgeFunction fPrime = f.composeWith(g); + EdgeFunction fPrime = IDEProblem.extend(f, g); if (SolverConfig.emitESG()) { IntermediateEdgeFunctions[std::make_tuple(n, d2, nPrime, d3)] .push_back(g); @@ -950,7 +950,8 @@ class IDESolver PHASAR_LOG_LEVEL(DEBUG, "Compose: " << f5 << " * " << f << " * " << f4); PHASAR_LOG_LEVEL(DEBUG, " (return * function * call)"); - EdgeFunction fPrime = f4.composeWith(f).composeWith(f5); + EdgeFunction fPrime = + IDEProblem.extend(IDEProblem.extend(f4, f), f5); PHASAR_LOG_LEVEL(DEBUG, " = " << fPrime); // for each jump function coming into the call, propagate to // return site using the composed function @@ -965,7 +966,7 @@ class IDESolver PHASAR_LOG_LEVEL(DEBUG, "Compose: " << fPrime << " * " << f3); WorkList.emplace_back(PathEdge(std::move(d3), RetSiteC, std::move(d5_restoredCtx)), - f3.composeWith(fPrime)); + IDEProblem.extend(f3, fPrime)); } } } @@ -1004,7 +1005,7 @@ class IDESolver } INC_COUNTER("EF Queries", 1, Full); PHASAR_LOG_LEVEL(DEBUG, "Compose: " << f5 << " * " << f); - propagteUnbalancedReturnFlow(RetSiteC, d5, f.composeWith(f5), + propagteUnbalancedReturnFlow(RetSiteC, d5, IDEProblem.extend(f, f5), Caller); // register for value processing (2nd IDE phase) UnbalancedRetSites.insert(RetSiteC); @@ -1153,7 +1154,7 @@ class IDESolver // was found return AllTop; }(); - EdgeFunction fPrime = JumpFnE.joinWith(f); + EdgeFunction fPrime = IDEProblem.combine(JumpFnE, f); bool NewFunction = fPrime != JumpFnE; IF_LOG_LEVEL_ENABLED(DEBUG, { diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h index 40d1dff44..b4410d1f9 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h @@ -11,6 +11,7 @@ #define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_PROBLEMS_IDEINSTINTERACTIONANALYSIS_H #include "phasar/DataFlow/IfdsIde/DefaultEdgeFunctionSingletonCache.h" +#include "phasar/DataFlow/IfdsIde/EdgeFunction.h" #include "phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h" #include "phasar/DataFlow/IfdsIde/FlowFunctions.h" #include "phasar/DataFlow/IfdsIde/IDETabulationProblem.h" @@ -949,59 +950,15 @@ class IDEInstInteractionAnalysisT l_t computeTarget(ByConstRef /* Src */) const { return Replacement; } - static EdgeFunction compose(EdgeFunctionRef This, - const EdgeFunction SecondFunction) { - - if (auto Default = defaultComposeOrNull(This, SecondFunction)) { - return Default; - } - - auto Cache = This.getCacheOrNull(); - assert(Cache != nullptr && "We expect a cache, because " - "IIAAKillOrReplaceEF is too large for SOO"); - - if (auto *AD = llvm::dyn_cast(SecondFunction)) { - auto Union = - IDEInstInteractionAnalysisT::joinImpl(This->Replacement, AD->Data); - return Cache->createEdgeFunction(std::move(Union)); - } - - if (auto *KR = llvm::dyn_cast(SecondFunction)) { - return SecondFunction; - } - llvm::report_fatal_error( - "found unexpected edge function in 'IIAAKillOrReplaceEF'"); + static EdgeFunction + compose(EdgeFunctionRef /*This*/, + const EdgeFunction /*SecondFunction*/) { + llvm::report_fatal_error("Implemented in 'extend'"); } - static EdgeFunction join(EdgeFunctionRef This, - const EdgeFunction &OtherFunction) { - /// XXX: Here, we underapproximate joins with EdgeIdentity - if (llvm::isa>(OtherFunction)) { - return This; - } - - if (auto Default = defaultJoinOrNull(This, OtherFunction)) { - return Default; - } - - auto Cache = This.getCacheOrNull(); - assert(Cache != nullptr && "We expect a cache, because " - "IIAAKillOrReplaceEF is too large for SOO"); - - if (auto *AD = llvm::dyn_cast(OtherFunction)) { - auto ADCache = OtherFunction.template getCacheOrNull(); - assert(ADCache); - auto Union = - IDEInstInteractionAnalysisT::joinImpl(This->Replacement, AD->Data); - return ADCache->createEdgeFunction(std::move(Union)); - } - if (auto *KR = llvm::dyn_cast(OtherFunction)) { - auto Union = IDEInstInteractionAnalysisT::joinImpl(This->Replacement, - KR->Replacement); - return Cache->createEdgeFunction(std::move(Union)); - } - llvm::report_fatal_error( - "found unexpected edge function in 'IIAAKillOrReplaceEF'"); + static EdgeFunction join(EdgeFunctionRef /*This*/, + const EdgeFunction & /*OtherFunction*/) { + llvm::report_fatal_error("Implemented in 'combine'"); } bool operator==(const IIAAKillOrReplaceEF &Other) const noexcept { @@ -1044,55 +1001,15 @@ class IDEInstInteractionAnalysisT return IDEInstInteractionAnalysisT::joinImpl(Src, Data); } - static EdgeFunction compose(EdgeFunctionRef This, - const EdgeFunction &SecondFunction) { - if (auto Default = defaultComposeOrNull(This, SecondFunction)) { - return Default; - } - - auto Cache = This.getCacheOrNull(); - assert(Cache != nullptr && "We expect a cache, because " - "IIAAAddLabelsEF is too large for SOO"); - - if (auto *AD = llvm::dyn_cast(SecondFunction)) { - auto Union = - IDEInstInteractionAnalysisT::joinImpl(This->Data, AD->Data); - return Cache->createEdgeFunction(std::move(Union)); - } - if (auto *KR = llvm::dyn_cast(SecondFunction)) { - return SecondFunction; - } - llvm::report_fatal_error( - "found unexpected edge function in 'IIAAAddLabelsEF'"); + static EdgeFunction + compose(EdgeFunctionRef /*This*/, + const EdgeFunction & /*SecondFunction*/) { + llvm::report_fatal_error("Implemented in 'extend'"); } - static EdgeFunction join(EdgeFunctionRef This, - const EdgeFunction &OtherFunction) { - /// XXX: Here, we underapproximate joins with EdgeIdentity - if (llvm::isa>(OtherFunction)) { - return This; - } - - if (auto Default = defaultJoinOrNull(This, OtherFunction)) { - return Default; - } - - auto Cache = This.getCacheOrNull(); - assert(Cache != nullptr && "We expect a cache, because " - "IIAAAddLabelsEF is too large for SOO"); - - if (auto *AD = llvm::dyn_cast(OtherFunction)) { - auto Union = - IDEInstInteractionAnalysisT::joinImpl(This->Data, AD->Data); - return Cache->createEdgeFunction(std::move(Union)); - } - if (auto *KR = llvm::dyn_cast(OtherFunction)) { - auto Union = - IDEInstInteractionAnalysisT::joinImpl(This->Data, KR->Replacement); - return Cache->createEdgeFunction(std::move(Union)); - } - llvm::report_fatal_error( - "found unexpected edge function in 'IIAAAddLabelsEF'"); + static EdgeFunction join(EdgeFunctionRef /*This*/, + const EdgeFunction & /*OtherFunction*/) { + llvm::report_fatal_error("Implemented in 'combine'"); } bool operator==(const IIAAAddLabelsEF &Other) const noexcept { @@ -1112,6 +1029,64 @@ class IDEInstInteractionAnalysisT } }; + const auto &getData(const EdgeFunction &EF) { + if (const auto *AddLabels = llvm::dyn_cast(EF)) { + return AddLabels->Data; + } + if (const auto *KillOrReplace = llvm::dyn_cast(EF)) { + return KillOrReplace->Replacement; + } + llvm::report_fatal_error( + "found unexpected first edge function in 'getData': " + + llvm::Twine(to_string(EF))); + } + + EdgeFunction extend(const EdgeFunction &FirstFunction, + const EdgeFunction &SecondFunction) override { + if (auto Default = defaultComposeOrNull(FirstFunction, SecondFunction)) { + return Default; + } + + const auto &ThisData = getData(FirstFunction); + + if (auto *AD = llvm::dyn_cast(SecondFunction)) { + auto Union = IDEInstInteractionAnalysisT::joinImpl(ThisData, AD->Data); + return llvm::isa(FirstFunction) + ? IIAAAddLabelsEFCache.createEdgeFunction(std::move(Union)) + : IIAAKillOrReplaceEFCache.createEdgeFunction( + std::move(Union)); + } + + llvm::report_fatal_error( + "found unexpected second edge function in 'extend'"); + } + + EdgeFunction combine(const EdgeFunction &FirstFunction, + const EdgeFunction &OtherFunction) override { + /// XXX: Here, we underapproximate joins with EdgeIdentity + if (llvm::isa>(FirstFunction)) { + return OtherFunction; + } + if (llvm::isa>(OtherFunction) && + !llvm::isa>(FirstFunction)) { + return FirstFunction; + } + + if (auto Default = defaultJoinOrNull(FirstFunction, OtherFunction)) { + return Default; + } + + const auto &ThisData = getData(FirstFunction); + const auto &OtherData = getData(OtherFunction); + auto Union = IDEInstInteractionAnalysisT::joinImpl(ThisData, OtherData); + + if (llvm::isa(FirstFunction) && + llvm::isa(OtherFunction)) { + return IIAAKillOrReplaceEFCache.createEdgeFunction(std::move(Union)); + } + return IIAAAddLabelsEFCache.createEdgeFunction(std::move(Union)); + } + // Provide functionalities for printing things and emitting text reports. static void stripBottomResults(std::unordered_map &Res) { @@ -1173,7 +1148,7 @@ class IDEInstInteractionAnalysisT } if (const auto *H = llvm::dyn_cast(I)) { if (!H->isIndirectCall() && H->getCalledFunction() && - this->ICF->isHeapAllocatingFunction(H->getCalledFunction())) { + psr::isHeapAllocatingFunction(H->getCalledFunction())) { Variables.insert(H); } } diff --git a/include/phasar/Utils/BitVectorSet.h b/include/phasar/Utils/BitVectorSet.h index 418d90e60..308245c82 100644 --- a/include/phasar/Utils/BitVectorSet.h +++ b/include/phasar/Utils/BitVectorSet.h @@ -177,11 +177,11 @@ template class BitVectorSet { } [[nodiscard]] BitVectorSet setUnion(const BitVectorSet &Other) const { - size_t MaxSize = std::max(Bits.size(), Other.Bits.size()); - BitVectorSet Res; - Res.Bits.reserve(MaxSize); - Res.Bits = Bits; - Res.Bits |= Other.Bits; + const bool ThisSetIsSmaller = Bits.size() < Other.Bits.size(); + BitVectorSet Res = ThisSetIsSmaller ? Other : *this; + const BitVectorSet &Smaller = ThisSetIsSmaller ? *this : Other; + + Res.Bits |= Smaller.Bits; return Res; } diff --git a/include/phasar/Utils/SemiRing.h b/include/phasar/Utils/SemiRing.h new file mode 100644 index 000000000..e4999d329 --- /dev/null +++ b/include/phasar/Utils/SemiRing.h @@ -0,0 +1,34 @@ +/****************************************************************************** + * Copyright (c) 2024 Fabian Schiebel. + * All rights reserved. This program and the accompanying materials are made + * available under the terms of LICENSE.txt. + * + * Contributors: + * Fabian Schiebel and others + *****************************************************************************/ + +#ifndef PHASAR_UTILS_SEMIRING_H +#define PHASAR_UTILS_SEMIRING_H + +#include "phasar/DataFlow/IfdsIde/EdgeFunction.h" + +namespace psr { +template class SemiRing { +public: + using l_t = typename AnalysisDomainTy::l_t; + + virtual ~SemiRing() = default; + + virtual EdgeFunction extend(const EdgeFunction &L, + const EdgeFunction &R) { + return L.composeWith(R); + } + + virtual EdgeFunction combine(const EdgeFunction &L, + const EdgeFunction &R) { + return L.joinWith(R); + } +}; +} // namespace psr + +#endif // PHASAR_UTILS_SEMIRING_H From 6e0f6f62288ff4130f2e7ac105ef6655991f1dce Mon Sep 17 00:00:00 2001 From: Fabian Schiebel <52407375+fabianbs96@users.noreply.github.com> Date: Fri, 9 Aug 2024 18:48:08 +0200 Subject: [PATCH 2/2] Move AnalysisController (#724) * Move Controller to phasar-cli * Simplify AnalysisController * Prevent invalid enum values to be accepted by the CLI parser * Add proper error messages in case of fatal failure * simplify linking * breaking changes * remove controller component from Config.cmake.in --- BreakingChanges.md | 1 + Config.cmake.in | 1 - include/phasar.h | 1 - include/phasar/Controller.h | 16 ---- include/phasar/Utils/InitPhasar.h | 22 +++++ lib/CMakeLists.txt | 2 - lib/Controller/CMakeLists.txt | 27 ------ lib/Utils/InitPhasar.cpp | 45 +++++++++ tools/phasar-cli/CMakeLists.txt | 32 +------ .../Controller/AnalysisController.cpp | 64 ++++--------- .../Controller/AnalysisController.h | 41 +++------ .../AnalysisControllerEmitterOptions.h | 0 .../Controller/AnalysisControllerInternal.h | 61 +++++------- .../AnalysisControllerInternalIDE.h | 9 +- .../AnalysisControllerInternalMono.h | 7 +- .../AnalysisControllerXIDECSTDIOTS.cpp | 2 +- .../Controller/AnalysisControllerXIDEIIA.cpp | 2 +- .../AnalysisControllerXIDELinearConst.cpp | 3 +- .../AnalysisControllerXIDEOpenSSLTS.cpp | 2 +- .../AnalysisControllerXIDESolverTest.cpp | 3 +- .../AnalysisControllerXIDEXTaint.cpp | 2 +- .../AnalysisControllerXIFDSConst.cpp | 2 +- .../AnalysisControllerXIFDSSolverTest.cpp | 3 +- .../AnalysisControllerXIFDSTaint.cpp | 2 +- .../AnalysisControllerXIFDSType.cpp | 2 +- .../AnalysisControllerXIFDSUninit.cpp | 3 +- ...AnalysisControllerXInterMonoSolverTest.cpp | 3 +- .../AnalysisControllerXInterMonoTaint.cpp | 3 +- ...alysisControllerXIntraMonoFullConstant.cpp | 3 +- ...AnalysisControllerXIntraMonoSolverTest.cpp | 3 +- tools/phasar-cli/Controller/CMakeLists.txt | 3 + tools/phasar-cli/phasar-cli.cpp | 92 ++++++++++++------- 32 files changed, 211 insertions(+), 251 deletions(-) delete mode 100644 include/phasar/Controller.h create mode 100644 include/phasar/Utils/InitPhasar.h delete mode 100644 lib/Controller/CMakeLists.txt create mode 100644 lib/Utils/InitPhasar.cpp rename {lib => tools/phasar-cli}/Controller/AnalysisController.cpp (76%) rename {include/phasar => tools/phasar-cli}/Controller/AnalysisController.h (51%) rename {include/phasar => tools/phasar-cli}/Controller/AnalysisControllerEmitterOptions.h (100%) rename {lib => tools/phasar-cli}/Controller/AnalysisControllerInternal.h (65%) rename {lib => tools/phasar-cli}/Controller/AnalysisControllerInternalIDE.h (82%) rename {lib => tools/phasar-cli}/Controller/AnalysisControllerInternalMono.h (83%) rename {lib => tools/phasar-cli}/Controller/AnalysisControllerXIDECSTDIOTS.cpp (90%) rename {lib => tools/phasar-cli}/Controller/AnalysisControllerXIDEIIA.cpp (95%) rename {lib => tools/phasar-cli}/Controller/AnalysisControllerXIDELinearConst.cpp (87%) rename {lib => tools/phasar-cli}/Controller/AnalysisControllerXIDEOpenSSLTS.cpp (90%) rename {lib => tools/phasar-cli}/Controller/AnalysisControllerXIDESolverTest.cpp (86%) rename {lib => tools/phasar-cli}/Controller/AnalysisControllerXIDEXTaint.cpp (89%) rename {lib => tools/phasar-cli}/Controller/AnalysisControllerXIFDSConst.cpp (88%) rename {lib => tools/phasar-cli}/Controller/AnalysisControllerXIFDSSolverTest.cpp (86%) rename {lib => tools/phasar-cli}/Controller/AnalysisControllerXIFDSTaint.cpp (88%) rename {lib => tools/phasar-cli}/Controller/AnalysisControllerXIFDSType.cpp (88%) rename {lib => tools/phasar-cli}/Controller/AnalysisControllerXIFDSUninit.cpp (87%) rename {lib => tools/phasar-cli}/Controller/AnalysisControllerXInterMonoSolverTest.cpp (86%) rename {lib => tools/phasar-cli}/Controller/AnalysisControllerXInterMonoTaint.cpp (88%) rename {lib => tools/phasar-cli}/Controller/AnalysisControllerXIntraMonoFullConstant.cpp (87%) rename {lib => tools/phasar-cli}/Controller/AnalysisControllerXIntraMonoSolverTest.cpp (86%) create mode 100644 tools/phasar-cli/Controller/CMakeLists.txt diff --git a/BreakingChanges.md b/BreakingChanges.md index 597f54a97..7792543ab 100644 --- a/BreakingChanges.md +++ b/BreakingChanges.md @@ -2,6 +2,7 @@ ## development HEAD +- Removed the phasar-library `phasar_controller`. It is now part of the tool `phasar-cli`. - The API of the `TypeHierarchy` interface (and thus the `LLVMTypeHierarchy` and `DIBasedTypeHierarchy` as well) has changed: - No handling of the super-type relation (only sub-types) - No VTable handling anymore -- has been out-sourced into `LLVMVFTableProvider` diff --git a/Config.cmake.in b/Config.cmake.in index f160d869b..adc1a9a6c 100644 --- a/Config.cmake.in +++ b/Config.cmake.in @@ -37,7 +37,6 @@ set(PHASAR_COMPONENTS llvm llvm_ifdside analysis_strategy - controller ) list(REMOVE_DUPLICATES phasar_FIND_COMPONENTS) diff --git a/include/phasar.h b/include/phasar.h index 0444cf20f..397cbba0f 100644 --- a/include/phasar.h +++ b/include/phasar.h @@ -13,7 +13,6 @@ #include "phasar/AnalysisStrategy.h" #include "phasar/Config.h" #include "phasar/ControlFlow.h" -#include "phasar/Controller.h" #include "phasar/DB.h" #include "phasar/DataFlow.h" #include "phasar/Domain.h" diff --git a/include/phasar/Controller.h b/include/phasar/Controller.h deleted file mode 100644 index 92d4c2202..000000000 --- a/include/phasar/Controller.h +++ /dev/null @@ -1,16 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2023 Fabian Schiebel. - * All rights reserved. This program and the accompanying materials are made - * available under the terms of LICENSE.txt. - * - * Contributors: - * Fabian Schiebel and others - *****************************************************************************/ - -#ifndef PHASAR_CONTROLLER_H -#define PHASAR_CONTROLLER_H - -#include "phasar/Controller/AnalysisController.h" -#include "phasar/Controller/AnalysisControllerEmitterOptions.h" - -#endif // PHASAR_CONTROLLER_H diff --git a/include/phasar/Utils/InitPhasar.h b/include/phasar/Utils/InitPhasar.h new file mode 100644 index 000000000..57bb37e5a --- /dev/null +++ b/include/phasar/Utils/InitPhasar.h @@ -0,0 +1,22 @@ +/****************************************************************************** + * Copyright (c) 2024 Fabian Schiebel. + * All rights reserved. This program and the accompanying materials are made + * available under the terms of LICENSE.txt. + * + * Contributors: + * Fabian Schiebel and others + *****************************************************************************/ + +#include "llvm/Support/InitLLVM.h" + +namespace psr { +class InitPhasar : llvm::InitLLVM { +public: + InitPhasar(int &Argc, const char **&Argv) noexcept; + InitPhasar(int &Argc, char **&Argv) noexcept + : InitPhasar(Argc, (const char **&)Argv) {} +}; +} // namespace psr + +#define PSR_INITIALIZER(argc, argv) \ + const ::psr::InitPhasar PsrInitializerVar((argc), (argv)) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 3c2ab5fdf..86d4c048d 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -4,7 +4,6 @@ add_subdirectory(PhasarPass) add_subdirectory(DB) add_subdirectory(Config) add_subdirectory(Utils) -add_subdirectory(Controller) add_subdirectory(Pointer) add_subdirectory(ControlFlow) if(BUILD_PHASAR_CLANG) @@ -36,7 +35,6 @@ set(PHASAR_LINK_LIBS phasar_llvm phasar_llvm_ifdside phasar_analysis_strategy - phasar_controller ) if(SQLite3_FOUND) list(APPEND PHASAR_LINK_LIBS phasar_db) diff --git a/lib/Controller/CMakeLists.txt b/lib/Controller/CMakeLists.txt deleted file mode 100644 index b5fe95c5b..000000000 --- a/lib/Controller/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -file(GLOB_RECURSE CONTROLLER_SRC *.h *.cpp) - -add_phasar_library(phasar_controller - FILES - ${CONTROLLER_SRC} - - LINKS - phasar_llvm_ifdside - phasar_mono - phasar_llvm_db - phasar_llvm_pointer - phasar_llvm_typehierarchy - phasar_llvm_controlflow - phasar_llvm_utils - phasar_utils - phasar_analysis_strategy - phasar_taintconfig - phasar_passes - - LLVM_LINK_COMPONENTS - Core - Support - Demangle - - LINK_PRIVATE - ${PHASAR_STD_FILESYSTEM} -) diff --git a/lib/Utils/InitPhasar.cpp b/lib/Utils/InitPhasar.cpp new file mode 100644 index 000000000..fc58a8458 --- /dev/null +++ b/lib/Utils/InitPhasar.cpp @@ -0,0 +1,45 @@ +#include "phasar/Utils/InitPhasar.h" + +#include "phasar/Utils/Logger.h" + +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/InitLLVM.h" +#include "llvm/Support/raw_ostream.h" + +using namespace psr; + +#define PSR_ISSUE_TRACKER_URL \ + "https://github.com/secure-software-engineering/phasar/issues" + +InitPhasar::InitPhasar(int &Argc, const char **&Argv) noexcept + : llvm::InitLLVM(Argc, Argv) { + static std::nullptr_t InitGlobals = [] { + // Replace LLVM's bug report URL with ours + llvm::setBugReportMsg("PLEASE create a bug report at " PSR_ISSUE_TRACKER_URL + " and include the crash backtrace.\n "); + + // Install custom error handlers, such that fatal errors do not start with + // "LLVM ERROR" + auto FatalErrorHandler = [](void * /*HandlerData*/, const char *Reason, + bool /*GenCrashDiag*/) { + // Prevent recursion in case our error handler itself fails + llvm::remove_fatal_error_handler(); + llvm::remove_bad_alloc_error_handler(); + + // Write the actual error message + Logger::addLinePrefix(llvm::errs(), SeverityLevel::CRITICAL, + std::nullopt); + llvm::errs() << Reason << '\n'; + llvm::errs().flush(); + }; + + // NOTE: Install the bad_alloc handler before the fatal_error handler due to + // a bug in LLVM + // https://github.com/llvm/llvm-project/issues/83040 + llvm::install_bad_alloc_error_handler(FatalErrorHandler, nullptr); + llvm::install_fatal_error_handler(FatalErrorHandler, nullptr); + // llvm::install_out_of_memory_new_handler() is already done by InitLLVM + return nullptr; + }(); + (void)InitGlobals; +} diff --git a/tools/phasar-cli/CMakeLists.txt b/tools/phasar-cli/CMakeLists.txt index a8276c347..f25ce28f7 100644 --- a/tools/phasar-cli/CMakeLists.txt +++ b/tools/phasar-cli/CMakeLists.txt @@ -20,38 +20,14 @@ else() ) endif() -# Warning! There is a another listing of libraries inside cmake/phasar_macros.cmake. -# If this list is altered the other one should be altered accordingly. +add_subdirectory(Controller) + target_link_libraries(phasar-cli PRIVATE - phasar_config - phasar_controller - phasar_llvm_controlflow - phasar_llvm_utils - phasar_analysis_strategy - phasar_llvm_ifdside - phasar_utils - phasar_mono - phasar_llvm_db - phasar_passes - phasar_llvm_pointer - phasar_llvm - phasar_llvm_typehierarchy - phasar_taintconfig - + phasar ${PHASAR_STD_FILESYSTEM} ) if (NOT PHASAR_IN_TREE) - if(USE_LLVM_FAT_LIB) - llvm_config(phasar-cli USE_SHARED ${LLVM_LINK_COMPONENTS}) - else() - llvm_config(phasar-cli ${LLVM_LINK_COMPONENTS}) - endif() - - install(TARGETS phasar-cli - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - ) + install(TARGETS phasar-cli) endif() diff --git a/lib/Controller/AnalysisController.cpp b/tools/phasar-cli/Controller/AnalysisController.cpp similarity index 76% rename from lib/Controller/AnalysisController.cpp rename to tools/phasar-cli/Controller/AnalysisController.cpp index fd77d2ec5..44f25be72 100644 --- a/lib/Controller/AnalysisController.cpp +++ b/tools/phasar-cli/Controller/AnalysisController.cpp @@ -7,7 +7,7 @@ * Philipp Schubert and others *****************************************************************************/ -#include "phasar/Controller/AnalysisController.h" +#include "AnalysisController.h" #include "phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" @@ -17,9 +17,8 @@ namespace psr { -static void -emitRequestedHelperAnalysisResults(AnalysisController::ControllerData &Data) { - auto WithResultFileOrStdout = [&ResultDirectory = Data.ResultDirectory]( +void AnalysisController::emitRequestedHelperAnalysisResults() { + auto WithResultFileOrStdout = [&ResultDirectory = this->ResultDirectory]( const auto &FileName, auto Callback) { if (!ResultDirectory.empty()) { if (auto OFS = openFileStream(ResultDirectory.string() + FileName)) { @@ -30,8 +29,8 @@ emitRequestedHelperAnalysisResults(AnalysisController::ControllerData &Data) { } }; - auto EmitterOptions = Data.EmitterOptions; - auto &HA = *Data.HA; + auto EmitterOptions = this->EmitterOptions; + auto &HA = *this->HA; if (EmitterOptions & AnalysisControllerEmitterOptions::EmitIR) { WithResultFileOrStdout("/psr-preprocess-ir.ll", [&HA](auto &OS) { @@ -96,24 +95,24 @@ emitRequestedHelperAnalysisResults(AnalysisController::ControllerData &Data) { } } -static void executeDemandDriven(AnalysisController::ControllerData & /*Data*/) { +static void executeDemandDriven(AnalysisController & /*Data*/) { llvm::report_fatal_error( "AnalysisStrategy 'demand-driven' not supported, yet!"); } -static void executeIncremental(AnalysisController::ControllerData & /*Data*/) { +static void executeIncremental(AnalysisController & /*Data*/) { llvm::report_fatal_error( "AnalysisStrategy 'incremental' not supported, yet!"); } -static void executeModuleWise(AnalysisController::ControllerData & /*Data*/) { +static void executeModuleWise(AnalysisController & /*Data*/) { llvm::report_fatal_error( "AnalysisStrategy 'module-wise' not supported, yet!"); } -static void executeVariational(AnalysisController::ControllerData & /*Data*/) { +static void executeVariational(AnalysisController & /*Data*/) { llvm::report_fatal_error( "AnalysisStrategy 'variational' not supported, yet!"); } -static void executeWholeProgram(AnalysisController::ControllerData &Data) { +static void executeWholeProgram(AnalysisController &Data) { for (auto DataFlowAnalysis : Data.DataFlowAnalyses) { using namespace controller; switch (DataFlowAnalysis) { @@ -171,60 +170,31 @@ static void executeWholeProgram(AnalysisController::ControllerData &Data) { } } -static void executeAs(AnalysisController::ControllerData &Data, - AnalysisStrategy Strategy) { +void AnalysisController::run() { switch (Strategy) { case AnalysisStrategy::None: return; case AnalysisStrategy::DemandDriven: - executeDemandDriven(Data); + executeDemandDriven(*this); return; case AnalysisStrategy::Incremental: - executeIncremental(Data); + executeIncremental(*this); return; case AnalysisStrategy::ModuleWise: - executeModuleWise(Data); + executeModuleWise(*this); return; case AnalysisStrategy::Variational: - executeVariational(Data); + executeVariational(*this); return; case AnalysisStrategy::WholeProgram: - executeWholeProgram(Data); + executeWholeProgram(*this); return; } llvm_unreachable( "All AnalysisStrategy variants should be handled in the switch above!"); } -AnalysisController::AnalysisController( - HelperAnalyses &HA, std::vector DataFlowAnalyses, - std::vector AnalysisConfigs, - std::vector EntryPoints, AnalysisStrategy Strategy, - AnalysisControllerEmitterOptions EmitterOptions, - IFDSIDESolverConfig SolverConfig, std::string ProjectID, - std::string OutDirectory) - : Data{ - &HA, - std::move(DataFlowAnalyses), - std::move(AnalysisConfigs), - std::move(EntryPoints), - Strategy, - EmitterOptions, - std::move(ProjectID), - std::move(OutDirectory), - SolverConfig, - } { - if (!Data.ResultDirectory.empty()) { - // create directory for results - Data.ResultDirectory /= Data.ProjectID + "-" + createTimeStamp(); - std::filesystem::create_directory(Data.ResultDirectory); - } - emitRequestedHelperAnalysisResults(Data); - executeAs(Data, Strategy); -} - -LLVMTaintConfig -controller::makeTaintConfig(AnalysisController::ControllerData &Data) { +LLVMTaintConfig controller::makeTaintConfig(AnalysisController &Data) { std::string AnalysisConfigPath = !Data.AnalysisConfigs.empty() ? Data.AnalysisConfigs[0] : ""; return !AnalysisConfigPath.empty() diff --git a/include/phasar/Controller/AnalysisController.h b/tools/phasar-cli/Controller/AnalysisController.h similarity index 51% rename from include/phasar/Controller/AnalysisController.h rename to tools/phasar-cli/Controller/AnalysisController.h index 7b9e132c4..b2757b0b8 100644 --- a/include/phasar/Controller/AnalysisController.h +++ b/tools/phasar-cli/Controller/AnalysisController.h @@ -11,37 +11,26 @@ #define PHASAR_CONTROLLER_ANALYSISCONTROLLER_H #include "phasar/AnalysisStrategy/Strategies.h" -#include "phasar/Controller/AnalysisControllerEmitterOptions.h" #include "phasar/DataFlow/IfdsIde/IFDSIDESolverConfig.h" #include "phasar/PhasarLLVM/HelperAnalyses.h" #include "phasar/PhasarLLVM/Utils/DataFlowAnalysisType.h" +#include "AnalysisControllerEmitterOptions.h" + #include namespace psr { -class AnalysisController { -public: - struct ControllerData { - HelperAnalyses *HA{}; - std::vector DataFlowAnalyses; - std::vector AnalysisConfigs; - std::vector EntryPoints; - [[maybe_unused]] AnalysisStrategy Strategy; - AnalysisControllerEmitterOptions EmitterOptions = - AnalysisControllerEmitterOptions::None; - std::string ProjectID; - std::filesystem::path ResultDirectory; - IFDSIDESolverConfig SolverConfig{}; - }; - - explicit AnalysisController( - HelperAnalyses &HA, std::vector DataFlowAnalyses, - std::vector AnalysisConfigs, - std::vector EntryPoints, AnalysisStrategy Strategy, - AnalysisControllerEmitterOptions EmitterOptions, - IFDSIDESolverConfig SolverConfig, - std::string ProjectID = "default-phasar-project", - std::string OutDirectory = ""); +struct AnalysisController { + HelperAnalyses *HA{}; + std::vector DataFlowAnalyses; + std::vector AnalysisConfigs; + std::vector EntryPoints; + [[maybe_unused]] AnalysisStrategy Strategy{}; + AnalysisControllerEmitterOptions EmitterOptions = + AnalysisControllerEmitterOptions::None; + IFDSIDESolverConfig SolverConfig{}; + std::string ProjectID = "default-phasar-project"; + std::filesystem::path ResultDirectory; static constexpr bool needsToEmitPTA(AnalysisControllerEmitterOptions EmitterOptions) { @@ -50,8 +39,8 @@ class AnalysisController { (EmitterOptions & AnalysisControllerEmitterOptions::EmitPTAAsText); } -private: - ControllerData Data; + void emitRequestedHelperAnalysisResults(); + void run(); }; } // namespace psr diff --git a/include/phasar/Controller/AnalysisControllerEmitterOptions.h b/tools/phasar-cli/Controller/AnalysisControllerEmitterOptions.h similarity index 100% rename from include/phasar/Controller/AnalysisControllerEmitterOptions.h rename to tools/phasar-cli/Controller/AnalysisControllerEmitterOptions.h diff --git a/lib/Controller/AnalysisControllerInternal.h b/tools/phasar-cli/Controller/AnalysisControllerInternal.h similarity index 65% rename from lib/Controller/AnalysisControllerInternal.h rename to tools/phasar-cli/Controller/AnalysisControllerInternal.h index 8a736e3a1..1246518fb 100644 --- a/lib/Controller/AnalysisControllerInternal.h +++ b/tools/phasar-cli/Controller/AnalysisControllerInternal.h @@ -10,7 +10,6 @@ #ifndef PHASAR_CONTROLLER_ANALYSISCONTROLLERINTERNAL_H #define PHASAR_CONTROLLER_ANALYSISCONTROLLERINTERNAL_H -#include "phasar/Controller/AnalysisController.h" #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" @@ -22,44 +21,34 @@ #include "llvm/Support/Compiler.h" +#include "AnalysisController.h" + namespace psr { template class IDESolver; } // namespace psr namespace psr::controller { -LLVM_LIBRARY_VISIBILITY void -executeIFDSUninitVar(AnalysisController::ControllerData &Data); -LLVM_LIBRARY_VISIBILITY void -executeIFDSConst(AnalysisController::ControllerData &Data); -LLVM_LIBRARY_VISIBILITY void -executeIFDSTaint(AnalysisController::ControllerData &Data); -LLVM_LIBRARY_VISIBILITY void -executeIFDSType(AnalysisController::ControllerData &Data); -LLVM_LIBRARY_VISIBILITY void -executeIFDSSolverTest(AnalysisController::ControllerData &Data); -LLVM_LIBRARY_VISIBILITY void -executeIFDSFieldSensTaint(AnalysisController::ControllerData &Data); -LLVM_LIBRARY_VISIBILITY void -executeIDEXTaint(AnalysisController::ControllerData &Data); -LLVM_LIBRARY_VISIBILITY void -executeIDEOpenSSLTS(AnalysisController::ControllerData &Data); -LLVM_LIBRARY_VISIBILITY void -executeIDECSTDIOTS(AnalysisController::ControllerData &Data); -LLVM_LIBRARY_VISIBILITY void -executeIDELinearConst(AnalysisController::ControllerData &Data); -LLVM_LIBRARY_VISIBILITY void -executeIDESolverTest(AnalysisController::ControllerData &Data); -LLVM_LIBRARY_VISIBILITY void -executeIDEIIA(AnalysisController::ControllerData &Data); -LLVM_LIBRARY_VISIBILITY void -executeIntraMonoFullConstant(AnalysisController::ControllerData &Data); -LLVM_LIBRARY_VISIBILITY void -executeIntraMonoSolverTest(AnalysisController::ControllerData &Data); -LLVM_LIBRARY_VISIBILITY void -executeInterMonoSolverTest(AnalysisController::ControllerData &Data); -LLVM_LIBRARY_VISIBILITY void -executeInterMonoTaint(AnalysisController::ControllerData &Data); +LLVM_LIBRARY_VISIBILITY void executeIFDSUninitVar(AnalysisController &Data); +LLVM_LIBRARY_VISIBILITY void executeIFDSConst(AnalysisController &Data); +LLVM_LIBRARY_VISIBILITY void executeIFDSTaint(AnalysisController &Data); +LLVM_LIBRARY_VISIBILITY void executeIFDSType(AnalysisController &Data); +LLVM_LIBRARY_VISIBILITY void executeIFDSSolverTest(AnalysisController &Data); +LLVM_LIBRARY_VISIBILITY void +executeIFDSFieldSensTaint(AnalysisController &Data); +LLVM_LIBRARY_VISIBILITY void executeIDEXTaint(AnalysisController &Data); +LLVM_LIBRARY_VISIBILITY void executeIDEOpenSSLTS(AnalysisController &Data); +LLVM_LIBRARY_VISIBILITY void executeIDECSTDIOTS(AnalysisController &Data); +LLVM_LIBRARY_VISIBILITY void executeIDELinearConst(AnalysisController &Data); +LLVM_LIBRARY_VISIBILITY void executeIDESolverTest(AnalysisController &Data); +LLVM_LIBRARY_VISIBILITY void executeIDEIIA(AnalysisController &Data); +LLVM_LIBRARY_VISIBILITY void +executeIntraMonoFullConstant(AnalysisController &Data); +LLVM_LIBRARY_VISIBILITY void +executeIntraMonoSolverTest(AnalysisController &Data); +LLVM_LIBRARY_VISIBILITY void +executeInterMonoSolverTest(AnalysisController &Data); +LLVM_LIBRARY_VISIBILITY void executeInterMonoTaint(AnalysisController &Data); /// /// \brief The maximum length of the CallStrings used in the InterMonoSolver @@ -67,7 +56,7 @@ executeInterMonoTaint(AnalysisController::ControllerData &Data); static constexpr unsigned K = 3; [[nodiscard]] LLVM_LIBRARY_VISIBILITY LLVMTaintConfig -makeTaintConfig(AnalysisController::ControllerData &Data); +makeTaintConfig(AnalysisController &Data); template static void statsEmitter(llvm::raw_ostream & /*OS*/, const T & /*Solver*/) {} @@ -75,9 +64,7 @@ template static void statsEmitter(llvm::raw_ostream &OS, const IDESolver &Solver); template -static void -emitRequestedDataFlowResults(AnalysisController::ControllerData &Data, - T &Solver) { +static void emitRequestedDataFlowResults(AnalysisController &Data, T &Solver) { auto EmitterOptions = Data.EmitterOptions; const auto &ResultDirectory = Data.ResultDirectory; diff --git a/lib/Controller/AnalysisControllerInternalIDE.h b/tools/phasar-cli/Controller/AnalysisControllerInternalIDE.h similarity index 82% rename from lib/Controller/AnalysisControllerInternalIDE.h rename to tools/phasar-cli/Controller/AnalysisControllerInternalIDE.h index fa758bbb6..645c055a7 100644 --- a/lib/Controller/AnalysisControllerInternalIDE.h +++ b/tools/phasar-cli/Controller/AnalysisControllerInternalIDE.h @@ -24,8 +24,7 @@ static void statsEmitter(llvm::raw_ostream &OS, const IDESolver &Solver) { } template -static void executeIfdsIdeAnalysis(AnalysisController::ControllerData &Data, - ArgTys &&...Args) { +static void executeIfdsIdeAnalysis(AnalysisController &Data, ArgTys &&...Args) { auto Problem = createAnalysisProblem(*Data.HA, std::forward(Args)...); SolverTy Solver(Problem, &Data.HA->getICFG()); @@ -44,15 +43,13 @@ static void executeIfdsIdeAnalysis(AnalysisController::ControllerData &Data, } template -static void executeIFDSAnalysis(AnalysisController::ControllerData &Data, - ArgTys &&...Args) { +static void executeIFDSAnalysis(AnalysisController &Data, ArgTys &&...Args) { executeIfdsIdeAnalysis, ProblemTy>( Data, std::forward(Args)...); } template -static void executeIDEAnalysis(AnalysisController::ControllerData &Data, - ArgTys &&...Args) { +static void executeIDEAnalysis(AnalysisController &Data, ArgTys &&...Args) { executeIfdsIdeAnalysis, ProblemTy>( Data, std::forward(Args)...); } diff --git a/lib/Controller/AnalysisControllerInternalMono.h b/tools/phasar-cli/Controller/AnalysisControllerInternalMono.h similarity index 83% rename from lib/Controller/AnalysisControllerInternalMono.h rename to tools/phasar-cli/Controller/AnalysisControllerInternalMono.h index e68878931..8bd649ca7 100644 --- a/lib/Controller/AnalysisControllerInternalMono.h +++ b/tools/phasar-cli/Controller/AnalysisControllerInternalMono.h @@ -18,8 +18,7 @@ namespace psr::controller { template -static void executeMonoAnalysis(AnalysisController::ControllerData &Data, - ArgTys &&...Args) { +static void executeMonoAnalysis(AnalysisController &Data, ArgTys &&...Args) { auto Problem = createAnalysisProblem(*Data.HA, std::forward(Args)...); SolverTy Solver(Problem); @@ -28,14 +27,14 @@ static void executeMonoAnalysis(AnalysisController::ControllerData &Data, } template -static void executeIntraMonoAnalysis(AnalysisController::ControllerData &Data, +static void executeIntraMonoAnalysis(AnalysisController &Data, ArgTys &&...Args) { executeMonoAnalysis, ProblemTy>( Data, std::forward(Args)...); } template -static void executeInterMonoAnalysis(AnalysisController::ControllerData &Data, +static void executeInterMonoAnalysis(AnalysisController &Data, ArgTys &&...Args) { executeMonoAnalysis, ProblemTy>( Data, std::forward(Args)...); diff --git a/lib/Controller/AnalysisControllerXIDECSTDIOTS.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIDECSTDIOTS.cpp similarity index 90% rename from lib/Controller/AnalysisControllerXIDECSTDIOTS.cpp rename to tools/phasar-cli/Controller/AnalysisControllerXIDECSTDIOTS.cpp index f6c268ae8..11f81a349 100644 --- a/lib/Controller/AnalysisControllerXIDECSTDIOTS.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIDECSTDIOTS.cpp @@ -14,7 +14,7 @@ using namespace psr; -void controller::executeIDECSTDIOTS(AnalysisController::ControllerData &Data) { +void controller::executeIDECSTDIOTS(AnalysisController &Data) { CSTDFILEIOTypeStateDescription TSDesc; executeIDEAnalysis>( Data, &TSDesc, Data.EntryPoints); diff --git a/lib/Controller/AnalysisControllerXIDEIIA.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIDEIIA.cpp similarity index 95% rename from lib/Controller/AnalysisControllerXIDEIIA.cpp rename to tools/phasar-cli/Controller/AnalysisControllerXIDEIIA.cpp index e44f08422..e16390901 100644 --- a/lib/Controller/AnalysisControllerXIDEIIA.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIDEIIA.cpp @@ -17,7 +17,7 @@ using namespace psr; -void controller::executeIDEIIA(AnalysisController::ControllerData &Data) { +void controller::executeIDEIIA(AnalysisController &Data) { // use Phasar's instruction ids as testing labels auto Generator = [](std::variant diff --git a/lib/Controller/AnalysisControllerXIDELinearConst.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIDELinearConst.cpp similarity index 87% rename from lib/Controller/AnalysisControllerXIDELinearConst.cpp rename to tools/phasar-cli/Controller/AnalysisControllerXIDELinearConst.cpp index 1e794814f..fc4e95ef5 100644 --- a/lib/Controller/AnalysisControllerXIDELinearConst.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIDELinearConst.cpp @@ -13,7 +13,6 @@ using namespace psr; -void controller::executeIDELinearConst( - AnalysisController::ControllerData &Data) { +void controller::executeIDELinearConst(AnalysisController &Data) { executeIDEAnalysis(Data, Data.EntryPoints); } diff --git a/lib/Controller/AnalysisControllerXIDEOpenSSLTS.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIDEOpenSSLTS.cpp similarity index 90% rename from lib/Controller/AnalysisControllerXIDEOpenSSLTS.cpp rename to tools/phasar-cli/Controller/AnalysisControllerXIDEOpenSSLTS.cpp index f45029770..9f65b2082 100644 --- a/lib/Controller/AnalysisControllerXIDEOpenSSLTS.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIDEOpenSSLTS.cpp @@ -14,7 +14,7 @@ using namespace psr; -void controller::executeIDEOpenSSLTS(AnalysisController::ControllerData &Data) { +void controller::executeIDEOpenSSLTS(AnalysisController &Data) { OpenSSLEVPKDFDescription TSDesc; executeIDEAnalysis>( Data, &TSDesc, Data.EntryPoints); diff --git a/lib/Controller/AnalysisControllerXIDESolverTest.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIDESolverTest.cpp similarity index 86% rename from lib/Controller/AnalysisControllerXIDESolverTest.cpp rename to tools/phasar-cli/Controller/AnalysisControllerXIDESolverTest.cpp index 719207aa3..baa3a27d2 100644 --- a/lib/Controller/AnalysisControllerXIDESolverTest.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIDESolverTest.cpp @@ -13,7 +13,6 @@ using namespace psr; -void controller::executeIDESolverTest( - AnalysisController::ControllerData &Data) { +void controller::executeIDESolverTest(AnalysisController &Data) { executeIDEAnalysis(Data, Data.EntryPoints); } diff --git a/lib/Controller/AnalysisControllerXIDEXTaint.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIDEXTaint.cpp similarity index 89% rename from lib/Controller/AnalysisControllerXIDEXTaint.cpp rename to tools/phasar-cli/Controller/AnalysisControllerXIDEXTaint.cpp index 892939457..dc03bda7f 100644 --- a/lib/Controller/AnalysisControllerXIDEXTaint.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIDEXTaint.cpp @@ -13,7 +13,7 @@ using namespace psr; -void controller::executeIDEXTaint(AnalysisController::ControllerData &Data) { +void controller::executeIDEXTaint(AnalysisController &Data) { auto Config = makeTaintConfig(Data); executeIDEAnalysis>(Data, Config, Data.EntryPoints); diff --git a/lib/Controller/AnalysisControllerXIFDSConst.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIFDSConst.cpp similarity index 88% rename from lib/Controller/AnalysisControllerXIFDSConst.cpp rename to tools/phasar-cli/Controller/AnalysisControllerXIFDSConst.cpp index 0393c2950..55a3600d4 100644 --- a/lib/Controller/AnalysisControllerXIFDSConst.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIFDSConst.cpp @@ -13,6 +13,6 @@ using namespace psr; -void controller::executeIFDSConst(AnalysisController::ControllerData &Data) { +void controller::executeIFDSConst(AnalysisController &Data) { executeIFDSAnalysis(Data, Data.EntryPoints); } diff --git a/lib/Controller/AnalysisControllerXIFDSSolverTest.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIFDSSolverTest.cpp similarity index 86% rename from lib/Controller/AnalysisControllerXIFDSSolverTest.cpp rename to tools/phasar-cli/Controller/AnalysisControllerXIFDSSolverTest.cpp index 08f8c2689..c8b37c574 100644 --- a/lib/Controller/AnalysisControllerXIFDSSolverTest.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIFDSSolverTest.cpp @@ -13,7 +13,6 @@ using namespace psr; -void controller::executeIFDSSolverTest( - AnalysisController::ControllerData &Data) { +void controller::executeIFDSSolverTest(AnalysisController &Data) { executeIFDSAnalysis(Data, Data.EntryPoints); } diff --git a/lib/Controller/AnalysisControllerXIFDSTaint.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIFDSTaint.cpp similarity index 88% rename from lib/Controller/AnalysisControllerXIFDSTaint.cpp rename to tools/phasar-cli/Controller/AnalysisControllerXIFDSTaint.cpp index a94abca60..0d410ccbc 100644 --- a/lib/Controller/AnalysisControllerXIFDSTaint.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIFDSTaint.cpp @@ -13,7 +13,7 @@ using namespace psr; -void controller::executeIFDSTaint(AnalysisController::ControllerData &Data) { +void controller::executeIFDSTaint(AnalysisController &Data) { auto Config = makeTaintConfig(Data); executeIFDSAnalysis(Data, &Config, Data.EntryPoints); } diff --git a/lib/Controller/AnalysisControllerXIFDSType.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIFDSType.cpp similarity index 88% rename from lib/Controller/AnalysisControllerXIFDSType.cpp rename to tools/phasar-cli/Controller/AnalysisControllerXIFDSType.cpp index e5a56d531..8c8410e99 100644 --- a/lib/Controller/AnalysisControllerXIFDSType.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIFDSType.cpp @@ -13,6 +13,6 @@ using namespace psr; -void controller::executeIFDSType(AnalysisController::ControllerData &Data) { +void controller::executeIFDSType(AnalysisController &Data) { executeIFDSAnalysis(Data, Data.EntryPoints); } diff --git a/lib/Controller/AnalysisControllerXIFDSUninit.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIFDSUninit.cpp similarity index 87% rename from lib/Controller/AnalysisControllerXIFDSUninit.cpp rename to tools/phasar-cli/Controller/AnalysisControllerXIFDSUninit.cpp index db66cfef1..7e4789808 100644 --- a/lib/Controller/AnalysisControllerXIFDSUninit.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIFDSUninit.cpp @@ -13,7 +13,6 @@ using namespace psr; -void controller::executeIFDSUninitVar( - AnalysisController::ControllerData &Data) { +void controller::executeIFDSUninitVar(AnalysisController &Data) { executeIFDSAnalysis(Data, Data.EntryPoints); } diff --git a/lib/Controller/AnalysisControllerXInterMonoSolverTest.cpp b/tools/phasar-cli/Controller/AnalysisControllerXInterMonoSolverTest.cpp similarity index 86% rename from lib/Controller/AnalysisControllerXInterMonoSolverTest.cpp rename to tools/phasar-cli/Controller/AnalysisControllerXInterMonoSolverTest.cpp index 17ad61168..3b2b8e78a 100644 --- a/lib/Controller/AnalysisControllerXInterMonoSolverTest.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXInterMonoSolverTest.cpp @@ -13,7 +13,6 @@ using namespace psr; -void controller::executeInterMonoSolverTest( - AnalysisController::ControllerData &Data) { +void controller::executeInterMonoSolverTest(AnalysisController &Data) { executeInterMonoAnalysis(Data, Data.EntryPoints); } diff --git a/lib/Controller/AnalysisControllerXInterMonoTaint.cpp b/tools/phasar-cli/Controller/AnalysisControllerXInterMonoTaint.cpp similarity index 88% rename from lib/Controller/AnalysisControllerXInterMonoTaint.cpp rename to tools/phasar-cli/Controller/AnalysisControllerXInterMonoTaint.cpp index cc24440e1..dbbb19d2a 100644 --- a/lib/Controller/AnalysisControllerXInterMonoTaint.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXInterMonoTaint.cpp @@ -13,8 +13,7 @@ using namespace psr; -void controller::executeInterMonoTaint( - AnalysisController::ControllerData &Data) { +void controller::executeInterMonoTaint(AnalysisController &Data) { auto Config = makeTaintConfig(Data); executeInterMonoAnalysis(Data, Config, Data.EntryPoints); diff --git a/lib/Controller/AnalysisControllerXIntraMonoFullConstant.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIntraMonoFullConstant.cpp similarity index 87% rename from lib/Controller/AnalysisControllerXIntraMonoFullConstant.cpp rename to tools/phasar-cli/Controller/AnalysisControllerXIntraMonoFullConstant.cpp index 65a95b338..8c17bbb9f 100644 --- a/lib/Controller/AnalysisControllerXIntraMonoFullConstant.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIntraMonoFullConstant.cpp @@ -13,8 +13,7 @@ using namespace psr; -void controller::executeIntraMonoFullConstant( - AnalysisController::ControllerData &Data) { +void controller::executeIntraMonoFullConstant(AnalysisController &Data) { executeIntraMonoAnalysis(Data, Data.EntryPoints); } diff --git a/lib/Controller/AnalysisControllerXIntraMonoSolverTest.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIntraMonoSolverTest.cpp similarity index 86% rename from lib/Controller/AnalysisControllerXIntraMonoSolverTest.cpp rename to tools/phasar-cli/Controller/AnalysisControllerXIntraMonoSolverTest.cpp index 557d5899d..c1043a6f1 100644 --- a/lib/Controller/AnalysisControllerXIntraMonoSolverTest.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIntraMonoSolverTest.cpp @@ -13,7 +13,6 @@ using namespace psr; -void controller::executeIntraMonoSolverTest( - AnalysisController::ControllerData &Data) { +void controller::executeIntraMonoSolverTest(AnalysisController &Data) { executeIntraMonoAnalysis(Data, Data.EntryPoints); } diff --git a/tools/phasar-cli/Controller/CMakeLists.txt b/tools/phasar-cli/Controller/CMakeLists.txt new file mode 100644 index 000000000..5977a5aef --- /dev/null +++ b/tools/phasar-cli/Controller/CMakeLists.txt @@ -0,0 +1,3 @@ +file(GLOB_RECURSE CONTROLLER_SRC *.h *.cpp) + +target_sources(phasar-cli PRIVATE ${CONTROLLER_SRC}) diff --git a/tools/phasar-cli/phasar-cli.cpp b/tools/phasar-cli/phasar-cli.cpp index 6781e8e4b..a6487aec4 100644 --- a/tools/phasar-cli/phasar-cli.cpp +++ b/tools/phasar-cli/phasar-cli.cpp @@ -10,25 +10,25 @@ #include "phasar/AnalysisStrategy/Strategies.h" #include "phasar/Config/Configuration.h" #include "phasar/ControlFlow/CallGraphAnalysisType.h" -#include "phasar/Controller/AnalysisController.h" -#include "phasar/Controller/AnalysisControllerEmitterOptions.h" #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/HelperAnalyses.h" -#include "phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h" #include "phasar/PhasarLLVM/Utils/DataFlowAnalysisType.h" #include "phasar/Pointer/AliasAnalysisType.h" #include "phasar/Utils/IO.h" +#include "phasar/Utils/InitPhasar.h" #include "phasar/Utils/Logger.h" #include "phasar/Utils/Soundness.h" +#include "phasar/Utils/Utilities.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/CommandLine.h" -#include "nlohmann/json.hpp" +#include "Controller/AnalysisController.h" +#include "Controller/AnalysisControllerEmitterOptions.h" #include #include -#include +#include #include #include @@ -40,6 +40,10 @@ namespace { cl::OptionCategory PsrCat("PhASAR"); +static auto values(std::initializer_list IList) { + return cl::ValuesClass(IList); +} + #define PSR_OPTION_FLAG(NAME, CMDFLAG, DESC, ...) \ cl::opt NAME(CMDFLAG, cl::desc(DESC), cl::cat(PsrCat), ##__VA_ARGS__) @@ -70,27 +74,28 @@ PSR_SHORTLONG_OPTION_TYPE( "Set the entry point(s) to be used; use '__ALL__' to specify all available " "function definitions as entry points"); -cl::list DataFlowAnalysisOpt( - "data-flow-analysis", cl::desc("Set the analyses to be run"), - cl::values( +cl::list + DataFlowAnalysisOpt("data-flow-analysis", + cl::desc("Set the analyses to be run"), + values({ #define DATA_FLOW_ANALYSIS_TYPES(NAME, CMDFLAG, DESC) \ clEnumValN(DataFlowAnalysisType::NAME, CMDFLAG, DESC), #include "phasar/PhasarLLVM/Utils/DataFlowAnalysisType.def" - clEnumValN(DataFlowAnalysisType::None, "none", "No-op")), - cl::cat(PsrCat)); + }), + cl::cat(PsrCat)); cl::alias DataFlowAnalysisAlias("D", cl::aliasopt(DataFlowAnalysisOpt), cl::desc("Alias for --data-flow-analysis"), cl::cat(PsrCat)); -cl::opt - StrategyOpt("analysis-strategy", cl::desc("The analysis strategy"), - cl::values( +cl::opt StrategyOpt("analysis-strategy", + cl::desc("The analysis strategy"), + values({ #define ANALYSIS_STRATEGY_TYPES(NAME, CMDFLAG, DESC) \ clEnumValN(AnalysisStrategy::NAME, CMDFLAG, DESC), #include "phasar/AnalysisStrategy/Strategies.def" - clEnumValN(AnalysisStrategy::None, "none", "none")), - cl::init(AnalysisStrategy::WholeProgram), cl::cat(PsrCat), - cl::Hidden); + }), + cl::init(AnalysisStrategy::WholeProgram), + cl::cat(PsrCat), cl::Hidden); cl::opt AnalysisConfigOpt( "analysis-config", @@ -102,36 +107,38 @@ cl::opt AliasTypeOpt( cl::desc("Set the alias analysis to be used (CFLSteens, " "CFLAnders). CFLSteens is ~O(N) but inaccurate while " "CFLAnders O(N^3) but more accurate."), - cl::values( + values({ #define ALIAS_ANALYSIS_TYPE(NAME, CMDFLAG, DESC) \ clEnumValN(AliasAnalysisType::NAME, CMDFLAG, DESC), #include "phasar/Pointer/AliasAnalysisType.def" - clEnumValN(AliasAnalysisType::Invalid, "invalid", "invalid")), + }), cl::init(AliasAnalysisType::CFLAnders), cl::cat(PsrCat)); cl::alias AliasTypeAlias("P", cl::aliasopt(AliasTypeOpt), cl::desc("Alias for --alias-analysis"), cl::cat(PsrCat)); -cl::opt CGTypeOpt( - "call-graph-analysis", cl::desc("Set the call-graph algorithm to be used"), - cl::values( +cl::opt + CGTypeOpt("call-graph-analysis", + cl::desc("Set the call-graph algorithm to be used"), + values({ #define CALL_GRAPH_ANALYSIS_TYPE(NAME, CMDFLAG, DESC) \ clEnumValN(CallGraphAnalysisType::NAME, CMDFLAG, DESC), #include "phasar/ControlFlow/CallGraphAnalysisType.def" - clEnumValN(CallGraphAnalysisType::Invalid, "invalid", "invalid")), - cl::init(CallGraphAnalysisType::OTF), cl::cat(PsrCat)); + }), + cl::init(CallGraphAnalysisType::OTF), cl::cat(PsrCat)); cl::alias CGTypeAlias("C", cl::aliasopt(CGTypeOpt), cl::desc("Alias for --call-graph-analysis"), cl::cat(PsrCat)); -cl::opt - SoundnessOpt("soundness", cl::desc("Set the soundiness level to be used"), - cl::values( +cl::opt SoundnessOpt("soundness", + cl::desc("Set the soundiness level to be used"), + values({ #define SOUNDNESS_FLAG_TYPE(NAME, CMDFLAG, DESC) \ clEnumValN(Soundness::NAME, CMDFLAG, DESC), #include "phasar/Utils/Soundness.def" - clEnumValN(Soundness::Invalid, "invalid", "invalid")), - cl::init(Soundness::Soundy), cl::cat(PsrCat), cl::Hidden); + }), + cl::init(Soundness::Soundy), cl::cat(PsrCat), + cl::Hidden); PSR_OPTION_FLAG(AutoGlobalsOpt, "auto-globals", "Enable automated support for global initializers", cl::init(true)); @@ -149,10 +156,10 @@ cl::opt LogSeverityOpt( "printed. Has no effect if logging is disabled. You can enable " "logging with --log/-L or by specifying at least one --log-cat."), cl::cat(PsrCat), - cl::values( + values({ #define SEVERITY_LEVEL(NAME, TYPE) clEnumValN(SeverityLevel::TYPE, NAME, NAME), #include "phasar/Utils/SeverityLevel.def" - clEnumValN(SeverityLevel::INVALID, "INVALID", "INVALID")), + }), cl::init(SeverityLevel::DEBUG)); cl::list @@ -319,6 +326,8 @@ void validatePTAJsonFile() { } // anonymous namespace int main(int Argc, const char **Argv) { + PSR_INITIALIZER(Argc, Argv); + cl::SetVersionPrinter([](llvm::raw_ostream &OS) { OS << "PhASAR " << PhasarConfig::PhasarVersion() << '\n'; }); @@ -458,8 +467,25 @@ int main(int Argc, const char **Argv) { return 1; } - AnalysisController Controller( - HA, DataFlowAnalysisOpt, {AnalysisConfigOpt.getValue()}, EntryOpt, - StrategyOpt, EmitterOptions, SolverConfig, ProjectIdOpt, OutDirOpt); + AnalysisController Controller{ + &HA, + DataFlowAnalysisOpt, + {AnalysisConfigOpt.getValue()}, + EntryOpt, + StrategyOpt, + EmitterOptions, + SolverConfig, + ProjectIdOpt.getValue(), + OutDirOpt.getValue(), + }; + if (!OutDirOpt.empty()) { + // create directory for results + Controller.ResultDirectory /= + Controller.ProjectID + "-" + createTimeStamp(); + std::filesystem::create_directory(Controller.ResultDirectory); + } + + Controller.emitRequestedHelperAnalysisResults(); + Controller.run(); return 0; }