当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虚拟化和云计算等各方各面.
评论
  • 在科技飞速发展的今天,医疗电子作为一个融合了医学与电子技术的交叉领域,正以前所未有的速度改变着我们的医疗模式和健康生活。它宛如一颗璀璨的明珠,在医疗领域绽放出耀眼的光芒,为人类的健康福祉带来了诸多惊喜与变革。医疗电子的神奇应用医疗电子的应用范围极为广泛,深入到医疗的各个环节。在诊断方面,各种先进的医学成像设备堪称医生的 “火眼金睛”。X 光、CT、MRI 等成像技术,能够清晰地呈现人体内部的结构和病变情况,帮助医生准确地发现疾病。以 CT 为例,它通过对人体进行断层扫描,能够提供比传统 X 光更
    Jeffreyzhang123 2024-12-27 15:46 116浏览
  • 在当今科技飞速发展的时代,工业电子作为现代制造业的中流砥柱,正以前所未有的速度推动着各个行业的变革与进步。从汽车制造到航空航天,从智能家居到工业自动化,工业电子的身影无处不在,为我们的生活和生产带来了巨大的改变。工业电子的崛起与发展工业电子的发展历程可谓是一部波澜壮阔的科技进化史。追溯到上世纪中叶,电子技术开始逐渐应用于工业领域,最初主要是简单的电子控制装置,用于提高生产过程的自动化程度。随着半导体技术、计算机技术和通信技术的不断突破,工业电子迎来了爆发式的增长。集成电路的发明使得电子设备的体积
    Jeffreyzhang123 2024-12-27 15:40 127浏览
  • 一、前言 回首2024,对于我而言,是充满挑战与收获的一年。在这一年里,我积极参与了论坛的众多活动,不仅拓宽了我的认知边界(有些东西不是你做不到,而是你想不到),还让我在实践中收获了宝贵的经验和。同时,多种多样的论坛活动让我们全方面的接受新东西,连接新知识,多种类型的的活动交织了你我的2024。在这里说一说对过去一年的活动经历,进行一次年终总结,并谈谈我的收获和感受,以及对2025年的展望。二、活动足迹(一)快速体验:机智云Gokit2.0开发板初体验 机智云Gokit2.0开发板的体验活动让大
    无言的朝圣 2024-12-27 14:50 88浏览
  • 在当今这个数字化的时代,电子设备无处不在,从我们手中的智能手机、随身携带的笔记本电脑,到复杂的工业控制系统、先进的医疗设备,它们的正常运行都离不开一个关键的 “幕后英雄”—— 印刷电路板(Printed Circuit Board,简称 PCB)。PCB 作为电子设备中不可或缺的重要部件,默默地承载着电子元件之间的连接与信号传输,是整个电子世界的基石。揭开 PCB 的神秘面纱PCB,简单来说,就是一块由绝缘材料制成的板子,上面通过印刷、蚀刻等工艺形成了导电线路和焊盘,用于固定和连接各种电子元件。
    Jeffreyzhang123 2024-12-27 17:21 113浏览
  • 在当今这个科技飞速发展的时代,物联网(IoT)已经不再是一个陌生的概念,它正以一种前所未有的速度改变着我们的生活和工作方式,像一股无形的力量,将世界紧密地连接在一起,引领我们步入一个全新的智能时代。物联网是什么简单来说,物联网就是通过感知设备、网络传输、数据处理等技术手段,实现物与物、人与物之间的互联互通和智能化管理。想象一下,你的家里所有的电器都能 “听懂” 你的指令,根据你的习惯自动调节;工厂里的设备能够实时监测自身状态,提前预警故障;城市的交通系统可以根据实时路况自动优化信号灯,减少拥堵…
    Jeffreyzhang123 2024-12-27 17:18 98浏览
  • 一、引言无人机,作为近年来迅速崛起的新兴技术产物,正以前所未有的速度改变着众多行业的运作模式,从民用领域的航拍、物流,到工业领域的测绘、巡检,再到军事领域的侦察、打击等,无人机的身影无处不在。为了深入了解无人机的现状,本次调研综合了市场数据、行业报告、用户反馈等多方面信息,全面剖析无人机的发展态势。二、市场规模与增长趋势随着技术的不断进步和成本的逐渐降低,无人机市场呈现出爆发式增长。近年来,全球无人机市场规模持续扩大,预计在未来几年内仍将保持较高的增长率。从应用领域来看,消费级无人机市场依然占据
    Jeffreyzhang123 2024-12-27 17:29 192浏览
  • 引言工程师作为推动科技进步和社会发展的核心力量,在各个领域发挥着关键作用。为深入了解工程师的职场现状,本次调研涵盖了不同行业、不同经验水平的工程师群体,通过问卷调查、访谈等方式,收集了大量一手数据,旨在全面呈现工程师的职场生态。1. 工程师群体基本信息行业分布:调研结果显示,工程师群体广泛分布于多个行业,其中制造业占比最高,达到 90%,其次是信息技术、电子通信、能源等行业。不同行业的工程师在工作内容、技术要求和职业发展路径上存在一定差异。年龄与经验:工程师群体以中青年为主,30 - 45 岁年
    Jeffreyzhang123 2024-12-27 17:39 136浏览
  • 在当今竞争激烈的商业世界中,供应链管理已成为企业生存与发展的核心竞争力之一。它就像一条无形的纽带,将供应商、制造商、分销商、零售商直至最终消费者紧密相连,确保产品和服务能够高效、顺畅地流转。今天,就让我们一同深入探索供应链管理的奥秘。供应链管理是什么简单来说,供应链管理是对从原材料采购、生产制造、产品配送直至销售给最终用户这一整个过程中,涉及的物流、信息流和资金流进行计划、协调、控制和优化的管理活动。它不仅仅是对各个环节的简单串联,更是一种通过整合资源、优化流程,实现整体效益最大化的管理理念和方
    Jeffreyzhang123 2024-12-27 17:27 112浏览
  • 从教师的角度来看,麻省理工学院开除因学术造假的学生,这一决定是合理且必要的。首先,学术诚信是学术研究的基石。在学术界,真实性和原创性是至关重要的。学术造假不仅破坏了学术研究的公正性和准确性,还损害了学术领域的整体声誉。因此,对于任何形式的学术不端行为,包括伪造数据、抄袭等,学校都应采取严厉措施,以维护学术诚信。其次,学校对学生具有管理权,包括对学生的处分权。按照相关规定,学校有权对违纪学生进行警告、严重警告、记过、留校察看、勒令退学、开除学籍等处分。开除学籍是一种严厉的处分,通常适用于严重违反学
    curton 2024-12-28 21:49 79浏览
  • 采购与分销是企业运营中至关重要的环节,直接影响到企业的成本控制、客户满意度和市场竞争力。以下从多个方面介绍如何优化采购与分销:采购环节优化供应商管理供应商评估与选择:建立一套全面、科学的供应商评估体系,除了考虑价格因素,还要综合评估供应商的产品质量、交货期、信誉、研发能力、售后服务等。通过多维度评估,选择那些能够提供优质产品和服务,且与企业战略目标相契合的供应商。建立长期合作关系:与优质供应商建立长期稳定的合作关系,这种合作模式可以带来诸多好处。双方可以在信任的基础上进行深度沟通与协作,共同开展
    Jeffreyzhang123 2024-12-27 17:43 128浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦