linux Qemu没有在我指定的地址加载我的图像文件

ha5z0ras  于 2023-05-28  发布在  Linux
关注(0)|答案(2)|浏览(176)

我的链接器脚本:

SECTIONS{
    . = 0xC0008000;
    __text_start = .;
    .text :
    {
        boot/start.o
        *(.text)
    }
    __text_end = .;
    .rodata ALIGN(4) : {*(.rodata*)}     
    .data ALIGN(4)   : { *(.data) }    
    __bss_start = .;    
    .bss ALIGN(4)  : { *(.bss)  *(COMMON) }    
    __bss_end = .;
}

0xC 0008000是引导加载程序的地址,我想在QEMU中指定它。
这是我尝试过的。\

qemu-system-arm \
        -machine virt \
        -cpu cortex-a15 \
        -nographic \
        -S -s \
        -m 4096M \
        -kernel Image \
        # -device loader,file=Image,addr=0xC0008000

它会将PC设置为0x 40000000,在几个指令后,PC将跳转到0x 40010000的引导加载程序。根据QEMU提供的文件,这是可以接受的,但不是我期望做的。
RAM从0x4000_0000 https://qemu.readthedocs.io/en/latest/system/arm/virt.html开始
但当我将命令更改为

qemu-system-arm \
        -machine virt \
        -cpu cortex-a15 \
        -nographic \
        -S -s \
        -m 4096M \
        -kernel Image \
        -device loader,file=Image,addr=0xC0008000

镜像加载正确,似乎是0xC 0008000中指令的0x 40010000中的重复指令,但它不能跳转到0xC 0008000,这使得调试困难。我想知道为什么PC不能跳到我期望的地方。谢谢!

b91juud3

b91juud31#

你没有说你的图像文件是什么格式。它是一个ELF文件,还是一个原始的二进制文件?从描述的行为来看,我猜这是一个原始的二进制文件。
如果您向QEMU传递-kernel选项,那么您就是在说“这个文件应该以Linux内核期望的方式启动”。这意味着,除其他事项外,你不关心它在内存Map中的位置,它应该首先设置几个寄存器,然后跳转到图像的开始。(有一个例外:ELF文件是根据ELF文件指示它们应该放置的位置来加载的,并通过跳转到ELF入口点来启动。但是现在ELF文件更好地使用通用加载器加载。)
(The“像Linux内核一样 Boot 我”的具体含义在this bit of the kernel documentation中列出。virt板将始终传递设备树blob,而不是ATAG。)
如果您的映像文件不希望像Linux内核那样引导,则不应使用-kernel选项。
相反,您可以使用通用加载器(-device loader)。您的第二个命令行几乎可以做到这一点,但它在两个方面是错误的:
1.你没有删除-kernel选项,所以你的镜像文件将被QEMU加载两次,在两个不同的地方。这只是令人困惑,所以删除-kernel选项。
1.要让通用加载程序为CPU设置启动PC,您需要显式地请求它。由于您想要的启动PC与映像加载地址相同,因此可以使用-device loader,file=Image,addr=0xc0008000,cpu-num=0来执行此操作。cpu-num部分说明要为PC设置哪个CPU。(如果需要,可以使用更复杂的语法将PC设置为图像加载地址以外的其他地址。)
注1:以上是原始图像文件。如果你有一个ELF文件,那么通用加载器将把文件加载到ELF文件指定的地址,你不需要指定addr=。如果您使用cpu-num=,它将使用初始PC的ELF入口点。
注2:对于32位CPU来说,4GB的RAM相当多。Cortex-A15具有LPAE,所以并不是说不可能访问超过4GB物理地址标记的RAM部分,但这似乎很奇怪。3GB(即从0x4000_0000到0xFFFF_FFFF的RAM)可能同样有用,并且可以保存VM使用的主机资源。

f4t66c6m

f4t66c6m2#

当您使用-kernel选项时,qemu将执行以下操作:
1.在地址(0x40010000)加载内核映像
1.将PC设置为启动DRAM基座(0x40000000

  • 开始执行指令(这些指令由QEMU设置):
  • 将DTB地址加载到X0寄存器
  • 跳转到内核映像的起始位置(0x40010000

现在,如果你想传输你的内核映像并开始执行而不执行上面的操作,那么将使用下面的命令:
要在特定位置传输内核,请执行以下操作:-device guest-loader,addr=<addr, where you want to copy img>,kernel=<kernel_img_path>
要在内核启动时加载PC,请执行以下操作:-device loader,addr=<addr, where you copied your img>,cpu-num=0

相关问题