Commit bdca749f authored by Chip Davis's avatar Chip Davis Committed by Alexandre Julliard

libwine: Use getsegmentdata(3) on Mac OS to find the end of the __TEXT segment.

Don't assume it ends 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, all in the __DATA segment. 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. Also, be sure to include the zero-fill (i.e. BSS) sections in the total size of the .data section. This should fix some tests that use large uninitialized arrays. Signed-off-by: 's avatarChip Davis <cdavis@codeweavers.com> Signed-off-by: 's avatarKen Thomases <ken@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 9b767ad6
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#undef LoadResource #undef LoadResource
#undef GetCurrentThread #undef GetCurrentThread
#include <pthread.h> #include <pthread.h>
#include <mach-o/getsect.h>
#else #else
extern char **environ; extern char **environ;
#endif #endif
...@@ -387,11 +388,15 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr ) ...@@ -387,11 +388,15 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
IMAGE_NT_HEADERS *nt; IMAGE_NT_HEADERS *nt;
IMAGE_SECTION_HEADER *sec; IMAGE_SECTION_HEADER *sec;
BYTE *addr; BYTE *addr;
DWORD code_start, data_start, data_end; DWORD code_start, code_end, data_start, data_end;
const size_t page_size = sysconf( _SC_PAGESIZE ); const size_t page_size = sysconf( _SC_PAGESIZE );
const size_t page_mask = page_size - 1; const size_t page_mask = page_size - 1;
int delta, nb_sections = 2; /* code + data */ int delta, nb_sections = 2; /* code + data */
unsigned int i; unsigned int i;
#ifdef __APPLE__
Dl_info dli;
unsigned long data_size;
#endif
size_t size = (sizeof(IMAGE_DOS_HEADER) size_t size = (sizeof(IMAGE_DOS_HEADER)
+ sizeof(IMAGE_NT_HEADERS) + sizeof(IMAGE_NT_HEADERS)
...@@ -425,7 +430,15 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr ) ...@@ -425,7 +430,15 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
delta = (const BYTE *)nt_descr - addr; delta = (const BYTE *)nt_descr - addr;
code_start = page_size; code_start = page_size;
data_start = delta & ~page_mask; data_start = delta & ~page_mask;
#ifdef __APPLE__
/* Need the mach_header, not the PE header, to give to getsegmentdata(3) */
dladdr(addr, &dli);
code_end = getsegmentdata(dli.dli_fbase, "__DATA", &data_size) - addr;
data_end = (code_end + data_size + page_mask) & ~page_mask;
#else
code_end = data_start;
data_end = (nt->OptionalHeader.SizeOfImage + delta + page_mask) & ~page_mask; data_end = (nt->OptionalHeader.SizeOfImage + delta + page_mask) & ~page_mask;
#endif
fixup_rva_ptrs( &nt->OptionalHeader.AddressOfEntryPoint, addr, 1 ); fixup_rva_ptrs( &nt->OptionalHeader.AddressOfEntryPoint, addr, 1 );
...@@ -434,7 +447,7 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr ) ...@@ -434,7 +447,7 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
#ifndef _WIN64 #ifndef _WIN64
nt->OptionalHeader.BaseOfData = data_start; nt->OptionalHeader.BaseOfData = data_start;
#endif #endif
nt->OptionalHeader.SizeOfCode = data_start - code_start; nt->OptionalHeader.SizeOfCode = code_end - code_start;
nt->OptionalHeader.SizeOfInitializedData = data_end - data_start; nt->OptionalHeader.SizeOfInitializedData = data_end - data_start;
nt->OptionalHeader.SizeOfUninitializedData = 0; nt->OptionalHeader.SizeOfUninitializedData = 0;
nt->OptionalHeader.SizeOfImage = data_end; nt->OptionalHeader.SizeOfImage = data_end;
...@@ -443,7 +456,7 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr ) ...@@ -443,7 +456,7 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
/* Build the code section */ /* Build the code section */
memcpy( sec->Name, ".text", sizeof(".text") ); memcpy( sec->Name, ".text", sizeof(".text") );
sec->SizeOfRawData = data_start - code_start; sec->SizeOfRawData = code_end - code_start;
sec->Misc.VirtualSize = sec->SizeOfRawData; sec->Misc.VirtualSize = sec->SizeOfRawData;
sec->VirtualAddress = code_start; sec->VirtualAddress = code_start;
sec->PointerToRawData = code_start; sec->PointerToRawData = code_start;
......
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