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
f4e58868
Commit
f4e58868
authored
May 23, 2013
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Make the entire relay entry point routine CPU-specific.
parent
1f47580e
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
166 additions
and
125 deletions
+166
-125
relay.c
dlls/ntdll/relay.c
+166
-125
No files found.
dlls/ntdll/relay.c
View file @
f4e58868
...
...
@@ -320,8 +320,68 @@ static inline void RELAY_PrintArgs( const INT_PTR *args, int nb_args, unsigned i
}
}
extern
LONGLONG
CDECL
call_entry_point
(
void
*
func
,
int
nb_args
,
const
INT_PTR
*
args
,
int
flags
);
static
void
print_timestamp
(
void
)
{
ULONG
ticks
=
NtGetTickCount
();
DPRINTF
(
"%3u.%03u:"
,
ticks
/
1000
,
ticks
%
1000
);
}
/***********************************************************************
* relay_trace_entry
*
* stack points to the return address, i.e. the first argument is stack[1].
*/
void
*
WINAPI
relay_trace_entry
(
struct
relay_descr
*
descr
,
unsigned
int
idx
,
const
INT_PTR
*
stack
)
{
WORD
ordinal
=
LOWORD
(
idx
);
BYTE
nb_args
=
LOBYTE
(
HIWORD
(
idx
));
struct
relay_private_data
*
data
=
descr
->
private
;
struct
relay_entry_point
*
entry_point
=
data
->
entry_points
+
ordinal
;
if
(
TRACE_ON
(
relay
))
{
if
(
TRACE_ON
(
timestamp
))
print_timestamp
();
if
(
entry_point
->
name
)
DPRINTF
(
"%04x:Call %s.%s("
,
GetCurrentThreadId
(),
data
->
dllname
,
entry_point
->
name
);
else
DPRINTF
(
"%04x:Call %s.%u("
,
GetCurrentThreadId
(),
data
->
dllname
,
data
->
base
+
ordinal
);
RELAY_PrintArgs
(
stack
+
1
,
nb_args
,
descr
->
arg_types
[
ordinal
]
);
DPRINTF
(
") ret=%08lx
\n
"
,
stack
[
0
]
);
}
return
entry_point
->
orig_func
;
}
/***********************************************************************
* relay_trace_exit
*/
void
WINAPI
relay_trace_exit
(
struct
relay_descr
*
descr
,
unsigned
int
idx
,
const
INT_PTR
*
stack
,
LONGLONG
retval
)
{
WORD
ordinal
=
LOWORD
(
idx
);
BYTE
flags
=
HIBYTE
(
HIWORD
(
idx
));
struct
relay_private_data
*
data
=
descr
->
private
;
struct
relay_entry_point
*
entry_point
=
data
->
entry_points
+
ordinal
;
if
(
!
TRACE_ON
(
relay
))
return
;
if
(
TRACE_ON
(
timestamp
))
print_timestamp
();
if
(
entry_point
->
name
)
DPRINTF
(
"%04x:Ret %s.%s()"
,
GetCurrentThreadId
(),
data
->
dllname
,
entry_point
->
name
);
else
DPRINTF
(
"%04x:Ret %s.%u()"
,
GetCurrentThreadId
(),
data
->
dllname
,
data
->
base
+
ordinal
);
if
(
flags
&
1
)
/* 64-bit return value */
DPRINTF
(
" retval=%08x%08x ret=%08lx
\n
"
,
(
UINT
)(
retval
>>
32
),
(
UINT
)
retval
,
stack
[
0
]
);
else
DPRINTF
(
" retval=%08lx ret=%08lx
\n
"
,
(
UINT_PTR
)
retval
,
stack
[
0
]
);
}
#ifdef __i386__
extern
LONGLONG
CDECL
call_entry_point
(
void
*
func
,
int
nb_args
,
const
INT_PTR
*
args
,
int
flags
);
__ASM_GLOBAL_FUNC
(
call_entry_point
,
"pushl %ebp
\n\t
"
__ASM_CFI
(
".cfi_adjust_cfa_offset 4
\n\t
"
)
...
...
@@ -355,7 +415,84 @@ __ASM_GLOBAL_FUNC( call_entry_point,
__ASM_CFI
(
".cfi_def_cfa %esp,4
\n\t
"
)
__ASM_CFI
(
".cfi_same_value %ebp
\n\t
"
)
"ret"
)
static
LONGLONG
WINAPI
relay_call
(
struct
relay_descr
*
descr
,
unsigned
int
idx
,
const
INT_PTR
*
stack
)
{
BYTE
nb_args
=
LOBYTE
(
HIWORD
(
idx
));
BYTE
flags
=
HIBYTE
(
HIWORD
(
idx
));
void
*
func
=
relay_trace_entry
(
descr
,
idx
,
stack
);
LONGLONG
ret
=
call_entry_point
(
func
,
nb_args
,
stack
+
1
,
flags
);
relay_trace_exit
(
descr
,
idx
,
stack
,
ret
);
return
ret
;
}
void
WINAPI
__regs_relay_call_regs
(
struct
relay_descr
*
descr
,
unsigned
int
idx
,
unsigned
int
orig_eax
,
unsigned
int
ret_addr
,
CONTEXT
*
context
)
{
WORD
ordinal
=
LOWORD
(
idx
);
BYTE
nb_args
=
LOBYTE
(
HIWORD
(
idx
));
struct
relay_private_data
*
data
=
descr
->
private
;
struct
relay_entry_point
*
entry_point
=
data
->
entry_points
+
ordinal
;
BYTE
*
orig_func
=
entry_point
->
orig_func
;
INT_PTR
*
args
=
(
INT_PTR
*
)
context
->
Esp
;
INT_PTR
args_copy
[
32
];
/* restore the context to what it was before the relay thunk */
context
->
Eax
=
orig_eax
;
context
->
Eip
=
ret_addr
;
context
->
Esp
+=
nb_args
*
sizeof
(
int
);
if
(
TRACE_ON
(
relay
))
{
if
(
entry_point
->
name
)
DPRINTF
(
"%04x:Call %s.%s("
,
GetCurrentThreadId
(),
data
->
dllname
,
entry_point
->
name
);
else
DPRINTF
(
"%04x:Call %s.%u("
,
GetCurrentThreadId
(),
data
->
dllname
,
data
->
base
+
ordinal
);
RELAY_PrintArgs
(
args
,
nb_args
,
descr
->
arg_types
[
ordinal
]
);
DPRINTF
(
") ret=%08x
\n
"
,
ret_addr
);
DPRINTF
(
"%04x: eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x "
"ebp=%08x esp=%08x ds=%04x es=%04x fs=%04x gs=%04x flags=%08x
\n
"
,
GetCurrentThreadId
(),
context
->
Eax
,
context
->
Ebx
,
context
->
Ecx
,
context
->
Edx
,
context
->
Esi
,
context
->
Edi
,
context
->
Ebp
,
context
->
Esp
,
context
->
SegDs
,
context
->
SegEs
,
context
->
SegFs
,
context
->
SegGs
,
context
->
EFlags
);
assert
(
orig_func
[
0
]
==
0x68
/* pushl func */
);
assert
(
orig_func
[
5
]
==
0x6a
/* pushl args */
);
assert
(
orig_func
[
7
]
==
0xe8
/* call */
);
}
/* now call the real function */
memcpy
(
args_copy
,
args
,
nb_args
*
sizeof
(
args
[
0
])
);
args_copy
[
nb_args
++
]
=
(
INT_PTR
)
context
;
/* append context argument */
call_entry_point
(
orig_func
+
12
+
*
(
int
*
)(
orig_func
+
1
),
nb_args
,
args_copy
,
0
);
if
(
TRACE_ON
(
relay
))
{
if
(
entry_point
->
name
)
DPRINTF
(
"%04x:Ret %s.%s() retval=%08x ret=%08x
\n
"
,
GetCurrentThreadId
(),
data
->
dllname
,
entry_point
->
name
,
context
->
Eax
,
context
->
Eip
);
else
DPRINTF
(
"%04x:Ret %s.%u() retval=%08x ret=%08x
\n
"
,
GetCurrentThreadId
(),
data
->
dllname
,
data
->
base
+
ordinal
,
context
->
Eax
,
context
->
Eip
);
DPRINTF
(
"%04x: eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x "
"ebp=%08x esp=%08x ds=%04x es=%04x fs=%04x gs=%04x flags=%08x
\n
"
,
GetCurrentThreadId
(),
context
->
Eax
,
context
->
Ebx
,
context
->
Ecx
,
context
->
Edx
,
context
->
Esi
,
context
->
Edi
,
context
->
Ebp
,
context
->
Esp
,
context
->
SegDs
,
context
->
SegEs
,
context
->
SegFs
,
context
->
SegGs
,
context
->
EFlags
);
}
}
extern
void
WINAPI
relay_call_regs
(
void
);
DEFINE_REGS_ENTRYPOINT
(
relay_call_regs
,
4
)
#elif defined(__arm__)
extern
LONGLONG
CDECL
call_entry_point
(
void
*
func
,
int
nb_args
,
const
INT_PTR
*
args
,
int
flags
);
__ASM_GLOBAL_FUNC
(
call_entry_point
,
".arm
\n\t
"
"push {r4, r5, LR}
\n\t
"
...
...
@@ -388,7 +525,25 @@ __ASM_GLOBAL_FUNC( call_entry_point,
"5:
\t
blx r4
\n\t
"
"mov SP, r5
\n\t
"
"pop {r4, r5, PC}"
)
#else
static
LONGLONG
WINAPI
relay_call
(
struct
relay_descr
*
descr
,
unsigned
int
idx
,
const
INT_PTR
*
stack
)
{
BYTE
nb_args
=
LOBYTE
(
HIWORD
(
idx
));
BYTE
flags
=
HIBYTE
(
HIWORD
(
idx
));
void
*
func
=
relay_trace_entry
(
descr
,
idx
,
stack
);
LONGLONG
ret
=
call_entry_point
(
func
,
nb_args
,
stack
+
1
,
flags
);
relay_trace_exit
(
descr
,
idx
,
stack
,
ret
);
return
ret
;
}
static
void
WINAPI
relay_call_regs
(
struct
relay_descr
*
descr
,
INT_PTR
idx
,
INT_PTR
*
stack
)
{
assert
(
0
);
/* should never be called */
}
#elif defined(__x86_64__)
extern
LONGLONG
CDECL
call_entry_point
(
void
*
func
,
int
nb_args
,
const
INT_PTR
*
args
,
int
flags
);
__ASM_GLOBAL_FUNC
(
call_entry_point
,
"pushq %rbp
\n\t
"
__ASM_CFI
(
".cfi_adjust_cfa_offset 8
\n\t
"
)
...
...
@@ -428,139 +583,25 @@ __ASM_GLOBAL_FUNC( call_entry_point,
__ASM_CFI
(
".cfi_adjust_cfa_offset -8
\n\t
"
)
__ASM_CFI
(
".cfi_same_value %rbp
\n\t
"
)
"ret"
)
#endif
static
void
print_timestamp
(
void
)
{
ULONG
ticks
=
NtGetTickCount
();
DPRINTF
(
"%3u.%03u:"
,
ticks
/
1000
,
ticks
%
1000
);
}
/***********************************************************************
* relay_call
*
* stack points to the return address, i.e. the first argument is stack[1].
*/
static
LONGLONG
WINAPI
relay_call
(
struct
relay_descr
*
descr
,
unsigned
int
idx
,
const
INT_PTR
*
stack
)
{
LONGLONG
ret
;
WORD
ordinal
=
LOWORD
(
idx
);
BYTE
nb_args
=
LOBYTE
(
HIWORD
(
idx
));
BYTE
flags
=
HIBYTE
(
HIWORD
(
idx
));
struct
relay_private_data
*
data
=
descr
->
private
;
struct
relay_entry_point
*
entry_point
=
data
->
entry_points
+
ordinal
;
if
(
!
TRACE_ON
(
relay
))
ret
=
call_entry_point
(
entry_point
->
orig_func
,
nb_args
,
stack
+
1
,
flags
);
else
{
if
(
TRACE_ON
(
timestamp
))
print_timestamp
();
if
(
entry_point
->
name
)
DPRINTF
(
"%04x:Call %s.%s("
,
GetCurrentThreadId
(),
data
->
dllname
,
entry_point
->
name
);
else
DPRINTF
(
"%04x:Call %s.%u("
,
GetCurrentThreadId
(),
data
->
dllname
,
data
->
base
+
ordinal
);
RELAY_PrintArgs
(
stack
+
1
,
nb_args
,
descr
->
arg_types
[
ordinal
]
);
DPRINTF
(
") ret=%08lx
\n
"
,
stack
[
0
]
);
ret
=
call_entry_point
(
entry_point
->
orig_func
,
nb_args
,
stack
+
1
,
flags
);
if
(
TRACE_ON
(
timestamp
))
print_timestamp
();
if
(
entry_point
->
name
)
DPRINTF
(
"%04x:Ret %s.%s()"
,
GetCurrentThreadId
(),
data
->
dllname
,
entry_point
->
name
);
else
DPRINTF
(
"%04x:Ret %s.%u()"
,
GetCurrentThreadId
(),
data
->
dllname
,
data
->
base
+
ordinal
);
if
(
flags
&
1
)
/* 64-bit return value */
DPRINTF
(
" retval=%08x%08x ret=%08lx
\n
"
,
(
UINT
)(
ret
>>
32
),
(
UINT
)
ret
,
stack
[
0
]
);
else
DPRINTF
(
" retval=%08lx ret=%08lx
\n
"
,
(
UINT_PTR
)
ret
,
stack
[
0
]
);
}
void
*
func
=
relay_trace_entry
(
descr
,
idx
,
stack
);
LONGLONG
ret
=
call_entry_point
(
func
,
nb_args
,
stack
+
1
,
flags
);
relay_trace_exit
(
descr
,
idx
,
stack
,
ret
);
return
ret
;
}
/***********************************************************************
* relay_call_regs
*/
#ifdef __i386__
void
WINAPI
__regs_relay_call_regs
(
struct
relay_descr
*
descr
,
unsigned
int
idx
,
unsigned
int
orig_eax
,
unsigned
int
ret_addr
,
CONTEXT
*
context
)
{
WORD
ordinal
=
LOWORD
(
idx
);
BYTE
nb_args
=
LOBYTE
(
HIWORD
(
idx
));
struct
relay_private_data
*
data
=
descr
->
private
;
struct
relay_entry_point
*
entry_point
=
data
->
entry_points
+
ordinal
;
BYTE
*
orig_func
=
entry_point
->
orig_func
;
INT_PTR
*
args
=
(
INT_PTR
*
)
context
->
Esp
;
INT_PTR
args_copy
[
32
];
/* restore the context to what it was before the relay thunk */
context
->
Eax
=
orig_eax
;
context
->
Eip
=
ret_addr
;
context
->
Esp
+=
nb_args
*
sizeof
(
int
);
if
(
TRACE_ON
(
relay
))
{
if
(
entry_point
->
name
)
DPRINTF
(
"%04x:Call %s.%s("
,
GetCurrentThreadId
(),
data
->
dllname
,
entry_point
->
name
);
else
DPRINTF
(
"%04x:Call %s.%u("
,
GetCurrentThreadId
(),
data
->
dllname
,
data
->
base
+
ordinal
);
RELAY_PrintArgs
(
args
,
nb_args
,
descr
->
arg_types
[
ordinal
]
);
DPRINTF
(
") ret=%08x
\n
"
,
ret_addr
);
DPRINTF
(
"%04x: eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x "
"ebp=%08x esp=%08x ds=%04x es=%04x fs=%04x gs=%04x flags=%08x
\n
"
,
GetCurrentThreadId
(),
context
->
Eax
,
context
->
Ebx
,
context
->
Ecx
,
context
->
Edx
,
context
->
Esi
,
context
->
Edi
,
context
->
Ebp
,
context
->
Esp
,
context
->
SegDs
,
context
->
SegEs
,
context
->
SegFs
,
context
->
SegGs
,
context
->
EFlags
);
assert
(
orig_func
[
0
]
==
0x68
/* pushl func */
);
assert
(
orig_func
[
5
]
==
0x6a
/* pushl args */
);
assert
(
orig_func
[
7
]
==
0xe8
/* call */
);
}
/* now call the real function */
memcpy
(
args_copy
,
args
,
nb_args
*
sizeof
(
args
[
0
])
);
args_copy
[
nb_args
++
]
=
(
INT_PTR
)
context
;
/* append context argument */
call_entry_point
(
orig_func
+
12
+
*
(
int
*
)(
orig_func
+
1
),
nb_args
,
args_copy
,
0
);
if
(
TRACE_ON
(
relay
))
{
if
(
entry_point
->
name
)
DPRINTF
(
"%04x:Ret %s.%s() retval=%08x ret=%08x
\n
"
,
GetCurrentThreadId
(),
data
->
dllname
,
entry_point
->
name
,
context
->
Eax
,
context
->
Eip
);
else
DPRINTF
(
"%04x:Ret %s.%u() retval=%08x ret=%08x
\n
"
,
GetCurrentThreadId
(),
data
->
dllname
,
data
->
base
+
ordinal
,
context
->
Eax
,
context
->
Eip
);
DPRINTF
(
"%04x: eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x "
"ebp=%08x esp=%08x ds=%04x es=%04x fs=%04x gs=%04x flags=%08x
\n
"
,
GetCurrentThreadId
(),
context
->
Eax
,
context
->
Ebx
,
context
->
Ecx
,
context
->
Edx
,
context
->
Esi
,
context
->
Edi
,
context
->
Ebp
,
context
->
Esp
,
context
->
SegDs
,
context
->
SegEs
,
context
->
SegFs
,
context
->
SegGs
,
context
->
EFlags
);
}
}
extern
void
WINAPI
relay_call_regs
(
void
);
DEFINE_REGS_ENTRYPOINT
(
relay_call_regs
,
4
)
#else
/* __i386__ */
void
WINAPI
relay_call_regs
(
struct
relay_descr
*
descr
,
INT_PTR
idx
,
INT_PTR
*
stack
)
static
void
WINAPI
relay_call_regs
(
struct
relay_descr
*
descr
,
INT_PTR
idx
,
INT_PTR
*
stack
)
{
assert
(
0
);
/* should never be called */
}
#endif
/* __i386__ */
#else
#error Not supported on this CPU
#endif
/***********************************************************************
...
...
@@ -645,7 +686,7 @@ void RELAY_SetupDLL( HMODULE module )
}
}
#else
/* __i386__ || __x86_64__ */
#else
/* __i386__ || __x86_64__
|| __arm__
*/
FARPROC
RELAY_GetProcAddress
(
HMODULE
module
,
const
IMAGE_EXPORT_DIRECTORY
*
exports
,
DWORD
exp_size
,
FARPROC
proc
,
DWORD
ordinal
,
const
WCHAR
*
user
)
...
...
@@ -657,7 +698,7 @@ void RELAY_SetupDLL( HMODULE module )
{
}
#endif
/* __i386__ || __x86_64__ */
#endif
/* __i386__ || __x86_64__
|| __arm__
*/
/***********************************************************************/
...
...
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