解决编译问题:undefined reference to `__aeabi_uidivmod‘
1、编译存在问题
在编译韦老师课程提供的裸机源码时(比如004_erase_write_016_005),弹出以下几种错误:
init.o:(.ARM.exidx+0x0): undefined reference to `__aeabi_unwind_cpp_pr0'
init.o:(.ARM.exidx+0x8): undefined reference to `__aeabi_unwind_cpp_pr1'
my_printf.c:(.text+0x11c): undefined reference to `__aeabi_uidivmod'
my_printf.c:(.text+0x14c): undefined reference to `__aeabi_uidiv'
2、解决问题的过程
2.1 猜想问题所在
根据“undefined reference to”,应该是未定义某些函数或者缺失某些内容。但这些裸机程序在韦老师的课程中是可以编译成功的,应该不缺东西的。那问题出在哪里呢?
我猜想,问题出在我使用的与韦老师当时使用的交叉编译工具链的版本不一样。
2.2 查看交叉编译工具链
韦老师的交叉编译工具链版本是gcc-3.4.5(由书P27可知)。
我使用的交叉编译工具链版本是gcc-4.4.1,如下所示。
xjh@ubuntu:~/iot$ arm-linux-gcc -v
Using built-in specs.
Target: arm-none-linux-gnueabi
Configured with: //这里省略一大堆的配置选项,直观形式见下面内容。
Thread model: posix
gcc version 4.4.1 (Sourcery G++ Lite 2009q3-67)
xjh@ubuntu:~/iot$
为了方便查看配置选项,这里单独把它挑出来,罗列成直观的形式。其中有一个配置选项--with-arch=armv5te ,我觉得应该是有问题的,因为S3C2440是ARMv4版本的ARM指令集。
/scratch/julian/2009q3-respin-linux-lite/src/gcc-4.4/configure
--build=i686-pc-linux-gnu
--host=i686-pc-linux-gnu
--target=arm-none-linux-gnueabi
--enable-threads
--disable-libmudflap
--disable-libssp
--disable-libstdcxx-pch
--enable-extra-sgxxlite-multilibs
--with-arch=armv5te
--with-gnu-as
--with-gnu-ld
--with-specs='%{funwind-tables|fno-unwind-tables|mabi=*|ffreestanding|nostdlib:;:-funwind-tables} %{O2:%{!fno-remove-local-statics: -fremove-local-statics}} %{O*:%{O|O0|O1|O2|Os:;:%{!fno-remove-local-statics: -fremove-local-statics}}}'
--enable-languages=c,c++
--enable-shared
--disable-lto
--enable-symvers=gnu
--enable-__cxa_atexit
--with-pkgversion='Sourcery G++ Lite 2009q3-67'
--with-bugurl=https://support.codesourcery.com/GNUToolchain/
--disable-nls
--prefix=/opt/codesourcery
--with-sysroot=/opt/codesourcery/arm-none-linux-gnueabi/libc
--with-build-sysroot=/scratch/julian/2009q3-respin-linux-lite/install/arm-none-linux-gnueabi/libc
--with-gmp=/scratch/julian/2009q3-respin-linux-lite/obj/host-libs-2009q3-67-arm-none-linux-gnueabi-i686-pc-linux-gnu/usr
--with-mpfr=/scratch/julian/2009q3-respin-linux-lite/obj/host-libs-2009q3-67-arm-none-linux-gnueabi-i686-pc-linux-gnu/usr
--with-ppl=/scratch/julian/2009q3-respin-linux-lite/obj/host-libs-2009q3-67-arm-none-linux-gnueabi-i686-pc-linux-gnu/usr
--with-host-libstdcxx='-static-libgcc -Wl,-Bstatic,-lstdc++,-Bdynamic -lm'
--with-cloog=/scratch/julian/2009q3-respin-linux-lite/obj/host-libs-2009q3-67-arm-none-linux-gnueabi-i686-pc-linux-gnu/usr
--disable-libgomp
--enable-poison-system-directories
--with-build-time-tools=/scratch/julian/2009q3-respin-linux-lite/install/arm-none-linux-gnueabi/bin
--with-build-time-tools=/scratch/julian/2009q3-respin-linux-lite/install/arm-none-linux-gnueabi/bin
2.3 更改交叉编译工具链
从上面可知,我使用的与韦老师当时所使用的交叉编译工具链,两者的版本的确不同。那么如果我换成韦老师所用的版本而编译成功,则说明问题出在交叉编译工具链的版本上面。
那如何更换或者说安装交叉编译工具链?
书籍配套光盘提供有 arm-linux-gcc-3.4.5-glibc-2.3.6.tar.bz2,我们可以参考书P25~26进行安装与设置(其实解压之后就算完成了安装,但还需要对环境变量PATH进行设置):
(1)环境变量PATH是在/etc/environment文件中定义的,是最原始的值。这里直接在它后面补充新安装的交叉编译工具链的路径。
#将
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"
#改为
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/local/arm/gcc-3.4.5-glibc-2.3.6/bin"
(2)在各个用户目录下有个.bashrc文件,即~/.bashrc文件。以前它里面使用export语句修改了PATH的值,即添加了交叉编译工具链的路径。为了避免对现在要安装的版本造成影响,先把export语句注释掉,然后"source ~/.bashrc"让修改生效。
#注释掉这个内容
export PATH=/usr/local/arm/arm-2009q3/bin:$PATH
(3)查看/etc/profile文件内容,看看有没有使用export导出以前交叉编译工具链的路径,有的话就先注释掉,以免对现在要安装的版本造成影响。然后“source /etc/profile”让修改生效。
#这里没有导出以前安装的交叉编译工具链,所以不注释也行
export PATH="/opt/hisi-linux/x86-arm/arm-hisiv300-linux/target/bin:$PATH"
(4)执行“arm-linux-gcc -v”,如果显示如下则说明安装成功。后续如果要恢复成原来版本,撤销上面的操作即可。
ot@ubuntu:/# arm-linux-gcc -v
Reading specs from /usr/local/arm/gcc-3.4.5-glibc-2.3.6/bin/../lib/gcc/arm-linux/3.4.5/specs
Configured with: //直观内容见下面
Thread model: posix
gcc version 3.4.5
root@ubuntu:/#
/work/tools/create_crosstools/crosstool-0.43/build/arm-linux/gcc-3.4.5-glibc-2.3.6/gcc-3.4.5/configure
--target=arm-linux
--host=i686-host_pc-linux-gnu
--prefix=/work/tools/gcc-3.4.5-glibc-2.3.6
--with-float=soft
--with-headers=/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/include
--with-local-prefix=/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux
--disable-nls
--enable-threads=posix
--enable-symvers=gnu
--enable-__cxa_atexit
--enable-languages=c,c++
--enable-shared
--enable-c99
--enable-long-long
2.4 测试是否已解决问题
更改交叉编译工具链之后,发现可以编译了:
xjh@ubuntu:~/iot/embedded_basic/jz2440/armBareMachine/004_erase_write_016_005$ make
arm-linux-gcc -march=armv4 -c -o start.o start.S
arm-linux-gcc -march=armv4 -c -o init.o init.c
init.c: In function `copy2sdram':
init.c:140: warning: passing arg 1 of `nand_read' makes integer from pointer without a cast
init.c:140: warning: passing arg 2 of `nand_read' from incompatible pointer type
arm-linux-gcc -march=armv4 -c -o interrupt.o interrupt.c
arm-linux-gcc -march=armv4 -c -o nand_flash.o nand_flash.c
arm-linux-gcc -march=armv4 -c -o led.o led.c
arm-linux-gcc -march=armv4 -c -o uart.o uart.c
arm-linux-gcc -march=armv4 -c -o main.o main.c
arm-linux-gcc -march=armv4 -c -o exception.o exception.c
arm-linux-gcc -march=armv4 -c -o timer.o timer.c
arm-linux-gcc -march=armv4 -c -o my_printf.o my_printf.c
arm-linux-gcc -march=armv4 -c -o string_utils.o string_utils.c
arm-linux-gcc -march=armv4 -c -o lib1funcs.o lib1funcs.S
#arm-linux-ld -Ttext 0 -Tdata 0x30000000 start.o led.o uart.o init.o main.o -o sdram.elf
arm-linux-ld -T sdram.lds start.o init.o interrupt.o nand_flash.o led.o uart.o main.o exception.o timer.o my_printf.o string_utils.o lib1funcs.o -o sdram.elf
arm-linux-objcopy -O binary -S sdram.elf sdram.bin
arm-linux-objdump -D sdram.elf > sdram.dis
xjh@ubuntu:~/iot/embedded_basic/jz2440/armBareMachine/004_erase_write_016_005$
2.5 其他解决方法
通过查询,网上似乎有解决这些问题的其他方法(不是更换版本的方法),不知道有没有真解决问题,有空测试一下。
(1)undefined reference to `__aeabi_uidivmod' 的解决方法
(2)编译报undefined reference to `__aeabi_uldivmod'错误
(3)__aeabi_uldivmod 解决办法
3、分析受版本影响的原因
为什么交叉编译工具链的版本会影响编译过程?按理说,我使用的版本比韦老师当时使用的版本更高,应该可以向下兼容。
待查明。
(1)解决uboot编译问题__aeabi_uidivmod'和o `__aeabi_uidiv'没定义的错误
(2)解决undefined reference to `__aeabi_uidivmod\'和undefined reference to `__aeabi_uidiv\'错误