/proc/kallsyms 中标有“T”的内核符号未导出
Posted
技术标签:
【中文标题】/proc/kallsyms 中标有“T”的内核符号未导出【英文标题】:kernel symbol marked with "T" in /proc/kallsyms is not exported 【发布时间】:2016-01-03 02:37:16 【问题描述】:符号machine_power_off
在/proc/kallsyms
中标有“T”:
$ grep -w machine_power_off /proc/kallsyms
ffffffff8102391b T machine_power_off
但它是not exported。 kallsyms 中的“T”对于导出符号是否必要且足够?导出是否足够在其他模块中使用?
我使用它的模块编译时出现警告:
WARNING: "machine_power_off" [/path/to/module.ko] undefined!
在主机 (3.2.0-4-amd64) 上我可以加载此模块,但在 VirtualBox (3.16.0-4-amd64) 上会产生以下消息:
insmod: ERROR: could not insert module module.ko: Unknown symbol in module
为什么这个模块在我的主机系统中加载,但在 VirtualBox 中没有?
【问题讨论】:
【参考方案1】:在/proc/kallsyms
中标记“T”表示该符号是全局可见的,并且可以在其他内核代码中使用(例如由驱动程序编译的内置) .
但是为了在内核模块的代码中使用,需要使用EXPORT_SYMBOL
或类似的方式导出符号。导出符号列表与内核中的所有符号列表分开维护。
导出的符号可以在文件/lib/modules/<kernel-version>/build/Module.symvers
中找到。
(该文件应该存在以便可以针对给定内核构建内核模块)。
【讨论】:
是否可以使用dlopen
和dlsym
来回避“仅内核”限制?
@jww:在 Linux 内核世界中,“搜索符号”功能被称为函数 kallsyms_lookup_name()
。它的用法在mdd's answer 中有描述。【参考方案2】:
要使用全局但未导出的内核符号(例如您提到的 machine_power_off
符号),您可以在模块代码中使用 kallsyms_lookup
:
#include <linux/kallsyms.h>
static void (*machine_power_off_p)(void);
machine_power_off_p = (void*) kallsyms_lookup_name("machine_power_off");
现在您可以通过machine_power_off_p
指针调用machine_power_off
函数:
(*machine_power_off_p)();
【讨论】:
这只有在kallsyms_lookup_name
也被导出时才有效(某些版本没有导出)
报告的错误之一是类型冲突。
其实挺好的,没什么特别的,他们只是丢了一个“_p”。不要忘记定义 CONFIG_KALLSYMS 。以上是关于/proc/kallsyms 中标有“T”的内核符号未导出的主要内容,如果未能解决你的问题,请参考以下文章
尝试将 /proc/kallsyms 添加到 gdb 以进行 vmlinux 调试:`/proc/kallsyms':无法读取符号:文件格式无法识别