From 621baa7799953a8111fe6825c96f798815be0d0c Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Mon, 10 Aug 2026 14:50:50 +0200 Subject: [PATCH 1/7] Make HelperAnalyses constructible with unique_ptr of LLVMProjectIRDB + improve entry-points and auto-globals handling in phasar-cli --- include/phasar/PhasarLLVM/HelperAnalyses.h | 3 ++ lib/PhasarLLVM/HelperAnalyses.cpp | 6 +++ tools/phasar-cli/phasar-cli.cpp | 59 ++++++++++++++++------ 3 files changed, 52 insertions(+), 16 deletions(-) diff --git a/include/phasar/PhasarLLVM/HelperAnalyses.h b/include/phasar/PhasarLLVM/HelperAnalyses.h index ec75980e46..2db44e853f 100644 --- a/include/phasar/PhasarLLVM/HelperAnalyses.h +++ b/include/phasar/PhasarLLVM/HelperAnalyses.h @@ -63,6 +63,9 @@ class HelperAnalyses { // NOLINT(cppcoreguidelines-special-member-functions) explicit HelperAnalyses(std::unique_ptr IRModule, std::vector EntryPoints, HelperAnalysisConfig Config = {}); + explicit HelperAnalyses(std::unique_ptr IRDB, + std::vector EntryPoints, + HelperAnalysisConfig Config = {}); ~HelperAnalyses() noexcept; [[nodiscard]] LLVMProjectIRDB &getProjectIRDB(); diff --git a/lib/PhasarLLVM/HelperAnalyses.cpp b/lib/PhasarLLVM/HelperAnalyses.cpp index 2ade892838..88dc1c47bb 100644 --- a/lib/PhasarLLVM/HelperAnalyses.cpp +++ b/lib/PhasarLLVM/HelperAnalyses.cpp @@ -75,6 +75,12 @@ HelperAnalyses::HelperAnalyses(std::unique_ptr IRModule, this->IRDB = std::make_unique( std::move(IRModule), Config.PreprocessExistingModule); } +HelperAnalyses::HelperAnalyses(std::unique_ptr IRDB, + std::vector EntryPoints, + HelperAnalysisConfig Config) + : HelperAnalyses(std::string(), std::move(EntryPoints), std::move(Config)) { + this->IRDB = std::move(IRDB); +} HelperAnalyses::~HelperAnalyses() noexcept = default; diff --git a/tools/phasar-cli/phasar-cli.cpp b/tools/phasar-cli/phasar-cli.cpp index e5d5e90d6e..435d1dd8d0 100644 --- a/tools/phasar-cli/phasar-cli.cpp +++ b/tools/phasar-cli/phasar-cli.cpp @@ -11,20 +11,24 @@ #include "phasar/Config/Configuration.h" #include "phasar/ControlFlow/CallGraphAnalysisType.h" #include "phasar/ControlFlow/CallGraphData.h" +#include "phasar/PhasarLLVM/ControlFlow/EntryFunctionUtils.h" +#include "phasar/PhasarLLVM/ControlFlow/ExternCallbackModel.h" +#include "phasar/PhasarLLVM/ControlFlow/GlobalCtorsDtorsModel.h" #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/HelperAnalyses.h" -#include "phasar/PhasarLLVM/HelperAnalysisConfig.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasSetData.h" #include "phasar/PhasarLLVM/Utils/DataFlowAnalysisType.h" #include "phasar/Pointer/AliasAnalysisType.h" #include "phasar/Pointer/UnionFindAliasAnalysisType.h" #include "phasar/Utils/InitPhasar.h" +#include "phasar/Utils/Lazy.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 "llvm/Support/WithColor.h" #include "Controller/AnalysisController.h" #include "Controller/AnalysisControllerEmitterOptions.h" @@ -156,6 +160,12 @@ PSR_OPTION_FLAG(AutoGlobalsOpt, "auto-globals", "Enable automated support for global initializers", cl::init(true)); +PSR_OPTION_FLAG(ExternalCallsRewriteOpt, "rewrite-external-calls", + "Whether to rewrite calls-to known external functions, such as " + "pthread_create, s.t., their callback calls are not lost in " + "the call-graph", + cl::init(true)); + PSR_SHORTLONG_OPTION( StatisticsOpt, bool, "S", "emit-stats", "Collect and emit statistics of the module(s) under analysis"); @@ -467,21 +477,38 @@ int main(int Argc, const char **Argv) { PrecomputedCallGraph = CallGraphData::deserializeJson(LoadCGFromJsonOpt); } - if (EntryOpt.empty()) { - EntryOpt.push_back("main"); - } + auto IRDB = std::make_unique( + PSR_LAZY(LLVMProjectIRDB::loadOrExit(ModuleOpt))); - HelperAnalysisConfig HAConfig{ - .PrecomputedCG = std::move(PrecomputedCallGraph), - .PTATy = AliasTypeOpt, - .UFAATy = UFAliasTypeOpt, - .CGTy = CGTypeOpt, - .SoundnessLevel = SoundnessOpt, - .AutoGlobalSupport = AutoGlobalsOpt, - .AllowLazyPTS = !AnalysisController::needsToEmitPTA(EmitterOptions), - }; - HelperAnalyses HA(std::move(ModuleOpt.getValue()), EntryOpt, - std::move(HAConfig)); + std::vector EntryPoints = std::move(EntryOpt); + if (EntryPoints.empty()) { + EntryPoints = getDefaultEntryPoints(*IRDB); + } + if (AutoGlobalsOpt) { + if (EntryPoints.size() == 1 && EntryPoints.front() == "main") { + GlobalCtorsDtorsModel::buildModel(*IRDB, EntryPoints); + EntryPoints = {GlobalCtorsDtorsModel::ModelName.str()}; + } else if (AutoGlobalsOpt.getNumOccurrences() > 0) { + llvm::WithColor::warning() + << "'--auto-globals' is currently not supported for libraries, only " + "for applications with 'main' as entry-point'\n"; + } + } + if (ExternalCallsRewriteOpt) { + ExternCallbackModel::rewriteCalls(*IRDB); + } + + HelperAnalyses HA( + std::move(IRDB), EntryPoints, + { + .PrecomputedCG = std::move(PrecomputedCallGraph), + .PTATy = AliasTypeOpt, + .UFAATy = UFAliasTypeOpt, + .CGTy = CGTypeOpt, + .SoundnessLevel = SoundnessOpt, + .AutoGlobalSupport = false, + .AllowLazyPTS = !AnalysisController::needsToEmitPTA(EmitterOptions), + }); if (!HA.getProjectIRDB().isValid()) { // Note: Error message has already been printed return 1; @@ -491,7 +518,7 @@ int main(int Argc, const char **Argv) { .HA = &HA, .DataFlowAnalyses = DataFlowAnalysisOpt, .AnalysisConfigs = {AnalysisConfigOpt.getValue()}, - .EntryPoints = EntryOpt, + .EntryPoints = std::move(EntryPoints), .Strategy = StrategyOpt, .EmitterOptions = EmitterOptions, .SolverConfig = SolverConfig, From a0da97cda42f293fdad05c8588d2512848b3e9f6 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Mon, 10 Aug 2026 15:02:54 +0200 Subject: [PATCH 2/7] Fix my mail address in README.dox --- docs/README.dox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.dox b/docs/README.dox index 6ae3b786c0..eb2643421b 100644 --- a/docs/README.dox +++ b/docs/README.dox @@ -16,7 +16,7 @@ PhASAR is primarily developed and maintained by the [Secure Software Engineering PhASAR was initially developed by Philipp Dominik Schubert (@pdschubert)(). \b Currently, PhASAR is maintained by -- Fabian Schiebel (@fabianbs96)(fabian.schiebel@iem.fraunhofer.de) +- Fabian Schiebel (@fabianbs96)(fabian.schiebel@uni-paderborn.de) - Sriteja Kummita (@sritejakv) - Lucas Briese (@jusito) - Martin Mory (@MMory)(martin.mory@upb.de) From 30d224e1237348e957549b2bc4be961d135d5054 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Mon, 10 Aug 2026 15:30:18 +0200 Subject: [PATCH 3/7] Make HA part of AnalysisController (no pointer indirection) --- .../Controller/AnalysisController.cpp | 6 ++-- .../Controller/AnalysisController.h | 2 +- .../AnalysisControllerInternalIDE.h | 14 ++++----- .../AnalysisControllerInternalMono.h | 2 +- .../AnalysisControllerXIFDSCFLEnvTaint.cpp | 4 +-- .../AnalysisControllerXMonoIFDSTaint.cpp | 6 ++-- tools/phasar-cli/phasar-cli.cpp | 29 ++++++++----------- 7 files changed, 29 insertions(+), 34 deletions(-) diff --git a/tools/phasar-cli/Controller/AnalysisController.cpp b/tools/phasar-cli/Controller/AnalysisController.cpp index 1f6feb5657..4e089ebb42 100644 --- a/tools/phasar-cli/Controller/AnalysisController.cpp +++ b/tools/phasar-cli/Controller/AnalysisController.cpp @@ -31,7 +31,7 @@ void AnalysisController::emitRequestedHelperAnalysisResults() { }; auto EmitterOptions = this->EmitterOptions; - auto &HA = *this->HA; + auto &HA = this->HA; if (EmitterOptions & AnalysisControllerEmitterOptions::EmitIR) { WithResultFileOrStdout("/psr-preprocess-ir.ll", [&HA](auto &OS) { @@ -211,9 +211,9 @@ LLVMTaintConfig controller::makeTaintConfig(AnalysisController &Data) { std::string AnalysisConfigPath = !Data.AnalysisConfigs.empty() ? Data.AnalysisConfigs[0] : ""; return !AnalysisConfigPath.empty() - ? LLVMTaintConfig(Data.HA->getProjectIRDB(), + ? LLVMTaintConfig(Data.HA.getProjectIRDB(), parseTaintConfig(AnalysisConfigPath)) - : LLVMTaintConfig(Data.HA->getProjectIRDB()); + : LLVMTaintConfig(Data.HA.getProjectIRDB()); } } // namespace psr diff --git a/tools/phasar-cli/Controller/AnalysisController.h b/tools/phasar-cli/Controller/AnalysisController.h index b2757b0b8e..565f0fa8d9 100644 --- a/tools/phasar-cli/Controller/AnalysisController.h +++ b/tools/phasar-cli/Controller/AnalysisController.h @@ -21,7 +21,7 @@ namespace psr { struct AnalysisController { - HelperAnalyses *HA{}; + HelperAnalyses HA; std::vector DataFlowAnalyses; std::vector AnalysisConfigs; std::vector EntryPoints; diff --git a/tools/phasar-cli/Controller/AnalysisControllerInternalIDE.h b/tools/phasar-cli/Controller/AnalysisControllerInternalIDE.h index c986ccc01a..527cefcd9e 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerInternalIDE.h +++ b/tools/phasar-cli/Controller/AnalysisControllerInternalIDE.h @@ -46,7 +46,7 @@ static void executeIfdsIdeAnalysisImpl(SolverTy &Solver, template static void executeSparseIfdsIdeAnalysis(AnalysisController &Data, ArgTys &&...Args) { - SparseLLVMBasedICFGView SVFG(&Data.HA->getICFG(), Data.HA->getAliasInfo()); + SparseLLVMBasedICFGView SVFG(&Data.HA.getICFG(), Data.HA.getAliasInfo()); executeIfdsIdeAnalysisImpl( Data, SVFG, std::forward(Args)...); } @@ -56,7 +56,7 @@ static void executeIFDSAnalysisWithICFG(AnalysisController &Data, const ICFG auto &ICF, ArgTys &&...Args) { auto Problem = - createAnalysisProblem(*Data.HA, std::forward(Args)...); + createAnalysisProblem(Data.HA, std::forward(Args)...); IFDSSolver Solver(&Problem, &ICF); executeIfdsIdeAnalysisImpl(Solver, Data); } @@ -64,34 +64,34 @@ template static void executeIDEAnalysisWithICFG(AnalysisController &Data, const ICFG auto &ICF, ArgTys &&...Args) { auto Problem = - createAnalysisProblem(*Data.HA, std::forward(Args)...); + createAnalysisProblem(Data.HA, std::forward(Args)...); IDESolver Solver(&Problem, &ICF); executeIfdsIdeAnalysisImpl(Solver, Data); } template static void executeIFDSAnalysis(AnalysisController &Data, ArgTys &&...Args) { - executeIFDSAnalysisWithICFG(Data, Data.HA->getICFG(), + executeIFDSAnalysisWithICFG(Data, Data.HA.getICFG(), PSR_FWD(Args)...); } template static void executeSparseIFDSAnalysis(AnalysisController &Data, ArgTys &&...Args) { - SparseLLVMBasedICFGView SVFG(&Data.HA->getICFG(), Data.HA->getAliasInfo()); + SparseLLVMBasedICFGView SVFG(&Data.HA.getICFG(), Data.HA.getAliasInfo()); executeIFDSAnalysisWithICFG(Data, SVFG, PSR_FWD(Args)...); } template static void executeIDEAnalysis(AnalysisController &Data, ArgTys &&...Args) { - executeIDEAnalysisWithICFG(Data, Data.HA->getICFG(), + executeIDEAnalysisWithICFG(Data, Data.HA.getICFG(), PSR_FWD(Args)...); } template static void executeSparseIDEAnalysis(AnalysisController &Data, ArgTys &&...Args) { - SparseLLVMBasedICFGView SVFG(&Data.HA->getICFG(), Data.HA->getAliasInfo()); + SparseLLVMBasedICFGView SVFG(&Data.HA.getICFG(), Data.HA.getAliasInfo()); executeIDEAnalysisWithICFG(Data, SVFG, PSR_FWD(Args)...); } diff --git a/tools/phasar-cli/Controller/AnalysisControllerInternalMono.h b/tools/phasar-cli/Controller/AnalysisControllerInternalMono.h index 8bd649ca75..7b2a1334fc 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerInternalMono.h +++ b/tools/phasar-cli/Controller/AnalysisControllerInternalMono.h @@ -20,7 +20,7 @@ namespace psr::controller { template static void executeMonoAnalysis(AnalysisController &Data, ArgTys &&...Args) { auto Problem = - createAnalysisProblem(*Data.HA, std::forward(Args)...); + createAnalysisProblem(Data.HA, std::forward(Args)...); SolverTy Solver(Problem); Solver.solve(); emitRequestedDataFlowResults(Data, Solver); diff --git a/tools/phasar-cli/Controller/AnalysisControllerXIFDSCFLEnvTaint.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIFDSCFLEnvTaint.cpp index c4ed6a7cf8..c2952b43f6 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXIFDSCFLEnvTaint.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIFDSCFLEnvTaint.cpp @@ -25,12 +25,12 @@ void controller::executeIFDSCFLEnvTaint(AnalysisController &Data) { auto Config = makeTaintConfig(Data); auto UserProblem = createAnalysisProblem( - *Data.HA, &Config, Data.EntryPoints, /*TaintMainArgs*/ false, + Data.HA, &Config, Data.EntryPoints, /*TaintMainArgs*/ false, /*EnableStrongUpdateStore*/ false); auto Printer = UserProblem.consumePrinter(); auto FieldSensProblem = CFLFieldSensIFDSProblem(&UserProblem); - IterativeIDESolver Solver(&FieldSensProblem, &Data.HA->getICFG()); + IterativeIDESolver Solver(&FieldSensProblem, &Data.HA.getICFG()); SimpleTimer MeasureTime; diff --git a/tools/phasar-cli/Controller/AnalysisControllerXMonoIFDSTaint.cpp b/tools/phasar-cli/Controller/AnalysisControllerXMonoIFDSTaint.cpp index 52d5138ead..2e73375aa6 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXMonoIFDSTaint.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXMonoIFDSTaint.cpp @@ -18,17 +18,17 @@ using namespace psr; void controller::executeMonoIFDSTaint(AnalysisController &Data) { - FilteredLLVMAliasIterator FAI(Data.HA->getAliasInfo()); + FilteredLLVMAliasIterator FAI(Data.HA.getAliasInfo()); auto Config = makeTaintConfig(Data); - monoifds::TaintAnalysis TA(&Config, &Data.HA->getUsedGlobals(), &FAI); + monoifds::TaintAnalysis TA(&Config, &Data.HA.getUsedGlobals(), &FAI); // monoifds::MonoIFDSSolver Solver(&TA, &Data.HA->getICFG()); // Solver // // .setCGSCCs(&Data.HA->getCGSCCs()) // .setFunctionCompressor(&Data.HA->getCompressedFunctions()); - monoifds::MonoIFDSSolver Solver(&TA, *Data.HA); + monoifds::MonoIFDSSolver Solver(&TA, Data.HA); { std::optional MeasureTime; diff --git a/tools/phasar-cli/phasar-cli.cpp b/tools/phasar-cli/phasar-cli.cpp index 435d1dd8d0..86f33850eb 100644 --- a/tools/phasar-cli/phasar-cli.cpp +++ b/tools/phasar-cli/phasar-cli.cpp @@ -498,24 +498,19 @@ int main(int Argc, const char **Argv) { ExternCallbackModel::rewriteCalls(*IRDB); } - HelperAnalyses HA( - std::move(IRDB), EntryPoints, - { - .PrecomputedCG = std::move(PrecomputedCallGraph), - .PTATy = AliasTypeOpt, - .UFAATy = UFAliasTypeOpt, - .CGTy = CGTypeOpt, - .SoundnessLevel = SoundnessOpt, - .AutoGlobalSupport = false, - .AllowLazyPTS = !AnalysisController::needsToEmitPTA(EmitterOptions), - }); - if (!HA.getProjectIRDB().isValid()) { - // Note: Error message has already been printed - return 1; - } - AnalysisController Controller{ - .HA = &HA, + .HA = HelperAnalyses( + std::move(IRDB), EntryPoints, + { + .PrecomputedCG = std::move(PrecomputedCallGraph), + .PTATy = AliasTypeOpt, + .UFAATy = UFAliasTypeOpt, + .CGTy = CGTypeOpt, + .SoundnessLevel = SoundnessOpt, + .AutoGlobalSupport = false, + .AllowLazyPTS = + !AnalysisController::needsToEmitPTA(EmitterOptions), + }), .DataFlowAnalyses = DataFlowAnalysisOpt, .AnalysisConfigs = {AnalysisConfigOpt.getValue()}, .EntryPoints = std::move(EntryPoints), From 883405b49f83821a5fd88ad9a20b8196e9d6a260 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Mon, 10 Aug 2026 16:18:54 +0200 Subject: [PATCH 4/7] Refactor phasar-cli to use LLVM's zero-copy filesystem utilities instead of std::filesystem, which uses std::fiulesyste::path that is not compatible with anything in phasar --- .../Controller/AnalysisController.cpp | 4 +- .../Controller/AnalysisController.h | 7 +- .../Controller/AnalysisControllerInternal.h | 8 +- .../AnalysisControllerXIFDSCFLEnvTaint.cpp | 2 +- .../AnalysisControllerXMonoIFDSTaint.cpp | 1 + tools/phasar-cli/phasar-cli.cpp | 146 +++++++++--------- 6 files changed, 87 insertions(+), 81 deletions(-) diff --git a/tools/phasar-cli/Controller/AnalysisController.cpp b/tools/phasar-cli/Controller/AnalysisController.cpp index 4e089ebb42..7e3e6a224d 100644 --- a/tools/phasar-cli/Controller/AnalysisController.cpp +++ b/tools/phasar-cli/Controller/AnalysisController.cpp @@ -9,6 +9,8 @@ #include "AnalysisController.h" +#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" +#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h" #include "phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h" #include "phasar/PhasarLLVM/Utils/DataFlowAnalysisType.h" @@ -22,7 +24,7 @@ void AnalysisController::emitRequestedHelperAnalysisResults() { auto WithResultFileOrStdout = [&ResultDirectory = this->ResultDirectory]( const auto &FileName, auto Callback) { if (!ResultDirectory.empty()) { - if (auto OFS = openFileStream(ResultDirectory.string() + FileName)) { + if (auto OFS = openFileStream(ResultDirectory + llvm::Twine(FileName))) { Callback(*OFS); } } else { diff --git a/tools/phasar-cli/Controller/AnalysisController.h b/tools/phasar-cli/Controller/AnalysisController.h index 565f0fa8d9..be62613790 100644 --- a/tools/phasar-cli/Controller/AnalysisController.h +++ b/tools/phasar-cli/Controller/AnalysisController.h @@ -15,9 +15,10 @@ #include "phasar/PhasarLLVM/HelperAnalyses.h" #include "phasar/PhasarLLVM/Utils/DataFlowAnalysisType.h" +#include "llvm/ADT/SmallString.h" + #include "AnalysisControllerEmitterOptions.h" -#include namespace psr { struct AnalysisController { @@ -29,8 +30,8 @@ struct AnalysisController { AnalysisControllerEmitterOptions EmitterOptions = AnalysisControllerEmitterOptions::None; IFDSIDESolverConfig SolverConfig{}; - std::string ProjectID = "default-phasar-project"; - std::filesystem::path ResultDirectory; + llvm::SmallString<128> ProjectID; + llvm::SmallString<128> ResultDirectory; static constexpr bool needsToEmitPTA(AnalysisControllerEmitterOptions EmitterOptions) { diff --git a/tools/phasar-cli/Controller/AnalysisControllerInternal.h b/tools/phasar-cli/Controller/AnalysisControllerInternal.h index 78a35898c0..c9f06c2f05 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerInternal.h +++ b/tools/phasar-cli/Controller/AnalysisControllerInternal.h @@ -10,12 +10,9 @@ #ifndef PHASAR_CONTROLLER_ANALYSISCONTROLLERINTERNAL_H #define PHASAR_CONTROLLER_ANALYSISCONTROLLERINTERNAL_H -#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" -#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" -#include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" +#include "phasar/ControlFlow/ICFG.h" #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" #include "phasar/PhasarLLVM/TaintConfig/LLVMTaintConfig.h" -#include "phasar/Utils/ChronoUtils.h" #include "phasar/Utils/IO.h" #include "phasar/Utils/Timer.h" @@ -79,8 +76,7 @@ static void emitRequestedDataFlowResults(AnalysisController &Data, T &Solver) { const auto PrintResult = [&ResultDirectory](llvm::StringRef Suffix, auto WithStream) { if (!ResultDirectory.empty()) { - if (auto OFS = - openFileStream(llvm::Twine(ResultDirectory.string()) + Suffix)) { + if (auto OFS = openFileStream(ResultDirectory + Suffix)) { WithStream(*OFS); } } else { diff --git a/tools/phasar-cli/Controller/AnalysisControllerXIFDSCFLEnvTaint.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIFDSCFLEnvTaint.cpp index c2952b43f6..2396c5bf90 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXIFDSCFLEnvTaint.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIFDSCFLEnvTaint.cpp @@ -52,7 +52,7 @@ void controller::executeIFDSCFLEnvTaint(AnalysisController &Data) { HasResultsDir = !Data.ResultDirectory.empty()]( const llvm::Twine &FileName, auto Handler) { if (HasResultsDir) { - if (auto OFS = openFileStream(Data.ResultDirectory.string() + FileName)) { + if (auto OFS = openFileStream(Data.ResultDirectory + FileName)) { Handler(*OFS); } } else { diff --git a/tools/phasar-cli/Controller/AnalysisControllerXMonoIFDSTaint.cpp b/tools/phasar-cli/Controller/AnalysisControllerXMonoIFDSTaint.cpp index 2e73375aa6..eb170f7a93 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXMonoIFDSTaint.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXMonoIFDSTaint.cpp @@ -8,6 +8,7 @@ *****************************************************************************/ #include "phasar/DataFlow/MonoIfds/MonoIFDSSolver.h" +#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" #include "phasar/PhasarLLVM/DataFlow/MonoIfds/Problems/MonoIFDSTaintAnalysis.h" #include "phasar/PhasarLLVM/Pointer/FilteredLLVMAliasIterator.h" diff --git a/tools/phasar-cli/phasar-cli.cpp b/tools/phasar-cli/phasar-cli.cpp index 86f33850eb..66ab2e28a3 100644 --- a/tools/phasar-cli/phasar-cli.cpp +++ b/tools/phasar-cli/phasar-cli.cpp @@ -26,15 +26,18 @@ #include "phasar/Utils/Soundness.h" #include "phasar/Utils/Utilities.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/Support/WithColor.h" #include "Controller/AnalysisController.h" #include "Controller/AnalysisControllerEmitterOptions.h" #include -#include #include #include #include @@ -74,7 +77,7 @@ cl::alias QuietAlias("quiet", cl::aliasopt(SilentOpt), cl::desc("Alias for --silent"), cl::cat(PsrCat)); PSR_SHORTLONG_OPTION(ModuleOpt, std::string, "m", "module", - "Path to the LLVM IR module under analysis"); + "Path to the LLVM IR module under analysis", cl::Required); PSR_SHORTLONG_OPTION_TYPE( EntryOpt, cl::list, "E", "entry-points", @@ -272,80 +275,93 @@ PSR_SHORTLONG_OPTION(PammOutOpt, std::string, "A", "pamm-out", "Filename for PAMM's gathered data", cl::init("PAMM_data.json"), cl::cat(PsrCat), cl::Hidden); -// void validateParamConfigFile(const std::string &Config) { -// if (!(std::filesystem::exists(Config) && -// !std::filesystem::is_directory(Config))) { -// llvm::errs() << "PhASAR configuration '" << Config << "' does not -// exist!\n"; exit(1); -// } -// } - void validateParamModule() { - if (ModuleOpt.empty()) { - llvm::errs() << "At least one LLVM target module is required!\n"; - exit(1); - } - - std::filesystem::path ModulePath(ModuleOpt.getValue()); - if (!(std::filesystem::exists(ModulePath) && - !std::filesystem::is_directory(ModulePath) && - (ModulePath.extension() == ".ll" || ModulePath.extension() == ".bc"))) { - llvm::errs() << "LLVM module '" << std::filesystem::canonical(ModulePath) - << "' does not exist!\n"; + if (!(llvm::sys::fs::exists(ModuleOpt) && + !llvm::sys::fs::is_directory(ModuleOpt) && + (llvm::is_contained({".bc", ".ll"}, + llvm::sys::path::extension(ModuleOpt))))) { + llvm::SmallString<256> RealModPath; + auto EC = llvm::sys::fs::real_path(ModuleOpt, RealModPath); + llvm::WithColor::error() + << "LLVM module '" << (EC ? ModuleOpt.getValue() : RealModPath.str()) + << "' does not exist!\n"; exit(1); } } void validateParamOutput() { if (!OutDirOpt.empty() && - !std::filesystem::is_directory(OutDirOpt.getValue())) { - llvm::errs() << '\'' << OutDirOpt - << "' does not exist, a valid output directory is required!\n"; + !llvm::sys::fs::is_directory(OutDirOpt.getValue())) { + llvm::WithColor::error() + << '\'' << OutDirOpt + << "' does not exist, a valid output directory is required!\n"; exit(1); } } void validateParamPointerAnalysis() { if (AliasTypeOpt == AliasAnalysisType::Invalid) { - llvm::errs() << "'Invalid' is not a valid pointer analysis!\n"; + llvm::WithColor::error() << "'Invalid' is not a valid pointer analysis!\n"; exit(1); } } void validateParamCallGraphAnalysis() { if (CGTypeOpt == CallGraphAnalysisType::Invalid) { - llvm::errs() << "'Invalid' is not a valid call-graph analysis!\n"; + llvm::WithColor::error() + << "'Invalid' is not a valid call-graph analysis!\n"; exit(1); } } void validateSoundnessFlag() { if (SoundnessOpt == Soundness::Invalid) { - llvm::errs() << "'Invalid' is not a valid soundness level!\n"; + llvm::WithColor::error() << "'Invalid' is not a valid soundness level!\n"; exit(1); } } void validateParamAnalysisConfig() { if (!AnalysisConfigOpt.empty() && - !(std::filesystem::exists(AnalysisConfigOpt.getValue()) && - !std::filesystem::is_directory(AnalysisConfigOpt.getValue()))) { - llvm::errs() << "Analysis configuration '" << AnalysisConfigOpt - << "' does not exist!\n"; + !(llvm::sys::fs::exists(AnalysisConfigOpt.getValue()) && + !llvm::sys::fs::is_directory(AnalysisConfigOpt.getValue()))) { + llvm::WithColor::error() << "Analysis configuration '" << AnalysisConfigOpt + << "' does not exist!\n"; exit(1); } } void validatePTAJsonFile() { if (!LoadPTAFromJsonOpt.empty() && - !(std::filesystem::exists(LoadPTAFromJsonOpt.getValue()) && - !std::filesystem::is_directory(LoadPTAFromJsonOpt.getValue()))) { - llvm::errs() << "Points-to info file '" << LoadPTAFromJsonOpt - << "' does not exist!\n"; + !(llvm::sys::fs::exists(LoadPTAFromJsonOpt.getValue()) && + !llvm::sys::fs::is_directory(LoadPTAFromJsonOpt.getValue()))) { + llvm::WithColor::error() << "Points-to info file '" << LoadPTAFromJsonOpt + << "' does not exist!\n"; exit(1); } } +std::vector setupIRAndEntrypoints(LLVMProjectIRDB &IRDB) { + std::vector EntryPoints = std::move(EntryOpt); + if (EntryPoints.empty()) { + EntryPoints = getDefaultEntryPoints(IRDB); + } + if (AutoGlobalsOpt) { + if (EntryPoints.size() == 1 && EntryPoints.front() == "main") { + GlobalCtorsDtorsModel::buildModel(IRDB, EntryPoints); + EntryPoints = {GlobalCtorsDtorsModel::ModelName.str()}; + } else if (AutoGlobalsOpt.getNumOccurrences() > 0) { + llvm::WithColor::warning() + << "'--auto-globals' is currently not supported for libraries, only " + "for applications with 'main' as entry-point'\n"; + } + } + if (ExternalCallsRewriteOpt) { + ExternCallbackModel::rewriteCalls(IRDB); + } + return EntryPoints; +} + } // anonymous namespace int main(int Argc, const char **Argv) { @@ -359,7 +375,7 @@ int main(int Argc, const char **Argv) { #ifdef DYNAMIC_LOG if (LogSeverityOpt == SeverityLevel::INVALID) { - llvm::errs() << "Invalid log-severity\n"; + llvm::WithColor::error() << "Invalid log-severity\n"; return 1; } if (LogOpt) { @@ -383,15 +399,6 @@ int main(int Argc, const char **Argv) { return 1; } - if (ProjectIdOpt.empty()) { - ProjectIdOpt = std::filesystem::path(ModuleOpt.getValue()) - .filename() - .replace_extension(); - if (ProjectIdOpt.empty()) { - ProjectIdOpt = "default-phasar-project"; - } - } - validateParamModule(); validateParamOutput(); validateParamPointerAnalysis(); @@ -437,9 +444,10 @@ int main(int Argc, const char **Argv) { EmitterOptions |= AnalysisControllerEmitterOptions::EmitCGAsJson; } if (EmitCGAsTextOpt) { - llvm::errs() - << "ERROR: emit-cg-as-text is currently not supported. Did you mean " - "emit-cg-as-dot? For reversible serialization use emit-cg-as-json\n"; + llvm::WithColor::error() + << "'--emit-cg-as-text' is currently not supported. Did you mean " + "'--emit-cg-as-dot'? For reversible serialization use " + "'--emit-cg-as-json'\n"; return 1; } if (EmitPTAAsTextOpt) { @@ -480,22 +488,26 @@ int main(int Argc, const char **Argv) { auto IRDB = std::make_unique( PSR_LAZY(LLVMProjectIRDB::loadOrExit(ModuleOpt))); - std::vector EntryPoints = std::move(EntryOpt); - if (EntryPoints.empty()) { - EntryPoints = getDefaultEntryPoints(*IRDB); - } - if (AutoGlobalsOpt) { - if (EntryPoints.size() == 1 && EntryPoints.front() == "main") { - GlobalCtorsDtorsModel::buildModel(*IRDB, EntryPoints); - EntryPoints = {GlobalCtorsDtorsModel::ModelName.str()}; - } else if (AutoGlobalsOpt.getNumOccurrences() > 0) { - llvm::WithColor::warning() - << "'--auto-globals' is currently not supported for libraries, only " - "for applications with 'main' as entry-point'\n"; + auto EntryPoints = setupIRAndEntrypoints(*IRDB); + + llvm::SmallString<128> ProjectId(llvm::sys::path::filename(ProjectIdOpt)); + if (ProjectId.empty()) { + llvm::sys::path::replace_extension(ProjectId, {}); + if (ProjectId.empty()) { + ProjectId = "default-phasar-project"; } } - if (ExternalCallsRewriteOpt) { - ExternCallbackModel::rewriteCalls(*IRDB); + + llvm::SmallString<128> OutDir(OutDirOpt); + if (!OutDir.empty()) { + // create directory for results + llvm::sys::path::append(OutDir, + ProjectId + llvm::Twine("-") + createTimeStamp()); + auto EC = llvm::sys::fs::create_directory(OutDir); + if (EC) { + llvm::WithColor::error() << EC.message() << '\n'; + return 1; + } } AnalysisController Controller{ @@ -517,15 +529,9 @@ int main(int Argc, const char **Argv) { .Strategy = StrategyOpt, .EmitterOptions = EmitterOptions, .SolverConfig = SolverConfig, - .ProjectID = ProjectIdOpt.getValue(), - .ResultDirectory = OutDirOpt.getValue(), + .ProjectID = std::move(ProjectId), + .ResultDirectory = std::move(OutDir), }; - if (!OutDirOpt.empty()) { - // create directory for results - Controller.ResultDirectory /= - Controller.ProjectID + "-" + createTimeStamp(); - std::filesystem::create_directory(Controller.ResultDirectory); - } Controller.emitRequestedHelperAnalysisResults(); Controller.run(); From a09e6665aba9f230142e2f7158cdb32b9eadb4f1 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Mon, 10 Aug 2026 16:41:30 +0200 Subject: [PATCH 5/7] Remove unnecessary checks from phasar-cli --- tools/phasar-cli/phasar-cli.cpp | 34 --------------------------------- 1 file changed, 34 deletions(-) diff --git a/tools/phasar-cli/phasar-cli.cpp b/tools/phasar-cli/phasar-cli.cpp index 66ab2e28a3..0dd7b72dc9 100644 --- a/tools/phasar-cli/phasar-cli.cpp +++ b/tools/phasar-cli/phasar-cli.cpp @@ -299,28 +299,6 @@ void validateParamOutput() { } } -void validateParamPointerAnalysis() { - if (AliasTypeOpt == AliasAnalysisType::Invalid) { - llvm::WithColor::error() << "'Invalid' is not a valid pointer analysis!\n"; - exit(1); - } -} - -void validateParamCallGraphAnalysis() { - if (CGTypeOpt == CallGraphAnalysisType::Invalid) { - llvm::WithColor::error() - << "'Invalid' is not a valid call-graph analysis!\n"; - exit(1); - } -} - -void validateSoundnessFlag() { - if (SoundnessOpt == Soundness::Invalid) { - llvm::WithColor::error() << "'Invalid' is not a valid soundness level!\n"; - exit(1); - } -} - void validateParamAnalysisConfig() { if (!AnalysisConfigOpt.empty() && !(llvm::sys::fs::exists(AnalysisConfigOpt.getValue()) && @@ -374,10 +352,6 @@ int main(int Argc, const char **Argv) { cl::ParseCommandLineOptions(Argc, Argv); #ifdef DYNAMIC_LOG - if (LogSeverityOpt == SeverityLevel::INVALID) { - llvm::WithColor::error() << "Invalid log-severity\n"; - return 1; - } if (LogOpt) { Logger::initializeStderrLogger(LogSeverityOpt); } else if (!SilentOpt) { @@ -394,16 +368,8 @@ int main(int Argc, const char **Argv) { << "\nA LLVM-based static analysis framework\n\n"; } - if (StrategyOpt == AnalysisStrategy::None) { - llvm::errs() << "Invalid analysis strategy!\n"; - return 1; - } - validateParamModule(); validateParamOutput(); - validateParamPointerAnalysis(); - validateParamCallGraphAnalysis(); - validateSoundnessFlag(); validateParamAnalysisConfig(); validatePTAJsonFile(); From b97c7cc18d9f3fe15268c7c96829c350cd5f8da2 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Mon, 10 Aug 2026 16:59:50 +0200 Subject: [PATCH 6/7] Deduplicate EntryPoints in AnalysisController + some restructuring in phasar-cli --- include/phasar/PhasarLLVM/HelperAnalyses.h | 4 + .../Controller/AnalysisController.h | 5 +- .../AnalysisControllerXIDECSTDIOTS.cpp | 2 +- .../Controller/AnalysisControllerXIDEFIIA.cpp | 2 +- .../Controller/AnalysisControllerXIDEIIA.cpp | 2 +- .../AnalysisControllerXIDELinearConst.cpp | 2 +- .../AnalysisControllerXIDEOpenSSLTS.cpp | 2 +- .../AnalysisControllerXIDESolverTest.cpp | 2 +- .../AnalysisControllerXIDEXTaint.cpp | 2 +- .../AnalysisControllerXIFDSCFLEnvTaint.cpp | 2 +- .../AnalysisControllerXIFDSConst.cpp | 2 +- .../AnalysisControllerXIFDSSolverTest.cpp | 2 +- .../AnalysisControllerXIFDSTaint.cpp | 2 +- .../AnalysisControllerXIFDSType.cpp | 2 +- .../AnalysisControllerXIFDSUninit.cpp | 2 +- ...AnalysisControllerXInterMonoSolverTest.cpp | 2 +- .../AnalysisControllerXInterMonoTaint.cpp | 2 +- ...alysisControllerXIntraMonoFullConstant.cpp | 4 +- ...AnalysisControllerXIntraMonoSolverTest.cpp | 2 +- .../AnalysisControllerXSparseIFDSTaint.cpp | 3 +- tools/phasar-cli/phasar-cli.cpp | 95 ++++++++++--------- 21 files changed, 80 insertions(+), 63 deletions(-) diff --git a/include/phasar/PhasarLLVM/HelperAnalyses.h b/include/phasar/PhasarLLVM/HelperAnalyses.h index 2db44e853f..8f82b85d8e 100644 --- a/include/phasar/PhasarLLVM/HelperAnalyses.h +++ b/include/phasar/PhasarLLVM/HelperAnalyses.h @@ -79,6 +79,10 @@ class HelperAnalyses { // NOLINT(cppcoreguidelines-special-member-functions) [[nodiscard]] const SCCDependencyGraph &getCGSCCCallers(); [[nodiscard]] const UsedGlobalsHolder & getUsedGlobals(); + [[nodiscard]] const std::vector & + getEntryPoints() const noexcept { + return EntryPoints; + } private: std::unique_ptr IRDB; diff --git a/tools/phasar-cli/Controller/AnalysisController.h b/tools/phasar-cli/Controller/AnalysisController.h index be62613790..3faca34057 100644 --- a/tools/phasar-cli/Controller/AnalysisController.h +++ b/tools/phasar-cli/Controller/AnalysisController.h @@ -25,7 +25,6 @@ struct AnalysisController { HelperAnalyses HA; std::vector DataFlowAnalyses; std::vector AnalysisConfigs; - std::vector EntryPoints; [[maybe_unused]] AnalysisStrategy Strategy{}; AnalysisControllerEmitterOptions EmitterOptions = AnalysisControllerEmitterOptions::None; @@ -42,6 +41,10 @@ struct AnalysisController { void emitRequestedHelperAnalysisResults(); void run(); + + [[nodiscard]] const auto &getEntryPoints() const noexcept { + return HA.getEntryPoints(); + } }; } // namespace psr diff --git a/tools/phasar-cli/Controller/AnalysisControllerXIDECSTDIOTS.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIDECSTDIOTS.cpp index 11f81a3498..ac485154c9 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXIDECSTDIOTS.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIDECSTDIOTS.cpp @@ -17,5 +17,5 @@ using namespace psr; void controller::executeIDECSTDIOTS(AnalysisController &Data) { CSTDFILEIOTypeStateDescription TSDesc; executeIDEAnalysis>( - Data, &TSDesc, Data.EntryPoints); + Data, &TSDesc, Data.getEntryPoints()); } diff --git a/tools/phasar-cli/Controller/AnalysisControllerXIDEFIIA.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIDEFIIA.cpp index 6bc04e31aa..8177577ad8 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXIDEFIIA.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIDEFIIA.cpp @@ -39,6 +39,6 @@ void controller::executeIDEFIIA(AnalysisController &Data) { Current); }; - executeIDEAnalysis(Data, Data.EntryPoints, + executeIDEAnalysis(Data, Data.getEntryPoints(), Generator); } diff --git a/tools/phasar-cli/Controller/AnalysisControllerXIDEIIA.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIDEIIA.cpp index e16390901a..8e5dc741e7 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXIDEIIA.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIDEIIA.cpp @@ -39,6 +39,6 @@ void controller::executeIDEIIA(AnalysisController &Data) { Current); }; - executeIDEAnalysis(Data, Data.EntryPoints, + executeIDEAnalysis(Data, Data.getEntryPoints(), Generator); } diff --git a/tools/phasar-cli/Controller/AnalysisControllerXIDELinearConst.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIDELinearConst.cpp index fc4e95ef56..f9d146d64f 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXIDELinearConst.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIDELinearConst.cpp @@ -14,5 +14,5 @@ using namespace psr; void controller::executeIDELinearConst(AnalysisController &Data) { - executeIDEAnalysis(Data, Data.EntryPoints); + executeIDEAnalysis(Data, Data.getEntryPoints()); } diff --git a/tools/phasar-cli/Controller/AnalysisControllerXIDEOpenSSLTS.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIDEOpenSSLTS.cpp index 9f65b2082a..fc1716bb46 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXIDEOpenSSLTS.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIDEOpenSSLTS.cpp @@ -17,5 +17,5 @@ using namespace psr; void controller::executeIDEOpenSSLTS(AnalysisController &Data) { OpenSSLEVPKDFDescription TSDesc; executeIDEAnalysis>( - Data, &TSDesc, Data.EntryPoints); + Data, &TSDesc, Data.getEntryPoints()); } diff --git a/tools/phasar-cli/Controller/AnalysisControllerXIDESolverTest.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIDESolverTest.cpp index baa3a27d25..07ba5b816d 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXIDESolverTest.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIDESolverTest.cpp @@ -14,5 +14,5 @@ using namespace psr; void controller::executeIDESolverTest(AnalysisController &Data) { - executeIDEAnalysis(Data, Data.EntryPoints); + executeIDEAnalysis(Data, Data.getEntryPoints()); } diff --git a/tools/phasar-cli/Controller/AnalysisControllerXIDEXTaint.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIDEXTaint.cpp index dc03bda7f0..7106b1c7b4 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXIDEXTaint.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIDEXTaint.cpp @@ -16,5 +16,5 @@ using namespace psr; void controller::executeIDEXTaint(AnalysisController &Data) { auto Config = makeTaintConfig(Data); executeIDEAnalysis>(Data, Config, - Data.EntryPoints); + Data.getEntryPoints()); } diff --git a/tools/phasar-cli/Controller/AnalysisControllerXIFDSCFLEnvTaint.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIFDSCFLEnvTaint.cpp index 2396c5bf90..a320f2feff 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXIFDSCFLEnvTaint.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIFDSCFLEnvTaint.cpp @@ -25,7 +25,7 @@ void controller::executeIFDSCFLEnvTaint(AnalysisController &Data) { auto Config = makeTaintConfig(Data); auto UserProblem = createAnalysisProblem( - Data.HA, &Config, Data.EntryPoints, /*TaintMainArgs*/ false, + Data.HA, &Config, Data.getEntryPoints(), /*TaintMainArgs*/ false, /*EnableStrongUpdateStore*/ false); auto Printer = UserProblem.consumePrinter(); auto FieldSensProblem = CFLFieldSensIFDSProblem(&UserProblem); diff --git a/tools/phasar-cli/Controller/AnalysisControllerXIFDSConst.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIFDSConst.cpp index 55a3600d45..733e62a848 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXIFDSConst.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIFDSConst.cpp @@ -14,5 +14,5 @@ using namespace psr; void controller::executeIFDSConst(AnalysisController &Data) { - executeIFDSAnalysis(Data, Data.EntryPoints); + executeIFDSAnalysis(Data, Data.getEntryPoints()); } diff --git a/tools/phasar-cli/Controller/AnalysisControllerXIFDSSolverTest.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIFDSSolverTest.cpp index c8b37c5746..847740b632 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXIFDSSolverTest.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIFDSSolverTest.cpp @@ -14,5 +14,5 @@ using namespace psr; void controller::executeIFDSSolverTest(AnalysisController &Data) { - executeIFDSAnalysis(Data, Data.EntryPoints); + executeIFDSAnalysis(Data, Data.getEntryPoints()); } diff --git a/tools/phasar-cli/Controller/AnalysisControllerXIFDSTaint.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIFDSTaint.cpp index 9d91efd7d0..66898a4530 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXIFDSTaint.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIFDSTaint.cpp @@ -17,6 +17,6 @@ void controller::executeIFDSTaint(AnalysisController &Data) { auto Config = makeTaintConfig(Data); // Note: Don't blindly generate argc and argv. Use a proper taint config // instead - executeIFDSAnalysis(Data, &Config, Data.EntryPoints, + executeIFDSAnalysis(Data, &Config, Data.getEntryPoints(), false); } diff --git a/tools/phasar-cli/Controller/AnalysisControllerXIFDSType.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIFDSType.cpp index 8c8410e996..89e7b76586 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXIFDSType.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIFDSType.cpp @@ -14,5 +14,5 @@ using namespace psr; void controller::executeIFDSType(AnalysisController &Data) { - executeIFDSAnalysis(Data, Data.EntryPoints); + executeIFDSAnalysis(Data, Data.getEntryPoints()); } diff --git a/tools/phasar-cli/Controller/AnalysisControllerXIFDSUninit.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIFDSUninit.cpp index 7e47898081..1e111f96bf 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXIFDSUninit.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIFDSUninit.cpp @@ -14,5 +14,5 @@ using namespace psr; void controller::executeIFDSUninitVar(AnalysisController &Data) { - executeIFDSAnalysis(Data, Data.EntryPoints); + executeIFDSAnalysis(Data, Data.getEntryPoints()); } diff --git a/tools/phasar-cli/Controller/AnalysisControllerXInterMonoSolverTest.cpp b/tools/phasar-cli/Controller/AnalysisControllerXInterMonoSolverTest.cpp index 3b2b8e78a7..d1d0a7f02f 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXInterMonoSolverTest.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXInterMonoSolverTest.cpp @@ -14,5 +14,5 @@ using namespace psr; void controller::executeInterMonoSolverTest(AnalysisController &Data) { - executeInterMonoAnalysis(Data, Data.EntryPoints); + executeInterMonoAnalysis(Data, Data.getEntryPoints()); } diff --git a/tools/phasar-cli/Controller/AnalysisControllerXInterMonoTaint.cpp b/tools/phasar-cli/Controller/AnalysisControllerXInterMonoTaint.cpp index dbbb19d2aa..946f809de3 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXInterMonoTaint.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXInterMonoTaint.cpp @@ -16,5 +16,5 @@ using namespace psr; void controller::executeInterMonoTaint(AnalysisController &Data) { auto Config = makeTaintConfig(Data); executeInterMonoAnalysis(Data, Config, - Data.EntryPoints); + Data.getEntryPoints()); } diff --git a/tools/phasar-cli/Controller/AnalysisControllerXIntraMonoFullConstant.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIntraMonoFullConstant.cpp index 8c17bbb9ff..7e8f714617 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXIntraMonoFullConstant.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIntraMonoFullConstant.cpp @@ -14,6 +14,6 @@ using namespace psr; void controller::executeIntraMonoFullConstant(AnalysisController &Data) { - executeIntraMonoAnalysis(Data, - Data.EntryPoints); + executeIntraMonoAnalysis( + Data, Data.getEntryPoints()); } diff --git a/tools/phasar-cli/Controller/AnalysisControllerXIntraMonoSolverTest.cpp b/tools/phasar-cli/Controller/AnalysisControllerXIntraMonoSolverTest.cpp index c1043a6f1a..a4f143197f 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXIntraMonoSolverTest.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXIntraMonoSolverTest.cpp @@ -14,5 +14,5 @@ using namespace psr; void controller::executeIntraMonoSolverTest(AnalysisController &Data) { - executeIntraMonoAnalysis(Data, Data.EntryPoints); + executeIntraMonoAnalysis(Data, Data.getEntryPoints()); } diff --git a/tools/phasar-cli/Controller/AnalysisControllerXSparseIFDSTaint.cpp b/tools/phasar-cli/Controller/AnalysisControllerXSparseIFDSTaint.cpp index 4d3b8623b8..17097b8e30 100644 --- a/tools/phasar-cli/Controller/AnalysisControllerXSparseIFDSTaint.cpp +++ b/tools/phasar-cli/Controller/AnalysisControllerXSparseIFDSTaint.cpp @@ -15,5 +15,6 @@ using namespace psr; void controller::executeSparseIFDSTaint(AnalysisController &Data) { auto Config = makeTaintConfig(Data); - executeSparseIFDSAnalysis(Data, &Config, Data.EntryPoints); + executeSparseIFDSAnalysis(Data, &Config, + Data.getEntryPoints()); } diff --git a/tools/phasar-cli/phasar-cli.cpp b/tools/phasar-cli/phasar-cli.cpp index 0dd7b72dc9..62f997aaf2 100644 --- a/tools/phasar-cli/phasar-cli.cpp +++ b/tools/phasar-cli/phasar-cli.cpp @@ -340,45 +340,9 @@ std::vector setupIRAndEntrypoints(LLVMProjectIRDB &IRDB) { return EntryPoints; } -} // anonymous namespace - -int main(int Argc, const char **Argv) { - PSR_INITIALIZER(Argc, Argv); - - cl::SetVersionPrinter([](llvm::raw_ostream &OS) { - OS << "PhASAR " << PhasarConfig::PhasarVersion() << '\n'; - }); - cl::HideUnrelatedOptions(PsrCat); - cl::ParseCommandLineOptions(Argc, Argv); - -#ifdef DYNAMIC_LOG - if (LogOpt) { - Logger::initializeStderrLogger(LogSeverityOpt); - } else if (!SilentOpt) { - Logger::initializeStderrLogger(SeverityLevel::ERROR); - } - for (const auto &LogCat : LogCategoriesOpt) { - Logger::initializeStderrLogger(LogSeverityOpt, LogCat); - } -#endif - - // Vanity header - if (!SilentOpt) { - llvm::outs() << "PhASAR " << PhasarConfig::PhasarVersion() - << "\nA LLVM-based static analysis framework\n\n"; - } - - validateParamModule(); - validateParamOutput(); - validateParamAnalysisConfig(); - validatePTAJsonFile(); - - [[maybe_unused]] auto &PConfig = PhasarConfig::getPhasarConfig(); - - // setup the emitter options to display the computed analysis results +[[nodiscard]] AnalysisControllerEmitterOptions setupEmitterOptions() { auto EmitterOptions = AnalysisControllerEmitterOptions::None; - IFDSIDESolverConfig SolverConfig{}; if (EmitIROpt) { EmitterOptions |= AnalysisControllerEmitterOptions::EmitIR; } @@ -414,7 +378,7 @@ int main(int Argc, const char **Argv) { << "'--emit-cg-as-text' is currently not supported. Did you mean " "'--emit-cg-as-dot'? For reversible serialization use " "'--emit-cg-as-json'\n"; - return 1; + exit(1); } if (EmitPTAAsTextOpt) { EmitterOptions |= AnalysisControllerEmitterOptions::EmitPTAAsText; @@ -431,13 +395,57 @@ int main(int Argc, const char **Argv) { if (EmitStatsAsJsonOpt) { EmitterOptions |= AnalysisControllerEmitterOptions::EmitStatisticsAsJson; } + return EmitterOptions; +} +[[nodiscard]] IFDSIDESolverConfig setupSolverConfig() { + IFDSIDESolverConfig SolverConfig{}; SolverConfig.setFollowReturnsPastSeeds(FollowReturnPastSeedsOpt); SolverConfig.setAutoAddZero(AutoAddZeroOpt); SolverConfig.setComputeValues(ComputeValuesOpt); SolverConfig.setRecordEdges(RecordEdgesOpt || EmitESGAsDotOpt); SolverConfig.setComputePersistedSummaries(PersistedSummariesOpt); SolverConfig.setEmitESG(EmitESGAsDotOpt); + return SolverConfig; +} + +} // anonymous namespace + +int main(int Argc, const char **Argv) { + PSR_INITIALIZER(Argc, Argv); + + cl::SetVersionPrinter([](llvm::raw_ostream &OS) { + OS << "PhASAR " << PhasarConfig::PhasarVersion() << '\n'; + }); + cl::HideUnrelatedOptions(PsrCat); + cl::ParseCommandLineOptions(Argc, Argv); + +#ifdef DYNAMIC_LOG + if (LogOpt) { + Logger::initializeStderrLogger(LogSeverityOpt); + } else if (!SilentOpt) { + Logger::initializeStderrLogger(SeverityLevel::ERROR); + } + for (const auto &LogCat : LogCategoriesOpt) { + Logger::initializeStderrLogger(LogSeverityOpt, LogCat); + } +#endif + + // Vanity header + if (!SilentOpt) { + llvm::outs() << "PhASAR " << PhasarConfig::PhasarVersion() + << "\nA LLVM-based static analysis framework\n\n"; + } + + validateParamModule(); + validateParamOutput(); + validateParamAnalysisConfig(); + validatePTAJsonFile(); + + [[maybe_unused]] auto &PConfig = PhasarConfig::getPhasarConfig(); + + // setup the emitter options to display the computed analysis results + auto EmitterOptions = setupEmitterOptions(); std::optional PrecomputedAliasSet; if (!LoadPTAFromJsonOpt.empty()) { @@ -464,9 +472,9 @@ int main(int Argc, const char **Argv) { } } + // create directory for results llvm::SmallString<128> OutDir(OutDirOpt); if (!OutDir.empty()) { - // create directory for results llvm::sys::path::append(OutDir, ProjectId + llvm::Twine("-") + createTimeStamp()); auto EC = llvm::sys::fs::create_directory(OutDir); @@ -478,23 +486,24 @@ int main(int Argc, const char **Argv) { AnalysisController Controller{ .HA = HelperAnalyses( - std::move(IRDB), EntryPoints, + std::move(IRDB), std::move(EntryPoints), { + .PrecomputedPTS = std::move(PrecomputedAliasSet), .PrecomputedCG = std::move(PrecomputedCallGraph), .PTATy = AliasTypeOpt, .UFAATy = UFAliasTypeOpt, .CGTy = CGTypeOpt, .SoundnessLevel = SoundnessOpt, - .AutoGlobalSupport = false, + .AutoGlobalSupport = + false, // already handled in setupIRAndEntrypoints() .AllowLazyPTS = !AnalysisController::needsToEmitPTA(EmitterOptions), }), .DataFlowAnalyses = DataFlowAnalysisOpt, .AnalysisConfigs = {AnalysisConfigOpt.getValue()}, - .EntryPoints = std::move(EntryPoints), .Strategy = StrategyOpt, .EmitterOptions = EmitterOptions, - .SolverConfig = SolverConfig, + .SolverConfig = setupSolverConfig(), .ProjectID = std::move(ProjectId), .ResultDirectory = std::move(OutDir), }; From e7c0bb10b973c027942a301cc08e10b160d0adeb Mon Sep 17 00:00:00 2001 From: Fabian Schiebel <52407375+fabianbs96@users.noreply.github.com> Date: Mon, 10 Aug 2026 18:28:36 +0200 Subject: [PATCH 7/7] Fix compilation of phasar-cli with LLVM 16 --- tools/phasar-cli/phasar-cli.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/phasar-cli/phasar-cli.cpp b/tools/phasar-cli/phasar-cli.cpp index 62f997aaf2..23a2b649c0 100644 --- a/tools/phasar-cli/phasar-cli.cpp +++ b/tools/phasar-cli/phasar-cli.cpp @@ -278,7 +278,7 @@ PSR_SHORTLONG_OPTION(PammOutOpt, std::string, "A", "pamm-out", void validateParamModule() { if (!(llvm::sys::fs::exists(ModuleOpt) && !llvm::sys::fs::is_directory(ModuleOpt) && - (llvm::is_contained({".bc", ".ll"}, + (llvm::is_contained(llvm::ArrayRef{".bc", ".ll"}, llvm::sys::path::extension(ModuleOpt))))) { llvm::SmallString<256> RealModPath; auto EC = llvm::sys::fs::real_path(ModuleOpt, RealModPath);