You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

QEMU未跳转至指定地址0xC0008000加载镜像的问题求助

QEMU中无法让PC跳转到指定Bootloader地址0xC0008000的原因及解决办法

我的链接脚本设置如下:

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 = .;
}

我指定0xC0008000作为bootloader的加载地址,希望QEMU能按这个地址加载镜像并执行,但尝试两种命令后都没达到预期:

第一种命令

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

执行后PC从0x40000000启动,随后跳转到0x40010000处的bootloader——这符合Virt平台RAM起始地址为0x40000000的特性,但不符合我让代码在0xC0008000执行的预期。

第二种命令

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

此时镜像成功加载到0xC0008000,但0x40010000处出现重复指令,且PC始终无法跳转到0xC0008000,调试陷入困境。


问题原因

  1. 重复加载的根源:-kernel参数是QEMU为ARM Virt平台预设的内核加载逻辑,它会自动把镜像加载到默认地址0x40010000,同时通知平台启动固件跳转到该地址执行。而你额外添加的-device loader参数又把镜像加载到了0xC0008000,导致同一镜像被加载到两个不同地址,这就是0x40010000出现重复指令的原因。

  2. PC不跳转的核心原因:Virt平台的启动流程由内置ROM固件控制,当你使用-kernel参数时,QEMU会向固件传递“内核入口在0x40010000”的信息,固件启动后会严格按照这个地址跳转,完全忽略你通过-device loader加载到0xC0008000的镜像。

解决办法

要实现PC跳转到0xC0008000执行,需要彻底抛弃-kernel参数的默认逻辑,改用-device loader完全控制镜像加载和入口地址:

qemu-system-arm \
    -machine virt \
    -cpu cortex-a15 \
    -nographic \
    -S -s \
    -m 4096M \
    -device loader,file=Image,addr=0xC0008000 \
    -device loader,addr=0xC0008000,cpu-num=0
  • 第一个loader设备负责把镜像加载到0xC0008000地址;
  • 第二个loader设备直接设置CPU 0的初始PC为0xC0008000,绕过ROM固件的默认跳转逻辑,启动后直接执行该地址的代码。

另外需要确认:你的链接脚本中boot/start.o的入口指令确实位于0xC0008000,没有因段对齐或其他原因产生偏移。


内容的提问来源于stack exchange,提问作者Haoson Q

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 06:45:00