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: Chip Davis <cdavis@codeweavers.com> Signed-off-by: Ken Thomases <ken@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
9b767ad6bb
commit
bdca749f7b
|
@ -49,6 +49,7 @@
|
|||
#undef LoadResource
|
||||
#undef GetCurrentThread
|
||||
#include <pthread.h>
|
||||
#include <mach-o/getsect.h>
|
||||
#else
|
||||
extern char **environ;
|
||||
#endif
|
||||
|
@ -387,11 +388,15 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
|
|||
IMAGE_NT_HEADERS *nt;
|
||||
IMAGE_SECTION_HEADER *sec;
|
||||
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_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)
|
||||
|
@ -425,7 +430,15 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
|
|||
delta = (const BYTE *)nt_descr - addr;
|
||||
code_start = page_size;
|
||||
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;
|
||||
#endif
|
||||
|
||||
fixup_rva_ptrs( &nt->OptionalHeader.AddressOfEntryPoint, addr, 1 );
|
||||
|
||||
|
@ -434,7 +447,7 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
|
|||
#ifndef _WIN64
|
||||
nt->OptionalHeader.BaseOfData = data_start;
|
||||
#endif
|
||||
nt->OptionalHeader.SizeOfCode = data_start - code_start;
|
||||
nt->OptionalHeader.SizeOfCode = code_end - code_start;
|
||||
nt->OptionalHeader.SizeOfInitializedData = data_end - data_start;
|
||||
nt->OptionalHeader.SizeOfUninitializedData = 0;
|
||||
nt->OptionalHeader.SizeOfImage = data_end;
|
||||
|
@ -443,7 +456,7 @@ static void *map_dll( const IMAGE_NT_HEADERS *nt_descr )
|
|||
/* Build the code section */
|
||||
|
||||
memcpy( sec->Name, ".text", sizeof(".text") );
|
||||
sec->SizeOfRawData = data_start - code_start;
|
||||
sec->SizeOfRawData = code_end - code_start;
|
||||
sec->Misc.VirtualSize = sec->SizeOfRawData;
|
||||
sec->VirtualAddress = code_start;
|
||||
sec->PointerToRawData = code_start;
|
||||
|
|
Loading…
Reference in New Issue