0
我正在用dtrace跟踪一些libc函数。我想做一个谓词,它只在函数返回地址时才执行动作,并进入参数中给定的特定模块。dtrace只有当函数返回到特定模块时才执行动作
copyin(uregs [R_ESP],1)在返回探测器上应该给出我认为的返回地址,我不完全确定它,所以如果有人可以确认,这将是很好的。
但是,然后我需要一种方法来解决这个地址到一个模块,这是可能的,以及如何?
我正在用dtrace跟踪一些libc函数。我想做一个谓词,它只在函数返回地址时才执行动作,并进入参数中给定的特定模块。dtrace只有当函数返回到特定模块时才执行动作
copyin(uregs [R_ESP],1)在返回探测器上应该给出我认为的返回地址,我不完全确定它,所以如果有人可以确认,这将是很好的。
但是,然后我需要一种方法来解决这个地址到一个模块,这是可能的,以及如何?
有一个ucaller
变量,它会给你 保存的程序计数器为uint64_t
和umod()
将 它翻译成相应的模块名称,例如
# 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
结果