Module: wine Branch: master Commit: ec3de128257a8ceb0637fae9d9fd2b067bb0e0d8 URL: https://gitlab.winehq.org/wine/wine/-/commit/ec3de128257a8ceb0637fae9d9fd2b0...
Author: Alexandre Julliard julliard@winehq.org Date: Thu Oct 5 10:43:02 2023 +0200
ntdll: Relocate dynamic base modules when mapping them.
---
dlls/kernel32/tests/loader.c | 4 ++-- dlls/ntdll/unix/virtual.c | 25 ++++++++++++++++++++++++- server/mapping.c | 3 ++- 3 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c index c250fc5d52d..ec6f2d5c6a7 100644 --- a/dlls/kernel32/tests/loader.c +++ b/dlls/kernel32/tests/loader.c @@ -2379,7 +2379,7 @@ static void test_import_resolution(void) offset.QuadPart = 0; status = pNtMapViewOfSection( mapping, GetCurrentProcess(), (void **)&mod, 0, 0, &offset, &size, 1 /* ViewShare */, 0, PAGE_READONLY ); - todo_wine_if (test < 6) + todo_wine_if (test == 5) ok( status == (test == 6 ? STATUS_IMAGE_NOT_AT_BASE : STATUS_SUCCESS), "NtMapViewOfSection failed %lx\n", status ); ok( mod != (void *)nt.OptionalHeader.ImageBase, "loaded at image base %p\n", mod ); @@ -2392,7 +2392,7 @@ static void test_import_resolution(void) "tls relocated %p / %p\n", (void *)ptr->tls.StartAddressOfRawData, (char *)nt.OptionalHeader.ImageBase + DATA_RVA( data.tls_data )); } - else todo_wine + else todo_wine_if (test == 5) { ok( (void *)pnt->OptionalHeader.ImageBase == mod, "not at base %p / %p\n", (void *)pnt->OptionalHeader.ImageBase, mod ); diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index c017b45fc1e..855aa9cd1eb 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -2687,7 +2687,7 @@ static NTSTATUS map_image_into_view( struct file_view *view, const WCHAR *filena IMAGE_NT_HEADERS *nt; IMAGE_SECTION_HEADER sections[96]; IMAGE_SECTION_HEADER *sec; - IMAGE_DATA_DIRECTORY *imports; + IMAGE_DATA_DIRECTORY *imports, *relocs; NTSTATUS status = STATUS_CONFLICTING_ADDRESSES; int i; off_t pos; @@ -2695,6 +2695,7 @@ static NTSTATUS map_image_into_view( struct file_view *view, const WCHAR *filena char *header_end; char *ptr = view->base; SIZE_T header_size, total_size = view->size; + INT_PTR delta;
TRACE_(module)( "mapping PE file %s at %p-%p\n", debugstr_w(filename), ptr, ptr + total_size );
@@ -2848,6 +2849,28 @@ static NTSTATUS map_image_into_view( struct file_view *view, const WCHAR *filena #endif if (machine && machine != nt->FileHeader.Machine) return STATUS_NOT_SUPPORTED;
+ /* relocate to dynamic base */ + + if (image_info->map_addr && (delta = image_info->map_addr - image_info->base)) + { + TRACE_(module)( "relocating %s dynamic base %lx -> %lx mapped at %p\n", debugstr_w(filename), + (ULONG_PTR)image_info->base, (ULONG_PTR)image_info->map_addr, ptr ); + + if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) + ((IMAGE_NT_HEADERS64 *)nt)->OptionalHeader.ImageBase = image_info->map_addr; + else + ((IMAGE_NT_HEADERS32 *)nt)->OptionalHeader.ImageBase = image_info->map_addr; + + if ((relocs = get_data_dir( nt, total_size, IMAGE_DIRECTORY_ENTRY_BASERELOC ))) + { + IMAGE_BASE_RELOCATION *rel = (IMAGE_BASE_RELOCATION *)(ptr + relocs->VirtualAddress); + IMAGE_BASE_RELOCATION *end = (IMAGE_BASE_RELOCATION *)((char *)rel + relocs->Size); + + while (rel && rel < end - 1 && rel->SizeOfBlock && rel->VirtualAddress < total_size) + rel = process_relocation_block( ptr + rel->VirtualAddress, rel, delta ); + } + } + /* set the image protections */
set_vprot( view, ptr, ROUND_SIZE( 0, header_size ), VPROT_COMMITTED | VPROT_READ ); diff --git a/server/mapping.c b/server/mapping.c index 41585b35924..c570bcf8f94 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -1407,7 +1407,8 @@ DECL_HANDLER(map_image_view) view->image.entry_point = req->entry; add_process_view( current, view );
- if (view->base != mapping->image.base) set_error( STATUS_IMAGE_NOT_AT_BASE ); + if (view->base != (mapping->image.map_addr ? mapping->image.map_addr : mapping->image.base)) + set_error( STATUS_IMAGE_NOT_AT_BASE ); if (view->image.machine != current->process->machine) { /* on 32-bit, the native 64-bit machine is allowed */