Mac OS X 上的`probemod` 打印出神秘的 hexdump 而不是模块名称
Posted
技术标签:
【中文标题】Mac OS X 上的`probemod` 打印出神秘的 hexdump 而不是模块名称【英文标题】:`probemod` on Mac OS X prints mysterious hexdump instead of module name 【发布时间】:2017-01-23 20:47:57 【问题描述】:以下方法可以很好地获取某个命令进行的每个系统调用的函数名称(这里我们跟踪date
命令):
sudo dtrace -n 'syscall:::entry @[probefunc] = count(); ' -c "date"
它产生如下输出:
read_nocancel 13
bsdthread_ctl 15
ioctl 26
现在知道模块名称真是太好了。所以我将probemod
添加到我的跟踪中,如下所示:
sudo dtrace -n 'syscall:::entry @[probemod, probefunc] = count(); ' -c "date"
它产生了这个(诚然时髦,但最终无用)hexdump:
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
ioctl 30
基于Oracle's documentation:我希望输出显示当前探测器的模块名称。实际上,存在a tutorial,这表明probemod
可以解析为诸如libumem.so.1
或libc.so.1
之类的库名称。在我的电脑上不是这样。
我使用的是 Mac OS X Sierra 10.12.3 Beta。
这是 DTrace 的预期行为,还是 Mac OS X 的实现有错误?还是我做错了什么?
【问题讨论】:
【参考方案1】:系统调用提供程序不提供探测模块。如果是这样,它将不是启动(调用)系统调用的模块,而是系统调用本身的模块。这就是为什么它没有意义,如果有,那也不是你想要的。
要确认,列出探针并观察空的“模块”列:
$ sudo dtrace -l -n 'syscall:::entry'
ID PROVIDER MODULE FUNCTION NAME
156 syscall syscall entry
158 syscall exit entry
160 syscall fork entry
162 syscall read entry
164 syscall write entry
.
.
.
您看到的十六进制转储基本上是一个充满 256 个空字节的缓冲区,这就是不存在的探测模块的明显表示方式。
【讨论】:
【参考方案2】:尝试在您的函数中使用stack()
和/或ustack()
:
sudo dtrace -n 'syscall:::entry @[probefunc, stack(), ustack()] = count(); ' -c "date"
示例输出:
ioctl
kernel`unix_syscall64+0x24a
kernel`hndl_unix_scall64+0x16
libsystem_kernel.dylib`__ioctl+0xa
libdtrace.dylib`dtrace_sleep+0x87
dtrace`main+0x1d15
libdyld.dylib`start+0x1
dtrace`0x5
1
stack()
函数
void stack(int nframes)
void stack(void)
stack()
操作将内核堆栈跟踪记录到定向的 缓冲。内核堆栈的深度由给出的值给出 帧。如果没有为 nframes 指定值,则堆栈操作记录一个 stackframes 选项指定的堆栈帧数。
ustack()
函数
void ustack(int nframes, int strsize)
void ustack(int nframes)
void ustack(void)
ustack()
操作将用户堆栈跟踪记录到定向的 缓冲。用户堆栈的深度等于指定的值 帧。如果 nframes 没有值,则 ustack 操作记录一个 由 ustackframes 选项指定的堆栈帧数。ustack()
操作确定调用帧的地址 当探头触发时。ustack()
操作不会翻译 将帧堆叠成符号,直到 DTrace 消费者处理ustack()
用户级别的操作。如果 strsize 的值为 指定且不为零,ustack()
操作分配指定的 字符串空间的数量并使用它来执行地址到符号 直接从内核翻译。
↳https://docs.oracle.com/cd/E18752_01/html/819-5488/gcfbn.html#gcgfo
【讨论】:
在这台计算机上:@[probefunc, stack(1), ustack(1)] = count();
分别给出:“ioctl”、“kernelunix_syscall64+0x24a" and "libsystem_kernel.dylib
__ioctl+0xa”,并带有一些错误的换行符以使事情复杂化。它当然证明 DTrace 可以看到探测器的模块名称,但除非有办法从这些字符串中选择重要部分:这不能用作 probemod
的完全替代品。我仍然很好奇为什么 probemod
的行为与预期不同。
我认为您需要使用格式字符串 (printf()
) 或类似字符串才能获得所需的输出。 probmod
在哪里表现不同?从您链接的示例中,它看起来几乎相同,除非我遗漏了什么。
在我链接的例子中,作者使用@[probemod,probefunc,arg0]= count();
和printa("probemod = %s, probefunc = %s size = %d, count = %@d \n",@);
,得到如下结果:probemod = libumem.so.1 probefunc = malloc size = 2048 count = 6
。换句话说:probemod = libumem.so.1
(这是一个比ustack(1)
返回的字符串短得多的字符串...输出:一些空格、一个由波浪号分隔的元组、一个函数名和某种指针)
这是针对malloc
进程的,它与syscall:::entry
不同;如果您在下方查看,您会看到ustack()
的输出看起来与我期望您得到的几乎相同。我认为可能有一些格式示例here 和here 最终可能会导致您获得想要的结果,不幸的是我在这方面并没有真正做太多。
我认为您的问题更多是关于让相关库显示。如果您想知道如何格式化它,那么我建议您专门问另一个问题。以上是关于Mac OS X 上的`probemod` 打印出神秘的 hexdump 而不是模块名称的主要内容,如果未能解决你的问题,请参考以下文章