不使用 Module.symvers 编译 Linux 内核模块

不使用 Module.symvers 编译 Linux 内核模块

我有这个嵌入式Linux设备。我想向其中添加内核级功能,但非常不希望为此编译自己的内核。 (如果内核未加载并进入用户空间,则设备已变砖;我无法访问引导加载程序来恢复它。当前内核没有 kexec 支持,因此我无法使用它来测试内核映像我自己的。)

该设备的内核支持模块,但我没有相应的 Module.symvers 文件的副本。

我的问题:如果我没有 Linux 内核的 Module.symvers 文件,但有内核映像和为其编译的模块,我是否可以编译更多可以插入该内核的模块,也许可以通过生成缺少的模块来实现。 symvers 文件,我需要什么?

该设备运行 Linux 内核版本 3.10。
内核映像(在其 uImage 容器中):https://www.olio.watch/olio-firmware-1.10.220/olio-firmware/uImage
配置(通过 CONFIG_IKCONFIG 从上图中提取):https://www.olio.watch/3.10.0-g2ae2f33-config
我拥有与该内核匹配的一个内核模块:https://www.olio.watch/olio-firmware-1.10.220/olio-firmware/drv2605.ko

答案1

首先,为了回答你的问题“我可以在没有 Module.symvers 的情况下编译 Linux 内核模块吗”,我们需要了解以下内容的目的是什么Module.symvers

Module.symvers有两个主要目的:

1) 它列出了 vmlinux 和所有模块的所有导出符号。

CONFIG_MODVERSIONS2) 如果启用则列出 CRC 。如果不CONFIG_MODVERSIONS启用,CRC 将读取 0x00000000。

Module.symvers将在内核构建期间生成,它包含来自内核和编译模块的所有导出符号。对于每个符号,还存储相应的 CRC 值。 Module.symvers 文件的语法是:

    <CRC>       <Symbol>           <module>

例如:

    0x2d036834  scsi_remove_host   drivers/scsi/scsi_mod

话虽如此,如果我们有的话Module.symvers,我们就可以构建任何模块,因为它包含所有必要的符号。

如果Module.symvers 不可用,我们仍然可以通过构建此文件或从另一个模块借用它来构建外部模块。

通常,在构建外部模块时,构建系统需要访问内核中的符号以检查是否定义了所有外部符号。这是在名为 的构建步骤中完成的MODPOST。此步骤通过Module.symvers从内核源代码树中读取来获取符号。

如果Module.symvers正在构建外部模块的目录中存在文件,则该文件也会被读取。在此MODPOST步骤中,将写入一个新Module.symvers文件,其中包含内核中未定义的所有导出符号。

如果 Module.symvers文件不存在,则外部模块可能正在使用从另一个外部模块导出的符号,kbuild需要充分了解所有符号以避免发出有关未定义符号的警告。

针对这种情况,有以下三种解决方案:

1) 使用顶级kbuild文件:如果您有两个模块foo.kobar.ko,其中foo.ko需要来自 的符号bar.ko,则可以使用通用的顶级kbuild文件,以便两个模块在同一版本中编译。考虑以下目录布局:

    ./foo/ <= contains foo.ko
    ./bar/ <= contains bar.ko

    The top-level kbuild file would then look like:

    #./Kbuild (or ./Makefile):
        obj-y := foo/ bar/

    And executing

        $ make -C $KDIR M=$PWD

    will then do the expected and compile both modules with
    full knowledge of symbols from either module.

2)使用额外的Module.symvers文件:当构建外部模块时,Module.symvers会生成一个文件,其中包含内核中未定义的所有导出符号。要访问 中的符号bar.ko,请将 Module.symvers 文件从 bar.ko 的编译复制到构建 foo.ko 的目录。在模块构建期间,kbuild将读取Module.symvers外部模块目录中的文件,构建完成后,Module.symvers将创建一个新文件,其中包含定义的所有符号的总和,而不是内核的一部分。

3) 使用“make”变量KBUILD_EXTRA_SYMBOLS:如果从另一个模块复制不切实际,您可以在构建文件中Module.symvers分配一个以空格分隔的文件列表。这些文件将在其符号表初始化期间KBUILD_EXTRA_SYMBOLS加载。modpost

更多细节1

相关内容