$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
#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);
答案 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
,看看它是否也会出现同样的错误。如果是,请尝试使用像
$(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)?”
我不完全确定你的意思,但我们可以通过实验回答你的问题。