trace系列1 - function trace学习笔记

本文详细解析了Linux内核Ftrace在ARM64架构下的实现原理,从编译到运行各阶段,展示了如何通过Ftrace跟踪函数调用。

1. 前言

本文主要是根据阅码场 《Linux内核tracers的实现原理与应用》视频课程在aarch64上的实践。通过观察钩子函数的创建过程以及替换过程,理解trace的原理。本文同样以blk_update_request函数为例进行说明。

kernel版本:5.10
平台:arm64

2. ARM64栈帧结构

在开始介绍arm64架构下的ftrace之前,先来简要说明一下arm64栈帧的相关知识。arm64有31个通用寄存器r0-r30,其中r0-r7用于Parameter/result 寄存器; r29为Frame Pointer寄存器,r30为Link寄存器,指向上级函数的返回地址;SP为栈指针。
将以如下代码为例,说明它的栈帧结构:

/*
 * ARCH: armv8
 * GCC版本:aarch64-linux-gnu-gcc (Linaro GCC 5.4-2017.01) 5.4.1 20161213
 */
int fun2(int c,int d)
{
   
   
   return 0;
}

int fun1(int a,int b)
{
   
   
   int c = 1;
   int d = 2;
   
   fun2(c, d);
   return 0;
}

int main(int argc,char **argv)
{
   
   
   int a = 0;
   int b = 1;
   fun1(a,b);
}

aarch64-linux-gnu-objdump -d a.out 反汇编后的结果为:

0000000000400530 <fun2>:
  /* 更新sp到fun2的栈顶 */
  400530:       d10043ff        sub     sp, sp, #0x10
  400534:       b9000fe0        str     w0, [sp,#12]
  400538:       b9000be1        str     w1, [sp,#8]
  40053c:       52800000        mov     w0, #0x0                        // #0
  400540:       910043ff        add     sp, sp, #0x10
  400544:       d65f03c0        ret

0000000000400548 <fun1>:
  /* 分配48字节栈空间,先更新sp=sp-48, 再入栈x29, x30, 此时sp指向栈顶 */
  400548:       a9bd7bfd        stp     x29, x30, [sp,#-48]!
  /* x29、sp指向栈顶*/
  40054c:       910003fd        mov     x29, sp
  /* 入栈fun1参数0 */
  400550:       b9001fa0        str     w0, [x29,#28]
  /* 入栈fun1参数1 */
  400554:       b9001ba1        str     w1, [x29,#24]
  /* 入栈fun1局部变量c */
  400558:       52800020        mov     w0, #0x1                        // #1
  40055c:       b9002fa0        str     w0, [x29,#44]
  /* 入栈fun1局部变量d */
  400560:       52800040        mov     w0, #0x2                        // #2
  400564:       b9002ba0        str     w0, [x29,#40]
  400568:       b9402ba1        ldr     w1, [x29,#40]
  40056c:       b9402fa0        ldr     w0, [x29,#44]
  /* 跳转到fun2 */
  400570:       97fffff0        bl      400530 <fun2>
  400574:       52800000        mov     w0, #0x0                        // #0
  400578:       a8c37bfd        ldp     x29, x30, [sp],#48
  40057c:       d65f03c0        ret

0000000000400580 <main>:
  /* 分配48字节栈空间,先更新sp=sp-48, 再入栈x29, x30, 此时sp指向栈顶*/
  400580:       a9bd7bfd        stp     x29, x30, [sp,#-48]!
  /* x29、sp指向栈顶*/
  400584:       910003fd        mov     x29, sp
  /* 入栈main参数0 */
  400588:       b9001fa0        str     w0, [x29,#28]
  /* 入栈main参数1 */
  40058c:       f9000ba1        str     x1, [x29,#16]
  /* 入栈变量a */
  400590:       b9002fbf        str     wzr, [x29,#44]
  400594:       52800020        mov     w0, #0x1                        // #1
  /* 入栈变量b */
  400598:       b9002ba0        str     w0, [x29,#40]
  40059c:       b9402ba1        ldr     w1, [x29,#40]
  4005a0:       b9402fa0        ldr     w0, [x29,#44]
  /* 跳转到fun1 */
  4005a4:       97ffffe9        bl      400548 <fun1>
  4005a8:       52800000        mov     w0, #0x0                        // #0
  4005ac:       a8c37bfd        ldp     x29, x30, [sp],#48
  4005b0:       d65f03c0        ret
  4005b4:       00000000        .inst   0x00000000 ; undefined

对应栈帧结构为:
在这里插入图片描述
总结一下:
通过对aarch64代码反汇编的分析,可以得出:

  1. 每个函数在入口处首先会分配栈帧空间,且一次分配,确定栈帧顶,之后sp将不再变化;
  2. 每个函数的栈帧顶部存放的是caller的栈帧顶指针,即fun1的栈帧顶存放的是main栈帧顶指针;
  3. 对于最后一级callee函数,由于x29保存了上一级caller的栈顶sp指针,因此不在需要入栈保存,如示例中fun2执行时,此时x29指向fun1的栈帧顶

下面我们将根据是否开启ftrace配置,并区分编译阶段、链接阶段和运行阶段,分别查看钩子函数的替换及构建情况。

3. 编译阶段

3.1 未开启ftrace时的blk_update_request

00000000000012ac <blk_update_request>:
    12ac:       d10183ff        sub     sp, sp, #0x60
    12b0:       a9017bfd        stp     x29, x30, [sp,#16]
    12b4:       910043fd        add     x29, sp, #0x10
    12b8:       a90253f3        stp     x19, x20, [sp,#32]
    12bc:       a9035bf5        stp     x21, x22, [sp,#48]
    12c0
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值