SystemTap应用跟踪探测的使用
用户静态定义探测点USDT
usdt(User-Statically-Defined-Tracepoint)是一种向应用插入跟踪点的技术方案,其特点是跟踪点的插入是静态的,通常需要修改应用的源码并再次编译。该技术方案源于DTrace,不过usdt
应用跟踪的功能在Systemtap和bcc等内核跟踪调试工具中已有良好的支持。Systemtap
开源工具提供了sys/sdt.h
头文件,该头文件没有相应用C代码实现,仅仅提供了多个STAP_PROBExxx
和DTRACE_PROBExxx
宏定义。这些宏定义通过GCC
编译器的内联汇编和段操作在编译成生的ELF
文件中加入一些用于跟踪的信息(主要加入一个nop
机器指令和.note.stapsdt
段信息)。当应用未被跟踪调试时,这些额外的信息不会影响应用的正常功能,也不会造成性能的消耗;当应用被跟踪调试时,Systemtap
或bcc
工具会通过Linux内核修改应用的代码段,将nop
命令替换为陷入Linux内核或调试代码的指令;具体的实现请参考Systemtap
的相关文档。
本文记录用笔者编写的简单usdt
调试应用及在64位arm64/Linux
设备上的调试过程。
跟踪应用层的内存申请与释放
在编写代码前,笔者需要在x86_64/Linux
主机上两次编译Systemtap
:分别为主机和嵌入式ARM设备编译;该操作这里不再详述。之后,笔者编写了以下代码mymalloc.c
,使用sys/sdt.h
中提供的宏,对应用的内存分配函数封装的同时,加入跟踪点:
#include <sys/sdt.h>extern void * __libc_malloc(size_t);
extern void __libc_free(void * ptr);
extern void * __libc_calloc(size_t nmemb, size_t size);
extern void * __libc_realloc(void * ptr, size_t size);void * my_malloc(size_t size)
{void * ret;ret = __libc_malloc(size);DTRACE_PROBE2(mymalloc, my_malloc, size, ret);return ret;
}void my_free(void * ptr)
{DTRACE_PROBE1(mymalloc, my_free, ptr);__libc_free(ptr);
}void * my_calloc(size_t nmemb, size_t size)
{void * ret;ret = __libc_calloc(nmemb, size);DTRACE_PROBE3(mymalloc, my_calloc, nmemb, size, ret);return ret;
}void * my_realloc(void * ptr, size_t size)
{void * ret;ret = __libc_realloc(ptr, size);DTRACE_PROBE3(mymalloc, my_realloc, ptr, size, ret);return ret;
}
使用了以上内存分配函数的封装,由C/C++编写的应用的绝大多数内存分配操作都可以被跟踪到,只需在编译选项中加入-Dmalloc=my_malloc -Dcalloc=my_calloc -Drealloc=my_realloc -Dfree=my_free
宏定义参数并重新编译即可(注意,这些编译参数可能有副作用)。其中,DTRACE_PROBEx
宏会在mymalloc.o
目标文件中引入nop
指令和.note.stapsdt
段信息,同时也支持一些调试参数的传递;这些信息是生成Systemtap
内核调试模块和调试时需要的:
$ aarch64-linux-gnu-objdump -d mymalloc.o
mymalloc.o: file format elf64-littleaarch64
Disassembly of section .text:
0000000000000000 <my_malloc>:0: a9be7bfd stp x29, x30, [sp, #-32]!4: 910003fd mov x29, sp8: f9000bf3 str x19, [sp, #16]c: aa0003f3 mov x19, x010: 94000000 bl 0 <__libc_malloc>14: d503201f nop18: f9400bf3 ldr x19, [sp, #16]1c: a8c27bfd ldp x29, x30, [sp], #3220: d65f03c0 ret24: d503201f nop
0000000000000028 <my_free>:28: d503201f nop2c: 14000000 b 0 <__libc_free>
0000000000000030 <my_calloc>:30: a9be7bfd stp x29, x30, [sp, #-32]!34: 910003fd mov x29, sp38: a90153f3 stp x19, x20, [sp, #16]3c: aa0003f3 mov x19, x040: aa0103f4 mov x20, x144: 94000000 bl 0 <__libc_calloc>48: d503201f nop4c: a94153f3 ldp x19, x20, [sp, #16]50: a8c27bfd ldp x29, x30, [sp], #3254: d65f03c0 ret
0000000000000058 <my_realloc>:58: a9be7bfd stp x29, x30, [sp, #-32]!5c: 910003fd mov x29, sp60: a90153f3 stp x19, x20, [sp, #16]64: aa0003f3 mov x19, x068: aa0103f4 mov x20, x16c: 94000000 bl 0 <__libc_realloc>70: d503201f nop74: a94153f3 ldp x19, x20, [sp, #16]78: a8c27bfd ldp x29, x30, [sp], #327c: d65f03c0 ret
$ aarch64-linux-gnu-readelf -S mymalloc.o
There are 25 section headers, starting at offset 0x20e8:
Section Headers:[Nr] Name Type Address OffsetSize EntSize Flags Link Info Align[ 6] .note.stapsdt NOTE 0000000000000000 000000c80000000000000134 0000000000000000 0 0 4[ 7] .rela.note.stapsd RELA 0000000000000000 000014f800000000000000c0 0000000000000018 I 22 6 8[ 8] .stapsdt.base PROGBITS 0000000000000000 000001fc0000000000000001 0000000000000000 AG 0 0 1
Systemtap
应用调试脚本
笔者将mymalloc.o
链接到简单的调试应用,test-malloc
;并把test-malloc
分别复制到主机和嵌入式设备的/tmp
目录下(仅仅是为了保证应用在主机和嵌入式设备上的路程径一致)。编写Systemtap
脚本,仅仅是将跟踪到的应用内存分配操作输出到调试终端:
$ cat mymalloc.stp
probe process("/tmp/test-malloc").provider("mymalloc").mark("my_malloc")
{printf("malloc(%lx) has returned: %lx\n", $arg1, $arg2);
}
probe process("/tmp/test-malloc").provider("mymalloc").mark("my_calloc")
{printf("calloc(%lx, %lx) has returned: %lx\n", $arg1, $arg2, $arg3);
}
probe process("/tmp/test-malloc").provider("mymalloc").mark("my_realloc")
{printf("realloc(%lx, %lx) has returned: %lx\n", $arg1, $arg2, $arg3);
}
probe process("/tmp/test-malloc").provider("mymalloc").mark("my_free")
{printf("free(%lx) has been invoked\n", $arg1);
}
之后,在x86_64/Linux
主机上使用stap
命令为嵌入式arm64/Linux
设备生成调试的内核模块(这是一个交叉编译的过程,在上一篇文章中笔者提到过):
# stap -v -a arm64 -B CROSS_COMPILE=aarch64-linux-gnu- \-r /home/yejq/program/linux-5.10 -m mymalloc mymalloc.stp
如果以上操作成功执行,就在会操作目录下生名称为mymalloc.ko
的内核模块,需要将该模块复制到嵌入式设备上,任意目录可以选择——接下来就是调试过程了。
在嵌入式设备上跟踪应用的内存操作
首先,需要把Linux内核的符号文件Module.symvers
和配置文件.config
复制到嵌入式设备的固定目录下,因为staprun
相关的命令在执行时可能需要读取这些文件:
# mkdir -p /lib/modules/$(uname -r)/build
# cp .config Modules.symvers /lib/modules/$(uname -r)/build/
之后就可以使用staprun
命令加载Systemtap
内核模块:
# staprun -v -v mymalloc.ko
staprun:main:493 modpath="./mymalloc.ko", modname="mymalloc"
staprun:init_staprun:399 init_staprun
staprun:insert_module:71 inserting module ./mymalloc.ko
staprun:insert_module:97 module options: _stp_bufsize=0
staprun:insert_module:105 module path canonicalized to '/tmp/mymalloc.ko'
staprun:insert_module:191 Module mymalloc inserted from file /tmp/mymalloc.ko
staprun:close_ctl_channel:88 Closed ctl fd 4
execing: /opt/addon/libexec/systemtap/stapio -v -v ./mymalloc.ko -F3
stapio:main:50 modpath="./mymalloc.ko", modname="mymalloc"
stapio:init_stapio:266 init_stapio
stapio:stp_main_loop:470 in main loop
stapio:stp_main_loop:490 select_supported: 1
stapio:init_relayfs:313 initializing relayfs
stapio:init_relayfs:342 attempting to openat trace0
stapio:init_relayfs:342 attempting to openat trace1
stapio:init_relayfs:342 attempting to openat trace2
stapio:init_relayfs:342 attempting to openat trace3
stapio:init_relayfs:366 ncpus=4, nprocs=4, bulkmode=0
stapio:init_relayfs:368 cpui=0, relayfd=0
stapio:init_relayfs:368 cpui=1, relayfd=1
stapio:init_relayfs:368 cpui=2, relayfd=2
stapio:init_relayfs:368 cpui=3, relayfd=3
stapio:init_relayfs:442 starting threads
stapio:stp_main_loop:690 systemtap_module_init() returned 0
接下来打开设备的另一个终端,手动执行/tmp/test-malloc
调试文件,可以看到staprun -v -v ./mymalloc.ko
所在的终端会输出test-malloc
被调试应用的内存分配信息:
malloc(b) has returned: 3119a260
calloc(c, 8) has returned: 3119a280
realloc(0, d) has returned: 3119a2f0
realloc(3119a2f0, e) has returned: 3119a2f0
free(3119a260) has been invoked
free(3119a280) has been invoked
free(0) has been invoked
free(3119a2f0) has been invoked
可见,usdt
跟踪在应用的调试中是很有效的,而且几乎不影响应用的执行效率;这种跟踪调试方案很适合用于大型的嵌入式应用(如音视频服务)的开发过程。在Systemtap
调试脚本mymalloc.stp
的基础上,可以加入一些Hash表,记录每一个应用分配的内存是否会释放,从一定程度上定位到内存是否存在泄露;或者增加一些放问应用的调用栈的操作,可以得到应用中具体分配内存的某个模块,从而深入地观深应用的行为。
SystemTap应用跟踪探测的使用相关推荐
- 用户空间的SystemTap探测是怎么工作的
这篇文章介绍SystemTap在用户层的实现原理.对文档进行了部分摘抄翻译,原文易懂,建议阅读原文:How SystemTap Userspace Probes Work.另外介绍另一篇文档:动态追踪 ...
- Linux中使用Systemtap调试SLUB
<Linux指令:SystemTap内核跟踪和探测工具> 之前的文章曾利用systemtap的"watchpoint"功能来监测变量数值的变化,但systemtap在内 ...
- 【技术干货】听阿里云CDN安防技术专家金九讲SystemTap使用技巧
1.简介 SystemTap是一个Linux非常有用的调试(跟踪/探测)工具,常用于Linux内核或者应用程序的信息采集,比如:获取一个函数里面运行时的变量.调用堆栈,甚至可以直接修改变量的值,对诊断 ...
- BPF学习笔记(五)--Systemtap BPF/BCC bpftrace 实践对比
文章目录 1. 使用BPF/BCC 1.1在centos8操作系统上安装对应的软件二进制包 1.2 源码包安装 1.3 程序示例 2. Systemtap 2.1安装 systemtap 2.2 St ...
- SystemTap使用技巧【四】
1.查看内核文件中函数的执行流程 前段时间研究了一下Linux内核信号处理流程,记录一下用到的技巧吧. 其实如果不用工具,硬是看代码去分析这个信号处理流程的话,还真的可能搞不定,因为不知道看到的代码是 ...
- SystemTap使用指南
1.简介 SystemTap是一个Linux非常有用的调试(跟踪/探测)工具,常用于Linux内核或者应用程序的信息采集,比如:获取一个函数里面运行时的变量.调用堆栈,甚至可以直接修改变量的值,对诊断 ...
- DSTREAM-PT仿真器——ARM公司推出的最高性能的调试跟踪解决方案
2019年4月,ARM公司推出最高性能的调试跟踪解决方案--DSTREAM-PT. DSTREAM-PT具有高性能调试和跟踪功能,快速下载特点,是自适应JTAG时钟速率和并行流跟踪的理想选择. DST ...
- systemtap调试linux内核源码,内核调试工具SystemTap:适合懒人的printk替代品
SystemTap是一个Linux调试和性能分析工具,可用于应用层和内核层的分析,但主要侧重内核层.SystemTab可以在不修改内核代码.不重复编译内核.不重启机器的情况下,收集运行内核的信息并使信 ...
- 跟踪百度服务器的路由信息,路由跟踪
本词条缺少概述图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧! Tracert(跟踪路由)是路由跟踪实用程序,用于确定 IP 数据报访问目标所采取的路径.Tracert 命令用 IP 生存时 ...
最新文章
- 最新的10个优质Python开源项目
- 高性能JavaScript笔记三(编程实践)
- VM虚拟机桥接模式无法联网解决办法
- Python爬虫学到什么程度就可以去找工作了?
- 如何使用async和await这对组合设计统一的取Access Token的函数
- C#中搜索关键词高亮显示
- 栈-线性表(代码、分析、汇编)
- Origin Pro2022教育版官方申请、安装及汉化、续期
- 禁止恶意域名访问服务器方法
- 常用计算机检索算符,计算机信息检索过程中常用的检索表达式
- 情商和逆商比智商更重要
- coffeescript html5,CoffeeScript函数
- Linux使用Maven部署SpiderFlow爬虫平台
- Spring Boot Actuator 端点启用和暴露
- wordpress创建_您可以使用WordPress创建的19种网站类型
- 编译问题追踪 :高通驱动移植 <utils/Log.h>问题
- RJ45隔离变压器作用
- 亚运赛场阿联酋公主亲自上阵 爱骑超千万
- windows10防火墙设置
- 微信小程序使用GoEasy实现websocket实时通讯
热门文章
- 学习笔记-第十二章 恶意代码分析实战
- 将android studio产生的.gradle .android .androidStudio缓存从默认C盘移动到D盘
- acer 驱动程序 linux,Ubuntu扫描仪驱动(Acer 3300U)
- IT-银行运维-广告方案概述
- U3D 自动更新/打Bundle/打包
- ligerui tree mysql_jQuery LigerUI ligerGrid 在开发中的应用记录
- 伤感mp3歌曲打包下载,云盘伤感歌曲打包下载
- 西南大学统考英语计算机有答案吗,2017年西南大学英语网络统考大学英语B复习题...
- 网络小黑揭秘系列之黑产江湖黑吃黑—中国菜刀的隐形把手
- ICV光子盒:2023全球量子通信与安全产业发展展望