2.交叉工具链

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2.交叉工具链相关的知识,希望对你有一定的参考价值。

2.交叉工具链

一、交叉工具链:

交叉工具链,其实他有两个含义,一个就是交叉工具,所谓的交叉工具就是运行的环境和编译的环境不是在一体的。就像我们现在,编译裸机程序是在pc机上面执行的。可我们运行程序是在开发板。链,就是很多的意思,就是一个工具的集合。在我们前面配置arm-linux-gcc的工具中。在/usr/local/arm/4.3.2/bin的目录下有很多编译工具。例如图1-1:

技术分享

图1.-1 交叉工具链

下面我们来写一个简单的程序,用这些工具编译。

Hello.c:

#include <stdio.h>

void main(){

????printf("hello fish!\n");

}

这是一个简单的hello程序。首先我们先用我们熟悉的gcc编译并执行。图1-2:

技术分享

图1-2

我们看到程序正常运行。输出了内容。

接下来我们用刚安装的交叉工具来编译运行。图1-3:

技术分享

图1-3

我们看见程序出错了。提示的信息是不能运行的二进制文件。这就奇怪了。这是为啥呢?其实呢。我在前面已经提过了,arm-linux-*工具,编译的程序是在开发板运行的。其实我们可以通过:file 文件名.来查看该应用程序运行的平台。图1-4:

技术分享

图1-4

可以看到信息,hello是gcc编译生成的是运行在x86架构的,hello1是arm-linux-gcc编译生成的是运行在ARM架构的。

接下来我们把hello1拷贝到开发板运行看看。

我已在开发板烧写好了linux系统,通过u盘,把hello1拷贝到开发板。然后插入开发板的usb口。在终端可以看见提示信息,这是因为我们的linux带有usb驱动,当我们的usb插进去的时候,它检测到了usb,加载好了驱动。现在我们进入u盘,运行hello1程序。图1-5.这时仍然提示错误。如下:

?

?

这是为啥呢?这是我们的开发板缺少程序运行时需要的动态库,因为我刚才编译的时候没有加-static属性。加上-static属性重新编译。图1-6:

技术分享

图1-6

可以看到,这次加入了-static条件,编译生成的hello2程序比hello1大了许多,就是因为把运行需要的库文件都静态链接进来了。同样拷贝到u盘,可以看到顺利运行。图1-7:

技术分享

图1-7

二、交叉工具链的详述:

1.arm-linux-gcc编译器:

前面,可以看到gcc和arm-linux-gcc工具的编译条件都是一样的。可为什么编译出来的应用程序会运行在不同的平台呢?这是因为,他们两个在编译的时候引用的头文件不同。传统的gcc是默认去/usr/include寻找它需要的头文件。图1-8:

技术分享

图1-8头文件

而arm-linux-gcc寻找的头文件的目录不同。首先使用arm-linux-gcc –help查看它的使用:图1-9:

技术分享

图1-9

注意到参数-print-search-dirs就是显示寻找头文件的参数目录。加上该参数得到一下信息图1-10:

技术分享

图1-10

从上面的显示看到arm-linux-gcc默认是到我们安装arm-linux-gcc的目录去找头文件的。

?

?

2.arm-linux-ld:

arm-linux-ld是链接器,下面介绍它的使用。

首先先用arm-linux-gcc生成中间文件.o文件。图2-1:

arm-linux-gcc -g -c led.S

技术分享

图2-1

在上面的参数中-g表示可以用gdb来调试信息,-c是只编译不链接。最后生成led.o中间文件。接下来就是使用arm-linux-ld把该文件链接成elf文件:图2-2:

arm-linux-ld -Tled.lds -o led.elf led.o

技术分享

图2-2

上面语句的意思是利用arm-linux-ld链接器,按照-T指定的链接器脚本,把生成的led.o(如果有多个.o文件,在后面继续加上),链接成led.elf文件。

?

3.arm-linux-readelf:

利用该工具可以查看生成的.elf文件的内容:

执行:arm-linux-readelf -a led.elf。-a参数是all的意思,表示查看所有信息:图2-3:

技术分享

技术分享

技术分享

技术分享

图2-3

从上面看到elf文件有一个固定的头:ELF Header:然后:

Data: 2‘s complement, little endian

是表示他是运行在小端处理器的。

Machine: ARM

是表示他是运行在ARM平台的。

所以当运行一个程序出错的时候,当检查完语法没问题,仍然不能运行的时候,就应该用readelf查看一下这些信息是否符合。如果上面的两种检查完了之后还是不能运行。接下来就是查看需要的库是否存在。使用的命令:

arm-linux-readelf -d hello

运行结果:图2-4:

技术分享

图2-4

上面显示了该hello应用程序需要的库是libc.so.6.如果没有该库,该程序运行不了。

?

?

?

?

4.arm-linux-objdump:

ARM反汇编器。

上面已经使用arm-linux-gcc编译产生了可执行文件hello2.现在对它进行反汇编。命令:

arm-linux-objdump -D -S hello2 >mydump

该命令的意思是将hello2可执行程序反汇编,输出到mydump文件。执行之后会在该目录下产生一个mydump文件:图2-5:

技术分享

打开可以看到对应的汇编代码:

技术分享

但是,都是汇编代码,看起来还是非常困难。可以在编译的时候加上-g调试信息的参数,这样反汇编之后会有部分的c代码存在。这样可以让我们更加容易看懂程序。

技术分享

技术分享

图2-5

可以看到加上-g编译,反汇编后,在汇编代码里居然有c代码出现。在上面的代码中printf("hello fish!\n");的汇编实现就是它下面两行。源代码:

技术分享

5.最后一个是文件格式转换工具:arm-linux-objcopy:

从上面的操作知道,汇编代码通过arm-linux-gcc -g -c led.S,把一个汇编文件转化为一个led.o文件,接着使用:arm-linux-ld -Tled.lds -o led.elf led.o,把led.o利用led.lds脚本,链接成一个led.elf文件。但是elf文件无法在板子运行,必须转化为.bin格式的二进制文件。这就是arm-linux-objcopy的功能:

arm-linux-objcopy -O binary led.elf led.bin

图2-6:

技术分享

图2-6

?

?

?

?

以上是关于2.交叉工具链的主要内容,如果未能解决你的问题,请参考以下文章

QtCreator配置交叉编译工具链

NDK交叉编译之自定义工具链

如何构建MIPS交叉编译工具链

LINUX交叉编译工具链和GCC是啥关系啊

arm交叉编译工具链下载

什么是交叉工具链