Compiling our first hello world program

First clone this repo and install the cross toolchain for riscv64. This depends on your distribution. We assume a debian based operating system, but feel free to use any distro you want.

sudo apt install build-essential gcc-riscv64-linux-gnu qemu-user

Clone and navigate to the labs/01-hello-riscv directory:

git clone https://github.com/riscv-technologies-lab/riscv-toolchain-labs.git cross-labs
cd cross-labs/labs/01-hello-riscv

Let's compile a simple hello world program natively. Take a look at the Makefile that we've prepared.

{{#include ../../labs/01-hello-riscv/hello.c}}
make run # compile the program natively
# gcc hello.c -o build/hello.elf
# build/hello.elf
# Hello, RISC-V!

Let's take a look at the generated executable with file command:

make show # run: file build/hello.elf
# gcc hello.c -o build/hello.elf
# file build/hello.elf
# build/hello.elf: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=52deb0fc601275b33ab8a638447f4bf2dcc1bb4a, for GNU/Linux 3.2.0, not stripped

We can dig deeper with ldd command.

ldd build/hello.elf
# linux-vdso.so.1 (0x00007fff042e9000)
# libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f058ff59000)
# /lib64/ld-linux-x86-64.so.2 (0x00007f0590169000)

What is vDSO? Now run readelf utility on the compiled binary and take explore the output by yourself. What happens if you compile with CCFLAGS=-static and run readelf again? Why is the output bigger?

Running under qemu usermode emulation

Run hello.elf with native usermode qemu. There's a make target to do that:

make run-qemu

Compile and run for riscv64 arch

Repeat the previous steps but with riscv64 toolchain. You can set make variables from command line, if they are defined with ?=. Take a look here. Set the compiler to riscv64-linux-gnu-gcc and qemu executable to qemu-riscv64. On ubuntu-23.04 make run-qemu fails with Could not open '/lib/ld-linux-riscv64-lp64d.so.1'. In case you encounter such an error run you can either compile with -static flag or create symlink riscv64-linux-gnu-ld with ln -s to the correct location. See the issue.