2017-06-06 77 views
2

我想編譯一個驅動程序作爲可加載模塊,但每當我將adb shell插入我的手機並執行insmod test.ko時,我會收到錯誤消息insmod: failed to load /data/local/tmp/test.ko: Exec format error。 Grep'ing dmesg我找到以下日誌:test: no symbol version for module_layout爲Android編譯外部模塊

我已經做了google搜索[Ref][Ref][Ref][Ref][Ref]和閱讀了Linux的kbuild文件txt文件[Ref][Ref]無濟於事的不少,所以如果有人知道答案這將會是晶圓廠:)(我只有引用了我找到的最有用的鏈接)。

什麼我迄今所做的是:

我有一個高通極光結賬,並在內核目錄我鍵入以下

cp arch/arm64/configs/gemini_user_defconfig .config [B]# Has CONFIG_MODVERSIONS enabled and MODULE_SIG*=n[/B] 
yes "" | make oldconfig ARCH=arm64 CROSS_COMPILE=aarch64-linux-android- V=1 
make prepare ARCH=arm64 CROSS_COMPILE=aarch64-linux-android- V=1 
make scripts ARCH=arm64 CROSS_COMPILE=aarch64-linux-android- V=1 
make modules ARCH=arm64 CROSS_COMPILE=aarch64-linux-android- V=1 

我有我的PATH設置爲指向/MyAOSBDir/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin如此我拿起正確的工具鏈。

此時看起來很好。在我的內核目錄中,我有Module.symvers,所以我似乎被設置。

我們我已經建立了這個構建樹之外與虛擬測試的目錄...的Makefile看起來是這樣的:

KERNEL_DIR:=/solomon-build/MiNote2AOSB/kernel/ 
obj-m += test.o 
PWD := $(shell pwd) 

.PHONY: all 
all: 
     $(MAKE) M=$(PWD) ARCH=arm64 CROSS_COMPILE=aarch64-linux-android- -C $(KERNEL_DIR) modules V=1 
clean: 
     $(MAKE) M=$(PWD) -C $(KERNEL_DIR) clean 

司機只是一個虛擬的:

#include <linux/module.h>  /* Needed by all modules */ 
#include <linux/kernel.h>  /* Needed for KERN_INFO */ 
#include <linux/init.h>   /* Needed for the macros */ 
static int __init hello_start(void) 
{ 
    printk(KERN_INFO "Hello world\n"); 
    return 0; 
} 
static void __exit hello_end(void) 
{ 
    printk(KERN_INFO "Goodbye world\n"); 
} 
module_init(hello_start); 
module_exit(hello_end); 

我做make all在註釋行,並得到如下的輸出:

make M=/solomon-build/build_mxt_kmod ARCH=arm64 CROSS_COMPILE=aarch64-linux-android- -C /solomon-build/MiNote2AOSB/kernel/ modules V=1 
make[1]: Entering directory `/solomon-build/MiNote2AOSB/kernel' 
test -e include/generated/autoconf.h -a -e include/config/auto.conf || (    \ 
     echo >&2;              \ 
     echo >&2 " ERROR: Kernel configuration is invalid.";   \ 
     echo >&2 "   include/generated/autoconf.h or include/config/auto.conf are missing.";\ 
     echo >&2 "   Run 'make oldconfig && make prepare' on kernel src to fix it.";  \ 
     echo >&2 ;              \ 
     /bin/false) 
mkdir -p /solomon-build/build_mxt_kmod/.tmp_versions ; rm -f /solomon-build/build_mxt_kmod/.tmp_versions/* 
make -f ./scripts/Makefile.build obj=/solomon-build/build_mxt_kmod 
    ./scripts/gcc-wrapper.py aarch64-linux-android-gcc -Wp,-MD,/solomon-build/build_mxt_kmod/.test.o.d -nostdinc -isystem /solomon-build/MiNote2AOSB/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/../lib/gcc/aarch64-linux-android/4.9.x-google/include -I./arch/arm64/include -Iarch/arm64/include/generated -Iinclude -I./arch/arm64/include/uapi -Iarch/arm64/include/generated/uapi -I./include/uapi -Iinclude/generated/uapi -include ./include/linux/kconfig.h -D__KERNEL__ -mlittle-endian -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -std=gnu89 -mgeneral-regs-only -fno-pic -fno-delete-null-pointer-checks -Os -Wno-maybe-uninitialized --param=allow-store-data-races=0 -Wframe-larger-than=2048 -fstack-protector -Wno-unused-but-set-variable -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-var-tracking-assignments -g -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -fconserve-stack -Werror=implicit-int -Werror=strict-prototypes -Werror=date-time -DMODULE -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(test)" -D"KBUILD_MODNAME=KBUILD_STR(test)" -c -o /solomon-build/build_mxt_kmod/.tmp_test.o /solomon-build/build_mxt_kmod/test.c 
(cat /dev/null; echo kernel//solomon-build/build_mxt_kmod/test.ko;) > /solomon-build/build_mxt_kmod/modules.order 
make -f ./scripts/Makefile.modpost 
    find /solomon-build/build_mxt_kmod/.tmp_versions -name '*.mod' | xargs -r grep -h '\.ko$' | sort -u | sed 's/\.ko$/.o/' | scripts/mod/modpost -m -i ./Module.symvers -I /solomon-build/build_mxt_kmod/Module.symvers -o /solomon-build/build_mxt_kmod/Module.symvers -S -E -w -s -T - 
    ./scripts/gcc-wrapper.py aarch64-linux-android-gcc -Wp,-MD,/solomon-build/build_mxt_kmod/.test.mod.o.d -nostdinc -isystem /solomon-build/MiNote2AOSB/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/../lib/gcc/aarch64-linux-android/4.9.x-google/include -I./arch/arm64/include -Iarch/arm64/include/generated -Iinclude -I./arch/arm64/include/uapi -Iarch/arm64/include/generated/uapi -I./include/uapi -Iinclude/generated/uapi -include ./include/linux/kconfig.h -D__KERNEL__ -mlittle-endian -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -std=gnu89 -mgeneral-regs-only -fno-pic -fno-delete-null-pointer-checks -Os -Wno-maybe-uninitialized --param=allow-store-data-races=0 -Wframe-larger-than=2048 -fstack-protector -Wno-unused-but-set-variable -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-var-tracking-assignments -g -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -fconserve-stack -Werror=implicit-int -Werror=strict-prototypes -Werror=date-time -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(test.mod)" -D"KBUILD_MODNAME=KBUILD_STR(test)" -DMODULE -c -o /solomon-build/build_mxt_kmod/test.mod.o /solomon-build/build_mxt_kmod/test.mod.c 
    aarch64-linux-android-ld -EL -r -T ./scripts/module-common.lds --build-id --fix-cortex-a53-843419 -o /solomon-build/build_mxt_kmod/test.ko /solomon-build/build_mxt_kmod/test.o /solomon-build/build_mxt_kmod/test.mod.o 
make[1]: Leaving directory `/solomon-build/MiNote2AOSB/kernel' 

因此,沒有消息說缺少Module.symvers,所以這很好,而且我得到一個內置的.ko文件。我不明白的是消息ERROR: Kernel configuration is invalid。它所談論的文件存在,所以我知道它們是在我的內核版本中創建的。

無論如何,試圖insmod這到手機給出我前面提到的消息。如果我的貓Module.symvers我看到:

0xff924338  backlight_force_update drivers/video/backlight/backlight  EXPORT_SYMBOL 
0x30254daf  test_iosched_register block/test-iosched  EXPORT_SYMBOL 
<snip> 
0xdd502540  backlight_device_unregister  drivers/video/backlight/backlight  EXPORT_SYMBOL 
0x9939eba0  backlight_unregister_notifier drivers/video/backlight/backlight  EXPORT_SYMBOL 

因此,沒有符號module_layout文件中,因此沒有CRC,這是我推測是建立在錯誤信息?

任何線索將不勝感激,謝謝。

哦,我還要提到的模塊和內核vermagic匹配:

# modinfo /data/local/tmp/test.ko 
filename:  /data/local/tmp/test.ko 
depends: 
vermagic:  3.18.20-mytestkernel-perf-g671c431-dirty SMP preempt mod_unload modversions aarch64 

# uname -a 
Linux localhost 3.18.20-mytestkernel-perf-g671c431-dirty #1 SMP PREEMPT Mon Jun 5 15:46:13 BST 2017 aarch64 

*編輯 - 發現其解決方法 - 新QUESTON *: 我自發布更進一步得到。我意識到的是,使用Android構建系統的內核編譯產生了與我上面的方法截然不同的Module.symvers(出於某種原因,花費了一段時間便士下降,並讓我檢查Andoird構建輸出 - 呃!)。事實上,我意識到我總是有Module.symvers文件,它只是位於../out/target/product/msm8996/obj/KERNEL_OBJ/Module.symvers相對於內核目錄。複製這個文件到內核和重新運行我的模塊構建現在生成一個模塊,加載正確:)

所以,我想問題變成了,爲什麼這兩個文件不同? Android的行爲有何不同?我認爲它是設置一些更詳細的配置,但如何/爲什麼?

回答

0

所以,答案是最終比較簡單...

我只是用採購envsetup.sh,運行lunch然後構建內核的正常Android編譯過程:

. build/envsetup.sh 
lunch msm8996-userdebug 
make kernel -j16 

(記住確保在.config文件中設置CONFIG_MODULES = y,並將任何內核驅動程序設置爲= m(如果需要它們作爲模塊)。

在單獨的目錄,而不是在Android構建樹現在我有新的模塊和下面的Makefile,現在看起來是這樣的:

MY_ANDROID_ROOT_DIR :=/path/to/my/android/checkout 
KERNEL_DIR:=$(MY_ANDROID_ROOT_DIR)/kernel 
obj-m += my_driver.o 
PWD := $(shell pwd) 

.PHONY: all 
all: 
     $(MAKE) \ 
      M=$(PWD) \ 
      ARCH=arm64 \ 
      CROSS_COMPILE=aarch64-linux-android- \ 
      -C $(KERNEL_DIR) \ 
      modules \ 
      V=1 \ 
      O=$(MY_ANDROID_ROOT_DIR)/out/target/product/msm8996/obj/KERNEL_OBJ 
clean: 
     $(MAKE) M=$(PWD) -C $(KERNEL_DIR) clean 

make all輸出仍然會在你的模塊目錄(不是Android輸出目錄)。

這與所有與純Linux版本相關的示例基本相同。我需要提供的唯一額外信息是Android構建系統輸出其構建文件的位置,即O=$(MY_ANDROID_ROOT_DIR)/out/target/product/<your-product>/obj/KERNEL_OBJ

O= define告訴Make在哪裏查找內核版本的輸出。

「V = 1」定義告訴Make輸出詳細的構建信息。

modules是一個內核目標,它將構建您在Makefile變量obj-m中定義的模塊。該變量「指定構建爲可加載內核模塊的目標文件」。

現在我的模塊編譯正常,我不需要擔心獨立編譯內核或類似的東西來修復丟失的文件消息(雖然它仍然會輸出關於autoconf.h,我不明白,因爲它存在於我的樹中,似乎並不能阻止我的模塊工作)。

PS如果您的模塊包含多個文件,請定義obj-m += my_driver.o然後my_driver-m:= <extra objects>