Previous:Analyzer Internals, Up:Static Analyzer [Contents][Index]
When debugging the analyzer I normally use all of these optionstogether:
./xgcc -B. \ -S \ -fanalyzer \ OTHER_GCC_ARGS \ -wrapper gdb,--args \ -fdump-analyzer-stderr \ -fdump-ipa-analyzer=stderr
where:
./xgcc -B.is the usual way to invoke a self-built GCC from within theBUILDDIR/gccsubdirectory.-Sso that the driver (./xgcc) invokescc1, but doesn’t botherrunning the assembler or linker (since the analyzer runs insidecc1).-fanalyzerenables the analyzer, obviously.-wrapper gdb,--argsinvokescc1 under the debugger so that I can debugcc1 andset breakpoints and step through things.-fdump-analyzer-stderrso that the logging interface is enabled and goes to stderr, which oftengives valuable context into what’s happening when stepping through theanalyzer-fdump-ipa-analyzer=stderrwhich dumps the GIMPLE IR seen by the analyzer pass to stderrOther useful options:
-fdump-analyzer-supergraphwhich dumpsSRC.supergraph.N.KIND.dot GraphViz files that I can look at (withpython-xdot)-fdump-analyzer-exploded-graphwhich dumps aSRC.eg.dot GraphViz file-fdump-analyzer-exploded-nodes-2which dumps aSRC.eg.txt file containing the fullexploded_graph.-fdiagnostics-add-output=experimental-html:show-state-diagrams=yeswhich writes out the diagnostics in HTML form, and generates SVG statediagrams visualizing the state of memory at each event (inspired by the"ddd" debugger). These can be seen by pressing ’j’ and ’k’ to single-stepforward and backward through events. Note that these SVG diagrams arecreated from an intermediate SARIF directed graph representation generated fromprogram_state objects. The SARIF representation can be easier toread - for example, rather than storing the contents of memory via byteoffsets, it uses fields for structs and element indexes for arrays,recursively. However it is a different representation, and thus bugs couldbe hidden by this transformation. Generating the SVG diagrams requiresan invocation of "dot" per event, so it noticeably slows down diagnosticemission, hence the opt-in command-line flag. The SARIF and “dot”representations can be seen by__analyzer_dump_xml and__analyzer_dump_dot below (writing them to stderr), or by addingshow-state-diagrams-sarif=yes andshow-state-diagrams-dot-src=yes to the html sink, which showsthem within the generated HTML next to the generated SVG.Assuming that you have thepython support scripts for gdbinstalled (which you should do, it makes debugging GCC much easier),you can use:
(gdb) break-on-saved-diagnostic
to put a breakpoint at the place where a diagnostic is saved duringexploded_graph exploration, to see where a particular diagnosticis being saved, and:
(gdb) break-on-diagnostic
to put a breakpoint at the place where diagnostics are actually emitted.
The analyzer recognizes various special functions by name, for usein debugging the analyzer, and for use in DejaGnu tests.
The declarations of these functions can be seen in the testsuiteinanalyzer-decls.h. None of these functions are actuallyimplemented in terms of code, merely asknown_function subclasses(ingcc/analyzer/kf-analyzer.cc).
__analyzer_breakAdd:
__analyzer_break ();
to the source being analyzed to trigger a breakpoint in the analyzer whenthat source is reached. By putting a series of these in the source, it’smuch easier to effectively step through the program state as it’s analyzed.
__analyzer_describeThe analyzer handles:
__analyzer_describe (0, expr);
by emitting a warning describing the 2nd argument (which can be of anytype), at a verbosity level given by the 1st argument. This is for use whendebugging, and may be of use in DejaGnu tests.
__analyzer_dump__analyzer_dump ();
will dump the copious information about the analyzer’s state each time itreaches the call in its traversal of the source.
__analyzer_dump_capacityextern void __analyzer_dump_capacity (const void *ptr);
will emit a warning describing the capacity of the base region ofthe region pointed to by the 1st argument.
__analyzer_dump_dot__analyzer_dump_dot ();
will dump GraphViz .dot source to stderr reaches the call in itstraversal of the source. This .dot source implements a diagramdescribing the analyzer’s state.
__analyzer_dump_escapedextern void __analyzer_dump_escaped (void);
will emit a warning giving the number of decls that have escaped on thisanalysis path, followed by a comma-separated list of their names,in alphabetical order.
__analyzer_dump_path__analyzer_dump_path ();
will emit a placeholder “note” diagnostic with a path to that call site,if the analyzer finds a feasible path to it. This can be useful forwriting DejaGnu tests for constraint-tracking and feasibility checking.
__analyzer_dump_exploded_nodesFor every callsite to__analyzer_dump_exploded_nodes the analyzerwill emit a warning after it finished the analysis containing informationon all of the exploded nodes at that program point.
__analyzer_dump_exploded_nodes (0);
will output the number of “processed” nodes, and the IDs ofboth “processed” and “merger” nodes, such as:
warning: 2 processed enodes: [EN: 56, EN: 58] merger(s): [EN: 54-55, EN: 57, EN: 59]
With a non-zero argument
__analyzer_dump_exploded_nodes (1);
it will also dump all of the states within the “processed” nodes.
__analyzer_dump_named_constantWhen the analyzer sees a call to__analyzer_dump_named_constant itwill emit a warning describing what is known about the value of a givennamed constant, for parts of the analyzer that interact with targetheaders.
For example:
__analyzer_dump_named_constant ("O_RDONLY");might lead to the analyzer emitting the warning:
warning: named constant 'O_RDONLY' has value '1'
__analyzer_dump_region_model__analyzer_dump_region_model ();
will dump the region_model’s state to stderr.
__analyzer_dump_state__analyzer_dump_state ("malloc", ptr);will emit a warning describing the state of the 2nd argument(which can be of any type) with respect to the state machine witha name matching the 1st argument (which must be a string literal).This is for use when debugging, and may be of use in DejaGnu tests.
__analyzer_dump_sarif__analyzer_dump_sarif ();
will dump the copious information about the analyzer’s state each time itreaches the call in its traversal of the source.
__analyzer_eval__analyzer_eval (expr);
will emit a warning with text "TRUE", FALSE" or "UNKNOWN" based on thetruthfulness of the argument. This is useful for writing DejaGnu tests.
__analyzer_get_unknown_ptr__analyzer_get_unknown_ptr ();
will obtain an unknownvoid *.
__analyzer_get_strlen__analyzer_get_strlen (buf);
will emit a warning if PTR doesn’t point to a null-terminated string.TODO: eventually get the strlen of the buffer (without theoptimizer touching it).
To compare two different exploded graphs, try-fdump-analyzer-exploded-nodes-2 -fdump-noaddr.This will dump aSRC.eg.txt file containing the fullexploded_graph. I usediff -u50 -p to compare two differentsuch files (e.g. before and after a patch) to find the first place where thetwo graphs diverge. The option-fdump-noaddr will suppressprinting pointers withihn the dumps (which would otherwise hide the realdifferences with irrelevent churn).
The option-fdump-analyzer-json will dump both the supergraphand the exploded graph in compressed JSON form.
One approach when tracking down where a particular bogus state isintroduced into theexploded_graph is to add custom code toprogram_state::validate.
The debug functionregion::is_named_decl_p can be used when debugging,such as for assertions and conditional breakpoints. For example, whentracking down a bug in handling a decl calledyy_buffer_stack, Itemporarily added a:
gcc_assert (!m_base_region->is_named_decl_p ("yy_buffer_stack"));tobinding_cluster::mark_as_escaped to trap a point whereyy_buffer_stack was mistakenly being treated as having escaped.
Previous:Analyzer Internals, Up:Static Analyzer [Contents][Index]