Page 1 of 1

Problem with using newlib

Posted: Sat Dec 11, 2021 1:02 am
by heavyweight87
Hi,

After about a year of not working on my os (new baby and no time :( ) I finally got around to working on it again and had to clone my project on a new PC

I wanted to see that I could still compile user space programs ok, but I have some problem with newlib. I've tried deleting newlib and recompiling as per instructions in "porting newlib". Making and installing newlib works completes without any problems...

my userspace program is a simple printf "hello world" but make complains with:

Code: Select all

in function `_sbrk_r': "...newlib/libc/reent/sbrkr.c:51: undefined reference to `_sbrk'"
and it will complain about every other system call printf needs (_write, _seek etc")

my makefile:

Code: Select all

CFILES = program.c
CC=i686-myos-gcc 

CFLAGS = -O0  -Wall -Wextra 
LIBS = ~/myos/sysroot/usr/lib/libc.a 

all:
	$(CC) $(LIBS) $(CFILES) $(CFLAGS) -o program.o

clean:
	rm -f *.o
I managed to compile and run a userspace program fine last time I worked on my os, so not sure what i'm missing here. Its trying to use reentrant functions it seems, as if it ignores my own system call wrappers that I wrote.
Any help is appreciated - thanks!

Re: Problem with using newlib

Posted: Sat Dec 11, 2021 7:01 am
by vhaudiquet
Its trying to use reentrant functions it seems, as if it ignores my own system call wrappers that I wrote.
The program you're trying to compile is using reentrant functions, but it does not mean it is ignoring your call wrappers.
If you did not tell newlib that you provide reentrant syscalls, sbrkr() just calls _sbrk()

I think that you need to provide a prototype for _<syscall> in unistd header for some compilers, so that newlib generates syscall wrappers;
so adding void* _sbrk(...); in unistd.h header might just fix this.
(i don't remember well, last time i compiled newlib was 3 years ago...)

Do you have a repository where your code is ?
What are the headers that you provide to newlib under /sys/myos ?

Re: Problem with using newlib

Posted: Sat Dec 11, 2021 10:42 am
by heavyweight87
Strange thing is this worked fine once! I didnt do any changes to my /sys/myos folder...

The sys calls I implemented are here... most are empty as if I dont provide implementation it won't work and I only really need write() for printf
https://github.com/heavyweight87/Sakura ... syscalls.c

Other than changes needed from the porting newlib guide, there arent many changes that I did to newlib

I always thought that printf was non-reentrant anyway!

so maybe I do actually jsut need to provide _write, _sbrk etc? event if it calls the original for now

Re: Problem with using newlib

Posted: Sat Dec 11, 2021 11:17 am
by vhaudiquet
I always thought that printf was non-reentrant anyway!
I don't understand what you mean by that. It seems the issue is with the reentrant version of the sbrk function, nothing related to printf.
so maybe I do actually jsut need to provide _write, _sbrk etc? event if it calls the original for now
No, you only have to provide prototypes.

Your OS does not provide <sys/xxx.h> headers, but it should. Take a look at the linux files in newlib, in your repository :
from https://github.com/heavyweight87/Sakura ... s/unistd.h,

Code: Select all

/* Provide prototypes for most of the _<systemcall> names that are
   provided in newlib for some compilers.  */
int     _close (int __fildes);
pid_t   _fork (void);
pid_t   _getpid (void);
int     _link (const char *__path1, const char *__path2);
off_t   _lseek (int __fildes, off_t __offset, int __whence);
_READ_WRITE_RETURN_TYPE _read (int __fd, void *__buf, size_t __nbyte);
void *  _sbrk (size_t __incr);
int     _unlink (const char *__path);
_READ_WRITE_RETURN_TYPE _write (int __fd, const void *__buf, size_t __nbyte);
int     _execve (const char *__path, char * const __argv[], char * const __envp[]);
It provides the prototypes in the header, but the function is never defined in the code (https://github.com/heavyweight87/Sakura ... inux/brk.c does not define a _sbrk function).
The prototypes allow newlib to make system call wrappers i think.
So you only need to provide those header files and it will work, i believe.

I agree with you that it is strange, and the comment "for some compilers" in the code is cryptic ; i don't have an explanation right now for why you need to do that, but if you do, i think it will work

Re: Problem with using newlib

Posted: Sat Dec 11, 2021 11:30 am
by vhaudiquet
Take a look at https://www.embecosm.com/appnotes/ean9/ ... igure_host :
The implementer defines non-reentrant, but namespace clean versions of the system calls. This is the approach we have used with the OpenRISC 1000 and all the implementer needs to do in this case is to set syscall_dir to syscalls in configure.host. newlib will map reentrant calls down to the non-reentrant versions.
The implementer defines non-reentrant, regular versions of the system calls (i.e. close rather than _close). The library will be neither reentrant, not namespace clean, but will work. In this case, -DMISSING_SYSCALL_NAMES is added to newlib_cflags in configure.host.
The implementer defines non-reentrant, regular versions of the system calls (i.e. close rather than _close). The reentrant system calls are mapped onto these functions. The library will not be namespace clean, but will offer reentrancy at the library level. In this case, -DMISSING_SYSCALL_NAMES and -DREENTRANT_SYSCALLS_PROVIDED are both added to newlib_cflags in configure.host.
It seems that you missed something in your configure.host configuration ; thus newlib does not find the "namespace clean" version of your system calls. I think that what i said before (defining them as prototype in header) will still work, but seems like a hack. Maybe you need to change your configure.host according to what you want to do, using the instructions on this page.

Re: Problem with using newlib

Posted: Sat Dec 11, 2021 1:27 pm
by heavyweight87
ok thanks ill take a look