diff options
author | q66 <daniel@octaforge.org> | 2019-11-10 15:32:28 +0100 |
---|---|---|
committer | q66 <daniel@octaforge.org> | 2019-11-10 16:06:20 +0100 |
commit | 19738b586c114ac2dab1cf546634173050dfa93d (patch) | |
tree | a121bc68f4f7da4cd4e4731c81765ba7a252eff8 /libgcompat | |
parent | 289a455f31e30f1d40ecdd10ed5741b76a313a87 (diff) | |
download | gcompat-19738b586c114ac2dab1cf546634173050dfa93d.tar.gz gcompat-19738b586c114ac2dab1cf546634173050dfa93d.tar.bz2 gcompat-19738b586c114ac2dab1cf546634173050dfa93d.tar.xz gcompat-19738b586c114ac2dab1cf546634173050dfa93d.zip |
internal: add a wrapper for __libc_start_main for PowerPC(64(le))
This is necessary because the musl and glibc function signatures
differ significantly.
Diffstat (limited to 'libgcompat')
-rw-r--r-- | libgcompat/internal.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/libgcompat/internal.c b/libgcompat/internal.c index 450c5e4..53ac429 100644 --- a/libgcompat/internal.c +++ b/libgcompat/internal.c @@ -2,6 +2,47 @@ #include <stdio.h> #include <stdlib.h> +#if defined(__powerpc__) + +/* On PowerPC as well as ppc64, we need to fix up __libc_start_main as the + * glibc and musl versions have wildly different signatures, which would + * result in the arguments to __libc_start_main being completely wrong. + * + * Using dlsym in this context is mildly questionable as this is before + * the full initialization has been done, but there is no better way. + */ + +#include <dlfcn.h> + +struct startup_info { + void *sda_base; + void *f_main; + void *f_init; + void *f_fini; +}; + +typedef int (*start_main_t)(void *mf, int argc, char **argv); + +/* + * ref: https://git.musl-libc.org/cgit/musl/tree/crt/crt1.c?id=90251cf + * ref: https://git.musl-libc.org/cgit/musl/tree/src/env/__libc_start_main.c?id=90251cf#n71 + * ref: https://github.com/bminor/glibc/blob/5cb226d/sysdeps/unix/sysv/linux/powerpc/libc-start.c#L36 + */ +int __libc_start_main(void *argc, void *argv, void *ev, void *auxv, void *fini, + struct startup_info *si, long *p) +{ + (void)argc; + (void)argv; + (void)ev; + (void)auxv; + (void)fini; + /* argc/argv from the stack, main from startup_info */ + start_main_t mainf = (start_main_t)dlsym(RTLD_NEXT, "__libc_start_main"); + return mainf(si->f_main, *p, (void *)(p + 1)); +} + +#endif /* defined(__powerpc__) */ + void GCOMPAT__panic(const char *fmt, ...) { va_list va; |