riscv-software-src / riscv-tools

RISC-V Tools (ISA Simulator and Tests)
1.13k stars 446 forks source link

RV32I -> undefined reference to `__umoddi3', `__udivdi3', `__umoddi3' #226

Closed pentin-as closed 5 years ago

pentin-as commented 5 years ago

I'm using the toolchain with RV32I. I compile benchmarks (which support the corresponding extension).

I have an error: Debug/common/syscalls.c.o: In function '.L46': syscalls.c:(.text+0x224): undefined reference to 'umoddi3' Debug/common/syscalls.c.o: In function '.L57': syscalls.c:(.text+0x242): undefined reference to 'udivdi3' syscalls.c:(.text+0x252): undefined reference to '__umoddi3'

This is the assembly file to which the syscall.c file is being compiled: syscalls.c.s.txt

If I comment goto on signed_number (line 305) and unsigned_number (lines 310 and 316), everything works. https://github.com/riscv/riscv-tests/blob/294bfce8a1ca2fc501b8939292146e44f813a2b8/benchmarks/common/syscalls.c#L305 https://github.com/riscv/riscv-tests/blob/294bfce8a1ca2fc501b8939292146e44f813a2b8/benchmarks/common/syscalls.c#L310 https://github.com/riscv/riscv-tests/blob/294bfce8a1ca2fc501b8939292146e44f813a2b8/benchmarks/common/syscalls.c#L316

I understand that in order for __umoddi3 (and so on) to appear in the project, I must link newlib, which in the benchmarks does not link. But I do not understand why the goto may need division and the remainder of the division. I think this is a mistake.

I'm attaching my test case (without toolchain). test_rv32i.zip

jim-wilson commented 5 years ago

The function printnum has while (1) { digs[pos++] = num % base; if (num < base) break; num /= base; } This is the typical way to convert a number into a string, by using divide and modulus operations.

If you comment out the gotos, then gcc can optimize away some dead code, which is the code that calls printnum.

umoddi3 and udivdi3 come from libgcc, which is a library that contains helper functions for gcc. You should always link with libgcc.

pentin-as commented 5 years ago

Thank you very much for the clarification.

Can I ask another question? Does not work: riscv32-unknown-elf-g++ -static -nostdlib -nostartfiles -lm -lgcc -T common/test.ld Debug/common/crt.S.o Debug/src/main.c.o Debug/common/syscalls.c.o -o Debug/test Working: riscv32-unknown-elf-g++ -static -nostartfiles -lm -lgcc -T common/test.ld Debug/common/crt.S.o Debug/src/main.c.o Debug/common/syscalls.c.o -o Debug/test Working: riscv32-unknown-elf-g++ -static -nostartfiles -lm -T common/test.ld Debug/common/crt.S.o Debug/src/main.c.o Debug/common/syscalls.c.o -o Debug/test

I understand correctly that the -nostdlib switch disables the libgcc library as well?

aswaterman commented 5 years ago

Does it work if you move -lm -lgcc to the end of the command line (after the list of source/object files)?

jim-wilson commented 5 years ago

Unix style static libraries are used only if there are undefined symbol references that can be satisfied by the library. If you put the library first on the command line, there will be no undefined symbols (because there are no symbols in the output yet), and hence nothing will be brought in from the library. If you put the library last on the command line, there will undefined symbols, and functions will be brought in from the library to satisfy them.

pentin-as commented 5 years ago

Working: toolchain/bin/riscv32-unknown-elf-g++ -static -nostdlib -nostartfiles -T common/test.ld Debug/common/crt.S.o Debug/src/main.c.o Debug/common/syscalls.c.o Debug/titan_hal/src/titan_hal_spi.c.o -lm -lgcc -o Debug/test_spi

Thank you.