GLIBC 2.16 支持systemtap静态检查点
原创文章,转载请注明: 转载自系统技术非业余研究
本文链接地址: GLIBC 2.16 支持systemtap静态检查点
刚@淘宝雕梁 告诉我 GLIBC 2.16 支持systemtap静态检查点,消息源在这里, 摘抄相关部分如下:
* New configure option –enable-systemtap builds SystemTap static probes
into libc for setjmp and longjmp and into libpthread for various operations.
So far the setjmp/longjmp probes and some of the libpthread probes are
provided only for i*86 and x86_64.
Implemented by Roland McGrath and Rayson Ho.
目前主要是在setjmp/longjmp和pthread相关的锁操作,而且只支持 i*86 and x86_64 平台。我们到源码验证下:
从这里下载源码glibc-2.16.0.tar.gz, 解开后简单的grep下:
[~/glibc-2.16.0]$grep -rin LIBC_PROBE . ./sysdeps/i386/__longjmp.S:35: LIBC_PROBE (longjmp, 3, 4@%eax, -4@8(%esp), 4@%edx) ./sysdeps/i386/__longjmp.S:53: LIBC_PROBE (longjmp_target, 3, 4@%eax, -4@8(%esp), 4@%edx) ./sysdeps/i386/__longjmp.S:61: LIBC_PROBE (longjmp, 3, 4@%ecx, -4@%eax, 4@%edx) ./sysdeps/i386/__longjmp.S:68: LIBC_PROBE (longjmp_target, 3, 4@%ecx, -4@%ecx, 4@%edx) ./sysdeps/i386/bsd-_setjmp.S:50: LIBC_PROBE (setjmp, 3, 4@%edx, -4@$0, 4@%ecx) ./sysdeps/i386/setjmp.S:46: LIBC_PROBE (setjmp, 3, 4@%eax, -4@SIGMSK(%esp), 4@%ecx) ./sysdeps/i386/bsd-setjmp.S:52: LIBC_PROBE (setjmp, 3, 4@%eax, -4@$1, 4@%ecx) ./sysdeps/unix/sysv/linux/i386/____longjmp_chk.S:83: LIBC_PROBE (longjmp, 3, 4@%ecx, -4@8(%esp), 4@%edx) ./sysdeps/unix/sysv/linux/i386/____longjmp_chk.S:107: LIBC_PROBE (longjmp_target, 3, 4@%ecx, -4@%eax, 4@%edx) ./sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S:108: LIBC_PROBE (longjmp, 3, LP_SIZE@%RDI_LP, -4@%esi, LP_SIZE@%RDX_LP) ./sysdeps/unix/sysv/linux/x86_64/____longjmp_chk.S:128: LIBC_PROBE (longjmp_target, 3, ./sysdeps/x86_64/__longjmp.S:45: LIBC_PROBE (longjmp, 3, LP_SIZE@%RDI_LP, -4@%esi, LP_SIZE@%RDX_LP) ./sysdeps/x86_64/__longjmp.S:65: LIBC_PROBE (longjmp_target, 3, ./sysdeps/x86_64/setjmp.S:51: LIBC_PROBE (setjmp, 3, LP_SIZE@%RDI_LP, -4@%esi, LP_SIZE@%RAX_LP) ./include/stap-probe.h:26:/* Our code uses one macro LIBC_PROBE (name, n, arg1, ..., argn). ./include/stap-probe.h:41: other headers that use LIBC_PROBE inside their own macros. We ./include/stap-probe.h:47:# define LIBC_PROBE(name, n, ...) \ ./include/stap-probe.h:48: LIBC_PROBE_1 (IN_LIB, name, n, ## __VA_ARGS__) ./include/stap-probe.h:50:# define LIBC_PROBE_1(lib, name, n, ...) \ ./include/stap-probe.h:55:# define LIBC_PROBE_ASM(name, template) \ ./include/stap-probe.h:58:# define LIBC_PROBE_ASM_OPERANDS STAP_PROBE_ASM_OPERANDS ./include/stap-probe.h:64:# define LIBC_PROBE(name, n, ...) \ ./include/stap-probe.h:66: _Bool __libc_probe_args[] = { 0, ## __VA_ARGS__ }; \ ./include/stap-probe.h:67: _Bool __libc_probe_verify_n[(sizeof __libc_probe_args / sizeof (_Bool)) \ ./include/stap-probe.h:69: (void) __libc_probe_verify_n; \ ./include/stap-probe.h:72:# define LIBC_PROBE(name, n, ...) /* Nothing. */ ./include/stap-probe.h:75:# define LIBC_PROBE_ASM(name, template) /* Nothing. */ ./include/stap-probe.h:76:# define LIBC_PROBE_ASM_OPERANDS(n, ...) /* Nothing. */ ./nptl/pthread_join.c:59: LIBC_PROBE (pthread_join, 1, threadid); ./nptl/pthread_join.c:116: LIBC_PROBE (pthread_join_ret, 3, threadid, result, pd->result); ./nptl/pthread_rwlock_wrlock.c:34: LIBC_PROBE (wrlock_entry, 1, rwlock); ./nptl/pthread_rwlock_wrlock.c:47: LIBC_PROBE (wrlock_acquire_write, 1, rwlock); ./nptl/ChangeLog:175: * pthread_create.c (start_thread): Define pthread_start LIBC_PROBE. ./nptl/pthread_mutex_lock.c:52: LIBC_PROBE (mutex_entry, 1, mutex); ./nptl/pthread_mutex_lock.c:133: LIBC_PROBE (mutex_acquired, 1, mutex); ./nptl/pthread_mutex_lock.c:475: LIBC_PROBE (mutex_acquired, 1, mutex); ./nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h:230: LIBC_PROBE (lll_futex_wake, 3, futex, nr, private); \ ./nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S:63: LIBC_PROBE (cond_timedwait, 3, %ebx, 24(%esp), %ebp) ./nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S:44: LIBC_PROBE (rdlock_entry, 1, %ebx) ./nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S:95:1: LIBC_PROBE (lll_lock_wait_private, 1, %ebx) ./nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S:52: LIBC_PROBE (cond_broadcast, 1, %edx) ./nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S:64: LIBC_PROBE (cond_wait, 2, 24(%esp), %ebx) ./nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S:47: LIBC_PROBE (cond_signal, 1, %edi) ./nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S:44: LIBC_PROBE (wrlock_entry, 1, %ebx) ./nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h:231: LIBC_PROBE (lll_futex_wake, 3, futex, nr, private); \ ./nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S:71: LIBC_PROBE (cond_timedwait, 3, %rdi, %rsi, %rdx) ./nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S:34: LIBC_PROBE (rdlock_entry, 1, %rdi) ./nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:91:1: LIBC_PROBE (lll_lock_wait_private, 1, %rdi) ./nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:131:1: LIBC_PROBE (lll_lock_wait, 2, %rdi, %rsi) ./nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S:36: LIBC_PROBE (cond_broadcast, 1, %rdi) ./nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:69: LIBC_PROBE (cond_wait, 2, %rdi, %rsi) ./nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S:37: LIBC_PROBE (cond_signal, 1, %rdi) ./nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S:34: LIBC_PROBE (wrlock_entry, 1, %rdi) ./nptl/pthread_cond_destroy.c:32: LIBC_PROBE (cond_destroy, 1, cond); ./nptl/pthread_cond_broadcast.c:35: LIBC_PROBE (cond_broadcast, 1, cond); ./nptl/pthread_cond_signal.c:38: LIBC_PROBE (cond_signal, 1, cond); ./nptl/pthread_rwlock_destroy.c:27: LIBC_PROBE (rwlock_destroy, 1, rwlock); ./nptl/pthread_mutex_init.c:138: LIBC_PROBE (mutex_init, 1, mutex); ./nptl/pthread_rwlock_rdlock.c:34: LIBC_PROBE (rdlock_entry, 1, rwlock); ./nptl/pthread_rwlock_rdlock.c:55: LIBC_PROBE (rdlock_acquire_read, 1, rwlock); ./nptl/pthread_mutex_timedlock.c:38: LIBC_PROBE (mutex_timedlock_entry, 2, mutex, abstime); ./nptl/pthread_mutex_timedlock.c:178: LIBC_PROBE (mutex_timedlock_acquired, 1, mutex); ./nptl/pthread_mutex_timedlock.c:250: LIBC_PROBE (mutex_timedlock_acquired, 1, mutex); ./nptl/pthread_mutex_timedlock.c:387: LIBC_PROBE (mutex_timedlock_acquired, 1, mutex); ./nptl/pthread_mutex_timedlock.c:490: LIBC_PROBE (mutex_timedlock_acquired, 1, mutex); ./nptl/pthread_mutex_unlock.c:54: LIBC_PROBE (mutex_release, 1, mutex); ./nptl/pthread_mutex_unlock.c:279: LIBC_PROBE (mutex_release, 1, mutex); ./nptl/pthread_mutex_unlock.c:288: LIBC_PROBE (mutex_release, 1, mutex); ./nptl/pthread_cond_wait.c:104: LIBC_PROBE (cond_wait, 2, cond, mutex); ./nptl/pthread_cond_init.c:44: LIBC_PROBE (cond_init, 2, cond, cond_attr); ./nptl/pthread_create.c:304: LIBC_PROBE (pthread_start, 3, (pthread_t) pd, pd->start_routine, pd->arg); ./nptl/pthread_create.c:563: LIBC_PROBE (pthread_create, 4, newthread, attr, start_routine, arg); ./nptl/pthread_rwlock_unlock.c:30: LIBC_PROBE (rwlock_unlock, 1, rwlock); ./nptl/pthread_mutex_destroy.c:29: LIBC_PROBE (mutex_destroy, 1, mutex);
确实验证了官方的说法。 那么这个特性如何的启用呢?
在编译libc的时候 configure –enable-systemtap 就好了。
那么如何验证这些检查点的存在呢? 参看systemtap官网的这篇文章,详细的介绍了静态检查点,参看这里
简单的说就是用 stap -L ‘process(“libc.so”).mark(“*”)’ 看可否列出所有的检查点。
那么这些检查点如何使用呢? 参数如何呢?
文档在这里 ./nptl/DESIGN-systemtap-probes.txt
我们来看下:
Systemtap is a dynamic tracing/instrumenting tool available on Linux. Probes
that are not fired at run time have close to zero overhead.The following probes are available for NPTL:
Thread creation & Join Probes
=============================
pthread_create – probe for pthread_create
arg1 = pointer (pthread_t*) to thread
arg2 = pointer (pthread_attr_t*) to attr
arg3 = pointer (void *) to start_routine
arg4 = arguments to start_routine
pthread_start – probe for actual thread creation
arg1 = struct pthread (members include thread ID, process ID)
arg2 = address of start_routine
arg3 = pointer to the list of arguments
pthread_join – probe for pthread_join
arg1 = thread ID
pthread_join_ret – probe for pthread_join return
arg1 = thread ID
arg2 = return valueLock-related Probes
===================
mutex_init – probe for pthread_mutex_init
arg1 = address of mutex lock
mutex_acquired – probe for succ. return of pthread_mutex_lock
arg1 = address of mutex lock
mutex_timedlock_acquired – probe for succ. return of pthread_mutex_timedlock
arg1 = address of mutex lock
mutex_entry – probe for entry to the pthread_mutex_lock function
arg1 = address of mutex lock
mutex_timedlock_entry – probe for entry to the pthread_mutex_timedlock function
arg1 = address of mutex lock, arg2 = address of timespec
mutex_release – probe for pthread_mutex_unlock after the successful release of a
mutex lock
arg1 = address of mutex lock
mutex_destroy – probe for pthread_mutex_destroy
arg1 = address of mutex lockwrlock_entry – probe for entry to the pthread_rwlock_wrlock function
arg1 = address of rw lock
rdlock_entry – probe for entry to the pthread_rwlock_rdlock function
arg1 = address of rw lockrwlock_destroy – probe for pthread_rwlock_destroy
arg1 = address of rw lock
wrlock_acquire_write – probe for pthread_rwlock_wrlock (after getting the lock)
arg1 = address of rw lock
rdlock_acquire_read – probe for pthread_rwlock_rdlock after successfully getting
the lock
arg1 = address of rw lock
rwlock_unlock – probe for pthread_rwlock_unlock
arg1 = address of rw locklll_lock_wait – probe in low-level (assembly language) locking code, only fired
when futex/FUTEX_WAIT is called (i.e. when trying to acquire a
contented lock)
arg1 = pointer to futex
arg2 = flags passed to the futex system call
lll_lock_wait_private – probe in low-level (assembly language) locking code,
only fired when futex/FUTEX_WAIT is called (i.e. when
trying to acquire a contented lock)
arg1 = pointer to futexlll_futex_wake – probe in low-level (assembly language) locking code, only fired
when futex (FUTEX_WAKE) is called
arg1 = pointer to futex
arg2 = number of processes to wake
arg3 = additional flagsCondition variable Probes
=========================
cond_init – probe for pthread_cond_init
arg1 = condition
arg2 = attr
cond_destroy – probe for pthread_cond_destroy
arg1 = cond
cond_wait – probe for pthread_cond_wait
arg1 = condition
arg2 = mutex lock
cond_timedwait – probe for pthread_cond_timedwait
arg1 = condition
arg2 = mutex lock
arg3 = timespec
cond_signal – probe for pthread_cond_signal
arg1 = condition
cond_broadcast – probe for pthread_cond_broadcast
arg1 = condition
还是很详细的。setjmp/longjmp不常用就算了。
有这些静态检查点的帮助,我们定位libc相关锁的问题就非常方便了,而且只有使用的时候才需要付出性能代价。
祝玩得开心!
Post Footer automatically generated by wp-posturl plugin for wordpress.
使用systemtap脚本应该可以探查到function pointer背后具体的实现函数,但是下面的system tap脚本打印出的始终是函数的地址,请问有什么解决办法吗?
global addr
probe kernel.function(“mpage_readpages”)
{
print(“hit func…\n”)
addr = sprintf(“%p”, $get_block)
exit()
}
probe begin
{
print(“staring probe…\n”);
}
probe end
{
print(“Function address and name are:\n”)
print_stack(addr)
}
Yu Feng Reply:
July 1st, 2012 at 9:43 pm
context-symbols.stp的symname是用来翻译地址和符号的。
原型如下:
function symname:string (addr: long) %{ /* pure */ /* pragma:symbols */
casualfish Reply:
July 1st, 2012 at 10:18 pm
多谢回复,我试了下,输出的还是函数地址,我的系统内核版本是2.6.32-220.el6.i686,是ext4的文件系统,按模块的形式编译。get_block对应的应该是ext4_get_block,但是没有输出。
casualfish Reply:
July 5th, 2012 at 9:29 pm
已经解决了,可以使用–all-modules或者-d 模块名(低版本systemtap没有
–all-modules选项)来加载模块信息,
不过只能使用print_stack输出函数名,symname还是不行。