ntdll: Redirect the module entry point for ARM64EC modules.

This commit is contained in:
Alexandre Julliard 2024-02-08 14:00:20 +01:00
parent e05c6c8211
commit 8c703f3e2f
4 changed files with 15 additions and 17 deletions

View file

@ -275,7 +275,6 @@ static void test_process_machine( HANDLE process, HANDLE thread,
win32_entry is the redirected x86-64 -> ARM64EC one */
ok( image.TransferAddress != entry_point, "wrong entry %p\n", image.TransferAddress );
ok( image.TransferAddress != win32_entry, "wrong entry %p\n", image.TransferAddress );
todo_wine
ok( win32_entry != entry_point, "wrong win32 entry %p\n", win32_entry );
}
}

View file

@ -1585,24 +1585,23 @@ static void load_ntdll_wow64_functions( HMODULE module )
/***********************************************************************
* redirect_arm64ec_ptr
* redirect_arm64ec_rva
*
* Redirect a function pointer through the arm64ec redirection table.
* Redirect an address through the arm64ec redirection table.
*/
static void *redirect_arm64ec_ptr( void *module, void *ptr,
const IMAGE_ARM64EC_REDIRECTION_ENTRY *map, ULONG map_count )
ULONG_PTR redirect_arm64ec_rva( void *base, ULONG_PTR rva, const IMAGE_ARM64EC_METADATA *metadata )
{
int min = 0, max = map_count - 1;
ULONG_PTR rva = (char *)ptr - (char *)module;
const IMAGE_ARM64EC_REDIRECTION_ENTRY *map = get_rva( base, metadata->RedirectionMetadata );
int min = 0, max = metadata->RedirectionMetadataCount - 1;
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) return map[pos].Destination;
if (map[pos].Source < rva) min = pos + 1;
else max = pos - 1;
}
return ptr;
return rva;
}
@ -1615,13 +1614,11 @@ 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 )
p##name = get_rva( module, redirect_arm64ec_rva( module, (char *)p##name - (char *)module, metadata ))
REDIRECT( DbgUiRemoteBreakin );
REDIRECT( KiRaiseUserExceptionDispatcher );
REDIRECT( KiUserExceptionDispatcher );

View file

@ -191,6 +191,7 @@ extern BOOL is_builtin_path( const UNICODE_STRING *path, WORD *machine );
extern NTSTATUS load_main_exe( const WCHAR *name, const char *unix_name, const WCHAR *curdir,
USHORT load_machine, WCHAR **image, void **module );
extern NTSTATUS load_start_exe( WCHAR **image, void **module );
extern ULONG_PTR redirect_arm64ec_rva( void *module, ULONG_PTR rva, const IMAGE_ARM64EC_METADATA *metadata );
extern void start_server( BOOL debug );
extern unsigned int server_call_unlocked( void *req_ptr );

View file

@ -2488,7 +2488,7 @@ 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_DATA_DIRECTORY *dir, UINT *entry_point )
{
const IMAGE_ARM64EC_METADATA *metadata;
const IMAGE_CHPE_RANGE_ENTRY *map;
@ -2501,6 +2501,7 @@ static void update_arm64ec_ranges( struct file_view *view, IMAGE_NT_HEADERS *nt,
if (!arm64ec_view) alloc_arm64ec_map();
commit_arm64ec_map( view );
metadata = (void *)(base + (cfg->CHPEMetadataPointer - nt->OptionalHeader.ImageBase));
*entry_point = redirect_arm64ec_rva( base, nt->OptionalHeader.AddressOfEntryPoint, metadata );
if (!metadata->CodeMap) return;
map = (void *)(base + metadata->CodeMap);
@ -2865,11 +2866,11 @@ static NTSTATUS map_image_into_view( struct file_view *view, const WCHAR *filena
(!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;
/* reload changed machine from NT header */
image_info->machine = nt->FileHeader.Machine;
}
if (image_info->machine == IMAGE_FILE_MACHINE_AMD64) update_arm64ec_ranges( view, nt, dir );
if (image_info->machine == IMAGE_FILE_MACHINE_AMD64)
update_arm64ec_ranges( view, nt, dir, &image_info->entry_point );
}
#endif
if (machine && machine != nt->FileHeader.Machine) return STATUS_NOT_SUPPORTED;