栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

linux trace机制分析 - 3.ftrace原理分析

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

linux trace机制分析 - 3.ftrace原理分析

文章目录
  • 简述
  • 编译时处理
  • 链接时处理
  • 系统初始化

简述

默认本篇文章的读者已经了解arm、编译和简单汇编。
arm64采用fpatchable-function-entry而不是pg,这里暂不讨论,扩展了解https://zhuanlan.zhihu.com/p/104683907。

简单叙述ftrace的原理和流程,ftrace的实现依赖3个过程,分别为编译、链接重定位、系统初始化、开启追踪。

  • 编译时:内核开启CONFIG_FUNCTION_TRACER后,编译选项会增加-pg,在每个函数中打上标记;
  • 链接重定位:将编译时标记链接到处理函数;
  • 系统初始化:将函数标记替换为nop指令;
  • 开启追踪:将函数标记替换为ftrace_caller,记录信息。
编译时处理
  1. 当内核开启CONFIG_FUNCTION_TRACER时,kernel Makefile会在编译参数增加-pg。
# The arch Makefiles can override CC_FLAGS_FTRACE. We may also append it later.
ifdef CONFIG_FUNCTION_TRACER
  CC_FLAGS_FTRACE := -pg
endif
  1. 示例驱动代码
int func2(int p1, int p2)
{
        return p1+p2;
}

int func1(int p1, int p2)
{
        return func2(p1, p2);
}

static int __init hello_init(void)
{
    pr_info("hello driver init!n");
    func1(1, 2);
    return 0;
}

static void __exit hello_exit(void)
{
    pr_info("hello driver exitn");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
  1. 未开启CONFIG_FUNCTION_TRACER 时,objdump -d如下:
00000000 :
   0:   e1a0c00d        mov     ip, sp
   4:   e92dd800        push    {fp, ip, lr, pc}
   8:   e24cb004        sub     fp, ip, #4
   c:   e0800001        add     r0, r0, r1
  10:   e89da800        ldm     sp, {fp, sp, pc}

00000014 :
  14:   e1a0c00d        mov     ip, sp
  18:   e92dd800        push    {fp, ip, lr, pc}
  1c:   e24cb004        sub     fp, ip, #4
  20:   e0800001        add     r0, r0, r1
  24:   e89da800        ldm     sp, {fp, sp, pc}

Disassembly of section .init.text:

00000000 :
   0:   e1a0c00d        mov     ip, sp
   4:   e92dd800        push    {fp, ip, lr, pc}
   8:   e24cb004        sub     fp, ip, #4
   c:   e59f0008        ldr     r0, [pc, #8]    ; 1c 
  10:   ebfffffe        bl      0 <_printk>
  14:   e3a00000        mov     r0, #0
  18:   e89da800        ldm     sp, {fp, sp, pc}
  1c:   00000000        .word   0x00000000
  1. 开启CONFIG_FUNCTION_TRACER 时,objdump -d如下:
00000000 :
   0:   e1a0c00d        mov     ip, sp
   4:   e92dd800        push    {fp, ip, lr, pc}
   8:   e24cb004        sub     fp, ip, #4
   c:   e52de004        push    {lr}            ; (str lr, [sp, #-4]!)
  10:   ebfffffe        bl      0 <__gnu_mcount_nc>
  14:   e0800001        add     r0, r0, r1
  18:   e89da800        ldm     sp, {fp, sp, pc}

0000001c :
  1c:   e1a0c00d        mov     ip, sp
  20:   e92dd800        push    {fp, ip, lr, pc}
  24:   e24cb004        sub     fp, ip, #4
  28:   e52de004        push    {lr}            ; (str lr, [sp, #-4]!)
  2c:   ebfffffe        bl      0 <__gnu_mcount_nc>
  30:   e0800001        add     r0, r0, r1
  34:   e89da800        ldm     sp, {fp, sp, pc}

Disassembly of section .init.text:

00000000 :
   0:   e1a0c00d        mov     ip, sp
   4:   e92dd800        push    {fp, ip, lr, pc}
   8:   e24cb004        sub     fp, ip, #4
   c:   e52de004        push    {lr}            ; (str lr, [sp, #-4]!)
  10:   ebfffffe        bl      0 <__gnu_mcount_nc>
  14:   e59f0008        ldr     r0, [pc, #8]    ; 24 
  18:   ebfffffe        bl      0 <_printk>
  1c:   e3a00000        mov     r0, #0
  20:   e89da800        ldm     sp, {fp, sp, pc}
  24:   00000000        .word   0x00000000
  1. 对比可以发现,开启CONFIG_FUNCTION_TRACER 后,编译代码会增加bl 0 <__gnu_mcount_nc>。
链接时处理

如果编译为ko,则链接时是在insmod时进行;如果是编译进内核,vmlinux就是链接后的文件,可以通过反汇编查看。
为方便展示,将上述驱动编译进内核,objdum -d vmlinux如下。

8069a694 :
8069a694:   e1a0c00d    mov ip, sp
8069a698:   e92dd830    push    {r4, r5, fp, ip, lr, pc}
8069a69c:   e24cb004    sub fp, ip, #4
8069a6a0:   e52de004    push    {lr}        ; (str lr, [sp, #-4]!)
8069a6a4:   ebe9d726    bl  80110344 <__gnu_mcount_nc>
8069a6a8:   e0050091    mul r5, r1, r0
8069a6ac:   e1a00005    mov r0, r5
8069a6b0:   ebffffe8    bl  8069a658 
8069a6b4:   e59f1014    ldr r1, [pc, #20]   ; 8069a6d0 
8069a6b8:   e1a04000    mov r4, r0
8069a6bc:   e1a02000    mov r2, r0
8069a6c0:   e59f000c    ldr r0, [pc, #12]   ; 8069a6d4 
8069a6c4:   ebebe82d    bl  80194780 
8069a6c8:   e0850004    add r0, r5, r4
8069a6cc:   e89da830    ldm sp, {r4, r5, fp, sp, pc}

可以看到bl 0 <__gnu_mcount_nc>已经被替换为bl 80110344 <__gnu_mcount_nc>。查看__gnu_mcount_nc实现如下。

80110344 <__gnu_mcount_nc>:
80110344:   e1a0c00e    mov ip, lr
80110348:   e8bd4000    ldmfd   sp!, {lr}
8011034c:   e1a0f00c    mov pc, ip

相当于执行了一个return;。

系统初始化

todo

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/859756.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号