基于QEMU通过GDB调试树莓派3的技术问题咨询
Troubleshooting Raspberry Pi 3 Bare-Metal Debugging with gdb-multiarch: Code Not Loading to Memory
Hey there, let’s tackle this frustrating bare-metal debugging issue you’re hitting with Raspberry Pi 3 and gdb-multiarch. I’ve seen this exact problem pop up when folks mix up Pi 3’s bootloader behavior with older Pi models, so let’s break it down step by step.
First, Understand Pi 3’s Boot Process (The Root of the Issue)
- Raspberry Pi 3 uses the GPU to handle initial boot: it runs
bootcode.bin, thenstart.elf, which is responsible for loading your bare-metal program into memory. - Critical note: Unlike older Pi models (which used 0x10000), Pi 3’s
start.elfloadskernel.img(your bare-metal binary) to 0x8000 by default. - The 0x0 address you’re seeing initially is the GPU’s ROM, not your program’s memory. The CPU starts here because it’s in reset, but the GPU will eventually jump to your program’s entry point at 0x8000. That random jump to 0x10000? It’s likely leftover behavior from outdated config or link scripts targeting older Pis.
Fix 1: Correct Your Link Script
Your link script is pointing to the wrong memory addresses. Here’s a minimal working example tailored for Pi 3:
ENTRY(_start) # Make sure this matches your assembly entry point label SECTIONS { . = 0x8000; # Align all sections to Pi 3's default load address .text : { *(.text) } # Code section .data : { *(.data) } # Initialized data .bss : { *(.bss) } # Uninitialized data (zeroed at boot) }
- Compile with this script using
-T link.ldto ensure your program is linked to the correct memory space. - Always generate a
kernel.imgbinary (usingobjcopy)—this is the only filename the Pi’s bootloader will look for by default.
Fix 2: Proper GDB-Multiarch Setup
For QEMU Simulation (Easier Debugging)
- Start QEMU with Pi 3 emulation, waiting for GDB to connect:
qemu-system-aarch64 -machine raspi3 -kernel kernel.img -s -S - In a separate terminal, launch gdb-multiarch and connect correctly:
gdb-multiarch kernel.elf # Load your ELF symbols first (gdb) target remote localhost:1234 # Connect to QEMU's debug port (gdb) b *0x8000 # Set breakpoint at your program's entry point (not 0x0!) (gdb) c # Continue execution—this will stop at your _start function
- Why not break at 0x0? That’s GPU ROM code, not your program. You’ll just follow the GPU’s boot sequence instead of your code.
For Hardware Debugging (JTAG/ST-Link)
- Ensure your debug probe is correctly mapping Pi 3’s memory space.
- After connecting to the target, load your ELF symbols with
file kernel.elf, then set a breakpoint at0x8000before resuming execution. - If you’re still seeing a jump to 0x10000, check your SD card’s
config.txtfor an outdatedkernel_address=0x10000line—remove it or set it to0x8000.
Verify Your Program Is Loaded
To confirm your code is in memory, use GDB’s memory inspection command:
(gdb) x/16x 0x8000 # Dump 16 bytes at the load address
- If you see your program’s machine code (match it to your assembly
_startfunction), it’s loaded correctly. If you see all zeros or garbage, double-check:- Is
kernel.imgin the SD card’s FAT32 boot partition? - Did you compile with the correct link script?
- Is your
config.txtoverriding the default load address?
- Is
If You Really Need 0x10000
If you have a specific reason to use 0x10000 instead of 0x8000:
- Update your link script to set
. = 0x10000; - Add
kernel_address=0x10000to your SD card’sconfig.txt - Set your GDB breakpoint at
0x10000instead of0x8000
内容的提问来源于stack exchange,提问作者Flayneorange
相关产品推荐
相关产品推荐

