Module: wine Branch: master Commit: 06b729f7773243a76fb2df3c1bfe53b39819da5f URL: https://source.winehq.org/git/wine.git/?a=commit;h=06b729f7773243a76fb2df3c1...
Author: Alexandre Julliard julliard@winehq.org Date: Thu Feb 25 12:37:37 2021 +0100
ntdll: Relocate the PE ntdll if necessary.
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ntdll/unix/loader.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index c4f897f3d0d..d03034f35fc 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -891,6 +891,98 @@ static void load_ntdll_functions( HMODULE module ) #undef SET_PTR }
+/* reimplementation of LdrProcessRelocationBlock */ +static IMAGE_BASE_RELOCATION *process_relocation_block( void *module, IMAGE_BASE_RELOCATION *rel, + INT_PTR delta ) +{ + char *page = get_rva( module, rel->VirtualAddress ); + UINT count = (rel->SizeOfBlock - sizeof(*rel)) / sizeof(USHORT); + USHORT *relocs = (USHORT *)(rel + 1); + + while (count--) + { + USHORT offset = *relocs & 0xfff; + switch (*relocs >> 12) + { + case IMAGE_REL_BASED_ABSOLUTE: + break; + case IMAGE_REL_BASED_HIGH: + *(short *)(page + offset) += HIWORD(delta); + break; + case IMAGE_REL_BASED_LOW: + *(short *)(page + offset) += LOWORD(delta); + break; + case IMAGE_REL_BASED_HIGHLOW: + *(int *)(page + offset) += delta; + break; +#ifdef _WIN64 + case IMAGE_REL_BASED_DIR64: + *(INT_PTR *)(page + offset) += delta; + break; +#elif defined(__arm__) + case IMAGE_REL_BASED_THUMB_MOV32: + { + DWORD *inst = (DWORD *)(page + offset); + WORD lo = ((inst[0] << 1) & 0x0800) + ((inst[0] << 12) & 0xf000) + + ((inst[0] >> 20) & 0x0700) + ((inst[0] >> 16) & 0x00ff); + WORD hi = ((inst[1] << 1) & 0x0800) + ((inst[1] << 12) & 0xf000) + + ((inst[1] >> 20) & 0x0700) + ((inst[1] >> 16) & 0x00ff); + DWORD imm = MAKELONG( lo, hi ) + delta; + + lo = LOWORD( imm ); + hi = HIWORD( imm ); + inst[0] = (inst[0] & 0x8f00fbf0) + ((lo >> 1) & 0x0400) + ((lo >> 12) & 0x000f) + + ((lo << 20) & 0x70000000) + ((lo << 16) & 0xff0000); + inst[1] = (inst[1] & 0x8f00fbf0) + ((hi >> 1) & 0x0400) + ((hi >> 12) & 0x000f) + + ((hi << 20) & 0x70000000) + ((hi << 16) & 0xff0000); + break; + } +#endif + default: + FIXME("Unknown/unsupported relocation %x\n", *relocs); + return NULL; + } + relocs++; + } + return (IMAGE_BASE_RELOCATION *)relocs; /* return address of next block */ +} + +static void relocate_ntdll( void *module ) +{ + IMAGE_DOS_HEADER *dos = module; + IMAGE_NT_HEADERS *nt = (IMAGE_NT_HEADERS *)((char *)dos + dos->e_lfanew); + IMAGE_DATA_DIRECTORY *relocs = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; + IMAGE_BASE_RELOCATION *rel, *end; + IMAGE_SECTION_HEADER *sec; + ULONG protect_old[96], i; + INT_PTR delta; + + ERR( "ntdll could not be mapped at preferred address (%p/%p), expect trouble\n", + module, (void *)nt->OptionalHeader.ImageBase ); + + if (!relocs->Size || !relocs->VirtualAddress) return; + + sec = (IMAGE_SECTION_HEADER *)((char *)&nt->OptionalHeader + nt->FileHeader.SizeOfOptionalHeader); + for (i = 0; i < nt->FileHeader.NumberOfSections; i++) + { + void *addr = get_rva( module, sec[i].VirtualAddress ); + SIZE_T size = sec[i].SizeOfRawData; + NtProtectVirtualMemory( NtCurrentProcess(), &addr, &size, PAGE_READWRITE, &protect_old[i] ); + } + + rel = get_rva( module, relocs->VirtualAddress ); + end = get_rva( module, relocs->VirtualAddress + relocs->Size ); + delta = (char *)module - (char *)nt->OptionalHeader.ImageBase; + while (rel && rel < end - 1 && rel->SizeOfBlock) rel = process_relocation_block( module, rel, delta ); + + for (i = 0; i < nt->FileHeader.NumberOfSections; i++) + { + void *addr = get_rva( module, sec[i].VirtualAddress ); + SIZE_T size = sec[i].SizeOfRawData; + NtProtectVirtualMemory( NtCurrentProcess(), &addr, &size, protect_old[i], &protect_old[i] ); + } +} +
static void *callback_module;
@@ -1534,8 +1626,11 @@ static void load_ntdll(void) status = open_builtin_file( name, &attr, &mapping, &module, &info, &st, FALSE ); if (!status && !module) { - status = map_builtin_module( mapping, &module, &st ); - NtClose( mapping ); + SIZE_T len = 0; + status = NtMapViewOfSection( mapping, NtCurrentProcess(), &module, 0, 0, NULL, &len, + ViewShare, 0, PAGE_EXECUTE_READ ); + if (status == STATUS_IMAGE_NOT_AT_BASE) relocate_ntdll( module ); + status = add_builtin_module( module, NULL, &st ); } if (status) fatal_error( "failed to load %s error %x\n", name, status ); free( name );