在 Linux 中修复 dtrace 中的“无符号类型信息”?

Posted

技术标签:

【中文标题】在 Linux 中修复 dtrace 中的“无符号类型信息”?【英文标题】:Fixing 'no symbolic type information' from dtrace in Linux? 【发布时间】:2013-07-27 21:31:46 【问题描述】:

仅记录此内容:(自行回答)

我知道由于许可问题,Sun 的 dtrace 没有为 Ubuntu 打包;所以我下载了它并在 Ubuntu 上从源代码构建它——但我遇到的问题与Simple dtraces not working · Issue #17 · dtrace4linux/linux · GitHub 中的问题非常相似;即加载驱动程序似乎很好:

dtrace-20130712$ sudo make load
tools/load.pl
23:20:31 Syncing...
23:20:31 Loading: build-2.6.38-16-generic/driver/dtracedrv.ko
23:20:34 Preparing symbols...
23:20:34 Probes available: 364377
23:20:44 Time: 13s

...但是,如果我尝试运行一个简单的脚本,它会失败:

$ sudo ./build/dtrace -n 'BEGIN  printf("Hello, world"); exit(0); '
dtrace: invalid probe specifier BEGIN  printf("Hello, world"); exit(0); : "/path/to/src/dtrace-20130712/etc/sched.d", line 60: no symbolic type information is available for kernel`dtrace_cpu_id: Invalid argument

根据上面的问题链接:

(ctf 需要一个私有且有效的 libdwarf 库 - 大多数旧版本都有损坏的版本)。

...然后我从源代码构建libdwarf,然后基于它构建dtrace(不是微不足道的,需要手动找到符号链接的正确位置);我仍然遇到同样的失败。

有办法解决吗?

【问题讨论】:

【参考方案1】:

好吧,在访问gdb 之后,我发现问题出现在dtrace 的函数dt_module_getctf(通过dtrace_symbol_type 调用,我认为是dt_module_lookup_by_name)。在其中,我注意到大多数调用都会传播属性/变量dm_name = "linux";但是当失败发生时,我会得到dm_name = "kernel"

请注意,sched.d 的原始第 60 行是:

    cpu_id = `dtrace_cpu_id; /* C->cpu_id; */

然后我找到thr3ads.net - dtrace discuss - accessing symbols without type info [Nov 2006];提到此错误消息的地方:

dtrace:无效的探测说明符 fbt::calcloadavg:entry printf("CMS_USER: %d, CMS_SYSTEM: %d, cpu_waitrq: %d\n", `cpu0.cpu_acct[0], `cpu0.cpu_acct[1], `cpu0.cpu_waitrq);: 在行动 列表:没有符号类型信息可用于 unix`cpu0:没有类型 可用于符号的信息

所以:

在该系统上,请求`cpu0.cpu_acct[0] 被解析为unix`cpu0; 在我的系统上,请求`dtrace_cpu_id 被解析为kernel`dtrace_cpu_id

并且由于“反引号运算符用于读取 内核变量的值,这将特定于正在运行的内核。”(howto measure CPU load - DTrace General Discussion - ArchiveOrange),我想也许明确地将这个“反引号变量”“强制转换”为linux会有所帮助。

确实如此 - 只有一小部分 sched.d 需要更改为:

translator cpuinfo_t < dtrace_cpu_t *C > 
    cpu_id = linux`dtrace_cpu_id; /* C->cpu_id; */
    cpu_pset = -1;
    cpu_chip = linux`dtrace_cpu_id; /* C->cpu_id; */
    cpu_lgrp = 0; /* XXX */
/*  cpu_info = *((_processor_info_t *)`dtrace_zero); /* ` */ /* XXX */
;

inline cpuinfo_t *curcpu = xlate <cpuinfo_t *> (&linux`dtrace_curcpu);

...突然间 - 它开始工作了!:

dtrace-20130712$ sudo ./build/dtrace -n 'BEGIN  printf("Hello, world"); exit(0); '
dtrace: description 'BEGIN ' matched 1 probe
CPU     ID                    FUNCTION:NAME
  1      1                           :BEGIN Hello, world

 

PS:

Protip 1:永远不要做dtrace -n '::: printf("Hello"); ' - 这意味着“在每个内核事件上执行 printf”,它会完全冻结内核;连 CTRL-Alt-Del 都不行!

Protip 2:如果你想像Debugging DTrace一样使用DTRACE_DEBUG,请使用sudo -E

dtrace-20130712$ DTRACE_DEBUG=1 sudo -E ./build/dtrace -n 'BEGIN  printf("Hello, world"); exit(0); '
libdtrace DEBUG: reading kernel .ctf: /path/to/src/dtrace-20130712/build-2.6.38-16-generic/linux-2.6.38-16-generic.ctf
libdtrace DEBUG: opened 32-bit /proc/kallsyms (syms=75761)
...

【讨论】:

以上是关于在 Linux 中修复 dtrace 中的“无符号类型信息”?的主要内容,如果未能解决你的问题,请参考以下文章

在 Oracle Linux 上使用 DTrace

Linux 上 DTrace 的替代方案是啥? [关闭]

在Oracle Linux上安装dtrace

Linux内核动态跟踪—SYstemTap

谓词中的 Dtrace 字符串比较不起作用

C中的无符号整数在java中的处理