From 676f261e5e9959e8fb9fe6266ffd2a29bcda2c0d Mon Sep 17 00:00:00 2001 From: Paul Gofman Date: Tue, 2 Jun 2020 21:10:34 +0300 Subject: [PATCH] Updated ntdll-ForceBottomUpAlloc patchset. --- ...h-on-mmap-error-in-try_map_free_area.patch | 8 +- ...XED_NOREPLACE-flag-in-try_map_free_a.patch | 8 +- ...om-up-allocation-order-for-64-bit-ar.patch | 10 +- ...tep-after-failed-map-attempt-in-try_.patch | 8 +- ...unctions-for-managing-free-area-list.patch | 260 ---------- ...rea-list-for-virtual-memory-allocati.patch | 447 ++++++++++++++++++ ...-exclude-natively-mapped-areas-from.patch} | 42 +- ...rea-list-for-virtual-memory-allocati.patch | 198 -------- patches/ntdll-ForceBottomUpAlloc/definition | 2 +- ...ive-symlinks-before-returning-sectio.patch | 34 +- patches/patchinstall.sh | 31 ++ 11 files changed, 531 insertions(+), 517 deletions(-) delete mode 100644 patches/ntdll-ForceBottomUpAlloc/0005-libs-wine-Add-functions-for-managing-free-area-list.patch create mode 100644 patches/ntdll-ForceBottomUpAlloc/0005-ntdll-Use-free-area-list-for-virtual-memory-allocati.patch rename patches/ntdll-ForceBottomUpAlloc/{0007-ntdll-Permanently-exclude-natively-mapped-areas-from.patch => 0006-ntdll-Permanently-exclude-natively-mapped-areas-from.patch} (54%) delete mode 100644 patches/ntdll-ForceBottomUpAlloc/0006-ntdll-Use-free-area-list-for-virtual-memory-allocati.patch diff --git a/patches/ntdll-ForceBottomUpAlloc/0001-ntdll-Stop-search-on-mmap-error-in-try_map_free_area.patch b/patches/ntdll-ForceBottomUpAlloc/0001-ntdll-Stop-search-on-mmap-error-in-try_map_free_area.patch index a32a8f5e..26b0385a 100644 --- a/patches/ntdll-ForceBottomUpAlloc/0001-ntdll-Stop-search-on-mmap-error-in-try_map_free_area.patch +++ b/patches/ntdll-ForceBottomUpAlloc/0001-ntdll-Stop-search-on-mmap-error-in-try_map_free_area.patch @@ -1,4 +1,4 @@ -From b42d3dd8af6e0910bb204d64ac885d2cdc09e4df Mon Sep 17 00:00:00 2001 +From 7dd611828bb181c29d20544c7dcae8f52215ae70 Mon Sep 17 00:00:00 2001 From: Paul Gofman Date: Thu, 9 Jan 2020 15:05:09 +0300 Subject: [PATCH] ntdll: Stop search on mmap() error in try_map_free_area(). @@ -10,10 +10,10 @@ makes the search take incredible time until it fails. 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c -index 8b515fcbce..1d6239f765 100644 +index c6f3c1685e0..37f83efa8fc 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c -@@ -570,8 +570,14 @@ static void* try_map_free_area( void *base, void *end, ptrdiff_t step, +@@ -767,8 +767,14 @@ static void* try_map_free_area( void *base, void *end, ptrdiff_t step, return start; TRACE( "Found free area is already mapped, start %p.\n", start ); @@ -31,5 +31,5 @@ index 8b515fcbce..1d6239f765 100644 if ((step > 0 && (char *)end - (char *)start < step) || (step < 0 && (char *)start - (char *)base < -step) || -- -2.24.1 +2.26.2 diff --git a/patches/ntdll-ForceBottomUpAlloc/0002-ntdll-Use-MAP_FIXED_NOREPLACE-flag-in-try_map_free_a.patch b/patches/ntdll-ForceBottomUpAlloc/0002-ntdll-Use-MAP_FIXED_NOREPLACE-flag-in-try_map_free_a.patch index 6986c8e1..120fdcf6 100644 --- a/patches/ntdll-ForceBottomUpAlloc/0002-ntdll-Use-MAP_FIXED_NOREPLACE-flag-in-try_map_free_a.patch +++ b/patches/ntdll-ForceBottomUpAlloc/0002-ntdll-Use-MAP_FIXED_NOREPLACE-flag-in-try_map_free_a.patch @@ -1,4 +1,4 @@ -From 61e5e74a97121f630fc7f5c5144fd0172d547b60 Mon Sep 17 00:00:00 2001 +From dae806ca4aa1d25e65539f33b784791a9b357a77 Mon Sep 17 00:00:00 2001 From: Paul Gofman Date: Thu, 16 Jan 2020 16:09:24 +0300 Subject: [PATCH] ntdll: Use MAP_FIXED_NOREPLACE flag in try_map_free_area() if @@ -11,10 +11,10 @@ already mapped. 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c -index 1d6239f765..486693f312 100644 +index 37f83efa8fc..4ee30af6548 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c -@@ -562,22 +562,28 @@ static struct wine_rb_entry *find_view_inside_range( void **base_ptr, void **end +@@ -759,22 +759,28 @@ static struct wine_rb_entry *find_view_inside_range( void **base_ptr, void **end static void* try_map_free_area( void *base, void *end, ptrdiff_t step, void *start, size_t size, int unix_prot ) { @@ -47,5 +47,5 @@ index 1d6239f765..486693f312 100644 if ((step > 0 && (char *)end - (char *)start < step) || (step < 0 && (char *)start - (char *)base < -step) || -- -2.24.1 +2.26.2 diff --git a/patches/ntdll-ForceBottomUpAlloc/0003-ntdll-Force-bottom-up-allocation-order-for-64-bit-ar.patch b/patches/ntdll-ForceBottomUpAlloc/0003-ntdll-Force-bottom-up-allocation-order-for-64-bit-ar.patch index 062ec92e..db1b99ec 100644 --- a/patches/ntdll-ForceBottomUpAlloc/0003-ntdll-Force-bottom-up-allocation-order-for-64-bit-ar.patch +++ b/patches/ntdll-ForceBottomUpAlloc/0003-ntdll-Force-bottom-up-allocation-order-for-64-bit-ar.patch @@ -1,4 +1,4 @@ -From 53e3f063ddc0ac0dfee0e53deffc58f818479cdd Mon Sep 17 00:00:00 2001 +From 15fdb467ef17b05df48abe7f5f23e718ce876d57 Mon Sep 17 00:00:00 2001 From: Paul Gofman Date: Mon, 25 Nov 2019 12:19:20 +0300 Subject: [PATCH] ntdll: Force bottom up allocation order for 64 bit arch @@ -11,10 +11,10 @@ Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46568 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c -index 170e310f34d..e90fabf614a 100644 +index 4ee30af6548..ba9ecd5a5b1 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c -@@ -1256,13 +1256,19 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, +@@ -1492,13 +1492,19 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, } else { @@ -35,7 +35,7 @@ index 170e310f34d..e90fabf614a 100644 if (unix_funcs->mmap_enum_reserved_areas( alloc_reserved_area_callback, &alloc, top_down )) { ptr = alloc.result; -@@ -1272,7 +1278,7 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, +@@ -1508,7 +1514,7 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, goto done; } @@ -44,7 +44,7 @@ index 170e310f34d..e90fabf614a 100644 { if (!(ptr = map_free_area( address_space_start, alloc.limit, size, top_down, VIRTUAL_GetUnixProt(vprot) ))) -@@ -1281,6 +1287,8 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, +@@ -1517,6 +1523,8 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, goto done; } diff --git a/patches/ntdll-ForceBottomUpAlloc/0004-ntdll-Increase-step-after-failed-map-attempt-in-try_.patch b/patches/ntdll-ForceBottomUpAlloc/0004-ntdll-Increase-step-after-failed-map-attempt-in-try_.patch index dffc980e..7a5de496 100644 --- a/patches/ntdll-ForceBottomUpAlloc/0004-ntdll-Increase-step-after-failed-map-attempt-in-try_.patch +++ b/patches/ntdll-ForceBottomUpAlloc/0004-ntdll-Increase-step-after-failed-map-attempt-in-try_.patch @@ -1,4 +1,4 @@ -From 0c2da5027e397cd2a3677cad6e505482e7c8b063 Mon Sep 17 00:00:00 2001 +From a95074355fd65c1396ac0fbd9fbc1c2c151b434b Mon Sep 17 00:00:00 2001 From: Paul Gofman Date: Tue, 14 Jan 2020 21:39:23 +0300 Subject: [PATCH] ntdll: Increase step after failed map attempt in @@ -9,10 +9,10 @@ Subject: [PATCH] ntdll: Increase step after failed map attempt in 1 file changed, 1 insertion(+) diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c -index 81d844ab17..a262401f58 100644 +index ba9ecd5a5b1..86062cd4546 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c -@@ -590,6 +590,7 @@ static void* try_map_free_area( void *base, void *end, ptrdiff_t step, +@@ -787,6 +787,7 @@ static void* try_map_free_area( void *base, void *end, ptrdiff_t step, step == 0) break; start = (char *)start + step; @@ -21,5 +21,5 @@ index 81d844ab17..a262401f58 100644 return NULL; -- -2.24.1 +2.26.2 diff --git a/patches/ntdll-ForceBottomUpAlloc/0005-libs-wine-Add-functions-for-managing-free-area-list.patch b/patches/ntdll-ForceBottomUpAlloc/0005-libs-wine-Add-functions-for-managing-free-area-list.patch deleted file mode 100644 index 6fb71cff..00000000 --- a/patches/ntdll-ForceBottomUpAlloc/0005-libs-wine-Add-functions-for-managing-free-area-list.patch +++ /dev/null @@ -1,260 +0,0 @@ -From 20012afe9a7e47f06550c9802e62d66ac9f9abba Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Tue, 14 Jan 2020 21:28:57 +0300 -Subject: [PATCH] libs/wine: Add functions for managing free area list. - ---- - include/wine/library.h | 6 ++++ - libs/wine/mmap.c | 75 ++++++++++++++++++++++++++++++++---------- - libs/wine/wine.map | 4 +++ - 3 files changed, 68 insertions(+), 17 deletions(-) - -diff --git a/include/wine/library.h b/include/wine/library.h -index 60d6b525c75..70b6a0b3055 100644 ---- a/include/wine/library.h -+++ b/include/wine/library.h -@@ -79,6 +79,12 @@ extern int wine_mmap_is_in_reserved_area( void *addr, size_t size ); - extern int wine_mmap_enum_reserved_areas( int (*enum_func)(void *base, size_t size, void *arg), - void *arg, int top_down ); - -+extern void wine_mmap_add_free_area( void *addr, size_t size ); -+extern void wine_mmap_remove_free_area( void *addr, size_t size, int unmap ); -+extern int wine_mmap_is_in_free_area( void *addr, size_t size ); -+extern int wine_mmap_enum_free_areas( int (*enum_func)(void *base, size_t size, void *arg), -+ void *arg, int top_down ); -+ - #ifdef __cplusplus - } - #endif -diff --git a/libs/wine/mmap.c b/libs/wine/mmap.c -index f2b5adc1d29..baa466c7766 100644 ---- a/libs/wine/mmap.c -+++ b/libs/wine/mmap.c -@@ -52,7 +52,9 @@ struct reserved_area - size_t size; - }; - --static struct list reserved_areas = LIST_INIT(reserved_areas); -+static struct list reserved_areas_list = LIST_INIT(reserved_areas_list); -+static struct list free_areas_list = LIST_INIT(free_areas_list); -+ - #ifndef __APPLE__ - static const unsigned int granularity_mask = 0xffff; /* reserved areas have 64k granularity */ - #endif -@@ -427,7 +429,7 @@ void mmap_init(void) - - reserve_malloc_space( 8 * 1024 * 1024 ); - -- if (!list_head( &reserved_areas )) -+ if (!list_head( &reserved_areas_list )) - { - /* if we don't have a preloader, try to reserve some space below 2Gb */ - reserve_area( (void *)0x00110000, (void *)0x40000000 ); -@@ -435,7 +437,7 @@ void mmap_init(void) - - /* check for a reserved area starting at the user space limit */ - /* to avoid wasting time trying to allocate it again */ -- LIST_FOR_EACH( ptr, &reserved_areas ) -+ LIST_FOR_EACH( ptr, &reserved_areas_list ) - { - area = LIST_ENTRY( ptr, struct reserved_area, entry ); - if ((char *)area->base > user_space_limit) break; -@@ -466,7 +468,7 @@ void mmap_init(void) - - /* reserve the DOS area if not already done */ - -- ptr = list_head( &reserved_areas ); -+ ptr = list_head( &reserved_areas_list ); - if (ptr) - { - area = LIST_ENTRY( ptr, struct reserved_area, entry ); -@@ -476,7 +478,7 @@ void mmap_init(void) - - #elif defined(__x86_64__) || defined(__aarch64__) - -- if (!list_head( &reserved_areas )) -+ if (!list_head( &reserved_areas_list )) - { - /* if we don't have a preloader, try to reserve the space now */ - reserve_area( (void *)0x000000010000, (void *)0x000068000000 ); -@@ -497,14 +499,14 @@ void mmap_init(void) - * Note: the reserved areas functions are not reentrant, caller is - * responsible for proper locking. - */ --void wine_mmap_add_reserved_area( void *addr, size_t size ) -+static void wine_mmap_add_area( struct list *areas, void *addr, size_t size ) - { - struct reserved_area *area; - struct list *ptr; - - if (!((char *)addr + size)) size--; /* avoid wrap-around */ - -- LIST_FOR_EACH( ptr, &reserved_areas ) -+ LIST_FOR_EACH( ptr, areas ) - { - area = LIST_ENTRY( ptr, struct reserved_area, entry ); - if (area->base > addr) -@@ -524,7 +526,7 @@ void wine_mmap_add_reserved_area( void *addr, size_t size ) - area->size += size; - - /* try to merge with the next one too */ -- if ((ptr = list_next( &reserved_areas, ptr ))) -+ if ((ptr = list_next( areas, ptr ))) - { - struct reserved_area *next = LIST_ENTRY( ptr, struct reserved_area, entry ); - if ((char *)addr + size == (char *)next->base) -@@ -546,6 +548,15 @@ void wine_mmap_add_reserved_area( void *addr, size_t size ) - } - } - -+void wine_mmap_add_reserved_area( void *addr, size_t size ) -+{ -+ wine_mmap_add_area(&reserved_areas_list, addr, size); -+} -+ -+void wine_mmap_add_free_area( void *addr, size_t size ) -+{ -+ wine_mmap_add_area(&free_areas_list, addr, size); -+} - - /*********************************************************************** - * wine_mmap_remove_reserved_area -@@ -556,14 +567,14 @@ void wine_mmap_add_reserved_area( void *addr, size_t size ) - * Note: the reserved areas functions are not reentrant, caller is - * responsible for proper locking. - */ --void wine_mmap_remove_reserved_area( void *addr, size_t size, int unmap ) -+static void wine_mmap_remove_area( struct list *areas, void *addr, size_t size, int unmap ) - { - struct reserved_area *area; - struct list *ptr; - - if (!((char *)addr + size)) size--; /* avoid wrap-around */ - -- ptr = list_head( &reserved_areas ); -+ ptr = list_head( areas ); - /* find the first area covering address */ - while (ptr) - { -@@ -584,7 +595,7 @@ void wine_mmap_remove_reserved_area( void *addr, size_t size, int unmap ) - else - { - /* range contains the whole area -> remove area completely */ -- ptr = list_next( &reserved_areas, ptr ); -+ ptr = list_next( areas, ptr ); - if (unmap) munmap( area->base, area->size ); - list_remove( &area->entry ); - free( area ); -@@ -616,10 +627,19 @@ void wine_mmap_remove_reserved_area( void *addr, size_t size, int unmap ) - } - } - } -- ptr = list_next( &reserved_areas, ptr ); -+ ptr = list_next( areas, ptr ); - } - } - -+void wine_mmap_remove_reserved_area( void *addr, size_t size, int unmap ) -+{ -+ wine_mmap_remove_area(&reserved_areas_list, addr, size, unmap); -+} -+ -+void wine_mmap_remove_free_area( void *addr, size_t size, int unmap ) -+{ -+ wine_mmap_remove_area(&free_areas_list, addr, size, unmap); -+} - - /*********************************************************************** - * wine_mmap_is_in_reserved_area -@@ -631,12 +651,12 @@ void wine_mmap_remove_reserved_area( void *addr, size_t size, int unmap ) - * Note: the reserved areas functions are not reentrant, caller is - * responsible for proper locking. - */ --int wine_mmap_is_in_reserved_area( void *addr, size_t size ) -+static int wine_mmap_is_in_area( struct list *areas, void *addr, size_t size ) - { - struct reserved_area *area; - struct list *ptr; - -- LIST_FOR_EACH( ptr, &reserved_areas ) -+ LIST_FOR_EACH( ptr, areas ) - { - area = LIST_ENTRY( ptr, struct reserved_area, entry ); - if (area->base > addr) break; -@@ -648,6 +668,15 @@ int wine_mmap_is_in_reserved_area( void *addr, size_t size ) - return 0; - } - -+int wine_mmap_is_in_reserved_area( void *addr, size_t size ) -+{ -+ return wine_mmap_is_in_area( &reserved_areas_list, addr, size ); -+} -+ -+int wine_mmap_is_in_free_area( void *addr, size_t size ) -+{ -+ return wine_mmap_is_in_area( &free_areas_list, addr, size ); -+} - - /*********************************************************************** - * wine_mmap_enum_reserved_areas -@@ -658,7 +687,7 @@ int wine_mmap_is_in_reserved_area( void *addr, size_t size ) - * Note: the reserved areas functions are not reentrant, caller is - * responsible for proper locking. - */ --int wine_mmap_enum_reserved_areas( int (*enum_func)(void *base, size_t size, void *arg), void *arg, -+int wine_mmap_enum_areas( struct list *areas, int (*enum_func)(void *base, size_t size, void *arg), void *arg, - int top_down ) - { - int ret = 0; -@@ -666,7 +695,7 @@ int wine_mmap_enum_reserved_areas( int (*enum_func)(void *base, size_t size, voi - - if (top_down) - { -- for (ptr = reserved_areas.prev; ptr != &reserved_areas; ptr = ptr->prev) -+ for (ptr = areas->prev; ptr != areas; ptr = ptr->prev) - { - struct reserved_area *area = LIST_ENTRY( ptr, struct reserved_area, entry ); - if ((ret = enum_func( area->base, area->size, arg ))) break; -@@ -674,7 +703,7 @@ int wine_mmap_enum_reserved_areas( int (*enum_func)(void *base, size_t size, voi - } - else - { -- for (ptr = reserved_areas.next; ptr != &reserved_areas; ptr = ptr->next) -+ for (ptr = areas->next; ptr != areas; ptr = ptr->next) - { - struct reserved_area *area = LIST_ENTRY( ptr, struct reserved_area, entry ); - if ((ret = enum_func( area->base, area->size, arg ))) break; -@@ -682,3 +711,15 @@ int wine_mmap_enum_reserved_areas( int (*enum_func)(void *base, size_t size, voi - } - return ret; - } -+ -+int wine_mmap_enum_reserved_areas( int (*enum_func)(void *base, size_t size, void *arg), void *arg, -+ int top_down ) -+{ -+ return wine_mmap_enum_areas(&reserved_areas_list, enum_func, arg, top_down); -+} -+ -+int wine_mmap_enum_free_areas( int (*enum_func)(void *base, size_t size, void *arg), void *arg, -+ int top_down ) -+{ -+ return wine_mmap_enum_areas(&free_areas_list, enum_func, arg, top_down); -+} -diff --git a/libs/wine/wine.map b/libs/wine/wine.map -index 9c4c86dde4d..32bf99bd6e6 100644 ---- a/libs/wine/wine.map -+++ b/libs/wine/wine.map -@@ -31,6 +31,10 @@ WINE_1.0 - wine_mmap_enum_reserved_areas; - wine_mmap_is_in_reserved_area; - wine_mmap_remove_reserved_area; -+ wine_mmap_add_free_area; -+ wine_mmap_enum_free_areas; -+ wine_mmap_is_in_free_area; -+ wine_mmap_remove_free_area; - wine_wctype_table; - - /* the following functions are obsolete and only exported for backwards compatibility */ --- -2.25.1 - diff --git a/patches/ntdll-ForceBottomUpAlloc/0005-ntdll-Use-free-area-list-for-virtual-memory-allocati.patch b/patches/ntdll-ForceBottomUpAlloc/0005-ntdll-Use-free-area-list-for-virtual-memory-allocati.patch new file mode 100644 index 00000000..08d32ea7 --- /dev/null +++ b/patches/ntdll-ForceBottomUpAlloc/0005-ntdll-Use-free-area-list-for-virtual-memory-allocati.patch @@ -0,0 +1,447 @@ +From d757532f375dee8d7b717e546ef14406ebbc3653 Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Tue, 14 Jan 2020 21:42:21 +0300 +Subject: [PATCH] ntdll: Use free area list for virtual memory allocation. + +--- + dlls/ntdll/virtual.c | 319 +++++++++++++++++++++++++++---------------- + 1 file changed, 204 insertions(+), 115 deletions(-) + +diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c +index 86062cd4546..81592a84715 100644 +--- a/dlls/ntdll/virtual.c ++++ b/dlls/ntdll/virtual.c +@@ -190,7 +190,11 @@ static BYTE *pages_vprot; + #endif + + static struct file_view *view_block_start, *view_block_end, *next_free_view; ++#ifdef _WIN64 ++static const size_t view_block_size = 0x200000; ++#else + static const size_t view_block_size = 0x100000; ++#endif + static void *preload_reserve_start; + static void *preload_reserve_end; + static BOOL use_locks; +@@ -235,13 +239,13 @@ static struct range_entry *free_ranges_lower_bound( void *addr ) + * + * Updates the free_ranges after a new view has been created. + */ +-static void free_ranges_insert_view( struct file_view *view ) ++static void free_ranges_remove_range( void *view_base, void *view_end, void *view_base_unaligned ) + { +- void *view_base = ROUND_ADDR( view->base, granularity_mask ); +- void *view_end = ROUND_ADDR( (char *)view->base + view->size + granularity_mask, granularity_mask ); + struct range_entry *range = free_ranges_lower_bound( view_base ); + struct range_entry *next = range + 1; + ++ TRACE("view %p-%p (%p).\n", view_base, view_end, view_base_unaligned); ++ + /* free_ranges initial value is such that the view is either inside range or before another one. */ + assert( range != free_ranges_end ); + assert( range->end > view_base || next != free_ranges_end ); +@@ -252,7 +256,7 @@ static void free_ranges_insert_view( struct file_view *view ) + (range->end == view_base && next->base >= view_end)) + { + /* on Win64, assert that it's correctly aligned so we're not going to be in trouble later */ +- assert( (!is_win64 && !is_wow64) || view->base == view_base ); ++ assert( (!is_win64 && !is_wow64) || view_base_unaligned == view_base ); + WARN( "range %p - %p is already mapped\n", view_base, view_end ); + return; + } +@@ -292,6 +296,12 @@ static void free_ranges_insert_view( struct file_view *view ) + } + } + ++static void free_ranges_insert_view( struct file_view *view ) ++{ ++ free_ranges_remove_range(ROUND_ADDR(view->base, granularity_mask), ++ ROUND_ADDR((char *)view->base + view->size + granularity_mask, granularity_mask), ++ view->base); ++} + + /*********************************************************************** + * free_ranges_remove_view +@@ -322,6 +332,7 @@ static void free_ranges_remove_view( struct file_view *view ) + return; + } + #endif ++ TRACE("view %p-%p.\n", view_base, view_end); + + /* free_ranges initial value is such that the view is either inside range or before another one. */ + assert( range != free_ranges_end ); +@@ -712,44 +723,6 @@ static struct file_view *find_view_range( const void *addr, size_t size ) + } + + +-/*********************************************************************** +- * find_view_inside_range +- * +- * Find first (resp. last, if top_down) view inside a range. +- * The csVirtual section must be held by caller. +- */ +-static struct wine_rb_entry *find_view_inside_range( void **base_ptr, void **end_ptr, int top_down ) +-{ +- struct wine_rb_entry *first = NULL, *ptr = views_tree.root; +- void *base = *base_ptr, *end = *end_ptr; +- +- /* find the first (resp. last) view inside the range */ +- while (ptr) +- { +- struct file_view *view = WINE_RB_ENTRY_VALUE( ptr, struct file_view, entry ); +- if ((char *)view->base + view->size >= (char *)end) +- { +- end = min( end, view->base ); +- ptr = ptr->left; +- } +- else if (view->base <= base) +- { +- base = max( (char *)base, (char *)view->base + view->size ); +- ptr = ptr->right; +- } +- else +- { +- first = ptr; +- ptr = top_down ? ptr->right : ptr->left; +- } +- } +- +- *base_ptr = base; +- *end_ptr = end; +- return first; +-} +- +- + /*********************************************************************** + * try_map_free_area + * +@@ -793,65 +766,11 @@ static void* try_map_free_area( void *base, void *end, ptrdiff_t step, + return NULL; + } + +- +-/*********************************************************************** +- * map_free_area +- * +- * Find a free area between views inside the specified range and map it. +- * The csVirtual section must be held by caller. +- */ +-static void *map_free_area( void *base, void *end, size_t size, int top_down, int unix_prot ) +-{ +- struct wine_rb_entry *first = find_view_inside_range( &base, &end, top_down ); +- ptrdiff_t step = top_down ? -(granularity_mask + 1) : (granularity_mask + 1); +- void *start; +- +- if (top_down) +- { +- start = ROUND_ADDR( (char *)end - size, granularity_mask ); +- if (start >= end || start < base) return NULL; +- +- while (first) +- { +- struct file_view *view = WINE_RB_ENTRY_VALUE( first, struct file_view, entry ); +- if ((start = try_map_free_area( (char *)view->base + view->size, (char *)start + size, step, +- start, size, unix_prot ))) break; +- start = ROUND_ADDR( (char *)view->base - size, granularity_mask ); +- /* stop if remaining space is not large enough */ +- if (!start || start >= end || start < base) return NULL; +- first = wine_rb_prev( first ); +- } +- } +- else +- { +- start = ROUND_ADDR( (char *)base + granularity_mask, granularity_mask ); +- if (!start || start >= end || (char *)end - (char *)start < size) return NULL; +- +- while (first) +- { +- struct file_view *view = WINE_RB_ENTRY_VALUE( first, struct file_view, entry ); +- if ((start = try_map_free_area( start, view->base, step, +- start, size, unix_prot ))) break; +- start = ROUND_ADDR( (char *)view->base + view->size + granularity_mask, granularity_mask ); +- /* stop if remaining space is not large enough */ +- if (!start || start >= end || (char *)end - (char *)start < size) return NULL; +- first = wine_rb_next( first ); +- } +- } +- +- if (!first) +- return try_map_free_area( base, end, step, start, size, unix_prot ); +- +- return start; +-} +- +- + /*********************************************************************** + * find_reserved_free_area + * + * Find a free area between views inside the specified range. + * The csVirtual section must be held by caller. +- * The range must be inside the preloader reserved range. + */ + static void *find_reserved_free_area( void *base, void *end, size_t size, int top_down ) + { +@@ -1065,8 +984,7 @@ static void delete_view( struct file_view *view ) /* [in] View */ + { + if (!(view->protect & VPROT_SYSTEM)) unmap_area( view->base, view->size ); + set_page_vprot( view->base, view->size, 0 ); +- if (unix_funcs->mmap_is_in_reserved_area( view->base, view->size )) +- free_ranges_remove_view( view ); ++ free_ranges_remove_view( view ); + wine_rb_remove( &views_tree, &view->entry ); + *(struct file_view **)view = next_free_view; + next_free_view = view; +@@ -1114,8 +1032,7 @@ static NTSTATUS create_view( struct file_view **view_ret, void *base, size_t siz + set_page_vprot( base, size, vprot ); + + wine_rb_put( &views_tree, view->base, &view->entry ); +- if (unix_funcs->mmap_is_in_reserved_area( view->base, view->size )) +- free_ranges_insert_view( view ); ++ free_ranges_insert_view( view ); + + *view_ret = view; + +@@ -1373,6 +1290,7 @@ struct alloc_area + int top_down; + void *limit; + void *result; ++ int unix_prot; + }; + + /*********************************************************************** +@@ -1414,6 +1332,179 @@ static int CDECL alloc_reserved_area_callback( void *start, SIZE_T size, void *a + return 0; + } + ++struct area_alloc_reserved ++{ ++ char *map_area_start, *map_area_end, *result; ++ size_t size; ++ ptrdiff_t step; ++ int unix_prot; ++ BOOL top_down; ++}; ++ ++static int CDECL alloc_area_in_reserved_or_between_callback( void *start, SIZE_T size, void *arg ) ++{ ++ struct area_alloc_reserved *area = arg; ++ char *end = (char *)start + size; ++ char *intersect_start, *intersect_end; ++ char *alloc_start; ++ ++ if (area->top_down) ++ { ++ if (area->map_area_start >= end) ++ return 1; ++ ++ if (area->map_area_end <= (char *)start) ++ return 0; ++ ++ intersect_start = max((char *)start, area->map_area_start); ++ intersect_end = min((char *)end, area->map_area_end); ++ ++ assert(ROUND_ADDR(intersect_start, granularity_mask) == intersect_start); ++ assert(ROUND_ADDR(intersect_end + granularity_mask - 1, granularity_mask) == intersect_end); ++ ++ alloc_start = ROUND_ADDR( (char *)area->map_area_end - size, granularity_mask ); ++ ++ if (alloc_start >= intersect_end) ++ { ++ if ((area->result = try_map_free_area( area->map_area_start, alloc_start + size, area->step, ++ alloc_start, area->size, area->unix_prot ))) ++ return 1; ++ } ++ ++ alloc_start = ROUND_ADDR( intersect_end - area->size, granularity_mask ); ++ if (alloc_start >= intersect_start) ++ { ++ if ((area->result = wine_anon_mmap( alloc_start, area->size, area->unix_prot, MAP_FIXED )) != alloc_start) ++ ERR("Could not map in reserved area, alloc_start %p, size %p.\n", ++ alloc_start, (void *)area->size); ++ return 1; ++ } ++ ++ area->map_area_end = intersect_start; ++ if (area->map_area_end - area->map_area_start < area->size) ++ return 1; ++ } ++ else ++ { ++ if (area->map_area_end <= (char *)start) ++ { ++ return 1; ++ } ++ ++ if (area->map_area_start >= (char *)end) ++ return 0; ++ ++ intersect_start = max((char *)start, area->map_area_start); ++ intersect_end = min((char *)end, area->map_area_end); ++ ++ assert(ROUND_ADDR(intersect_start, granularity_mask) == intersect_start); ++ assert(ROUND_ADDR(intersect_end + granularity_mask - 1, granularity_mask) == intersect_end); ++ ++ if (intersect_start - area->map_area_start >= area->size) ++ { ++ if ((area->result = try_map_free_area( area->map_area_start, intersect_start, area->step, ++ area->map_area_start, area->size, area->unix_prot ))) ++ return 1; ++ } ++ ++ if (intersect_end - intersect_start >= area->size) ++ { ++ if ((area->result = wine_anon_mmap( intersect_start, area->size, area->unix_prot, MAP_FIXED )) ++ != intersect_start) ++ ERR("Could not map in reserved area.\n"); ++ return 1; ++ } ++ area->map_area_start = intersect_end; ++ if (area->map_area_end - area->map_area_start < area->size) ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static void *alloc_free_area(void *limit, size_t size, BOOL top_down, int unix_prot) ++{ ++ struct range_entry *range, *ranges_start, *ranges_end; ++ struct area_alloc_reserved area; ++ char *start, *base, *end; ++ int ranges_inc; ++ ++ TRACE("limit %p, size %p, top_down %#x.\n", limit, (void *)size, top_down); ++ ++ if (top_down) ++ { ++ ranges_start = free_ranges_end - 1; ++ ranges_end = free_ranges - 1; ++ ranges_inc = -1; ++ } ++ else ++ { ++ ranges_start = free_ranges; ++ ranges_end = free_ranges_end; ++ ranges_inc = 1; ++ } ++ ++ memset(&area, 0, sizeof(area)); ++ area.step = top_down ? -(granularity_mask + 1) : (granularity_mask + 1); ++ area.size = size; ++ area.top_down = top_down; ++ area.unix_prot = unix_prot; ++ ++ for (range = ranges_start; range != ranges_end; range += ranges_inc) ++ { ++ base = range->base; ++ end = range->end; ++ ++ TRACE("range %p-%p.\n", base, end); ++ ++ if (base < (char *)address_space_start) base = (char *)address_space_start; ++ if (end > (char *)limit + granularity_mask + 1) end = (char *)limit + granularity_mask + 1; ++ if (base >= end) continue; ++ ++ area.map_area_start = base; ++ area.map_area_end = end; ++ ++ if (top_down) ++ { ++ start = ROUND_ADDR( (char *)end - size, granularity_mask ); ++ if (start >= end || start < base) ++ continue; ++ } ++ else ++ { ++ start = ROUND_ADDR( (char *)base + granularity_mask, granularity_mask ); ++ if (!start || start >= end || (char *)end - (char *)start < size) ++ continue; ++ } ++ unix_funcs->mmap_enum_reserved_areas( alloc_area_in_reserved_or_between_callback, &area, top_down ); ++ if (area.result) ++ return area.result; ++ ++ if (top_down) ++ { ++ start = ROUND_ADDR( area.map_area_end - size, granularity_mask ); ++ if (start >= area.map_area_end || start < area.map_area_start) ++ continue; ++ ++ if ((area.result = try_map_free_area( area.map_area_start, start + size, area.step, ++ start, size, unix_prot ))) ++ return area.result; ++ } ++ else ++ { ++ start = ROUND_ADDR( area.map_area_start + granularity_mask, granularity_mask ); ++ if (!start || start >= area.map_area_end ++ || area.map_area_end - start < size) ++ continue; ++ ++ if ((area.result = try_map_free_area( start, area.map_area_end, area.step, ++ start, size, unix_prot ))) ++ return area.result; ++ } ++ } ++ return NULL; ++} ++ + /*********************************************************************** + * map_fixed_area + * +@@ -1499,11 +1590,15 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, + alloc.size = size; + alloc.top_down = top_down; + alloc.limit = (void*)(get_zero_bits_64_mask( zero_bits_64 ) & (UINT_PTR)user_space_limit); ++ alloc.unix_prot = VIRTUAL_GetUnixProt(vprot); + +- if (is_win64 && !top_down) ++ if (is_win64 || zero_bits_64) + { +- /* Ditch 0x7ffffe000000 - 0x7fffffff0000 reserved area. */ +- alloc.limit = min(alloc.limit, (void *)0x7ffffe000000); ++ if (!(ptr = alloc_free_area( alloc.limit, alloc.size, top_down, alloc.unix_prot))) ++ return STATUS_NO_MEMORY; ++ ++ TRACE( "got mem in free area %p-%p\n", ptr, (char *)ptr + size ); ++ goto done; + } + + if (unix_funcs->mmap_enum_reserved_areas( alloc_reserved_area_callback, &alloc, top_down )) +@@ -1514,16 +1609,6 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, + return STATUS_INVALID_PARAMETER; + goto done; + } +- +- if (is_win64 || zero_bits_64) +- { +- if (!(ptr = map_free_area( address_space_start, alloc.limit, size, +- top_down, VIRTUAL_GetUnixProt(vprot) ))) +- return STATUS_NO_MEMORY; +- TRACE( "got mem with map_free_area %p-%p\n", ptr, (char *)ptr + size ); +- goto done; +- } +- + view_size = size + granularity_mask + 1; + + for (;;) +@@ -2256,10 +2341,14 @@ void virtual_init(void) + pages_vprot = (void *)((char *)alloc_views.base + 2 * view_block_size); + wine_rb_init( &views_tree, compare_view ); + +- free_ranges[0].base = (void *)0; +- free_ranges[0].end = (void *)~0; ++ free_ranges[0].base = address_space_start; ++ free_ranges[0].end = address_space_limit; + free_ranges_end = free_ranges + 1; + ++ free_ranges_remove_range(ROUND_ADDR(preload_reserve_start, granularity_mask), ++ ROUND_ADDR((char *)preload_reserve_end + granularity_mask, ++ granularity_mask), preload_reserve_start); ++ + /* make the DOS area accessible (except the low 64K) to hide bugs in broken apps like Excel 2003 */ + size = (char *)address_space_start - (char *)0x10000; + if (size && unix_funcs->mmap_is_in_reserved_area( (void*)0x10000, size ) == 1) +-- +2.26.2 + diff --git a/patches/ntdll-ForceBottomUpAlloc/0007-ntdll-Permanently-exclude-natively-mapped-areas-from.patch b/patches/ntdll-ForceBottomUpAlloc/0006-ntdll-Permanently-exclude-natively-mapped-areas-from.patch similarity index 54% rename from patches/ntdll-ForceBottomUpAlloc/0007-ntdll-Permanently-exclude-natively-mapped-areas-from.patch rename to patches/ntdll-ForceBottomUpAlloc/0006-ntdll-Permanently-exclude-natively-mapped-areas-from.patch index 19d9ab14..ad2f44b3 100644 --- a/patches/ntdll-ForceBottomUpAlloc/0007-ntdll-Permanently-exclude-natively-mapped-areas-from.patch +++ b/patches/ntdll-ForceBottomUpAlloc/0006-ntdll-Permanently-exclude-natively-mapped-areas-from.patch @@ -1,18 +1,18 @@ -From edf5fb86ff4d075fb48fd562fc0be2140c8e66bb Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Wed, 15 Jan 2020 17:05:09 +0300 +From 0c26b2508ad1fc3c5bfb8eb775fb21febfeb4c0e Mon Sep 17 00:00:00 2001 +From: Paul Gofman +Date: Tue, 2 Jun 2020 21:06:33 +0300 Subject: [PATCH] ntdll: Permanently exclude natively mapped areas from free areas list. --- - dlls/ntdll/virtual.c | 22 ++++++++++++++++++++++ - 1 file changed, 22 insertions(+) + dlls/ntdll/virtual.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c -index 18524fc12de..63a10435890 100644 +index 81592a84715..6c6efea0285 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c -@@ -111,6 +111,9 @@ static const BYTE VIRTUAL_Win32Flags[16] = +@@ -112,6 +112,9 @@ static const BYTE VIRTUAL_Win32Flags[16] = static struct wine_rb_tree views_tree; @@ -22,7 +22,7 @@ index 18524fc12de..63a10435890 100644 static RTL_CRITICAL_SECTION csVirtual; static RTL_CRITICAL_SECTION_DEBUG critsect_debug = { -@@ -566,6 +569,13 @@ static void* try_map_free_area( void *base, void *end, ptrdiff_t step, +@@ -755,6 +758,13 @@ static void* try_map_free_area( void *base, void *end, ptrdiff_t step, if (ptr != (void *)-1) munmap( ptr, size ); @@ -36,37 +36,31 @@ index 18524fc12de..63a10435890 100644 if ((step > 0 && (char *)end - (char *)start < step) || (step < 0 && (char *)start - (char *)base < -step) || step == 0) -@@ -1136,6 +1146,8 @@ static int alloc_free_area_callback( void *base, size_t area_size, void *arg ) - ptrdiff_t step = alloc->top_down ? -(granularity_mask + 1) : (granularity_mask + 1); - void *start; +@@ -1594,9 +1604,24 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, -+ TRACE("base %p, area_size %p, size %p.\n", base, (void *)area_size, (void *)size); -+ - if (base < address_space_start) base = address_space_start; - if (is_beyond_limit( base, size, alloc->limit )) end = alloc->limit; - if (base >= end) return 0; -@@ -1265,11 +1277,21 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, - goto done; - } - -+ if (is_win64 || zero_bits_64) { + last_already_mapped = NULL; + - if (!wine_mmap_enum_free_areas( alloc_free_area_callback, &alloc, top_down )) + if (!(ptr = alloc_free_area( alloc.limit, alloc.size, top_down, alloc.unix_prot))) return STATUS_NO_MEMORY; + if (last_already_mapped) + { ++ void *last_mapped_start, *last_mapped_end; ++ + TRACE("Permanently excluding %p - %p from free list.\n", + last_already_mapped, (char *)last_already_mapped + last_already_mapped_size - 1); -+ wine_mmap_remove_free_area(last_already_mapped, last_already_mapped_size, 0); ++ last_mapped_start = ROUND_ADDR(last_already_mapped, granularity_mask); ++ last_mapped_end = ROUND_ADDR((char *)last_already_mapped + last_already_mapped_size + granularity_mask, ++ granularity_mask); ++ if (ptr > last_mapped_end || (char *)ptr + size < (char *)last_mapped_start) ++ free_ranges_remove_range(last_mapped_start, last_mapped_end, last_already_mapped); + } + - ptr = alloc.result; TRACE( "got mem in free area %p-%p\n", ptr, (char *)ptr + size ); goto done; + } -- 2.26.2 diff --git a/patches/ntdll-ForceBottomUpAlloc/0006-ntdll-Use-free-area-list-for-virtual-memory-allocati.patch b/patches/ntdll-ForceBottomUpAlloc/0006-ntdll-Use-free-area-list-for-virtual-memory-allocati.patch deleted file mode 100644 index 98952797..00000000 --- a/patches/ntdll-ForceBottomUpAlloc/0006-ntdll-Use-free-area-list-for-virtual-memory-allocati.patch +++ /dev/null @@ -1,198 +0,0 @@ -From e659b08734ee7f9265736dadfe7b9a763e7ee2c6 Mon Sep 17 00:00:00 2001 -From: Paul Gofman -Date: Tue, 14 Jan 2020 21:42:21 +0300 -Subject: [PATCH] ntdll: Use free area list for virtual memory allocation. - ---- - dlls/ntdll/virtual.c | 111 +++++++++++++++++++++---------------------- - 1 file changed, 55 insertions(+), 56 deletions(-) - -diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c -index 167b9a7fedc..b66b7874ab7 100644 ---- a/dlls/ntdll/virtual.c -+++ b/dlls/ntdll/virtual.c -@@ -577,59 +577,6 @@ static void* try_map_free_area( void *base, void *end, ptrdiff_t step, - return NULL; - } - -- --/*********************************************************************** -- * map_free_area -- * -- * Find a free area between views inside the specified range and map it. -- * The csVirtual section must be held by caller. -- */ --static void *map_free_area( void *base, void *end, size_t size, int top_down, int unix_prot ) --{ -- struct wine_rb_entry *first = find_view_inside_range( &base, &end, top_down ); -- ptrdiff_t step = top_down ? -(granularity_mask + 1) : (granularity_mask + 1); -- void *start; -- -- if (top_down) -- { -- start = ROUND_ADDR( (char *)end - size, granularity_mask ); -- if (start >= end || start < base) return NULL; -- -- while (first) -- { -- struct file_view *view = WINE_RB_ENTRY_VALUE( first, struct file_view, entry ); -- if ((start = try_map_free_area( (char *)view->base + view->size, (char *)start + size, step, -- start, size, unix_prot ))) break; -- start = ROUND_ADDR( (char *)view->base - size, granularity_mask ); -- /* stop if remaining space is not large enough */ -- if (!start || start >= end || start < base) return NULL; -- first = wine_rb_prev( first ); -- } -- } -- else -- { -- start = ROUND_ADDR( (char *)base + granularity_mask, granularity_mask ); -- if (!start || start >= end || (char *)end - (char *)start < size) return NULL; -- -- while (first) -- { -- struct file_view *view = WINE_RB_ENTRY_VALUE( first, struct file_view, entry ); -- if ((start = try_map_free_area( start, view->base, step, -- start, size, unix_prot ))) break; -- start = ROUND_ADDR( (char *)view->base + view->size + granularity_mask, granularity_mask ); -- /* stop if remaining space is not large enough */ -- if (!start || start >= end || (char *)end - (char *)start < size) return NULL; -- first = wine_rb_next( first ); -- } -- } -- -- if (!first) -- return try_map_free_area( base, end, step, start, size, unix_prot ); -- -- return start; --} -- -- - /*********************************************************************** - * find_reserved_free_area - * -@@ -844,6 +791,7 @@ static struct file_view *alloc_view(void) - */ - static void delete_view( struct file_view *view ) /* [in] View */ - { -+ wine_mmap_add_free_area(view->base, view->size); - if (!(view->protect & VPROT_SYSTEM)) unmap_area( view->base, view->size ); - set_page_vprot( view->base, view->size, 0 ); - wine_rb_remove( &views_tree, &view->entry ); -@@ -901,6 +849,7 @@ static NTSTATUS create_view( struct file_view **view_ret, void *base, size_t siz - TRACE( "forcing exec permission on %p-%p\n", base, (char *)base + size - 1 ); - mprotect( base, size, unix_prot | PROT_EXEC ); - } -+ wine_mmap_remove_free_area(view->base, view->size, 0); - return STATUS_SUCCESS; - } - -@@ -1137,6 +1086,7 @@ struct alloc_area - int top_down; - void *limit; - void *result; -+ int unix_prot; - }; - - /*********************************************************************** -@@ -1178,6 +1128,41 @@ static int CDECL alloc_reserved_area_callback( void *start, SIZE_T size, void *a - return 0; - } - -+static int alloc_free_area_callback( void *base, size_t area_size, void *arg ) -+{ -+ struct alloc_area *alloc = arg; -+ void *end = (char *)base + area_size; -+ size_t size = alloc->size; -+ ptrdiff_t step = alloc->top_down ? -(granularity_mask + 1) : (granularity_mask + 1); -+ void *start; -+ -+ if (base < address_space_start) base = address_space_start; -+ if (is_beyond_limit( base, size, alloc->limit )) end = alloc->limit; -+ if (base >= end) return 0; -+ -+ if (alloc->top_down) -+ { -+ start = ROUND_ADDR( (char *)end - size, granularity_mask ); -+ if (start >= end || start < base) -+ return 0; -+ -+ if ((alloc->result = try_map_free_area( base, (char *)start + size, step, -+ start, size, alloc->unix_prot ))) -+ return 1; -+ } -+ else -+ { -+ start = ROUND_ADDR( (char *)base + granularity_mask, granularity_mask ); -+ if (!start || start >= end || (char *)end - (char *)start < size) -+ return 0; -+ -+ if ((alloc->result = try_map_free_area( start, end, step, -+ start, size, alloc->unix_prot ))) -+ return 1; -+ } -+ return 0; -+} -+ - /*********************************************************************** - * map_fixed_area - * -@@ -1263,6 +1248,7 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, - alloc.size = size; - alloc.top_down = top_down; - alloc.limit = (void*)(get_zero_bits_64_mask( zero_bits_64 ) & (UINT_PTR)user_space_limit); -+ alloc.unix_prot = VIRTUAL_GetUnixProt(vprot); - - if (is_win64 && !top_down) - { -@@ -1281,10 +1267,11 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, - - if (is_win64 || zero_bits_64) - { -- if (!(ptr = map_free_area( address_space_start, alloc.limit, size, -- top_down, VIRTUAL_GetUnixProt(vprot) ))) -+ if (!wine_mmap_enum_free_areas( alloc_free_area_callback, &alloc, top_down )) - return STATUS_NO_MEMORY; -- TRACE( "got mem with map_free_area %p-%p\n", ptr, (char *)ptr + size ); -+ -+ ptr = alloc.result; -+ TRACE( "got mem in free area %p-%p\n", ptr, (char *)ptr + size ); - goto done; - } - -@@ -1956,6 +1943,12 @@ static int CDECL alloc_virtual_heap( void *base, SIZE_T size, void *arg ) - return (alloc->base != (void *)-1); - } - -+static int remove_reserved_area_from_free( void *base, size_t size, void *arg ) -+{ -+ wine_mmap_remove_free_area(base, size, 0); -+ return 0; -+} -+ - /*********************************************************************** - * virtual_init - */ -@@ -2021,6 +2014,9 @@ void virtual_init(void) - size = (char *)address_space_start - (char *)0x10000; - if (size && unix_funcs->mmap_is_in_reserved_area( (void*)0x10000, size ) == 1) - wine_anon_mmap( (void *)0x10000, size, PROT_READ | PROT_WRITE, MAP_FIXED ); -+ -+ wine_mmap_add_free_area(address_space_start, (char *)user_space_limit - (char *)address_space_start); -+ wine_mmap_enum_reserved_areas( remove_reserved_area_from_free, NULL, 0); - } - - -@@ -2792,6 +2788,9 @@ void virtual_set_large_address_space(void) - /* no large address space on win9x */ - if (NtCurrentTeb()->Peb->OSPlatformId != VER_PLATFORM_WIN32_NT) return; - -+ if (address_space_limit > user_space_limit) -+ wine_mmap_add_free_area(user_space_limit, (char *)address_space_limit - (char *)user_space_limit); -+ - user_space_limit = working_set_limit = address_space_limit; - } - --- -2.26.2 - diff --git a/patches/ntdll-ForceBottomUpAlloc/definition b/patches/ntdll-ForceBottomUpAlloc/definition index c58d53a5..fe758c9e 100644 --- a/patches/ntdll-ForceBottomUpAlloc/definition +++ b/patches/ntdll-ForceBottomUpAlloc/definition @@ -1,3 +1,3 @@ Fixes: [48175] AION (64 bit) - crashes in crysystem.dll.CryFree() due to high memory pointers allocated Fixes: [46568] 64-bit msxml6.dll from Microsoft Core XML Services 6.0 redist package fails to load (Wine doesn't respect 44-bit user-mode VA limitation from Windows < 8.1) -Disabled: true + diff --git a/patches/ntdll-NtQueryVirtualMemory/0008-ntdll-Resolve-drive-symlinks-before-returning-sectio.patch b/patches/ntdll-NtQueryVirtualMemory/0008-ntdll-Resolve-drive-symlinks-before-returning-sectio.patch index b125f578..81e23dc8 100644 --- a/patches/ntdll-NtQueryVirtualMemory/0008-ntdll-Resolve-drive-symlinks-before-returning-sectio.patch +++ b/patches/ntdll-NtQueryVirtualMemory/0008-ntdll-Resolve-drive-symlinks-before-returning-sectio.patch @@ -1,4 +1,4 @@ -From 70785e15d5f0344c186714e859595b667dc34a07 Mon Sep 17 00:00:00 2001 +From bc7e6ddf9534dd8afced865788a3d6ce8d068a47 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Sun, 28 May 2017 11:17:26 +0200 Subject: [PATCH] ntdll: Resolve drive symlinks before returning section name. @@ -11,10 +11,10 @@ Subject: [PATCH] ntdll: Resolve drive symlinks before returning section name. 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c -index 453568d641e..12da4316e88 100644 +index 7a9de26ccb0..1062e35e009 100644 --- a/dlls/ntdll/directory.c +++ b/dlls/ntdll/directory.c -@@ -2798,7 +2798,7 @@ static NTSTATUS nt_to_unix_file_name_internal( const UNICODE_STRING *nameW, ANSI +@@ -2806,7 +2806,7 @@ static NTSTATUS nt_to_unix_file_name_internal( const UNICODE_STRING *nameW, ANSI } /* read the contents of an NT symlink object */ @@ -24,10 +24,10 @@ index 453568d641e..12da4316e88 100644 OBJECT_ATTRIBUTES attr; UNICODE_STRING targetW; diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h -index 427cdaad441..f92adb0c0dc 100644 +index b6507599a92..b7822c54ad0 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h -@@ -177,6 +177,7 @@ extern NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_S +@@ -182,6 +182,7 @@ extern NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_S UINT disposition ) DECLSPEC_HIDDEN; /* virtual memory */ @@ -36,19 +36,19 @@ index 427cdaad441..f92adb0c0dc 100644 const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr, ULONG alloc_type, ULONG protect, pe_image_info_t *image_info ) DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c -index fb9a1a57729..89ed3bb3f0b 100644 +index cc1d6e5d6f2..3d53b92cb8e 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c -@@ -188,6 +188,8 @@ static BYTE **pages_vprot; +@@ -192,6 +192,8 @@ static BYTE **pages_vprot; static BYTE *pages_vprot; #endif +#define MAX_DIR_ENTRY_LEN 255 /* max length of a directory entry in chars */ + static struct file_view *view_block_start, *view_block_end, *next_free_view; - static const size_t view_block_size = 0x100000; - static void *preload_reserve_start; -@@ -3471,12 +3473,15 @@ static NTSTATUS get_section_name( HANDLE process, LPCVOID addr, + #ifdef _WIN64 + static const size_t view_block_size = 0x200000; +@@ -3713,12 +3715,15 @@ static NTSTATUS get_section_name( HANDLE process, LPCVOID addr, MEMORY_SECTION_NAME *info, SIZE_T len, SIZE_T *res_len ) { @@ -65,7 +65,7 @@ index fb9a1a57729..89ed3bb3f0b 100644 if (!addr || !info || !res_len) return STATUS_INVALID_PARAMETER; -@@ -3535,14 +3540,34 @@ static NTSTATUS get_section_name( HANDLE process, LPCVOID addr, +@@ -3777,14 +3782,34 @@ static NTSTATUS get_section_name( HANDLE process, LPCVOID addr, } found: @@ -106,10 +106,10 @@ index fb9a1a57729..89ed3bb3f0b 100644 else status = (len < sizeof(MEMORY_SECTION_NAME)) ? STATUS_INFO_LENGTH_MISMATCH : STATUS_BUFFER_OVERFLOW; diff --git a/dlls/psapi/tests/psapi_main.c b/dlls/psapi/tests/psapi_main.c -index f6a7b69eca0..a8263a2f44b 100644 +index 99e87db9543..3984805d2b9 100644 --- a/dlls/psapi/tests/psapi_main.c +++ b/dlls/psapi/tests/psapi_main.c -@@ -476,7 +476,6 @@ static void test_GetMappedFileName(void) +@@ -488,7 +488,6 @@ static void test_GetMappedFileName(void) ret = GetMappedFileNameA(GetCurrentProcess(), base, map_name, sizeof(map_name)); ok(ret, "GetMappedFileName error %d\n", GetLastError()); ok(ret > strlen(device_name), "map_name should be longer than device_name\n"); @@ -117,7 +117,7 @@ index f6a7b69eca0..a8263a2f44b 100644 ok(memcmp(map_name, device_name, strlen(device_name)) == 0, "map name does not start with a device name: %s\n", map_name); SetLastError(0xdeadbeef); -@@ -489,7 +488,6 @@ todo_wine { +@@ -501,7 +500,6 @@ todo_wine { { ok(memcmp(map_nameW, nt_map_name, lstrlenW(map_nameW)) == 0, "map name does not start with a device name: %s\n", map_name); WideCharToMultiByte(CP_ACP, 0, map_nameW, -1, map_name, MAX_PATH, NULL, NULL); @@ -125,7 +125,7 @@ index f6a7b69eca0..a8263a2f44b 100644 ok(memcmp(map_name, device_name, strlen(device_name)) == 0, "map name does not start with a device name: %s\n", map_name); } -@@ -502,7 +500,6 @@ todo_wine +@@ -514,7 +512,6 @@ todo_wine { ok(memcmp(map_nameW, nt_map_name, lstrlenW(map_nameW)) == 0, "map name does not start with a device name: %s\n", map_name); WideCharToMultiByte(CP_ACP, 0, map_nameW, -1, map_name, MAX_PATH, NULL, NULL); @@ -133,7 +133,7 @@ index f6a7b69eca0..a8263a2f44b 100644 ok(memcmp(map_name, device_name, strlen(device_name)) == 0, "map name does not start with a device name: %s\n", map_name); } -@@ -510,7 +507,6 @@ todo_wine +@@ -522,7 +519,6 @@ todo_wine ret = GetMappedFileNameA(GetCurrentProcess(), base + 0x2000, map_name, sizeof(map_name)); ok(ret, "GetMappedFileName error %d\n", GetLastError()); ok(ret > strlen(device_name), "map_name should be longer than device_name\n"); @@ -141,7 +141,7 @@ index f6a7b69eca0..a8263a2f44b 100644 ok(memcmp(map_name, device_name, strlen(device_name)) == 0, "map name does not start with a device name: %s\n", map_name); SetLastError(0xdeadbeef); -@@ -592,7 +588,7 @@ static void test_GetProcessImageFileName(void) +@@ -604,7 +600,7 @@ static void test_GetProcessImageFileName(void) { /* Windows returns 2*strlen-1 */ ok(ret >= strlen(szImgPath), "szImgPath=\"%s\" ret=%d\n", szImgPath, ret); diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 6e38522a..752ef3b8 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -175,6 +175,7 @@ patch_enable_all () enable_ntdll_FileDispositionInformation="$1" enable_ntdll_FileFsFullSizeInformation="$1" enable_ntdll_Fix_Alignment="$1" + enable_ntdll_ForceBottomUpAlloc="$1" enable_ntdll_HashLinks="$1" enable_ntdll_Heap_Improvements="$1" enable_ntdll_Hide_Wine_Exports="$1" @@ -625,6 +626,9 @@ patch_enable () ntdll-Fix_Alignment) enable_ntdll_Fix_Alignment="$2" ;; + ntdll-ForceBottomUpAlloc) + enable_ntdll_ForceBottomUpAlloc="$2" + ;; ntdll-HashLinks) enable_ntdll_HashLinks="$2" ;; @@ -3863,6 +3867,33 @@ if test "$enable_ntdll_Fix_Alignment" -eq 1; then ) >> "$patchlist" fi +# Patchset ntdll-ForceBottomUpAlloc +# | +# | This patchset fixes the following Wine bugs: +# | * [#48175] AION (64 bit) - crashes in crysystem.dll.CryFree() due to high memory pointers allocated +# | * [#46568] 64-bit msxml6.dll from Microsoft Core XML Services 6.0 redist package fails to load (Wine doesn't respect +# | 44-bit user-mode VA limitation from Windows < 8.1) +# | +# | Modified files: +# | * dlls/ntdll/virtual.c +# | +if test "$enable_ntdll_ForceBottomUpAlloc" -eq 1; then + patch_apply ntdll-ForceBottomUpAlloc/0001-ntdll-Stop-search-on-mmap-error-in-try_map_free_area.patch + patch_apply ntdll-ForceBottomUpAlloc/0002-ntdll-Use-MAP_FIXED_NOREPLACE-flag-in-try_map_free_a.patch + patch_apply ntdll-ForceBottomUpAlloc/0003-ntdll-Force-bottom-up-allocation-order-for-64-bit-ar.patch + patch_apply ntdll-ForceBottomUpAlloc/0004-ntdll-Increase-step-after-failed-map-attempt-in-try_.patch + patch_apply ntdll-ForceBottomUpAlloc/0005-ntdll-Use-free-area-list-for-virtual-memory-allocati.patch + patch_apply ntdll-ForceBottomUpAlloc/0006-ntdll-Permanently-exclude-natively-mapped-areas-from.patch + ( + printf '%s\n' '+ { "Paul Gofman", "ntdll: Stop search on mmap() error in try_map_free_area().", 1 },'; + printf '%s\n' '+ { "Paul Gofman", "ntdll: Use MAP_FIXED_NOREPLACE flag in try_map_free_area() if available.", 1 },'; + printf '%s\n' '+ { "Paul Gofman", "ntdll: Force bottom up allocation order for 64 bit arch unless top down is requested.", 1 },'; + printf '%s\n' '+ { "Paul Gofman", "ntdll: Increase step after failed map attempt in try_map_free_area().", 1 },'; + printf '%s\n' '+ { "Paul Gofman", "ntdll: Use free area list for virtual memory allocation.", 1 },'; + printf '%s\n' '+ { "Paul Gofman", "ntdll: Permanently exclude natively mapped areas from free areas list.", 1 },'; + ) >> "$patchlist" +fi + # Patchset ntdll-HashLinks # | # | Modified files: