1//===- SSAFAnalyzer.cpp - SSAF Analyzer Tool ------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the SSAF analyzer tool that runs whole-program
10// analyses over an LUSummary and writes the resulting WPASuite to an
11// output file.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
16#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.h"
17#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
18#include "clang/ScalableStaticAnalysis/SSAFForceLinker.h" // IWYU pragma: keep
19#include "clang/ScalableStaticAnalysis/Tool/Utils.h"
20#include "llvm/ADT/SmallVector.h"
21#include "llvm/Support/CommandLine.h"
22#include "llvm/Support/InitLLVM.h"
23#include <memory>
24#include <string>
25
26using namespace llvm;
27using namespace clang::ssaf;
28
29namespace {
30
31//===----------------------------------------------------------------------===//
32// Command-Line Options
33//===----------------------------------------------------------------------===//
34
35cl::OptionCategory SsafAnalyzerCategory("clang-ssaf-analyzer options");
36
37cl::opt<std::string> InputPath(cl::Positional, cl::desc("<input file>"),
38 cl::Required, cl::cat(SsafAnalyzerCategory));
39
40cl::opt<std::string> OutputPath("o", cl::desc("Output file path"),
41 cl::value_desc("path"), cl::Required,
42 cl::cat(SsafAnalyzerCategory));
43
44cl::list<std::string> AnalysisNames("a", cl::desc("Analysis name to run"),
45 cl::value_desc("name"),
46 cl::cat(SsafAnalyzerCategory));
47
48cl::alias AnalysisNamesAlias("analysis", cl::aliasopt(AnalysisNames),
49 cl::desc("Alias for -a"));
50
51cl::list<std::string> LoadPlugins("load",
52 cl::desc("Load a plugin shared library"),
53 cl::value_desc("path"),
54 cl::cat(SsafAnalyzerCategory));
55
56cl::alias LoadPluginsAlias("l", cl::aliasopt(LoadPlugins),
57 cl::desc("Alias for --load"));
58
59//===----------------------------------------------------------------------===//
60// Input Validation
61//===----------------------------------------------------------------------===//
62
63struct AnalyzerInput {
64 FormatFile InputFile;
65 FormatFile OutputFile;
66 llvm::SmallVector<AnalysisName> Names;
67};
68
69AnalyzerInput validate() {
70 AnalyzerInput AI;
71
72 // Validate the input path.
73 AI.InputFile = FormatFile::fromInputPath(Path: InputPath);
74
75 // Validate the output path.
76 AI.OutputFile = FormatFile::fromOutputPath(Path: OutputPath);
77
78 // Build and validate analysis names.
79 for (const auto &Name : AnalysisNames) {
80 if (Name.empty()) {
81 fail(Msg: "analysis name must not be empty");
82 }
83 AI.Names.push_back(Elt: AnalysisName(Name));
84 }
85
86 return AI;
87}
88
89//===----------------------------------------------------------------------===//
90// Analysis Pipeline
91//===----------------------------------------------------------------------===//
92
93void analyze(const AnalyzerInput &AI) {
94 // Read the LUSummary.
95 auto ExpectedLU = AI.InputFile.Format->readLUSummary(Path: AI.InputFile.Path);
96 if (!ExpectedLU) {
97 fail(Err: ExpectedLU.takeError());
98 }
99
100 // Run analyses. If specific names were given, run only those;
101 // otherwise run all registered analyses.
102 AnalysisDriver Driver(std::make_unique<LUSummary>(args: std::move(*ExpectedLU)));
103 auto ExpectedSuite =
104 AI.Names.empty() ? std::move(Driver).run() : Driver.run(Names: AI.Names);
105 if (!ExpectedSuite) {
106 fail(Err: ExpectedSuite.takeError());
107 }
108
109 // Write the WPASuite.
110 if (auto Err = AI.OutputFile.Format->writeWPASuite(Suite: *ExpectedSuite,
111 Path: AI.OutputFile.Path)) {
112 fail(Err: std::move(Err));
113 }
114}
115
116} // namespace
117
118//===----------------------------------------------------------------------===//
119// Driver
120//===----------------------------------------------------------------------===//
121
122int main(int argc, const char **argv) {
123 llvm::StringRef ToolHeading = "SSAF Analyzer";
124
125 InitLLVM X(argc, argv);
126 initTool(argc, argv, Version: "0.1", Category&: SsafAnalyzerCategory, ToolHeading);
127
128 loadPlugins(Paths: LoadPlugins);
129
130 AnalyzerInput AI = validate();
131 analyze(AI);
132
133 return 0;
134}
135