[Solved] Newlib exit in crt0 causes page fault

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
Agola
Member
Member
Posts: 155
Joined: Sun Nov 20, 2016 7:26 am
Location: Somewhere

[Solved] Newlib exit in crt0 causes page fault

Post by Agola »

Hi osdevers :|

I finally finished debugging and writing my elf loader.
I loaded some elf binaries, and elf loader works good.

Then I wanted to load an elf binary compiled with my OS-Specific toolchain (i686-agola-gcc)
Then... Bam... Got a pagefault with faulting address 0xFF0AF300 :(

Then started to debugging my crt0.c

After some debugging, I found exit(ex) causes the pagefault. Using _exit instead of exit() solves problem, except exit is more correct and elegant, because of also "does two kinds of cleanup before _exit" (from exit.c, newlib)

That is my crt0.c:

Code: Select all

#include <fcntl.h>

extern int main ();
extern void exit(int code);
extern void _init();
extern void _init_signal();
 
void _start() {
    _init();
    _init_signal();
    int ex = main();
    exit(ex); //Page fault, fault happens while executing memory, non-present page, usually in 0xFF0AF300
}
Why exit causes page faults?

Thanks :oops:
Last edited by Agola on Fri Jan 20, 2017 2:22 pm, edited 1 time in total.
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.
User avatar
dchapiesky
Member
Member
Posts: 204
Joined: Sun Dec 25, 2016 1:54 am
Libera.chat IRC: dchapiesky

Re: Newlib exit in crt0 causes page fault

Post by dchapiesky »

Are you using the reentrant version of newlib?

As you need to initialize the GLOBAL_REENT pointer used by newlib/libc/stdlib/exit.c

as early as possible in _start():

Code: Select all

#include <reent.h>

extern void __sinit(struct _reent *);

_REENT_INIT_PTR(_GLOBAL_REENT);
__sinit(__GLOBAL_REENT);
The _REENT_INIT_PTR() sets some values up that are needed so your exit() doesn't call _GLOBAL_REENT->_cleanup() unless it is defined.

The __sinit() initializes newlib's stdio to be reentrant as well.

Also I presume your elf loader is clearing bss?
Plagiarize. Plagiarize. Let not one line escape thine eyes...
User avatar
Agola
Member
Member
Posts: 155
Joined: Sun Nov 20, 2016 7:26 am
Location: Somewhere

Re: Newlib exit in crt0 causes page fault

Post by Agola »

dchapiesky wrote:Are you using the reentrant version of newlib?

As you need to initialize the GLOBAL_REENT pointer used by newlib/libc/stdlib/exit.c

as early as possible in _start():

Code: Select all

#include <reent.h>

extern void __sinit(struct _reent *);

_REENT_INIT_PTR(_GLOBAL_REENT);
__sinit(__GLOBAL_REENT);
The _REENT_INIT_PTR() sets some values up that are needed so your exit() doesn't call _GLOBAL_REENT->_cleanup() unless it is defined.

The __sinit() initializes newlib's stdio to be reentrant as well.

Also I presume your elf loader is clearing bss?
I'm not using reentrant version of newlib.
I'm not sure actually. I didn't use any reentrant code in syscalls. And syscalls' form isn't reentrant (ex. open() not open_r()) So I'm not using reentrant version of newlib, right?

And yes, I'm clearing bss.
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.
User avatar
dchapiesky
Member
Member
Posts: 204
Joined: Sun Dec 25, 2016 1:54 am
Libera.chat IRC: dchapiesky

Re: Newlib exit in crt0 causes page fault

Post by dchapiesky »

The simplest way of figuring this out is to dump the assembly of exit().....

if you see reference to a pointer called _impure_ptr or _global_impure_ptr then you are using the reentrant version.... do the init I suggested.

In newlib 2.4.0 at least, the code in newlib/libc/reent is included always in every compile - so if you are using this version you may not have a choice in the matter...

Using 2.4.0 - I had posts on osdev about faults in getenv() which ultimately was this reent stuff.
Plagiarize. Plagiarize. Let not one line escape thine eyes...
User avatar
Agola
Member
Member
Posts: 155
Joined: Sun Nov 20, 2016 7:26 am
Location: Somewhere

Re: Newlib exit in crt0 causes page fault

Post by Agola »

dchapiesky wrote:The simplest way of figuring this out is to dump the assembly of exit().....

if you see reference to a pointer called _impure_ptr or _global_impure_ptr then you are using the reentrant version.... do the init I suggested.

In newlib 2.4.0 at least, the code in newlib/libc/reent is included always in every compile - so if you are using this version you may not have a choice in the matter...

Using 2.4.0 - I had posts on osdev about faults in getenv() which ultimately was this reent stuff.
Whoa... Crashes back, just copied wrong .elf file :(
Last edited by Agola on Wed Jan 18, 2017 10:53 am, edited 1 time in total.
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.
User avatar
Agola
Member
Member
Posts: 155
Joined: Sun Nov 20, 2016 7:26 am
Location: Somewhere

Re: Newlib exit in crt0 causes page fault

Post by Agola »

I don't know what did I do, page faults started again :(
Maybe I copied another .elf file, and thought it is correct.

Even with initialization, I still get page fault, but I know my Newlib version is reentrant, at least :|
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.
User avatar
Agola
Member
Member
Posts: 155
Joined: Sun Nov 20, 2016 7:26 am
Location: Somewhere

Re: Newlib exit in crt0 causes page fault

Post by Agola »

I'm downgrading to Newlib 2.2.0, same crt0 was working in Newlib 2.2.0, that crt0 faults started after upgrading to Newlib 2.5.0, probably because of the wrong reentrancy initialization you said.

Edit:

Fixed, without downgrading...

Wrote :

Code: Select all

    _REENT_INIT_PTR(_REENT);
    _REENT_INIT_PTR(_GLOBAL_REENT);
    __sinit(_GLOBAL_REENT);
Instead of :

Code: Select all

    _REENT_INIT_PTR(_GLOBAL_REENT);
    __sinit(_GLOBAL_REENT);
But maybe still something is incomplete, missing or wrong... @dchapiesky, could you help me, please?

Maybe that was about exit uses _impure_ptr. I decompiled exit, it uses _impure_ptr instead of _global_impure_ptr.

Also which one is correct? __sinit(_GLOBAL_REENT); or __sinit(_REENT);
If _REENT_INIT_PTR(_REENT); worked, does _REENT_INIT_PTR(_GLOBAL_REENT); need to be added also?
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.
User avatar
Agola
Member
Member
Posts: 155
Joined: Sun Nov 20, 2016 7:26 am
Location: Somewhere

Re: Newlib exit in crt0 causes page fault

Post by Agola »

There are 2-3 of combinations works also.
How will I know which one correct, and does the full initialization?
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.
User avatar
dchapiesky
Member
Member
Posts: 204
Joined: Sun Dec 25, 2016 1:54 am
Libera.chat IRC: dchapiesky

Re: Newlib exit in crt0 causes page fault

Post by dchapiesky »

To be honest I had to check the source code...

Code: Select all

cd newlib
find . -type f -print0 | xargs -0 grep impure
to search the whole thing....

oooo just remembered -

find getreent.c - whatever var it is referencing is what you want...

getreent() is called from a macro and is called all over the place.

Sorry I am not much more help.
Plagiarize. Plagiarize. Let not one line escape thine eyes...
User avatar
Agola
Member
Member
Posts: 155
Joined: Sun Nov 20, 2016 7:26 am
Location: Somewhere

Re: Newlib exit in crt0 causes page fault

Post by Agola »

dchapiesky wrote:To be honest I had to check the source code...

Code: Select all

cd newlib
find . -type f -print0 | xargs -0 grep impure
to search the whole thing....

oooo just remembered -

find getreent.c - whatever var it is referencing is what you want...

getreent() is called from a macro and is called all over the place.

Sorry I am not much more help.
Oh, finally it got work fully.
I started porting easy software now :roll:
Keyboard not found!

Press F1 to run setup.
Press F2 to continue.
User avatar
dchapiesky
Member
Member
Posts: 204
Joined: Sun Dec 25, 2016 1:54 am
Libera.chat IRC: dchapiesky

Re: [Solved] Newlib exit in crt0 causes page fault

Post by dchapiesky »

glad to hear it... cheers
Plagiarize. Plagiarize. Let not one line escape thine eyes...
Post Reply