Systemtap不会显示内核函数中的所有局部变量

时间:2015-06-24 16:10:26

标签: linux linux-kernel kernel systemtap

我正在尝试使用systemtap在内核中调试一些代码。我需要在该函数中打印局部变量的值,但看起来systemtap只能看到函数参数而不能看到该函数中定义的局部变量。这是我的探针脚本。

probe kernel.function("tcp_write_xmit") {
    if( execname() == "bw_client"){
            printf(
               "tcp_write_xmit skb len %d\n",
               $skb
            );
    }
}

当我运行时,我收到以下错误

semantic error: failed to retrieve location attribute for 'skb'
[man error::dwarf] (dieoffset: 0x5bd30b4): identifier 
'$skb' at /home/cca-user/systaptest/txprobe.stp:37:6
source:                    $skb
                           ^
Pass 2: analysis failed.  [man error::pass2]

但是,tcp_write_xmit函数显然有skb

使用-L选项打印可用变量给出了5个变量,这些变量是函数参数,但没有看到局部变量。

root@i-sahmed-node2: /mnt/linux-3.13.0 # stap -L
'kernel.function("tcp_write_xmit")'
kernel.function("tcp_write_xmit@/build/buildd/linux-3.13.0/net/ipv4
/tcp_output.c:1832") $sk:struct sock* $mss_now:unsigned int $nonagle:int  
$push_one:int $gfp:gfp_t

这是我正在运行的内核和systemtap版本

root@i-sahmed-node2: /mnt/linux-3.13.0 # stap --version
Systemtap translator/driver (version 2.3/0.158, Debian version 2.3-1ubuntu1 (trusty))
Copyright (C) 2005-2013 Red Hat, Inc. and others
This is free software; see the source for copying conditions.
enabled features: AVAHI LIBSQLITE3 NSS TR1_UNORDERED_MAP NLS

root@i-sahmed-node2: /mnt/linux-3.13.0 # uname -a
Linux i-sahmed-node2 3.13.0-53-generic #89-Ubuntu SMP Wed May 20 10:34:39 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

任何想法?

3 个答案:

答案 0 :(得分:3)

您正在使用 .function 探针。在此探测中,只有传递给函数的参数是可见的。如果您需要检查局部变量,则需要使用 .statement 探测。

More info about probing

答案 1 :(得分:0)

尝试stap -L 'kernel.statement("tcp_write_xmit@*:*")'以查看调试信息中仍保留哪些语句和变量。确保你的内核没有使用像KCFLAGS += -fno-var-tracking-assignments这样的有害内容来阻碍gcc。

答案 2 :(得分:0)

如果您需要检查局部变量,则需要使用 .statement 探针。一个例子如下:

# script
$ cat trace_statement.stp
probe kernel.statement("*@kernel/events/core.c:11758") {
    printf("func name: %s\n\n", ppfunc())
    printf("local variables: %s\n\n", $$locals)
    printf("pretty print pmu structure: %s\n\n", $pmu$)
    //printf("%s\n", kernel_string(@var("pmu")->name))
    printf("pmu name field: %s\n\n", $pmu->name$)
}


# output
$ stap trace_statement.stp

func name: __do_sys_perf_event_open

local variables: group_leader=? output_event=0x0 event=0xffff001803fa6000 sibling=? attr={...} ctx=? gctx=? event_file=0x0 group={...} task=? pmu=0xffff0008025d6000 event_fd=0x3 move_group=0x0 err=? f_flags=0x80002 cgroup_fd=?

pretty print pmu structure: {.entry={...}, .module=0x0, .dev=0xffff0008025d6c00, .attr_groups=0xffff0008025d6270, .attr_update=0x0, .name="armv8_pmuv3", .type=8, .capabilities=64, .pmu_disable_count=0xffff8000113c6628, .pmu_cpu_context=0xffff8000113c6630, .exclusive_cnt={...}, .task_ctx_nr=0, .hrtimer_interval_ms=4, .nr_addr_filters=0, .pmu_enable=0xffff8000108c9f30, .pmu_disable=0xffff8000108c9e70, .event_init=0xffff8000108c9c64, .event_mapped=0x0, .event_unmapped=0x0, .add=0xffff8000108ca1c0, .del=0xffff8000108ca600, .start=0xffff8

pmu name field: "armv8_pmuv3"

probe kernel.statement("*@kernel/events/core.c:11758") 在第 11756 行探测内核文件 core.c

$$vars 包括探测点范围内的每个变量,$$locals 扩展为仅包含局部变量的 $$vars 子集。

我们可以直接通过名字访问局部变量pmu$ 后缀可用于漂亮地打印数据结构。

可以链接 -> 运算符以查看数据中包含的数据结构 结构并遵循指向其他数据结构的指针。因此我们使用 $pmu->name 来访问数据结构的 name 字段。

您可以参考https://sourceware.org/systemtap/SystemTap_Beginners_Guide/了解更多详情。