Linux下的目标文件、动态库文件、可执行文件,其格式为elf格式。
elf文件是有结构的文件,其内部有丰富的信息,例如,可能包含了可执行文件的入口地址,各个节的起始地址,可重定位信息,还可能包含指令与代码行的对应关系(用于调试)。
内核则利用elf文件中的相关信息,加载运行可执行文件。
然而内核映像,u-boot映像这些特殊的文件,则是raw_binary文件。这当然有他的原因。
以u-boot为例,cpu通电后,就开始执行指令。而首先要执行的就是u-boot中的指令。然而cpu不具备解析elf文件的能力,他只知道执行指令。因此,只好给他一块纯粹的机器码让他跑。
因此,u-boot映像就做成了raw_binary文件。
raw_binary文件是没有任何结构的,其内容就是赤裸裸的代码与数据的组合体。
因此,不具备可解析性。
下面以一个简单的小例子,来看看raw_binary文件的面貌。
elf文件是有结构的文件,其内部有丰富的信息,例如,可能包含了可执行文件的入口地址,各个节的起始地址,可重定位信息,还可能包含指令与代码行的对应关系(用于调试)。
内核则利用elf文件中的相关信息,加载运行可执行文件。
然而内核映像,u-boot映像这些特殊的文件,则是raw_binary文件。这当然有他的原因。
以u-boot为例,cpu通电后,就开始执行指令。而首先要执行的就是u-boot中的指令。然而cpu不具备解析elf文件的能力,他只知道执行指令。因此,只好给他一块纯粹的机器码让他跑。
因此,u-boot映像就做成了raw_binary文件。
raw_binary文件是没有任何结构的,其内容就是赤裸裸的代码与数据的组合体。
因此,不具备可解析性。
下面以一个简单的小例子,来看看raw_binary文件的面貌。
raw_binary.c是个简单的小程序,其内容如下:
char the_data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
char bss_data1[3], bss_data2[4];
/* 为了初始化bss节,这里借助链接脚本中创建的两个符号,以得到bss节的地址区间 */
extern char __bss_start[], __bss_end[];
void init_bss_area();
void my_test_func()
{
/* 为了能以raw binary形式运行,程序自己实现对bss节的清零 */
init_bss_area();
the_data[1]++;
while (1)
{
asm volatile ("nop");
}
}
void init_bss_area()
{
int i, len = __bss_end - __bss_start;
for (i=0; i<len; i++)
__bss_start[i] = 0;
}
我们通过如下命令将上述代码编译成一个可执行文件。
[root@localhost raw_binary]# gcc -O2 -c raw_binary.c -o raw_binary.o
[root@localhost raw_binary]# ld -T raw_binary.lds raw_binary.o -o raw_binary.exe
注意,上述编译过程中,我们用到了一个链接脚本raw_binary.lds。其内容如下:
ENTRY(my_test_func)
SECTIONS
{
/* 这里设置代码段从2M开始 */
. = 0x200000;
.text :
{
*(.text)
}
/* 我们让数据段的虚拟地址空间开始于8字节对齐的地方 */
.