Module: wine Branch: master Commit: 949920a7dcdb8d9451e2212247ca2165d5f0064a URL: https://gitlab.winehq.org/wine/wine/-/commit/949920a7dcdb8d9451e2212247ca216...
Author: Alexandre Julliard julliard@winehq.org Date: Tue Oct 3 15:19:49 2023 +0200
ntdll: Add a helper to find a mapping address for a PE image.
---
dlls/ntdll/unix/virtual.c | 80 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 24 deletions(-)
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 6ed44431c9b..25487d7c3cd 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -566,12 +566,12 @@ static void mmap_init( const struct preload_info *preload_info ) /*********************************************************************** * get_wow_user_space_limit */ -static void *get_wow_user_space_limit(void) +static ULONG_PTR get_wow_user_space_limit(void) { #ifdef _WIN64 - return (void *)(user_space_wow_limit & ~granularity_mask); + return user_space_wow_limit & ~granularity_mask; #endif - return user_space_limit; + return (ULONG_PTR)user_space_limit; }
@@ -2595,7 +2595,7 @@ static void update_arm64x_mapping( struct file_view *view, IMAGE_NT_HEADERS *nt, * Map an executable (PE format) image into an existing view. * virtual_mutex must be held by caller. */ -static NTSTATUS map_image_into_view( struct file_view *view, const WCHAR *filename, int fd, void *orig_base, +static NTSTATUS map_image_into_view( struct file_view *view, const WCHAR *filename, int fd, pe_image_info_t *image_info, USHORT machine, int shared_fd, BOOL removable ) { @@ -2791,7 +2791,7 @@ static NTSTATUS map_image_into_view( struct file_view *view, const WCHAR *filena }
#ifdef VALGRIND_LOAD_PDB_DEBUGINFO - VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, ptr - (char *)orig_base); + VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, ptr - (char *)wine_server_get_ptr( image_info->base )); #endif return STATUS_SUCCESS; } @@ -2845,6 +2845,54 @@ static unsigned int get_mapping_info( HANDLE handle, ACCESS_MASK access, unsigne }
+/*********************************************************************** + * map_image_view + * + * Map a view for a PE image at an appropriate address. + */ +static NTSTATUS map_image_view( struct file_view **view_ret, pe_image_info_t *image_info, SIZE_T size, + ULONG_PTR limit_low, ULONG_PTR limit_high, ULONG alloc_type ) +{ + unsigned int vprot = SEC_IMAGE | SEC_FILE | VPROT_COMMITTED | VPROT_READ | VPROT_EXEC | VPROT_WRITECOPY; + void *base = wine_server_get_ptr( image_info->base ); + NTSTATUS status; + ULONG_PTR start, end; + + limit_low = max( limit_low, (ULONG_PTR)address_space_start ); /* make sure the DOS area remains free */ + if (!limit_high) limit_high = (ULONG_PTR)user_space_limit; + + /* first try the specified base */ + + if (base && (ULONG_PTR)base == image_info->base) + { + status = map_view( view_ret, base, size, alloc_type, vprot, limit_low, limit_high, 0 ); + if (!status) return status; + } + + /* then some appropriate address range */ + + if (image_info->base >= limit_4g) + { + start = max( limit_low, limit_4g ); + end = limit_high; + } + else + { + start = limit_low; + end = min( limit_high, get_wow_user_space_limit() ); + } + if (start < end && (start != limit_low || end != limit_high)) + { + status = map_view( view_ret, NULL, size, alloc_type, vprot, start, end, 0 ); + if (!status) return status; + } + + /* then any suitable address */ + + return map_view( view_ret, NULL, size, alloc_type, vprot, limit_low, limit_high, 0 ); +} + + /*********************************************************************** * virtual_map_image * @@ -2855,14 +2903,12 @@ static NTSTATUS virtual_map_image( HANDLE mapping, void **addr_ptr, SIZE_T *size USHORT machine, pe_image_info_t *image_info, WCHAR *filename, BOOL is_builtin ) { - unsigned int vprot = SEC_IMAGE | SEC_FILE | VPROT_COMMITTED | VPROT_READ | VPROT_EXEC | VPROT_WRITECOPY; int unix_fd = -1, needs_close; int shared_fd = -1, shared_needs_close = 0; SIZE_T size = image_info->map_size; struct file_view *view; unsigned int status; sigset_t sigset; - void *base;
if ((status = server_get_unix_fd( mapping, 0, &unix_fd, &needs_close, NULL, NULL ))) return status; @@ -2874,26 +2920,12 @@ static NTSTATUS virtual_map_image( HANDLE mapping, void **addr_ptr, SIZE_T *size return status; }
- status = STATUS_INVALID_PARAMETER; server_enter_uninterrupted_section( &virtual_mutex, &sigset );
- base = wine_server_get_ptr( image_info->base ); - if ((ULONG_PTR)base != image_info->base) base = NULL; - - limit_low = max( limit_low, (ULONG_PTR)address_space_start ); /* make sure the DOS area remains free */ - status = map_view( &view, base, size, alloc_type, vprot, limit_low, limit_high, 0 ); - if (status && limit_low < limit_4g) - { - if ((ULONG_PTR)base >= limit_4g) status = map_view( &view, NULL, size, alloc_type, vprot, - limit_4g, limit_high, 0 ); - else if (limit_high > limit_2g) status = map_view( &view, NULL, size, alloc_type, vprot, - limit_low, limit_2g - 1, 0 ); - } - if (status) status = map_view( &view, NULL, size, alloc_type, vprot, limit_low, limit_high, 0 ); + status = map_image_view( &view, image_info, size, limit_low, limit_high, alloc_type ); if (status) goto done;
- status = map_image_into_view( view, filename, unix_fd, base, image_info, - machine, shared_fd, needs_close ); + status = map_image_into_view( view, filename, unix_fd, image_info, machine, shared_fd, needs_close ); if (status == STATUS_SUCCESS) { SERVER_START_REQ( map_image_view ) @@ -4382,7 +4414,7 @@ static NTSTATUS get_extended_params( const MEM_EXTENDED_PARAMETER *parameters, U MEM_ADDRESS_REQUIREMENTS *r = parameters[i].Pointer; ULONG_PTR limit;
- if (is_wow64()) limit = (ULONG_PTR)get_wow_user_space_limit(); + if (is_wow64()) limit = get_wow_user_space_limit(); else limit = (ULONG_PTR)user_space_limit;
if (r->Alignment)