设为首页 加入收藏

TOP

Linux内核模块的加载过程(六)
2014-11-24 08:27:23 来源: 作者: 【 】 浏览:8
Tags:Linux 内核 模块 加载 过程

mod->trace_events = section_objs(hdr, sechdrs, secstrings,
"_ftrace_events",
sizeof(*mod->trace_events),
&mod->num_trace_events);
#endif
#ifdef CONFIG_FTRACE_MCOUNT_RECORD
/* sechdrs[0].sh_size is always zero */
/*
* 获取__mcount_loc段的运行时地址,及其存储的
* 对象的个数。
*/
mod->ftrace_callsites = section_objs(hdr, sechdrs, secstrings,
"__mcount_loc",
sizeof(*mod->ftrace_callsites),
&mod->num_ftrace_callsites);
#endif
#ifdef CONFIG_MODVERSIONS
if ((mod->num_syms && !mod->crcs)
|| (mod->num_gpl_syms && !mod->gpl_crcs)
|| (mod->num_gpl_future_syms && !mod->gpl_future_crcs)
#ifdef CONFIG_UNUSED_SYMBOLS
|| (mod->num_unused_syms && !mod->unused_crcs)
|| (mod->num_unused_gpl_syms && !mod->unused_gpl_crcs)
#endif
) {
err = try_to_force_load(mod,
"no versions for exported symbols");
if (err)
goto cleanup;
}
#endif


/* Now do relocations. */
for (i = 1; i < hdr->e_shnum; i++) {
const char *strtab = (char *)sechdrs[strindex].sh_addr;
unsigned int info = sechdrs[i].sh_info;


/* Not a valid relocation section */
/*
* 如果当前段附加的段的索引大于段的数目,
* 则info不是一个有效的索引,不做处理。
*/
if (info >= hdr->e_shnum)
continue;


/* Don't bother with non-allocated sections */
/*
* 如果段在执行过程中不占内存,则
* 不需要进行处理。
*/
if (!(sechdrs[info].sh_flags & SHF_ALLOC))
continue;


/*
* 如果当前段包含重定向表项,但是没有补齐内容
* 则调用apply_relocate来处理。(只关心64位系统)。
*/
if (sechdrs[i].sh_type == SHT_REL)
err = apply_relocate(sechdrs, strtab, symindex, i,mod);
/*
* 如果当前段包含重定向表项,但是可能有补齐内容
* 则调用apply_relocate_add来处理。
*/
else if (sechdrs[i].sh_type == SHT_RELA)
err = apply_relocate_add(sechdrs, strtab, symindex, i,
mod);
if (err < 0)
goto cleanup;
}


/* Find duplicate symbols */
/*
* 检查模块导出的符号在内核导出的或其他模块
* 导出的符号是否有重复的。
*/
err = verify_export_symbols(mod);
if (err < 0)
goto cleanup;


/* Set up and sort exception table */
/*
* 获取__ex_table段的运行时地址,及其存储的
* 对象的个数。
*/
mod->extable = section_objs(hdr, sechdrs, secstrings, "__ex_table",
sizeof(*mod->extable), &mod->num_exentries);
sort_extable(mod->extable, mod->extable + mod->num_exentries);


/* Finally, copy percpu area over. */
percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr,
sechdrs[pcpuindex].sh_size);


/*
* 初始化模块中字符串表、符号表相关的成员,
* 初始化core section中的字符串表和符号表。
*/
add_kallsyms(mod, sechdrs, hdr->e_shnum, symindex, strindex,
symoffs, stroffs, secstrings, strmap);
/*
* 释放用于字符串表名称映射的位图
*/
kfree(strmap);
strmap = NULL;


if (!mod->taints) {
/*
* 处理用于debug的段,不关注这个。
*/
struct _ddebug *debug;
unsigned int num_debug;


debug = section_objs(hdr, sechdrs, secstrings, "__verbose",
sizeof(*debug), &num_debug);
if (debug)
dynamic_debug_setup(debug, num_debug);
}


err = module_finalize(hdr, sechdrs, mod);
if (err < 0)
goto cleanup;


/* flush the icache in correct context */
/*
* get_fs是用来获取当前进程的地址限制,当当前的限制是
* KERNEL_DS时,内核不会检查参数中的地址类型
*/
old_fs = get_fs();
set_fs(KERNEL_DS);


/*
* Flush the instruction cache, since we've played with text.
* Do it before processing of module parameters, so the module
* can provide parameter accessor functions of its own.
*/
/*
* flush_icache_range函数中没有任何操作,不用考虑。
*/
if (mod->module_init)
flush_icache_range((unsigned long)mod->module_init,
(unsigned long)mod->module_init
+ mod->init_size);
flush_icache_range((unsigned long)mod->module_core,
(unsigned long)mod->module_core + mod->

首页 上一页 3 4 5 6 下一页 尾页 6/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇网络编程常用接口的内核实现----s.. 下一篇shell脚本删除目录下的指定文件

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·Redis on AWS:Elast (2025-12-27 04:19:30)
·在 Spring Boot 项目 (2025-12-27 04:19:27)
·使用华为开发者空间 (2025-12-27 04:19:24)
·Getting Started wit (2025-12-27 03:49:24)
·Ubuntu 上最好用的中 (2025-12-27 03:49:20)