一、交叉编译
我们下载到开发板上的镜像文件,往往都是开源代码,先移植(软硬件不匹配需要移植也就是配置),然后编译成机器码生成可执行文件形成的镜像文件,接下来将讨论如何移植这些文件。
1.1编译原理
汇编语言与机器码一 一对应且无法移植,c语言不区分平台
1.机器码(二进制)是处理器能直接识别的语言,不同的机器码代表不同的运算指令,处理器能够识别哪些机器码是由处理器的硬件设计所决定的,不同的处理器机器码不同,所以机器码不可移植
2.汇编语言是机器码的符号化,即汇编就是用一个符号来代替一条机器码,所以不同的处理器汇编也不一样,即汇编语言也不可移植
3.C语言在编译时我们可以使用不同的编译器将C源码编译成不同架构处理器的汇编,所以C语言可以移植
1.2 GCC编译过程
在ubuntu上写一个test.c的文件说明此过程
1>.在C语言中以#开头的是预处理指令,不能被CPU执行,即不能汇编和编译;预处理宏定义替换,头文件展开即如下所示。
2>.编译:编译为汇编代码
3>.汇编:汇编语言转换为机器码
4>.链接:不同的机器码链接到一块(组内负责各个模块的代码汇编后链接成一个文件)
1.3 交叉编译
程序的编译和运行不在同一台机器上
1.3.1 交叉编译工具链
交叉编译工具链的获取:
1)官网获取(不推荐,需要自己进行复杂配置与编译)
http://ftp.gnu.org/gnu/gcc/
2) BSP板级开发支持包(推荐)
samsung、全志...
交叉编译工具链的内容
1)交叉编译工具
gcc/readelf/size/nm/strip/objcopy/objdump/addr2line
2) 库ARM架构的库
.so:共享库
.a:静态库
库分架构(二进制代码)
ubuntu上的库是在x86编译时链接的
交叉编译内的库是在交叉编译时链接的,ARM架构的
二、ELF文件格式
ELF运行于linux之前的可执行文件(应用层文件一般为ELF格式)。 Linux/unix也支持其他格式的可执行文件,但在嵌入式领域,基本是ELF格式。
ELF格式是Linux平台上应用最广泛的二进制工业标准之一。ELF格式的文件内包含了很多个段不同的段存储了不同的信息;因为ELF格式的文件要通过Linux系统的加载和管理才能运行,所以除了最基本的代码段和数据段之外(除了可执行语句和全局变量,Linux加载和管理ELF格式的文件),ELF还存储了很多其他信息,如符号表(C函数名,汇编标识符),调试信息(-g -GDB调试信息)、链接信息等。
2.1 ELF 文件相关命令
file
file + 文件名查看文件的详细信息
readelf
readelf -h + 文件名 列出elf文件的头部信息
readelf -a + 文件名 列出elf文件的所有信息
ubuntu下的readelf和arm-none-linux-gnueabi-readelf 使用效果相同。
2.2 BIN文件格式
BIN文件(二进制文件)一般是直接运行在CPU之上的可执行文件,文件内只包含CPU能够了直接识别和运行的指令和数据(汇编编译生成的机器码和全局变量对应的机器码),不包含其它系统相关的信息
三、交叉编译工具链常用工具
3.1 size:列出目标文件每一段的大小以及总体的大小
size + 文件名
text:代码段,汇编指令编译生成的机器码
data:全局变量(int a = 100;)和 static静态局部变量
bss:未初始化的全局变量(int a;)和未初始化静态局部变量
bss段内的变量会统一清零,方便后面赋值。
dec是总的大小(前三个和),hex是16进制
局部变量 程序运行时在栈内分配空间,编译时不会分配空间
区分ll命令:ll命令是整个ELF文件的大小,size命令是能够在CPU上运行的变量和代码。
不同编译器编译c语言代码出来的可执行文件大小也不同。
3.2 nm:列出目标文件中的符号表(标示符)
nm + 文件名
函数名在编译的时候存放在符号表中。函数名在链接时可以指示函数地址,在执行时没有作用。
3.3 strip 丢弃目标文件中的符号
strip + 文件名注:对于嵌入式开发,这个命令很重要
在编译执行过程中,符号表不会被加载到内存,也不会加载到CPU执行,对生成的可执行文件瘦身,将符号表减掉,节省磁盘空间。对嵌入式开发很重要
通过file 命令查看文件是否经过瘦身2
而符号表的意义:.o目标文件状态下可以查看函数名(不给别人知道函数怎么写的,给.o文件 )
3.4 objdump:从目标文件中显示信息
eg:objdump -d + 文件名将目标文件反汇编(机器码->汇编)
反汇编:机器码->汇编 (汇编语言和机器码一一对应)
ARM 反汇编
3.5 bjcopy :对目标文件进行复制和转换
eg:objcopy --gap-fill=0xff -O binary a.out a.bin 将目标文件转换为bin格式
ELF是Linux系统下生成的文件,BIN是直接运行在CPU之上的。
gcc默认生成的是ELF文件,将ELF中的文件删除附加信息,命令中 --gap-fill=0xff 填充空隙。
分架构命令不同