模块格式无效

时间:2011-06-24 17:15:46

标签: makefile linux-kernel kernel-module

$insmod helloworld module generates the error message "Invalid module format".

$dmesg outputs:

overflow in relocation type 10 val ffffffff88640070
'hello' likely not compiled with -mcmodel=kernel

Makefile是传统格式(使用(CC))和模块构建系统格式"make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules"的混合。

系统为1.6.18-194.el5 x86_64。在i386机器上使用时,相同的Makefile工作正常。

知道该怎么做?感谢。


#Makefile, mix of (CC) and kernel module build system

CFLAGS+=-D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(hello)"
CFLAGS+=-D__KERNEL__ -DMODULE -I$(KERNEL_BUILD_DIR)/include

KERNEL_BUILD_DIR=/lib/modules/2.6.18-194.el5/build
TARGETNAME=hello
BUILD_ALT_DIR=linux

# The main target (note that both library and driver are .ko files
#
all: $(BUILD_ALT_DIR)/$(TARGETNAME).ko
$(BUILD_ALT_DIR)/_$(TARGETNAME).o: hello.o
@echo Linking objects to loadable module
@mkdir -p $(BUILD_ALT_DIR)
@echo $(CURDIR)/$@
@$(LD) -Map=$@.map -r -o $@ $^
@echo " LD_D [$@]"

$(BUILD_ALT_DIR)/$(TARGETNAME).ko: $(BUILD_ALT_DIR)/_$(TARGETNAME).o
@rm -f $(BUILD_ALT_DIR)/$(TARGETNAME).o
@echo create Makefile
@$(SHELL) -c 'echo "obj-m := $(TARGETNAME).o" > $(BUILD_ALT_DIR)/Makefile'
@$(SHELL) -c 'echo "$(TARGETNAME)-objs := _$(TARGETNAME).o" >> $(BUILD_ALT_DIR)/Makefile'
@$(SHELL) -c 'echo ".PHONY: `pwd`/$(BUILD_ALT_DIR)/_$(TARGETNAME).o" >> $(BUILD_ALT_DIR)/Makefile'
@$(SHELL) -c 'cd $(BUILD_ALT_DIR); $(MAKE) -C $(KERNEL_BUILD_DIR) M=`pwd`'
@echo " KO_D [$@]"


$(BUILD_ALT_DIR)/%.o: %.c
@echo Compiling C source to object file:
@mkdir -p $(BUILD_ALT_DIR)
# @echo $(CURDIR)/$@
@$(CC) -c -Wall $(CFLAGS) $(CFLAGS) $< -o $@
@echo " CC_D [$@]"

clean:
    rm -f $(BUILD_ALT_DIR)/*.o $(BUILD_ALT_DIR)/*.d  $(BUILD_ALT_DIR)/core  $(BUILD_ALT_DIR)/*.map

的hello.c

#include <linux/autoconf.h> // this is needed

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

static int hello_init(void)
{ 
  printk(KERN_ALERT "Hello, world\n");

    return 0;
}

static void hello_exit(void)
{
    printk(KERN_ALERT "Goodbye, cruel world\n");
}

module_init(hello_init);
module_exit(hello_exit);

2 个答案:

答案 0 :(得分:3)

dmesg输出会告诉您错误:

'hello' likely not compiled with -mcmodel=kernel

在x86-64架构上,内核中运行的所有代码(包括模块)必须使用特殊标志进行编译,该标志告诉编译器生成将在上半部分运行的代码。虚拟地址空间(用户模式程序在地址空间的下半部分运行)。

如果我正确地读取你的Makefile,你正在编译内核构建系统外部的 C ,并且仅为最终链接调用内核构建系统。 不要这样做。不仅仅是内存模型,在编译C源代码时还必须添加其他几个标志。这些标志可能随内核版本而变化,甚至可能随内核配置而变化 - 您不知道,并且您不应该知道,因为内核构建系统会为您处理所有内容。

这不仅仅是-mcmodel=kernel。还有很多其他人,错误会导致问题。

在代码中可以看到错过正确标记的事实:

#include <linux/autoconf.h> // this is needed

不,这不是必需的。如果你需要它,你做错了。看一下内核构建系统传递给C编译器的标志之一:

-include include/linux/autoconf.h

此标志告诉C编译器始终隐式包含linux/autoconf.h标头。由于它总是隐式包含在内,因此您无需手动包含它。由于您从未手动添加,因此可以更改其位置 - 它已移至generated/autoconf.h,之后移至linux/kconfig.h,并且知道接下来会在哪里结束。

它在32位x86中对你有用的事实只是运气。即使在32位上也应该以正确的方式进行。

答案 1 :(得分:0)

第二次迭代:

好的,您已确认Make build _helloworld.o$(BUILD_ALT_DIR)/Makefile。你现在可以发布$(KERNEL_BUILD_DIR)中的makefile(在x86_64上)吗?

(我会说明问题可能是$(BUILD_ALT_DIR)$(KERNEL_BUILD_DIR)在i386上是相同的,但在x84_64上却没有。)

编辑:(第三次迭代)
1400线? 一个分支中的大多数?半个include指令?特定于架构的分支?的Autoconf?

你是否可以修改这个噩梦,或者你必须修补像automake这样的高级工具吗? (我只是因为在后一种情况下找出问题并没有多大帮助,你可能不得不从头开始。)

1)从$(KERNEL_BUILD_DIR),尝试make M=$(BUILD_ALT_DIR)(无论$(BUILD_ALT_DIR)是什么)。验证这会给您相同的错误消息。如果没有,则忽略后面的内容(在此迭代中)。

2)从$(BUILD_ALT_DIR)开始,尝试make,看看它是否也会出现同样的错误。如果是,请尝试使用像

这样的简单makefile替换makefile(在$(BUILD_ALT_DIR)中)
all:
    @echo trivial makefile working

并测试它,然后再次尝试第1步。 如果它只是说“琐碎的makefile工作”并且没有给出错误,那么事情看起来不错。

编辑:(第四次迭代)

好的,我们无法更改$(KERNEL_BUILD_DIR)/Makefile。这不一定会让我们陷入困境。

“你的建议(1)不起作用,因为$(BUILD_ALT_DIR)是一个输出目录,其中没有来源。”

Make不需要源代码的存在,以及这是否可行(无论“工作”意味着什么),这是你的makefile似乎正在尝试:

@$(SHELL) -c 'cd $(BUILD_ALT_DIR); $(MAKE) -C $(KERNEL_BUILD_DIR) M=`pwd`'

尝试一下,看看会发生什么。

“x86_64是否有可能不支持内核模块的传统格式(CC)?”

我不完全确定你的意思,但我们可以通过实验回答你的问题。