如何让gcc吐出从流程图到源代码行号的映射

时间:2009-03-30 15:59:55

标签: c gcc call-graph

给定一个C文件,gcc可以吐出一个所有函数调用的列表,其中包含调用本身和函数声明的文件名和行号吗?

我知道gcc不知何故用-g(调试器依赖它)保留这些信息,并且它可以使用-dr转储控制流图(但没有文件名或行号);但是有一个随时可用的工具,它可以获取gcc输出并完成我想要的工作吗?

我希望这样一个工具使用gcc的原因是,这将允许我将它与大多数基于gcc的软件一起使用的标准构建系统一起使用(例如./configure&& make),即使在工具的情况下也是如此依赖于他们自己的预处理器和/或解析器是一个很大的麻烦。我已经知道了几个这样的工具,例如CTAGS。所以这个问题是question 525899的后续问题。

3 个答案:

答案 0 :(得分:10)

尝试gcc选项-fdump-tree-fixupcfg-lineno

它将以一种可以使用相对简单的词法分析器或任何正则表达式引擎轻松解析的方式解析AST(带行号)。只需找到前面带有'='的所有非关键字,然后是'(' - 它将是函数调用。

所有复杂的表达式将被分成几行,因此一行上不会出现两个函数调用。

采取简单的程序:

#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;
}

-fdump-tree-fixupcfg-lineno编译它,你会得到类似的东西:

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

}

你不会得到任何复杂的表达式 - 只是赋值和函数调用而且没有CPP宏,非常容易解析。循环和条件不会让事情变得更加困难。

答案 1 :(得分:3)

Valgrind和KCacheGrind似乎是这个用途的好工具:

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

这将为您提供一个名为callgrind.out.pid的文件,您可以使用KCacheGrind打开该文件。这将让你看到很多信息,如call graph,filename ...

答案 2 :(得分:3)

您可以尝试Treehydra,这是一个GCC插件,可以在编译期间为您提供对GCC内部代码表示的只读访问权限。 (但是,构建它是一件苦差事,我不确定它会比-fdump- *给出更好的结果来解决这个问题。)