Ferramentas para obter um gráfico de chamada de função pictórica do código [fechado]

106

Tenho um grande espaço de trabalho que contém muitos arquivos-fonte de código C. Embora eu possa ver as funções chamadas de uma função no MS VS2005 usando o navegador de objetos, e também no MSVC 6.0, isso só mostra as funções chamadas de uma função específica em um tipo de exibição não gráfica. Além disso, ele não mostra a função chamada a partir de say main()e, em seguida, as funções chamadas a partir dela e assim por diante, mais profundamente na função de nível folha.

Eu preciso de uma ferramenta que me dê um gráfico de chamada de função pictoricamente com funções calleee callerconectado por setas ou algo parecido, começando do main()último nível da função, ou pelo menos mostrando um gráfico de chamada de todas as funções em um arquivo C de forma pictórica. Seria ótimo se eu pudesse imprimir este gráfico.

Alguma boa ferramenta para fazer isso (não precisam ser ferramentas gratuitas)?

meio dourado
fonte
4
Relacionado: stackoverflow.com/a/17844310/1959808
Ioannis Filippidis

Respostas:

53
filante
fonte
2
pergunta sobre CodeViz, se você passar seu código para que ele gerará o código ou não? Ou você mesmo deveria fazer gráfico por codevis?
Mohammad Reza Rezwani,
5
Acabei de experimentar o Egito. O gráfico é horrível. Não tenho certeza sobre os outros.
ar2015
29

Métodos de análise dinâmica

Aqui, descrevo alguns métodos de análise dinâmica.

Os métodos dinâmicos realmente executam o programa para determinar o gráfico de chamadas.

O oposto dos métodos dinâmicos são os métodos estáticos, que tentam determiná-lo apenas a partir da fonte, sem executar o programa.

Vantagens dos métodos dinâmicos:

  • captura ponteiros de função e chamadas virtuais de C ++. Eles estão presentes em grande número em qualquer software não trivial.

Desvantagens dos métodos dinâmicos:

  • você tem que executar o programa, que pode ser lento, ou requer uma configuração que você não tem, por exemplo, compilação cruzada
  • apenas as funções que foram realmente chamadas serão exibidas. Por exemplo, algumas funções podem ser chamadas ou não dependendo dos argumentos da linha de comando.

KcacheGrind

https://kcachegrind.github.io/html/Home.html

Programa de teste:

int f2(int i) { return i + 2; }
int f1(int i) { return f2(2) + i + 1; }
int f0(int i) { return f1(1) + f2(2); }
int pointed(int i) { return i; }
int not_called(int i) { return 0; }

int main(int argc, char **argv) {
    int (*f)(int);
    f0(1);
    f1(1);
    f = pointed;
    if (argc == 1)
        f(1);
    if (argc == 2)
        not_called(1);
    return 0;
}

Uso:

sudo apt-get install -y kcachegrind valgrind

# Compile the program as usual, no special flags.
gcc -ggdb3 -O0 -o main -std=c99 main.c

# Generate a callgrind.out.<PID> file.
valgrind --tool=callgrind ./main

# Open a GUI tool to visualize callgrind data.
kcachegrind callgrind.out.1234

Agora você está dentro de um programa de GUI incrível que contém muitos dados de desempenho interessantes.

No canto inferior direito, selecione a guia "Gráfico de chamadas". Isso mostra um gráfico de chamadas interativo que se correlaciona com as métricas de desempenho em outras janelas conforme você clica nas funções.

Para exportar o gráfico, clique com o botão direito e selecione "Exportar Gráfico". O PNG exportado tem a seguinte aparência:

A partir disso, podemos ver que:

  • o nó raiz é _start, que é o ponto de entrada ELF real e contém boilerplate de inicialização glibc
  • f0, f1e f2são chamados conforme o esperado um do outro
  • pointedtambém é mostrado, embora o tenhamos chamado com um ponteiro de função. Ele poderia não ter sido chamado se tivéssemos passado um argumento de linha de comando.
  • not_called não é mostrado porque não foi chamado durante a execução, porque não passamos um argumento de linha de comando extra.

A coisa legal sobre valgrind é que não requer nenhuma opção especial de compilação.

Portanto, você pode usá-lo mesmo que não tenha o código-fonte, apenas o executável.

valgrindconsegue fazer isso executando seu código por meio de uma "máquina virtual" leve. Isso também torna a execução extremamente lenta em comparação com a execução nativa.

Como pode ser visto no gráfico, as informações de tempo sobre cada chamada de função também são obtidas e podem ser usadas para traçar o perfil do programa, que é provavelmente o caso de uso original desta configuração, não apenas para ver os gráficos de chamadas: Como posso traçar o perfil Código C ++ em execução no Linux?

Testado no Ubuntu 18.04.

gcc -finstrument-functions + etrace

https://github.com/elcritch/etrace

-finstrument-functions adiciona chamadas de retorno , o etrace analisa o arquivo ELF e implementa todos os retornos de chamada.

Não consegui fazer funcionar, mas infelizmente: Por que `-finstrument-functions` não funciona para mim?

A saída reivindicada está no formato:

\-- main
|   \-- Crumble_make_apple_crumble
|   |   \-- Crumble_buy_stuff
|   |   |   \-- Crumble_buy
|   |   |   \-- Crumble_buy
|   |   |   \-- Crumble_buy
|   |   |   \-- Crumble_buy
|   |   |   \-- Crumble_buy
|   |   \-- Crumble_prepare_apples
|   |   |   \-- Crumble_skin_and_dice
|   |   \-- Crumble_mix
|   |   \-- Crumble_finalize
|   |   |   \-- Crumble_put
|   |   |   \-- Crumble_put
|   |   \-- Crumble_cook
|   |   |   \-- Crumble_put
|   |   |   \-- Crumble_bake

Provavelmente o método mais eficiente, além do suporte de rastreamento de hardware específico, mas tem a desvantagem de recompilar o código.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fonte
2
Observe que o gráfico de chamadas dinâmico cobre apenas uma execução do programa.
smwikipedia
1
@smwikipedia sim, atualizei a resposta para deixar isso mais claro
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Também explicado aqui - stackoverflow.com/questions/311840/…
tauseef_CuriousGuy
17

O Understand faz um ótimo trabalho na criação de gráficos de chamadas.

MattK
fonte
9

Nosso kit de ferramentas de reengenharia de software DMS tem análise de gráfico de controle / fluxo de dados / pontos para / chamada estática que foi aplicada a sistemas enormes (~ ~ 25 milhões de linhas) de código C e produziu esses gráficos de chamada, incluindo funções chamadas por meio de ponteiros de função .

Ira Baxter
fonte
1
Ah, legal, é 2016 e agora um downvoter aparece. Tenho certeza de que seu voto negativo foi baseado em uma avaliação precisa de que essa ferramenta não pode fazer isso. Bem, talvez não. Com certeza faz o que o OP solicitou.
Ira Baxter
1
Faça uma votação positiva para contra-atacar. Eu não me importo se é o seu software ou proprietário, contanto que faça o trabalho :-)
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
7

Você pode tentar CScope + tceetree + Graphviz .

Fabio Visona '
fonte
Como usar esta combinação para obter o gráfico, existe um tutorial ou pelo menos alguma explicação.
Muhammad Yusuf
@Muhammad Yusuf sim, existe uma página wiki .
BillyJoe
5

Você pode verificar meu gerador de árvore de chamadas C baseado em bash aqui . Ele permite que você especifique uma ou mais funções C para as quais deseja informações do chamador e / ou chamadas, ou você pode especificar um conjunto de funções e determinar o gráfico de alcançabilidade das chamadas de função que as conecta ... Ou seja, diga-me todas as formas principais ( ), foo () e bar () estão conectados. Ele usa graphviz / dot para um motor gráfico.

Jason Nyberg
fonte
4

Astrée é a ferramenta mais robusta e sofisticada que existe, IMHO.

ЯegDwight
fonte