Mac OS X 上的 `probemod` 打印神秘的 hexdump 而不是模块名称

`probemod` on Mac OS X prints mysterious hexdump instead of module name

下面的代码可以很好地获取某个命令发出的每个系统调用的函数名(这里我们跟踪 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"

它产生了这个(诚然很时髦,但最终没有帮助)十六进制转储:

           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: I expected the output to show the module name of the current probe. Indeed, there exists a tutorial,表明 probemod 可以解析为库名称,例如 libumem.so.1libc.so.1。在我的电脑上不是这样。

我正在使用 Mac OS X Sierra 10.12.3 Beta。

这是 DTrace 的预期行为,还是 Mac OS X 的实现有错误?还是我做错了什么?

尝试在您的函数中使用 stack() and/or 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)

The stack() action records a kernel stack trace to the directed buffer. The depth of the kernel stack is given by the value given in nframes. If no value is given for nframes, the stack action records a number of stack frames specified by the stackframes option. The

ustack()函数

void ustack(int nframes, int strsize)
void ustack(int nframes)
void ustack(void)

The ustack() action records a user stack trace to the directed buffer. The depth of the user stack is equal to the value specified in nframes. If there is no value for nframes, the ustack action records a number of stack frames that is specified by the ustackframes option. The ustack() action determines the address of the calling frames when the probe fires. The ustack() action does not translate the stack frames into symbols until the DTrace consumer processes the ustack() action at the user level. If a value for strsize is specified and not zero, the ustack() action allocates the specified amount of string space and uses it to perform address-to-symbol translation directly from the kernel.

https://docs.oracle.com/cd/E18752_01/html/819-5488/gcfbn.html#gcgfo

系统调用提供程序不提供探测模块。如果是这样,那将不是启动(调用)系统调用的模块,而是系统调用本身的模块。这就是为什么它没有意义,如果有的话,也不是你想要的。

为了确认,列出探测器并观察空的 "MODULE" 列:

$ 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 个空字节的缓冲区,这就是缺失的探测模块的明显表现形式。