Linux中ftracer用于用户空间分析

gcc4.6 添加了一个编译选项 -mfentry, 当程序编译之后,程序中的所有函数,除了notrace属性
#define notrace __attribute__((no_instrument_function))
的函数头上都会添加上call __fentry__,占用5个字节,__fentry__函数在程序中可以自定义, 比如在linux kernel中被定义为 retq直接返回。
sym_func_start(__fentry__)
retq
sym_func_end(__fentry__)
定义成retq的意思是我不想直接使用__fentry__, 其实现也是在内核启动的时候把__fentry__换成了nopl, 然后在需要trace内核函数时,再替换成对应的trampoline(中文: 蹦床)。
本篇讲解ftrace(function trace)在用户空间的应用。
以下代码来自此git工程:
https://github.com/x-lugoo/ftracer.git
ftracer.c中对__fentry__函数进行了自定义:
ftracer.c
asm(
“ .globl __fentry__

“__fentry__:

/* save arguments */
“ push %rax

“ push %rdi

“ push %rsi

“ push %rdx

“ push %rcx

“ push %r8

“ push %r9

“ movq %rsp,%rdi

“ call ftracer

“ pop %r9

“ pop %r8

“ pop %rcx

“ pop %rdx

“ pop %rsi

“ pop %rdi

“ pop %rax

“ ret
”);
上面__fentry__函数的实现把所有传参寄存器(x86_64架构)全部压栈,然后把sp指针传给ftracer()的第一个参数。
__attribute__((used)) void ftracer(struct frame *fr)
{
if (!tenabled)
return;
struct trace *t = &tbuf[tcur++];
if (tcur 》= tsize)
tcur = 0;
t-》tstamp = __builtin_ia32_rdtsc();
t-》src = fr-》caller;
t-》dst = fr-》callee;
t-》arg1 = fr-》rdi;
t-》arg2 = fr-》rsi;
t-》arg3 = fr-》rdx;
}
struct frame {
uint64_t r9;
uint64_t r8;
uint64_t rcx;
uint64_t rdx;
uint64_t rsi;
uint64_t rdi;
uint64_t rax;
uint64_t callee;
uint64_t caller;
};
其中callee是被调用函数地址,caller是调用函数地址 ,比如f1()调用f2(), f2函数头上调用了__fentry__, 那么__fentry__ 就可以从frame结构中的rax变量地址之后找到callee和caller
f1() {
call f2
f2() {
call __fentry__
ftracer()的实现把函数调用参数,被调用函数,调用函数,函数执行时间戳都存在tbuf中
使用一个测试程序验证ftrace功能:
test.c
#include “ftracer.h”
#define mb() asm volatile (“” ::: “memory”)
void f3(int a, int b, int c)
{
mb();
}
void f2(int a, int b, int c)
{
f3(4, 5, 6);
}
void f1(int a, int b, int c)
{
f2(7, 8, 9);
}
main()
{
ftrace_dump_at_exit(0);
ftrace_enable();
f1(1, 2, 3);
}
函数调用关系:main-》f1-》f2-》f3
编译:
gcc -c ftracer.cgcc -pg -mfentry ftracer.o test.c -o test
执行。/test的时候调用ftrace_dump(), 打印出tbuf中的数据,
void ftrace_dump(unsigned max)
t = &tbuf[i];
printf(“%llx %llx-》%llx %llx %llx %llx
”,
t-》tstamp,
t-》src, t-》dst,
t-》arg1, t-》arg2, t-》arg3);
tbuf中包含函数调用关系和函数执行时时间戳:
。/test
2b4fcfe84137ab 4008d1-》400893 4 5 6 (f2-》f3)
2b4fcfe8413763 4008fe-》4008ac 7 8 9 (f1-》f2)
2b4fcfe84136ee 40092d-》4008d9 1 2 3 (main-》f1)
以上函数调用关系对应各个函数代码段:
function f2:
0x00000000004008a7 《+0》: callq 0x400657 《__fentry__》
0x00000000004008ac 《+5》: push %rbp
0x00000000004008ad 《+6》: mov %rsp,%rbp
0x00000000004008cc 《+37》: callq 0x40088e 《f3》
0x00000000004008d1 《+42》: nop
0x00000000004008d2 《+43》: leaveq
0x00000000004008d3 《+44》: retq
function f3:
0x000000000040088e 《+0》: callq 0x400657 《__fentry__》
0x0000000000400893 《+5》: push %rbp
0x00000000004008a6 《+24》: retq
function f1
0x00000000004008d4 《+0》: callq 0x400657 《__fentry__》
0x00000000004008d9 《+5》: push %rbp
0x00000000004008f4 《+32》: mov $0x7,%edi
0x00000000004008f9 《+37》: callq 0x4008a7 《f2》
0x00000000004008fe 《+42》: nop
0x00000000004008ff 《+43》: leaveq
0x0000000000400900 《+44》: retq
function main
0x0000000000400901 《+0》: callq 0x400657 《__fentry__》
0x0000000000400928 《+39》: callq 0x4008d4 《f1》
0x000000000040092d 《+44》: mov $0x0,%eax
0x0000000000400932 《+49》: pop %rbp
0x0000000000400933 《+50》: retq
总结:以上分析了ftracer用于用户空间,可以跟踪函数调用参数和函数执行时间戳。
小编最新一直被催更微信公众号文章,我最近一直在设计优化tracer视频课程,内容已经迭代了四五次了,希望到时候能通俗易懂、图文并茂地讲解linux内核中function tracer /function graph/ kprobe/kretprobe/trace event 的最底层原理和应用,预期三月下旬发布。
掌握之后将对linux kernel的研究学习方式和debug方式带来很大的帮助,big picture 如下图所示:
原文标题:当ftrace用于用户空间
文章出处:【微信公众号:linuxer】欢迎添加关注!文章转载请注明出处。


高品质洗烘一体机盘点 衣物即洗即干即穿
小米手表高清图集
加速5G商用步伐,叠境数字与三大运营商共推5G实时全息
现场总线技术有什么优点
基于NanoPin无线电发射器对动物进行追踪保护
Linux中ftracer用于用户空间分析
贸泽与Molex联手推出医疗解决方案专题网站
光敏电阻的主要参数和基本特性
东软睿驰NeuSAR列入AUTOSAR组织20周年纪念册成功案例
【节能学院】AcrelCloud-6800智慧消防管理云平台在某中学的应用
Aqara智能门锁N200开售,支持一体化3D半导体指纹识别
三星芯片代工计划曝光 6nm 5nm和4nm纷纷面世
海康威视为医疗安全问题提供“四维一体”综合安防解决方案
WiFi万能钥匙助力提升行业安全防御能力
新崛起的5款国产手机:一加3T、乐Pro3、小米5C、华为P9、小米MIX确实使人称赞
苹果无人车或明年上路 与大众面包车达成协议
foc控制原理与逻辑电路原理
芯片OS测试原理
D君讲堂|电动压缩机的结构和原理(下篇)
在波形图表中显示波形