当ftrace用于用户空间

Linux阅码场 2021-03-06 00:00

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__\n"
"__fentry__:\n"
/* save arguments */
"       push %rax\n"
"       push %rdi\n"
"       push %rsi\n"
"       push %rdx\n"
"       push %rcx\n"
"       push %r8\n"
"       push %r9\n"
"       movq %rsp,%rdi\n"
"       call ftracer\n"
"       pop %r9\n"
"       pop %r8\n"
"       pop %rcx\n"
"       pop %rdx\n"
"       pop %rsi\n"
"       pop %rdi\n"
"       pop %rax\n"
"       ret\n");


上面__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(456); 
}
void f1(int a, int b, int c)
{
        f2(789); 
}
main()
{
        ftrace_dump_at_exit(0);
        ftrace_enable();
        f1(123); 
}


函数调用关系: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\n",
                                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 如下图所示:

本公众号持续分享实际工作和学习中关于linux内核的知识总结,偶尔也会出一些视频分享,前不久根据Linux实际工程中的底层需求,设计了一个视频《Linux常见锁和lockup检测机制》发布在了阅码场平台。点击左下角阅读原文可以一键报名和试看。


Linux阅码场 专业的Linux技术社区和Linux操作系统学习平台,内容涉及Linux内核,Linux内存管理,Linux进程管理,Linux文件系统和IO,Linux性能调优,Linux设备驱动以及Linux虚拟化和云计算等各方各面.
评论 (0)
  •  电机转速传感器是工业自动化和控制系统中的重要元件,它们能够实时、准确地测量电机或其他旋转设备的转速,确保系统运行的稳定性和可靠性。随着技术的发展,电机转速传感器的种类和类型日益丰富,以满足不同应用场合的需求。 电机转速传感器是用于测量电机转速的设备,广泛应用于工业自动化、车辆、家电等领域。根据工作原理和应用场景,电机转速传感器主要可以分为以下几种类型: 1、光电传感器: (1)光电编码器:通过光学原理测量转速,通常由一个旋转的编码盘和光源组成。编码盘上有透明和不透明的区域,光源通过编码盘产生脉
    博扬智能 2024-09-14 17:26 195浏览
  • 作者介绍 一、Skydel与NI USRP软件定义架构(Software Defined Architecture)是一种新型的架构模式,它是一种基于软件的架构,通过软件来定义系统的功能,从而提高系统的运行效率和能量效率。软件定义架构可以将硬件资源抽象化,从而使得应用程序可以更好地利用硬件资源,提高系统的性能和可靠性。Skydel GNSS仿真引擎是创新型的软件定义GNSS模拟仿真引擎,它利用PC的GPU的计算能力并借助Nvidia GPU极快的数学计算能力处理星座、频率与轨迹信息,并
    虹科测试测量TM 2024-09-14 15:33 134浏览
  • 在信息安全的诸多领域之中,密码的安全存储无疑已然成为最为核心的问题之一。随着攻击技术的不断演进,传统的密码存储方法已无法抵御现代复杂的威胁。更为安全、健壮的密码存储机制也成为当代信息安全从业者的关注点。本篇文章将引入并介绍密码存储中的基石,关于密码哈希、盐加密(Salting)、密钥派生函数(KDF)的原理及其应用,揭示密码存储中的常见误区,并分享一系列安全实践。一、为什么不能使用明文存储密码直接将密码以明文存储在数据库中无异于为攻击者打开了方便之门。一旦数据库遭遇泄露,攻击者将轻而易举地获得所
    艾体宝IT 2024-09-14 17:40 181浏览
  • 采用快速紧凑的 Raspberry Pi 计算模块3(Raspberry Pi Compute Module 3)的简易设置,为Korg备受推崇的高端乐器提供了一种经济高效的解决方案。解决方案:Compute Module 3企业规模:大型企业行业:音乐技术标志性的乐器制造商Korg起源于20世纪60年代的日本,最初将鼓机推向市场,随后是日本第一台合成器和世界上第一台针式调音器。随着20世纪70年代和80年代电子音乐的兴起,Korg在国际上声名鹊起。随着对功能更强大且更实惠的合成器的需求不断增长
    树莓派开发者 2024-09-14 14:54 138浏览
  • 最近,巴黎奥运会将全球人民的心捆绑在一起,奥林匹克精神的魅力也让低沉已久的大众情绪再度昂扬。在这样一场场顶尖运动员大展身手的体育盛事中,你可能会好奇,运动员们如何在激烈的比赛中保持最佳状态呢?特别是对于耐力运动员?这就不得不提到一个关键因素——体温管理。比如游泳。当地时间8月4日,在巴黎奥运会男子4×100米混合泳接力决赛中,由徐嘉余、覃海洋、孙佳俊、潘展乐组成的中国队夺得金牌。这是中国游泳队首次获得该项目的奥运金牌,更是打破了美国队在该项目奥运会历史上长达40年的金牌垄断。在全民感慨游泳健儿拼
    艾迈斯欧司朗 2024-09-14 17:35 182浏览
  • 随着物联网(IoT)、工业自动化、医疗设备等领域对嵌入式系统的需求不断增加。嵌入式核心板(SOM)作为嵌入式系统的核心组件,其市场需求也随之增长。在快速发展的同时,也面临一定的挑战:如进口芯片供应链不可控、单一平台受地域政策限制、多平台产品开发周期长、开发难度高等问题,米尔电子设计开发了纯FPGA 开发平台,支持一款平台,双芯设计,支持同款底板可换国产和进口芯片,推出MYIR 7A100T和PG2L100H核心板,解决客户对国内国际市场的不同需求。国产开发维护与进口主流出货痛点痛点一 政策受限,
    米尔电子嵌入式 2024-09-14 14:56 109浏览
  • 2024年9月14日,调研咨询机构环洋市场咨询出版的《全球D级全动飞行模拟机行业总体规模、主要厂商及IPO上市调研报告,2024-2030》,主要调研全球D级全动飞行模拟机总体规模,主要地区规模,主要企业规模和份额,主要产品分类规模,下游主要应用规模以及未来发展前景预测。统计维度包括销量、价格、收入,和市场份额。同时也重点分析全球市场主要厂商(品牌)产品特点、产品规格、价格、销量、销售收入及发展动态。历史数据为2019至2023年,预测数据为2024至2030年。 调研机构:Global In
    GIRtina 2024-09-14 11:59 122浏览
  •  电机转速传感器是一种将电机旋转速度转换为可测量电信号的装置,它不仅是电机控制系统中的重要组成部分,更是实现设备精准控制、提高生产效率的关键。无论是风力发电、汽车制造还是工业自动化领域,电机转速传感器都发挥着不可替代的作用。 一、揭秘电机转速传感器的工作原理电机转速传感器的工作原理多种多样,但核心思想都是通过感知电机的旋转运动,并将其转换为电信号输出。以下介绍几种常见的转速传感器类型及其工作原理: (1)磁电式转速传感器 磁电式转速传感器以其结构简单、抗干扰性强而广受青睐。它主要由铁芯、磁钢和感
    博扬智能 2024-09-14 15:59 146浏览
  •  电容位移传感器将继续向更高精度、更高灵敏度、更小型化的方向发展。随着物联网、大数据等技术的不断普及,电容位移传感器将与更多领域相结合,为人类创造更加美好的未来。 一、电容位移传感器的构成 电容位移传感器通常由两个平行极板构成,其中一个极板固定不动,另一个极板与被测物体相连,随被测物体的位移而移动。当被测物体发生位移时,两个极板之间的距离会发生变化,从而导致电容值的变化。通过测量这一变化,就可以准确地知道被测物体的位移量。 二、电容位移传感器的优势 1.高精度:具有极高的测量精度,能够满足各种高
    博扬智能 2024-09-14 15:35 129浏览
  • 2024年9月14日  Global Info Research行业调研机构发布的《全球人工智能实验室行业总体规模、主要厂商及IPO上市调研报告,2024-2030》分析了全球人工智能实验室总体规模,主要地区规模,主要企业规模和份额,主要产品分类规模,下游主要应用规模等。统计维度包括收入和市场份额等。不仅全面分析全球范围内主要企业竞争态势,收入和市场份额等。同时也重点分析全球市场主要厂商(品牌)产品特点、产品规格、收入、毛利率及市场份额、及发展动态。历史数据为2019至2023年,预测
    GIRtina 2024-09-14 13:41 157浏览
我要评论
0
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦