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:
Chip Davis 2018-08-01 15:46:09 -05:00 committed by Alexandre Julliard
parent 9b767ad6bb
commit bdca749f7b
1 changed files with 16 additions and 3 deletions

View File

@ -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;