Commit 4e6dbf3b authored by Brendan Shanks's avatar Brendan Shanks Committed by Alexandre Julliard

loader: In macOS preloader, add __program_vars section.

This is needed to be a correct macOS 10.7 binary.
parent cfa0dd9d
...@@ -106,6 +106,39 @@ void *__stack_chk_guard = 0; ...@@ -106,6 +106,39 @@ void *__stack_chk_guard = 0;
void __stack_chk_fail_local(void) { return; } void __stack_chk_fail_local(void) { return; }
void __stack_chk_fail(void) { return; } void __stack_chk_fail(void) { return; }
/* Binaries targeting 10.6 and 10.7 contain the __program_vars section, and
* dyld4 (starting in Monterey) does not like it to be missing:
* - running vmmap on a Wine process prints this warning:
* "Process exists but has not fully started -- dyld has initialized but libSystem has not"
* - because libSystem is not initialized, dlerror() always returns NULL (causing GStreamer
* to crash on init).
* - starting with macOS Sonoma, Wine crashes on launch if libSystem is not initialized.
*
* Adding __program_vars fixes those issues, and also allows more of the vars to
* be set correctly by the preloader for the loaded binary.
*
* See also:
* <https://github.com/apple-oss-distributions/Csu/blob/Csu-88/crt.c#L42>
* <https://github.com/apple-oss-distributions/dyld/blob/dyld-1042.1/common/MachOAnalyzer.cpp#L2185>
*/
int NXArgc = 0;
const char** NXArgv = NULL;
const char** environ = NULL;
const char* __progname = NULL;
extern void* __dso_handle;
struct ProgramVars
{
void* mh;
int* NXArgcPtr;
const char*** NXArgvPtr;
const char*** environPtr;
const char** __prognamePtr;
};
__attribute__((used)) static struct ProgramVars pvars
__attribute__ ((section ("__DATA,__program_vars"))) = { &__dso_handle, &NXArgc, &NXArgv, &environ, &__progname };
/* /*
* When 'start' is called, stack frame looks like: * When 'start' is called, stack frame looks like:
* *
...@@ -620,15 +653,16 @@ static void fixup_stack( void *stack ) ...@@ -620,15 +653,16 @@ static void fixup_stack( void *stack )
static void set_program_vars( void *stack, void *mod ) static void set_program_vars( void *stack, void *mod )
{ {
int *pargc; int *pargc;
char **argv, **env; const char **argv, **env;
int *wine_NXArgc = pdlsym( mod, "NXArgc" ); int *wine_NXArgc = pdlsym( mod, "NXArgc" );
char ***wine_NXArgv = pdlsym( mod, "NXArgv" ); const char ***wine_NXArgv = pdlsym( mod, "NXArgv" );
char ***wine_environ = pdlsym( mod, "environ" ); const char ***wine_environ = pdlsym( mod, "environ" );
pargc = stack; pargc = stack;
argv = (char **)pargc + 1; argv = (const char **)pargc + 1;
env = &argv[*pargc-1] + 2; env = &argv[*pargc-1] + 2;
/* set vars in the loaded binary */
if (wine_NXArgc) if (wine_NXArgc)
*wine_NXArgc = *pargc; *wine_NXArgc = *pargc;
else else
...@@ -643,6 +677,11 @@ static void set_program_vars( void *stack, void *mod ) ...@@ -643,6 +677,11 @@ static void set_program_vars( void *stack, void *mod )
*wine_environ = env; *wine_environ = env;
else else
wld_printf( "preloader: Warning: failed to set environ\n" ); wld_printf( "preloader: Warning: failed to set environ\n" );
/* set vars in the __program_vars section */
NXArgc = *pargc;
NXArgv = argv;
environ = env;
} }
void *wld_start( void *stack, int *is_unix_thread ) void *wld_start( void *stack, int *is_unix_thread )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment