210 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
			
		
		
	
	
			210 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
| ============
 | |
| Debug Checks
 | |
| ============
 | |
| 
 | |
| .. contents::
 | |
|    :local:
 | |
| 
 | |
| The analyzer contains a number of checkers which can aid in debugging. Enable
 | |
| them by using the "-analyzer-checker=" flag, followed by the name of the
 | |
| checker.
 | |
| 
 | |
| 
 | |
| General Analysis Dumpers
 | |
| ========================
 | |
| 
 | |
| These checkers are used to dump the results of various infrastructural analyses
 | |
| to stderr. Some checkers also have "view" variants, which will display a graph
 | |
| using a 'dot' format viewer (such as Graphviz on OS X) instead.
 | |
| 
 | |
| - debug.DumpCallGraph, debug.ViewCallGraph: Show the call graph generated for
 | |
|   the current translation unit. This is used to determine the order in which to
 | |
|   analyze functions when inlining is enabled.
 | |
| 
 | |
| - debug.DumpCFG, debug.ViewCFG: Show the CFG generated for each top-level
 | |
|   function being analyzed.
 | |
| 
 | |
| - debug.DumpDominators: Shows the dominance tree for the CFG of each top-level
 | |
|   function.
 | |
| 
 | |
| - debug.DumpLiveVars: Show the results of live variable analysis for each
 | |
|   top-level function being analyzed.
 | |
| 
 | |
| - debug.ViewExplodedGraph: Show the Exploded Graphs generated for the
 | |
|   analysis of different functions in the input translation unit. When there
 | |
|   are several functions analyzed, display one graph per function. Beware 
 | |
|   that these graphs may grow very large, even for small functions.
 | |
| 
 | |
| Path Tracking
 | |
| =============
 | |
| 
 | |
| These checkers print information about the path taken by the analyzer engine.
 | |
| 
 | |
| - debug.DumpCalls: Prints out every function or method call encountered during a
 | |
|   path traversal. This is indented to show the call stack, but does NOT do any
 | |
|   special handling of branches, meaning different paths could end up
 | |
|   interleaved.
 | |
| 
 | |
| - debug.DumpTraversal: Prints the name of each branch statement encountered
 | |
|   during a path traversal ("IfStmt", "WhileStmt", etc). Currently used to check
 | |
|   whether the analysis engine is doing BFS or DFS.
 | |
| 
 | |
| 
 | |
| State Checking
 | |
| ==============
 | |
| 
 | |
| These checkers will print out information about the analyzer state in the form
 | |
| of analysis warnings. They are intended for use with the -verify functionality
 | |
| in regression tests.
 | |
| 
 | |
| - debug.TaintTest: Prints out the word "tainted" for every expression that
 | |
|   carries taint. At the time of this writing, taint was only introduced by the
 | |
|   checks under experimental.security.taint.TaintPropagation; this checker may
 | |
|   eventually move to the security.taint package.
 | |
| 
 | |
| - debug.ExprInspection: Responds to certain function calls, which are modeled
 | |
|   after builtins. These function calls should affect the program state other
 | |
|   than the evaluation of their arguments; to use them, you will need to declare
 | |
|   them within your test file. The available functions are described below.
 | |
| 
 | |
| (FIXME: debug.ExprInspection should probably be renamed, since it no longer only
 | |
| inspects expressions.)
 | |
| 
 | |
| 
 | |
| ExprInspection checks
 | |
| ---------------------
 | |
| 
 | |
| - void clang_analyzer_eval(bool);
 | |
| 
 | |
|   Prints TRUE if the argument is known to have a non-zero value, FALSE if the
 | |
|   argument is known to have a zero or null value, and UNKNOWN if the argument
 | |
|   isn't sufficiently constrained on this path.  You can use this to test other
 | |
|   values by using expressions like "x == 5".  Note that this functionality is
 | |
|   currently DISABLED in inlined functions, since different calls to the same
 | |
|   inlined function could provide different information, making it difficult to
 | |
|   write proper -verify directives.
 | |
| 
 | |
|   In C, the argument can be typed as 'int' or as '_Bool'.
 | |
| 
 | |
|   Example usage::
 | |
| 
 | |
|     clang_analyzer_eval(x); // expected-warning{{UNKNOWN}}
 | |
|     if (!x) return;
 | |
|     clang_analyzer_eval(x); // expected-warning{{TRUE}}
 | |
| 
 | |
| 
 | |
| - void clang_analyzer_checkInlined(bool);
 | |
| 
 | |
|   If a call occurs within an inlined function, prints TRUE or FALSE according to
 | |
|   the value of its argument. If a call occurs outside an inlined function,
 | |
|   nothing is printed.
 | |
| 
 | |
|   The intended use of this checker is to assert that a function is inlined at
 | |
|   least once (by passing 'true' and expecting a warning), or to assert that a
 | |
|   function is never inlined (by passing 'false' and expecting no warning). The
 | |
|   argument is technically unnecessary but is intended to clarify intent.
 | |
| 
 | |
|   You might wonder why we can't print TRUE if a function is ever inlined and
 | |
|   FALSE if it is not. The problem is that any inlined function could conceivably
 | |
|   also be analyzed as a top-level function (in which case both TRUE and FALSE
 | |
|   would be printed), depending on the value of the -analyzer-inlining option.
 | |
| 
 | |
|   In C, the argument can be typed as 'int' or as '_Bool'.
 | |
| 
 | |
|   Example usage::
 | |
| 
 | |
|     int inlined() {
 | |
|       clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
 | |
|       return 42;
 | |
|     }
 | |
|     
 | |
|     void topLevel() {
 | |
|       clang_analyzer_checkInlined(false); // no-warning (not inlined)
 | |
|       int value = inlined();
 | |
|       // This assertion will not be valid if the previous call was not inlined.
 | |
|       clang_analyzer_eval(value == 42); // expected-warning{{TRUE}}
 | |
|     }
 | |
| 
 | |
| - void clang_analyzer_warnIfReached();
 | |
| 
 | |
|   Generate a warning if this line of code gets reached by the analyzer.
 | |
| 
 | |
|   Example usage::
 | |
| 
 | |
|     if (true) {
 | |
|       clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
 | |
|     }
 | |
|     else {
 | |
|       clang_analyzer_warnIfReached();  // no-warning
 | |
|     }
 | |
| 
 | |
| - void clang_analyzer_warnOnDeadSymbol(int);
 | |
| 
 | |
|   Subscribe for a delayed warning when the symbol that represents the value of
 | |
|   the argument is garbage-collected by the analyzer.
 | |
| 
 | |
|   When calling 'clang_analyzer_warnOnDeadSymbol(x)', if value of 'x' is a
 | |
|   symbol, then this symbol is marked by the ExprInspection checker. Then,
 | |
|   during each garbage collection run, the checker sees if the marked symbol is
 | |
|   being collected and issues the 'SYMBOL DEAD' warning if it does.
 | |
|   This way you know where exactly, up to the line of code, the symbol dies.
 | |
| 
 | |
|   It is unlikely that you call this function after the symbol is already dead,
 | |
|   because the very reference to it as the function argument prevents it from
 | |
|   dying. However, if the argument is not a symbol but a concrete value,
 | |
|   no warning would be issued.
 | |
| 
 | |
|   Example usage::
 | |
| 
 | |
|     do {
 | |
|       int x = generate_some_integer();
 | |
|       clang_analyzer_warnOnDeadSymbol(x);
 | |
|     } while(0);  // expected-warning{{SYMBOL DEAD}}
 | |
| 
 | |
| 
 | |
| - void clang_analyzer_explain(a single argument of any type);
 | |
| 
 | |
|   This function explains the value of its argument in a human-readable manner
 | |
|   in the warning message. You can make as many overrides of its prototype
 | |
|   in the test code as necessary to explain various integral, pointer,
 | |
|   or even record-type values.
 | |
| 
 | |
|   Example usage::
 | |
| 
 | |
|     void clang_analyzer_explain(int);
 | |
|     void clang_analyzer_explain(void *);
 | |
| 
 | |
|     void foo(int param, void *ptr) {
 | |
|       clang_analyzer_explain(param); // expected-warning{{argument 'param'}}
 | |
|       if (!ptr)
 | |
|         clang_analyzer_explain(ptr); // expected-warning{{memory address '0'}}
 | |
|     }
 | |
| 
 | |
| - size_t clang_analyzer_getExtent(void *);
 | |
| 
 | |
|   This function returns the value that represents the extent of a memory region
 | |
|   pointed to by the argument. This value is often difficult to obtain otherwise,
 | |
|   because no valid code that produces this value. However, it may be useful
 | |
|   for testing purposes, to see how well does the analyzer model region extents.
 | |
| 
 | |
|   Example usage::
 | |
| 
 | |
|     void foo() {
 | |
|       int x, *y;
 | |
|       size_t xs = clang_analyzer_getExtent(&x);
 | |
|       clang_analyzer_explain(xs); // expected-warning{{'4'}}
 | |
|       size_t ys = clang_analyzer_getExtent(&y);
 | |
|       clang_analyzer_explain(ys); // expected-warning{{'8'}}
 | |
|     }
 | |
| 
 | |
| Statistics
 | |
| ==========
 | |
| 
 | |
| The debug.Stats checker collects various information about the analysis of each
 | |
| function, such as how many blocks were reached and if the analyzer timed out.
 | |
| 
 | |
| There is also an additional -analyzer-stats flag, which enables various
 | |
| statistics within the analyzer engine. Note the Stats checker (which produces at
 | |
| least one bug report per function) may actually change the values reported by
 | |
| -analyzer-stats.
 |