

#From scratch manual
│įor bug reporting instructions, please see: │įind the GDB manual and other documentation resources online at: │ Type "show configuration" for configuration details. # While we can start GDB without any arguments, specifying 'a.out' tells GDB # to load debug symbols from that file for the newly created session.Īnd we should now find ourselves inside GDB! This GDB was configured as "-host=x86_64-apple-darwin17.7.0 -target=riscv64-unknown-elf". Now that our program is running inside QEMU with a GDB server on host localhost and port 1234, let’s connect to it with our RISC-V GDB client from a separate terminal: # -tui gives us a (t)extual (ui) for our GDB session. We’ve chosen the virt RISC-V machine, which is one riscv-qemu comes with out of the box. Qemu-system-riscv64 -machine virt -m 128M -gdb tcp::1234 -kernel a.out # -kernel tells QEMU what we're looking to run, even if our executable isn't # exactly a "kernel". # -gdb tcp::1234 tells QEMU to also start a GDB server on localhost:1234 where # TCP is the means of communication. # -m is the amount of memory to allocate to our virtual machine. Run qemu-system-riscv64 -machine help to list # all available machines. We can now run this brand new executable inside qemu: # -machine tells QEMU which among our list of available machines we want to # run our executable against. This produces a file called a.out, which is the default name gcc gives executables when we don’t tell it what we want them to be called. # -g to tell GCC to preserve debug info in our executable. Without this, GCC might optimize # away our infinite addition since the result 'c' is never used. We want to run this program, and the first step on that path is compiling it into something executable by our RISC-V CPU. file: riscv-from-scratch/work/add.c int main () Let’s start our journey by using the text editor of your choice to create a simple C program called add.c that infinitely adds two numbers together. # cd riscv-from-scratch/workĪs the name suggests, the work directory will serve as our working directory for this and future posts.

git clone or `git clone ` to clone # via HTTPS rather than SSH # alternatively, if you are a GitHub user, you can fork this repo.
#From scratch code
Next, let’s set up a workspace for the code we will write today (and in future posts).
#From scratch series
If you missed the previous post in this series and don’t have riscv-qemu and the RISC-V toolchain installed and were hoping to follow along, jump to the “QEMU and RISC-V toolchain setup” section (or in RISC-V assembly, jal x0, qemu_and_toolchain_setup) and complete that before moving on. We’ll then examine and modify a linker script, write our own C runtime to get our program set up and running, and finally invoke GDB and step through our program. We’ll write and attempt to debug a simple C program of our own, unveil the magic hidden behind main, and examine the hardware layout of a qemu virtual machine. In this post, we’ll break free from the freedom-e-sdk. This is great if you’re looking to quickly become productive, but these details are exactly the sort of thing we want to learn about! We didn’t have to worry about setting up any linker scripts or writing a runtime that sets up our stack, calls into main, and more.

The freedom-e-sdk made it trivial for us to compile, debug, and run any C program on an emulated or physical RISC-V processor.
#From scratch full
In the first post of this series, we introduced RISC-V, explained why it’s important, set up the full GNU RISC-V toolchain, and built and ran a simple program on an emulated version of a RISC-V processor with the help of SiFive’s freedom-e-sdk. Welcome to the second post in the RISC-V from scratch series! As a quick recap, throughout RISC-V from scratch we will explore various low-level concepts (compilation and linking, primitive runtimes, assembly, and more), typically through the lens of RISC-V and its ecosystem.
