Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
221d5aba
Commit
221d5aba
authored
Aug 25, 2023
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
wow64: Reimplement syscall resolution using the syscall dispatcher name table.
parent
7ee9c196
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
46 additions
and
118 deletions
+46
-118
syscall.c
dlls/wow64/syscall.c
+46
-118
No files found.
dlls/wow64/syscall.c
View file @
221d5aba
...
...
@@ -644,98 +644,67 @@ NTSTATUS WINAPI wow64_NtWow64IsProcessorFeaturePresent( UINT *args )
/**********************************************************************
* get_syscall_num
*/
static
DWORD
get_syscall_num
(
const
BYTE
*
syscall
)
{
WORD
*
arm_syscall
=
(
WORD
*
)((
ULONG_PTR
)
syscall
&
~
1
);
DWORD
id
=
~
0u
;
if
(
!
syscall
)
return
id
;
switch
(
current_machine
)
{
case
IMAGE_FILE_MACHINE_I386
:
if
(
syscall
[
0
]
==
0xb8
&&
syscall
[
5
]
==
0xba
&&
syscall
[
10
]
==
0xff
&&
syscall
[
11
]
==
0xd2
)
id
=
*
(
DWORD
*
)(
syscall
+
1
);
break
;
case
IMAGE_FILE_MACHINE_ARMNT
:
if
(
*
arm_syscall
==
0xb40f
)
{
DWORD
inst
=
*
(
DWORD
*
)(
arm_syscall
+
1
);
id
=
((
inst
<<
1
)
&
0x0800
)
+
((
inst
<<
12
)
&
0xf000
)
+
((
inst
>>
20
)
&
0x0700
)
+
((
inst
>>
16
)
&
0x00ff
);
}
break
;
}
return
id
;
}
/**********************************************************************
* get_rva
*/
static
void
*
get_rva
(
const
IMAGE_NT_HEADERS
*
nt
,
HMODULE
module
,
DWORD
rva
,
IMAGE_SECTION_HEADER
**
section
,
BOOL
image
)
static
void
*
get_rva
(
HMODULE
module
,
DWORD
rva
)
{
if
(
image
)
return
(
void
*
)((
char
*
)
module
+
rva
);
return
RtlImageRvaToVa
(
nt
,
module
,
rva
,
section
);
return
(
void
*
)((
char
*
)
module
+
rva
);
}
/**********************************************************************
* init_syscall_table
*/
static
void
init_syscall_table
(
HMODULE
module
,
ULONG
idx
,
const
SYSTEM_SERVICE_TABLE
*
orig_table
,
BOOL
imag
e
)
static
void
init_syscall_table
(
HMODULE
module
,
void
*
dispatcher
,
const
SYSTEM_SERVICE_TABLE
*
orig_tabl
e
)
{
static
syscall_thunk
thunks
[
2048
];
static
ULONG
start_pos
;
const
IMAGE_NT_HEADERS
*
nt
=
RtlImageNtHeader
(
module
);
IMAGE_SECTION_HEADER
*
section
=
NULL
;
struct
syscall_info32
{
UINT
dispatcher
;
UINT
version
;
USHORT
id
;
USHORT
limit
;
/* USHORT names[limit]; */
/* BYTE args[limit]; */
}
*
info
=
dispatcher
;
const
USHORT
*
name_ptrs
=
(
const
USHORT
*
)(
info
+
1
);
const
IMAGE_EXPORT_DIRECTORY
*
exports
;
const
ULONG
*
functions
,
*
names
;
const
USHORT
*
ordinals
;
ULONG
id
,
exp_size
,
exp_pos
,
wrap_pos
,
max_pos
=
0
;
const
ULONG
*
names
;
ULONG
id
,
exp_size
,
wrap_pos
;
const
char
**
syscall_names
=
(
const
char
**
)
orig_table
->
CounterTable
;
exports
=
RtlImageDirectoryEntryToData
(
module
,
image
,
IMAGE_DIRECTORY_ENTRY_EXPORT
,
&
exp_size
);
ordinals
=
get_rva
(
nt
,
module
,
exports
->
AddressOfNameOrdinals
,
&
section
,
image
);
functions
=
get_rva
(
nt
,
module
,
exports
->
AddressOfFunctions
,
&
section
,
image
);
names
=
get_rva
(
nt
,
module
,
exports
->
AddressOfNames
,
&
section
,
image
);
for
(
exp_pos
=
wrap_pos
=
0
;
exp_pos
<
exports
->
NumberOfNames
;
exp_pos
++
)
if
(
info
->
version
!=
0xca110001
)
{
char
*
name
=
get_rva
(
nt
,
module
,
names
[
exp_pos
],
&
section
,
image
);
int
res
=
-
1
;
WARN
(
"invalid syscall table version %x
\n
"
,
info
->
version
);
return
;
}
if
(
syscall_tables
[
info
->
id
].
ServiceTable
)
return
;
/* already initialized */
if
(
strncmp
(
name
,
"Nt"
,
2
)
&&
strncmp
(
name
,
"wine"
,
4
)
&&
strncmp
(
name
,
"__wine"
,
6
))
continue
;
/* not a syscall */
exports
=
RtlImageDirectoryEntryToData
(
module
,
TRUE
,
IMAGE_DIRECTORY_ENTRY_EXPORT
,
&
exp_size
);
names
=
get_rva
(
module
,
exports
->
AddressOfNames
);
id
=
get_syscall_num
(
get_rva
(
nt
,
module
,
functions
[
ordinals
[
exp_pos
]],
&
section
,
image
));
if
(
id
==
~
0u
)
continue
;
/* not a syscall */
for
(
id
=
wrap_pos
=
0
;
id
<
info
->
limit
;
id
++
)
{
char
*
name
=
get_rva
(
module
,
names
[
name_ptrs
[
id
]]
);
int
res
=
-
1
;
if
(
wrap_pos
<
orig_table
->
ServiceLimit
)
res
=
strcmp
(
name
,
syscall_names
[
wrap_pos
]
);
if
(
!
res
)
/* got a match */
{
ULONG
table_idx
=
(
id
>>
12
)
&
3
,
table_pos
=
id
&
0xfff
;
if
(
table_idx
==
idx
)
{
if
(
start_pos
+
table_pos
<
ARRAY_SIZE
(
thunks
))
{
thunks
[
start_pos
+
table_pos
]
=
(
syscall_thunk
)
orig_table
->
ServiceTable
[
wrap_pos
++
];
max_pos
=
max
(
table_pos
,
max_pos
);
}
else
ERR
(
"invalid syscall id %04lx for %s
\n
"
,
id
,
name
);
}
else
ERR
(
"wrong syscall table id %04lx for %s
\n
"
,
id
,
name
);
if
(
start_pos
+
id
<
ARRAY_SIZE
(
thunks
))
thunks
[
start_pos
+
id
]
=
(
syscall_thunk
)
orig_table
->
ServiceTable
[
wrap_pos
++
];
else
ERR
(
"invalid syscall id %04lx for %s
\n
"
,
id
,
name
);
}
else
if
(
res
>
0
)
{
FIXME
(
"no export for syscall %s
\n
"
,
syscall_names
[
wrap_pos
]
);
wrap_pos
++
;
exp_pos
--
;
/* try again */
id
--
;
/* try again */
}
else
FIXME
(
"missing wrapper for syscall %04lx %s
\n
"
,
id
,
name
);
}
...
...
@@ -743,9 +712,9 @@ static void init_syscall_table( HMODULE module, ULONG idx, const SYSTEM_SERVICE_
for
(
;
wrap_pos
<
orig_table
->
ServiceLimit
;
wrap_pos
++
)
FIXME
(
"no export for syscall %s
\n
"
,
syscall_names
[
wrap_pos
]
);
syscall_tables
[
i
dx
].
ServiceTable
=
(
ULONG_PTR
*
)(
thunks
+
start_pos
);
syscall_tables
[
i
dx
].
ServiceLimit
=
max_pos
+
1
;
start_pos
+=
max_pos
+
1
;
syscall_tables
[
i
nfo
->
id
].
ServiceTable
=
(
ULONG_PTR
*
)(
thunks
+
start_pos
);
syscall_tables
[
i
nfo
->
id
].
ServiceLimit
=
info
->
limit
;
start_pos
+=
info
->
limit
;
}
...
...
@@ -754,59 +723,19 @@ static void init_syscall_table( HMODULE module, ULONG idx, const SYSTEM_SERVICE_
*/
void
init_image_mapping
(
HMODULE
module
)
{
void
*
*
ptr
=
RtlFindExportedRoutineByName
(
module
,
"Wow64Transition"
);
ULONG
*
ptr
=
RtlFindExportedRoutineByName
(
module
,
"Wow64Transition"
);
if
(
!
ptr
)
return
;
*
ptr
=
pBTCpuGetBopCode
(
);
*
ptr
=
PtrToUlong
(
pBTCpuGetBopCode
()
);
if
(
!
win32u_module
&&
RtlFindExportedRoutineByName
(
module
,
"NtUserInitializeClientPfnArrays"
))
{
win32u_module
=
module
;
init_syscall_table
(
win32u_module
,
1
,
psdwhwin32
,
TRUE
);
init_syscall_table
(
win32u_module
,
ptr
,
psdwhwin32
);
}
}
/**********************************************************************
* load_32bit_module
*/
static
HMODULE
load_32bit_module
(
const
WCHAR
*
name
,
WORD
machine
,
BOOL
image
)
{
NTSTATUS
status
;
OBJECT_ATTRIBUTES
attr
;
IO_STATUS_BLOCK
io
;
LARGE_INTEGER
size
;
UNICODE_STRING
str
;
SIZE_T
len
=
0
;
void
*
ptr
=
NULL
;
HANDLE
handle
,
mapping
;
WCHAR
path
[
MAX_PATH
];
const
WCHAR
*
dir
=
get_machine_wow64_dir
(
machine
);
swprintf
(
path
,
MAX_PATH
,
L"%s
\\
%s"
,
dir
,
name
);
RtlInitUnicodeString
(
&
str
,
path
);
InitializeObjectAttributes
(
&
attr
,
&
str
,
OBJ_CASE_INSENSITIVE
,
0
,
NULL
);
status
=
NtOpenFile
(
&
handle
,
GENERIC_READ
|
SYNCHRONIZE
,
&
attr
,
&
io
,
FILE_SHARE_READ
|
FILE_SHARE_DELETE
,
FILE_SYNCHRONOUS_IO_NONALERT
|
FILE_NON_DIRECTORY_FILE
);
if
(
status
)
return
NULL
;
size
.
QuadPart
=
0
;
status
=
NtCreateSection
(
&
mapping
,
STANDARD_RIGHTS_REQUIRED
|
SECTION_QUERY
|
SECTION_MAP_READ
|
SECTION_MAP_EXECUTE
,
NULL
,
&
size
,
PAGE_EXECUTE_READ
,
image
?
SEC_IMAGE
:
SEC_COMMIT
,
handle
);
NtClose
(
handle
);
if
(
status
)
return
NULL
;
status
=
NtMapViewOfSection
(
mapping
,
NtCurrentProcess
(),
&
ptr
,
0
,
0
,
NULL
,
&
len
,
ViewShare
,
0
,
PAGE_EXECUTE_READ
);
NtClose
(
mapping
);
if
(
!
NT_SUCCESS
(
status
))
ptr
=
NULL
;
return
ptr
;
}
/**********************************************************************
* load_64bit_module
*/
static
HMODULE
load_64bit_module
(
const
WCHAR
*
name
)
...
...
@@ -875,9 +804,10 @@ static const WCHAR *get_cpu_dll_name(void)
static
DWORD
WINAPI
process_init
(
RTL_RUN_ONCE
*
once
,
void
*
param
,
void
**
context
)
{
PEB32
*
peb32
;
HMODULE
module
,
ntdll
;
HMODULE
module
;
UNICODE_STRING
str
=
RTL_CONSTANT_STRING
(
L"ntdll.dll"
);
SYSTEM_BASIC_INFORMATION
info
;
ULONG
*
p__wine_syscall_dispatcher
,
*
p__wine_unix_call_dispatcher
;
RtlWow64GetProcessMachines
(
GetCurrentProcess
(),
&
current_machine
,
&
native_machine
);
if
(
!
current_machine
)
current_machine
=
native_machine
;
...
...
@@ -924,16 +854,14 @@ static DWORD WINAPI process_init( RTL_RUN_ONCE *once, void *param, void **contex
module
=
(
HMODULE
)(
ULONG_PTR
)
pLdrSystemDllInitBlock
->
ntdll_handle
;
init_image_mapping
(
module
);
*
(
void
**
)
RtlFindExportedRoutineByName
(
module
,
"__wine_syscall_dispatcher"
)
=
pBTCpuGetBopCode
();
*
(
void
**
)
RtlFindExportedRoutineByName
(
module
,
"__wine_unix_call_dispatcher"
)
=
p__wine_get_unix_opcode
();
GET_PTR
(
KiRaiseUserExceptionDispatcher
);
GET_PTR
(
__wine_syscall_dispatcher
);
GET_PTR
(
__wine_unix_call_dispatcher
);
if
((
ntdll
=
load_32bit_module
(
L"ntdll.dll"
,
current_machine
,
FALSE
)))
{
init_syscall_table
(
ntdll
,
0
,
&
ntdll_syscall_table
,
FALSE
);
NtUnmapViewOfSection
(
NtCurrentProcess
(),
ntdll
);
}
else
init_syscall_table
(
module
,
0
,
&
ntdll_syscall_table
,
TRUE
);
*
p__wine_syscall_dispatcher
=
PtrToUlong
(
pBTCpuGetBopCode
()
);
*
p__wine_unix_call_dispatcher
=
PtrToUlong
(
p__wine_get_unix_opcode
()
);
init_syscall_table
(
module
,
p__wine_syscall_dispatcher
,
&
ntdll_syscall_table
);
init_file_redirects
();
return
TRUE
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment