一、交叉工具链:
交叉工具链,其实他有两个含义,一个就是交叉工具,所谓的交叉工具就是运行的环境和编译的环境不是在一体的。就像我们现在,编译裸机程序是在pc机上面执行的。可我们运行程序是在开发板。链,就是很多的意思,就是一个工具的集合。在我们前面配置arm-linux-gcc的工具中。在/usr/local/arm/4.3.2/bin的目录下有很多编译工具。例如图1-1:
图1.-1 交叉工具链
下面我们来写一个简单的程序,用这些工具编译。
Hello.c:
#include 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
上一篇:3.Makefile工程管理
下一篇:1.裸机开发环境的体验(Redhat 6.4 + vbox)
推荐阅读最新更新时间:2024-11-20 10:49