ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ftrace浅析-龙芯64位平台

2020-03-09 22:43:04  阅读:378  来源: 互联网

标签:function ftrace 龙芯 trace ops caller 浅析 函数


 

ftrace 工作原理-龙芯平台

 

一、函数注入trace调用

1.以kernel_thread和sys_fork为例,源代码如图1-1所示:

图1-1 源码

2.在编译内核时,通过 gcc -pg 选项,编译时,函数开头自动插入ftrace_caller调用。

上述两个函数的汇编代码如图1-2所示。

图1-2 代码生成的汇编码

在图1-1的源码中并没有ftrace_caller的调用,但是内核编译完成后却加入调用。

 

3.接下来分析ftrace_caller源码如图1-3所示,汇编代码如图1-4所示。

图1-3 ftrace_caller 源码

 

图1-4   ftrace_caller汇编码

 

二、ftrace运行状态

1.系统启动后默认状态kernel_thread和sys_fork二进制码如图2-1所示,ftrace_caller汇编码如图2-2所示。

图2-1 系统启动后代码二进制指令码

 

图2-2 ftrace_caller系统启动后的指令码

 

对比图2-1和图1-2,发现地址0x8024137c和地址0x802413bc由原来的0x0c085428即跳转ftrace_caller函数的指令在系统启动后变为0(即nop指令)。

对比图2-2和图1-4,发现地址0x802150a0由原来的0x10000027即跳转ftrace_stub函数的指令在系统启动后变为0(即nop指令)。

系统初始化时调用ftrace_init完成上述的改变:ftrace_dyn_arch_init(&addr)函数调用ftrace_modify_code(MCOUNT_ADDR, INSN_NOP)将ftrace_caller开始的 b ftrace

_stub指令修改为nop指令。函数ftrace_process_locs(NULL,__start_mcount_loc,

__stop_mcount_loc)来完成将所有包含jal ftrace_caller的函数该指令修改为nop。Start

_mcount_loc中的内容为所有调用jal ftrace_caller的地址(在编译阶段生成),方便找到地址并修改,该区域中有地址0x0x8024137c(kernel_thread)和地址0x802413bc

(sys_fork)。

 

 

 

2.echo function > current_tracer后系统中的函数和变量的变化

kernel_thread和sys_fork源码的指令码变化如图2-3所示,ftrace_caller源码的指令码变化如图2-4所示。

图2-3 sys_fork & kernel_thread指令码

 

图2-4 ftrace_caller指令码

对比图2-3和图2-1,发现地址0x8024137c和地址0x802413bc由原来的0x0(即nop指令)变为0x0c08542a即跳转ftrace_caller函数地址+8的地址指令处(即0x802150a8)。

对比图2-4和图2-2,发现地址0x80215104由原来的0(nop)修改为0x0c0b9ff2即跳转ftrace_ops_no_ops函数(地址为0x802e7fc8)。

ftrace_ops_no_ops源码如图2-5所示,函数会扫描ftrace_ops_list链表调用注册的函数。

图2-5 ftrace_ops_no_ops源码中的关键函数

通过反汇编看一下ftrace_ops_list链表中的内容,内核编译完成后的内容如图2-6所示,

通过echo function > current_tracer后的内容如图2-7所示。

图2-6 ftrace_ops_list内容

图2-7     ftrace_ops_list中的内容码

通过上图可以,ftrace_ops_list的内容有原来的0x81024060(即ftrace_list_end)修改了0x81037510(即global_ops)。global_ops的内容由原来的0x80215140(即ftrace_stub),修改为0x80301330(即function_trace_call函数)。

目前加入了调用ftrace_caller的函数最终调用的函数为function_trace_call函数。

echo function > current_tracer 该动作所调用的函数为tracing_set_trace_write(),该函数从全局变量trace_types中取出与“function”字符一样的tracer。所有的tracer是调用register_tracer()函数来完成注册的,如function的注册过程如图2-8所示(init阶段完成的)。

         tracing_set_trace_write()函数调用function的中的init函数即function_trace_init来完成其它的初始化,如调用register_ftrace_function(&trace_ops)函数完成trace_ops的注册,将trace_ops加入global_ops链表;如给全局变量ftrace_trace_function赋值等。最终使得调用ftrace_caller可以调用到function_trace_call函数。

 

3.echo function > current_tracer后系统目前可以调用函数,但是真正的trace还没有开始,需要echo 1 > tracing_on后,系统才会开始。

         在函数function_trace_call()则调用trace_function将信息记录在 ring_buffer中。

         echo 1 > tracing_on动作产生调用rb_simple_write(),调用tr->current_trace->start即调用function_trace_start()函数,将buffer->record_disabled减1,将cpu_

buffer-> record_disabled减1来使能记录日志到buffer功能。trace_function记录日志的函数中,其中ring_buffer_lock_reserve会判断两个record_disabled是否已满足要求,如果满足则记录日志,否则退出。

 

 

4.ring_buffer如何工作?

具体可参考:http://blog.chinaunix.net/uid-20543183-id-1930845.html

标签:function,ftrace,龙芯,trace,ops,caller,浅析,函数
来源: https://blog.csdn.net/yuanjunqing/article/details/104762579

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有