MIPS32 路由器:module_init 未调用内核模块

MIPS32 router: module_init not called for kernel module

我正在开发一个内核模块,我想 运行 在我的路由器上。路由器型号是Netgear的DGN2200v2。在 MIPS 上是 运行ning Linux 2.6.30。我的问题是,当我加载我的模块时,我的 module_init 似乎没有被调用。我试图通过将我的 module_init 修改为 return -3(表示错误?)来缩小范围,并且 insmod 仍然报告成功。我可以在 lsmod 的输出中看到我的模块,但是使用 dmesg.

看不到我的 printk 输出

对于初学者,我想创建最简单的模块:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

static int my_init(void)
{
    printk(KERN_EMERG "init_module() called\n");
    return -3;
}

static void my_cleanup(void)
{
    printk(KERN_EMERG "cleanup_module() called\n");
}

module_init(my_init);
module_exit(my_cleanup);

这是我正在使用的 Makefile:

TOOLCHAIN=/home/user/buildroot-2016.08/output/host/usr/bin/mips-buildroot-linux-uclibc-
ARCH=mips
CC = $(TOOLCHAIN)gcc

KBUILD_CFLAGS:=.

EXTRA_CFLAGS := -I/home/user/buildroot-2016.08/output/build/linux-headers-2.6.30/include\
  -I/home/user/buildroot-2016.08/output/build/linux-headers-2.6.30/arch/mips/include/asm/mach-mipssim\
  -I/home/user/buildroot-2016.08/output/build/linux-headers-2.6.30/arch/mips/include/asm/mach-generic\
  -fno-pic -mno-abicalls -O2

obj-m := module.o
KDIR := /home/user/buildroot-2016.08/output/build/linux-headers-2.6.30
PWD := $(shell pwd)

default:
    $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

我 运行宁 make 像这样:

make ARCH=mips CROSS_COMPILE=/home/user/buildroot-2016.08/output/host/usr/bin/mips-buildroot-linux-uclibc-

成功通过。

如您所见,我正在使用我(希望)正确配置的 Buildroot。如果需要,我可以粘贴我的 .config。

我在我的模块上 运行 objdump 并没有发现问题。特别是,module_init 符号似乎指向与我的 my_init 函数相同的位置,并且它似乎具有我期望的代码:

module.ko:     file format elf32-tradbigmips
module.ko
architecture: mips:isa32, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x00000000
private flags = 50001001: [abi=O32] [mips32] [not 32bitmode] [noreorder]

MIPS ABI Flags Version: 0

ISA: MIPS32
GPR size: 32
CPR1 size: 0
CPR2 size: 0
FP ABI: Soft float
ISA Extension: None
ASEs:
    None
FLAGS 1: 00000001
FLAGS 2: 00000000

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .MIPS.abiflags 00000018  00000000  00000000  00000038  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA, LINK_ONCE_SAME_SIZE
  1 .reginfo      00000018  00000000  00000000  00000050  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA, LINK_ONCE_SAME_SIZE
  2 .note.gnu.build-id 00000024  00000018  00000018  00000068  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .text         00000040  00000000  00000000  00000090  2**4
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  4 .rodata.str1.4 00000038  00000000  00000000  000000d0  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .modinfo      0000005c  00000000  00000000  00000108  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .data         00000000  00000000  00000000  00000170  2**4
                  CONTENTS, ALLOC, LOAD, DATA
  7 .gnu.linkonce.this_module 0000014c  00000000  00000000  00000170  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, DATA, LINK_ONCE_DISCARD
  8 .bss          00000000  00000000  00000000  000002c0  2**4
                  ALLOC
  9 .comment      00000040  00000000  00000000  000002c0  2**0
                  CONTENTS, READONLY
 10 .pdr          00000040  00000000  00000000  00000300  2**2
                  CONTENTS, RELOC, READONLY
 11 .gnu.attributes 00000010  00000000  00000000  00000340  2**0
                  CONTENTS, READONLY
 12 .mdebug.abi32 00000000  00000000  00000000  00000350  2**0
                  CONTENTS, READONLY
SYMBOL TABLE:
00000000 l    d  .MIPS.abiflags 00000000 .MIPS.abiflags
00000000 l    d  .reginfo   00000000 .reginfo
00000018 l    d  .note.gnu.build-id 00000000 .note.gnu.build-id
00000000 l    d  .text  00000000 .text
00000000 l    d  .rodata.str1.4 00000000 .rodata.str1.4
00000000 l    d  .modinfo   00000000 .modinfo
00000000 l    d  .data  00000000 .data
00000000 l    d  .gnu.linkonce.this_module  00000000 .gnu.linkonce.this_module
00000000 l    d  .bss   00000000 .bss
00000000 l    d  .comment   00000000 .comment
00000000 l    d  .pdr   00000000 .pdr
00000000 l    d  .gnu.attributes    00000000 .gnu.attributes
00000000 l    d  .mdebug.abi32  00000000 .mdebug.abi32
00000000 l    df *ABS*  00000000 module.c
00000000 l     F .text  0000002c my_init
0000002c l     F .text  00000014 my_cleanup
00000000 l       .rodata.str1.4 00000000 $LC0
0000001c l       .rodata.str1.4 00000000 $LC1
00000000 l    df *ABS*  00000000 module.mod.c
00000000 l     O .modinfo   00000023 __mod_srcversion23
00000024 l     O .modinfo   00000009 __module_depends
00000030 l     O .modinfo   0000002c __mod_vermagic5
00000000 g     O .gnu.linkonce.this_module  0000014c __this_module
0000002c g     F .text  00000014 cleanup_module
00000000 g     F .text  0000002c init_module
00000000         *UND*  00000000 printk



Disassembly of section .MIPS.abiflags:

00000000 <.MIPS.abiflags>:
   0:   00002001    movf    a0,zero,$fcc0
   4:   01000003    0x1000003
    ...
  10:   00000001    movf    zero,zero,$fcc0
  14:   00000000    nop

Disassembly of section .reginfo:

00000000 <.reginfo>:
   0:   a2000014    sb  zero,20(s0)
    ...
  14:   00007fef    0x7fef

Disassembly of section .note.gnu.build-id:

00000018 <.note.gnu.build-id>:
  18:   00000004    sllv    zero,zero,zero
  1c:   00000014    0x14
  20:   00000003    sra zero,zero,0x0
  24:   474e5500    c1  0x14e5500
  28:   c8e5d654    lwc2    ,-10668(a3)
  2c:   cb477d3d    lwc2    ,32061(k0)
  30:   dfa48d71    ldc3    ,-29327(sp)
  34:   c2ea16da    ll  t2,5850(s7)
  38:   f6bcae7d    sdc1    $f28,-20867(s5)

Disassembly of section .text:

00000000 <init_module>:
   0:   27bdffe8    addiu   sp,sp,-24
   4:   3c040000    lui a0,0x0
            4: R_MIPS_HI16  $LC0
   8:   3c020000    lui v0,0x0
            8: R_MIPS_HI16  printk
   c:   afbf0014    sw  ra,20(sp)
  10:   24420000    addiu   v0,v0,0
            10: R_MIPS_LO16 printk
  14:   0040f809    jalr    v0
  18:   24840000    addiu   a0,a0,0
            18: R_MIPS_LO16 $LC0
  1c:   8fbf0014    lw  ra,20(sp)
  20:   2402fffd    li  v0,-3
  24:   03e00008    jr  ra
  28:   27bd0018    addiu   sp,sp,24

modinfo 输出也符合我的预期(与在路由器上找到的另一个 .ko 相同的 modinfo 输出,除了我的模块具有的 srcversion 但另一个路由器上的模块没有):

filename:       /home/user/module/module.ko
srcversion:     B0BADBA395A121CF49B74DC
depends:        
vermagic:       2.6.30 mod_unload MIPS32_R1 32BIT 

完全有可能是我在 Buildroot 配置中搞砸了,或者某些东西与路由器的 CPU 类型不完全匹配,但我的初始化代码太少了,以至于我没有想法至于哪里出了问题。

原来这个问题与我的开发环境和路由器之间的不同内核配置有关。具体来说,我的内核使用的是 CONFIG_UNUSED_SYMBOLS 而路由器的不是。

即使在普通模块中也会导致问题的原因是,当内核加载模块时,它不仅会在模块的符号 table 中查找 module_init 符号。相反,它从模块(从 .gnu.linkonce.this_module 部分)读取 module 结构,然后通过该结构调用 init 模块。

init函数指针在module结构中的偏移量取决于内核配置,这就解释了为什么内核找不到init函数,如果配置是不同。

感谢 Sam Protsenko 投入大量时间帮助我解决这个问题!