我们如何加载Linux映像以适应内存中的位置

Ami*_*mar 5 linux bootstrapping linux-kernel bootloader

我们正在尝试将linux映像加载到我们位于特定位置的DRAM中,DRAM结束地址为0x80000000,我们从启动日志中了解到"mem device ending address是0x80000000".我们正在加载地址为"0x5000000"的图像并且在图像中的variuos部分加载到某个大于"0x80000000"的地址之前,从引导日志再次获得eaxmple

 loading section to address 0xc5000000 from file position 0x1000, size is 0x5ac13e
Run Code Online (Sandbox Code Playgroud)

什么意思是"从文件位置0x1000"在上面的行.

加载的第一部分是.text部分,下面是我们的部分标题的vmlinux图像转储

[Nr]      Name           Type            Addr     Off    Size   ES Flg Lk Inf Al

[ 0]                     NULL            00000000 000000 000000 00      0   0  0

 [ 1]   .text            PROGBITS        c5000000 001000 5ac13e 00  AX  0   0 4096

 [ 2]      .notes           NOTE            c55ac140 5ad140 000168 00  AX  0   0  4

 [ 3]    __ex_table        PROGBITS        c55ac2b0 5ad2b0 000fe0 00   A  0   0  4

 [ 4]   .rodata           PROGBITS        c55ae000 5af000 20a930 00   A  0   0 64

 [ 5]   __bug_table       PROGBITS        c57b8930 7b9930 0075fc 00   A  0   0  1

 [ 6]   .pci_fixup        PROGBITS        c57bff2c 7c0f2c 001a90 00   A  0   0  4

 [ 7]    .builtin_fw       PROGBITS        c57c19bc 7c29bc 0000cc 00   A  0   0  4
Run Code Online (Sandbox Code Playgroud)

它是一个相当大的列表,所以没有发布完整.但是我们可以在这里看到一件事.text部分大于DRAM结束地址,所以尽管我们在加载第一部分之后没有收到任何错误但是图像不应该被正确编码在加载其他部分但在此消息之后它会挂起.

    program load complete, entry point: 0x5000000, size: 0x92e7fc
Run Code Online (Sandbox Code Playgroud)

我的问题是如何将这些不同的部分地址与我们的DRAM地址对齐,这里可以使用objcopy实用程序来更改这些不同部分的地址.

在编译之前有没有办法设置这些节地址?第二件事可能是这个Hang afer程序加载完成的原因.

Ale*_*nze 6

from file position 0x1000意味着什么.你在转储中有它:

[Nr]      Name           Type            Addr     Off    Size   ES Flg Lk Inf Al
...
[ 1]   .text            PROGBITS        c5000000 001000 5ac13e 00  AX  0   0 4096
Run Code Online (Sandbox Code Playgroud)

这是该.text部分在文件中以偏移量开始的位置0x1000.

但有一件事我们可以在这里看到.text部分大于DRAM结束地址

不,它并不是更大(至少在更大的意义上),它的编译期望它将被加载0xc5000000到内存中的地址.

因此,虽然我们在加载第一部分之后没有收到任何错误,但它不会被正确编码,因此它会继续加载其他部分

图像可以在任何地方加载,它只是用于加载目的的数据.

OTOH,如果loading section to address 0xc5000000意味着它所说的,那么文件就会因为你的RAM结束而无处加载0x7fffffff.

但在此消息之后它会挂起.

这是预期的.机器代码很少与位置无关,因此如果将它加载到与应该加载​​的位置不同的位置,它将无法工作.或者如果它甚至没有加载,那么你要执行什么?垃圾.

在编译之前有没有办法设置这些节地址?

根据系统的不同,您可以选择以下两个选项之一或两者:

  • 设置页面翻译,使得虚拟地址从0xc5000000和向上映射到0x5000000整个程序的物理地址
  • 找到编译器正在使用的链接器脚本并将初始节地址更改0xc50000000x5000000,google up,请参阅编译器/链接器文档

此外,入口点的位置有点奇怪0x5000000.并不是说这一定是错的,只是很少这样.我确保start标签(或其_start任何东西)确实收到与该.text部分开头相同的地址.如果出于某种原因,情况并非如此,那么链接器脚本或编译器/链接器命令行选项或加载器都会出现问题.