Module: wine Branch: master Commit: 406016536703f084b950b62f0dae714c1c11bb53 URL: https://gitlab.winehq.org/wine/wine/-/commit/406016536703f084b950b62f0dae714...
Author: Alexandre Julliard julliard@winehq.org Date: Wed Nov 15 15:00:29 2023 +0100
ntdll: Redirect PE function pointers through the ARM64EC redirection map.
---
dlls/ntdll/unix/loader.c | 50 ++++++++++++++++++++++++++++++++++++++++++ dlls/ntdll/unix/unix_private.h | 8 ++++++- 2 files changed, 57 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index b7a18f94950..5b6098df3bc 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -1819,6 +1819,55 @@ static void load_ntdll_wow64_functions( HMODULE module ) }
+/*********************************************************************** + * redirect_arm64ec_ptr + * + * Redirect a function pointer through the arm64ec redirection table. + */ +static void *redirect_arm64ec_ptr( void *module, void *ptr, + const IMAGE_ARM64EC_REDIRECTION_ENTRY *map, ULONG map_count ) +{ + int min = 0, max = map_count - 1; + ULONG_PTR rva = (char *)ptr - (char *)module; + + while (min <= max) + { + int pos = (min + max) / 2; + if (map[pos].Source == rva) return get_rva( module, map[pos].Destination ); + if (map[pos].Source < rva) min = pos + 1; + else max = pos - 1; + } + return ptr; +} + + +/*********************************************************************** + * redirect_ntdll_functions + * + * Redirect ntdll functions on arm64ec. + */ +static void redirect_ntdll_functions( HMODULE module ) +{ + const IMAGE_LOAD_CONFIG_DIRECTORY *loadcfg; + const IMAGE_ARM64EC_METADATA *metadata; + const IMAGE_ARM64EC_REDIRECTION_ENTRY *map; + + if (!(loadcfg = get_module_data_dir( module, IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, NULL ))) return; + if (!(metadata = (void *)loadcfg->CHPEMetadataPointer)) return; + if (!(map = get_rva( module, metadata->RedirectionMetadata ))) return; +#define REDIRECT(name) \ + p##name = redirect_arm64ec_ptr( module, p##name, map, metadata->RedirectionMetadataCount ) + REDIRECT( DbgUiRemoteBreakin ); + REDIRECT( KiRaiseUserExceptionDispatcher ); + REDIRECT( KiUserExceptionDispatcher ); + REDIRECT( KiUserApcDispatcher ); + REDIRECT( KiUserCallbackDispatcher ); + REDIRECT( LdrInitializeThunk ); + REDIRECT( RtlUserThreadStart ); +#undef REDIRECT +} + + /*********************************************************************** * load_ntdll */ @@ -1851,6 +1900,7 @@ static void load_ntdll(void) if (status) fatal_error( "failed to load %s error %x\n", name, status ); free( name ); load_ntdll_functions( module ); + if (is_arm64ec()) redirect_ntdll_functions( module ); }
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index d9d830a7462..f15efa45d14 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -64,6 +64,7 @@ static inline TEB64 *NtCurrentTeb64(void) { return (TEB64 *)NtCurrentTeb()->GdiB
extern WOW_PEB *wow_peb DECLSPEC_HIDDEN; extern ULONG_PTR user_space_wow_limit DECLSPEC_HIDDEN; +extern SECTION_IMAGE_INFORMATION main_image_info DECLSPEC_HIDDEN;
static inline WOW_TEB *get_wow_teb( TEB *teb ) { @@ -81,6 +82,12 @@ static inline BOOL is_old_wow64(void) return !is_win64 && wow_peb; }
+static inline BOOL is_arm64ec(void) +{ + return (current_machine == IMAGE_FILE_MACHINE_ARM64 && + main_image_info.Machine == IMAGE_FILE_MACHINE_AMD64); +} + /* thread private data, stored in NtCurrentTeb()->GdiTebBatch */ struct ntdll_thread_data { @@ -152,7 +159,6 @@ extern USHORT *uctable DECLSPEC_HIDDEN; extern USHORT *lctable DECLSPEC_HIDDEN; extern SIZE_T startup_info_size DECLSPEC_HIDDEN; extern BOOL is_prefix_bootstrap DECLSPEC_HIDDEN; -extern SECTION_IMAGE_INFORMATION main_image_info DECLSPEC_HIDDEN; extern int main_argc DECLSPEC_HIDDEN; extern char **main_argv DECLSPEC_HIDDEN; extern char **main_envp DECLSPEC_HIDDEN;