Static code analysis for embedded systems

Visao checks embedded C and C++ with your cross toolchain, before the code reaches a board.

With the MISRA C:2012 profile, each finding carries its rule number, and the run ends with a summary of the rules checked and not checked.

visao · firmwareExample
$visao --compiler-path "gcc:/opt/arm/bin/arm-none-eabi-gcc" \
        --cpu arm --os baremetal --standard misra-c-2012 \
        --baseline visao-baseline.sarif --fail-on high \
        build/compile_commands.json
Using toolchain arm-none-eabi-gcc (gcc)
Solving …
src/uart.c:88:14: error: Possible integer overflow
  MISRA C:2012 Rule 12.4 (Advisory)
✓ Finished successfully · 2.1 s
$echo $?
1

Static analysis for embedded code.Checking firmware before the board.

Static code analysis for embedded systems checks C and C++ for microcontrollers and embedded Linux without running it. It needs no board, no debugger and no time at the bench.

This matters more in embedded work than elsewhere. Once code runs on a device, a fault is hard to see: often there is only a console and a few logs. A defect found in the source is fixed in the merge request. The same defect found at the bench takes longer to isolate, because the code and the hardware act together.

Visao reads the compile_commands.json that your cross build writes. It uses your compiler, your flags and your include paths, so it sees the code the way the target build sees it.

How the analysis works, with a worked example: Static code analysis.

MISRA C:2012 coverage.What one build checks, rule by rule.

This is the example compliance summary from the Visao docs, broken down by chapter of the standard. Choose a chapter to see which rules that build checks.

MISRA C:2012Example from the Visao docs

rules checked by this build

  • 19Checked, with findings in the example run
  • 48Checked, no findings
  • 107Not checked by this build

By MISRA category

Mandatory9 / 16
Required43 / 119
Advisory15 / 39
The summary at the end of the run
visao --standard misra-c-2012 -- src/*.c▎ Compliance (174)
  • MISRA C:2012
    ↳ rules in the standard: 174
    ↳ checked by this build: 67
    ↳ checked rules with findings: 19
    ↳ Rule 21.3 (Required) - 2 finding(s): Use of the memory-allocation functions
    ↳ not checked by this build: 107
    ↳ Dir 1.1 (Required), Dir 3.1 (Required), …

Chapters of the standard

Directives

6 of 17 rules checked

Checked by this build

  • Dir 2.1RequiredA translation unit that does not compile
  • Dir 4.7RequiredA returned error indication that is never tested
  • Dir 4.11RequiredA value passed to a library function without being checked
  • Dir 4.12RequiredUse of dynamic memory allocation
  • Dir 4.13AdvisoryResource operations called out of sequence
  • Dir 4.14RequiredA value from an external source used without being checked

Not checked by this build

Dir 1.1, Dir 3.1, Dir 4.1, Dir 4.2, Dir 4.3, Dir 4.4, Dir 4.5, Dir 4.6, Dir 4.8, Dir 4.9, Dir 4.10

1. A standard C environment

1 of 3 rules checked

Checked by this build

  • Rule 1.3RequiredConstructs whose behaviour the standard leaves undefined

Not checked by this build

Rule 1.1, Rule 1.2

2. Unused code

4 of 7 rules checked

Checked by this build

  • Rule 2.1RequiredCode that cannot be reached
  • Rule 2.2RequiredA statement whose removal changes nothing
  • Rule 2.6AdvisoryA label no goto refers to
  • Rule 2.7AdvisoryA parameter the function never reads

Not checked by this build

Rule 2.3, Rule 2.4, Rule 2.5

3. Comments

0 of 2 rules checked

Checked by this build

None

Not checked by this build

Rule 3.1, Rule 3.2

4. Character sets and lexical conventions

0 of 2 rules checked

Checked by this build

None

Not checked by this build

Rule 4.1, Rule 4.2

5. Identifiers

1 of 9 rules checked

Checked by this build

  • Rule 5.3RequiredAn identifier in an inner scope hiding one in an outer scope

Not checked by this build

Rule 5.1, Rule 5.2, Rule 5.4, Rule 5.5, Rule 5.6, Rule 5.7, Rule 5.8, Rule 5.9

6. Types

0 of 2 rules checked

Checked by this build

None

Not checked by this build

Rule 6.1, Rule 6.2

7. Literals and constants

0 of 4 rules checked

Checked by this build

None

Not checked by this build

Rule 7.1, Rule 7.2, Rule 7.3, Rule 7.4

8. Declarations and definitions

2 of 14 rules checked

Checked by this build

  • Rule 8.2RequiredA function declared without a prototype
  • Rule 8.14RequiredUse of the restrict qualifier

Not checked by this build

Rule 8.1, Rule 8.3, Rule 8.4, Rule 8.5, Rule 8.6, Rule 8.7, Rule 8.8, Rule 8.9, Rule 8.10, Rule 8.11, Rule 8.12, Rule 8.13

9. Initialization

1 of 5 rules checked

Checked by this build

  • Rule 9.1MandatoryAn object read before it holds a value

Not checked by this build

Rule 9.2, Rule 9.3, Rule 9.4, Rule 9.5

10. The essential type model

3 of 8 rules checked

Checked by this build

  • Rule 10.3RequiredA value assigned to an object of narrower or different type
  • Rule 10.4RequiredOperands of mixed essential type category
  • Rule 10.6RequiredA composite expression assigned to a wider object

Not checked by this build

Rule 10.1, Rule 10.2, Rule 10.5, Rule 10.7, Rule 10.8

11. Pointer type conversions

2 of 9 rules checked

Checked by this build

  • Rule 11.3RequiredA pointer cast to a pointer of unrelated object type, and used
  • Rule 11.4AdvisoryA conversion between a pointer and an integer

Not checked by this build

Rule 11.1, Rule 11.2, Rule 11.5, Rule 11.6, Rule 11.7, Rule 11.8, Rule 11.9

12. Expressions

3 of 5 rules checked

Checked by this build

  • Rule 12.2RequiredA shift the left operand's width cannot accommodate
  • Rule 12.3AdvisoryUse of the comma operator
  • Rule 12.4AdvisoryA constant expression that wraps around

Not checked by this build

Rule 12.1, Rule 12.5

13. Side effects

3 of 6 rules checked

Checked by this build

  • Rule 13.2RequiredA value that depends on the order its operands are evaluated in
  • Rule 13.4AdvisoryThe result of an assignment used as a value
  • Rule 13.6MandatoryAn operand of sizeof that has side effects

Not checked by this build

Rule 13.1, Rule 13.3, Rule 13.5

14. Control statement expressions

1 of 4 rules checked

Checked by this build

  • Rule 14.3RequiredA controlling expression whose value is invariant

Not checked by this build

Rule 14.1, Rule 14.2, Rule 14.4

15. Control flow

6 of 7 rules checked

Checked by this build

  • Rule 15.1AdvisoryUse of goto
  • Rule 15.2RequiredA goto that jumps backwards
  • Rule 15.4AdvisoryMore than one break or goto terminating one loop
  • Rule 15.5AdvisoryA return anywhere but at the end of the function
  • Rule 15.6RequiredA control statement body that is not a compound statement
  • Rule 15.7RequiredAn if ... else if chain with no final else

Not checked by this build

Rule 15.3

16. Switch statements

4 of 7 rules checked

Checked by this build

  • Rule 16.3RequiredA switch clause that is not terminated by a break
  • Rule 16.4RequiredA switch without a default clause
  • Rule 16.5RequiredA default clause that is neither first nor last
  • Rule 16.6RequiredA switch with fewer than two clauses

Not checked by this build

Rule 16.1, Rule 16.2, Rule 16.7

17. Functions

6 of 8 rules checked

Checked by this build

  • Rule 17.1RequiredUse of the <stdarg.h> variadic facilities
  • Rule 17.2RequiredA function that calls itself, directly or through others
  • Rule 17.3MandatoryA call to a function that was never declared
  • Rule 17.4MandatoryAn exit path of a non-void function with no return value
  • Rule 17.7RequiredA returned value that is never used
  • Rule 17.8AdvisoryA parameter the function assigns to

Not checked by this build

Rule 17.5, Rule 17.6

18. Pointers and arrays

7 of 8 rules checked

Checked by this build

  • Rule 18.1RequiredPointer arithmetic leaving the object it started in
  • Rule 18.2RequiredA subtraction of pointers into different objects
  • Rule 18.4AdvisoryPointer arithmetic other than array indexing
  • Rule 18.5AdvisoryMore than two levels of pointer nesting
  • Rule 18.6RequiredThe address of an automatic object escaping its lifetime
  • Rule 18.7RequiredA flexible array member
  • Rule 18.8RequiredA variable-length array

Not checked by this build

Rule 18.3

19. Overlapping storage

2 of 2 rules checked

Checked by this build

  • Rule 19.1MandatoryAn object copied to an object that overlaps it
  • Rule 19.2AdvisoryUse of a union

20. Preprocessing directives

0 of 14 rules checked

Checked by this build

None

Not checked by this build

Rule 20.1, Rule 20.2, Rule 20.3, Rule 20.4, Rule 20.5, Rule 20.6, Rule 20.7, Rule 20.8, Rule 20.9, Rule 20.10, Rule 20.11, Rule 20.12, Rule 20.13, Rule 20.14

21. Standard libraries

12 of 21 rules checked

Checked by this build

  • Rule 21.3RequiredUse of the memory-allocation functions of <stdlib.h> 2 findings in the docs example
  • Rule 21.4RequiredUse of <setjmp.h>
  • Rule 21.5RequiredUse of <signal.h>
  • Rule 21.6RequiredUse of the input/output functions of <stdio.h>
  • Rule 21.7RequiredUse of atof, atoi, atol or atoll
  • Rule 21.8RequiredUse of abort, exit, getenv or system
  • Rule 21.9RequiredUse of bsearch or qsort
  • Rule 21.10RequiredUse of the time and date functions
  • Rule 21.11RequiredUse of <tgmath.h>
  • Rule 21.12AdvisoryUse of the <fenv.h> exception facilities
  • Rule 21.17MandatoryA string operation reaching beyond the object it was given
  • Rule 21.18MandatoryA size passed to a <string.h> function that the object cannot accommodate

Not checked by this build

Rule 21.1, Rule 21.2, Rule 21.13, Rule 21.14, Rule 21.15, Rule 21.16, Rule 21.19, Rule 21.20, Rule 21.21

22. Resources

3 of 10 rules checked

Checked by this build

  • Rule 22.1RequiredA resource obtained and never released
  • Rule 22.2MandatoryA block freed twice, or freed by the wrong function
  • Rule 22.6MandatoryA FILE pointer used after the stream was closed

Not checked by this build

Rule 22.3, Rule 22.4, Rule 22.5, Rule 22.7, Rule 22.8, Rule 22.9, Rule 22.10

The breakdown by chapter and category comes from the rule list of the same Visao build. Another version can check a different set. Each description says what Visao looks for, which is often narrower than the rule itself. The rule texts belong to MISRA and are not reproduced here.

Compliance evidence is not certification.

The summary speaks only for the rules this build checks. A rule that Visao does not check is listed as not checked, never as passed.

Compliance rests on the MISRA document and on your project's deviation records. The Visao summary is evidence for that argument. Neither Visao nor Midair certifies code.

Before the board.Five steps from commit to device.

Choose a step to see what happens there. The commands and the output are examples.

Write the code

A developer changes C or C++ for the target and opens a merge request.

git · uart-dmasrc/uart.c   +42  -7
src/dma.c    +18  -3
merge request !214 opened

Cross-compile with arm-none-eabi-gcc

The build runs with the cross toolchain and writes compile_commands.json. Visao reads that file, so it uses the same compiler, flags and include paths.

$ cmake -B build -DCMAKE_TOOLCHAIN_FILE=arm-none-eabi.cmake \
          -DCMAKE_EXPORT_COMPILE_COMMANDS=ON$ cmake --build build
[100%] Built target firmware.elf
build/compile_commands.json

Analyze against a baseline

Visao analyzes the change for a bare-metal target with the MISRA profile. The baseline from the main branch drops every finding that was already there.

$ visao --os baremetal --standard misra-c-2012 \
        --baseline visao-baseline.sarif \
        --report-format sarif --report-output visao.sarif \
        build/compile_commands.jsonsrc/uart.c:88:14: error: Possible integer overflow
1 new finding, 213 known findings dropped by the baseline

Only new findings gate the merge

With --fail-on high, the step fails only when a new finding is High or above. Known findings stay in the baseline file and do not block the merge.

$ visao ... --baseline visao-baseline.sarif --fail-on highsrc/uart.c:88:14: error: Possible integer overflow
$ echo $?
1
merge request !214: pipeline failed

Test on the device later

The same build then goes to the board. Midair runs the test suite on real hardware and keeps the evidence of each run.

Firmware testing services
fw-smoke · board rev Aboot/time_to_shell   PASSED  6.1 s
update/keep_config   PASSED
12 as expected

Questions.Short answers.

What is static code analysis for embedded systems?

Static code analysis for embedded systems checks C and C++ for the target without running it on a board. It finds defects such as overflows, indexes past the end of an array and memory used after release, and it can check MISRA C:2012 rules.

Does Visao support MISRA C:2012?

Yes. Run it with --standard misra-c-2012. Matching findings carry the MISRA rule number, and the run ends with a compliance summary. In the example from the docs, that build checks 67 of the 174 rules and names the 107 it does not check.

Does a clean MISRA summary mean our code is certified?

No. The summary covers only the rules the build checks. Compliance rests on the standard and your deviation records, and the summary is evidence for that argument. Visao and Midair certify nothing.

Which toolchains and targets does it work with?

Any GCC-like cross toolchain that you register with --compiler-path, for example arm-none-eabi-gcc. Targets include --os baremetal and --cpu arm, arm64 or mips. Visao reads compile_commands.json, so it uses the flags of your target build.

We have many old findings. Can we still gate merges?

Yes. Write a baseline from the main branch once. After that, --baseline drops the known findings and --fail-on fails the merge only on new ones. Findings match by rule, file, message and source line, so moved code does not look new.

Can we use our own rule selection?

Yes. --standard-rules takes a file with one rule per line, for an amended edition or your project's own selection. The summary counts the rules from that file that the build knows, and counts the rest apart.

Start with one firmware repository.See which MISRA rules your build covers.

Compare the plans on the pricing page. Prices are monthly, in euros.

Join the waitlist