Issue compiling RISC-V_RV32_QEMU_VIRT_GCC for 64 bit architecture

Hi guys,
I’m new to RISC-V and FreeRTOS, I am trying to follow the tutorial for creating a generic RISC-V project for FreeRTOS: RISC-V_RV32_QEMU_VIRT_GCC (as a new user I can’t post links :smiling_face_with_tear:)

I correctly compiled the 32-bit version but, unfortunately, could not compile the 64-bit version.
I have attached the error that I obtained below:

luca@Lenovo-V15-G3-ABA:~/FreeRTOS/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC$ make -C build/gcc/ RVA23=1
make: entering directory «/home/luca/FreeRTOS/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc»
Using RVA23 build


--- Final linking ---

riscv64-unknown-elf-gcc ./output/tasks.o ./output/list.o ./output/queue.o ./output/timers.o ./output/event_groups.o ./output/stream_buffer.o ./output/heap_4.o ./output/port.o ./output/AbortDelay.o ./output/BlockQ.o ./output/blocktim.o ./output/countsem.o ./output/death.o ./output/dynamic.o ./output/EventGroupsDemo.o ./output/GenQTest.o ./output/integer.o ./output/IntSemTest.o ./output/MessageBufferAMP.o ./output/MessageBufferDemo.o ./output/PollQ.o ./output/QPeek.o ./output/QueueOverwrite.o ./output/QueueSet.o ./output/QueueSetPolling.o ./output/recmutex.o ./output/semtest.o ./output/StaticAllocation.o ./output/StreamBufferDemo.o ./output/StreamBufferInterrupt.o ./output/TaskNotify.o ./output/TaskNotifyArray.o ./output/TimerDemo.o ./output/main.o ./output/main_blinky.o ./output/main_full.o ./output/ns16550.o ./output/riscv-virt.o ./output/printf-stdarg.o ./output/portASM.o ./output/start.o ./output/RegTest.o ./output/vector.o -nostartfiles -Xlinker --gc-sections -Wl,-Map,./output/RTOSDemo.map -T./fake_rom.ld -march=rv64imafdc_zicsr_zicntr_zihpm_ziccif_ziccrse_ziccamoa_zicclsm_za64rs_zihintpause_zic64b_zicbom_zicbop_zicboz_zfhmin_zkt_zihintntl_zawrs -mabi=lp64d -mcmodel=medany -Xlinker --defsym=__stack_size=350 -Wl,--start-group -Wl,--end-group -Wl,--wrap=malloc -Wl,--wrap=free -Wl,--wrap=open -Wl,--wrap=lseek -Wl,--wrap=read -Wl,--wrap=write -Wl,--wrap=fstat -Wl,--wrap=stat -Wl,--wrap=close -Wl,--wrap=link -Wl,--wrap=unlink -Wl,--wrap=execve -Wl,--wrap=fork -Wl,--wrap=getpid -Wl,--wrap=kill -Wl,--wrap=wait -Wl,--wrap=isatty -Wl,--wrap=times -Wl,--wrap=sbrk -Wl,--wrap=puts -Wl,--wrap=_malloc -Wl,--wrap=_free -Wl,--wrap=_open -Wl,--wrap=_lseek -Wl,--wrap=_read -Wl,--wrap=_write -Wl,--wrap=_fstat -Wl,--wrap=_stat -Wl,--wrap=_close -Wl,--wrap=_link -Wl,--wrap=_unlink -Wl,--wrap=_execve -Wl,--wrap=_fork -Wl,--wrap=_getpid -Wl,--wrap=_kill -Wl,--wrap=_wait -Wl,--wrap=_isatty -Wl,--wrap=_times -Wl,--wrap=_sbrk -Wl,--wrap=__exit -Wl,--wrap=_puts -o ./output/RTOSDemo.elf
/home/luca/riscv-tools/lib/gcc/riscv64-unknown-elf/14.2.0/rv64imafdc/lp64d/libgcc.a(_clzsi2.o): in function `__clzdi2':
/home/luca/riscv-gnu-toolchain/build-gcc-newlib-stage2/riscv64-unknown-elf/rv64imafdc/lp64d/libgcc/../../../../.././gcc/libgcc/libgcc2.c:690:(.text+0x18): relocation truncated to fit: R_RISCV_HI20 against symbol `__clz_tab' defined in .rodata section in /home/luca/riscv-tools/lib/gcc/riscv64-unknown-elf/14.2.0/rv64imafdc/lp64d/libgcc.a(_clz.o)
collect2: error: ld returned 1 exit status
make: *** [Makefile:164: output/RTOSDemo.elf] Errore 1
make: exiting directory «/home/luca/FreeRTOS/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc»

I followed the content of the readme file in that folder. Do you think there is a bug with this project? I saw that the 64-bit version was released one week ago…

I am using the self-built RISC-V toolchain downloaded from GitHub (again, I can’t put the link).
These are the details of my toolchain:

luca@Lenovo-V15-G3-ABA:~/riscv-tools$ riscv64-unknown-elf-gcc --version
riscv64-unknown-elf-gcc (g04696df096) 14.2.0
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

luca@Lenovo-V15-G3-ABA:~/riscv-tools$ riscv64-unknown-elf-gcc -v
Using built-in specs.
COLLECT_GCC=riscv64-unknown-elf-gcc
COLLECT_LTO_WRAPPER=/home/luca/riscv-tools/libexec/gcc/riscv64-unknown-elf/14.2.0/lto-wrapper
Target: riscv64-unknown-elf
Configured with: /home/luca/riscv-gnu-toolchain/gcc/configure --target=riscv64-unknown-elf --prefix=/home/luca/riscv-tools --disable-shared --disable-threads --enable-languages=c,c++ --with-pkgversion=g04696df096 --with-system-zlib --enable-tls --with-newlib --with-sysroot=/home/luca/riscv-tools/riscv64-unknown-elf --with-native-system-header-dir=/include --disable-libmudflap --disable-libssp --disable-libquadmath --disable-libgomp --disable-nls --disable-tm-clone-registry --src=.././gcc --enable-multilib --with-abi=lp64d --with-arch=rv64gc --with-tune=rocket --with-isa-spec=20191213 'CFLAGS_FOR_TARGET=-Os    -mcmodel=medlow' 'CXXFLAGS_FOR_TARGET=-Os    -mcmodel=medlow'
Thread model: single
Supported LTO compression algorithms: zlib zstd
gcc version 14.2.0 (g04696df096) 

Thank you very much for your support!

Regards,
Luca

P.S.: sorry if the category could be wrong… I didn’t find a RISC-V category

I think you did not configure the toolchain with --enable-multilib option. Please use the following commands to build toolchain:

git clone https://github.com/riscv-collab/riscv-gnu-toolchain.git
cd riscv-gnu-toolchain
./configure --prefix=/home/ubuntu/software/riscv --enable-multilib --with-cmodel=medany --enable-qemu-system
make -j8

Build Qemu:

 make build-sim SIM=qemu -j8

Hi Gaurav,
Thank you for your super-fast response!

Checking my bash history, I saw that I built the toolchain with the following command:

  ./configure --prefix=$HOME/riscv-tools --enable-multilib
  make -j$(($(nproc) - 2))

Do you think it is ok?
Please, consider that I would like to execute my code not only on qemu but also on gem5.

I don’t know if that can be helpful or not… However, those are all the possible tools that I have in my riscv-tools folder

luca@Lenovo-V15-G3-ABA:~/riscv-tools$ ls
bin  etc  include  lib  libexec  riscv64-unknown-elf  riscv64-unknown-linux-gnu  share  sysroot
luca@Lenovo-V15-G3-ABA:~/riscv-tools$ riscv64-unknown-
riscv64-unknown-elf-addr2line              riscv64-unknown-elf-objcopy
riscv64-unknown-linux-gnu-gcov-tool        riscv64-unknown-elf-ar
riscv64-unknown-elf-objdump                riscv64-unknown-linux-gnu-gdb
riscv64-unknown-elf-as                     riscv64-unknown-elf-ranlib
riscv64-unknown-linux-gnu-gdb-add-index    riscv64-unknown-elf-c++
riscv64-unknown-elf-readelf                riscv64-unknown-linux-gnu-gfortran
riscv64-unknown-elf-c++filt                riscv64-unknown-elf-run
riscv64-unknown-linux-gnu-gp-archive       riscv64-unknown-elf-cpp
riscv64-unknown-elf-size                   riscv64-unknown-linux-gnu-gp-collect-app
riscv64-unknown-elf-elfedit                riscv64-unknown-elf-strings
riscv64-unknown-linux-gnu-gp-display-html  riscv64-unknown-elf-g++
riscv64-unknown-elf-strip                  riscv64-unknown-linux-gnu-gp-display-src
riscv64-unknown-elf-gcc                    riscv64-unknown-linux-gnu-addr2line
riscv64-unknown-linux-gnu-gp-display-text  riscv64-unknown-elf-gcc-14.2.0
riscv64-unknown-linux-gnu-ar               riscv64-unknown-linux-gnu-gprof
riscv64-unknown-elf-gcc-ar                 riscv64-unknown-linux-gnu-as
riscv64-unknown-linux-gnu-gprofng          riscv64-unknown-elf-gcc-nm
riscv64-unknown-linux-gnu-c++              riscv64-unknown-linux-gnu-ld
riscv64-unknown-elf-gcc-ranlib             riscv64-unknown-linux-gnu-c++filt
riscv64-unknown-linux-gnu-ld.bfd           riscv64-unknown-elf-gcov
riscv64-unknown-linux-gnu-cpp              riscv64-unknown-linux-gnu-lto-dump
riscv64-unknown-elf-gcov-dump              riscv64-unknown-linux-gnu-elfedit
riscv64-unknown-linux-gnu-nm               riscv64-unknown-elf-gcov-tool
riscv64-unknown-linux-gnu-g++              riscv64-unknown-linux-gnu-objcopy
riscv64-unknown-elf-gdb                    riscv64-unknown-linux-gnu-gcc
riscv64-unknown-linux-gnu-objdump          riscv64-unknown-elf-gdb-add-index
riscv64-unknown-linux-gnu-gcc-14.2.0       riscv64-unknown-linux-gnu-ranlib
riscv64-unknown-elf-gprof                  riscv64-unknown-linux-gnu-gcc-ar
riscv64-unknown-linux-gnu-readelf          riscv64-unknown-elf-ld
riscv64-unknown-linux-gnu-gcc-nm           riscv64-unknown-linux-gnu-run
riscv64-unknown-elf-ld.bfd                 riscv64-unknown-linux-gnu-gcc-ranlib
riscv64-unknown-linux-gnu-size             riscv64-unknown-elf-lto-dump
riscv64-unknown-linux-gnu-gcov             riscv64-unknown-linux-gnu-strings
riscv64-unknown-elf-nm                     riscv64-unknown-linux-gnu-gcov-dump
riscv64-unknown-linux-gnu-strip

Thank you very much for your support!

It might be the --with-cmodel=medany then. I remember seeing this error and therefore, I am reasonably sure that it should go away if you use the commands I shared. Please do a clean build of the toolchain and let me know whatever you observe.

1 Like

It is indeed the code model. Configuring the toolchain to use the medany core model should solve the issue.

1 Like

Ok, thank you very much to both of you!

I am re-building the toolchain configuring it in this way:

./configure --prefix=$HOME/riscv-tools --enable-multilib --with-cmodel=medany --enable-qemu-system

It’s taking a long time, I’ll update you ASAP…

So, just to be sure that I grasped your idea, by default the Toolchain doesn’t support the medany model, and providing that flag will enable also the support for that model?

In that case, another solution could be simply to change the memory model. Am I wrong?

Thank you very much to both of you!

Re-building Steps

I’ll write all the steps to keep track also for future users. I went back to the risc-v-gnu-toolchain toolchain folder, I cleaned its content, and re-built the toolchain as you suggested:

 $ cd ~/riscv-gnu-toolchain
 $ ./configure --prefix=$HOME/riscv-tools --enable-multilib --with-cmodel=medany --enable-qemu-system
 $ make -j8

Then, I also executed the command you suggested for QEMU (even if, I already had a QEMU installation):

 $ make build-sim SIM=qemu -j8

The operation took some time (around 35 minutes with my CPU AMD Ryzen 5 5625U with Radeon Graphics × 6).

Then, I went back to the project folder and I tried to compile again the project:

 $ make -C build/gcc/ clean
 $ make -C build/gcc/ RVA23=1

This time finally the compiling process succeeded!

--- Final linking ---
### Whole command removed, keeping only final output for brevity!
riscv64-unknown-elf-size ./output/RTOSDemo.elf
   text    data     bss     dec     hex filename
  67960     168  244670  312798   4c5de ./output/RTOSDemo.elf

To execute the generated .elf file, as @aggarg correctly said in the following reply I entered the following command and the project finally started working!

$ qemu-system-riscv64 -nographic -machine virt -net none -chardev stdio,id=con,mux=on \
    -serial chardev:con -mon chardev=con,mode=readline -bios none -smp 4 \
    -s --kernel build/gcc/output/RTOSDemo.elf

I would like to thank you again for your support!
It was really invaluable!

You need to use these commands as described in the README. For RV32:

$ qemu-system-riscv32 -nographic -machine virt -net none -chardev stdio,id=con,mux=on \
    -serial chardev:con -mon chardev=con,mode=readline -bios none -smp 4 \
    -s --kernel build/gcc/output/RTOSDemo.elf

For RVA23:

$ qemu-system-riscv64 -nographic -machine virt -net none -chardev stdio,id=con,mux=on \
    -serial chardev:con -mon chardev=con,mode=readline -bios none -smp 4 \
    -s --kernel build/gcc/output/RTOSDemo.elf

Oh… You’re right!
I made so many attempts that I forgot that they specified a precise command to execute the project in this tutorial… Thank you!

I used the command you mentioned and it worked!
Both versions! 32 and 64 bits!

Thank you very much for your support! I was lost without you!
I also edit my previous answer to don’t create confusion for other potential future readers!

Glad that it worked!

1 Like