DTrace tricks and tips (3) - 訪問程序全局變量

在stackoverflow上有人問如何用DTrace訪問程序的全局變量(http://stackoverflow.com/questions/11228352/dtrace-accessing-global-variables-from-application),答案也簡單,只需知道全局變量的地址,然後把地址作爲指針,按照變量的類型,解引用指針即可。所以問題來了,如何得到全局變量地址?


還是以stackoverflow上問題的代碼做例子,並假設編譯後生成的可執行文件名爲a:

#include 
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 
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:
...
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 

(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

如果你對DTrace感興趣,歡迎關注DTrace公衆號(微信號:chinadtrace,博客地址:http://blog.segmentfault.com/chinadtrace),介紹關於DTrace的使用技巧,經驗分享,話題討論等等。也非常歡迎你轉發給其它對DTrace感興趣的朋友。



發佈了67 篇原創文章 · 獲贊 1 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章