Module: wine Branch: master Commit: 8f507ff9a77cc369fc7020a9c0ef0d48c0e0b547 URL: https://gitlab.winehq.org/wine/wine/-/commit/8f507ff9a77cc369fc7020a9c0ef0d4...
Author: Alexandre Julliard julliard@winehq.org Date: Tue Oct 31 13:07:07 2023 +0100
ntdll: Also update code ranges for pure ARM64EC binaries.
---
dlls/ntdll/unix/virtual.c | 90 ++++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 44 deletions(-)
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 2c2000751e5..464f343a575 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -2461,6 +2461,34 @@ static void alloc_arm64ec_map(void) }
+/*********************************************************************** + * update_arm64ec_ranges + */ +static void update_arm64ec_ranges( struct file_view *view, IMAGE_NT_HEADERS *nt, + const IMAGE_DATA_DIRECTORY *dir ) +{ + const IMAGE_ARM64EC_METADATA *metadata; + const IMAGE_CHPE_RANGE_ENTRY *map; + char *base = view->base; + const IMAGE_LOAD_CONFIG_DIRECTORY *cfg = (void *)(base + dir->VirtualAddress); + ULONG i, size = min( dir->Size, cfg->Size ); + + if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY, CHPEMetadataPointer )) return; + if (!cfg->CHPEMetadataPointer) return; + if (!arm64ec_view) alloc_arm64ec_map(); + commit_arm64ec_map( view ); + metadata = (void *)(base + (cfg->CHPEMetadataPointer - nt->OptionalHeader.ImageBase)); + if (!metadata->CodeMap) return; + map = (void *)(base + metadata->CodeMap); + + for (i = 0; i < metadata->CodeMapCount; i++) + { + if ((map[i].StartOffset & 0x3) != 1 /* arm64ec */) continue; + set_arm64ec_range( base + (map[i].StartOffset & ~3), map[i].Length ); + } +} + + /*********************************************************************** * apply_arm64x_relocations */ @@ -2506,44 +2534,13 @@ static void apply_arm64x_relocations( char *base, const IMAGE_BASE_RELOCATION *r * update_arm64x_mapping */ static void update_arm64x_mapping( struct file_view *view, IMAGE_NT_HEADERS *nt, - IMAGE_SECTION_HEADER *sections ) + const IMAGE_DATA_DIRECTORY *dir, IMAGE_SECTION_HEADER *sections ) { - ULONG i, size, sec, offset; - const IMAGE_DATA_DIRECTORY *dir; - const IMAGE_LOAD_CONFIG_DIRECTORY *cfg; - const IMAGE_ARM64EC_METADATA *metadata; const IMAGE_DYNAMIC_RELOCATION_TABLE *table; const char *ptr, *end; char *base = view->base; - - /* retrieve config directory */ - - if (nt->FileHeader.Machine != IMAGE_FILE_MACHINE_ARM64) return; - if (nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) return; - dir = nt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG; - if (!dir->VirtualAddress || !dir->Size) return; - cfg = (void *)(base + dir->VirtualAddress); - size = min( dir->Size, cfg->Size ); - - /* update code ranges */ - - if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY, CHPEMetadataPointer )) return; - if (!cfg->CHPEMetadataPointer) return; - if (!arm64ec_view) alloc_arm64ec_map(); - commit_arm64ec_map( view ); - metadata = (void *)(base + (cfg->CHPEMetadataPointer - nt->OptionalHeader.ImageBase)); - if (metadata->CodeMap) - { - const IMAGE_CHPE_RANGE_ENTRY *map = (void *)(base + metadata->CodeMap); - - for (i = 0; i < metadata->CodeMapCount; i++) - { - if ((map[i].StartOffset & 0x3) != 1 /* arm64ec */) continue; - set_arm64ec_range( base + (map[i].StartOffset & ~3), map[i].Length ); - } - } - - /* apply dynamic relocations */ + const IMAGE_LOAD_CONFIG_DIRECTORY *cfg = (void *)(base + dir->VirtualAddress); + ULONG sec, offset, size = min( dir->Size, cfg->Size );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY, DynamicValueRelocTableSection )) return; offset = cfg->DynamicValueRelocTableOffset; @@ -2687,7 +2684,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, *relocs; + IMAGE_DATA_DIRECTORY *imports, *dir; NTSTATUS status = STATUS_CONFLICTING_ADDRESSES; int i; off_t pos; @@ -2838,13 +2835,18 @@ static NTSTATUS map_image_into_view( struct file_view *view, const WCHAR *filena }
#ifdef __aarch64__ - if (machine == IMAGE_FILE_MACHINE_AMD64 || - (!machine && main_image_info.Machine == IMAGE_FILE_MACHINE_AMD64)) + if ((dir = get_data_dir( nt, total_size, IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG ))) { - update_arm64x_mapping( view, nt, sections ); - /* reload changed data from NT header */ - image_info->machine = nt->FileHeader.Machine; - image_info->entry_point = nt->OptionalHeader.AddressOfEntryPoint; + if (image_info->machine == IMAGE_FILE_MACHINE_ARM64 && + (machine == IMAGE_FILE_MACHINE_AMD64 || + (!machine && main_image_info.Machine == IMAGE_FILE_MACHINE_AMD64))) + { + update_arm64x_mapping( view, nt, dir, sections ); + /* reload changed data from NT header */ + image_info->machine = nt->FileHeader.Machine; + image_info->entry_point = nt->OptionalHeader.AddressOfEntryPoint; + } + if (image_info->machine == IMAGE_FILE_MACHINE_AMD64) update_arm64ec_ranges( view, nt, dir ); } #endif if (machine && machine != nt->FileHeader.Machine) return STATUS_NOT_SUPPORTED; @@ -2861,10 +2863,10 @@ static NTSTATUS map_image_into_view( struct file_view *view, const WCHAR *filena else ((IMAGE_NT_HEADERS32 *)nt)->OptionalHeader.ImageBase = image_info->map_addr;
- if ((relocs = get_data_dir( nt, total_size, IMAGE_DIRECTORY_ENTRY_BASERELOC ))) + if ((dir = 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); + IMAGE_BASE_RELOCATION *rel = (IMAGE_BASE_RELOCATION *)(ptr + dir->VirtualAddress); + IMAGE_BASE_RELOCATION *end = (IMAGE_BASE_RELOCATION *)((char *)rel + dir->Size);
while (rel && rel < end - 1 && rel->SizeOfBlock && rel->VirtualAddress < total_size) rel = process_relocation_block( ptr + rel->VirtualAddress, rel, delta );