From: Anna Zaks
Date: Mon, 7 Nov 2011 05:36:29 +0000 (+0000)
Subject: [analyzer] Add overview and checker registration to the checker developer manual.
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=464ef2e2dcbaf03c8a19ce116fb5e5d64bc210e8;p=clang
[analyzer] Add overview and checker registration to the checker developer manual.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143911 91177308-0d34-0410-b5e6-96231b3b80d8
---
diff --git a/www/analyzer/checker_dev_manual.html b/www/analyzer/checker_dev_manual.html
index b31b11b477..c079f33d6d 100644
--- a/www/analyzer/checker_dev_manual.html
+++ b/www/analyzer/checker_dev_manual.html
@@ -28,8 +28,9 @@ for general developer guidelines and information.
- Getting Started
- - Static Analyzer Overview
+ - Analyzer Overview
- Idea for a Checker
+ - Checker Registration
- Checker Skeleton
- Exploded Node
- Bug Reports
@@ -40,16 +41,19 @@ for general developer guidelines and information.
Getting Started
- - To check out the source code and build the project, follow steps 1-4 of the Clang Getting Started
+
- To check out the source code and build the project, follow steps 1-4 of
+ the Clang Getting Started
page.
- The analyzer source code is located under the Clang source tree:
$ cd llvm/tools/clang
-
See: include/clang/StaticAnalyzer, lib/StaticAnalyzer, test/Analysis.
+
See: include/clang/StaticAnalyzer, lib/StaticAnalyzer,
+ test/Analysis.
- - The analyzer regression tests can be executed from the Clang's build directory:
+
- The analyzer regression tests can be executed from the Clang's build
+ directory:
$ cd ../../../; cd build/tools/clang; TESTDIRS=Analysis make test
@@ -64,7 +68,8 @@ for general developer guidelines and information.
$ clang -cc1 -analyzer-checker-help
- - See the analyzer help for different output formats, fine tuning, and debug options:
+
- See the analyzer help for different output formats, fine tuning, and
+ debug options:
$ clang -cc1 -help | grep "analyzer"
@@ -72,45 +77,126 @@ for general developer guidelines and information.
Static Analyzer Overview
- ExplidedGraph, ExplodedNode (ProgramPoint, State)
- Engine-Checker Interaction
- Symbols
+ The analyzer core performs symbolic execution of the given program. All the
+ input values are represented with symbolic values; further, the engine deduces
+ the values of all the expressions in the program based on the input symbols
+ and the path. The execution is path sensitive and every possible path through
+ the program is explored. The explored execution traces are represented with
+ ExplidedGraph object.
+ Each node of the graph is
+ ExplodedNode,
+ which consists of a ProgramPoint and a ProgramState.
+
+ ProgramPoint
+ represents the corresponding location in the program (or the CFG graph).
+ ProgramPoint is also used to record additional information on
+ when/how the state was added. For example, PostPurgeDeadSymbolsKind
+ kind means that the state is the result of purging dead symbols - the
+ analyzer's equivalent of garbage collection.
+
+ ProgramState
+ represents abstract state of the program. It consists of:
+
+ - Environment - a mapping from source code expressions to symbolic
+ values
+
- Store - a mapping from memory locations to symbolic values
+
- GenericDataMap - constraints on symbolic values
+
-
+
+ Checkers are not merely passive receivers of the analyzer core changes - they
+ actively participate in the ProgramState construction through the
+ GenericDataMap which can be used to store the checker-defined part
+ of the state. Each time the analyzer engine explores a new statement, it
+ notifies each checker registered to listen for that statement, giving it an
+ opportunity to either report a bug or modify the state. (As a rule of thumb,
+ the checker itself should be stateless.) The checkers are called one after another
+ in the predefined order; thus, calling all the checkers adds a chain to the
+ ExplodedGraph.
+
Idea for a Checker
- Here are several questions which you should consider when evaluating your checker idea:
+ Here are several questions which you should consider when evaluating your
+ checker idea:
- - Can the check be effectively implemented without path-sensitive analysis? See AST Visitors.
+ - Can the check be effectively implemented without path-sensitive
+ analysis? See AST Visitors.
- How high the false positive rate is going to be? Looking at the occurrences
- of the issue you want to write a checker for in the existing code bases might give you some
- ideas.
+ of the issue you want to write a checker for in the existing code bases might
+ give you some ideas.
- How the current limitations of the analysis will effect the false alarm
rate? Currently, the analyzer only reasons about one procedure at a time (no
- inter-procedural analysis). Also, it uses a simple range tracking based solver to model symbolic
- execution.
+ inter-procedural analysis). Also, it uses a simple range tracking based
+ solver to model symbolic execution.
- Consult the Bugzilla database
to get some ideas for new checkers and consider starting with improving/fixing
bugs in the existing checkers.
+Checker Registration
+ All checker implementation files are located in clang/lib/StaticAnalyzer/Checkers
+ folder. Follow the steps below to register a new checker with the analyzer.
+
+ - Create a new checker implementation file, for example ./lib/StaticAnalyzer/Checkers/NewChecker.cpp
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class NewChecker: public Checker< check::PreStmt > {
+public:
+ void checkPreStmt(const CallExpr *CE, CheckerContext &Ctx) const {}
+}
+}
+void ento::registerNewChecker(CheckerManager &mgr) {
+ mgr.registerChecker();
+}
+
+
+ - Pick the package name for your checker and add the registration code to
+./lib/StaticAnalyzer/Checkers/Checkers.td. Note, all checkers should
+first be developed as experimental. Suppose our new checker performs security
+related checks, then we should add the following lines under
+SecurityExperimental package:
+
+let ParentPackage = SecurityExperimental in {
+...
+def NewChecker : Checker<"NewChecker">,
+ HelpText<"This text should give a short description of the checks performed.">,
+ DescFile<"NewChecker.cpp">;
+...
+} // end "security.experimental"
+
+
+ - Make the source code file visible to CMake by adding it to
+./lib/StaticAnalyzer/Checkers/CMakeLists.txt.
+
+
- Compile and see your checker in the list of available checkers by running:
+$clang -cc1 -analyzer-checker-help
+
+
+
Checker Skeleton
- The source code for all the checkers goes into clang/lib/StaticAnalyzer/Checkers.
There are two main decisions you need to make:
- Which events the checker should be tracking.
- - What data you want to store as part of the checker-specific program state. Try to minimize the checker state as much as possible.
+ - What data you want to store as part of the checker-specific program
+ state. Try to minimize the checker state as much as possible.
- Describe the registration process.
Bug Reports
AST Visitors
Some checks might not require path-sensitivity to be effective. Simple AST walk
- might be sufficient. If that is the case, consider implementing a Clang compiler warning.
- On the other hand, a check might not be acceptable as a compiler
+ might be sufficient. If that is the case, consider implementing a Clang
+ compiler warning. On the other hand, a check might not be acceptable as a compiler
warning; for example, because of a relatively high false positive rate. In this
situation, AST callbacks checkASTDecl and
checkASTCodeBody are your best friends.
@@ -126,7 +212,8 @@ for general developer guidelines and information.
Useful Commands/Debugging Hints
-
-While investigating a checker-related issue, instruct the analyzer to only execute a single checker:
+While investigating a checker-related issue, instruct the analyzer to only
+execute a single checker:
$ clang -cc1 -analyze -analyzer-checker=osx.KeychainAPI test.c
@@ -150,19 +237,26 @@ $ clang -cc1 -analyzer-checker-help | grep "debug"
-
-To see which function is failing while processing a large file use -analyzer-display-progress option.
+To see which function is failing while processing a large file use
+-analyzer-display-progress option.
-
-While debugging execute clang -cc1 -analyze -analyzer-checker=core instead of clang --analyze, as the later would call the compiler in a separate process.
+While debugging execute clang -cc1 -analyze -analyzer-checker=core
+instead of clang --analyze, as the later would call the compiler
+in a separate process.
-
-To view ExplodedGraph (the state graph explored by the analyzer) while debugging, goto a frame that has clang::ento::ExprEngine object and execute:
+To view ExplodedGraph (the state graph explored by the analyzer) while
+debugging, goto a frame that has clang::ento::ExprEngine object and
+execute:
(gdb) p ViewGraph(0)
-
-To see clang::Expr while debugging use the following command. If you pass in a SourceManager object, it will also dump the corresponding line in the source code.
+To see clang::Expr while debugging use the following command. If you
+pass in a SourceManager object, it will also dump the corresponding line in the
+source code.
(gdb) p E->dump()