如何使用 crosstool-ng 为系统构建 OS/ABI

How to builld OS/ABI for SystemV using crosstool-ng

我正在尝试为我的DNS-320L NAS构建一个内核模块。

我已经在 Debian lenny chroot 环境中构建了 crosstool-ng,但是在我编译了我的内核模块并尝试安装它之后,我得到:

insmod: error inserting 'kernel/net/ip4/ipip.ko': -1 Invalid module format

当我使用 readelf 检查工作内核模块时,我得到:

~/ct-ng-build$ readelf -h ~/ct-ng-build/kernel/orig/ipip.ko 
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          6696 (bytes into file)
  Flags:                             0x5000000, Version5 EABI
  Size of this header:               52 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           40 (bytes)
  Number of section headers:         51

但是我的模块有一些不同:

~/ct-ng-build$ readelf -h ~/ct-ng-build/kernel/modules/lib/modules/2.6.31.8/kernel/net/ipv4/ipip.ko 
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 61 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            ARM
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          6280 (bytes into file)
  Flags:                             0x600, GNU EABI, software FP, VFP
  Size of this header:               52 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           40 (bytes)
  Number of section headers:         23
  Section header string table index: 20

我的cross_compile环境是:

$ echo $CROSS_COMPILE 
arm-none-eabi-


make CROSS_COMPILE=${CROSS_COMPILE} INSTALL_PATH=~/ct-ng-build/kernel/install INSTALL_MOD_PATH=~/ct-ng-build/kernel/modules INSTALL_FW_PATH=~/ct-ng-build/kernel/firmware

我的gcc编译成功了:

$  ${CROSS_COMPILE}gcc -v
Using built-in specs.
Target: arm-none-eabi
Configured with: ~/ct-ng-build/targets/src/gcc-4.3.2/configure --build=x86_64-build_unknown-linux-gnu --host=x86_64-build_unknown-linux-gnu --target=arm-none-eabi --prefix=~/x-tools/arm-none-eabi --with-local-prefix=~/x-tools/arm-none-eabi/arm-none-eabi//sys-root --disable-multilib --disable-libmudflap --with-sysroot=~/x-tools/arm-none-eabi/arm-none-eabi//sys-root --with-newlib --enable-threads=no --disable-shared --with-pkgversion=crosstool-NG-1.9.0 --with-arch=armv5te --with-tune=arm926ej-s --disable-__cxa_atexit --with-gmp=~/ct-ng-build/targets/arm-none-eabi/build/static --with-mpfr=~/ct-ng-build/targets/arm-none-eabi/build/static --enable-target-optspace --disable-nls --enable-symvers=gnu --enable-languages=c,c++
Thread model: single
gcc version 4.3.2 (crosstool-NG-1.9.0)

关于如何将 OS/ABI 变为 "UNIX - System V" 并将标志变为“0x5000000,Version5 EABI”而不是 "Arm" 和“0x600,GNU EABI,软件 FP,VFP”的任何想法" ?

还是有其他问题?

谢谢!

--- 编辑 ---- 我专门尝试针对我现有的 NAS OS:

Kernel  2.6.31.8 #1 armv5tel
C library   gcc-4.3-mt-1.44.0 

# /lib/libc-2.8.so 
GNU C Library stable release version 2.8, by Roland McGrath et al.
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.3.2.

到目前为止,我只能使用 crosstool-ng-1.9.0 构建一个 crosstool-ng 环境,但它生成了上面的二进制文件。

我尝试按照 3.17.2 ARM Options 设置 -mabi=apcs-gnu 但 C 库无法编译并出现奇怪的 "missing headers" 错误(我可能会再试一次 - 可能与我的 chroot 环境有关)。

使用 crosstool-NG 构建新的工具链,但针对 OABI 而不是 EABI 配置它。
参见 Configuring crosstool-NG

All debian releases (for ARM) upto and including Lenny were OABI.

参考:https://wiki.embeddedarm.com/wiki/EABI_vs_OABI

即使您的工具链前缀是 arm-none-eabi-,它生成的二进制文件看起来也像 OABI。
我有产生相同 readelf 输出的 OABI 二进制文件,以及具有与您想要的相同 readelf 输出 ("UNIX - System V") 的 EABI 二进制文件。

这个 question 描述了一个与您相似但相反的情况,即他的工具链正在生成 EABI 二进制文件,但他需要 OABI。

显然,您的工具链是为生成 OABI 而构建的,但使用了误导性前缀。
您需要使用 crosstool-NG 构建一个新的工具链,但将其配置为 EABI 而不是 OABI。
较新版本的 crosstool-NG 实际上通过强制 selection EABI 使 OABI 的配置变得困难,除非启用 Use obsolete features


附录

You say "but configure it for OABI rather than EABI.", but how?

使用crosstool-NG v1.18安装,我可以指定&build
* Linux 内核版本 2.6.31.14,
* gcc 版本 4.3.2,
* binutils 版本 2.18a 2.19.1a,
* glibc 版本 2.8。

为了unselect Target options ---> Use EABI(unselecting表示使用OABI),
我先得select Paths and misc options ---> Use obsolete features.

在此版本的 crosstool-NG 中,Use EABI 会自动 selected。


Use EABI 菜单项的描述有:

Set up the toolchain so that it generates EABI-compliant binaries.

If you say 'n' here, then the toolchain will generate OABI binaries.
OABI has long been deprecated, and is now considered legacy.

由于 OABI 在此版本的 crosstool-NG 中被认为已弃用,因此配置符号 ARCH_ARM_EABI_FORCE 处于活动状态,除非 Use obsolete features指定。

我在这里提取一些最后的评论:

正如@sawdust 所推荐的,我在以下 CT-NG 环境中使用 EABI:

crosstool-NG version: 1.9.0
gcc 4.3.2
binutils 2.19.1
libc 2.8
gmp 4.3.2
mpfr 2.4.2

为了让 GCC 编译器进行编译, 我不得不进行一些修改! 即:

  • targets/src/glibc-2.8/nscd 中删除 res_hconf.c(一次,在源被提取后)
  • nscd/Makefile
  • 中的对象列表中删除 res_hconf
  • ~/x-tools/arm-unknown-linux-gnueabi/arm-unknown-linux-gnueabi//sys-root/usr/include/gnu 中的 stubs-.h 创建软 link 到 stubs-32.h(构建开始后)。

我只需要下载正确的 Linux 内核并安装它。缺少的命令是:

make ARCH=arm kirkwood_defconfig

之后我只需要使用 make ARCH=arm menuconfig 来自定义东西。

gcc -v 说:

Using built-in specs.
Target: arm-unknown-linux-gnueabi
Configured with: ~/ct-ng-build/targets/src/gcc-4.3.2/configure --build=x86_64-build_unknown-linux-gnu --host=x86_64-build_unknown-linux-gnu --target=arm-unknown-linux-gnueabi --prefix=~/x-tools/arm-unknown-linux-gnueabi --with-sysroot=~/x-tools/arm-unknown-linux-gnueabi/arm-unknown-linux-gnueabi//sys-root --enable-languages=c,c++ --disable-multilib --with-arch=armv5te --with-tune=arm926ej-s --with-float=soft --disable-shared --with-pkgversion=crosstool-NG-1.9.0 --disable-sjlj-exceptions --enable-__cxa_atexit --disable-libmudflap --disable-libgomp --disable-libssp --with-gmp=~/ct-ng-build/targets/arm-unknown-linux-gnueabi/build/static --with-mpfr=~/ct-ng-build/targets/arm-unknown-linux-gnueabi/build/static --enable-threads=posix --enable-target-optspace --with-local-prefix=~/x-tools/arm-unknown-linux-gnueabi/arm-unknown-linux-gnueabi//sys-root --disable-nls --enable-symvers=gnu --enable-c99 --enable-long-long
Thread model: posix
gcc version 4.3.2 (crosstool-NG-1.9.0) 

最后,为了生成 SYSV 模块,我不得不破解内核 arch/arm/Makefile 以从 EABI 部分删除 -mabi=aapcs-linux 设置。

现在的错误是:

"modprobe: can't load module ntfs (kernel/fs/ntfs/ntfs.ko): unknown symbol in module, or unknown parameter

这是另一个问题:D

我仍然无法构建一个可用的内核模块(可能 因为 的 hacks!)但也可能是因为我没有NAS 的兼容内核 .config

最后的改动是:

  • 不使用展开
  • 禁用一些内核调试和跟踪
  • 使用 SLAB 代替 SLUB

更改是通过跟踪 dmsg 消息选择的。

现在可以加载生成的编译内核模块,如果它们与编译内核兼容的话。

(警告注意事项:当我开始添加 iptables 模块时遇到了一点麻烦,当时我被锁定在我的网络连接之外!小心!幸运的是模块没有重新加载重启时。)