我遇到了一些关于内核模块负载的奇怪问题,我怀疑它与链接和加载有关。如何以编程方式计算每个部分在内存中加载后的地址(从模块本身内部)。比如.bss / .data / .text等等。
阅读本文 https://lwn.net/Articles/90913/
我正在寻找的直接排序。
答案 0 :(得分:2)
您可以看到这些部分从用户空间开始这样的地址(需要root权限):
sudo cat /sys/module/<modulename>/sections/.text
我浏览过syfs如何检索这些地址,我发现了以下内容: struct module
中有一个section属性309 /* Section attributes */
310 struct module_sect_attrs *sect_attrs;
这个attrs是一堆attr结构
1296 struct module_sect_attrs {
1297 struct attribute_group grp;
1298 unsigned int nsections;
1299 struct module_sect_attr attrs[0];
1300 };
其中sect attr就是你要找的东西
1290 struct module_sect_attr {
1291 struct module_attribute mattr;
1292 char *name;
1293 unsigned long address;
答案 1 :(得分:1)
从模块的代码THIS_MODULE
宏实际上是指向struct module
对象的指针。其module_init
和module_core
字段指向内存区域,其中加载了所有模块部分。
据我所知,模块代码无法访问分区(在模块加载到内存后,struct load_info
被删除)。但是有了模块的文件,您可以在加载后轻松推断出部分的地址:
module_init:
- init sections with code (.init.text)
- init sections with readonly data
- init sections with writable data
module_core:
- sections with code (.text)
- sections with readonly data
- sections with writable data
如果有几个部分适合一个类别,则它们按照与模块文件中相同的顺序放置。
在模块的代码中,您还可以打印任何符号的地址,并在计算该部分的开始后,包含此符号。
答案 2 :(得分:0)
虽然这个问题已有5岁,但我认为我会贡献我的2美分。我能够以Alex Hoppus的回答为灵感,以一种骇人听闻的方式访问内核的各个部分。我不主张这样做,除非您正在编写内核模块以进行调试或了解内核等。
无论如何,我将以下两个结构复制到模块中,以帮助解决不完整的类型。
struct module_sect_attr {
struct module_attribute mattr;
char *name;
unsigned long address;
};
struct module_sect_attrs {
struct attribute_group grp;
unsigned int nsections;
struct module_sect_attr attrs[0];
};
然后,在我的模块初始化功能中,我执行以下操作以获取段地址。
unsigned long text = 0;
unsigned int nsections = 0;
unsigned int i;
struct module_sect_attr* sect_attr;
nsections = THIS_MODULE->sect_attrs->nsections;
sect_attr = THIS_MODULE->sect_attrs->attrs;
for (i = 0; i < nsections; i++) {
if (strcmp((sect_attr + i)->name, ".text") == 0)
text = (sect_attr + i)->address;
}
最后,应注意,如果要查找.rodata
,.bss
或.data
的地址,则需要定义常量全局变量,未初始化的全局变量或如果您不想忽略这些部分,则分别使用常规全局变量。