我有一个系统点击脚本,用于探测内核功能“ 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))
已安装以下内核软件包:
答案 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
...因此,临时代码必须容忍色域。