/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中找到。

(该文件应该存在以便可以针对给定内核构建内核模块)。

【讨论】:

是否可以使用dlopendlsym 来回避“仅内核”限制? @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”的内核符​​号未导出的主要内容,如果未能解决你的问题,请参考以下文章

怎么查看linux的内核符号表?

kallsyms是否具有内核函数的所有符号?

尝试将 /proc/kallsyms 添加到 gdb 以进行 vmlinux 调试:`/proc/kallsyms':无法读取符号:文件格式无法识别

性能:内核模块符号未显示在分析中

什么是__ksymtab?在linux内核中

内核符号 __tracepoint_module_load 在哪里定义?