4. Analyzing Code

Note

This section assumes that a project file exists for your codebase and has been configured to be compatible with GNAT SAS according to Project Setup. If there is no project file defined, follow Creating a Project File.

This section describes how to run an analysis with GNAT SAS and presents in more details some analysis features such as Analysis modes and Timelines.

It also provides recommendations to get the best out of the analysis depending on your needs, see Getting the Right GNAT SAS Settings.

See also

The analysis can be configured in various ways (analysis scope, precision, output directory...). This is described in details in Configuring the Analysis.

4.1. Running GNAT SAS Analysis

4.1.1. Running GNAT SAS from the Command Line

GNAT SAS can be run from the command line, when doing simple experiments, development or for running jobs automatically. A typical invocation of GNAT SAS will look like:

$ gnatsas analyze -Pmy_project

Once done, GNAT SAS generates a SAM file that contains the results of the analysis (see GNAT SAS Files Reference). You can then view the results in multiple formats or IDEs (e.g. GNAT Studio, a Web browser, a SARIF viewer...), or directly in text format from your terminal with:

$ gnatsas report -Pmy_project
alias.adb:10:11: high: divide by zero fails here: requires Page_Size /= 0

See also

4.1.2. Running GNAT SAS from GNAT Studio

GNAT SAS can also be run from GNAT Studio where it is fully integrated. See Running GNAT SAS Analysis.

4.2. Analysis modes

You can vary the thorougness of GNAT SAS' analysis by changing its mode. Two modes are available, and can be selected from the command-line or from GNAT Studio: fast and deep. Analyses are done in fast mode by default.

Command-line examples:

Fast mode

$ gnatsas analyze -Pmy_project
or
$ gnatsas analyze -Pmy_project --mode fast

Deep mode

$ gnatsas analyze -Pmy_project --mode deep

For selecting the mode in GNAT Studio, see GNAT SAS menu.

We recommend developers run fast mode, as it offers the best precision/performance trade-off. Also, incrementality is very important to get fast analysis times e.g. when running from GNAT Studio. Deep mode should be reserved when a more precise analysis is meaningful, e.g. during nightly testing.

Note

Note that changing the mode currently only impacts Inspector's results and has no impact on other engines. The impact on Inspector is as below.

  • In fast mode, Inspector analyzes each library unit separately. This allows Inspector's analysis to be incremental: when re-analyzing a project, only the units that have changed will need to be re-inspected.

  • In deep mode, Inspector performs the analysis by group of units, whose size depend on factors depending in Partitioning of Analysis. The analysis will start from scratch each time, and will be more thorough overall.

Importantly, for each analysis mode, GNAT SAS generates a separate baseline. Each new run in a given mode is automatically compared to the associated baseline. The implications are described in the next section.

4.3. Timelines

The fact that GNAT SAS uses a separate baseline for each analysis mode, and is able to compare runs in a given mode to the associated baseline, is due to the existence of timelines. A timeline is exactly that: a name associated to a baseline run, and the automatic comparison of each new run to that baseline. As such, timelines are separate from one another.

Both fast and deep modes, as well as combinations of an analysis mode and switches that have an influence on the scope of the analysis (detailed below), are automatically associated to a separate timeline.

More specifically, the timeline name is computed as follows:

  • The timeline for the default mode (fast mode) of a given project MyProject.gpr when none of the switches below are specified is "fast", and the timeline of a deep analysis is "deep".

  • with --file FILE_NAME or --file FILE_PATH: "<FILE_NAME>[.deep]"

  • with --files-from FILE_NAME or --files-from FILE_PATH: "<FILE_NAME>[.deep]"

  • with -U: "_U[.deep]"

  • with -U FILE_NAME or -U FILE_PATH: "_U_<FILE_NAME>[.deep]"

  • with --no-subprojects: "_no_sub[.deep]"

where .deep is appended in deep mode.

See also

4.3.1. Using custom timelines

In some cases, it may be desirable to manipulate specific timelines different from the default generated ones. For example:

  • When you want to perform an analysis in a given mode, but due to the settings large discrepancies are expected. Typically, when using different scenario variables values in the project file. As an example, consider a case where you want to have a finer control over the scope of the analysis (typically excluding some directories or projects), and you do not want to mix the results with the results from an analysis of the whole project tree. The analysis can be run on the whole project tree in one timeline, and then on a more restricted project tree in another.

  • You may also want to do that in order to later merge otherwise separated timelines (e.g. fast and deep mode).

To support such use cases, GNAT SAS provides the capability to create and use new timelines with the --timeline switch.

The --timeline <name> switch can be set to the gnatsas analyze subcommand, with the following effects:

  • The first analysis of a timeline becomes the baseline of the said timeline (unless a baseline was specifically set prior to it with gnatsas baseline --timeline <name> --set-baseline <baseline> , see Comparing GNAT SAS Runs ).

  • All analyses are automatically compared to the timeline's baseline.

The --timeline <name> switch can be set for the gnatsas report subcommand too. The effect is to display the results of the specified timeline's last run (instead of the actual last run's results).

The --timeline <name> switch can be specified in the gnatsas baseline subcommand in order to manipulate the specified timeline's baseline (see Comparing GNAT SAS Runs), or current run (see use cases in Importing GNAT SAS Results and sam-from-db).

4.3.2. Displaying timeline information

Information about available timelines can be displayed using the --list-timelines switch. This switch will display all timelines that were automatically created by the tool or explicitly specified by users for the specified project.

For example:

$ gnatsas analyze -Pprj
$ gnatsas analyze -Pprj --mode=deep
$ gnatsas analyze -Pprj --list-timelines

will display the list of timelines (fast, deep) and related information, such as the date of last run, command-line and project switches used for the analysis, paths to SAM file and baseline file.

See also

See GNAT SAS CLI Reference for more details about the GNAT SAS command line and supported switches.

4.4. Getting the Right GNAT SAS Settings

We recommend that you first get familiar with System Requirements for a proper recommended configuration to run GNAT SAS.

4.4.1. Analyze Messages

If a given run contains many messages, start analyzing them and identify if there are groups of uninteresting or incorrect messages. You can disable a category of messages producing uninteresting results in text output using the --show switch (see Filtering Messages for more details).

For example if messages related to access checks are not producing interesting results in your code base, you can disable these messages in text output using --show kind-access_check with gnatsas report.

If many uninteresting or incorrect messages are issued for a file, you can exclude this file from analysis via the Analyzer'Excluded_Source_Files project attribute or via pragma Annotate (GNATSAS, Skip_Analysis) as explained in Partial Analysis.

Also choose the relevant messages based on ranking: GNAT SAS ranks messages in categories depending on how interesting and likely to happen they are (see Categorization of Messages).

While analyzing existing code, you should start looking at High messages first, then Medium, and finally if it makes sense, Low messages.

A recommended setting is to consider High and Medium messages, which is what is displayed by default in the GNAT Studio report.

If the run is mostly clean or contains mainly interesting messages, then try to see if there are messages disabled by default which may be interesting in your context. These are some Infer Messages, some GNAT Warnings Messages, some GNATcheck Messages, and Race Condition Messages.

See also

During this analysis of the results, you may want to start triaging and reviewing some messages. Refer to Reviewing Results and Improving Code for more details about the review process.

4.4.2. Run GNAT SAS Faster

If runs are too slow for your needs (e.g. quick user feedback as opposed to nightly runs) then you should consider disabling some analysis engines (see gnatsas analyze switches), making sure you are using the -j0 switch (enabled by default unless you are using another -jxx switch explicitly) and using a machine with as many cores as possible as well as using local fast drives, as explained in System Requirements.

If this isn't sufficient, or you don't want to disable an analysis engine that takes a lot of time, the next step is to identify the files that are taking a long time to analyze and exclude them from the analysis as per Partial Analysis.

4.4.2.1. Identifying files that take a long time to analyze by Inspector

To identify the files that are taking a long time to analyze by Inspector, you can save GNAT SAS' default output and sort it on the 4th column (timing info):

analyzed main.scil in 0.05 seconds
analyzed main__body.scil in 620.31 seconds
analyzed pack1__body.scil in 20.02 seconds
analyzed pack2__body.scil in 5.13 seconds

For example using the sort utility:

$ gnatsas analyze -Pprj |& grep "^analyzed " | tee gnatsas-output.txt
sort -r -g -k 4 gnatsas-output.txt

You'll get:

analyzed main__body.scil in 620.31 seconds
analyzed pack1__body.scil in 20.02 seconds
analyzed pack2__body.scil in 5.13 seconds
analyzed main.scil in 0.05 seconds

In this simple example, skipping the analysis of the body of unit main (e.g. main.adb) will produce a 25 seconds analysis instead of taking more than 10 minutes.

If it is not acceptable to exclude the whole file from the analysis, it is possible to use the switch --dbg-on dbg_slow_analyses to get Inspector timings for individual subprograms and exclude only particular subprograms from the analysis, like this:

package Analyzer is
   for Switches ("inspector") use ("--dbg-on", "dbg_slow_analyses");
end Analyzer;

4.4.2.2. Identifying files that take a long time to analyze by Infer

Warning

This section is specific to Unix systems. In particular, it does not apply to Windows systems.

For Infer, you can use an interactive progress bar to get the information where Infer spent long time. You can enable this progress-bar by using -Q --progress-bar-style multiline, like this:

package Analyzer is
   for Switches ("infer") use ("-Q", "--progress-bar-style", "multiline");
end Analyzer;