Domanda come fare gcc sputare una mappatura dai grafici di flusso ai numeri di riga del codice sorgente


Può gcc sputare, dato un file C, un elenco di tutte le chiamate di funzione che si verificano, con nome file e numero di riga sia per la chiamata stessa sia per la dichiarazione della funzione?

So che gcc in qualche modo conserva queste informazioni con -g (i debugger si basano su di esso) e che può scaricare i diagrammi di flusso di controllo con -dr (ma senza nomi di file o numeri di riga); ma c'è uno strumento pronto all'uso che prende l'output di gcc e fa ciò che voglio?

La ragione per cui voglio che un tale strumento utilizzi gcc è che questo mi consentirà di usarlo con il sistema di compilazione standard con la maggior parte del software basato su gcc (ad es ./configure && make) anche nei casi in cui gli strumenti si basano sul proprio preprocessore e / o parser sono un grosso problema per adattarsi. Sono già a conoscenza di molti di questi strumenti, ad es ctags. Quindi questa domanda è un seguito a domanda 525899.


10
2018-03-30 15:59


origine


risposte:


Prova l'opzione gcc -fdump-tree-fixupcfg-lineno.

Sarà "carina" l'analisi di AST (con numeri di linea) in un modo che può essere facilmente analizzato usando lessico relativamente semplice o qualsiasi motore regex. Basta trovare tutte le parole chiave non precedute da '=' e seguite da '(' - saranno chiamate di funzione.

Tutte le espressioni complesse saranno divise in più righe in modo che nessuna chiamata a due funzioni appaia su una riga.

Fai un semplice programma:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define PI (3.1415926536)

int main(int argc, char *argv[]) {
    double  angle = PI / 2.0;
    printf("Sine = %lf, cosine = %lf\n", sin(angle), cos(angle));
    return EXIT_SUCCESS;
}

Compilalo con -fdump-tree-fixupcfg-lineno e ottieni qualcosa del genere:

main (argc, argv)
{
  double angle;
  int D.3381;
  double D.3380;
  double D.3379;

  # BLOCK 2, starting at line 8
  # PRED: ENTRY (fallthru)
  [test.c : 8] angle = 1.57079632680000003119857865385711193084716796875e+0;
  [test.c : 9] D.3379 = [test.c : 9] cos (angle);
  [test.c : 9] D.3380 = [test.c : 9] sin (angle);
  [test.c : 9] printf (&"Sine = %lf, cosine = %lf\n"[0], D.3380, D.3379);
  [test.c : 10] D.3381 = 0;
  return D.3381;
  # SUCC: EXIT

}

Non otterrai espressioni complesse, solo assegnazioni e chiamate di funzione e nessuna macro CPP, molto facile da analizzare. Loops e condizionali non rendono molto più difficile.


10
2018-03-30 17:21



Valgrind e KCacheGrind sembrano un buon strumento per questo uso:

valgrind --tool=callgrind --dump-instr=yes ./your_binary

Questo ti darà un file chiamato callgrind.out.pid che puoi aprire con KCacheGrind. Questo ti permetterà di vedere molte informazioni come call graph, filename ...


3
2018-03-30 16:24



Potresti provare Treehydra, un plugin GCC che offre accesso in sola lettura alle rappresentazioni interne del codice GCC durante la compilazione. (Tuttavia, è un po 'complicato da costruire, e non sono sicuro che fornirà risultati migliori di -fdump- * per questo problema.)


3
2017-12-11 16:52