在Ubuntu下编译运行arm架构程序

Ubuntu本身是不支持arm架构的,但是可以通过qemu来执行,编译可以使用gcc对于arm的交叉编译器。

下面的命令是用来安装qemu和gcc for arm的:

sudo apt install qemu gcc-5-arm-linux-gnueabihf gcc-5-multilib-arm-linux-gnueabihf

下面是gcc的命令:

arm-linux-gnueabihf-addr2line     arm-linux-gnueabihf-gcc-nm-5      arm-linux-gnueabihf-nm
arm-linux-gnueabihf-ar            arm-linux-gnueabihf-gcc-ranlib-5  arm-linux-gnueabihf-objcopy
arm-linux-gnueabihf-as            arm-linux-gnueabihf-gcov-5        arm-linux-gnueabihf-objdump
arm-linux-gnueabihf-c++filt       arm-linux-gnueabihf-gcov-dump-5   arm-linux-gnueabihf-ranlib
arm-linux-gnueabihf-cpp-5         arm-linux-gnueabihf-gcov-tool-5   arm-linux-gnueabihf-readelf
arm-linux-gnueabihf-dwp           arm-linux-gnueabihf-gprof         arm-linux-gnueabihf-size
arm-linux-gnueabihf-elfedit       arm-linux-gnueabihf-ld            arm-linux-gnueabihf-strings
arm-linux-gnueabihf-gcc-5         arm-linux-gnueabihf-ld.bfd        arm-linux-gnueabihf-strip
arm-linux-gnueabihf-gcc-ar-5      arm-linux-gnueabihf-ld.gold

下面我们来编译一下:

root@1afe15b25d69:~# cat main.c 
#include<stdio.h>

int main()
{
    printf("hello world\n");
    return 0;
}
root@1afe15b25d69:~# arm-linux-gnueabihf-gcc-5 -o main main.c 
root@1afe15b25d69:~# ls -l
total 16
-rwxr-xr-x 1 root root 8344 Feb 13 17:00 main
-rw-r--r-- 1 root root   77 Feb 13 16:58 main.c

直接运行是不行的,如下面所示:

root@1afe15b25d69:~# ./main 
-bash: ./main: cannot execute binary file: Exec format error
root@1afe15b25d69:~# file main
main: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=cdb542c00934db3b58d2fd566e245f919262f416, not stripped

所以我们使用qemu-arm来运行:

root@1afe15b25d69:~# qemu-arm ./main
/lib/ld-linux-armhf.so.3: No such file or directory

如上所示,缺少了/lib/ld-linux-armhf.so.3,让我们来找找这个文件在哪。

root@1afe15b25d69:~# find / -name ld-linux-armhf.so.3
find: ‘/proc/1/map_files’: Operation not permitted
find: ‘/proc/22/map_files’: Operation not permitted
find: ‘/proc/50/map_files’: Operation not permitted
find: ‘/proc/55/map_files’: Operation not permitted
find: ‘/proc/56/map_files’: Operation not permitted
find: ‘/proc/57/map_files’: Operation not permitted
find: ‘/proc/58/map_files’: Operation not permitted
find: ‘/proc/59/map_files’: Operation not permitted
find: ‘/proc/63/map_files’: Operation not permitted
find: ‘/proc/68/map_files’: Operation not permitted
find: ‘/proc/79/map_files’: Operation not permitted
find: ‘/proc/1599/map_files’: Operation not permitted
/usr/arm-linux-gnueabihf/lib/ld-linux-armhf.so.3
/usr/arm-linux-gnueabi/libhf/ld-linux-armhf.so.3

然后使用下面的命令创建软链接:

ln -s /usr/arm-linux-gnueabihf/lib/ld-linux-armhf.so.3 /lib/ld-linux-armhf.so.3

再运行试试:

root@1afe15b25d69:~# qemu-arm ./main
./main: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory

还是不行,正如错误所说找不到基地址库,让我们再找找:

root@1afe15b25d69:~# find / -name libc.so.6
/lib/x86_64-linux-gnu/libc.so.6
/lib/i386-linux-gnu/libc.so.6
find: ‘/proc/1/map_files’: Operation not permitted
find: ‘/proc/22/map_files’: Operation not permitted
find: ‘/proc/50/map_files’: Operation not permitted
find: ‘/proc/55/map_files’: Operation not permitted
find: ‘/proc/56/map_files’: Operation not permitted
find: ‘/proc/57/map_files’: Operation not permitted
find: ‘/proc/58/map_files’: Operation not permitted
find: ‘/proc/59/map_files’: Operation not permitted
find: ‘/proc/63/map_files’: Operation not permitted
find: ‘/proc/68/map_files’: Operation not permitted
find: ‘/proc/79/map_files’: Operation not permitted
find: ‘/proc/1603/map_files’: Operation not permitted
/usr/arm-linux-gnueabihf/lib/libc.so.6
/usr/arm-linux-gnueabihf/libsf/libc.so.6
/usr/arm-linux-gnueabi/lib/libc.so.6
/usr/arm-linux-gnueabi/libhf/libc.so.6
/lib32/libc.so.6
/libx32/libc.so.6

知道地址后可以直接执行下面的命令让系统会到该目录去查找库:

export LD_LIBRARY_PATH=/usr/arm-linux-gnueabihf/lib/:$LD_LIBRARY_PATH

再运行看看就没问题了:

root@1afe15b25d69:~# export LD_LIBRARY_PATH=/usr/arm-linux-gnueabihf/lib/:$LD_LIBRARY_PATH
root@1afe15b25d69:~# qemu-arm ./main
hello world

为了方便也可以直接把该命令写入自启动脚本:

echo "export LD_LIBRARY_PATH=/usr/arm-linux-gnueabihf/lib/:$LD_LIBRARY_PATH" >> ~/.bashrc