Dtrace中的局部变量

时间:2017-03-28 10:04:32

标签: dtrace

如何使用dtrace访问函数的本地变量?

例如,在下面的代码片段中,我想知道使用dtrace的变量x的值。

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

1 个答案:

答案 0 :(得分:3)

内核代码无法跟踪局部变量,因为没有机制来检测任意内核指令。即使在用户区中,跟踪局部变量也有点复杂,因此,对于您给出的具体示例,跟踪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;

并使用DWARF ...作为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 -24,但DW_OP_fbreg本身必须是DW_AT_frame_base 由父函数DW_OP_reg6的结果代替 属性,即%rbp。 DWARF使用自己的架构不可知 寄存器的编号和到各个寄存器的映射最多 适当的标准机构。在这种情况下,AMD64 ABI告诉我 我们DWARF寄存器6对应x。因此%rbp - 0x18存储在 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; } 。 (有关DWARF本身的更多信息,我推荐Michael Eager's Introduction to the DWARF Debugging Format。)

因此,如果您找到了您所在的源代码行 感兴趣的是偏移量0x32(也许是通过检查DWARF 然后你可以写一个类似的探测器:

# 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

#

这是我在运行演示程序时看到的内容:

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

df = pd.DataFrame({'a': np.random.rand(25)*1000,
                   'b': np.random.rand(25)*1000,
                   'c': np.random.rand(25)})

def handlepick(event):
    artist = event.artist
    lab = artist.get_label()
    if lab in d:
        for ind in event.ind:
            ann = d[lab][ind]
            ann.set_visible(not ann.get_visible() )
    plt.gcf().canvas.draw()


plt.figure()
plt.scatter(data=df, x='a', y='c', c='blue', s='a', alpha=0.5, picker=5, label='a')
plt.scatter(data=df, x='b', y='c', c='red', s='b', alpha=0.5, picker=5, label='b')

d = {"a" : [], "b": []}
for i  in range(len(df)):
    ann = plt.annotate("blue", xy=(df["a"].iloc[i], df["c"].iloc[i]), visible=False)
    d["a"].append(ann)
    ann = plt.annotate("red", xy=(df["b"].iloc[i], df["c"].iloc[i]), visible=False)
    d["b"].append(ann)
plt.gcf().canvas.mpl_connect('pick_event', handlepick)
plt.show()