我有一个系统点击脚本,该脚本探讨内核函数" memcpy"。我想根据SRC缓冲区的内容打印堆栈跟踪。
我的代码:
%{
#include <linux/string.h>
%}
probe begin
{
printf("Beginn");
}
probe kernel.function("memcpy")
{
buffer = @cast($src, "char");
if (isinstr(buffer, "some pattern") != NULL) {
printf("Foundn");
print_backtrace();
}
}
当我运行脚本如下时,此脚本给了我一个错误:" stap -g stacktrace.stp"
未解决的目标符号表达式:标识符'$ src'
语义错误:键入不匹配(字符串):stacktrace.stp:31:14
的标识符"缓冲区"source: if (isinstr(buffer, "shubham") != NULL) { ^
语义错误:类型是在此处推断的(长):标识符"缓冲区":30:2
source: buffer = @cast($src, "char"); ^
通过2:分析失败。[MAN ERROR :: 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
- 内核-3.10.0-514.el7.x86_64
- 内核头 - 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:
buffer = @cast($src, "char");
应该是 char指针而不是 char ?
更新1 :来自SystemTap Docs
语义错误:未解决的目标符号表达式
在无法解析的探针处理程序中提到了一个目标变量。或者,目标变量在诸如脚本函数之类的上下文中根本无效。该变量可能是通过优化编译器来体现的,或者可能没有合适的类型,或者在某处可能只是一个烦人的错误。再次尝试使用略有不同的探针点(使用语句()而不是函数())在同一区域中搜索更合作的邻居。
原始杂物
变量作为友好事物的概念称为 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看到平台的组件。
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
...因此,订阅代码必须忍受范围。