您可以使用 pid 提供器跟踪用户函数中的任何指令。pid 提供器将根据需要,为函数中的每条指令创建探测器。每个探测器的名称即函数中与其对应的,以十六进制整数表示的指令的偏移量。例如,要启用与 bar.so 模块的 foo 函数中的偏移量为 0x1c 的指令(位于 PID 为 123 的进程中)关联的探测器,可使用以下命令:
# dtrace -n pid123:bar.so:foo:1c |
要启用函数 foo 中的所有探测器(包括每条指令的探测器),可使用以下命令:
# dtrace -n pid123:bar.so:foo: |
此命令展示了一种功能非常强大的、用于调试和分析用户应用程序的方法。由于很难重现不经常发生的错误,因此对其进行调试可能并不容易。通常,您可以在出现故障后确定问题,但这对于重构代码路径已太迟。以下示例演示了如何将 pid 提供器与推理跟踪(请参见第 13 章)进行结合,以便通过跟踪函数中的每条指令来解决该问题。
pid$1::$2:entry { self->spec = speculation(); speculate(self->spec); printf("%x %x %x %x %x", arg0, arg1, arg2, arg3, arg4); } pid$1::$2: /self->spec/ { speculate(self->spec); } pid$1::$2:return /self->spec && arg1 == 0/ { discard(self->spec); self->spec = 0; } pid$1::$2:return /self->spec && arg1 != 0/ { commit(self->spec); self->spec = 0; }
执行 errorpath.d 将会生成与以下示例类似的输出:
# ./errorpath.d 100461 _chdir dtrace: script './errorpath.d' matched 19 probes CPU ID FUNCTION:NAME 0 25253 _chdir:entry 81e08 6d140 ffbfcb20 656c73 0 0 25253 _chdir:entry 0 25269 _chdir:0 0 25270 _chdir:4 0 25271 _chdir:8 0 25272 _chdir:c 0 25273 _chdir:10 0 25274 _chdir:14 0 25275 _chdir:18 0 25276 _chdir:1c 0 25277 _chdir:20 0 25278 _chdir:24 0 25279 _chdir:28 0 25280 _chdir:2c 0 25268 _chdir:return |