Setting Up the Toolchain and QEMU
1. TL;DR
- Use
riscv64-unknown-elf-gccfor all builds. - Run programs with
qemu-system-riscv32in system-mode. - No libc is used; all output goes through the QEMU
virtUART.
2. Before we start
All the source files are available in GitHub RISC-V Experiments Repository.
3. Required tools
We need the RISC-V GCC cross-compiler, QEMU, GDB, and some standard build tools. On Ubuntu 24.04 (or similar Debian-based systems), install them with:
| |
gcc-riscv64-unknown-elf: The cross-compiler for bare-metal software.qemu-system-riscv32: Emulates a 32-bit RISC-V computer.gdb-multiarch: Debugger that can talk to different architectures (like our RISC-V target).binutils-riscv64-unknown-elf: Providesreadelf,objdump,objcopy, etc.
3.1. Install Pwndbg
Pwndbg is a powerful GDB plug-in that provides a better interface for reverse engineering and debugging. It will be useful for inspecting registers and memory in later chapters.
| |
4. Project layout
| |
| |
5. Minimal UART “hello”
File: src/hello_uart.c
| |
Build and run:
| |
You should see the greeting printed in your terminal.
6. Running with GDB
Start QEMU in halted mode:
| |
Connect from another terminal:
| |
7. Exercises
- Confirm you can run
qemu-system-riscv32 --versionon your system. - Confirm you can run
riscv64-unknown-elf-gcc --versionon your system. - Verify you can use make by running
make --versionon your system. - Verify you can run gdb-multiarch by running
gdb-multiarch --versionon your system. - Change the string and verify it prints correctly.
- Add a second
uart_putsline and step through it in GDB.
8. Summary
- The
riscv64-unknown-elf-gcctoolchain builds freestanding RV32 code. - QEMU
virtruns the ELF directly with-kerneland no BIOS. - UART output provides immediate feedback without libc.