devkitPro / wut

Let's try to make a Wii U Toolchain / SDK for creating rpx/rpl.
zlib License
244 stars 52 forks source link

Add missing __libc_init_array and __libc_fini_array calls #172

Closed GaryOderNichts closed 3 years ago

GaryOderNichts commented 3 years ago

Needed for static C++ constructors to be called before main.

__libc_init_array will call _init and __libc_fini_array will call _fini so these need to be implemented as well. I just put them into wut_crt.c for now.

fincs commented 3 years ago

We use the EABI abi (-meabi), which results in main() beginning with a call to __eabi silently inserted by the compiler. This function in turn calls __init, which in turn calls the static constructors.

What is this PR intended to fix?

GaryOderNichts commented 3 years ago

For some reason static constructors don't seem to be called with -meabi.

If I compile this simple test program with the latest sample Makefile, name is never initialized. It should be initialized to "test", which I confirmed on PC and which works with this PR.

#include <whb/proc.h>
#include <whb/log.h>
#include <whb/log_udp.h>

class A {
public:
    A(const char* name) : name(name) { }

    const char* const name;
};

static A a("test");

int main()
{
    WHBProcInit();
    WHBLogUdpInit();

    WHBLogPrintf("name is %s", a.name);

    while (WHBProcIsRunning());
    WHBLogUdpDeinit();
    WHBProcShutdown();
    return 0;
}
fincs commented 3 years ago

I'm doing a bit of digging, and this seems to be actually caused by a linkscript issue messing with the ordering of the ctor/dtor data. More investigation will be done soon.

GaryOderNichts commented 3 years ago

Alright thanks, I guess I was a bit quick with this PR. Didn't think of __eabi.

fincs commented 3 years ago

Can you try if this works for you? Revert back to upstream, then edit share/wut.ld like this:

@@ -47,30 +47,26 @@ SECTIONS
       PROVIDE_HIDDEN (__preinit_array_start = .);
       KEEP (*(.preinit_array))
       PROVIDE_HIDDEN (__preinit_array_end = .);

       PROVIDE_HIDDEN (__init_array_start = .);
-      KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
-      KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
-      PROVIDE_HIDDEN (__init_array_end = .);
-
-      PROVIDE_HIDDEN (__fini_array_start = .);
-      KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
-      KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
-      PROVIDE_HIDDEN (__fini_array_end = .);
-
       KEEP (*crtbegin.o(.ctors))
       KEEP (*crtbegin?.o(.ctors))
-      KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+      KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+      KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
       KEEP (*(SORT(.ctors.*)))
       KEEP (*(.ctors))
+      PROVIDE_HIDDEN (__init_array_end = .);

+      PROVIDE_HIDDEN (__fini_array_start = .);
       KEEP (*crtbegin.o(.dtors))
       KEEP (*crtbegin?.o(.dtors))
-      KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+      KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+      KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
       KEEP (*(SORT(.dtors.*)))
       KEEP (*(.dtors))
+      PROVIDE_HIDDEN (__fini_array_end = .);

       KEEP (*(.jcr))
       *(.fixup)
       *(.got1)
       *(.got2)
GaryOderNichts commented 3 years ago

Yeah, initialization works fine for me with that patch.