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.1libc.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 而不是模块名称的主要内容,如果未能解决你的问题,请参考以下文章

Mac OS X添加网络打印机

mac OS X:[11]如何添加打印机

Mac OS X 下查看和设置JAVA_HOME

将文件写入mac os x中的etc目录

如何 在Mac OS X 上的 Appium 上 Run *.app 文件

Mac OS X 上的 GCC 标志 -Os 来自哪里?