4

我想看看在我的用户空间 C99 程序中调用了哪些函数以及调用的顺序。另外,给出了哪些参数。

我可以用 DTrace 做到这一点吗?

例如对于程序

int g(int a, int b) { puts("I'm g"); }
int f(int a, int b) { g(5+a,b);g(8+b,a);}
int main() {f(5,2);f(5,3);}

我想看到一个文本文件:

main(1,{"./a.out"})
 f(5,2);
  g(10,2);
   puts("I'm g");
  g(10,5);
   puts("I'm g");
 f(5,3);
  g(10,3);
   puts("I'm g");
  g(11,5);
   puts("I'm g");

我不想修改我的源代码,而且程序真的很大——有 9000 个函数。

我有所有来源;我有一个编译了调试信息的程序,gdb 能够在回溯中打印函数参数。

DTrace 可以解决这个任务吗?

我的操作系统是 BSD、Linux、MacOS、Solaris 之一。我更喜欢 Linux,但我可以使用任何列出的操作系统。

4

3 回答 3

1

以下是使用 DTrace 执行此操作的方法:

script='pid$target:a.out::entry,pid$target:a.out::return { trace(arg1); }'
dtrace -F -n "$script" -c ./a.out

此命令的输出在 FreeBSD 14.0-CURRENT 上如下所示:

dtrace: description 'pid$target:a.out::entry,pid$target:a.out::return ' matched 17 probes
I'm g
I'm g
I'm g
I'm g
dtrace: pid 39275 has exited
CPU FUNCTION
  3  -> _start                                      34361917680
  3    -> handle_static_init                    140737488341872
  3    <- handle_static_init                            2108000
  3    -> main                                  140737488341872
  3      -> f                                                 2
  3        -> g                                               2
  3        <- g                                           32767
  3        -> g                                               5
  3        <- g                                           32767
  3      <- f                                                 0
  3      -> f                                                 3
  3        -> g                                               3
  3        <- g                                           32767
  3        -> g                                               5
  3        <- g                                           32767
  3      <- f                                                 0
  3    <- main                                                0
  3    -> __do_global_dtors_aux                 140737488351184
  3    <- __do_global_dtors_aux                               0

烦人的是我还没有找到打印所有函数参数的方法(请参阅如何在 DTrace 中打印关联数组?)。一个 hacky 解决方法是添加trace(arg2),trace(arg3)等。问题是对于不存在的参数,将会打印出垃圾。

于 2021-11-03T09:54:23.503 回答
0

是的,您可以使用 dtrace 执行此操作。但是你可能永远无法在 linux 上做到这一点。我已经尝试了多个版本的 dtrace 的 linux 端口,但它从来没有完成我想要的。事实上,它曾经引起过 CPU 恐慌。从http://www.brendangregg.com/dtrace.html下载 dtrace 工具包。然后相应地设置您的 PATH 。然后执行这个:

 dtruss -a yourprogram args...
于 2013-05-02T17:17:36.873 回答
-3

您的问题极有可能被误导。对于任何重要的程序,打印所有使用其参数执行的函数调用的序列将导致多 MB 甚至多 GB 的输出,您将无法理解(人类无法理解的太多细节理解)。

也就是说,我不相信你可以用dtrace.

您可以从使用 GCC-finstrument-functions标志开始,它可以让您轻松地在每个函数的入口/出口打印函数地址。然后,您可以使用 addr2line 将地址简单地转换为函数名称。这为您提供了您所要求的(参数除外)。

如果结果证明不是太详细,您可以在 GDB 中的每个函数上设置一个断点(使用rb .命令),并将continue命令附加到每个断点。这将导致断点源源不断地被命中(带有参数),但执行速度可能会慢至少 100 到 1000 倍。

于 2011-08-24T03:44:01.360 回答