1

我在内核模块加载上遇到了一些奇怪的问题,我怀疑这与链接和加载有关。如何在将每个部分加载到内存后(从模块本身内部)以编程方式找出每个部分的地址。比如 .bss / .data / .text 等在哪里。

通过阅读这篇文章 https://lwn.net/Articles/90913/

这是我正在寻找的直接方式。

4

3 回答 3

3

您可以从用户空间看到这样的部分开始地址(需要 root 权限):

sudo cat /sys/module/<modulename>/sections/.text

我浏览了 syfs 是如何检索这个地址的,我发现如下: There is a section attributes in struct module

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;
于 2015-07-16T05:07:15.620 回答
2

从模块的代码THIS_MODULE宏实际上是一个指向struct module对象的指针。它的module_initmodule_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

如果多个部分适合一个类别,它们将按照与模块文件中相同的顺序放置。

在模块的代码中,您还可以打印其任何符号的地址,并且在计算节的开始之后,包含该符号。

于 2015-07-16T07:38:29.837 回答
0

虽然这个问题已经有五年了,但我想我会贡献我的两分钱。我能够以一种受 Alex Hoppus 回答启发的 hack-y 方式访问内核的部分。我不提倡以这种方式做事,除非您正在编写内核模块来调试事物或了解内核等。

无论如何,我将以下两个结构复制到我的模块中以帮助解决不完整的类型。

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您不希望省略这些部分,则需要分别定义常量全局变量、未初始化的全局变量或常规全局变量。

于 2020-05-04T13:37:34.090 回答