"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "dlls/ntdll/unix/virtual.c" between
wine-5.12.tar.xz and wine-5.13.tar.xz

About: Wine is an Open Source implementation of the MS Windows API on top of X, OpenGL, and Unix. Think of Wine as a compatibility layer for running Windows programs. Development release.

virtual.c  (wine-5.12.tar.xz):virtual.c  (wine-5.13.tar.xz)
skipping to change at line 159 skipping to change at line 159
static void *working_set_limit = (void *)0x7fffffff0000; /* top of the curren t working set */ static void *working_set_limit = (void *)0x7fffffff0000; /* top of the curren t working set */
#else #else
static void *user_space_limit = (void *)0x7fff0000; static void *user_space_limit = (void *)0x7fff0000;
static void *working_set_limit = (void *)0x7fff0000; static void *working_set_limit = (void *)0x7fff0000;
#endif #endif
struct _KUSER_SHARED_DATA *user_shared_data = (void *)0x7ffe0000; struct _KUSER_SHARED_DATA *user_shared_data = (void *)0x7ffe0000;
SIZE_T signal_stack_size = 0; SIZE_T signal_stack_size = 0;
SIZE_T signal_stack_mask = 0; SIZE_T signal_stack_mask = 0;
static SIZE_T signal_stack_align;
/* TEB allocation blocks */ /* TEB allocation blocks */
static TEB *teb_block; static TEB *teb_block;
static TEB *next_free_teb; static TEB *next_free_teb;
static int teb_block_pos; static int teb_block_pos;
static struct list teb_list = LIST_INIT( teb_list ); static struct list teb_list = LIST_INIT( teb_list );
#define ROUND_ADDR(addr,mask) ((void *)((UINT_PTR)(addr) & ~(UINT_PTR)(mask))) #define ROUND_ADDR(addr,mask) ((void *)((UINT_PTR)(addr) & ~(UINT_PTR)(mask)))
#define ROUND_SIZE(addr,size) (((SIZE_T)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask) #define ROUND_SIZE(addr,size) (((SIZE_T)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask)
#define VIRTUAL_DEBUG_DUMP_VIEW(view) do { if (TRACE_ON(virtual)) dump_view(view ); } while (0) #define VIRTUAL_DEBUG_DUMP_VIEW(view) do { if (TRACE_ON(virtual)) dump_view(view ); } while (0)
#ifndef MAP_NORESERVE #ifndef MAP_NORESERVE
#define MAP_NORESERVE 0 #define MAP_NORESERVE 0
#endif #endif
#ifndef MAP_TRYFIXED #ifndef MAP_TRYFIXED
#define MAP_TRYFIXED 0 #define MAP_TRYFIXED 0
#endif #endif
#ifndef MAP_FIXED_NOREPLACE
#define MAP_FIXED_NOREPLACE 0
#endif
#ifdef _WIN64 /* on 64-bit the page protection bytes use a 2-level table */ #ifdef _WIN64 /* on 64-bit the page protection bytes use a 2-level table */
static const size_t pages_vprot_shift = 20; static const size_t pages_vprot_shift = 20;
static const size_t pages_vprot_mask = (1 << 20) - 1; static const size_t pages_vprot_mask = (1 << 20) - 1;
static size_t pages_vprot_size; static size_t pages_vprot_size;
static BYTE **pages_vprot; static BYTE **pages_vprot;
#else /* on 32-bit we use a simple array with one byte per page */ #else /* on 32-bit we use a simple array with one byte per page */
static BYTE *pages_vprot; static BYTE *pages_vprot;
#endif #endif
skipping to change at line 203 skipping to change at line 205
struct range_entry struct range_entry
{ {
void *base; void *base;
void *end; void *end;
}; };
static struct range_entry *free_ranges; static struct range_entry *free_ranges;
static struct range_entry *free_ranges_end; static struct range_entry *free_ranges_end;
static inline BOOL is_inside_signal_stack( void *ptr )
{
return ((char *)ptr >= (char *)get_signal_stack() &&
(char *)ptr < (char *)get_signal_stack() + signal_stack_size);
}
static void reserve_area( void *addr, void *end ) static void reserve_area( void *addr, void *end )
{ {
#ifdef __APPLE__ #ifdef __APPLE__
#ifdef __i386__ #ifdef __i386__
static const mach_vm_address_t max_address = VM_MAX_ADDRESS; static const mach_vm_address_t max_address = VM_MAX_ADDRESS;
#else #else
static const mach_vm_address_t max_address = MACH_VM_MAX_ADDRESS; static const mach_vm_address_t max_address = MACH_VM_MAX_ADDRESS;
#endif #endif
mach_vm_address_t address = (mach_vm_address_t)addr; mach_vm_address_t address = (mach_vm_address_t)addr;
skipping to change at line 287 skipping to change at line 295
if (size) if (size)
{ {
reserve_area( addr, (char *)addr + size ); reserve_area( addr, (char *)addr + size );
reserve_area( (char *)addr + size, end ); reserve_area( (char *)addr + size, end );
} }
#endif /* __APPLE__ */ #endif /* __APPLE__ */
} }
static void mmap_init( const struct preload_info *preload_info ) static void mmap_init( const struct preload_info *preload_info )
{ {
#ifdef __i386__ #ifndef _WIN64
#ifndef __APPLE__ #ifndef __APPLE__
char stack; char stack;
char * const stack_ptr = &stack; char * const stack_ptr = &stack;
#endif #endif
char *user_space_limit = (char *)0x7ffe0000; char *user_space_limit = (char *)0x7ffe0000;
int i; int i;
if (preload_info) if (preload_info)
{ {
/* check for a reserved area starting at the user space limit */ /* check for a reserved area starting at the user space limit */
skipping to change at line 329 skipping to change at line 337
/* Heuristic: assume the stack is near the end of the address */ /* Heuristic: assume the stack is near the end of the address */
/* space, this avoids a lot of futile allocation attempts */ /* space, this avoids a lot of futile allocation attempts */
end = (char *)(((unsigned long)base + 0x0fffffff) & 0xf0000000); end = (char *)(((unsigned long)base + 0x0fffffff) & 0xf0000000);
#endif #endif
reserve_area( base, end ); reserve_area( base, end );
} }
else else
#endif #endif
reserve_area( user_space_limit, 0 ); reserve_area( user_space_limit, 0 );
#elif defined(__x86_64__) || defined(__aarch64__) #else
if (preload_info) return; if (preload_info) return;
/* if we don't have a preloader, try to reserve the space now */ /* if we don't have a preloader, try to reserve the space now */
reserve_area( (void *)0x000000010000, (void *)0x000068000000 ); reserve_area( (void *)0x000000010000, (void *)0x000068000000 );
reserve_area( (void *)0x00007ff00000, (void *)0x00007fff0000 ); reserve_area( (void *)0x00007ff00000, (void *)0x00007fff0000 );
reserve_area( (void *)0x7ffffe000000, (void *)0x7fffffff0000 ); reserve_area( (void *)0x7ffffe000000, (void *)0x7fffffff0000 );
#endif #endif
} }
skipping to change at line 986 skipping to change at line 994
* Try mmaping some expected free memory region, eventually stepping and * Try mmaping some expected free memory region, eventually stepping and
* retrying inside it, and return where it actually succeeded, or NULL. * retrying inside it, and return where it actually succeeded, or NULL.
*/ */
static void* try_map_free_area( void *base, void *end, ptrdiff_t step, static void* try_map_free_area( void *base, void *end, ptrdiff_t step,
void *start, size_t size, int unix_prot ) void *start, size_t size, int unix_prot )
{ {
void *ptr; void *ptr;
while (start && base <= start && (char*)start + size <= (char*)end) while (start && base <= start && (char*)start + size <= (char*)end)
{ {
if ((ptr = wine_anon_mmap( start, size, unix_prot, 0 )) == start) if ((ptr = wine_anon_mmap( start, size, unix_prot, MAP_FIXED_NOREPLACE ) ) == start)
return start; return start;
TRACE( "Found free area is already mapped, start %p.\n", start ); TRACE( "Found free area is already mapped, start %p.\n", start );
if (ptr == (void *)-1 && errno != EEXIST)
{
ERR( "wine_anon_mmap() error %s, range %p-%p, unix_prot %#x.\n",
strerror(errno), start, (char *)start + size, unix_prot );
return NULL;
}
if (ptr != (void *)-1) if (ptr != (void *)-1)
munmap( ptr, size ); munmap( ptr, size );
if ((step > 0 && (char *)end - (char *)start < step) || if ((step > 0 && (char *)end - (char *)start < step) ||
(step < 0 && (char *)start - (char *)base < -step) || (step < 0 && (char *)start - (char *)base < -step) ||
step == 0) step == 0)
break; break;
start = (char *)start + step; start = (char *)start + step;
} }
skipping to change at line 2297 skipping to change at line 2312
} }
/*********************************************************************** /***********************************************************************
* virtual_init * virtual_init
*/ */
void virtual_init(void) void virtual_init(void)
{ {
const struct preload_info **preload_info = dlsym( RTLD_DEFAULT, "wine_main_p reload_info" ); const struct preload_info **preload_info = dlsym( RTLD_DEFAULT, "wine_main_p reload_info" );
const char *preload = getenv( "WINEPRELOADRESERVE" ); const char *preload = getenv( "WINEPRELOADRESERVE" );
struct alloc_virtual_heap alloc_views; struct alloc_virtual_heap alloc_views;
size_t size; size_t size, align;
int i; int i;
pthread_mutexattr_t attr; pthread_mutexattr_t attr;
pthread_mutexattr_init( &attr ); pthread_mutexattr_init( &attr );
pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE ); pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
pthread_mutex_init( &virtual_mutex, &attr ); pthread_mutex_init( &virtual_mutex, &attr );
pthread_mutexattr_destroy( &attr ); pthread_mutexattr_destroy( &attr );
if (preload_info && *preload_info) if (preload_info && *preload_info)
for (i = 0; (*preload_info)[i].size; i++) for (i = 0; (*preload_info)[i].size; i++)
skipping to change at line 2325 skipping to change at line 2340
if (sscanf( preload, "%lx-%lx", &start, &end ) == 2) if (sscanf( preload, "%lx-%lx", &start, &end ) == 2)
{ {
preload_reserve_start = (void *)start; preload_reserve_start = (void *)start;
preload_reserve_end = (void *)end; preload_reserve_end = (void *)end;
/* some apps start inside the DOS area */ /* some apps start inside the DOS area */
if (preload_reserve_start) if (preload_reserve_start)
address_space_start = min( address_space_start, preload_reserve_ start ); address_space_start = min( address_space_start, preload_reserve_ start );
} }
} }
size = ROUND_SIZE( 0, sizeof(TEB) ) + max( MINSIGSTKSZ, 8192 ); size = teb_size + max( MINSIGSTKSZ, 8192 );
/* find the first power of two not smaller than size */ /* find the first power of two not smaller than size */
signal_stack_align = page_shift; align = page_shift;
while ((1u << signal_stack_align) < size) signal_stack_align++; while ((1u << align) < size) align++;
signal_stack_mask = (1 << signal_stack_align) - 1; signal_stack_mask = (1 << align) - 1;
signal_stack_size = (1 << signal_stack_align) - ROUND_SIZE( 0, sizeof(TEB) ) signal_stack_size = (1 << align) - teb_size;
;
/* try to find space in a reserved area for the views and pages protection t able */ /* try to find space in a reserved area for the views and pages protection t able */
#ifdef _WIN64 #ifdef _WIN64
pages_vprot_size = ((size_t)address_space_limit >> page_shift >> pages_vprot _shift) + 1; pages_vprot_size = ((size_t)address_space_limit >> page_shift >> pages_vprot _shift) + 1;
alloc_views.size = 2 * view_block_size + pages_vprot_size * sizeof(*pages_vp rot); alloc_views.size = 2 * view_block_size + pages_vprot_size * sizeof(*pages_vp rot);
#else #else
alloc_views.size = 2 * view_block_size + (1U << (32 - page_shift)); alloc_views.size = 2 * view_block_size + (1U << (32 - page_shift));
#endif #endif
if (mmap_enum_reserved_areas( alloc_virtual_heap, &alloc_views, 1 )) if (mmap_enum_reserved_areas( alloc_virtual_heap, &alloc_views, 1 ))
mmap_remove_reserved_area( alloc_views.base, alloc_views.size ); mmap_remove_reserved_area( alloc_views.base, alloc_views.size );
skipping to change at line 2487 skipping to change at line 2502
for (i = 0; i < nt->FileHeader.NumberOfSections; i++) for (i = 0; i < nt->FileHeader.NumberOfSections; i++)
{ {
BYTE flags = VPROT_COMMITTED; BYTE flags = VPROT_COMMITTED;
if (sec[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) flags |= VPROT_E XEC; if (sec[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) flags |= VPROT_E XEC;
if (sec[i].Characteristics & IMAGE_SCN_MEM_READ) flags |= VPROT_READ ; if (sec[i].Characteristics & IMAGE_SCN_MEM_READ) flags |= VPROT_READ ;
if (sec[i].Characteristics & IMAGE_SCN_MEM_WRITE) flags |= VPROT_WRI TE; if (sec[i].Characteristics & IMAGE_SCN_MEM_WRITE) flags |= VPROT_WRI TE;
set_page_vprot( (char *)base + sec[i].VirtualAddress, sec[i].Misc.Vi rtualSize, flags ); set_page_vprot( (char *)base + sec[i].VirtualAddress, sec[i].Misc.Vi rtualSize, flags );
} }
VIRTUAL_DEBUG_DUMP_VIEW( view ); VIRTUAL_DEBUG_DUMP_VIEW( view );
if (is_beyond_limit( base, size, working_set_limit )) working_set_limit = address_space_limit;
} }
server_leave_uninterrupted_section( &virtual_mutex, &sigset ); server_leave_uninterrupted_section( &virtual_mutex, &sigset );
return status; return status;
} }
/* set some initial values in a new TEB */ /* set some initial values in a new TEB */
static void init_teb( TEB *teb, PEB *peb ) static void init_teb( TEB *teb, PEB *peb )
{ {
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->Gd iTebBatch; struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->Gd iTebBatch;
skipping to change at line 2520 skipping to change at line 2536
/*********************************************************************** /***********************************************************************
* virtual_alloc_first_teb * virtual_alloc_first_teb
*/ */
TEB *virtual_alloc_first_teb(void) TEB *virtual_alloc_first_teb(void)
{ {
TEB *teb; TEB *teb;
PEB *peb; PEB *peb;
NTSTATUS status; NTSTATUS status;
SIZE_T data_size = page_size; SIZE_T data_size = page_size;
SIZE_T peb_size = page_size; SIZE_T peb_size = page_size;
SIZE_T teb_size = signal_stack_mask + 1; SIZE_T block_size = signal_stack_size + teb_size;
SIZE_T total = 32 * teb_size; SIZE_T total = 32 * block_size;
/* reserve space for shared user data */ /* reserve space for shared user data */
status = NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&user_shared_ data, 0, &data_size, status = NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&user_shared_ data, 0, &data_size,
MEM_RESERVE | MEM_COMMIT, PAGE_READONLY ); MEM_RESERVE | MEM_COMMIT, PAGE_READONLY );
if (status) if (status)
{ {
ERR( "wine: failed to map the shared user data: %08x\n", status ); ERR( "wine: failed to map the shared user data: %08x\n", status );
exit(1); exit(1);
} }
NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&teb_block, 0, &total, NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&teb_block, 0, &total,
MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE ); MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE );
teb_block_pos = 30; teb_block_pos = 30;
teb = (TEB *)((char *)teb_block + 30 * teb_size); teb = (TEB *)((char *)teb_block + 30 * block_size);
peb = (PEB *)((char *)teb_block + 32 * teb_size - peb_size); peb = (PEB *)((char *)teb_block + 32 * block_size - peb_size);
NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&teb, 0, &teb_size, ME NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&teb, 0, &block_size,
M_COMMIT, PAGE_READWRITE ); MEM_COMMIT, PAGE_READWRITE );
NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&peb, 0, &peb_size, ME M_COMMIT, PAGE_READWRITE ); NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&peb, 0, &peb_size, ME M_COMMIT, PAGE_READWRITE );
init_teb( teb, peb ); init_teb( teb, peb );
*(ULONG_PTR *)peb->Reserved = get_image_address(); *(ULONG_PTR *)peb->Reserved = get_image_address();
return teb; return teb;
} }
/*********************************************************************** /***********************************************************************
* virtual_alloc_teb * virtual_alloc_teb
*/ */
NTSTATUS virtual_alloc_teb( TEB **ret_teb ) NTSTATUS virtual_alloc_teb( TEB **ret_teb )
skipping to change at line 2670 skipping to change at line 2686
*/ */
NTSTATUS CDECL virtual_alloc_thread_stack( INITIAL_TEB *stack, SIZE_T reserve_si ze, SIZE_T commit_size, SIZE_T *pthread_size ) NTSTATUS CDECL virtual_alloc_thread_stack( INITIAL_TEB *stack, SIZE_T reserve_si ze, SIZE_T commit_size, SIZE_T *pthread_size )
{ {
struct file_view *view; struct file_view *view;
NTSTATUS status; NTSTATUS status;
sigset_t sigset; sigset_t sigset;
SIZE_T size, extra_size = 0; SIZE_T size, extra_size = 0;
if (!reserve_size || !commit_size) if (!reserve_size || !commit_size)
{ {
IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseA ddress ); IMAGE_NT_HEADERS *nt = get_exe_nt_header();
if (!reserve_size) reserve_size = nt->OptionalHeader.SizeOfStackReserve; if (!reserve_size) reserve_size = nt->OptionalHeader.SizeOfStackReserve;
if (!commit_size) commit_size = nt->OptionalHeader.SizeOfStackCommit; if (!commit_size) commit_size = nt->OptionalHeader.SizeOfStackCommit;
} }
size = max( reserve_size, commit_size ); size = max( reserve_size, commit_size );
if (size < 1024 * 1024) size = 1024 * 1024; /* Xlib needs a large stack */ if (size < 1024 * 1024) size = 1024 * 1024; /* Xlib needs a large stack */
size = (size + 0xffff) & ~0xffff; /* round to 64K boundary */ size = (size + 0xffff) & ~0xffff; /* round to 64K boundary */
if (pthread_size) *pthread_size = extra_size = max( page_size, ROUND_SIZE( 0 , *pthread_size )); if (pthread_size) *pthread_size = extra_size = max( page_size, ROUND_SIZE( 0 , *pthread_size ));
server_enter_uninterrupted_section( &virtual_mutex, &sigset ); server_enter_uninterrupted_section( &virtual_mutex, &sigset );
skipping to change at line 2744 skipping to change at line 2760
wine_anon_mmap( stack, size, PROT_READ | PROT_WRITE, MAP_FIXED ); wine_anon_mmap( stack, size, PROT_READ | PROT_WRITE, MAP_FIXED );
if (force_exec_prot) mprotect( stack, size, PROT_READ | PROT_WRITE | PROT_EX EC ); if (force_exec_prot) mprotect( stack, size, PROT_READ | PROT_WRITE | PROT_EX EC );
} }
/*********************************************************************** /***********************************************************************
* virtual_map_user_shared_data * virtual_map_user_shared_data
*/ */
void virtual_map_user_shared_data(void) void virtual_map_user_shared_data(void)
{ {
static const WCHAR wine_usdW[] = {'\\','K','e','r','n','e','l','O','b','j',' static const WCHAR nameW[] = {'\\','K','e','r','n','e','l','O','b','j','e','
e','c','t','s', c','t','s',
'\\','_','_','w','i','n','e','_','u','s',' '\\','_','_','w','i','n','e','_','u','s','e','
e','r','_','s','h','a','r','e','d','_','d','a','t','a',0}; r','_','s','h','a','r','e','d','_','d','a','t','a',0};
OBJECT_ATTRIBUTES attr = {sizeof(attr)}; UNICODE_STRING name_str = { sizeof(nameW) - sizeof(WCHAR), sizeof(nameW), (W
UNICODE_STRING wine_usd_str; CHAR *)nameW };
OBJECT_ATTRIBUTES attr = { sizeof(attr), 0, &name_str };
NTSTATUS status; NTSTATUS status;
HANDLE section; HANDLE section;
int res, fd, needs_close; int res, fd, needs_close;
RtlInitUnicodeString( &wine_usd_str, wine_usdW );
InitializeObjectAttributes( &attr, &wine_usd_str, OBJ_OPENIF, NULL, NULL );
if ((status = NtOpenSection( &section, SECTION_ALL_ACCESS, &attr ))) if ((status = NtOpenSection( &section, SECTION_ALL_ACCESS, &attr )))
{ {
ERR( "failed to open the USD section: %08x\n", status ); ERR( "failed to open the USD section: %08x\n", status );
exit(1); exit(1);
} }
if ((res = server_get_unix_fd( section, 0, &fd, &needs_close, NULL, NULL )) || if ((res = server_get_unix_fd( section, 0, &fd, &needs_close, NULL, NULL )) ||
(user_shared_data != mmap( user_shared_data, page_size, PROT_READ, MAP_S HARED|MAP_FIXED, fd, 0 ))) (user_shared_data != mmap( user_shared_data, page_size, PROT_READ, MAP_S HARED|MAP_FIXED, fd, 0 )))
{ {
ERR( "failed to remap the process USD: %d\n", res ); ERR( "failed to remap the process USD: %d\n", res );
exit(1); exit(1);
} }
if (needs_close) close( fd ); if (needs_close) close( fd );
NtClose( section ); NtClose( section );
} }
/*********************************************************************** /***********************************************************************
* grow_thread_stack
*/
static NTSTATUS grow_thread_stack( char *page )
{
NTSTATUS ret = 0;
size_t guaranteed = max( NtCurrentTeb()->GuaranteedStackBytes, page_size * (
is_win64 ? 2 : 1) );
set_page_vprot_bits( page, page_size, 0, VPROT_GUARD );
mprotect_range( page, page_size, 0, 0 );
if (page >= (char *)NtCurrentTeb()->DeallocationStack + page_size + guarante
ed)
{
set_page_vprot_bits( page - page_size, page_size, VPROT_COMMITTED | VPRO
T_GUARD, 0 );
mprotect_range( page - page_size, page_size, 0, 0 );
}
else /* inside guaranteed space -> overflow exception */
{
page = (char *)NtCurrentTeb()->DeallocationStack + page_size;
set_page_vprot_bits( page, guaranteed, VPROT_COMMITTED, VPROT_GUARD );
mprotect_range( page, guaranteed, 0, 0 );
ret = STATUS_STACK_OVERFLOW;
}
NtCurrentTeb()->Tib.StackLimit = page;
return ret;
}
/***********************************************************************
* virtual_handle_fault * virtual_handle_fault
*/ */
NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err, BOOL on_signal_stack ) NTSTATUS virtual_handle_fault( void *addr, DWORD err, void *stack )
{ {
NTSTATUS ret = STATUS_ACCESS_VIOLATION; NTSTATUS ret = STATUS_ACCESS_VIOLATION;
void *page = ROUND_ADDR( addr, page_mask ); char *page = ROUND_ADDR( addr, page_mask );
sigset_t sigset;
BYTE vprot; BYTE vprot;
server_enter_uninterrupted_section( &virtual_mutex, &sigset ); pthread_mutex_lock( &virtual_mutex ); /* no need for signal masking inside signal handler */
vprot = get_page_vprot( page ); vprot = get_page_vprot( page );
if (!on_signal_stack && (vprot & VPROT_GUARD)) if (!is_inside_signal_stack( stack ) && (vprot & VPROT_GUARD))
{ {
set_page_vprot_bits( page, page_size, 0, VPROT_GUARD ); if (page < (char *)NtCurrentTeb()->DeallocationStack ||
mprotect_range( page, page_size, 0, 0 ); page >= (char *)NtCurrentTeb()->Tib.StackBase)
ret = STATUS_GUARD_PAGE_VIOLATION; {
set_page_vprot_bits( page, page_size, 0, VPROT_GUARD );
mprotect_range( page, page_size, 0, 0 );
ret = STATUS_GUARD_PAGE_VIOLATION;
}
else ret = grow_thread_stack( page );
} }
else if (err & EXCEPTION_WRITE_FAULT) else if (err & EXCEPTION_WRITE_FAULT)
{ {
if (vprot & VPROT_WRITEWATCH) if (vprot & VPROT_WRITEWATCH)
{ {
set_page_vprot_bits( page, page_size, 0, VPROT_WRITEWATCH ); set_page_vprot_bits( page, page_size, 0, VPROT_WRITEWATCH );
mprotect_range( page, page_size, 0, 0 ); mprotect_range( page, page_size, 0, 0 );
} }
/* ignore fault if page is writable now */ /* ignore fault if page is writable now */
if (get_unix_prot( get_page_vprot( page )) & PROT_WRITE) if (get_unix_prot( get_page_vprot( page )) & PROT_WRITE)
{ {
if ((vprot & VPROT_WRITEWATCH) || is_write_watch_range( page, page_s ize )) if ((vprot & VPROT_WRITEWATCH) || is_write_watch_range( page, page_s ize ))
ret = STATUS_SUCCESS; ret = STATUS_SUCCESS;
} }
} }
server_leave_uninterrupted_section( &virtual_mutex, &sigset ); pthread_mutex_unlock( &virtual_mutex );
return ret; return ret;
} }
/*********************************************************************** /***********************************************************************
* virtual_setup_exception
*/
void *virtual_setup_exception( void *stack_ptr, size_t size, EXCEPTION_RECORD *r
ec )
{
char *stack = stack_ptr;
if (is_inside_signal_stack( stack ))
{
ERR( "nested exception on signal stack in thread %04x addr %p stack %p (
%p-%p-%p)\n",
GetCurrentThreadId(), rec->ExceptionAddress, stack, NtCurrentTeb()-
>DeallocationStack,
NtCurrentTeb()->Tib.StackLimit, NtCurrentTeb()->Tib.StackBase );
abort_thread(1);
}
if (stack - size > stack || /* check for overflow in subtraction */
stack <= (char *)NtCurrentTeb()->DeallocationStack ||
stack > (char *)NtCurrentTeb()->Tib.StackBase)
{
WARN( "exception outside of stack limits in thread %04x addr %p stack %p
(%p-%p-%p)\n",
GetCurrentThreadId(), rec->ExceptionAddress, stack, NtCurrentTeb()
->DeallocationStack,
NtCurrentTeb()->Tib.StackLimit, NtCurrentTeb()->Tib.StackBase );
return stack - size;
}
stack -= size;
if (stack < (char *)NtCurrentTeb()->DeallocationStack + 4096)
{
/* stack overflow on last page, unrecoverable */
UINT diff = (char *)NtCurrentTeb()->DeallocationStack + 4096 - stack;
ERR( "stack overflow %u bytes in thread %04x addr %p stack %p (%p-%p-%p)
\n",
diff, GetCurrentThreadId(), rec->ExceptionAddress, stack, NtCurrent
Teb()->DeallocationStack,
NtCurrentTeb()->Tib.StackLimit, NtCurrentTeb()->Tib.StackBase );
abort_thread(1);
}
else if (stack < (char *)NtCurrentTeb()->Tib.StackLimit)
{
pthread_mutex_lock( &virtual_mutex ); /* no need for signal masking ins
ide signal handler */
if ((get_page_vprot( stack ) & VPROT_GUARD) && grow_thread_stack( ROUND_
ADDR( stack, page_mask )))
{
rec->ExceptionCode = STATUS_STACK_OVERFLOW;
rec->NumberParameters = 0;
}
pthread_mutex_unlock( &virtual_mutex );
}
#if defined(VALGRIND_MAKE_MEM_UNDEFINED)
VALGRIND_MAKE_MEM_UNDEFINED( stack, size );
#elif defined(VALGRIND_MAKE_WRITABLE)
VALGRIND_MAKE_WRITABLE( stack, size );
#endif
return stack;
}
/***********************************************************************
* check_write_access * check_write_access
* *
* Check if the memory range is writable, temporarily disabling write watches if necessary. * Check if the memory range is writable, temporarily disabling write watches if necessary.
*/ */
static NTSTATUS check_write_access( void *base, size_t size, BOOL *has_write_wat ch ) static NTSTATUS check_write_access( void *base, size_t size, BOOL *has_write_wat ch )
{ {
size_t i; size_t i;
char *addr = ROUND_ADDR( base, page_mask ); char *addr = ROUND_ADDR( base, page_mask );
size = ROUND_SIZE( base, size ); size = ROUND_SIZE( base, size );
skipping to change at line 2848 skipping to change at line 2946
unsigned int ret = STATUS_ACCESS_VIOLATION; unsigned int ret = STATUS_ACCESS_VIOLATION;
if (!size) return wine_server_call( req_ptr ); if (!size) return wine_server_call( req_ptr );
server_enter_uninterrupted_section( &virtual_mutex, &sigset ); server_enter_uninterrupted_section( &virtual_mutex, &sigset );
if (!(ret = check_write_access( addr, size, &has_write_watch ))) if (!(ret = check_write_access( addr, size, &has_write_watch )))
{ {
ret = server_call_unlocked( req ); ret = server_call_unlocked( req );
if (has_write_watch) update_write_watches( addr, size, wine_server_reply _size( req )); if (has_write_watch) update_write_watches( addr, size, wine_server_reply _size( req ));
} }
else memset( &req->u.reply, 0, sizeof(req->u.reply) );
server_leave_uninterrupted_section( &virtual_mutex, &sigset ); server_leave_uninterrupted_section( &virtual_mutex, &sigset );
return ret; return ret;
} }
/*********************************************************************** /***********************************************************************
* virtual_locked_read * virtual_locked_read
*/ */
ssize_t virtual_locked_read( int fd, void *addr, size_t size ) ssize_t virtual_locked_read( int fd, void *addr, size_t size )
{ {
sigset_t sigset; sigset_t sigset;
skipping to change at line 2947 skipping to change at line 3046
sigset_t sigset; sigset_t sigset;
server_enter_uninterrupted_section( &virtual_mutex, &sigset ); server_enter_uninterrupted_section( &virtual_mutex, &sigset );
if ((view = find_view( addr, size ))) if ((view = find_view( addr, size )))
ret = !(view->protect & VPROT_SYSTEM); /* system views are not visible to the app */ ret = !(view->protect & VPROT_SYSTEM); /* system views are not visible to the app */
server_leave_uninterrupted_section( &virtual_mutex, &sigset ); server_leave_uninterrupted_section( &virtual_mutex, &sigset );
return ret; return ret;
} }
/*********************************************************************** /***********************************************************************
* virtual_handle_stack_fault
*
* Handle an access fault inside the current thread stack.
* Return 1 if safely handled, -1 if handled into the overflow space.
* Called from inside a signal handler.
*/
int virtual_handle_stack_fault( void *addr )
{
int ret = 0;
if ((char *)addr < (char *)NtCurrentTeb()->DeallocationStack) return 0;
if ((char *)addr >= (char *)NtCurrentTeb()->Tib.StackBase) return 0;
pthread_mutex_lock( &virtual_mutex ); /* no need for signal masking inside
signal handler */
if (get_page_vprot( addr ) & VPROT_GUARD)
{
size_t guaranteed = max( NtCurrentTeb()->GuaranteedStackBytes, page_size
* (is_win64 ? 2 : 1) );
char *page = ROUND_ADDR( addr, page_mask );
set_page_vprot_bits( page, page_size, 0, VPROT_GUARD );
mprotect_range( page, page_size, 0, 0 );
if (page >= (char *)NtCurrentTeb()->DeallocationStack + page_size + guar
anteed)
{
set_page_vprot_bits( page - page_size, page_size, VPROT_COMMITTED |
VPROT_GUARD, 0 );
mprotect_range( page - page_size, page_size, 0, 0 );
ret = 1;
}
else /* inside guaranteed space -> overflow exception */
{
page = (char *)NtCurrentTeb()->DeallocationStack + page_size;
set_page_vprot_bits( page, guaranteed, VPROT_COMMITTED, VPROT_GUARD
);
mprotect_range( page, guaranteed, 0, 0 );
ret = -1;
}
NtCurrentTeb()->Tib.StackLimit = page;
}
pthread_mutex_unlock( &virtual_mutex );
return ret;
}
/***********************************************************************
* virtual_check_buffer_for_read * virtual_check_buffer_for_read
* *
* Check if a memory buffer can be read, triggering page faults if needed for DI B section access. * Check if a memory buffer can be read, triggering page faults if needed for DI B section access.
*/ */
BOOL virtual_check_buffer_for_read( const void *ptr, SIZE_T size ) BOOL virtual_check_buffer_for_read( const void *ptr, SIZE_T size )
{ {
if (!size) return TRUE; if (!size) return TRUE;
if (!ptr) return FALSE; if (!ptr) return FALSE;
__TRY __TRY
skipping to change at line 3248 skipping to change at line 3307
server_leave_uninterrupted_section( &virtual_mutex, &sigset ); server_leave_uninterrupted_section( &virtual_mutex, &sigset );
} }
/*********************************************************************** /***********************************************************************
* virtual_set_large_address_space * virtual_set_large_address_space
* *
* Enable use of a large address space when allowed by the application. * Enable use of a large address space when allowed by the application.
*/ */
void CDECL virtual_set_large_address_space(void) void CDECL virtual_set_large_address_space(void)
{ {
IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddre ss ); IMAGE_NT_HEADERS *nt = get_exe_nt_header();
if (!(nt->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)) retu rn; if (!(nt->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)) retu rn;
/* no large address space on win9x */ /* no large address space on win9x */
if (NtCurrentTeb()->Peb->OSPlatformId != VER_PLATFORM_WIN32_NT) return; if (NtCurrentTeb()->Peb->OSPlatformId != VER_PLATFORM_WIN32_NT) return;
user_space_limit = working_set_limit = address_space_limit; user_space_limit = working_set_limit = address_space_limit;
} }
/*********************************************************************** /***********************************************************************
* NtAllocateVirtualMemory (NTDLL.@) * NtAllocateVirtualMemory (NTDLL.@)
 End of changes. 27 change blocks. 
81 lines changed or deleted 147 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)