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, &not);
      |-->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地址是如何被定位到的,又是如何被修改的?

 

posted on 2014-12-20 22:05  阿加  阅读(1102)  评论(0)    收藏  举报

导航