简体   繁体   中英

How to override C lib functions like _sbrk with user-defined one?

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.

  1. Implement these functions yourself.

     #include <stdlib.h> void* malloc(size_t size) { (void)size; return NULL; }
  2. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM