int lookup_module_symbol_name(unsigned long addr, char *symname) 用于返回addr 对应symbol的name
使用的例子如下:
int lookup_symbol_name(unsigned long addr, char *symname)
{
symname[0] = '\0';
symname[KSYM_NAME_LEN - 1] = '\0';
if (is_ksym_addr(addr)) {
unsigned long pos;
pos = get_symbol_pos(addr, NULL, NULL);
/* Grab name */
kallsyms_expand_symbol(get_symbol_offset(pos),
symname, KSYM_NAME_LEN);
return 0;
}
/* See if it's in a module. */
return lookup_module_symbol_name(addr, symname);
}
其源码分享如下:
int lookup_module_symbol_name(unsigned long addr, char *symname)
{
struct module *mod;
//在查找modules 这个list的时候,一定要用preempt_disable()/preempt_enable()来禁止内核抢占
preempt_disable();
list_for_each_entry_rcu(mod, &modules, list) {
// 只查找活动的模块,因此如果模块的state等于MODULE_STATE_UNFORMED就跳过这个模块
if (mod->state == MODULE_STATE_UNFORMED)
continue;
//查看这个地址是否在模块的init和core 段中
if (within_module(addr, mod)) {
const char *sym;
//得到这个地址对应的symbol,get_ksymbol 之前的博文分析过,除了能返回当前addr对应的symbol外,还能返回size和offset,由于这里我们用不到,因此直接传NULL
sym = get_ksymbol(mod, addr, NULL, NULL);
if (!sym)
goto out;
//由于get_ksymbol得到的symbol是在module的init和core 段,因此通过strlcpy 将这个子串copy到用户的buffer symname 中.
strlcpy(symname, sym, KSYM_NAME_LEN);
preempt_enable();
return 0;
}
}
out:
preempt_enable();
return -ERANGE;
}
模块API之lookup_module_symbol_name
最新推荐文章于 2023-08-25 17:12:30 发布