Don't assume it starts with the fake PE header. This assumption doesn't hold on Mac OS: the __data section where it was placed is located after several other sections.
Unfortunately, this causes Wine, when DEP/NX is turned off, to override the page protections for the start of the __DATA segment, removing write permission from them, leading to a crash when winemac.drv attempted to use an Objective-C class for the first time.
Signed-off-by: Chip Davis cdavis@codeweavers.com --- libs/wine/loader.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/libs/wine/loader.c b/libs/wine/loader.c index c07042a583e6..e757a59cd682 100644 --- a/libs/wine/loader.c +++ b/libs/wine/loader.c @@ -49,6 +49,7 @@ #undef LoadResource #undef GetCurrentThread #include <pthread.h> +#include <mach-o/getsect.h> #else extern char **environ; #endif @@ -392,6 +393,10 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr ) const size_t page_mask = page_size - 1; int delta, nb_sections = 2; /* code + data */ unsigned int i; +#ifdef __APPLE__ + Dl_info dli; + unsigned long data_size; +#endif
size_t size = (sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) @@ -424,8 +429,15 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
delta = (const BYTE *)nt_descr - addr; code_start = page_size; +#ifdef __APPLE__ + /* Need the mach_header, not the PE header, to give to getsegmentdata(3) */ + dladdr(addr, &dli); + data_start = getsegmentdata(dli.dli_fbase, "__DATA", &data_size) - addr; + data_end = (data_start + data_size + page_mask) & ~page_mask; +#else data_start = delta & ~page_mask; data_end = (nt->OptionalHeader.SizeOfImage + delta + page_mask) & ~page_mask; +#endif
fixup_rva_ptrs( &nt->OptionalHeader.AddressOfEntryPoint, addr, 1 );