Linux kernel module symbols relocation

来源:互联网 发布:爱微游数据修改 编辑:程序博客网 时间:2024/06/01 07:44

尝试回答两个问题:

1. Module如何解决kernel的函数调用问题

2. Module如何解决使用到其它module的函数调用问题


*.ko是个ELF文件,本质上与跑在user space的APP一样. 从Module编译结果看起:

执行指令: readelf -a usb_wwan.ko,摘录部分与本主题有关系:

00002104  0001801c R_ARM_CALL        00000000   printk0000210c  00018b1c R_ARM_CALL        00001014   usb_serial_get_by_inde

 与printk不一样, usb_serial_get_by_inde来自于usbserial.ko,但是二者在usb_wwan.ko并无值得关注的差别,也就是说此刻,usb_wwan.ko并没区分它所调用的函数来自于何方


那加载usb_wwan.ko的时候,kernel做了些什么事情呢?

load_module干的活太多,我们还是只关注relocation相关细节, simplify_symbols()完成了symbols的处理,看具体细节

load_module() --> simplify_symbols()

case SHN_UNDEF:ksym = resolve_symbol_wait(mod, info, name);
SHN_UNDEF处理了kernel及其他模块的符号,go on...

simplify_symbols() -->resolve_symbol_wait()-->resolve_symbol() -->find_symbol()-->each_symbol_section()

bool each_symbol_section(bool (*fn)(const struct symsearch *arr,    struct module *owner,    void *data), void *data){struct module *mod;static const struct symsearch arr[] = {{ __start___ksymtab, __stop___ksymtab, __start___kcrctab,  NOT_GPL_ONLY, false },{ __start___ksymtab_gpl, __stop___ksymtab_gpl,  __start___kcrctab_gpl,  GPL_ONLY, false },{ __start___ksymtab_gpl_future, __stop___ksymtab_gpl_future,  __start___kcrctab_gpl_future,  WILL_BE_GPL_ONLY, false },#ifdef CONFIG_UNUSED_SYMBOLS{ __start___ksymtab_unused, __stop___ksymtab_unused,  __start___kcrctab_unused,  NOT_GPL_ONLY, true },{ __start___ksymtab_unused_gpl, __stop___ksymtab_unused_gpl,  __start___kcrctab_unused_gpl,  GPL_ONLY, true },#endif};//Kernel EXPORT_SYMBOL        //所以,下面是在kernel的符号表里搜索,找到了就高高兴兴的返回if (each_symbol_in_section(arr, ARRAY_SIZE(arr), NULL, fn, data))return true;        //modules是所有已加载的module的表头,所以开始苦逼的一个模块一个模块的寻找了list_for_each_entry_rcu(mod, &modules, list) {struct symsearch arr[] = {{ mod->syms, mod->syms + mod->num_syms, mod->crcs,  NOT_GPL_ONLY, false },{ mod->gpl_syms, mod->gpl_syms + mod->num_gpl_syms,  mod->gpl_crcs,  GPL_ONLY, false },{ mod->gpl_future_syms,  mod->gpl_future_syms + mod->num_gpl_future_syms,  mod->gpl_future_crcs,  WILL_BE_GPL_ONLY, false },#ifdef CONFIG_UNUSED_SYMBOLS{ mod->unused_syms,  mod->unused_syms + mod->num_unused_syms,  mod->unused_crcs,  NOT_GPL_ONLY, true },{ mod->unused_gpl_syms,  mod->unused_gpl_syms + mod->num_unused_gpl_syms,  mod->unused_gpl_crcs,  GPL_ONLY, true },#endif};                //得之,我幸if (each_symbol_in_section(arr, ARRAY_SIZE(arr), mod, fn, data))return true;}return false;//不得,我命,报错吧}

符号处理完了,下部就是动真格的地址替换了

load_module() -->apply_relocations()-->apply_relocate()

apply_relocate()是个架构相关的函数.


至于post_relocation(), 就是宣告下,大概像什么事情都办完了,可以去民政局领证的意思吧,呵呵


结论:

module对于来自kernel或者来自其他module的函数处理方法一致. module.c帮忙处理了这部分差异. 而load_module真的是劳苦功高,脏活累活都干完了,只要这个函数执行完,新加载的module就跟built in的东西,一样一样的了

0 0
原创粉丝点击