Неверный формат модуля - PullRequest
2 голосов
/ 24 июня 2011
$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.Тот же Makefile прекрасно работает, когда он используется в машине i386.

Есть идеи, на что обратить внимание?Спасибо.


#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 ]

3 голосов
/ 14 августа 2011

Вывод 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-битном.

0 голосов
/ 27 июня 2011

Вторая итерация:

Хорошо, вы подтвердили, что Make строит _helloworld.o и $(BUILD_ALT_DIR)/Makefile. Не могли бы вы опубликовать make-файл, который находится в $(KERNEL_BUILD_DIR) (на 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 и посмотрите, выдает ли она ту же ошибку. Если это так, попробуйте заменить make-файл (в $(BUILD_ALT_DIR)) на тривиальный make-файл, такой как

all:
    @echo trivial makefile working

и протестируйте его, затем повторите шаг 1. Если он просто говорит "тривиальная работа make-файла" и не выдает ошибку, то все выглядит хорошо.

РЕДАКТИРОВАТЬ: (четвертая итерация)

Хорошо, мы не можем изменить $(KERNEL_BUILD_DIR)/Makefile. Это не обязательно потопит нас.

"Ваше предложение (1) не будет работать, поскольку $ (BUILD_ALT_DIR) является выходным каталогом, в котором нет источника."

Make не требует наличия исходного кода, и то, будет ли это работать (независимо от того, что означает «работа»), это то, что пытается сделать ваш make-файл:

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

Попробуйте и посмотрите, что получится.

«Существует ли вероятность того, что x86_64 не поддерживает традиционный формат (CC) для модуля ядра?»

Я не совсем уверен, что вы имеете в виду, но мы, вероятно, можем ответить на ваш вопрос экспериментальным путем.

...