【问题标题】:memory access when writing a linux kernel module in assembler在汇编程序中编写 linux 内核模块时的内存访问
【发布时间】:2012-12-04 20:42:36
【问题描述】:

我尝试在汇编程序中编写内核模块。有一次我需要一个全局变量。我在 .data(或 .bss)部分定义了一个 dword,在 init 函数中我尝试将 1 添加到 var。我的程序 seccesfully 制作,但 insmod sey 我:

$ 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 $@ $^

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

【问题讨论】:

    标签: linux assembly linux-kernel nasm kernel-module


    【解决方案1】:

    内核模式位于地址空间的“负”(即顶部)部分,不能使用 32 位绝对地址(因为它们没有符号扩展)。正如您所注意到的,gcc 使用 rip-relative 地址来解决这个问题,它给出了当前指令指针的偏移量。您可以使用 DEFAULT REL 指令使 nasm 做同样的事情。请参阅relevant section in the nasm documentation

    【讨论】:

    • 魔术!)非常感谢你,它的工作!我不知道它是如何工作的,但我一定会读到关于这个的 moar。
    【解决方案2】:

    您可以随时使用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));      
    

    【讨论】:

    • 很遗憾,我不能使用内联汇编器(
    猜你喜欢
    • 2012-11-20
    • 2015-09-21
    • 2022-01-06
    • 2012-09-27
    • 2015-08-30
    • 1970-01-01
    • 1970-01-01
    • 2015-10-05
    • 1970-01-01
    相关资源
    最近更新 更多