任何人都可以帮助解决我的 ARM + GCC + UCLIBC 与 crossdev 的链接问题吗?
也在这里发布到 Gentoo 论坛:http ://forums.gentoo.org/viewtopic-t-925012.html
最近,我被分配到一个项目,该项目具有使用带有 OABI 的旧 GCC 开发的可执行文件。作为参考,这是一个在系统上运行良好的可执行文件的 readelf 头输出:
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: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0x9464
Start of program headers: 52 (bytes into file)
Start of section headers: 540956 (bytes into file)
Flags: 0x202, has entry point, GNU EABI, software FP
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 6
Size of section headers: 40 (bytes)
Number of section headers: 35
Section header string table index: 32
我使用 crossdev 和最新的 gcc/binutils/linux-headers/etc 创建了一个交叉编译器。并与 EABI。
$ crossdev arm-softfloat-linux-uclibceabi
我很高兴地开始使用该交叉编译器在我的本地文件夹中填充可执行文件,只是后来在我的硬件上尝试了可执行文件并发现我最终遇到了分段错误。我意识到,只是通过相当多的谷歌搜索,我真的需要为 uclibc 拥有旧的、遗留的 ABI:OABI。我以前的交叉编译器是从大约 2005 年开始的。
作为另一个参考点,我的 eabi 可执行文件从 readelf 生成的头文件看起来有点像这样:
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: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0x8130
Start of program headers: 52 (bytes into file)
Start of section headers: 21284 (bytes into file)
Flags: 0x5000002, has entry point, Version5 EABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 7
Size of section headers: 40 (bytes)
Number of section headers: 21
Section header string table index: 18
虽然机器是相同的,但分段错误不提供在目标上执行二进制文件的方法。
在谷歌搜索更多之后,我发现可能有一种方法可以使用 eabi 编译器为遗留系统生成一些代码。当我运行这个命令时,我很高兴:
$ arm-softfloat-linux-uclibceabi-gcc -mabi=apcs-gnu -static -c -o /mnt/arm_uclibc/tmp/test /mnt/arm/tmp/test.c && readelf -h /mnt/arm_uclibc/tmp/test
我最终得到:
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: 248 (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: 12
Section header string table index: 9
在这一点上,我开始坐立不安,我决定尝试使用 -mabi=apcs-gnu 创建一个可执行文件,
arm-softfloat-linux-uclibceabi-gcc -mabi=apcs-gnu -static -o /mnt/arm_uclibc/tmp/test /mnt/arm/tmp/test.c
我得到一个链接器错误:
/usr/libexec/gcc/arm-softfloat-linux-uclibceabi/ld: error: Source object /tmp/ccDq2f6R.o has EABI version 0, but target /mnt/arm_uclibc/tmp/test has EABI version 5
/usr/libexec/gcc/arm-softfloat-linux-uclibceabi/ld: failed to merge target specific data of file /tmp/ccDq2f6R.o
collect2: ld returned 1 exit status
问题:这让我相信我的 EABI 不正确,我需要 OABI。是对的吗?
我相信是这样,于是开始通过crossdev研究uclibc:
$ crossdev arm-softfloat-linux-uclibc -P -v
我很高兴地报告说,被编译成某种对象二进制文件的文件具有正确的 elf 标头。所以我想这就是我想要的。
但是这在编译 uclibc 时会死掉,如下所示:
make[1]: `lib/ld-uClibc.so' is up to date.
LD libuClibc-0.9.33.2.so
libc/libc_so.a(_fpmaxtostr.os): In function `_fpmaxtostr':
_fpmaxtostr.c:(.text+0xbc): undefined reference to `__nedf2'
_fpmaxtostr.c:(.text+0xe0): undefined reference to `__eqdf2'
_fpmaxtostr.c:(.text+0xfc): undefined reference to `__divdf3'
_fpmaxtostr.c:(.text+0x108): undefined reference to `__ltdf2'
_fpmaxtostr.c:(.text+0x17c): undefined reference to `__muldf3'
_fpmaxtostr.c:(.text+0x348): undefined reference to `__gedf2'
_fpmaxtostr.c:(.text+0x40c): undefined reference to `__fixunsdfsi'
libc/libc_so.a(__psfs_do_numeric.os): In function `__psfs_do_numeric':
__psfs_do_numeric.c:(.text+0x534): undefined reference to `__truncdfsf2'
libc/libc_so.a(close.oS):(.ARM.exidx+0x0): undefined reference to `__aeabi_unwind_cpp_pr0'
collect2: ld returned 1 exit status
make: *** [lib/libc.so] Error 1
如果我正确地分解了错误,我相信
1) arm Makefile.arch 没有正确构建 __aeabi_unwind_cpp_pr0 因为该文件仅在设置 EABI 时构建:
$ find . -name 'Makefile.arch' -exec grep -i -H -n 'pr1' "{}" \;
./uclibc-0.9.33.2/work/uClibc-0.9.33.2/libc/sysdeps/linux/arm/Makefile.arch:45: $(ARCH_OUT)/aeabi_sighandlers.os $(ARCH_OUT)/aeabi_unwind_cpp_pr1.o
$ find . -name 'aeabi_unwind_cpp_pr1.c*'
./uclibc-0.9.33.2/work/uClibc-0.9.33.2/libc/sysdeps/linux/arm/aeabi_unwind_cpp_pr1.c
$ cat ./uclibc-0.9.33.2/work/uClibc-0.9.33.2/libc/sysdeps/linux/arm/aeabi_unwind_cpp_pr1.c
#include <stdlib.h>
attribute_hidden void __aeabi_unwind_cpp_pr0 (void);
attribute_hidden void __aeabi_unwind_cpp_pr0 (void)
{
}
attribute_hidden void __aeabi_unwind_cpp_pr1 (void);
attribute_hidden void __aeabi_unwind_cpp_pr1 (void)
{
}
attribute_hidden void __aeabi_unwind_cpp_pr2 (void);
attribute_hidden void __aeabi_unwind_cpp_pr2 (void)
{
}
我相信这个错误的修复是:
--- Makefile.arch.old 2012-05-28 00:43:52.918708833 -0500
+++ Makefile.arch.new 2012-05-28 00:44:30.658708443 -0500
@@ -42,5 +42,6 @@
libc-static-y += $(ARCH_OUT)/aeabi_lcsts.o $(ARCH_OUT)/aeabi_math.o \
$(ARCH_OUT)/aeabi_sighandlers.o
libc-nonshared-y += $(ARCH_OUT)/aeabi_lcsts.os $(ARCH_OUT)/aeabi_math.os \
- $(ARCH_OUT)/aeabi_sighandlers.os $(ARCH_OUT)/aeabi_unwind_cpp_pr1.o
+ $(ARCH_OUT)/aeabi_sighandlers.os
endif
+libc-nonshared-y += $(ARCH_OUT)/aeabi_unwind_cpp_pr1.o
2) gcc 中的软浮点数也没有被链接器正确包含。在这一点上,我真的不知道为什么。
$ find . -name '*.c' -exec grep -i -H -n nedf2 "{}" \;
./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/mips/mips.c:11123: set_optab_libfunc (ne_optab, DFmode, "__mips16_nedf2");
./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/soft-fp/eqdf2.c:51:strong_alias(__eqdf2, __nedf2);
./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/testsuite/gcc.c-torture/execute/gofast.c:32:int nedf2 (double a, double b) { return a != b; }
./gcc-4.5.3-r2/work/gcc-4.5.3/libgcc/config/rx/rx-abi-functions.c:41:int _COM_CMPNEd (double a, double b) { return __nedf2 (a, b) != 0; }
$ ls ./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/soft-fp/
README double.h extendsftf2.c fixsfti.c fixunssfdi.c floatdisf.c floattitf.c floatuntidf.c lesf2.c negtf2.c single.h trunctfdf2.c
adddf3.c eqdf2.c extendxftf2.c fixtfdi.c fixunssfsi.c floatditf.c floatundidf.c floatuntisf.c letf2.c op-1.h soft-fp.h trunctfsf2.c
addsf3.c eqsf2.c fixdfdi.c fixtfsi.c fixunssfti.c floatsidf.c floatundisf.c floatuntitf.c muldf3.c op-2.h subdf3.c trunctfxf2.c
addtf3.c eqtf2.c fixdfsi.c fixtfti.c fixunstfdi.c floatsisf.c floatunditf.c gedf2.c mulsf3.c op-4.h subsf3.c unorddf2.c
divdf3.c extenddftf2.c fixdfti.c fixunsdfdi.c fixunstfsi.c floatsitf.c floatunsidf.c gesf2.c multf3.c op-8.h subtf3.c unordsf2.c
divsf3.c extended.h fixsfdi.c fixunsdfsi.c fixunstfti.c floattidf.c floatunsisf.c getf2.c negdf2.c op-common.h t-softfp unordtf2.c
divtf3.c extendsfdf2.c fixsfsi.c fixunsdfti.c floatdidf.c floattisf.c floatunsitf.c ledf2.c negsf2.c quad.h truncdfsf2.c
$ grep -i -H -n nedf2 ./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/soft-fp/*
./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/soft-fp/eqdf2.c:51:strong_alias(__eqdf2, __nedf2);
$ grep -i -H -n eqdf2 ./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/soft-fp/*
./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/soft-fp/eqdf2.c:35:CMPtype __eqdf2(DFtype a, DFtype b)
./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/soft-fp/eqdf2.c:51:strong_alias(__eqdf2, __nedf2);
$ grep -i -H -n divdf3 ./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/soft-fp/*
./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/soft-fp/divdf3.c:35:DFtype __divdf3(DFtype a, DFtype b)
$ grep -i -H -n ltdf2 ./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/soft-fp/*
./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/soft-fp/ledf2.c:51:strong_alias(__ledf2, __ltdf2);
$ grep -i -H -n muldf3 ./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/soft-fp/*
./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/soft-fp/muldf3.c:35:DFtype __muldf3(DFtype a, DFtype b)
$ grep -i -H -n gedf2 ./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/soft-fp/*
./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/soft-fp/gedf2.c:35:CMPtype __gedf2(DFtype a, DFtype b)
./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/soft-fp/gedf2.c:51:strong_alias(__gedf2, __gtdf2);
$ grep -i -H -n fixunsdfsi ./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/soft-fp/*
./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/soft-fp/fixunsdfsi.c:35:USItype __fixunsdfsi(DFtype a)
./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/soft-fp/t-softfp:71:softfp_func_list := $(filter-out floatdidf floatdisf fixunsdfsi fixunssfsi \
$ grep -i -H -n truncdfsf2 ./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/soft-fp/*
./gcc-4.5.3-r2/work/gcc-4.5.3/gcc/config/soft-fp/truncdfsf2.c:36:SFtype __truncdfsf2(DFtype a)
所以我试图强制 GCC 为软浮点构建,并在稍后在 uclibc 的构建中获得链接:
$ UCLIBC_CPU=ARM926T ACCEPT_KEYWORDS="arm" CPU_CFLAGS="-marm -march=armv5te -mtune=arm926ej-s -mabi=apcs-gnu -mno-thumb" EXTRA_FLAGS="-msoft-float -mfloat-abi=soft" UCLIBC_EXTRA_CFLAGS="${CPU_CFLAGS} ${EXTRA_CFLAGS}" STAGE1_CFLAGS="${EXTRA_CFLAGS}" CFLAGS="${EXTRA_CFLAGS}" crossdev -A arm -t arm-softfloat-linux-uclibc -P -v
然后我检查了是否在任何日志中使用了 -msoft-float 和 -mfloat-abi=soft 进行编译。
$ find . -name '*.log' -exec grep -i -H -n msoft-float "{}" \;
<nothing>
$ find . -name '*.log'
./work/build/arm-softfloat-linux-uclibc/libgcc/config.log
./work/build/libcpp/config.log
./work/build/gcc/config.log
./work/build/fixincludes/config.log
./work/build/intl/config.log
./work/build/build-x86_64-pc-linux-gnu/libiberty/config.log
./work/build/build-x86_64-pc-linux-gnu/fixincludes/config.log
./work/build/libdecnumber/config.log
./work/build/libiberty/config.log
./work/build/config.log
./work/gcc-4.5.3/contrib/reghunt/examples/29478.log
./work/gcc-4.5.3/contrib/reghunt/examples/29906a.log
./work/gcc-4.5.3/contrib/reghunt/examples/29906b.log
./work/gcc-4.5.3/contrib/reghunt/examples/28970.log
./work/gcc-4.5.3/contrib/reghunt/examples/29106.log
./work/gcc-4.5.3/contrib/reghunt/examples/30643.log
./temp/elibtool.log
./temp/epatch_user.log
./temp/epatch.log
./temp/eclass-debug.log
./temp/build.log
但我确实注意到 --with-float=soft 是在 config.log 中设置的,所以这让我相信应该已经生成了浮点数。
我注意到 gcc 的编译选项中的 -D__GCC_FLOAT_NOT_NEEDED 。
我对 GCC 进行了回归,以查看中断发生的位置。
- gcc 4.x 不适用于 uclibc。-- 从 4.4.4-r2 开始,uclibc 与 gcc 的链接失败 -- 在 4.4.4 之前,gcc 似乎没有
- 如果使用 USE=-nptl,gcc-3.4.6-r2 确实可以工作
作为参考,我跑了:binutils: 2.22-r1 Linux Header: 3.3, 3.4 uclibc: 0.9.33.2 gcc: 3.2.3-r4, 3.3.6-r1, 3.4.6-r2, 4.1.4-r1, 4.3.3 -r2、4.4.2、4.4.4-r2、4.4.5、4.4.6-r1、4.4.7、4.5.3-r2、4.6.0、4.6.1-r1、4.6.2、4.6.3