Linux内核的ftrace调试接口

发表于:2013-4-08 09:23

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:nono    来源:51Testing软件测试网采编

  为了抓住一个自定义的内核函数是如何被执行的,需要一定的调试手段,其实就需要一种跟踪手段就可以了,理论上不太复杂,可是Linux内核的调试接口太多了,始终找不到一个方便的,直到遇到了ftrace,它简单的使用文件系统作为接口,不需要安装任何用户态程序,和杂乱的发行版毫无关系,这正合我意,相比SystemTap等复杂的前置设置等调试手段,简直棒极了。因为我很讨厌为了做一件理论上很简单的事而去花去大量的时间去做前置工作

  使用文件系统作为接口的优势自然不必多说,它可以将任意复杂的操作映射到既有的简单的读,写,控制,打开,关闭等简单操作上,ftrace的另一个妙点在于其动态二进制修正技术。其实kprobe也是使用了二进制修正技术,然而它做的很硬,而ftrace则使用了GCC内置的mcount机制,通过重载mcount函数来完成对任意函数调用的统计。

  mcount机制是GCC的一个特性,在任何函数调用时,会纪录关于该函数的一些信息。比如以下的程序:

  mcount.c:

#include <stdio.h>
void  mcount()
{       
    printf("@@@@\n");
}

  gcc -c mcount.c

  main.c:

#include <stdlib.h>
#include <stdio.h>
extern void mcount(void);
void b(int i)
{
        printf("b:%d\n", i);
}
int a(int i)
{
        b(i);
        return 3;
}
int main()
{
        int i = 3;
        int k = a(i);
        return k;
}

  gcc -c main.c -pg

  gcc mcount.o main.o -o test

  执行test,则会发现每个函数调用都会打印出@@@,这说明我们重载mcount成功了。如果能将mcount做成一个只执行ret的stub函数,或者连call mcount一起都执行nop的stub,那么相当于没有这个mcount函数,如果某个时间用户启用了ftrace,则将上述stub替换为真正的trace函数,那不就可以动态开启/关闭trace功能了么?Linux kernel正是这么做的。要想这么做,stub函数要做的足够灵活,以上面的mcount.c/main.c为例,一个比较灵活但不绝对灵活的设计框架如下:

char code[] = {0xc3, 0x90, 0x90...} //0xc3为直接ret

void mcount()
{
    int (*pf)(void);
    pf = &code[0];
    pf();
}

21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号