我写了这个简单的内核模块:
#include <linux/module.h> // for printk() int init( void ) { printk( "n Kello, everybody! nn" ); return 0; } void exit( void ) { printk( "n Goodbye now... nn" ); } MODULE_LICENSE("GPL"); module_init(init); module_exit(exit);
我试图理解代码如何被转换为asm,所以我objdumped它:
root@ubuntu:/home/alex/Desktop/KModule# objdump -D kmodule.ko kmodule.ko: file format elf64-x86-64 Disassembly of section .note.gnu.build-id: 0000000000000000 <.note.gnu.build-id>: 0: 04 00 add $0x0,%al 2: 00 00 add %al,(%rax) 4: 14 00 adc $0x0,%al 6: 00 00 add %al,(%rax) 8: 03 00 add (%rax),%eax a: 00 00 add %al,(%rax) c: 47 rex.RXB d: 4e 55 rex.WRX push %rbp f: 00 5e ef add %bl,-0x11(%rsi) 12: 7d 73 jge 87 <__mod_vermagic5+0x4f> 14: 83 47 e9 4d addl $0x4d,-0x17(%rdi) 18: 98 cwtl 19: eb b8 jmp ffffffffffffffd3 <__mod_vermagic5+0xffffffffffffff9b> 1b: eb 18 jmp 35 <__module_depends+0x6> 1d: fb sti 1e: 84 28 test %ch,(%rax) 20: 73 db jae fffffffffffffffd <__mod_vermagic5+0xffffffffffffffc5> 22: 51 push %rcx 23: e4 .byte 0xe4 Disassembly of section .text: 0000000000000000 <init>: 0: 55 push %rbp 1: 48 89 e5 mov %rsp,%rbp 4: e8 00 00 00 00 callq 9 <init+0x9> 9: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 10: 31 c0 xor %eax,%eax 12: e8 00 00 00 00 callq 17 <init+0x17> 17: 31 c0 xor %eax,%eax 19: 5d pop %rbp 1a: c3 retq 1b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 0000000000000020 <cleanup_module>: 20: 55 push %rbp 21: 48 89 e5 mov %rsp,%rbp 24: e8 00 00 00 00 callq 29 <cleanup_module+0x9> 29: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 30: 31 c0 xor %eax,%eax 32: e8 00 00 00 00 callq 37 <cleanup_module+0x17> 37: 5d pop %rbp 38: c3 retq 39: 00 00 add %al,(%rax) ... Disassembly of section .rodata.str1.1: 0000000000000000 <.rodata.str1.1>: 0: 0a 20 or (%rax),%ah 2: 20 20 and %ah,(%rax) 4: 4b rex.WXB 5: 65 gs 6: 6c insb (%dx),%es:(%rdi) 7: 6c insb (%dx),%es:(%rdi) 8: 6f outsl %ds:(%rsi),(%dx) 9: 2c 20 sub $0x20,%al b: 65 gs c: 76 65 jbe 73 <__mod_vermagic5+0x3b> e: 72 79 jb 89 <__mod_vermagic5+0x51> 10: 62 (bad) 11: 6f outsl %ds:(%rsi),(%dx) 12: 64 fs 13: 79 21 jns 36 <__module_depends+0x7> 15: 20 0a and %cl,(%rdx) 17: 0a 00 or (%rax),%al 19: 0a 20 or (%rax),%ah 1b: 20 20 and %ah,(%rax) 1d: 47 6f rex.RXB outsl %ds:(%rsi),(%dx) 1f: 6f outsl %ds:(%rsi),(%dx) 20: 64 fs 21: 62 (bad) 22: 79 65 jns 89 <__mod_vermagic5+0x51> 24: 20 6e 6f and %ch,0x6f(%rsi) 27: 77 2e ja 57 <__mod_vermagic5+0x1f> 29: 2e 2e 20 0a cs and %cl,%cs:(%rdx) 2d: 0a 00 or (%rax),%al Disassembly of section .modinfo: 0000000000000000 <__mod_license27>: 0: 6c insb (%dx),%es:(%rdi) 1: 69 63 65 6e 73 65 3d imul $0x3d65736e,0x65(%rbx),%esp 8: 47 50 rex.RXB push %r8 a: 4c 00 73 72 rex.WR add %r14b,0x72(%rbx) 000000000000000c <__mod_srcversion31>: c: 73 72 jae 80 <__mod_vermagic5+0x48> e: 63 76 65 movslq 0x65(%rsi),%esi 11: 72 73 jb 86 <__mod_vermagic5+0x4e> 13: 69 6f 6e 3d 45 33 46 imul $0x4633453d,0x6e(%rdi),%ebp 1a: 38 45 32 cmp %al,0x32(%rbp) 1d: 30 39 xor %bh,(%rcx) 1f: 34 37 xor $0x37,%al 21: 44 32 31 xor (%rcx),%r14b 24: 33 30 xor (%rax),%esi 26: 32 35 44 36 39 34 xor 0x34393644(%rip),%dh # 34393670 <__mod_vermagic5+0x34393638> 2c: 34 45 xor $0x45,%al ... 000000000000002f <__module_depends>: 2f: 64 fs 30: 65 gs 31: 70 65 jo 98 <__mod_vermagic5+0x60> 33: 6e outsb %ds:(%rsi),(%dx) 34: 64 fs 35: 73 3d jae 74 <__mod_vermagic5+0x3c> ... 0000000000000038 <__mod_vermagic5>: 38: 76 65 jbe 9f <__mod_vermagic5+0x67> 3a: 72 6d jb a9 <__mod_vermagic5+0x71> 3c: 61 (bad) 3d: 67 69 63 3d 33 2e 30 imul $0x2e302e33,0x3d(%ebx),%esp 44: 2e 45: 30 2d 31 36 2d 67 xor %ch,0x672d3631(%rip) # 672d367c <__mod_vermagic5+0x672d3644> 4b: 65 6e outsb %gs:(%rsi),(%dx) 4d: 65 gs 4e: 72 69 jb b9 <__mod_vermagic5+0x81> 50: 63 20 movslq (%rax),%esp 52: 53 push %rbx 53: 4d 50 rex.WRB push %r8 55: 20 6d 6f and %ch,0x6f(%rbp) 58: 64 fs 59: 5f pop %rdi 5a: 75 6e jne ca <__mod_vermagic5+0x92> 5c: 6c insb (%dx),%es:(%rdi) 5d: 6f outsl %ds:(%rsi),(%dx) 5e: 61 (bad) 5f: 64 20 6d 6f and %ch,%fs:0x6f(%rbp) 63: 64 fs 64: 76 65 jbe cb <__mod_vermagic5+0x93> 66: 72 73 jb db <__mod_vermagic5+0xa3> 68: 69 .byte 0x69 69: 6f outsl %ds:(%rsi),(%dx) 6a: 6e outsb %ds:(%rsi),(%dx) 6b: 73 20 jae 8d <__mod_vermagic5+0x55> ... Disassembly of section __mcount_loc: 0000000000000000 <__mcount_loc>: ... Disassembly of section __versions: 0000000000000000 <____versions>: 0: 73 24 jae 26 <____versions+0x26> 2: 57 push %rdi 3: 41 00 00 add %al,(%r8) 6: 00 00 add %al,(%rax) 8: 6d insl (%dx),%es:(%rdi) 9: 6f outsl %ds:(%rsi),(%dx) a: 64 fs b: 75 6c jne 79 <____versions+0x79> d: 65 gs e: 5f pop %rdi f: 6c insb (%dx),%es:(%rdi) 10: 61 (bad) 11: 79 6f jns 82 <____versions+0x82> 13: 75 74 jne 89 <____versions+0x89> ... 3d: 00 00 add %al,(%rax) 3f: 00 49 a0 add %cl,-0x60(%rcx) 42: e1 27 loope 6b <____versions+0x6b> 44: 00 00 add %al,(%rax) 46: 00 00 add %al,(%rax) 48: 70 72 jo bc <____versions+0xbc> 4a: 69 6e 74 6b 00 00 00 imul $0x6b,0x74(%rsi),%ebp ... 7d: 00 00 add %al,(%rax) 7f: 00 9a 0f 39 b4 00 add %bl,0xb4390f(%rdx) 85: 00 00 add %al,(%rax) 87: 00 6d 63 add %ch,0x63(%rbp) 8a: 6f outsl %ds:(%rsi),(%dx) 8b: 75 6e jne fb <__mod_vermagic5+0xc3> 8d: 74 00 je 8f <____versions+0x8f> ... Disassembly of section .gnu.linkonce.this_module: 0000000000000000 <__this_module>: ... 18: 6b 6d 6f 64 imul $0x64,0x6f(%rbp),%ebp 1c: 75 6c jne 8a <__this_module+0x8a> 1e: 65 00 00 add %al,%gs:(%rax) ... Disassembly of section .comment: 0000000000000000 <.comment>: 0: 00 47 43 add %al,0x43(%rdi) 3: 43 3a 20 rex.XB cmp (%r8),%spl 6: 28 55 62 sub %dl,0x62(%rbp) 9: 75 6e jne 79 <__mod_vermagic5+0x41> b: 74 75 je 82 <__mod_vermagic5+0x4a> d: 2f (bad) e: 4c 69 6e 61 72 6f 20 imul $0x34206f72,0x61(%rsi),%r13 15: 34 16: 2e 36 2e 31 2d 39 75 cs ss xor %ebp,%cs:%ss:0x75627539(%rip) # 75627558 <__mod_vermagic5+0x75627520> 1d: 62 75 1f: 6e outsb %ds:(%rsi),(%dx) 20: 74 75 je 97 <__mod_vermagic5+0x5f> 22: 33 29 xor (%rcx),%ebp 24: 20 34 2e and %dh,(%rsi,%rbp,1) 27: 36 2e 31 00 ss xor %eax,%cs:%ss:(%rax) 2b: 00 47 43 add %al,0x43(%rdi) 2e: 43 3a 20 rex.XB cmp (%r8),%spl 31: 28 55 62 sub %dl,0x62(%rbp) 34: 75 6e jne a4 <__mod_vermagic5+0x6c> 36: 74 75 je ad <__mod_vermagic5+0x75> 38: 2f (bad) 39: 4c 69 6e 61 72 6f 20 imul $0x34206f72,0x61(%rsi),%r13 40: 34 41: 2e 36 2e 31 2d 39 75 cs ss xor %ebp,%cs:%ss:0x75627539(%rip) # 75627583 <__mod_vermagic5+0x7562754b> 48: 62 75 4a: 6e outsb %ds:(%rsi),(%dx) 4b: 74 75 je c2 <__mod_vermagic5+0x8a> 4d: 33 29 xor (%rcx),%ebp 4f: 20 34 2e and %dh,(%rsi,%rbp,1) 52: 36 2e 31 00 ss xor %eax,%cs:%ss:(%rax)
但是有些东西与其他东西不太一样
如何调用printk函数? 我只能看到“callq 9”,这个偏移量没有告诉我任何东西。这是下一个指令..那么是什么? “Kello”消息得到正确打印,但我找不到代码发生这种情况!
此外,这个代码如何在.rodata.str1.1节中访问string“Kello etc ..”? 如果这是一个映射到ds寄存器的程序段,不应该像“ds:0”那样访问它吗?
我很困惑..
内核模块可重定位,并在加载时链接到内核中。 实际的内存地址只在当时确定。 这是因为内核函数的地址以及模块将被加载的地址在编译时是不知道的。
如果您查看所有call
指令的字节码,您将看到它们都有四个零字节。 当模块被加载时,这些字节将被替换为实际的功能地址。 字符串地址也是如此:在指令mov $0x0,%rdi
,零将被替换为正确的地址。
你看到像callq 9
和callq 17
这样的指令的原因是call
指令指定了相对于下一条指令的地址。 由于存储在文件中的相对地址为0,反汇编器将显示它,就好像call
指令正在调用其后的指令一样。
使用objdump -r
应该显示模块的重定位。