如何在SystemTap中获取内核函数的参数并将void指针转换为char?

时间:2019-02-19 05:38:22

标签: debugging systemtap

我有一个系统点击脚本,用于探测内核功能“ memcpy”。我想根据src缓冲区的内容(即空指针)打印堆栈跟踪。

我的代码:

%{
        #include <linux/string.h>
%}
probe begin
{
        printf("Begin\n");
}
probe kernel.function("memcpy")
{
        buffer = @cast($src, "char");
        if (isinstr(buffer, "some pattern") != NULL) {
                printf("Found\n");
                print_backtrace();
        }
}

当我按如下方式运行脚本时,此脚本给我一个错误:“ stap -g stacktrace.stp”

  

未解析的目标符号表达式:标识符'$ src'

     

语义错误:类型不匹配(字符串):stacktrace.stp:31:14处的标识符“缓冲区”

 source:         if (isinstr(buffer, "shubham") != NULL) {
                                ^
     

语义错误:首先在此处推断类型(长整数):标识符'buffer'位于:30:2

   source:         buffer = @cast($src, "char");
                    ^
     

阶段2:分析失败。 [人为错误:: pass2]

我已经在Linux内核代码中看到了memcpy的函数定义,并且该参数仅被命名为src。我无法解析变量名。我尝试使用不同的名称$src$from$s,但没有任何效果。

计算机的内核版本为:3.10.0-514.el7.x86_64(RHEL 7.3(Maipo))

已安装以下内核软件包:

  • kernel-debuginfo-common-x86_64-3.10.0-514.el7.x86_64
  • kernel-3.10.0-514.el7.x86_64
  • kernel-headers-3.10.0-514.el7.x86_64
  • kernel-debuginfo-3.10.0-514.el7.x86_64
  • kernel-devel-3.10.0-514.el7.x86_64

2 个答案:

答案 0 :(得分:0)

更新2:

buffer = @cast($src, "char");

应该是 char指针而不是 char 吗?


更新1 :来自systemtap docs

语义错误:未解析的目标符号表达

在无法解析的探针处理程序中引用了目标变量。或者,目标变量在诸如脚本功能之类的上下文中根本无效。该变量可能已被优化的编译器消除,或者可能没有合适的类型,或者某个地方可能只有令人讨厌的错误。使用稍微不同的探测点重试一次(使用statement()代替function())在同一区域中搜索更协作的邻居。


原始杂物

变量的友好概念称为 src ,仅存在于人类可读的源代码中。查看您的代码。您尚未声明任何名为 src 的变量。

  

我已经在Linux内核代码中看到了memcpy的函数定义,并且参数名为src

是的,但这再次是为了人类的利益。


您缺少的部分是,当将源代码编译到应用程序中时,编译器将整理我们所有的人工构造并将其转换为堆栈偏移量。

警告:为了简单起见,我完全忽略了函数调用约定。

如果您在平台上查看编译的二进制文件,则可以看到一些更好的提示,以了解您需要做什么。假设您使用的是x86系统,您将看到类似以下内容的

memcpy:
  push ebp
  mov ebp, esp
  sub esp, 8

  // The function body starts here and you will see references 
  // to what we recognize as the variable "src" with an instructions like

  mov edi, esp+0
  // That just loaded the EDI register with a reference to the location of src

您可以使用gdb查看平台的程序集。

答案 1 :(得分:0)

用于内核的gcc debuginfo可能在使用memcpy的每个位置保留内联副本的形式参数方面都不一致。

stap -vL 'kernel.function("memcpy").*'

应列出所有站点的个人或摘要。机会大概是

stap -e '
  probe kernel.function("memcpy") 
   { if (@defined($p) && @defined($q)) println($p, " ", $q) }'

可以解决问题。它只会在同时定义了这两个参数的那些探针位置触发println。在我最近的内核中,人们看到了类似...的变化

kernel.function("memcpy@./include/linux/string.h:347").inline /* pc=_stext+0x68c6a */ $q:void const* $p:void*
kernel.function("memcpy@./include/linux/string.h:347").inline /* pc=_stext+0x178ec */ $size:__kernel_size_t $p:void*
kernel.function("memcpy@./include/linux/string.h:347").inline /* pc=_stext+0x15a31 */ $size:__kernel_size_t $q:void const* $p:void*
kernel.function("memcpy@./include/linux/string.h:347").inline /* pc=_stext+0x13f1f */ $size:__kernel_size_t $q:void const* $p:void* $p_size:size_t $q_size:size_t
kernel.function("memcpy@./include/linux/string.h:347").inline /* pc=_stext+0xc717 */ $size:__kernel_size_t $q:void const* $p:void* $p_size:size_t $q_size:size_t

...因此,临时代码必须容忍色域。