2012-12-04 66 views
1

我嘗試在彙編程序中編寫內核模塊。有一次我需要一個全球變量。我在.data(或.bss)部分定義了一個雙字,並且在init函數中,我嘗試將1添加到var。我的程序seccesfully做,但INSMOD賽克我:在彙編程序中編寫linux內核模塊時的內存訪問

$ sudo insmod ./test.ko 
insmod: ERROR: could not insert module ./test.ko: Invalid module format 

它在NASM我的彙編代碼:

[bits 64] 

global init 
global cleanup 

extern printk 

section .data 
    init_mess db "Hello!", 10, 0 
    g_var dd 0 

section .text 

init: 
    push rbp 
    mov rbp, rsp 

    inc dword [g_var] 

    mov rdi, init_mess 
    xor rax, rax 
    call printk 

    xor rax, rax 
    mov rsp, rbp 
    pop rbp 
    ret 

cleanup: 
    xor rax, rax 
    ret 

,如果我在C代碼寫入來添加,所有的工作好:

static i = 0; 
static int __init main_init(void) { i++; return init(); } 

但在這objdump -d test.ko爲我寫了一個非常穩定的代碼:

0000000000000000 <init_module>: 
    0: 55      push %rbp 
    1: ff 05 00 00 00 00  incl 0x0(%rip)  # 7 <init_module+0x7> 
    7: 48 89 e5    mov %rsp,%rbp 
    a: e8 00 00 00 00   callq f <init_module+0xf> 
    f: 5d      pop %rbp 
    10: c3      retq 

這是什麼意思(包括0x0(%rip))?我如何訪問內存?請幫我:) (我的系統是ArchLinux的x86_64的)

正確化妝模塊我的C代碼:

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

MODULE_AUTHOR("Actics"); 
MODULE_DESCRIPTION("Description"); 
MODULE_LICENSE("GPL"); 

extern int init(void); 
extern int cleanup(void); 

static int __init main_init(void) { return init(); } 
static void __exit main_cleanup(void) { cleanup(); } 

module_init(main_init); 
module_exit(main_cleanup); 

和我的Makefile:

obj-m := test.o 
test-objs := inthan.o module.o 
KVERSION = $(shell uname -r) 
inthan.o: inthan.asm 
    nasm -f elf64 -o [email protected] $^ 

build: 
    make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules 

回答

3

內核模式生活在「負面」(即頂部)部分o f地址空間,其中32位絕對地址不能使用(因爲它們沒有符號擴展)。正如您已經注意到的那樣,gcc使用相對於rip的地址來解決這個問題,該問題給出了當前指令指針的偏移量。您可以使用DEFAULT REL指令使nasm執行相同的操作。請參閱relevant section in the nasm documentation

+0

Magic!)非常感謝你,它的工作!我不知道,它是如何工作的,但我必須讀這篇文章。 –

1

,你可以隨時使用inline assembly

asm("add %3,%1 ; sbb %0,%0 ; cmp %1,%4 ; sbb $0,%0"    \ 
54    : "=&r" (flag), "=r" (roksum)        \ 
55    : "1" (addr), "g" ((long)(size)),       \ 
56    "rm" (limit));  
+0

不幸的是,我不能使用內聯彙編程序( –