2017-03-28 66 views
2

如何使用dtrace訪問函數本地的函數?Dtrace中的局部變量

例如,在下面的代碼片段中,我想通過dtrace知道變量x的值。

void foo(int a){ 
    int x=some_fun(a); 
} 

回答

3

跟蹤局部變量對於內核代碼是不可能的,因爲沒有任何機制來檢測任意內核指令。即使在user-land中,跟蹤局部變量也有些複雜,因此,對於您給出的具體示例,跟蹤some_fun()的返回值會更有意義。

如果你必須跟蹤任意的局部變量,那麼你將需要確定它在特定關注點的位置(通常是寄存器或內存中的位置)。對於簡單的情況,您可以通過分解功能並檢查輸出來完成此操作。對於更復雜的情況,使用DWARF構建對象可能會很有幫助,然後查找本地變量的DIE的DW_AT_location屬性。

你發現變量的位置,你需要用D表示它;請注意,寄存器通過uregs[]陣列暴露。此外,由於dtrace(1)無法理解行號,因此需要使用函數內的偏移量來描述探針。有關更多信息,請參閱Oracle Solaris Dynamic Tracing Guide中的「用戶進程跟蹤」部分。

舉個例子,我寫了包含

int 
foo(int i) 
{ 
    int x; 
    ... 
    for (x = 0; x < 10; x++) 
     i += 2; 

一個簡單的程序,並建立了它,作爲一個AMD64可執行文件,而且矮...

cc -m64 -g -o demo demo.c 

...尋找foo()前其定義爲x輸出 的dwarfdump demo

< 1><0x000000e4> DW_TAG_subprogram 
        DW_AT_name     "foo" 
        ... 
        DW_AT_frame_base   DW_OP_reg6 



< 2><0x00000121>  DW_TAG_variable 
         DW_AT_name     "x" 
         ... 
         DW_AT_location    DW_OP_fbreg -24 

x被描述爲DW_OP_fbreg -24DW_OP_fbreg本身必須是 由父功能的DW_AT_frame_base 屬性的結果被取代,即DW_OP_reg6。 DWARF使用其自己的體系結構不可知的 編號爲寄存器和映射到單個寄存器是高達 適當的標準體。在這種情況下,AMD64 ABI告訴 us DWARF寄存器6對應於%rbp。因此x存儲在 %rbp - 0x18。 (欲瞭解更多有關矮本身,我建議邁克爾·伊格的 Introduction to the DWARF Debugging Format

因此,如果你已經發現,源在你 感興趣的是線的偏移0x32(或許通過檢查DWARF 線表)那麼你可能會寫這樣一探頭:

pid$target:a.out:foo:32 
{ 
    self->up = (uintptr_t)(uregs[R_RBP] - 0x18); 
    self->kp = (int *)copyin(self->up, sizeof (int)); 
    printf("x = %d\n", *self->kp); 
    self->up = 0; 
    self->kp = 0; 
} 

這是我所看到的,當我運行演示程序:

# dtrace -q -s test.d -c /tmp/demo 
x = 1 
x = 2 
x = 3 
x = 4 
x = 5 
x = 6 
x = 7 
x = 8 
x = 9 
x = 10 

# 
+0

我斗膽這是一個容易得多DTrace探測器添加的源代碼,如果pos錫布爾赫丁。請參閱http://www.ibm.com/developerworks/aix/library/au-dtraceprobes.html和https://blogs.oracle。COM/d /項/ adding_dtrace_probes_to_user –