d0iasm/rvemu

Bare-metal C Program compilation fails

apivovarov opened this issue · 3 comments

I'm trying to follow the instructions described in Bare-metal C Program in README

I got the following errors (OS: Ubuntu 20.10 x86_64)

root@292c6ad9bfc1:~/workplace/riscv# riscv64-unknown-elf-gcc -S -nostdlib foo.c
root@292c6ad9bfc1:~/workplace/riscv# riscv64-unknown-elf-gcc -Wl,-Ttext=0x80000000 -nostdlib -o foo foo.s
/opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0/../../../../riscv64-unknown-elf/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000080000000
/tmp/ccfhLgt3.o: in function `main':
foo.c:(.text+0x8): relocation truncated to fit: R_RISCV_HI20 against `.LC0'
collect2: error: ld returned 1 exit status

foo.c

#include <stdio.h>

int main() {
  puts("Hello World!");
  return 0;
}

foo.s

	.file	"foo.c"
	.option nopic
	.attribute arch, "rv64i2p0_m2p0_a2p0_f2p0_d2p0_c2p0"
	.attribute unaligned_access, 0
	.attribute stack_align, 16
	.text
	.section	.rodata
	.align	3
.LC0:
	.string	"Hello World!"
	.text
	.align	1
	.globl	main
	.type	main, @function
main:
	addi	sp,sp,-16
	sd	ra,8(sp)
	sd	s0,0(sp)
	addi	s0,sp,16
	lui	a5,%hi(.LC0)
	addi	a0,a5,%lo(.LC0)
	call	puts
	li	a5,0
	mv	a0,a5
	ld	ra,8(sp)
	ld	s0,0(sp)
	addi	sp,sp,16
	jr	ra
	.size	main, .-main
	.ident	"GCC: (GNU) 10.2.0"

Thank you for trying to use this emulator!

You can't use #include <stdio.h> in foo.c because we use -nostdlib flag at riscv64-unknown-elf-gcc, which means we can't depend on the standard library.

bin/raw/simple.c is one of the simplest sample C code. We can compile it with the instructions described in Bare-metal C Program in README. Once simple.c is executed in this emulator, we'll see the value of 42 at x10 (a0) register. The x10 register stores a return value of the main function.

I was able to generate simple.text myself, but the content and size of my file is different from the official simple.text

I did the following to generate simple.text (BTW, I got ld warning)

$ riscv64-unknown-elf-gcc -S -nostdlib simple.c 
$ riscv64-unknown-elf-gcc -Wl,-Ttext=0x80000000 -nostdlib -o simple simple.s
/opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0/../../../../riscv64-unknown-elf/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000080000000
$ riscv64-unknown-elf-objcopy -O binary simple simple.text

The content of my simple.text is hexdump -C simple.text

00000000  41 11 22 e4 00 08 93 07  a0 02 3e 85 22 64 41 01  |A.".......>."dA.|
00000010  82 80                                             |..|
00000012

Official simple.text has different content and size

00000000  13 01 01 ff 23 34 81 00  13 04 01 01 93 07 a0 02  |....#4..........|
00000010  13 85 07 00 03 34 81 00  13 01 01 01 67 80 00 00  |.....4......g...|
00000020

As a result if I run my simple.text in rvemu.app it does not set x10= 0x2a

What I'm doing wrong?

My OS is Ubuntu 20.10.

riscv64-unknown-elf-gcc (GCC) 10.2.0

my simple.c is the same as the official simple.c

int main() {
    return 42;
}

my simple.s is almost the same as the official simple.s

	.file	"simple.c"
	.option nopic
	.attribute arch, "rv64i2p0_m2p0_a2p0_f2p0_d2p0_c2p0"
	.attribute unaligned_access, 0
	.attribute stack_align, 16
	.text
	.align	1
	.globl	main
	.type	main, @function
main:
	addi	sp,sp,-16
	sd	s0,8(sp)
	addi	s0,sp,16
	li	a5,42
	mv	a0,a5
	ld	s0,8(sp)
	addi	sp,sp,16
	jr	ra
	.size	main, .-main
	.ident	"GCC: (GNU) 10.2.0"

Sorry for my late response. I've been busy these days.

I think your compiler is using compressed instructions (RV64C). Each length of compressed instructions is 2 bytes and the original simple.text binary is composed of non-compressed instructions, each length of them is 4 bytes. That's why the length of your binary differs.

The app rvemu.app didn't support compressed instructions so that you coludn't see the result x10= 0x2a. It, however, is updated to support compressed instructions now. I think you can see x10= 0x2a with your binary.

FYI: If you want to compile code into RV64G (without compressed) instructions, you need to compile RISC-V toolchain with --with-arch=rv64g option.

$ git clone --recursive git@github.com:riscv/riscv-gnu-toolchain.git
$ cd riscv-gnu-toolchain
$ ./configure --prefix=/opt/riscv --with-arch=rv64g
$ make
$ make linux