IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> linux trace机制分析 - 3.ftrace原理分析 -> 正文阅读

[系统运维]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 exit\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
  1. 未开启CONFIG_FUNCTION_TRACER 时,objdump -d如下:
00000000 <func2>:
   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 <func1>:
  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 <init_module>:
   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 <init_module+0x1c>
  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 <func2>:
   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 <func1>:
  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 <init_module>:
   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 <init_module+0x24>
  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 <func1>:
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 <func2>
8069a6b4:   e59f1014    ldr r1, [pc, #20]   ; 8069a6d0 <func1+0x3c>
8069a6b8:   e1a04000    mov r4, r0
8069a6bc:   e1a02000    mov r2, r0
8069a6c0:   e59f000c    ldr r0, [pc, #12]   ; 8069a6d4 <func1+0x40>
8069a6c4:   ebebe82d    bl  80194780 <printk>
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

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-05-05 12:01:58  更:2022-05-05 12:03:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 17:47:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码