Dtrace中的局部变量 [英] Local Variables in Dtrace

查看:92
本文介绍了Dtrace中的局部变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用dtrace访问函数局部变量?

How do I access variables local to a function using dtrace?

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

For example, in the following snippet I would like to know the value of variable x using dtrace.

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

推荐答案

对于内核代码来说,跟踪局部变量是不可能的,因为没有机制可以检测任意内核指令.甚至在用户领域,跟踪局部变量也有些复杂,因此,对于您给出的特定示例,改为跟踪some_fun()的返回值会更有意义.

Tracing local variables is impossible for kernel code because there is no mechanism to instrument arbitrary kernel instructions. Even in user-land, tracing local variables is somewhat convoluted and so, for the specific example you give, it would make a lot more sense to trace the return value of some_fun() instead.

如果必须跟踪任意局部变量,则需要确定其在特定兴趣点的位置(通常是寄存器或内存中的位置).对于简单的情况,您可以通过反汇编功能并检查输出来执行此操作.对于更复杂的情况,使用DWARF构建对象,然后找到局部变量的DIE的DW_AT_location属性可能会有所帮助.

If you must trace an arbitrary local variable then you will need to determine its location (typically a register or a location in memory) at the specific point of interest. For simple cases you may be able to do this by disassembling the function and inspecting the output. For more complex cases it may be helpful to build the object with DWARF and then find the DW_AT_location attribute of the local variable's DIE.

您会发现需要用D表示变量的位置;请注意,寄存器通过uregs[]数组公开.此外,由于dtrace(1)无法理解行号,因此您需要使用函数内的偏移量来描述探针.请参见 Oracle Solaris Dynamic 跟踪指南以获取更多信息.

One you find the variable's location you'll need to express it in D; note that registers are exposed through the uregs[] array. Furthermore, you'll need to describe your probe using the offset within the function since dtrace(1) has no way of understanding line numbers. See the section on "User Process Tracing" in the Oracle Solaris Dynamic Tracing Guide for more.

作为一个例子,我编写了一个包含以下内容的简单程序

As an example, I wrote a trivial program containing

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

并使用DWARF将其构建为amd64可执行文件...

and built it, as an amd64 executable, with DWARF...

cc -m64 -g -o demo demo.c

...在输出中查找foo()及其定义x之前 的dwarfdump demo:

...before looking for foo() and its definition of x in the output of 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. DWARF使用自己的架构不可知 寄存器编号以及到单个寄存器的映射最多 适当的标准机构.在这种情况下, AMD64 ABI 告诉 我们知道DWARF寄存器6对应于%rbp.因此x存储在 %rbp - 0x18. (有关DWARF本身的更多信息,我推荐Michael Eager的 DWARF调试格式简介.)

x is described as DW_OP_fbreg -24 but DW_OP_fbreg itself must be substituted by the result of the parent function's DW_AT_frame_base attribute, i.e. DW_OP_reg6. DWARF uses its own architecture-agnostic numbering for registers and the mapping to individual registers is up to the appropriate standards body. In this case, the AMD64 ABI tells us that DWARF register 6 corresponds to %rbp. Thus x is stored at %rbp - 0x18. (For more about DWARF itself I recommend Michael Eager's Introduction to the DWARF Debugging Format.)

因此,如果您发现您所在的源代码行 感兴趣的是偏移量0x32(也许通过检查DWARF 行表),那么您可以编写类似以下内容的探针:

Thus, if you had found that the line of source in which you're interested is at offset 0x32 (perhaps by inspecting the DWARF line table) then you might write a probe like:

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;
}

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

This is what I see when I run the demo program:

# 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

#

这篇关于Dtrace中的局部变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆