ntdll: Relocate dynamic base modules when mapping them.

This commit is contained in:
Alexandre Julliard 2023-10-05 10:43:02 +02:00
parent efd03f40e6
commit ec3de12825
3 changed files with 28 additions and 4 deletions

View file

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

View file

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

View file

@ -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 */