Skip to content

RISC V binutils

Oleg Ladin edited this page Feb 8, 2020 · 8 revisions

How to get binutils source files

RISC-V binutils must be build manually, so first you'll need to get sources.

The source files are stored in GitHub repository in the RISC-V's riscv-gnu-toolchain project. Use git to get a local clone of the repository (--recursive option is required to get all submodules):

git clone --recursive https://github.com/riscv/riscv-gnu-toolchain

In case if submodules were not initialized automatically (their folders contain only .git file), set them manually from the project root:

cd riscv-gnu-toolchain
git submodule foreach 'git reset --hard'

You can face problem with cloning "qemu" submodule. It is not required for the most of our usage cases, thus this can be ignored.


How to build binutils

This cheat-sheet is based on GitHub README. See it if you have any problem or need more information.

# Install prerequisites
sudo apt-get install autoconf automake autotools-dev curl libmpc-dev libmpfr-dev libgmp-dev gawk build-essential \
    bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev

# For convenience, you can proceed the build from project root
cd riscv-gnu-toolchain

# Create a directory where the binutils will be installed (can be any)
mkdir bin

# Create a directory for a build process (can be any), enter it
mkdir build && cd build

# Configure build (configures for RV64GC by default) using script from the project root.
# Set absolute path of destination binutils directory ("bin") for "prefix" flag
../configure --prefix=/riscv-gnu-toolchain/bin

# Make sources (can dump a lot of info). Paralleling can be archieved by specifying "-j NUMBER_OF_WORKERS" flag.
# Note: environment variables $CXX ($CC) should point to compiler supporting at least C++11 by default.
make

# Install (can dump a lot of info, usually requires sudo)
sudo make install

# Update $PATH variable to have binaries available
export PATH=$PATH:/riscv-gnu-toolchain/bin/bin
setenv PATH $PATH:/riscv-gnu-toolchain/bin/bin

Create a RISC-V binary with binutils

  • Create a file with assembler code and save it as <test_name>.s.
    The simplest example of the program (a single NOP):
.section .text
.globl _start
_start:
    addi x0, x0, 0

For further steps, you can look into RISC-V Assembly Programmer's Manual.

  • Generate an object file:
riscv64-unknown-elf-as <test_name>.s -o <test_name>.o
  • Convert the object file into the binary file:
riscv64-unknown-elf-ld <test_name>.o -o <test_name>.out
  • (Optional) Look the content of <test_name>.out using (pay attention only to .text section):
riscv64-unknown-elf-objdump -D <test_name>.out

Note that in addition to assembler this RISC-V GNU toolchain also includes C and C++ cross-compiler, so you can also build C/C++ code into a RISC-V binary on regular x86 machines.


Example of program

.section .rodata # Read-only data
##############################################################################
# This section includes read-only memory data. Big constants could be added
# here. Below is a Word (32b) with "0xdeadbeef" value, addressed as
# "example_data":
##############################################################################
example_data:
    .word 0xDEADBEEF


.section .text # Instructions
.globl _start

##############################################################################
# Parameters (something like C/C++ "#define") but for small immediate values
# only:
##############################################################################
.equ PARAMETER, 2

_start:
##############################################################################
# Main code section.
##############################################################################
    lw t0, example_data # t0 = mem[example_data]  (t0 = 0xdeadbeef)
    addi t1, zero, PARAMETER # t1 = zero + PARAMETER  (t1 = 0 + 2 = 2)
loop:
    addi t1, t1, t0
    j loop
Clone this wiki locally