链接完成之后,会生成可执行格式的文件。常见可执行格式有exe和elf。这些可执行格式一般依赖于动态共享库,由操作系统加载并替换符号,然后执行。换言之,EXE/ELF格式的可执行文件,由操作系统执行,即执行流程的起点是操作系统。
然而这并不是软件执行的起点,软件执行的起点是系统上电后,CPU读取并执行的第一条指令。如何生成CPU执行的可执行格式的程序呢?
一. CPU执行的可执行格式
其实很简单,CPU执行的可执行格式,即是一条条指令的机器码组成的程序。这个程序固化在硬盘的启动扇区,或者烧写在flash中。位于CPU地址区间的地址0即0x0000_0000处。
CPU执行的可执行格式也不是一成不变,一定从地址0读取第一条指令开始执行的。如MPC56xx即是查找Boot sector,然后从中提取要执行的代码的地址(reset vector)。还有的CPU会从boot sector中找到栈地址并赋值给SP寄存器。
二.objcopy
Link Command File或者Link Description Script或者Linker Script控制链接器生成的可执行程序中各个段的分布。如之前的FLASH.lcf,也是按照CPU的需要生成的可执行格式:
其中__bam_bootarea即是boot sector。不过遗憾的是,链接生成的是ELF格式的可执行文件。
但也可以想到,如果要通过这个ELF格式的可执行文件,生成CPU执行的可执行格式,即可以烧录FLASH的image镜像,距离也不远了。
所需要的工具是objcopy, 只需要这一步即可。
ELF和Image镜像(CPU上电执行的可执行格式)的区别在哪里呢?
Image镜像文件偏移量0处是与CPU约定好的格式,要么是复位中断向量,要么是Boot sector;而ELF偏移量0处是ELF文件头。
ELF文件开头:
镜像文件开头:
ELF中包含调试信息,符号信息,库引用信息等;Image镜像文件一般是静态链接,不依赖动态共享库,谁来帮他查找这些符号呢?
其他等等。
三.反其道而行之
FLASH中存储的是CPU执行的可执行格式的镜像,这是objcopy生成之后,烧录进FLASH中的。
那么把FLASH拆下来通过烧录器读取其中的内容,即是CPU执行的可执行格式的镜像文件。执行生成这个镜像文件的逆过程,即先objcopy恢复成ELF格式(可能信息丢失不可逆,无法成功),然后再反汇编即可看到代码的内容。实际上,镜像文件可以直接被反汇编。可以做的事情有哪些,就可以想象了。