ftrace实现(二)----ftrace_init
__mcount_loc段是如何被处理的:
__mcount_loc段中一共有num_to_init个调用mcount的条目,每个条目将用 dyn_ftrace 存储。并且将各个函数中调用mcount之处的指令全部改为空指令。
具体:
ftrace_init |-->ftrace_dyn_arch_init(&ftrace_stub) |-->*(unsinged long*)ftrace_stub = 0; |-->memcpy(ftrace_nop, content_of_nop_insn, MCOUNT_INSN_SIZE); |-->count = __stop_mcount_loc - __start_mcount_loc; |-->ret = ftrace_dyn_table_alloc(count) |-->ftrace_pages_start = (void*)get_zeroed_page(GFP_KERNEL); |-->struct ftrace_page *pg = ftrace_pages = ftrace_page_start; |-->cnt = num_to_init / ENTRIES_PER_PAGE; | __mcount_loc段中一共有num_to_init个调用mcount的条目,每个条目将用 dyn_ftrace 存储,需要 | 用大量内存存储,每个page_size上将存放ENTRIES_PER_PAGE个dyn_ftrace. | ftrace: allocating 38278 entries in 150 pages | |-->for (i = 0; i < cnt; i++) { 按页大小申请分配空间,并用ftrace_page->next域串接} | |-->last_frace_enabled = ftrace_enabled = 1; |-->ret = ftrace_convert_nops(NULL, __start_mcount_loc, __stop_mcount_loc); |-->把__mcount_loc段的每个条目都用dyn_ftrace存储下来,并把调用mcount指令处的指令替换为空指令 |-->unsigned long *p = __start_mcount_loc; |-->unsigned long addr; |-->while(p < __stop_mcount_loc) { |--> addr = ftrace_call_adjust(*p++); //获取调用mcount的地址 |--> if (!addr) continue; |--> ftrace_record_ip(addr); |-->struct dyn_ftrace *rec; |-->rec = ftrace_alloc_dyn_node(ip);//从ftrace_pages中分配一个dyn_ftrace |-->rec->ip = ip; rec->newlist = ftrace_new_addrs; ftrace_new_addrs = rec; | 完成构造dyn_ftrace |-->} | |-->ftrace_update_code(NULL); |-->struct dyn_ftrace *p; |-->while (ftrace_new_addrs) { |--> p = ftrace_new_addrs; |--> ftrace_new_addrs = p->newlist; |--> p->flags = 0; |--> if (ftrace_code_disable(mod, p)) { //将p->ip处的指令调用,使用ftrace_nop中的空指令代替 |--> p->flags |= FTRACE_FL_CONVERTED; |--> ftrace_update_cnt++; |--> } |-->} |-->ftrace_update_tot_cnt += ftrace_update_cnt; |-->register_module_notifier(&ftrace_module_nb); | 向发布者module_notify_list订阅事件信息,当由事件发生事,将会通知ftrace_module_nb; | |-->set_ftrace_early_filters(); |-->if (ftrace_filter_buf[0]) set_ftrace_early_filter(ftrace_filter_buf, 1); |-->if (ftrace_notrace_buf[0]) set_ftrace_early_filter(ftrace_notrace_buf, 0); set_ftrace_early_filter(char *buf, int eable) |-->char *func; |-->while (buf) { |--> func = strsep(&buf, ","); |--> ftrace_set_regex(func, strlen(func, 0, enable); |-->} ftrace_set_regex(unsigned char *buf, int len, int reset, int enable) |-->if (reset) |--> ftrace_filter_reset(enable) |-->unsigned long type = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE; |-->if (enable) ftrace_filtered = 0; |-->do_for_each_ftrace_rec(pg, rec) { |--> rec->flags &= ~type; |-->} while_for_each_ftrace_rec(); |-->if (buf) |--> ftrace_match_records(buf, len, enable); |-->int type, not; char *search; |-->unsigned long flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE; |-->type = ftrace_setup_glob(buff, len, &search, ¬); |-->search_len = strlen(search); | |-->do_for_each_ftrace_rec(pg, rec) { |--> if (ftrace_match_record(rec, search, search_len, type)) { |--> if (not) rec->flags &= ~flag; |--> else rec->flags |= flag; |--> } |--> if (enable && (rec->flags & FTRACE_FL_FILTER)) ftrace_filtered = 1; |-->} while_for_each_ftrace_rec()
仍然没有解决上一篇的疑问:如果要trace某个函数,那么相应的调用mcount地址是如何被定位到的,又是如何被修改的?
浙公网安备 33010602011771号