Thursday, February 3, 2022

[SOLVED] riscv/gcc/ld - "Undefined reference to printf" using own script to link

Issue

Currently, I'm learning RISC-V, use the RISC-V toolchain, and edit a new ld script for my embedded. I write a example, and compile to watch the opcode.

Example:

#include <stdio.h> //float.c

int main()
{
float a=1.04;
printf("a=%f\n",a);
return 0;
}

My steps is:

1. riscv64-unknown-elf-gcc -S float.c  *//generate assembly code*

2. riscv64-unknown-elf-as float.s -o float.o  *//generate obj file*

3. riscv64-unknown-elf-ld -T elf64lriscv1.x float.o *//use own script to link, -T is using other script*

and then,it will show "float.c:(.text+0x50): undefined reference to `printf'

I'm try

Add -lc parameter, but doesn't working, it will show more undefined message.

My ld script

OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv","elf64-littleriscv")
OUTPUT_ARCH(riscv)
ENTRY(_start)
SEARCH_DIR("/path/to/install/riscv/toolchain/riscv64-unknow-elf/lib");
/*MEMORY{  //for my embedded allocation
  flash : org = 0x0, l = 0x10000
  ram : org= 0x10000, l = 512
}*/
SECTIONS{
_start =0x10000;
.text :
{
  *(.text)
}
.bss :
{
  *(.bss)
  *(.sbss)
}}

Also, i'm trying to use the default script, like this command:

$ riscv-unknown-elf-ld float.o -o float

but it is same result.... please help me!

Regards!


Solution

printf is provided by the C standard library (and is very difficult to implement). You need to link it (perhaps by adding -lc to your riscv-unknown-elf-ld command, or by giving the complete path of that library)

You might pass additional options to your riscv-unknown-elf-ld perhaps -M, -L search-dir, --trace, --verbose, etc. Read also more carefully the chapter about ld scripts.

Since you are cross-compiling, you might need to cross-compile some libc from source code.

You need to spend more time understanding the behavior of linkers and ELF object files and executable format (see also elf(5)). Consider reading Linkers and Loaders

You could use other cross- binutils programs (like cross- objdump, nm, readelf etc...) to explore the relevant object files.

If you are coding for a bare metal system, you might want to compile in freestanding mode (passing -ffreestanding to your GCC) and provide so implement your own printf (or other output) function. Existing free software C libraries could inspire you (but you need to find one or work many months to develop some equivalent). Study for inspiration the source code of GNU libc or of musl-libc.

I recommend also reading about OSes, e.g. Operating Systems: Three Easy Pieces (since the OS concepts are relevant to you, because an embedded system on the bare metal share features with OSes). OSDEV wiki might also be helpful (but is not about RISC-V).

You could need several months of work (or even years), so budget it appropriately.

BTW, I am surprized that you use a float in your example. Floating point is difficult. See floating-point-gui.de ; For a first try, I would consider using integer only.



Answered By - Basile Starynkevitch
Answer Checked By - Mildred Charles (WPSolving Admin)