10

给定一个 C 文件,gcc 能否吐出所有发生的函数调用的列表,以及调用本身和函数声明的文件名和行号?

我知道 gcc 以某种方式使用 -g 保留了这些信息(调试器依赖它),并且它可以使用 -dr 转储控制流图(但没有文件名或行号);但是是否有一个现成的工具可以获取 gcc 输出并执行我想要的操作?

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

4

3 回答 3

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 宏,很容易解析。循环和条件不会使它变得更加困难。

于 2009-03-30T17:21:31.657 回答
3

Valgrind 和 KCacheGrind 似乎是一个很好的工具:

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

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

于 2009-03-30T16:24:43.587 回答
3

您可以尝试Treehydra,这是一个 GCC 插件,可让您在编译期间以只读方式访问 GCC 内部代码表示。(但是,构建起来有点麻烦,我不确定它会比 -fdump-* 提供更好的结果。)

于 2009-12-11T16:52:27.857 回答