arm linux 内核模块加载过程详解
基础环境
- kernel version:3.10.70
- ARCH:arm
参考资料
- 《深入Linux设备驱动程序内核机制》
- 《linux设备驱动开发详解》
- http://www.cnblogs.com/xmphoenix/archive/2011/10/23/2221879.html
- http://www.cnblogs.com/LittleHann/p/3920387.html
- http://www.cnblogs.com/LittleHann/p/3871092.html
what is ko
Kernel modules are small pieces of compiled code which can be inserted in the running kernel, rather than being permanently built into the kernel.
ko文件在数据组织形式上是ELF(Excutable And Linking Format)格式,是一种普通的可重定位目标文件。
linux module 基本操作
busybox 中提供了一系列的相关的操作工具
- insmod 将模块加载到内核中
- modprobe 将模块加载到内核中并且自动处理模块间依赖关系
- lsmod 列出加载到内核中的所有模块
- depmod 更新模块间依赖关系
- rmmod 移除模块
- modinfo 查看模块信息
ELF of ko
为了帮助更好的理解模块符号导出,重定向等细节,有必要在这里对ELF文件做一些介绍,
下面的ELF文件格式是KO文件的映像视图。
使用 readelf 工具可以查看elf文件的详细信息
读取ko文件的ELF头,我们可以看到magic, 目标cpu架构,类型,还有一些其他信息,因为是KO文件,所以 程序头表长度为0,只有节区头表
readelf -h kdbg.ko
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: ARM
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 56788 (bytes into file)
Flags: 0x5000000, Version5 EABI
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 47
Section header string table index: 44
读取节区头部表
readelf -S kdbg.ko
There are 47 section headers, starting at offset 0xddd4:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 000794 00 AX 0 0 4
[ 2] .rel.text REL 00000000 00e52c 000218 08 45 1 4
[ 3] .init.text PROGBITS 00000000 0007c8 0000c4 00 AX 0 0 4
[ 4] .rel.init.text REL 00000000 00e744 000050 08 45 3 4
[ 5] .exit.text PROGBITS 00000000 00088c 000038 00 AX 0 0 4
[ 6] .rel.exit.text REL 00000000 00e794 000018 08 45 5 4
[ 7] .note.gnu.build-i NOTE 00000000 0008c4 000024 00 A 0 0 4
[ 8] __ksymtab PROGBITS 00000024 0008e8 000008 00 A 0 0 4
[ 9] .rel__ksymtab REL 00000000 00e7ac 000010 08 45 8 4
[10] .ARM.extab PROGBITS 00000000 0008f0 000018 00 A 0 0 4
[11] .ARM.exidx ARM_EXIDX 00000000 000908 000080 00 AL 1 0 4
[12] .rel.ARM.exidx REL 00000000 00e7bc 0000a0 08 45 11 4
[13] .ARM.extab.init.t PROGBITS 00000000 000988 000000 00 A 0 0 1
[14] .ARM.exidx.init.t ARM_EXIDX 00000000 000988 000008 00 AL 3 0 4
[15] .rel.ARM.exidx.in REL 00000000 00e85c 000010 08 45 14 4
[16] .ARM.extab.exit.t PROGBITS 00000000 000990 000000 00 A 0 0 1
[17] .ARM.exidx.exit.t ARM_EXIDX 00000000 000990 000008 00 AL 5 0 4
[18] .rel.ARM.exidx.ex REL 00000000 00e86c 000010 08 45 17 4
[19] .modinfo PROGBITS 00000000 000998 00007c 00 A 0 0 4
[20] __ksymtab_strings PROGBITS 00000000 000a14 00000f 00 A 0 0 1
[21] .rodata.str1.4 PROGBITS 00000000 000a24 000250 01 AMS 0 0 4
[22] .data PROGBITS 00000000 000c74 000074 00 WA 0 0 4
[23] .rel.data REL 00000000 00e87c 000028 08 45 22 4
[24] .gnu.linkonce.thi PROGBITS 00000000 000ce8 000158 00 WA 0 0 4
[25] .rel.gnu.linkonce REL 00000000 00e8a4 000010 08 45 24 4
[26] .bss NOBITS 00000000 000e40 00003c 00 WA 0 0 4
[27] .debug_frame PROGBITS 00000000 000e40 0001e0 00 0 0 4
[28] .rel.debug_frame REL 00000000 00e8b4 000120 08 45 27 4
[29] .debug_info PROGBITS 00000000 001020 0073e4 00 0 0 1
[30] .rel.debug_info REL 00000000 00e9d4 003510 08 45 29 4
[31] .debug_abbrev PROGBITS 00000000 008404 000742 00 0 0 1
[32] .debug_loc PROGBITS 00000000 008b46 000630 00 0 0 1
[33] .rel.debug_loc REL 00000000 011ee4 000680 08 45 32 4
[34] .debug_aranges PROGBITS 00000000 009176 000030 00 0 0 1
[35] .rel.debug_arange REL 00000000 012564 000020 08 45 34 4
[36] .debug_ranges PROGBITS 00000000 0091a6 000088 00 0 0 1
[37] .rel.debug_ranges REL 00000000 012584 0000c0 08 45 36 4
[38] .debug_line PROGBITS 00000000 00922e 000997 00 0 0 1
[39] .rel.debug_line REL 00000000 012644 000018 08 45 38 4
[40] .debug_str PROGBITS 00000000 009bc5 003f70 01 MS 0 0 1
[41] .comment PROGBITS 00000000 00db35 000094 01 MS 0 0 1
[42] .note.GNU-stack PROGBITS 00000000 00dbc9 000000 00 0 0 1
[43] .ARM.attributes ARM_ATTRIBUTES 00000000 00dbc9 000031 00 0 0 1
[44] .shstrtab STRTAB 00000000 00dbfa 0001d8 00 0 0 1
[45] .symtab SYMTAB 00000000 01265c 0007b0 10 46 81 4
[46] .strtab STRTAB 00000000 012e0c 0002e4 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
这里对部分节区做一些说明
.rel.xxxxx
对应xxxxx section的relocate表,用于符号重定位,比如说 .rel.text 就是 .text 的重定向表所在的节区
readelf -r kdbg.ko
Relocation section '.rel.text' at offset 0xe52c contains 67 entries:
Offset Info Type Sym.Value Sym. Name
00000050 00000e02 R_ARM_ABS32 00000000 .rodata.str1.4
00000054 00005802 R_ARM_ABS32 00000000 memcpy
00000058 00006902 R_ARM_ABS32 00000000 printk
0000005c 00000e02 R_ARM_ABS32 00000000 .rodata.str1.4
00000120 00006c02 R_ARM_ABS32 00000000 _ctype
00000124 00007502 R_ARM_ABS32 00000000 strlen
000001c8 00007502 R_ARM_ABS32 00000000 strlen
000001cc 00006402 R_ARM_ABS32 00000000 match_int
000001d0 00006c02 R_ARM_ABS32 00000000 _ctype
000001d4 00007302 R_ARM_ABS32 00000000 match_hex
000001fc 0000521c R_ARM_CALL 00000128 parse_interger
0000023c 00006302 R_ARM_ABS32 00000000 kallsyms_lookup_name
00000290 0000741c R_ARM_CALL 00000060 str_trim
0000029c 0000521c R_ARM_CALL 00000128 parse_interger
.symtab
模块中所有的符号记录都在这里面
readelf -s ssp.ko | more
Symbol table '.symtab' contains 53529 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 SECTION LOCAL DEFAULT 1
2: 00000000 0 SECTION LOCAL DEFAULT 3
3: 00000000 0 SECTION LOCAL DEFAULT 5
4: 00000000 0 SECTION LOCAL DEFAULT 7
5: 00000000 0 SECTION LOCAL DEFAULT 8
6: 00000000 0 SECTION LOCAL DEFAULT 10
7: 00000000 0 SECTION LOCAL DEFAULT 13
8: 00000000 0 SECTION LOCAL DEFAULT 23
9: 00000000 0 SECTION LOCAL DEFAULT 24
10: 00000000 0 SECTION LOCAL DEFAULT 31
11: 00000000 0 NOTYPE LOCAL DEFAULT 1 $a
12: 00000088 0 NOTYPE LOCAL DEFAULT 1 $d
13: 00000000 0 NOTYPE LOCAL DEFAULT 28 $d
14: 00000098 0 NOTYPE LOCAL DEFAULT 1 $a
15: 00000150 0 NOTYPE LOCAL DEFAULT 1 $d
16: 00000164 0 NOTYPE LOCAL DEFAULT 1 $a
.shstrtab
节区名称字符串表,所有的节区名称字符串都放在这里
readelf -p 35 ssp.ko
String dump of section '.shstrtab':
[ 1] .symtab
[ 9] .strtab
[ 11] .shstrtab
[ 1b] .rel.text
[ 25] .rel.text.unlikely
[