3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

クロスコンパイルした Debian GNU/Linux でデバイスドライバをセルフコンパイルする際の注意点(Linux Kernel 5.x編)

Last updated at Posted at 2019-10-17

はじめに

以下の記事にて、クロスコンパイルした Debian GNU/Linux でデバイスドライバをセルフコンパイルする際の注意点を紹介しました。

上の記事は Linux Kernel 4.x を対象にしたものでしたが、Linux Kernel 5.x では新たな問題が発生しました。この記事では、Linux Kernel 5.x にてデバイスドライバをセルフコンパイル(ターゲットシステムの上でコンパイル)しようとしたときに遭遇した問題点と(暫定的な)解決方法について説明します。

セルフコンパイルの失敗例

ダウンロード

ここで dtbocfg (Device Tree Blob Overlay Configuration File System)を例としてコンパイルしてみます。

root@debian-fpga:~/work# git clone https://github.com/ikwzm/dtbocfg.git
Cloning into 'dtbocfg'...
remote: Enumerating objects: 59, done.
remote: Total 59 (delta 0), reused 0 (delta 0), pack-reused 59
Unpacking objects: 100% (59/59), done.
root@debian-fpga:~/work# cd dtbocfg/

失敗時のログ

すると、次のようにビルドに失敗します。

root@debian-fpga:~/work/dtbocfg# make
make -C /lib/modules/5.0.21-armv7-fpga/build ARCH=arm CROSS_COMPILE= M=/root/work/dtbocfg modules
make[1]: Entering directory '/usr/src/linux-headers-5.0.21-armv7-fpga'
  CC [M]  /root/work/dtbocfg/dtbocfg.o
  Building modules, stage 2.
  MODPOST 1 modules
/bin/sh: 1: scripts/mod/modpost: Exec format error
make[2]: *** [scripts/Makefile.modpost:92: __modpost] Error 2
make[1]: *** [Makefile:1581: modules] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-5.0.21-armv7-fpga'
make: *** [Makefile:19: all] Error 2

失敗の理由

ログを見ると、どうやら scripts/mod/modpost の実行フォーマットが違うと言っているようです。scripts/mod/modpost/usr/src/linux-headers-*/scripts/mod/modpost にあります。ファイルの型を確認すると、ホストコンピュータのアーキテクチャ(ここでは x86-64)のバイナリファイルになっています。

root@debian-fpga:~/work/dtbocfg# file /usr/src/linux-headers-5.0.21-armv7-fpga/scripts/mod/modpost
/usr/src/linux-headers-5.0.21-armv7-fpga/scripts/mod/modpost: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=b5044d5ffd526059755d33a6d8a8ab6c16e25293, not stripped

「クロスコンパイルした Debian GNU/Linux でデバイスドライバをセルフコンパイルする際の注意点」 @Qiita で紹介した方法で linux-headers の Debian package を作ると、Debian package をターゲットシステムにインストールした時に自動的に make scripts が走ってアーキテクチャに依存する各種実行ファイルを再ビルドします。

そこで linux-headers の Debian package をインストールした時のログを確認してみると、何故か、scripts/mod/modpost の再ビルドが行われていませんでした。

root@debian-fpga:/home/fpga/debian# dpkg -i linux-headers-5.0.21-armv7-fpga_5.0.21-armv7-fpga-0_armhf-old.deb
Selecting previously unselected package linux-headers-5.0.21-armv7-fpga.
(Reading database ... 134399 files and directories currently installed.)
Preparing to unpack linux-headers-5.0.21-armv7-fpga_5.0.21-armv7-fpga-0_armhf-old.deb ...
Unpacking linux-headers-5.0.21-armv7-fpga (5.0.21-armv7-fpga-0) ...
Setting up linux-headers-5.0.21-armv7-fpga (5.0.21-armv7-fpga-0) ...
make: Entering directory '/usr/src/linux-headers-5.0.21-armv7-fpga'
  HOSTCC  scripts/basic/fixdep
  HOSTLD  scripts/kconfig/conf
scripts/kconfig/conf  --syncconfig Kconfig
  HOSTCC  scripts/dtc/dtc.o
  HOSTCC  scripts/dtc/flattree.o
  HOSTCC  scripts/dtc/fstree.o
  HOSTCC  scripts/dtc/data.o
  HOSTCC  scripts/dtc/livetree.o
  HOSTCC  scripts/dtc/treesource.o
  HOSTCC  scripts/dtc/srcpos.o
  HOSTCC  scripts/dtc/checks.o
  HOSTCC  scripts/dtc/util.o
  HOSTCC  scripts/dtc/dtc-lexer.lex.o
  HOSTCC  scripts/dtc/dtc-parser.tab.o
  HOSTLD  scripts/dtc/dtc
  HOSTCC  scripts/genksyms/genksyms.o
  HOSTCC  scripts/genksyms/parse.tab.o
  HOSTCC  scripts/genksyms/lex.lex.o
  HOSTLD  scripts/genksyms/genksyms
  HOSTCC  scripts/bin2c
  HOSTCC  scripts/kallsyms
  HOSTCC  scripts/conmakehash
  HOSTCC  scripts/sortextable
  HOSTCC  scripts/asn1_compiler
  HOSTCC  scripts/extract-cert
make: Leaving directory '/usr/src/linux-headers-5.0.21-armv7-fpga'

どうやら、Linux Kernel 5.x になって scripts/mod/modpost のビルド手順が変更になり、make scripts では scripts/mod/modpost のビルドが行われなくなったようです。scripts/Makefile を Linux Kernel 5.0.21 と 4.19.57 とで比較してみると、mod まわりに変更が加えられていました。

--- linux-5.0.21-armv7-fpga/scripts/Makefile	2019-10-17 13:21:30.586261800 +0900
+++ linux-4.19.57-armv7-fpga/scripts/Makefile	2019-07-10 11:25:25.002216800 +0900
@@ -36,10 +36,11 @@ PHONY += build_unifdef
 build_unifdef: $(obj)/unifdef
 	@:
 
-subdir-$(CONFIG_GCC_PLUGINS) += gcc-plugins
 subdir-$(CONFIG_MODVERSIONS) += genksyms
+subdir-y                     += mod
 subdir-$(CONFIG_SECURITY_SELINUX) += selinux
+subdir-$(CONFIG_DTC)         += dtc
 subdir-$(CONFIG_GDB_SCRIPTS) += gdb
 
 # Let clean descend into subdirs
-subdir-	+= basic dtc kconfig mod package
+subdir-	+= basic kconfig package gcc-plugins

Linux Kernel 5.x では scripts/mod/modpost のビルドは トップレベルの Makefile の prepare0 で定義されていました。

Makefile
    :
  (前略)
    :
# prepare2 creates a makefile if using a separate output directory.
# From this point forward, .config has been reprocessed, so any rules
# that need to depend on updated CONFIG_* values can be checked here.
prepare2: prepare3 outputmakefile asm-generic

prepare1: prepare2 $(version_h) $(autoksyms_h) include/generated/utsrelease.h
	$(cmd_crmodverdir)

archprepare: archheaders archscripts prepare1 scripts

prepare0: archprepare
	$(Q)$(MAKE) $(build)=scripts/mod
	$(Q)$(MAKE) $(build)=.

# All the preparing..
prepare: prepare0 prepare-objtool
    :
  (後略)
    :

そこでターゲットシステム上の /usr/src/linux-headers-*/make prepare0 を実行してみました。

oot@debian-fpga:~/work/dtbocfg# cd /usr/src/linux-headers-5.0.21-armv7-fpga/
root@debian-fpga:/usr/src/linux-headers-5.0.21-armv7-fpga# make prepare0
make[1]: *** No rule to make target 'arch/arm/tools/syscall.tbl', needed by 'arch/arm/include/generated/uapi/asm/unistd-common.h'.  Stop.
make: *** [arch/arm/Makefile:323: archheaders] Error 2

今度は arch/arm/tools/syscall.tbl が無いと言われました。

ヘッダーパッケージの修正

本来ならばターゲットアーキテクチャ用にコンパイルした実行ファイルをヘッダーパッケージに含めるようにするのが正しい方法だと思います。しかし、私の調べた範囲では、このようにヘッダーパッケージをビルドする方法が判りませんでした。どなたか詳しい方がいらっしゃれば、教えてくださると有難いです。

次善の策として、ターゲットにヘッダーパッケージをインストールした際に自動的に各種スクリプトを再ビルドするように、ヘッダーパッケージを作り直します。具体的には、ヘッダーパッケージを生成するスクリプトに次のようなパッチを当てます。

diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index 8ac25d10a..00ad59866 100755
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -155,9 +155,9 @@ done
 
 # Build kernel header package
 (cd $srctree; find . -name Makefile\* -o -name Kconfig\* -o -name \*.pl) > "$objtree/debian/hdrsrcfiles"
-(cd $srctree; find arch/*/include include scripts -type f -o -type l) >> "$objtree/debian/hdrsrcfiles"
+(cd $srctree; find arch/*/include include tools/include scripts -type f -o -type l) >> "$objtree/debian/hdrsrcfiles"
 (cd $srctree; find arch/$SRCARCH -name module.lds -o -name Kbuild.platforms -o -name Platform) >> "$objtree/debian/hdrsrcfiles"
-(cd $srctree; find $(find arch/$SRCARCH -name include -o -name scripts -type d) -type f) >> "$objtree/debian/hdrsrcfiles"
+(cd $srctree; find $(find arch/$SRCARCH -name include -o -name scripts -o -name tools -type d) -type f) >> "$objtree/debian/hdrsrcfiles"
 if grep -q '^CONFIG_STACK_VALIDATION=y' $KCONFIG_CONFIG ; then
 	(cd $objtree; find tools/objtool -type f -executable) >> "$objtree/debian/hdrobjfiles"
 fi
@@ -172,6 +172,15 @@ mkdir -p "$destdir"
 (cd $objtree; cp $KCONFIG_CONFIG $destdir/.config) # copy .config manually to be where it's expected to be
 ln -sf "/usr/src/linux-headers-$version" "$kernel_headers_dir/lib/modules/$version/build"
 rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles"
+mkdir -m 755 -p "$kernel_headers_dir/DEBIAN"
+cat <<EOF >> $kernel_headers_dir/DEBIAN/postinst
+#!/bin/sh -e
+
+make -C /usr/src/linux-headers-$version prepare0
+
+EOF
+
+chmod 755 $kernel_headers_dir/DEBIAN/postinst
 
 if [ "$ARCH" != "um" ]; then
 	create_package "$kernel_headers_packagename" "$kernel_headers_dir"

このパッチファイルは builddeb に対して、tools/include 以下のファイルを含めるようにしています。これにより scripts/sortextable のビルドが正常に終了します(「クロスコンパイルした Debian GNU/Linux でデバイスドライバをセルフコンパイルする際の注意点」 @Qiita参照)。

さらに builddeb に対して arch/$SRCARCH/tools 以下のファイルを含めるようにしています。これにより scripts/mod/modpost のビルドが正常に終了します。

そして、スクリプトをターゲット用に再ビルドするための postinst スクリプトをヘッダーパッケージに追加しています。postinst スクリプトで make prepare0 を実行するようにしています。これにより、ヘッダーパッケージをインストールした際、自動的にスクリプトを再ビルドします。

修正したヘッダーパッケージのインストール

前節で説明した方法でビルドしたヘッダーパッケージをターゲットシステムにインストールします。

root@debian-fpga:/home/fpga/debian# dpkg -i linux-headers-5.0.21-armv7-fpga_5.0.21-armv7-fpga-0_armhf.deb
Selecting previously unselected package linux-headers-5.0.21-armv7-fpga.
(Reading database ... 134399 files and directories currently installed.)
Preparing to unpack linux-headers-5.0.21-armv7-fpga_5.0.21-armv7-fpga-0_armhf.deb ...
Unpacking linux-headers-5.0.21-armv7-fpga (5.0.21-armv7-fpga-0) ...
Setting up linux-headers-5.0.21-armv7-fpga (5.0.21-armv7-fpga-0) ...
make: Entering directory '/usr/src/linux-headers-5.0.21-armv7-fpga'
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/kconfig/conf.o
  HOSTCC  scripts/kconfig/confdata.o
  HOSTCC  scripts/kconfig/expr.o
  HOSTCC  scripts/kconfig/symbol.o
  HOSTCC  scripts/kconfig/preprocess.o
  LEX     scripts/kconfig/zconf.lex.c
  YACC    scripts/kconfig/zconf.tab.h
  HOSTCC  scripts/kconfig/zconf.lex.o
  YACC    scripts/kconfig/zconf.tab.c
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  scripts/kconfig/conf
scripts/kconfig/conf  --syncconfig Kconfig
  HOSTCC  scripts/dtc/dtc.o
  HOSTCC  scripts/dtc/flattree.o
  HOSTCC  scripts/dtc/fstree.o
  HOSTCC  scripts/dtc/data.o
  HOSTCC  scripts/dtc/livetree.o
  HOSTCC  scripts/dtc/treesource.o
  HOSTCC  scripts/dtc/srcpos.o
  HOSTCC  scripts/dtc/checks.o
  HOSTCC  scripts/dtc/util.o
  HOSTCC  scripts/dtc/dtc-lexer.lex.o
  HOSTCC  scripts/dtc/dtc-parser.tab.o
  HOSTLD  scripts/dtc/dtc
  HOSTCC  scripts/genksyms/genksyms.o
  HOSTCC  scripts/genksyms/parse.tab.o
  HOSTCC  scripts/genksyms/lex.lex.o
  HOSTLD  scripts/genksyms/genksyms
  HOSTCC  scripts/bin2c
  HOSTCC  scripts/kallsyms
  HOSTCC  scripts/conmakehash
  HOSTCC  scripts/sortextable
  HOSTCC  scripts/asn1_compiler
  HOSTCC  scripts/extract-cert
  CC      scripts/mod/empty.o
  HOSTCC  scripts/mod/mk_elfconfig
  MKELF   scripts/mod/elfconfig.h
  HOSTCC  scripts/mod/modpost.o
  CC      scripts/mod/devicetable-offsets.s
  HOSTCC  scripts/mod/file2alias.o
  HOSTCC  scripts/mod/sumversion.o
  HOSTLD  scripts/mod/modpost
make: Leaving directory '/usr/src/linux-headers-5.0.21-armv7-fpga'

無事に scripts/mod/modpost が再ビルドされています。

dtbocfg をコンパイルしてみましょう。

root@debian-fpga:~/work/dtbocfg# make
make -C /lib/modules/5.0.21-armv7-fpga/build ARCH=arm CROSS_COMPILE= M=/root/work/dtbocfg modules
make[1]: Entering directory '/usr/src/linux-headers-5.0.21-armv7-fpga'
  CC [M]  /root/work/dtbocfg/dtbocfg.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /root/work/dtbocfg/dtbocfg.mod.o
  LD [M]  /root/work/dtbocfg/dtbocfg.ko
make[1]: Leaving directory '/usr/src/linux-headers-5.0.21-armv7-fpga'

今度は無事にコンパイル出来ました。

root@debian-fpga:~/work/dtbocfg# insmod dtbocfg.ko
[32165.177417] dtbocfg_module_init
[32165.180623] dtbocfg_module_init: OK

コンパイルした dtbocfg もちゃんとロード出来ているようです。

参考

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?