systemmap 使用记录
一:内核支持
编译内核以支持systemtap :首先让内核中有调试信息,编译内核时需要加上 -g 标志;其次,你还需要在配置内核时将 Kprobe 和 debugfs 开关打开。
最终效果是,你能在内核 .config 文件中看到下面四个选项是设置的:
CONFIG_DEBUG_INFO
CONFIG_KPROBES
CONFIG_DEBUG_FS
CONFIG_RELAY
二:获取systemtap源码
从此地址 https://sourceware.org/systemtap/ftp/releases下载已经发布的systemtap的源代码
依赖库:https://sourceware.org/elfutils/ftp/
$./configure --host=arm-linux CC=aarch64-linux-gnu-gcc CXX=aarch64-linux-gnu-g++ --prefix=/home/workspace/systemtap-3.3/finstall --disable-translator --with-elfutils=/home/liushichang/arm_gcc_elfutil/include/elfutils --disable-option-checking --disable-nls --enable-FEATRUE=no CFLAGS="-I/home/arm_gcc_elfutil/include/elfutils -I/home/arm_gcc_elfutil/include"
参考:SystemTap
ftbuild stap -r /home/kernel_tmp/linux-4.4.x-klinux -a arm64 -B CROSS_COMPILE=aarch64-linux-gnu- -m soft soft.stp
编译完成后在对应主机上执行如下:
./bin/staprun -x 6717(pid) ./soft.ko
./bin/staprun -x 6717 ./soft.ko ==irq number:dev_name 3,arch_timer->1420 10,eth0->10 14,PHYT0003:00->9 46,0000:0a:00.0->1 ==workqueue wq_thread:work_func ==irq number:dev_name 3,arch_timer->1505 14,PHYT0003:00->148 10,eth0->34 46,0000:0a:00.0->3 ==workqueue wq_thread:work_func
1. 从文件(通常以.stp作为文件名后缀)中读入并运行脚本:stap [选项] 文件名
2. 从标准输入中读入并运行脚本: stap [选项] -
3. 运行命令行中的脚本:stap [选项] -e 脚本
4. 直接运行脚本文件(需要可执行属性并且第一行加上#!/usr/bin/stap):./脚本文件名使用"Ctrl+C"中止SystemTap的运行。
systemtap的选项还在不断的扩展和更新中,其中最常用的选项包括:
-v -- 打印中间信息
-p NUM -- 运行完Pass Num后停止(缺省是运行到Pass 5)
-k -- 运行结束后保留临时文件不删除
-b -- 使用RelayFS文件系统来将数据从内核空间传输到用户空间
-M -- 仅当使用-b选项时有效,运行结束时不合并每个CPU的单独数据文件
-o FILE -- 输出到文件,而不是输出到标准输出
-c CMD -- 启动探测后,运行CMD命令,直到命令结束后退出
-g -- 采用guru模式,允许脚本中嵌入C语句
内核模块签名完成后,便可以使用 staprun 命令手工运行相关内核模块了
命令:
// 注意:签名脚本会将生产的内核模块重命名,需要将名字改回去……(脚本bug) staprun -x {进程号} {内核模块名} > demo.bt
使用帮助文档:https://spacewander.gitbooks.io/systemtapbeginnersguide_zh/content/index.html
systemtap原理
SystemTap采用其他的内核框架做源:静态指针使用tracepoints,动态指针使用Kprobe。用户级别的使用uprobes。
Kprobes 从 2.6.9 版本开始就添加到主流的 Linux 内核中。它提供一些不同的服务,但最重要的两种服务是 Kprobe 和 Kretprobe。
Kprobe 特定于架构,它在需要检查的指令的第一个字节中插入一个断点指令。当调用该指令时,将执行针对探针的特定处理函数。执行完成之后,接着执行原始的指令(从断点开始)。
断点指令(breakpoint instruction):__asm INT 3,机器码为CC。
断点中断(INT3)是一种软中断,当执行到INT 3指令时,CPU会把当时的程序指针(CS和EIP)压入堆栈保存起来,
然后通过中断向量表调用INT 3所对应的中断例程。
INT是软中断指令,中断向量表是中断号和中断处理函数地址的对应表。
INT 3即触发软中断3,相应的中断处理函数的地址为:中断向量表地址 + 4 * 3。
Kretprobes 有所不同,它操作调用函数的返回结果。注意,因为一个函数可能有多个返回点,所以听起来事情有些复杂。不过,它实际使用一种称为 trampoline 的简单技术。您将向函数条目添加一小段代码,而不是检查函数中的每个返回点。这段代码使用 trampoline 地址替换堆栈上的返回地址 (Kretprobe 地址)。当该函数存在时,它没有返回到调用方,而是调用 Kretprobe(执行它的功能),然后从 Kretprobe 返回到实际的调用方。
stap 实用程序将 stap 脚本转换成提供探针行为的内核模块。https://klwork.com/category/018linux/systemtap.html
https://sourceware.org/systemtap/documentation.html
https://files.cnblogs.com/files/codestack/install_systemmap.tar.gz
https://files.cnblogs.com/files/codestack/systemtap-crash.zip
https://sourceware.org/systemtap/tapsets/
其systemmap api 有:https://sourceware.org/systemtap/tapsets/
可参考blog有:https://klwork.com/category/018linux/systemtap.html
https://sourceware.org/systemtap/wiki/WarStories
https://sourceware.org/systemtap/SystemTap_Beginners_Guide/index.html
对于使用systemstp 探测用户态进程 可以参考:
https://blog.csdn.net/wangzuxi/article/details/42976577
https://blog.csdn.net/wangzuxi/article/details/44901285