色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

objtrace使用方法與代碼分析

Linux閱碼場 ? 來源:Linux閱碼場 ? 作者:陳松 ? 2022-06-21 09:08 ? 次閱讀

作者介紹:

陳松,畢業于天津大學精密儀器專業。先后在索尼愛立信,意法愛立信和華為技術有限公司任軟件工程師,軟件架構師等職務,主要負責手機內核和應用的開發工作。2019年加入麒麟,現任裝備事業部軟件工程師,主要負責實時內核研發和新技術預研等工作。

1、objtrace和Ftrace的關系

我們在內核代碼調試過程中,經常會遇到需要跟蹤函數參數值變化的情況,objtrace是一個非常有創造性的工具,它可以將我們從笨重的調試工作中解脫出來,讓我們能夠很簡潔,直觀而且優雅的找到我們期望在代碼中發現的內容。

Kprobe和function tracer共建于ftrace的基礎設施,objtrace將二者巧妙的結合起來,在開發者設置了kprobe的時候,objtrace打開了function tracer,并注冊了回調函數。

當代碼運行到kprobe關聯的函數的時候,objtrace將開發者所設定的參數的地址,偏移量,大小等信息保存起來。

之后,當內核代碼運行到任何一個function tracer可以跟蹤的函數的時候,objtrace都會將該函數的參數依次取出來,與已經存儲的,需要跟蹤的參數的地址進行比對,如果發現符合條件的話,就將參數的值打印到ftrace中。

2、如何獲取objtrace源代碼

Objtrace的源碼最早由閱碼場資深用戶JeffXie提交給內核社區,大家可以在github上找到,大家可以下載,編譯,試用,很便捷。目前objtrace應該已經到了v12,大家找到v12的分支即可。作者之前一直在v10上調試,下載代碼的命令:git clone -b objtrace-v10 https://github.com/x-lugoo/linux.git

3、功能描述

我們在開發和調試代碼的過程中,經常會遇到一個場景,變量在函數之間傳遞的過程中,我們需要追蹤這個變量的值變化的過程,比如下面這個例子中的bio:

bio_add_page(struct bio *bio ...) -->__bio_try_merge_page(bio ...) -->         bio_flagged(bio...)   __bio_add_page(bio...)...

通常,我們會增加很多printk,然后編譯安裝內核,重啟。如果有的函數分支忽略掉的話,還需要再增加printk,再次編譯安裝內核和重啟,是不是很笨重?

內核中的kprobe提供了可以不用修改代碼而直接查看函數參數值的方法:

cd /sys/kernel/debug/tracingecho 'p bio_add_page arg1=$arg1 arg2=$arg2' > ./kprobe_eventsecho 1 > events/kprobes/p_bio_add_page_0/enablecat your_file > /dev/nullcat trace
     jbd2/sda5-8-220     [000] ...1. 55531.677782: p_bio_add_page_0: (bio_add_page+0x0/0x90) arg1=0xffff8ecac98aba00 arg2=0xfffff58a0122a400     jbd2/sda5-8-220     [000] ...1. 55531.677786: p_bio_add_page_0: (bio_add_page+0x0/0x90) arg1=0xffff8ecac98abc00 arg2=0xfffff58a04141140     jbd2/sda5-8-220     [000] ...1. 55531.677790: p_bio_add_page_0: (bio_add_page+0x0/0x90) arg1=0xffff8ecac98ab100 arg2=0xfffff58a02e9f880     jbd2/sda5-8-220     [000] ...1. 55531.677794: p_bio_add_page_0: (bio_add_page+0x0/0x90) arg1=0xffff8ecac98ab300 arg2=0xfffff58a041d1b00     jbd2/sda5-8-220     [000] ...1. 55531.677798: p_bio_add_page_0: (bio_add_page+0x0/0x90) arg1=0xffff8ecac98ab600 arg2=0xfffff58a04141280...

Kprobe利用了ftrace中function tracer的架構,將代碼段中__fentry__(或__mcount)替換為kprobe_ftrace_handler,kprobe_ftrace_handler將函數名稱和參數值打印到了ftraceringbuffer之中。

但還有一個問題,kprobe只能追蹤變量在bio_add_page內的值,不能跟蹤變量在其之后的變化。

國內社區的jeff老師近期開發了objtrace可以實現變量持續跟蹤的功能,objtrace結合使用了kprobe和function tracer的功能,持續跟蹤一個或多個變量,同時還可以設置偏移量,獲取變量結構內部元素的值。

目前objtrace正在評審中,很快就會進入到內核代碼樹的主線。

4、使用方法

1)進入debugfs的目錄:

cd /sys/kernel/debug/tracing

2)設置kprobe

echo 'p bio_add_page arg1=$arg1 arg2=$arg2' > ./kprobe_events查看kprobe:ls events/kprobes/ -al里面增加了p_bio_add_page_0cat events/kprobes/p_bio_add_page_0/trigger# Available triggers:# traceon traceoff snapshot stacktrace enable_event disable_event enable_hist disable_hist hist objtrace
可以看到除了原有的traceon traceoff snapshot stacktrace之外,增加了一個新的觸發器objtrace

3)設置objtrace

echo 'objtracearg1,0x285 if comm == "cat"' > ./events/kprobes/p_bio_add_page_0/trigger表示在kprobe:bio_add_page需要跟蹤第一個參數,也就是結構bio偏移量為0x28的變量的值。cat events/kprobes/p_bio_add_page_0/triggerobjtracearg1,0x28count=0 if comm == "cat"

4)觸發

cat your_file > /dev/null  //讀取一個大文件,觸發bio_add_page,也就是內核需要調用到bio_add_page函數

5)查看日志

cat trace# tracer: nop## entries-in-buffer/entries-written: 309/401   #P:4##                                _-----=> irqs-off/BH-disabled#                               / _----=> need-resched#                              | / _---=> hardirq/softirq#                              || / _--=> preempt-depth#                              ||| / _-=> migrate-disable#                              |||| /     delay#           TASK-PID     CPU#  |||||  TIMESTAMP  FUNCTION#              | |         |   |||||     |         |    kworker/3:1H-79      [003] ...1.   248.076143: wbt_issue <-__rq_qos_issue object:0xffffa0c886cc8700 value:0x1000    kworker/3:1H-79      [003] ...1.   248.076143: blk_add_timer <-blk_mq_start_request object:0xffffa0c886cc8700 value:0x1000##### CPU 1 buffer started ####          -0       [001] .Ns2.   248.080898: bio_endio <-blk_update_request object:0xffffa0c886cc8700 value:0x0          -0       [001] .Ns2.   248.080900: __rq_qos_done_bio <-bio_endio object:0xffffa0c886cc8700 value:0x0          -0       [001] .Ns2.   248.080900: bio_uninit <-bio_endio object:0xffffa0c886cc8700 value:0x0          -0       [001] .Ns2.   248.080901: bio_uninit <-bio_endio object:0xffffa0c886cc8700 value:0x0          -0       [001] .Ns2.   248.080901: __rcu_read_lock <-bio_uninit object:0xffffa0c886cc8700 value:0x0-0[001].Ns2.248.080901:__rcu_read_lock<-bio_uninit?object:0xffffa0c886cc8700?value:0x0

5、代碼分析

5.1初始化

初始化就是讓內核的ftrace架構知道有objtrace這樣的一個trigger(觸發器),當開發者創建一個kprobe的時候,在這個kprobetrigger目錄下,會出現objtrace的選項。代碼流程如下:

start_kernel -->trace_init -->trace_event_init -->event_trace_enable -->register_trigger_cmds -->register_trigger_object_cmd -- > register_event_command(&trigger_object_cmd); 注冊trigger_object_cmdtrigger_object_cmd包含了event_command所需要的函數,如event_object_trigger_parse就是工程是輸入objtrace:add...之后,將這個字符串解析的過程。static struct event_command trigger_object_cmd = {     .name           = "objtrace",     .trigger_type       = ETT_TRACE_OBJECT,     .flags          = EVENT_CMD_FL_NEEDS_REC,     .parse          = event_object_trigger_parse,     .reg            = register_trigger,     .unreg          = unregister_trigger,     .get_trigger_ops    = objecttrace_get_trigger_ops,     .set_filter     = set_trigger_filter, };
此外,start_kernel還有一個路徑初始化objtrace的另一部分start_kernel -->early_trace_init -->tracer_alloc_buffers -->allocate_objtrace_dataallocate_objtrace_data中申請并初始化了一個結構體objtrace_data *obj_data,其中最重要的是obj_data->fops->func = trace_object_events_call,函數trace_object_events_call負責跟蹤參數值并打印到ftrace的ring buffer中,可以說trace_object_events_call是objtrace中最重要的一個函數。注意,此時trace_object_events_call只是放到了obj_data->fops->func中,并沒有開始使用。

5.2設置 “echo 'objtracearg1,0x285 if comm == "cat"' > ./events/kprobes/p_bio_add_page_0/trigger”

當開發者輸入這個命令的時候,系統需要將 'objtracearg1,0x285 if comm == "cat"' 解析出來,并調用event_trigger_register注冊到ftrace中,這樣當內核走到bio_add_page這個函數的時候,就會觸發kprobe。函數調用過程如下:我在event_trigger_set_filter中增加了一個WARN_ONCE,可以看到調用棧,同時在event_object_trigger_parse中增加了一個printk,看到一些變量。通常我都是使用function_grath來看代碼調用的流程,但ftrace本身的函數不能使用ftrace來觀測,這樣會造成遞歸調用,很不幸不是,只能使用這種笨辦法了:[  180.024670] chensong: event_object_trigger_parse add:arg1,0x285, objtrace_cmd:add[  180.024685] ------------[ cut here ]------------[  180.024688] chensong: set_trigger_filter, filter_str:if comm == "cat"[  180.024698] WARNING: CPU: 3 PID: 4332 at kernel/trace/trace_events_trigger.c:1056 set_trigger_filter+0x13d/0x170...[  180.024844] CPU: 3 PID: 4332 Comm: bash Not tainted 5.18.0-rc2-objtrace-v10+ #2[  180.024848] Hardware name: LENOVO YangTianT4900v-00/, BIOS FCKT65AUS 01/12/2015[  180.024851] RIP: 0010:set_trigger_filter+0x13d/0x170[  180.024856] Code: 83 c4 18 44 89 e0 5b 41 5c 41 5d 5d c3 48 89 fa 48 c7 c6 e0 15 23 84 48 c7 c7 15 e4 5a 84 c6 05 27 84 94 01 01 e8 d2 f7 9c 00 <0f> 0b 48 8b 45 d0 e9 f6 fe ff ff e8 73 57 a3 00 48 8b 7b 20 41 bc[  180.024859] RSP: 0018:ffffa28003a77d60 EFLAGS: 00010286...[  180.024879] CR2: 00007fbeb41fa020 CR3: 000000000a0f6003 CR4: 00000000001706e0[  180.024882] Call Trace:[  180.024884]  [  180.024888]  event_trigger_set_filter+0x22/0x30[  180.024894]  event_object_trigger_parse.cold+0x313/0x345[  180.024904]  trigger_process_regex+0xc1/0x110[  180.024908]  event_trigger_write+0x70/0xd0...[  180.024913]  vfs_write+0xc0/0x2b0[  180.024920]  ksys_write+0x67/0xe0[  180.024926]  __x64_sys_write+0x1a/0x20[  180.024931]  do_syscall_64+0x3b/0x90[  180.024937]  entry_SYSCALL_64_after_hwframe+0x44/0xae

event_object_trigger_parse首先解析objtracearg1,0x285,并將結果保存到變量trigger_data中,最后調用event_trigger_register,過程如下:

static int event_object_trigger_parse(struct event_command *cmd_ops,... {     struct event_trigger_data *trigger_data;     struct objtrace_trigger_data *obj_data;           ...     obj_data->field = field;                                             --- (1)     obj_data->obj_offset = offset;     obj_data->obj_value_type_size = obj_value_type_size;     obj_data->tr = file->tr;     snprintf(obj_data->objtrace_cmd, OBJTRACE_CMD_LEN, objtrace_cmd);
     trigger_data = event_trigger_alloc(cmd_ops, cmd, param, obj_data);   ---(2) ...     ret = event_trigger_set_filter(cmd_ops, file, filter, trigger_data); ---(3)     if (ret < 0)         goto out_free;
     ret = event_trigger_register(cmd_ops, file, glob, trigger_data);     ---(4)    ...    } int event_trigger_register(struct event_command *cmd_ops, {       return cmd_ops->reg(glob, trigger_data, file);                      ---(5) } int event_trigger_set_filter(struct event_command *cmd_ops, {       if (param && cmd_ops->set_filter)         return cmd_ops->set_filter(param, trigger_data, file);          ---(6)     return 0; }    
static struct event_command trigger_object_cmd = {    --- (7)    .name           = "objtrace",    .trigger_type       = ETT_TRACE_OBJECT,    .flags          = EVENT_CMD_FL_NEEDS_REC,    .parse          = event_object_trigger_parse,    .reg            = register_trigger,                                      .unreg          = unregister_trigger,    .get_trigger_ops    = objecttrace_get_trigger_ops,    .set_filter     = set_trigger_filter,                                };

  • (1)解析的結果放到objtrace_trigger_data中。

  • (2)同時,將objtrace_trigger_data放置到event_trigger_data中。

  • (3)注冊filter,也就是if comm == "cat"

  • (4)注冊trigger。

  • (5)event_trigger_register就是調用trigger_object_cmd中的.reg,也就是register_trigger。

  • (6)event_trigger_set_filter就是調用trigger_object_cmd中的.set_filter,也就是set_trigger_filter

  • (7)trigger_object_cmd的定義。

objtrace還有一個重要的工作,就是要跟蹤變量的流向,這個就超出了kprobe的功能范圍,需要借助function tracer了,所以kprobe部分還有一個重要的工作,就是使能function tracer。我花了很多時間來找如何使能function tracer的,一直沒有找到。但如果你了解function tracer的話,會知道在使能function tracer,必然會調用ftrace_replace_code來替換代碼段,將__fentry__(或__mcount)替換為ftrace_call,那么我就在ftrace_replace_code中增加一個WARN,看一下調用棧:

增加調試代碼:arch/x86/kernel/ftrace.c  +194  ftrace_replace_code    +static int counter = 0; void ftrace_replace_code(int enable) {                rec = ftrace_rec_iter_record(iter);+               WARN_ONCE(1, "chensong: ip:%pS 
", rec->ip);+               counter++;+               if (counter%100 == 0) +                 printk("chensong:%s, ip:%pS
", __FUNCTION__, rec->ip);輸入echo 'objtracearg1,0x285 if comm == "cat"' > ./events/kprobes/p_bio_add_page_0/trigger后,得到調用棧[  168.674941] chensong: ip:__traceiter_initcall_level+0x0/0x40 [  168.674954] WARNING: CPU: 3 PID: 3032 at arch/x86/kernel/ftrace.c:205 ftrace_replace_code+0x10b/0x1d0...[  168.675108] CPU: 3 PID: 3032 Comm: bash Not tainted 5.18.0-rc2-objtrace-v10+ #6[  168.675112] Hardware name: LENOVO YangTianT4900v-00/, BIOS FCKT65AUS 01/12/2015[  168.675115] RIP: 0010:ftrace_replace_code+0x10b/0x1d0[  168.675121] Code: 89 fe 89 c7 e8 f7 97 b4 00 5b 41 5c 41 5d 41 5e 41 5f 5d c3 48 8b 30 48 c7 c7 78 c5 b8 a5 c6 05 f0 6e ab 01 01 e8 4f f3 b3 00 <0f> 0b eb 80 e8 bc d1 13 00 31 db 45 85 f6 49 c7 c6 30 32 49 a6 0f[  168.675124] RSP: 0018:ffffb8a90299fc78 EFLAGS: 00010286[  168.675128] RAX: 0000000000000000 RBX: ffffffffa6493230 RCX: 0000000000000000...[  168.675149] Call Trace:[  168.675151]  [  168.675156]  ftrace_modify_all_code+0xcc/0x160[  168.675165]  arch_ftrace_update_code+0x9/0x10[  168.675170]  ftrace_run_update_code+0x1a/0x70[  168.675176]  ftrace_startup_enable+0x2e/0x50[  168.675181]  ftrace_startup+0xa8/0x120[  168.675185]  register_ftrace_function+0x25/0x70[  168.675189]  event_object_trigger_init+0x32/0x50[  168.675194]  register_trigger+0x69/0xd0[  168.675200]  event_trigger_register+0x1c/0x20[  168.675204]  event_object_trigger_parse+0x323/0x390[  168.675211]  trigger_process_regex+0xc1/0x110[  168.675216]  event_trigger_write+0x70/0xd0[  168.675221]  vfs_write+0xc0/0x2b0[  168.675228]  ksys_write+0x67/0xe0[  168.675234]  __x64_sys_write+0x1a/0x20[  168.675240]  do_syscall_64+0x3b/0x90[168.675246]entry_SYSCALL_64_after_hwframe+0x44/0xae

這部分代碼也是從register_trigger調用過來的,最終調用了

register_trigger -->event_object_trigger_init --> register_ftrace_function -->ftrace_modify_all_code其中,register_ftrace_function還將&tr->obj_data->fops注冊到function tracer的框架中,那么函數調用function tracer時,function tracer會調用tr->obj_data->fops中的回調函數func,也就是在allocate_objtrace_data中賦值的trace_object_events_call函數,此時trace_object_events_call開始工作。

至此,function tracer被打開,以后內核中所有可以trace的函數,都將要走過function tracer這條路徑,也就是每一個函數調用之后,都會運行到trace_object_events_call中。

5.3觸發 “cat /home/kylin/workspace/opensource/linux-objtrace-jeff/kernel/sched/core.c > /dev/null”

本節是objtrace中最重要的一個環節,當kprobe和objtrace都設置好了,一旦內核調用到bio_add_page,就要開始跟蹤bio這個變量了,objtrace是如何在原有的kprobe的基礎上實現這個功能的呢?

我在閱讀代碼的時候,將這個過程分為兩部分,一個是kprobe,另一個是function tracer,我們先來看看當kprobe被觸發的時候,objtrace做了什么工作:

同樣的,我還是使用了printk和WARN_ONCE來進行調試,我首先在函數set_trace_object中增加了一個WARN_ONCE,得到的調用棧如下:[  248.069971] chensong:set_trace_object, call stack of set trace object[  248.069980] WARNING: CPU: 3 PID: 4343 at kernel/trace/trace_object.c:162 trace_object_trigger+0x184/0x1a0....[  248.070450] Hardware name: LENOVO YangTianT4900v-00/, BIOS FCKT65AUS 01/12/2015[  248.070455] RIP: 0010:trace_object_trigger+0x184/0x1a0[  248.070462] Code: 7a ae 48 c7 c6 2d 69 3d ad e8 28 82 fe ff eb bc 48 c7 c6 60 05 43 ae 48 c7 c7 80 ce 7a ae c6 05 2c 11 95 01 01 e8 db 84 9d 00 <0f> 0b eb 9e 48 85 db 0f 84 16 ff ff ff 48 c7 c0 80 96 bc ae e9 d1[  248.070467] RSP: 0018:ffffb122007d36a8 EFLAGS: 00010086....[  248.070515] Call Trace:[  248.070520]  [  248.070533]  trace_object_count_trigger+0x1e/0x30[  248.070541]  event_triggers_call+0x5d/0xe0
[  248.070556]  trace_event_buffer_commit+0x1a2/0x260[  248.070573]  kprobe_trace_func+0x1ad/0x2a0[  248.070602]  kprobe_dispatcher+0x42/0x70

[  248.070610]  ? bio_add_page+0x1/0x90[  248.070622]  kprobe_ftrace_handler+0x168/0x1f0[  248.070629]  ? bio_add_page+0x5/0x90[  248.070636]  ? __bio_try_merge_page+0x140/0x140[  248.070648]  arch_ftrace_ops_list_func+0xe5/0x160[  248.070655]  ? submit_bh_wbc+0xca/0x140[  248.070677]  ftrace_regs_call+0x5/0x52[  248.070689] RIP: 0010:bio_add_page+0x1/0x90....[  248.070781]  ? bio_add_page+0x5/0x90[  248.070789]  ? submit_bh_wbc+0xca/0x140

我們可以看到,當bio_add_page被觸發之后,進入和kprobe的調用路徑:

bio_add_page -->ftrace_regs_call -->arch_ftrace_ops_list_func-->kprobe_ftrace_handler -->kprobe_dispatcher -->kprobe_trace_func -->event_triggers_call --> trace_object_count_trigger --> set_trace_object

其中trace_object_count_trigger也是trigger_object_cmd中定義的回調函數,在trigger條件符合被觸發的時候被調用,我在set_trace_object中還增加了一個printk,打印obj的地址,也就是需要跟蹤的變量的地址。

   static void set_trace_object(void *obj, int obj_offset,             int obj_value_type_size, struct trace_array *tr){     unsigned long flags;     struct object_instance *obj_ins;     struct objtrace_data *obj_data;
...     obj_ins = &obj_data->traced_obj[atomic_read(&obj_data->num_traced_obj)];     obj_ins->obj = obj;                                     --- (1)     printk("chensong:%s, obj:0x%lx", __FUNCTION__, obj);     obj_ins->obj_value_type_size = obj_value_type_size;     obj_ins->obj_offset = obj_offset;     obj_ins->tr = tr;     /* make sure the num_traced_obj update always appears after traced_obj update */     smp_wmb();     atomic_inc(&obj_data->num_traced_obj);
     //WARN_ONCE(1, "chensong:%s, call stack of set trace object
", __FUNCTION__); out:     raw_spin_unlock_irqrestore(&obj_data->obj_data_lock, flags); }

(1)這個時候內核已經走到了bio_add_page,所以已經知道了bio的地址了,所以需要將bio的地址保存到object_instance的obj中,object_instance中其余的元素保存偏移量,變量大小等信息。

接下來是function tracer的部分,在上一部分講過,開發者運行命令“echo 'objtracearg1,0x285 if comm == "cat"' > ./events/kprobes/p_bio_add_page_0/trigger”之后,function tracer被打開,以后內核中所有可以trace的函數,都將要走過function tracer這條路徑,每一個函數調用之后,都會運行到trace_object_events_call中,trace_object_events_call的代碼如下:

static voidtrace_object_events_call(unsigned long ip, unsigned long parent_ip,        struct ftrace_ops *op, struct ftrace_regs *fregs){    struct pt_regs *pt_regs = ftrace_get_regs(fregs);    int cpu, n;        for (n = 0; n < max_args_num; n++) {            obj = regs_get_kernel_argument(pt_regs, n);                            --- (1)            if (object_exist((void *)obj, tr)) {                                       --- (2)         ...                if (get_object_value(&val, (void *)(obj + obj_offset), val_type_size))  --- (3)                    continue;
                submit_trace_object(ip, parent_ip, obj, val, tr);                     ---(4)            }...}static inline unsigned long regs_get_register(struct pt_regs *regs,                          unsigned int offset){    return *(unsigned long *)((unsigned long)regs + offset);     --- (5)}
static bool object_exist(void *obj, struct trace_array *tr){ ...    for (i = 0; i < max; i++) {        if (obj_data->traced_obj[i].obj == obj)                   --- (6)            return true;    }    return false;}

  • (1)Function tracer使能后,每個可以trace的函數都會調用到trace_object_events_call中,調用棧如下:

Any kernel tracable function -->ftrace_regs_call -->    arch_ftrace_ops_list_func -->          __ftrace_ops_list_func -->              op->func(ip, parent_ip, op, fregs); -->                    trace_object_events_call -->                           get_object_value

trace_object_events_call首先調用regs_get_kernel_argument,依次獲得函數的參數,本例中為bio_add_page的參數。

  • (2)調用object_exist來檢查是不是需要跟蹤的變量,這個變量的地址在開發者輸入cat file > /dev/null之后, 內核代碼走到了bio_add_pagebio就會在set_trace_object中保存到了object_instanceobj中,所以在這個時候,后續函數如果使用了bio,object_exist返回為TRUE。如果內核代碼沒有走到過bio_add_page或者該函數的參數中沒有bio,object_exist會返回FALSE

  • (3)獲取變量值,保存到val中。

  • (4)調用submit_trace_object將value打印到ftrace的ringbuffer中。

  • (5)regs_get_kernel_argument最終會調用到regs_get_register中,返回指定參數的地址。

  • (6)object_exist通過比較地址來判斷,當前函數的參數中是不是包含需要跟蹤的變量。

好了,到此為止,objtrace的大部分工作都結束了,找到了變量,獲得了它的值,并打印到ringbuffer中,很巧妙,避免了大量的printk和WARN這樣笨重的方法。

但objtrace打開了所有函數的function tracer,每個函數都要去調用trace_object_events_call,還有調用object_exist進行變量的比對,會增加一定的系統開銷,所以objtrace最好不用和性能調試的trace一起工作。

5.4打印 cat trace

從debugfs的trace文件中打印到中斷,顯示給開發者,調用棧如下:

[ 1617.394055] chensong:trace_object_print[ 1617.394073] WARNING: CPU: 2 PID: 4761 at kernel/trace/trace_output.c:1567 trace_object_print+0x73/0x90
[ 1617.394733] RIP: 0010:trace_object_print+0x73/0x90[ 1617.394749] Code: c6 83 b5 fa b8 e8 9d 0d 00 00 4c 89 e7 be 0a 00 00 00 e8 d0 0a 00 00 48 c7 c6 30 f5 c2 b8 48 c7 c7 90 b5 fa b8 e8 ec a6 9e 00 <0f> 0b 4c 89 e7 e8 23 37 ff ff 5b 41 5c 5d c3 0f 0b eb 97 66 2e 0f
[ 1617.394841] Call Trace:[ 1617.394850]  [ 1617.394864]  print_trace_line+0x25e/0x570[ 1617.394878]  ? ring_buffer_iter_advance+0x32/0x40[ 1617.394902]  s_show+0x4c/0x160[ 1617.394919]  seq_read_iter+0x2a3/0x450[ 1617.394947]  seq_read+0xee/0x120[ 1617.394983]  vfs_read+0xa7/0x1a0[ 1617.395006]  ksys_read+0x67/0xe0[ 1617.395029]  __x64_sys_read+0x1a/0x20[ 1617.395042]  do_syscall_64+0x3b/0x90[ 1617.395056]  entry_SYSCALL_64_after_hwframe+0x44/0xae

原文標題:Ftrace源碼分析系列之objtrace

文章出處:【微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。

審核編輯:湯梓紅
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 內核
    +關注

    關注

    3

    文章

    1375

    瀏覽量

    40314
  • 調試
    +關注

    關注

    7

    文章

    581

    瀏覽量

    33971
  • 源代碼
    +關注

    關注

    96

    文章

    2945

    瀏覽量

    66793

原文標題:Ftrace源碼分析系列之objtrace

文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    TTL電路分析、工作原理、使用方法

    今天給大家分享的是: TTL電路的分析 、TTL電路 工作原理 、TTL電路 使用方法 。
    發表于 05-18 09:06 ?5160次閱讀
    TTL電路<b class='flag-5'>分析</b>、工作原理、<b class='flag-5'>使用方法</b>

    頻譜分析儀的工作原理和使用方法

    頻譜分析儀的工作原理和使用方法
    發表于 07-16 22:04

    ComponentCodelab——Tablist的使用方法

    讓開發者了解HarmonyOS應用開發常用布局和常用組件之Tablist的使用方法,體驗從工程創建到代碼、布局的編寫,再到編譯構建、部署和運行的全過程。
    發表于 05-08 22:04

    assessPort工具的使用方法

    這里主要講assessPort這個工具的使用方法,所以代碼方面就給官方給的準備1、將代碼編譯燒寫到芯片中,這里assessPort只是個工具,和板子芯片版本沒有關系。2、打開assessPort
    發表于 01-12 08:16

    如何看懂源代碼--(分析代碼方法)

    如何看懂源代碼--(分析代碼方法) ________________________________________我們在寫程式時,有不少時間都是在看別人的
    發表于 02-10 14:40 ?51次下載

    Matlab使用方法和程序設計

    Matlab使用方法和程序設計 實驗一 Matlab使用方法和程序設計一、
    發表于 10-17 00:18 ?5399次閱讀
    Matlab<b class='flag-5'>使用方法</b>和程序設計

    傳感器的使用方法及各種數據分析

    傳感器的使用方法及各種數據分析 ①最小檢測物體與透鏡直徑、靈
    發表于 03-03 14:54 ?7706次閱讀

    示波器的使用方法

    數字萬用表使用方法和示波器的使用方法詳解。
    發表于 03-14 10:38 ?32次下載

    淺談光耦的使用方法_章圣焰

    淺談光耦的使用方法及設計電路的分析技巧
    發表于 10-16 13:44 ?6次下載

    xilinx 原語使用方法

    xilinx 原語使用方法
    發表于 10-17 08:57 ?11次下載
    xilinx 原語<b class='flag-5'>使用方法</b>

    ORCAD PSPICE 使用方法

    ORCAD PSPICE 使用方法
    發表于 10-18 14:52 ?39次下載
    ORCAD PSPICE <b class='flag-5'>使用方法</b>

    示波器的使用方法(三):示波器的使用方法詳解

    示波器的使用方法并非很難,重點在于正確使用示波器的使用方法。往期文章中,小編對模擬示波器的使用方法和數字示波器的使用方法均有所介紹。為增進大家對示波器的
    的頭像 發表于 12-24 20:37 ?3311次閱讀

    土壤分析使用方法是怎樣的

    土壤分析儀【恒美HM-GT4】使用方法是怎樣的。研究與分析土壤養分成分是現代農業生產中的重要步驟,我們知道傳統的土壤化驗必須在實驗室中操作,檢測難、操作難,而且需要專業的化驗人員進行操作
    發表于 05-21 14:06 ?821次閱讀

    頻譜分析儀的使用方法

    頻譜分析儀的使用方法? 頻譜分析儀是一種用于測量電子信號頻譜的儀器,廣泛應用于通信、無線電、音頻等領域。它可以分析信號的頻率、幅度、相位等參數,幫助工程師進行信號
    的頭像 發表于 09-19 16:03 ?2359次閱讀

    手柄控制代碼使用方法

    手柄控制代碼使用方法
    的頭像 發表于 05-15 10:19 ?1885次閱讀
    主站蜘蛛池模板: 国产WW久久久久久久久久| 人性本色联盟| 真实的强视频免费网站| 少妇邻居内射在线| 欧美一级久久久久久久久大| 伦理电影v男人天堂| 久久兔费黄A级毛片高清| 精品久久久久久久高清| seba51久久精品| 亚洲国产成人精品无码区5566 | 菠萝菠萝蜜高清观看在线| 性欧美videosex18嫩| 男人叼女人| 国内精品欧美久久精品| 国产人人为我我为人人澡| 国产成人免费高清视频| 国产黄A片在线观看永久免费麻豆 国产互换后人妻的疯狂VIDEO | 亚洲精品国产自在在线观看 | 99精品久久| bl被教练啪到哭H玉势| 亚洲欧美中文字幕网站大全| 人妻系列合集| 人妻插B视频一区二区三区| 漂亮的保姆3集电影免费观看中文| 欧美精品成人久久网站| 久久99国产综合精品AV蜜桃| 久久成人伊人欧洲精品AV| 老女人与小伙子露脸对白| 蜜芽手机在线观看| 久久国产伦子伦精品| 麻豆AV福利AV久久AV| 免费在线伦理片| 久久才是精品亚洲国产| 久久综合香蕉久久久久久久| 免费三级网址| 日日操日日射| 亚洲 日韩 在线 国产 视频| 色婷婷欧美在线播放内射| 午夜爱情动作片P| 亚洲男同tv| 97影院理论午夜伦不卡偷|