dtrace 仅在函数返回特定模块时执行操作

Posted

技术标签:

【中文标题】dtrace 仅在函数返回特定模块时执行操作【英文标题】:dtrace execute action only when the function returns to a specific module 【发布时间】:2013-07-08 17:54:09 【问题描述】:

我正在使用 dtrace 跟踪一些 libc 函数。我想做一个谓词,仅在函数返回到参数中给定的特定模块的地址时才执行操作。

返回探针上的copyin(uregs[R_ESP],1) 应该给出我认为的返回地址,我不完全确定,所以如果有人能确认会很好。

但是我需要一种方法来将该地址解析为模块,这可能吗?如何实现?

【问题讨论】:

【参考方案1】:

有一个ucaller 变量可以为您提供 将程序计数器保存为 uint64_tumod() 将 将其翻译成相应的模块名称,例如

# dtrace -n 'pid$target:::entry @[umod(ucaller)]=count()' -p `pgrep -n xscreensaver`
dtrace: description 'pid$target:::entry ' matched 14278 probes
^C

  xscreensaver                                                     16
  libXt.so.4                                                       73
  libX11.so.4                                                      92
  libxcb.so.1                                                     141
  libc.so.1                                                       144
^C# 

但是,umod() 是一个动作(相对于子程序);它 不能分配给左值,因此不能用于 一个表达式(因为翻译被推迟到地址 由 dtrace(1) 用户级程序接收)。

幸运的是,没有什么能阻止您找到地址 libc 在您的进程中占用的范围并将其与ucaller 进行比较。 这是 Solaris 上的一个示例(其中特定于硬件的 libc 是 在启动时安装):

# mount | fgrep libc
/lib/libc.so.1 on /usr/lib/libc/libc_hwcap1.so.1 read/write/setuid/devices/rstchown/dev=30d0002 on Sat Jul 13 20:27:32 2013
# pmap `pgrep -n gedit` | fgrep libc_hwcap1.so.1
FEE10000    1356K r-x--  /usr/lib/libc/libc_hwcap1.so.1
FEF73000      44K rwx--  /usr/lib/libc/libc_hwcap1.so.1
FEF7E000       4K rwx--  /usr/lib/libc/libc_hwcap1.so.1
#

我假设文本部分是只有 读取和执行权限,但请注意,在某些 文本部分可写的情况。

# cat Vision.d 
/*
 * self->current is a boolean indicating whether or not execution is currently
 * within the target range.
 *
 * self->next is a boolean indicating whether or not execution is about to
 * return to the target range.
 */
BEGIN

    self->current = 1;


pid$target:::entry
   
    self->current = (uregs[R_PC] >= $1 && uregs[R_PC] < $2);


syscall:::return
/pid==$target/

    self->next = self->current;
    self->current = 0;


pid$target:::return

    self->next = (ucaller >= $1 && ucaller < $2);


pid$target:::return,syscall:::return
/pid==$target && self->next && !self->current/

    printf("Returning to target from %s:%s:%s:%s...\n",
        probeprov, probemod, probefunc, probename);
    ustack();
    printf("\n");


pid$target:::return,syscall:::return
/pid==$target/

    self->current = self->next;
 
# dtrace -qs Vision.d 0xFEE10000 0xFEF73000 -p `pgrep -n gedit`

这会产生类似的结果

Returning to target from pid2095:libcairo.so.2.10800.10:cairo_bo_event_compare:return...

              libcairo.so.2.10800.10`cairo_bo_event_compare+0x158
              libc.so.1`qsort+0x51c
              libcairo.so.2.10800.10`_cairo_bo_event_queue_init+0x122
              libcairo.so.2.10800.10`_cairo_bentley_ottmann_tessellate_bo_edges+0x2d
              libcairo.so.2.10800.10`_cairo_bentley_ottmann_tessellate_polygon+0
              .
              .
              .

Returning to target from syscall::pollsys:return...

              libc.so.1`__pollsys+0x15
              libc.so.1`poll+0x81
              libxcb.so.1`_xcb_conn_wait+0xb5
              libxcb.so.1`_xcb_out_send+0x3b
              libxcb.so.1`xcb_writev+0x65
              libX11.so.4`_XSend+0x17c
              libX11.so.4`_XFlush+0x30
              libX11.so.4`XFlush+0x37

【讨论】:

以上是关于dtrace 仅在函数返回特定模块时执行操作的主要内容,如果未能解决你的问题,请参考以下文章

如何在 DTrace 操作中打印 CFStringRef?

仅在 MySQL 中显示特定数据库的函数和过程

在 Node.js 程序上使用 DTrace 时没有函数名称

FreeBSD 用户空间 DTrace 和用户空间的转储函数参数

仅在第一个功能完成后才执行功能 - ios

C 语言字符串模型 ( 两头堵模型 | 将 两头堵模型 抽象成业务模块函数 | 形参返回值 | 函数返回值 | 形参指针判空 | 形参返回值操作 )