在stackoverflow上有人问如何用DTrace访问程序的全局变量(http://stackoverflow.com/questions/11228352/dtrace-accessing-global-variables-from-application),答案也简单,只需知道全局变量的地址,然后把地址作为指针,按照变量的类型,解引用指针即可。所以问题来了,如何得到全局变量地址?
还是以stackoverflow上问题的代码做例子,并假设编译后生成的可执行文件名为a:
#include <stdio.h> int global_var; void change_var(){ global_var++; } int main(void){ change_var(); return 0; }
(1)用printf打印变量地址,这个最简单:“printf(”%p\n”, &global_var);”,但是这需要执行代码一次。
(2)用gdb调试程序,打印地址,同样也要执行一次:
bash-3.2# gdb a GNU gdb (GDB) 7.5 Copyright (C) 2012 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-pc-solaris2.10". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /data1/nan/a...done. (gdb) start Temporary breakpoint 1 at 0x8050c12: file a.c, line 9. Starting program: /data1/nan/a [Thread debugging using libthread_db enabled] [New Thread 1 (LWP 1)] [Switching to Thread 1 (LWP 1)] Temporary breakpoint 1, main () at a.c:9 9 change_var(); (gdb) p &gl glcs glob global_gt global_var globfree globit (gdb) p &global_var $1 = (int *) 0x8060e78 <global_var>
(3)用操作elf文件的命令得到变量地址。以elfdump命令为例:
elfdump a | grep global_var [21] 0x08060e78 0x00000004 OBJT GLOB D 1 .bss global_var [89] 0x08060e78 0x00000004 OBJT GLOB D 0 .bss global_var 18 [21] global_var
知道地址后,就可以用DTrace脚本来观察值了。DTrace脚本如下:
#!/usr/sbin/dtrace -qs pid$target:a:change_var:return { this->global_var = (int32*)copyin(0x8060e78, sizeof(int32)); printf("global_var = %d\n", *this->global_var); }
执行如下命令:
./check.d -c ./a global_var = 1