【问题标题】:Linux kernel module - accessing memory mappingLinux内核模块——访问内存映射
【发布时间】:2015-10-05 05:17:19
【问题描述】:

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

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

我正在寻找的是直接的。

【问题讨论】:

    标签: linux-kernel android-kernel


    【解决方案1】:

    虽然这个问题已经问了五年,但我想我会贡献我的两分钱。我能够以一种受 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的地址,则需要分别定义常量全局变量、未初始化全局变量或常规全局变量,如果您不想省略这些部分。

    【讨论】:

      【解决方案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;
      

      【讨论】:

      • 我确实看过 /sys/module//sections/。对于我正在使用的内核,它没有填充部分信息,我不知道为什么。如何从模块 init 中获取 struct module 或 struct load_info 的句柄?
      • 其实我看到这个函数section_addr是静态的,所以我认为这不是合适的方式。我需要看看它是如何在 sysfs 中完成的。
      【解决方案3】:

      从模块的代码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
      

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

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

      【讨论】:

      • 我的问题是我认为装载机出了点问题。我的 bss 部分的开始位置不为零,如果我写入它,我的模块会崩溃。所以我正在尝试验证加载程序将我的 bss 放置在哪里与变量实际结束的位置。
      • 您可以比较变量的地址,写入哪个导致崩溃,与 [THIS_MODULE->module_core; THIS_MODULE->module_core + THIS_MODULE->core_ro_size) 区域:该区域被模块的加载器标记为只读。
      • 实际上,我认为我们可以浏览 sysfs 源代码,看看它是如何完成的......我的意思是部分地址打印
      猜你喜欢
      • 1970-01-01
      • 2014-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-29
      • 2015-07-08
      • 2018-05-20
      • 2014-06-01
      相关资源
      最近更新 更多