交叉编译工具链和反汇编
交叉编译工具链
如果C程序是运行在linux上的,那么就需要linux系统下的编译器,同样的,任何平台都有其专用的编译器。
win或者linux上的程序想要成功写到arm中,需要用到专用的编译工具链。
日常工作中大家就顺口叫做编译器,但其实要明白,讲的其实就是交叉编译工具链。里面包括了预处理器、编译器、链接器、反汇编等等一系列工具。比如:
我们首先安装和配置arm环境下的交叉编译工具链。
linux中安装软件比windows中复杂。linux中安装软件一般有以下几种方法:
第一种:在线安装。譬如ubuntu中使用apt-get install vim来安装vim软件。
第二种:自己下载安装包来安装。这种方式的缺陷就是你不知道你下载的安装包和你的系统是否匹配。
第三种:最装逼的一种方式,就是源代码安装。
总结:我们安装交叉编译工具链(arm-linux-gcc)实际采用第二种安装方式。我们选择交叉编译工具链的原则:和我们所使用的目标平台(给哪款SoC编程)尽量去匹配。譬如我们开发S5PV210的程序就是用arm-2009q3这个版本,因为三星官方在开发S5pv210时就使用这个版本的交叉编译工具链,这样可以最大限度的避免稀奇古怪的问题出现。
交叉编译工具链的安装
步骤1:打开虚拟机,在/usr/local/下创建/usr/local/arm文件夹
步骤2:先将安装包从Windows中弄到linux中去。可以用共享文件夹,也可以用Samba,也可以cuteftp。接着将安装包复制或者移动到刚才创建的arm文件夹中。
步骤3:解压。tar -jxvf arm-2009q3.tar.bz2
到此相当于程序已经安装完毕,真正的应用程序安装在/usr/local/arm/arm-2009q3/bin目录下注:linux中的目录管理方法。技术角度来讲,linux中所有目录性质都是一样的,所以技术角度来讲我们把软件安装到哪里都行。但是因为如果胡乱放置,将来程序可能不好找。所以久而久之大家就总结了一个文件放置的一般定义,譬如说/bin目录放置一些系统自带的用户使用的应用程序,/sbin目录下存放的是系统自带的系统管理方面的应用程序。
那我们装软件放在哪里?一般都在/usr目录下。我们安装arm-linux-gcc,就在/usr/local/底下创建一个arm文件夹,然后装到里面。
安装后的测试:
到真正的应用程序的安装目录下(也就是/usr/local/arm/arm-2009q3/bin),去执行arm-linux-gcc -v,这里的arm-linux-gcc是一种统称,不同源的编译链可能名称不一样,这里的具体执行方法是:./arm-none-linux-gnueabi-gcc -v
执行后可以得到一长串输出,其中有“gcc version 4.4.1 ”字样,即表示安装成功。在bin目录下执行时遇到了问题:
解决方法:arm-none-linux-gnueabi-gcc No such file or directory这个错误的解决方法
配置环境变量
交叉编译链安装完成之后,如果想要使用,必须进入到该工具的安装目录下才能执行,否则系统找不到该命令,为了解决这个问题,就需要配置环境变量。
环境变量就是操作系统的全局变量。每一个环境变量对操作系统来说都是唯一的,名字和所代表的意义都是唯一的。linux系统可以有很多个环境变量。其中有一部分是linux系统自带的,还有一些是我们自己来扩充的。我们这里涉及到的一个环境变量是PATH。PATH这个环境变量是系统自带的,它的含义就是系统在查找可执行程序时会搜索的路径范围。将工具链导出到环境变量
export PATH=/usr/local/arm/arm-2009q3/bin:$PATH
在一个终端中执行以上命令后,该终端中就可以直接使用arm-linux-gcc了,但是只要关掉这个终端再另外打开一个立马就不行了。原因是我们本次终端中执行时的操作只是针对本终端,以后再打开的终端并未被执行过这个命令所以没导出。解决方案是在~/.bashrc中,添加export PATH=/usr/local/arm/arm-2009q3/bin:$PATH 即可。
注意:我们导出这个环境变量是在当前用户,如果你登录时在其他用户下是没用的。
比如:ln arm-none-linux-gnueabi-gcc -s arm-linux-gcc有个问题,当在bin目录下时,前面加不加./来执行都可以,但是配置了环境变量后,在别的地方就不能再加./来执行了。
我想了想,这个./是啥意思,其实就是最基本的意思,表示在当前目录下!!!配置了之后就不用再加这个了,因为已经不是在当前目录下了。linux中执行程序,其实指明pathname即可。
这些命令都太长了,要输入半天:
为了方便使用,可以进入到对应的bin目录下为每一个工具创建符号链接。
那么多重复动作,可以创建一个shell脚本来执行,建议直接在linux下创建脚本,因为win和linux中的回车键是不同的,在win中是\n\r,而在linux中是\r\r。
实践操作:
1、vim lnarm210.sh写入如下内容:
ln -s arm-none-linux-gnueabi-c++filt arm210-c++filt
ln -s arm-none-linux-gnueabi-cpp arm210-cpp
ln -s arm-none-linux-gnueabi-g++ arm210-g++
ln -s arm-none-linux-gnueabi-gcc arm210-gcc
ln -s arm-none-linux-gnueabi-gcc-4.4.1 arm210-gcc-4.4.1
ln -s arm-none-linux-gnueabi-gcov arm210-gcov
ln -s arm-none-linux-gnueabi-gdb arm210-gdb
ln -s arm-none-linux-gnueabi-gdbtui arm210-gdbtui
ln -s arm-none-linux-gnueabi-gprof arm210-gprof
ln -s arm-none-linux-gnueabi-ld arm210-ld
ln -s arm-none-linux-gnueabi-nm arm210-nm
ln -s arm-none-linux-gnueabi-objcopy arm210-objcopy
ln -s arm-none-linux-gnueabi-objdump arm210-objdump
ln -s arm-none-linux-gnueabi-ranlib arm210-ranlib
ln -s arm-none-linux-gnueabi-readelf arm210-readelf
ln -s arm-none-linux-gnueabi-size arm210-size
ln -s arm-none-linux-gnueabi-sprite arm210-sprite
ln -s arm-none-linux-gnueabi-strings arm210-strings
ln -s arm-none-linux-gnueabi-strip arm210-strip
这里我在退出的时候遇到了一个问题:Can't open file for writing,权限不足导致的,网上找到的解决方案如下:Linux使用vi编辑文件报错:E212:Can‘topenfileforwritingP。。。 - 百度文库
2、执行脚本source lnarm210.sh,这里又遇到了权限的问题;
只能sudo chmod 744 lnarm210.sh,但是因为刚才文件创建是在root用户下,所以属主和属组都是root,所以需要改变其他用户的权限,或者切换到root目录下去执行,我这里切换到root下去执行:
到此,已顺利创建完成。
常见用法
对于交叉编译工具链,怎么去用这个命令,各命令都有哪些参数?
这个我没有找到具体的用法解释,估计实际中厂家会给到,我这里就把课程中讲到的做个简单的记录。
链接命令:
arm-linux-ld -Ttext 0x0 -o led.elf $^
将elf文件制作成bin文件:
arm-linux-objcopy -O binary led.elf led.bin反汇编:将可执行程序led.elf反汇编为led_elf.dis
arm-linux-objdump -D led.elf > led_elf.dis
示例演示
当前,我这里有这几个文件
Makefile文件中内容如下:
led.bin: start.o arm210-ld -Ttext 0x0 -o led.elf $^arm210-objcopy -O binary led.elf led.binarm210-objdump -D led.elf > led_elf.disgcc mkv210_image.c -o mkx210./mkx210 led.bin 210.bin%.o : %.Sarm210-gcc -o $@ $< -c%.o : %.carm210-gcc -o $@ $< -c clean:rm *.o *.elf *.bin *.dis mkx210 -f我把这些文件放到共享文件夹中,然后在linux中执行make(在第一次使用make时需要先安装该应用)
反汇编
反汇编工具objdump的使用简介
反汇编的原理&为什么要反汇编
arm-linux-objdump -D led.elf > led_elf.dis
objdump是gcc工具链中的反汇编工具,作用是由编译链接好的elf格式的可执行程序反过来得到汇编源代码
-D表示反汇编 > 左边的是elf的可执行程序(反汇编时的原材料),>右边的是反汇编生成的反汇编程序
反汇编的原因有以下:
1.逆向破解,通常elf可执行程序我们用文本打开看就是一串乱码
如果想看,需要用特定的二进制文件阅读工具,比如WinHex
这里了解即可,事实上,elf中有很多冗余信息,如果要看具体的内容,需要打开对应的bin文件,如下所示:
采用的是小端模式,所以后面对应的是高位。
2.调试程序时,反汇编代码可以帮助我们理解程序(我们学习时使用objdump主要目的是这个),尤其是在理解链接脚本、链接地址等概念时。
3. 把C语言源代码编译链接生成的可执行程序反汇编后得到对应的汇编代码,可以帮助我们理解C语言和汇编语言之间的对应关系。非常有助于深入理解C语言。
反汇编文件的格式和看法
(汇编 assembly 反汇编 dissembly)
标号地址、标号名字、指令地址、指令机器码、指令机器码反汇编到的指令led.elf: file format elf32-littlearmDisassembly of section .text:00000000 <_start>:0: e59f104c ldr r1, [pc, #76] ; 544: e59f004c ldr r0, [pc, #76] ; 58 8: e5810000 str r0, [r1]c: e3a02a01 mov r2, #4096 ; 0x100000000010 :10: e59f1044 ldr r1, [pc, #68] ; 5c 14: e3a00000 mov r0, #018: e5810000 str r0, [r1]1c: eb000007 bl 40 20: e59f1034 ldr r1, [pc, #52] ; 5c 24: e3a00038 mov r0, #56 ; 0x3828: e5810000 str r0, [r1]2c: eb000003 bl 40 30: e2422001 sub r2, r2, #134: e3520000 cmp r2, #038: 1afffff4 bne 10 0000003c :3c: eafffffe b 3c 00000040 :40: e3a00609 mov r0, #9437184 ; 0x90000000000044 :44: e3500000 cmp r0, #048: e2400001 sub r0, r0, #14c: 1afffffc bne 44 50: e1a0f00e mov pc, lr54: e0200240 eor r0, r0, r0, asr #458: 00111000 andseq r1, r1, r05c: e0200244 eor r0, r0, r4, asr #4Disassembly of section .ARM.attributes:00000000 <.ARM.attributes>:0: 00001a41 andeq r1, r0, r1, asr #204: 61656100 cmnvs r5, r0, lsl #28: 01006962 tsteq r0, r2, ror #18c: 00000010 andeq r0, r0, r0, lsl r010: 45543505 ldrbmi r3, [r4, #-1285] ; 0x50514: 08040600 stmdaeq r4, {r9, sl}18: Address 0x00000018 is out of bounds.
上面有些地址里是指令码,有些是数据。
有些命令后面有个分号;后面还有个数字或者地址,这个就是前面的指令中的第二个参数所代表的值,比如[pc, #76],即PC往后偏移76个字节所指向的内存地址的结果就是54。再比如#4096对应的十六进制数就是0x1000
另外,这里提一下ARM的三级流水线:
下载烧录执行的bin文件,内部其实是一条一条的指令机器码。这些指令每一条都有一个指令地址,这个地址是连接的时候ld给指定的(ld根据我们写的链接脚本来指定)
展望:反汇编工具帮助我们分析链接脚本
反汇编的时候得到的指令地址是链接器考虑了链接脚本之后得到的地址,而我们写代码时通过指定连接脚本来让链接器给我们链接合适的地址。
但是有时候我们写的链接脚本有误(或者我们不知道这个链接脚本会怎么样),这时候可以通过看反汇编文件来分析这个链接脚本的效果,看是不是我们想要的,如果不是可以改了再看。
ELF和BIN文件
ELF是Linux环境下的可执行文件,类似于win下的EXE文件。
Gcc编译出来的是ELF文件。通常gcc –o test test.c,生成的test文件就是ELF格式的,在linuxshell下输入 ./test就可以执行。
Bin 文件是经过压缩的可执行文件,去掉ELF格式的东西。是直接的内存映像的表示。在系统没有加载操作系统的时候可以执行。
elf(executable and link format)文件里面包含了符号表,汇编等。
BIN文件是将elf文件中的代码段,数据段,还有一些自定义的段抽取出来做成的一个内存的镜像。在Embedded中,如果上电开始运行,没有OS系统,如果将ELF格式的文件烧写进去,包含一些ELF格式的东西,arm运行碰到这些指令,就会导致失败,如果用arm-softfloat-linux-gnu-objcopy生成纯粹的汇编 bin文件,程序就可以一步一步运行。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!













