Análise estática de código para sistemas embebidos

O Visao verifica C e C++ embebido com a sua toolchain cruzada, antes de o código chegar a uma placa.

Com o perfil MISRA C:2012, cada ocorrência indica o número da regra, e a execução termina com um resumo das regras verificadas e não verificadas.

visao · firmwareExemplo
$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

Análise estática para código embebido.Verificar o firmware antes da placa.

A análise estática de código para sistemas embebidos verifica C e C++ para microcontroladores e Linux embebido sem o executar. Não precisa de placa, de debugger nem de tempo na bancada.

No trabalho embebido isto pesa mais do que noutros lados. Quando o código já corre num dispositivo, uma falha é difícil de ver: muitas vezes só há uma consola e alguns logs. Um defeito encontrado no código-fonte corrige-se no merge request. O mesmo defeito encontrado na bancada demora mais a isolar, porque o código e o hardware atuam em conjunto.

O Visao lê o compile_commands.json que o seu build cruzado escreve. Usa o seu compilador, as suas flags e os seus caminhos de include. Por isso, vê o código tal como o build do alvo o vê.

Como funciona a análise, com um exemplo completo: Análise estática de código.

Cobertura MISRA C:2012.O que um build verifica, regra a regra.

Este é o resumo de conformidade de exemplo da documentação do Visao, dividido pelos capítulos da norma. Escolha um capítulo para ver que regras esse build verifica.

MISRA C:2012Exemplo da documentação do Visao

regras verificadas por este build

  • 19Verificadas, com ocorrências na execução de exemplo
  • 48Verificadas, sem ocorrências
  • 107Não verificadas por este build

Por categoria MISRA

Mandatory9 / 16
Required43 / 119
Advisory15 / 39
O resumo no fim da execução
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), …

Capítulos da norma

Diretivas

6 de 17 regras verificadas

Verificadas por este build

  • Dir 2.1RequiredUma unidade de tradução que não compila
  • Dir 4.7RequiredUma indicação de erro devolvida que nunca é testada
  • Dir 4.11RequiredUm valor passado a uma função de biblioteca sem ser verificado
  • Dir 4.12RequiredUso de alocação dinâmica de memória
  • Dir 4.13AdvisoryOperações sobre um recurso chamadas fora de ordem
  • Dir 4.14RequiredUm valor de uma fonte externa usado sem ser verificado

Não verificadas por este 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. Um ambiente C normalizado

1 de 3 regras verificadas

Verificadas por este build

  • Rule 1.3RequiredConstruções cujo comportamento a norma deixa indefinido

Não verificadas por este build

Rule 1.1, Rule 1.2

2. Código não usado

4 de 7 regras verificadas

Verificadas por este build

  • Rule 2.1RequiredCódigo que nunca pode ser alcançado
  • Rule 2.2RequiredUma instrução cuja remoção não muda nada
  • Rule 2.6AdvisoryUma etiqueta a que nenhum goto se refere
  • Rule 2.7AdvisoryUm parâmetro que a função nunca lê

Não verificadas por este build

Rule 2.3, Rule 2.4, Rule 2.5

3. Comentários

0 de 2 regras verificadas

Verificadas por este build

Nenhuma

Não verificadas por este build

Rule 3.1, Rule 3.2

4. Conjuntos de caracteres e convenções léxicas

0 de 2 regras verificadas

Verificadas por este build

Nenhuma

Não verificadas por este build

Rule 4.1, Rule 4.2

5. Identificadores

1 de 9 regras verificadas

Verificadas por este build

  • Rule 5.3RequiredUm identificador num âmbito interior que esconde outro de um âmbito exterior

Não verificadas por este 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. Tipos

0 de 2 regras verificadas

Verificadas por este build

Nenhuma

Não verificadas por este build

Rule 6.1, Rule 6.2

7. Literais e constantes

0 de 4 regras verificadas

Verificadas por este build

Nenhuma

Não verificadas por este build

Rule 7.1, Rule 7.2, Rule 7.3, Rule 7.4

8. Declarações e definições

2 de 14 regras verificadas

Verificadas por este build

  • Rule 8.2RequiredUma função declarada sem protótipo
  • Rule 8.14RequiredUso do qualificador restrict

Não verificadas por este 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. Inicialização

1 de 5 regras verificadas

Verificadas por este build

  • Rule 9.1MandatoryUm objeto lido antes de ter um valor

Não verificadas por este build

Rule 9.2, Rule 9.3, Rule 9.4, Rule 9.5

10. O modelo de tipos essenciais

3 de 8 regras verificadas

Verificadas por este build

  • Rule 10.3RequiredUm valor atribuído a um objeto de tipo mais estreito ou diferente
  • Rule 10.4RequiredOperandos de categorias de tipo essencial diferentes
  • Rule 10.6RequiredUma expressão composta atribuída a um objeto mais largo

Não verificadas por este build

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

11. Conversões de tipos de ponteiro

2 de 9 regras verificadas

Verificadas por este build

  • Rule 11.3RequiredUm ponteiro convertido para um ponteiro de tipo de objeto não relacionado, e usado
  • Rule 11.4AdvisoryUma conversão entre um ponteiro e um inteiro

Não verificadas por este build

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

12. Expressões

3 de 5 regras verificadas

Verificadas por este build

  • Rule 12.2RequiredUm deslocamento que a largura do operando esquerdo não comporta
  • Rule 12.3AdvisoryUso do operador vírgula
  • Rule 12.4AdvisoryUma expressão constante que dá a volta

Não verificadas por este build

Rule 12.1, Rule 12.5

13. Efeitos secundários

3 de 6 regras verificadas

Verificadas por este build

  • Rule 13.2RequiredUm valor que depende da ordem de avaliação dos operandos
  • Rule 13.4AdvisoryO resultado de uma atribuição usado como valor
  • Rule 13.6MandatoryUm operando de sizeof com efeitos secundários

Não verificadas por este build

Rule 13.1, Rule 13.3, Rule 13.5

14. Expressões das instruções de controlo

1 de 4 regras verificadas

Verificadas por este build

  • Rule 14.3RequiredUma expressão de controlo cujo valor nunca muda

Não verificadas por este build

Rule 14.1, Rule 14.2, Rule 14.4

15. Fluxo de controlo

6 de 7 regras verificadas

Verificadas por este build

  • Rule 15.1AdvisoryUso de goto
  • Rule 15.2RequiredUm goto que salta para trás
  • Rule 15.4AdvisoryMais do que um break ou goto a terminar o mesmo ciclo
  • Rule 15.5AdvisoryUm return em qualquer ponto que não o fim da função
  • Rule 15.6RequiredO corpo de uma instrução de controlo que não é uma instrução composta
  • Rule 15.7RequiredUma cadeia if ... else if sem else final

Não verificadas por este build

Rule 15.3

16. Instruções switch

4 de 7 regras verificadas

Verificadas por este build

  • Rule 16.3RequiredUma cláusula de switch que não termina com break
  • Rule 16.4RequiredUm switch sem cláusula default
  • Rule 16.5RequiredUma cláusula default que não é a primeira nem a última
  • Rule 16.6RequiredUm switch com menos de duas cláusulas

Não verificadas por este build

Rule 16.1, Rule 16.2, Rule 16.7

17. Funções

6 de 8 regras verificadas

Verificadas por este build

  • Rule 17.1RequiredUso das funcionalidades variádicas de <stdarg.h>
  • Rule 17.2RequiredUma função que se chama a si própria, diretamente ou através de outras
  • Rule 17.3MandatoryUma chamada a uma função que nunca foi declarada
  • Rule 17.4MandatoryUm caminho de saída de uma função não void sem valor de retorno
  • Rule 17.7RequiredUm valor devolvido que nunca é usado
  • Rule 17.8AdvisoryUm parâmetro a que a função atribui um valor

Não verificadas por este build

Rule 17.5, Rule 17.6

18. Ponteiros e arrays

7 de 8 regras verificadas

Verificadas por este build

  • Rule 18.1RequiredAritmética de ponteiros que sai do objeto onde começou
  • Rule 18.2RequiredUma subtração de ponteiros para objetos diferentes
  • Rule 18.4AdvisoryAritmética de ponteiros que não é indexação de arrays
  • Rule 18.5AdvisoryMais de dois níveis de indireção de ponteiros
  • Rule 18.6RequiredO endereço de um objeto automático que sobrevive ao seu tempo de vida
  • Rule 18.7RequiredUm membro de array flexível
  • Rule 18.8RequiredUm array de comprimento variável

Não verificadas por este build

Rule 18.3

19. Armazenamento sobreposto

2 de 2 regras verificadas

Verificadas por este build

  • Rule 19.1MandatoryUm objeto copiado para outro que se sobrepõe a ele
  • Rule 19.2AdvisoryUso de uma union

20. Diretivas de pré-processamento

0 de 14 regras verificadas

Verificadas por este build

Nenhuma

Não verificadas por este 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. Bibliotecas normalizadas

12 de 21 regras verificadas

Verificadas por este build

  • Rule 21.3RequiredUso das funções de alocação de memória de <stdlib.h> 2 ocorrências no exemplo da documentação
  • Rule 21.4RequiredUso de <setjmp.h>
  • Rule 21.5RequiredUso de <signal.h>
  • Rule 21.6RequiredUso das funções de entrada/saída de <stdio.h>
  • Rule 21.7RequiredUso de atof, atoi, atol ou atoll
  • Rule 21.8RequiredUso de abort, exit, getenv ou system
  • Rule 21.9RequiredUso de bsearch ou qsort
  • Rule 21.10RequiredUso das funções de data e hora
  • Rule 21.11RequiredUso de <tgmath.h>
  • Rule 21.12AdvisoryUso das funcionalidades de exceções de <fenv.h>
  • Rule 21.17MandatoryUma operação de strings que vai além do objeto que recebeu
  • Rule 21.18MandatoryUm tamanho passado a uma função de <string.h> que o objeto não comporta

Não verificadas por este 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. Recursos

3 de 10 regras verificadas

Verificadas por este build

  • Rule 22.1RequiredUm recurso obtido e nunca libertado
  • Rule 22.2MandatoryUm bloco libertado duas vezes, ou libertado pela função errada
  • Rule 22.6MandatoryUm ponteiro FILE usado depois de o stream ser fechado

Não verificadas por este build

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

A divisão por capítulo e por categoria vem da lista de regras do mesmo build do Visao. Outra versão pode verificar um conjunto diferente. Cada descrição diz o que o Visao procura, o que muitas vezes é mais restrito do que a própria regra. Os textos das regras pertencem à MISRA e não estão reproduzidos aqui.

Evidências de conformidade não são certificação.

O resumo só fala das regras que este build verifica. Uma regra que o Visao não verifica aparece como não verificada, nunca como cumprida.

A conformidade assenta no documento MISRA e nos registos de desvios do seu projeto. O resumo do Visao é uma evidência para esse argumento. Nem o Visao nem o Midair certificam código.

Antes da placa.Cinco passos do commit ao dispositivo.

Escolha um passo para ver o que acontece nele. Os comandos e a saída são exemplos.

Escrever o código

Um programador altera o código C ou C++ para o alvo e abre um merge request.

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

Compilar com arm-none-eabi-gcc

O build corre com a toolchain cruzada e escreve o compile_commands.json. O Visao lê esse ficheiro, por isso usa o mesmo compilador, as mesmas flags e os mesmos caminhos de include.

$ 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

Analisar com uma linha de base

O Visao analisa a alteração para um alvo bare-metal com o perfil MISRA. A linha de base do branch principal retira todas as ocorrências que já lá estavam.

$ 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 ocorrência nova, 213 ocorrências conhecidas retiradas pela linha de base

Só as ocorrências novas bloqueiam o merge

Com --fail-on high, o passo só falha quando uma ocorrência nova é High ou superior. As ocorrências conhecidas ficam no ficheiro da linha de base e não bloqueiam o merge.

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

Testar no dispositivo mais tarde

Depois, o mesmo build vai para a placa. O Midair executa a suite de testes em hardware real e guarda as evidências de cada execução.

Testes de firmware
fw-smoke · board rev Aboot/time_to_shell   PASSED  6.1 s
update/keep_config   PASSED
12 as expected

Perguntas.Respostas curtas.

O que é a análise estática de código para sistemas embebidos?

A análise estática de código para sistemas embebidos verifica C e C++ para o alvo sem o executar numa placa. Encontra defeitos como overflows, índices além do fim de um array e memória usada depois de libertada, e pode verificar regras MISRA C:2012.

O Visao suporta MISRA C:2012?

Sim. Execute-o com --standard misra-c-2012. As ocorrências correspondentes indicam o número da regra MISRA, e a execução termina com um resumo de conformidade. No exemplo da documentação, esse build verifica 67 das 174 regras e indica as 107 que não verifica.

Um resumo MISRA sem ocorrências significa que o código está certificado?

Não. O resumo só cobre as regras que o build verifica. A conformidade assenta na norma e nos seus registos de desvios, e o resumo é uma evidência para esse argumento. O Visao e o Midair não certificam nada.

Com que toolchains e alvos funciona?

Com qualquer toolchain cruzada do tipo GCC que registe com --compiler-path, por exemplo arm-none-eabi-gcc. Os alvos incluem --os baremetal e --cpu arm, arm64 ou mips. O Visao lê o compile_commands.json, por isso usa as flags do build do alvo.

Temos muitas ocorrências antigas. Podemos bloquear merges na mesma?

Sim. Escreva uma vez uma linha de base a partir do branch principal. Depois, --baseline retira as ocorrências conhecidas e --fail-on só faz falhar o merge com ocorrências novas. A correspondência usa a regra, o ficheiro, a mensagem e a linha de código, por isso código movido não parece novo.

Podemos usar a nossa própria seleção de regras?

Sim. --standard-rules recebe um ficheiro com uma regra por linha, para uma edição revista ou para a seleção do seu projeto. O resumo conta as regras desse ficheiro que o build conhece e conta as restantes à parte.

Comece por um repositório de firmware.Veja que regras MISRA o seu build cobre.

Compare os planos na página de preços. Os preços são mensais, em euros.

Entrar na lista de espera