I want to use STL functions in C and C++ on RISCV that are provided by newlib
. In order to use those I must replace the default implementation of _sbrk
, _read
, _write
and some other functions. By default, newlib
provides these functions and they use syscalls
using RISCV's ecall
instruction. However, I don't want to implement ecall
instructions and instead provide new functions for them.
The problem is that I don't know how to replace a function in C and C++. So my question is basically, how do I override a function in C/C++? Specifically the _sbrk
and other syscall
functions.
Note: Since I don't have a cross-compiler for RiscV, this example uses malloc()
instead of _sbrk()
. The principle is the same.
Implement these functions yourself.
#include <stdlib.h> void* malloc(size_t size) { (void)size; return NULL; }
Then link that module to your other modules, and the functions will not be taken from the library.
Let's say we have this simple program:
#include <stdio.h> #include <stdlib.h> int main() { printf("%p\n", malloc(23)); return 0; }
This is how I compiled and linked:
gcc -Wall -Wextra -pedantic -g -c main.c -o main.o gcc -Wall -Wextra -pedantic -g -c malloc.c -o malloc.o gcc -Wall -Wextra main.o malloc.o -g -Wl,-Map=my_own.map -o my_own
The produced map file is not trivial, however, these are the relevant lines:
[--- lines cut ---]
.plt 0x0000000000001020 0x20 /usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../lib/Scrt1.o
0x0000000000001030 printf@@GLIBC_2.2.5
*(.iplt)
[--- lines cut ---]
.text 0x0000000000001040 0x2f /usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../lib/Scrt1.o
0x0000000000001040 _start
.text 0x000000000000106f 0x0 /usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../lib/crti.o
*fill* 0x000000000000106f 0x1
.text 0x0000000000001070 0xc9 /usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/crtbeginS.o
.text 0x0000000000001139 0x29 main.o
0x0000000000001139 main
.text 0x0000000000001162 0xf malloc.o
0x0000000000001162 malloc
[--- lines cut ---]
As shown, printf()
is taken from the library, but my own malloc()
is used.
This is what you need: https://github.com/openhwgroup/cv32e40p/blob/master/example_tb/core/custom/syscalls.c All required syscalls are there, malloc() is fully functional using this stub functions... Other stuff like printf() works as well, assuming the UART is at 0x10000000 (tested using qemu-system-riscv32 -machine virt)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.