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
8c1bb2aa
Commit
8c1bb2aa
authored
Dec 07, 2017
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Display floating point arguments in relay debugging on i386 and x86-64.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
83bbeab9
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
383 additions
and
184 deletions
+383
-184
relay.c
dlls/ntdll/relay.c
+276
-121
build.h
tools/winebuild/build.h
+1
-0
spec32.c
tools/winebuild/spec32.c
+106
-63
No files found.
dlls/ntdll/relay.c
View file @
8c1bb2aa
...
...
@@ -44,14 +44,13 @@ struct relay_descr /* descriptor for a module */
{
void
*
magic
;
/* signature */
void
*
relay_call
;
/* functions to call from relay thunks */
void
*
relay_call_regs
;
/* no longer used */
void
*
private
;
/* reserved for the relay code private data */
const
char
*
entry_point_base
;
/* base address of entry point thunks */
const
unsigned
int
*
entry_point_offsets
;
/* offsets of entry points thunks */
const
unsigned
int
*
arg_types
;
/* table of argument types for all entry poi
nts */
const
char
*
args_string
;
/* string describing the argume
nts */
};
#define RELAY_DESCR_MAGIC ((void *)0xdeb9000
1
)
#define RELAY_DESCR_MAGIC ((void *)0xdeb9000
2
)
#define IS_INTARG(x) (((ULONG_PTR)(x) >> 16) == 0)
/* private data built at dll load time */
...
...
@@ -295,49 +294,85 @@ static BOOL check_from_module( const WCHAR **includelist, const WCHAR **excludel
return
show
;
}
/***********************************************************************
* RELAY_PrintArgs
*/
static
inline
void
RELAY_PrintArgs
(
const
INT_PTR
*
args
,
int
nb_args
,
unsigned
int
typemask
)
static
BOOL
is_ret_val
(
char
type
)
{
while
(
nb_args
--
)
{
if
((
typemask
&
3
)
&&
!
IS_INTARG
(
*
args
))
{
if
(
typemask
&
2
)
TRACE
(
"%08lx %s"
,
*
args
,
debugstr_w
((
LPCWSTR
)
*
args
)
);
else
TRACE
(
"%08lx %s"
,
*
args
,
debugstr_a
((
LPCSTR
)
*
args
)
);
}
else
TRACE
(
"%08lx"
,
*
args
);
if
(
nb_args
)
TRACE
(
","
);
args
++
;
typemask
>>=
2
;
}
return
type
>=
'A'
&&
type
<=
'Z'
;
}
static
const
char
*
func_name
(
struct
relay_private_data
*
data
,
unsigned
int
ordinal
)
{
struct
relay_entry_point
*
entry_point
=
data
->
entry_points
+
ordinal
;
if
(
entry_point
->
name
)
return
wine_dbg_sprintf
(
"%s.%s"
,
data
->
dllname
,
entry_point
->
name
);
else
return
wine_dbg_sprintf
(
"%s.%u"
,
data
->
dllname
,
data
->
base
+
ordinal
);
}
static
void
trace_string_a
(
INT_PTR
ptr
)
{
if
(
!
IS_INTARG
(
ptr
))
TRACE
(
"%08lx %s"
,
ptr
,
debugstr_a
(
(
char
*
)
ptr
));
else
TRACE
(
"%08lx"
,
ptr
);
}
static
void
trace_string_w
(
INT_PTR
ptr
)
{
if
(
!
IS_INTARG
(
ptr
))
TRACE
(
"%08lx %s"
,
ptr
,
debugstr_w
(
(
WCHAR
*
)
ptr
));
else
TRACE
(
"%08lx"
,
ptr
);
}
#ifdef __i386__
/***********************************************************************
* relay_trace_entry
*
* stack points to the return address, i.e. the first argument is stack[1].
*/
DECLSPEC_HIDDEN
void
*
WINAPI
relay_trace_entry
(
struct
relay_descr
*
descr
,
unsigned
int
idx
,
const
INT_PTR
*
stack
)
DECLSPEC_HIDDEN
void
*
WINAPI
relay_trace_entry
(
struct
relay_descr
*
descr
,
unsigned
int
idx
,
const
DWORD
*
stack
,
unsigned
int
*
nb_args
)
{
WORD
ordinal
=
LOWORD
(
idx
);
BYTE
nb_args
=
LOBYTE
(
HIWORD
(
idx
)
);
const
char
*
arg_types
=
descr
->
args_string
+
HIWORD
(
idx
);
struct
relay_private_data
*
data
=
descr
->
private
;
struct
relay_entry_point
*
entry_point
=
data
->
entry_points
+
ordinal
;
unsigned
int
i
,
pos
;
TRACE
(
"
\1
Call %s("
,
func_name
(
data
,
ordinal
));
if
(
TRACE_ON
(
relay
)
)
for
(
i
=
pos
=
0
;
!
is_ret_val
(
arg_types
[
i
]
);
i
++
)
{
if
(
entry_point
->
name
)
TRACE
(
"
\1
Call %s.%s("
,
data
->
dllname
,
entry_point
->
name
);
else
TRACE
(
"
\1
Call %s.%u("
,
data
->
dllname
,
data
->
base
+
ordinal
);
RELAY_PrintArgs
(
stack
+
1
,
nb_args
,
descr
->
arg_types
[
ordinal
]
);
TRACE
(
") ret=%08lx
\n
"
,
stack
[
0
]
);
switch
(
arg_types
[
i
])
{
case
'j'
:
/* int64 */
TRACE
(
"%x%08x"
,
stack
[
pos
+
1
],
stack
[
pos
]
);
pos
+=
2
;
break
;
case
'k'
:
/* int128 */
TRACE
(
"{%08x,%08x,%08x,%08x}"
,
stack
[
pos
],
stack
[
pos
+
1
],
stack
[
pos
+
2
],
stack
[
pos
+
3
]
);
pos
+=
4
;
break
;
case
's'
:
/* str */
trace_string_a
(
stack
[
pos
++
]
);
break
;
case
'w'
:
/* wstr */
trace_string_w
(
stack
[
pos
++
]
);
break
;
case
'f'
:
/* float */
TRACE
(
"%g"
,
*
(
const
float
*
)
&
stack
[
pos
++
]
);
break
;
case
'd'
:
/* double */
TRACE
(
"%g"
,
*
(
const
double
*
)
&
stack
[
pos
]
);
pos
+=
2
;
break
;
case
'i'
:
/* long */
default:
TRACE
(
"%08x"
,
stack
[
pos
++
]
);
break
;
}
if
(
!
is_ret_val
(
arg_types
[
i
+
1
]
))
TRACE
(
","
);
}
*
nb_args
=
pos
;
if
(
arg_types
[
0
]
==
't'
)
*
nb_args
|=
0x80000000
;
/* thiscall */
TRACE
(
") ret=%08x
\n
"
,
stack
[
-
1
]
);
return
entry_point
->
orig_func
;
}
...
...
@@ -345,63 +380,21 @@ DECLSPEC_HIDDEN void * WINAPI relay_trace_entry( struct relay_descr *descr,
* relay_trace_exit
*/
DECLSPEC_HIDDEN
void
WINAPI
relay_trace_exit
(
struct
relay_descr
*
descr
,
unsigned
int
idx
,
const
INT_PTR
*
stack
,
LONGLONG
retval
)
void
*
retaddr
,
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
;
const
char
*
arg_types
=
descr
->
args_string
+
HIWORD
(
idx
);
if
(
entry_point
->
name
)
TRACE
(
"
\1
Ret %s.%s()"
,
data
->
dllname
,
entry_point
->
name
);
else
TRACE
(
"
\1
Ret %s.%u()"
,
data
->
dllname
,
data
->
base
+
ordinal
);
TRACE
(
"
\1
Ret %s()"
,
func_name
(
descr
->
private
,
LOWORD
(
idx
)
));
if
(
flags
&
1
)
/* 64-bit return value */
TRACE
(
" retval=%08x%08x ret=%08lx
\n
"
,
(
UINT
)(
retval
>>
32
),
(
UINT
)
retval
,
stack
[
0
]
);
while
(
!
is_ret_val
(
*
arg_types
))
arg_types
++
;
if
(
*
arg_types
==
'J'
)
/* int64 return value */
TRACE
(
" retval=%08x%08x ret=%08x
\n
"
,
(
UINT
)(
retval
>>
32
),
(
UINT
)
retval
,
(
UINT
)
retaddr
);
else
TRACE
(
" retval=%08
lx ret=%08lx
\n
"
,
(
UINT_PTR
)
retval
,
stack
[
0
]
);
TRACE
(
" retval=%08
x ret=%08x
\n
"
,
(
UINT
)
retval
,
(
UINT
)
retaddr
);
}
#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
"
)
__ASM_CFI
(
".cfi_rel_offset %ebp,0
\n\t
"
)
"movl %esp,%ebp
\n\t
"
__ASM_CFI
(
".cfi_def_cfa_register %ebp
\n\t
"
)
"pushl %esi
\n\t
"
__ASM_CFI
(
".cfi_rel_offset %esi,-4
\n\t
"
)
"pushl %edi
\n\t
"
__ASM_CFI
(
".cfi_rel_offset %edi,-8
\n\t
"
)
"movl 12(%ebp),%edx
\n\t
"
"shll $2,%edx
\n\t
"
"jz 1f
\n\t
"
"subl %edx,%esp
\n\t
"
"andl $~15,%esp
\n\t
"
"movl 12(%ebp),%ecx
\n\t
"
"movl 16(%ebp),%esi
\n\t
"
"movl %esp,%edi
\n\t
"
"cld
\n\t
"
"rep; movsl
\n
"
"testl $2,20(%ebp)
\n\t
"
/* (flags & 2) -> thiscall */
"jz 1f
\n\t
"
"popl %ecx
\n\t
"
"1:
\t
call *8(%ebp)
\n\t
"
"leal -8(%ebp),%esp
\n\t
"
"popl %edi
\n\t
"
__ASM_CFI
(
".cfi_same_value %edi
\n\t
"
)
"popl %esi
\n\t
"
__ASM_CFI
(
".cfi_same_value %esi
\n\t
"
)
"popl %ebp
\n\t
"
__ASM_CFI
(
".cfi_def_cfa %esp,4
\n\t
"
)
__ASM_CFI
(
".cfi_same_value %ebp
\n\t
"
)
"ret"
)
extern
LONGLONG
WINAPI
relay_call
(
struct
relay_descr
*
descr
,
unsigned
int
idx
,
const
INT_PTR
*
stack
);
extern
LONGLONG
WINAPI
relay_call
(
struct
relay_descr
*
descr
,
unsigned
int
idx
);
__ASM_GLOBAL_FUNC
(
relay_call
,
"pushl %ebp
\n\t
"
__ASM_CFI
(
".cfi_adjust_cfa_offset 4
\n\t
"
)
...
...
@@ -415,22 +408,24 @@ __ASM_GLOBAL_FUNC( relay_call,
"pushl %ecx
\n\t
"
__ASM_CFI
(
".cfi_rel_offset %ecx,-12
\n\t
"
)
/* trace the parameters */
"pushl 16(%ebp)
\n\t
"
"pushl %eax
\n\t
"
"pushl %esp
\n\t
"
/* number of args return ptr */
"leal 20(%ebp),%esi
\n\t
"
/* stack */
"pushl %esi
\n\t
"
"pushl 12(%ebp)
\n\t
"
"pushl 8(%ebp)
\n\t
"
"call "
__ASM_NAME
(
"relay_trace_entry"
)
"
\n\t
"
/* copy the arguments*/
"mov
zbl 14
(%ebp),%ecx
\n\t
"
/* number of args */
"mov
l -16
(%ebp),%ecx
\n\t
"
/* number of args */
"jecxz 1f
\n\t
"
"andl $0x7fffffff,%ecx
\n\t
"
"leal 0(,%ecx,4),%edx
\n\t
"
"subl %edx,%esp
\n\t
"
"andl $~15,%esp
\n\t
"
"movl 16(%ebp),%esi
\n\t
"
"addl $4,%esi
\n\t
"
"movl %esp,%edi
\n\t
"
"cld
\n\t
"
"rep; movsl
\n\t
"
"test
b $2,15(%ebp)
\n\t
"
/* (flags & 2) ->
thiscall */
"test
l $0x80000000,-16(%ebp)
\n\t
"
/*
thiscall */
"jz 1f
\n\t
"
"popl %ecx
\n
"
/* call the entry point */
...
...
@@ -458,11 +453,73 @@ __ASM_GLOBAL_FUNC( relay_call,
"popl %ebp
\n\t
"
__ASM_CFI
(
".cfi_def_cfa %esp,4
\n\t
"
)
__ASM_CFI
(
".cfi_same_value %ebp
\n\t
"
)
"ret $
12
"
)
"ret $
8
"
)
#elif defined(__arm__)
extern
LONGLONG
CDECL
call_entry_point
(
void
*
func
,
int
nb_args
,
const
INT_PTR
*
args
,
int
flags
);
/***********************************************************************
* relay_trace_entry
*/
DECLSPEC_HIDDEN
void
*
WINAPI
relay_trace_entry
(
struct
relay_descr
*
descr
,
unsigned
int
idx
,
const
DWORD
*
stack
,
unsigned
int
*
nb_args
)
{
WORD
ordinal
=
LOWORD
(
idx
);
const
char
*
arg_types
=
descr
->
args_string
+
HIWORD
(
idx
);
struct
relay_private_data
*
data
=
descr
->
private
;
struct
relay_entry_point
*
entry_point
=
data
->
entry_points
+
ordinal
;
unsigned
int
i
,
pos
;
TRACE
(
"
\1
Call %s("
,
func_name
(
data
,
ordinal
));
for
(
i
=
pos
=
0
;
!
is_ret_val
(
arg_types
[
i
]
);
i
++
)
{
switch
(
arg_types
[
i
])
{
case
'j'
:
/* int64 */
TRACE
(
"%x%08x"
,
stack
[
pos
+
1
],
stack
[
pos
]
);
pos
+=
2
;
break
;
case
'k'
:
/* int128 */
TRACE
(
"{%08x,%08x,%08x,%08x}"
,
stack
[
pos
],
stack
[
pos
+
1
],
stack
[
pos
+
2
],
stack
[
pos
+
3
]
);
pos
+=
4
;
break
;
case
's'
:
/* str */
trace_string_a
(
stack
[
pos
++
]
);
break
;
case
'w'
:
/* wstr */
trace_string_w
(
stack
[
pos
++
]
);
break
;
case
'i'
:
/* long */
default
:
TRACE
(
"%08x"
,
stack
[
pos
++
]
);
break
;
}
if
(
!
is_ret_val
(
arg_types
[
i
+
1
]
))
TRACE
(
","
);
}
*
nb_args
=
pos
;
TRACE
(
") ret=%08x
\n
"
,
stack
[
-
1
]
);
return
entry_point
->
orig_func
;
}
/***********************************************************************
* relay_trace_exit
*/
DECLSPEC_HIDDEN
void
WINAPI
relay_trace_exit
(
struct
relay_descr
*
descr
,
unsigned
int
idx
,
DWORD
retaddr
,
LONGLONG
retval
)
{
const
char
*
arg_types
=
descr
->
args_string
+
HIWORD
(
idx
);
TRACE
(
"
\1
Ret %s()"
,
func_name
(
descr
->
private
,
LOWORD
(
idx
)
));
while
(
!
is_ret_val
(
*
arg_types
))
arg_types
++
;
if
(
*
arg_types
==
'J'
)
/* int64 return value */
TRACE
(
" retval=%08x%08x ret=%08x
\n
"
,
(
UINT
)(
retval
>>
32
),
(
UINT
)
retval
,
retaddr
);
else
TRACE
(
" retval=%08x ret=%08x
\n
"
,
(
UINT
)
retval
,
retaddr
);
}
extern
LONGLONG
CDECL
call_entry_point
(
void
*
func
,
int
nb_args
,
const
DWORD
*
args
);
__ASM_GLOBAL_FUNC
(
call_entry_point
,
".arm
\n\t
"
"push {r4, r5, LR}
\n\t
"
...
...
@@ -487,19 +544,64 @@ __ASM_GLOBAL_FUNC( call_entry_point,
"mov SP, r5
\n\t
"
"pop {r4, r5, PC}"
)
static
LONGLONG
WINAPI
relay_call
(
struct
relay_descr
*
descr
,
unsigned
int
idx
,
const
INT_PTR
*
stack
)
static
LONGLONG
WINAPI
relay_call
(
struct
relay_descr
*
descr
,
unsigned
int
idx
,
const
DWORD
*
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
);
unsigned
int
nb_args
;
void
*
func
=
relay_trace_entry
(
descr
,
idx
,
stack
,
&
nb_args
);
LONGLONG
ret
=
call_entry_point
(
func
,
nb_args
,
stack
);
relay_trace_exit
(
descr
,
idx
,
stack
[
-
1
],
ret
);
return
ret
;
}
#elif defined(__aarch64__)
extern
LONGLONG
CDECL
call_entry_point
(
void
*
func
,
int
nb_args
,
const
INT_PTR
*
args
,
int
flags
);
/***********************************************************************
* relay_trace_entry
*/
DECLSPEC_HIDDEN
void
*
WINAPI
relay_trace_entry
(
struct
relay_descr
*
descr
,
unsigned
int
idx
,
const
INT_PTR
*
stack
,
unsigned
int
*
nb_args
)
{
WORD
ordinal
=
LOWORD
(
idx
);
const
char
*
arg_types
=
descr
->
args_string
+
HIWORD
(
idx
);
struct
relay_private_data
*
data
=
descr
->
private
;
struct
relay_entry_point
*
entry_point
=
data
->
entry_points
+
ordinal
;
unsigned
int
i
;
TRACE
(
"
\1
Call %s("
,
func_name
(
data
,
ordinal
));
for
(
i
=
0
;
!
is_ret_val
(
arg_types
[
i
]
);
i
++
)
{
switch
(
arg_types
[
i
])
{
case
's'
:
/* str */
trace_string_a
(
stack
[
i
]
);
break
;
case
'w'
:
/* wstr */
trace_string_w
(
stack
[
i
]
);
break
;
case
'i'
:
/* long */
default
:
TRACE
(
"%08lx"
,
stack
[
i
]
);
break
;
}
if
(
!
is_ret_val
(
arg_types
[
i
+
1
]
))
TRACE
(
","
);
}
*
nb_args
=
i
;
TRACE
(
") ret=%08lx
\n
"
,
stack
[
-
1
]
);
return
entry_point
->
orig_func
;
}
/***********************************************************************
* relay_trace_exit
*/
DECLSPEC_HIDDEN
void
WINAPI
relay_trace_exit
(
struct
relay_descr
*
descr
,
unsigned
int
idx
,
INT_PTR
retaddr
,
INT_PTR
retval
)
{
TRACE
(
"
\1
Ret %s() retval=%08lx ret=%08lx
\n
"
,
func_name
(
descr
->
private
,
LOWORD
(
idx
)
),
retval
,
retaddr
);
}
extern
LONGLONG
CDECL
call_entry_point
(
void
*
func
,
int
nb_args
,
const
INT_PTR
*
args
);
__ASM_GLOBAL_FUNC
(
call_entry_point
,
"stp x29, x30, [SP,#-16]!
\n\t
"
"stp x19, x20, [SP,#-16]!
\n\t
"
...
...
@@ -544,43 +646,97 @@ __ASM_GLOBAL_FUNC( call_entry_point,
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
+
3
);
LONGLONG
ret
=
call_entry_point
(
func
,
nb_args
,
stack
+
4
,
flags
);
relay_trace_exit
(
descr
,
idx
,
stack
+
3
,
ret
);
unsigned
int
nb_args
;
void
*
func
=
relay_trace_entry
(
descr
,
idx
,
stack
,
&
nb_args
);
LONGLONG
ret
=
call_entry_point
(
func
,
nb_args
,
stack
);
relay_trace_exit
(
descr
,
idx
,
stack
[
-
1
],
ret
);
return
ret
;
}
#elif defined(__x86_64__)
extern
void
*
WINAPI
relay_call
(
struct
relay_descr
*
descr
,
unsigned
int
idx
,
const
INT_PTR
*
stack
);
/***********************************************************************
* relay_trace_entry
*/
DECLSPEC_HIDDEN
void
*
WINAPI
relay_trace_entry
(
struct
relay_descr
*
descr
,
unsigned
int
idx
,
const
INT_PTR
*
stack
,
unsigned
int
*
nb_args
)
{
WORD
ordinal
=
LOWORD
(
idx
);
const
char
*
arg_types
=
descr
->
args_string
+
HIWORD
(
idx
);
struct
relay_private_data
*
data
=
descr
->
private
;
struct
relay_entry_point
*
entry_point
=
data
->
entry_points
+
ordinal
;
unsigned
int
i
;
TRACE
(
"
\1
Call %s("
,
func_name
(
data
,
ordinal
));
for
(
i
=
0
;
!
is_ret_val
(
arg_types
[
i
]
);
i
++
)
{
switch
(
arg_types
[
i
])
{
case
's'
:
/* str */
trace_string_a
(
stack
[
i
]
);
break
;
case
'w'
:
/* wstr */
trace_string_w
(
stack
[
i
]
);
break
;
case
'f'
:
/* float */
TRACE
(
"%g"
,
*
(
const
float
*
)
&
stack
[
i
]
);
break
;
case
'd'
:
/* double */
TRACE
(
"%g"
,
*
(
const
double
*
)
&
stack
[
i
]
);
break
;
case
'i'
:
/* long */
default
:
TRACE
(
"%08lx"
,
stack
[
i
]
);
break
;
}
if
(
!
is_ret_val
(
arg_types
[
i
]
))
TRACE
(
","
);
}
*
nb_args
=
i
;
TRACE
(
") ret=%08lx
\n
"
,
stack
[
-
1
]
);
return
entry_point
->
orig_func
;
}
/***********************************************************************
* relay_trace_exit
*/
DECLSPEC_HIDDEN
void
WINAPI
relay_trace_exit
(
struct
relay_descr
*
descr
,
unsigned
int
idx
,
INT_PTR
retaddr
,
INT_PTR
retval
)
{
TRACE
(
"
\1
Ret %s() retval=%08lx ret=%08lx
\n
"
,
func_name
(
descr
->
private
,
LOWORD
(
idx
)
),
retval
,
retaddr
);
}
extern
INT_PTR
WINAPI
relay_call
(
struct
relay_descr
*
descr
,
unsigned
int
idx
,
const
INT_PTR
*
stack
);
__ASM_GLOBAL_FUNC
(
relay_call
,
"pushq %rbp
\n\t
"
__ASM_CFI
(
".cfi_adjust_cfa_offset 8
\n\t
"
)
__ASM_CFI
(
".cfi_rel_offset %rbp,0
\n\t
"
)
"movq %rsp,%rbp
\n\t
"
__ASM_CFI
(
".cfi_def_cfa_register %rbp
\n\t
"
)
"subq $0x30,%rsp
\n\t
"
"movq %rsi,0x20(%rsp)
\n\t
"
"leaq -0x48(%rbp),%rsp
\n\t
"
"andq $~15,%rsp
\n\t
"
"movq %rcx,-32(%rbp)
\n\t
"
__ASM_CFI
(
".cfi_rel_offset %rcx,-32
\n\t
"
)
"movq %rdx,-24(%rbp)
\n\t
"
__ASM_CFI
(
".cfi_rel_offset %rdx,-24
\n\t
"
)
"movq %rsi,-16(%rbp)
\n\t
"
__ASM_CFI
(
".cfi_rel_offset %rsi,-16
\n\t
"
)
"movq %rdi,
0x28(%rs
p)
\n\t
"
"movq %rdi,
-8(%rb
p)
\n\t
"
__ASM_CFI
(
".cfi_rel_offset %rdi,-8
\n\t
"
)
/* trace the parameters */
"movq %rcx,0x10(%rbp)
\n\t
"
"movq %rdx,0x18(%rbp)
\n\t
"
"movq %r8,0x20(%rbp)
\n\t
"
"leaq 24(%rbp),%r8
\n\t
"
/* stack */
"leaq -40(%rbp),%r9
\n\t
"
"call "
__ASM_NAME
(
"relay_trace_entry"
)
"
\n\t
"
/* copy the arguments */
"mov
zbq 0x1a(%rbp),%r
dx
\n\t
"
/* number of args */
"mov
l -40(%rbp),%e
dx
\n\t
"
/* number of args */
"movq $4,%rcx
\n\t
"
"cmp %rcx,%rdx
\n\t
"
"cmovgq %rdx,%rcx
\n\t
"
"leaq -16(,%rcx,8),%rdx
\n\t
"
"andq $~15,%rdx
\n\t
"
"subq %rdx,%rsp
\n\t
"
"movq 0x20(%rbp),%r8
\n\t
"
/* original stack */
"leaq 8(%r8),%rsi
\n\t
"
"leaq 24(%rbp),%rsi
\n\t
"
/* original stack */
"movq %rsp,%rdi
\n\t
"
"rep; movsq
\n\t
"
/* call the entry point */
...
...
@@ -594,20 +750,19 @@ __ASM_GLOBAL_FUNC( relay_call,
"movq 24(%rsp),%xmm3
\n\t
"
"callq *%rax
\n\t
"
/* trace the return value */
"leaq -0x30(%rbp),%rsp
\n\t
"
"movq 0x10(%rbp),%rcx
\n\t
"
"movq 0x18(%rbp),%rdx
\n\t
"
"movq 0x20(%rbp),%r8
\n\t
"
"movq -32(%rbp),%rcx
\n\t
"
"movq -24(%rbp),%rdx
\n\t
"
"movq 16(%rbp),%r8
\n\t
"
/* retaddr */
"movq %rax,%rsi
\n\t
"
"movaps %xmm0,
0x10(%rb
p)
\n\t
"
"movaps %xmm0,
32(%rs
p)
\n\t
"
"movq %rax,%r9
\n\t
"
"call "
__ASM_NAME
(
"relay_trace_exit"
)
"
\n\t
"
/* restore return value and return */
"movq %rsi,%rax
\n\t
"
"movaps
0x10(%rb
p),%xmm0
\n\t
"
"movq
0x20(%rs
p),%rsi
\n\t
"
"movaps
32(%rs
p),%xmm0
\n\t
"
"movq
-16(%rb
p),%rsi
\n\t
"
__ASM_CFI
(
".cfi_same_value %rsi
\n\t
"
)
"movq
0x28(%rs
p),%rdi
\n\t
"
"movq
-8(%rb
p),%rdi
\n\t
"
__ASM_CFI
(
".cfi_same_value %rdi
\n\t
"
)
"movq %rbp,%rsp
\n\t
"
__ASM_CFI
(
".cfi_def_cfa_register %rsp
\n\t
"
)
...
...
tools/winebuild/build.h
View file @
8c1bb2aa
...
...
@@ -86,6 +86,7 @@ typedef struct
typedef
struct
{
int
nb_args
;
int
args_str_offset
;
enum
arg_type
args
[
MAX_ARGUMENTS
];
}
ORD_FUNCTION
;
...
...
tools/winebuild/spec32.c
View file @
8c1bb2aa
...
...
@@ -94,6 +94,88 @@ static int has_relays( DLLSPEC *spec )
return
0
;
}
static
int
cmp_func_args
(
const
void
*
p1
,
const
void
*
p2
)
{
const
ORDDEF
*
odp1
=
*
(
const
ORDDEF
**
)
p1
;
const
ORDDEF
*
odp2
=
*
(
const
ORDDEF
**
)
p2
;
return
odp2
->
u
.
func
.
nb_args
-
odp1
->
u
.
func
.
nb_args
;
}
static
void
get_arg_string
(
ORDDEF
*
odp
,
char
str
[
MAX_ARGUMENTS
+
1
]
)
{
int
i
;
for
(
i
=
0
;
i
<
odp
->
u
.
func
.
nb_args
;
i
++
)
{
switch
(
odp
->
u
.
func
.
args
[
i
])
{
case
ARG_STR
:
str
[
i
]
=
's'
;
break
;
case
ARG_WSTR
:
str
[
i
]
=
'w'
;
break
;
case
ARG_FLOAT
:
str
[
i
]
=
'f'
;
break
;
case
ARG_DOUBLE
:
str
[
i
]
=
'd'
;
break
;
case
ARG_INT64
:
case
ARG_INT128
:
if
(
get_ptr_size
()
==
4
)
{
str
[
i
]
=
(
odp
->
u
.
func
.
args
[
i
]
==
ARG_INT64
)
?
'j'
:
'k'
;
break
;
}
/* fall through */
case
ARG_LONG
:
case
ARG_PTR
:
default:
str
[
i
]
=
'i'
;
break
;
}
}
if
(
target_cpu
==
CPU_x86
&&
odp
->
type
==
TYPE_THISCALL
)
str
[
0
]
=
't'
;
/* append return value */
if
(
get_ptr_size
()
==
4
&&
(
odp
->
flags
&
FLAG_RET64
))
strcpy
(
str
+
i
,
"J"
);
else
strcpy
(
str
+
i
,
"I"
);
}
/*******************************************************************
* build_args_string
*/
static
char
*
build_args_string
(
DLLSPEC
*
spec
)
{
int
i
,
count
=
0
,
len
=
1
;
char
*
p
,
*
buffer
;
char
str
[
MAX_ARGUMENTS
+
2
];
ORDDEF
**
funcs
;
funcs
=
xmalloc
(
(
spec
->
limit
+
1
-
spec
->
base
)
*
sizeof
(
*
funcs
)
);
for
(
i
=
spec
->
base
;
i
<=
spec
->
limit
;
i
++
)
{
ORDDEF
*
odp
=
spec
->
ordinals
[
i
];
if
(
!
needs_relay
(
odp
))
continue
;
funcs
[
count
++
]
=
odp
;
len
+=
odp
->
u
.
func
.
nb_args
+
1
;
}
/* sort functions by decreasing number of arguments */
qsort
(
funcs
,
count
,
sizeof
(
*
funcs
),
cmp_func_args
);
buffer
=
xmalloc
(
len
);
buffer
[
0
]
=
0
;
/* build the arguments string, reusing substrings where possible */
for
(
i
=
0
;
i
<
count
;
i
++
)
{
get_arg_string
(
funcs
[
i
],
str
);
if
(
!
(
p
=
strstr
(
buffer
,
str
)))
{
p
=
buffer
+
strlen
(
buffer
);
strcpy
(
p
,
str
);
}
funcs
[
i
]
->
u
.
func
.
args_str_offset
=
p
-
buffer
;
}
free
(
funcs
);
return
buffer
;
}
/*******************************************************************
* output_relay_debug
*
...
...
@@ -101,8 +183,7 @@ static int has_relays( DLLSPEC *spec )
*/
static
void
output_relay_debug
(
DLLSPEC
*
spec
)
{
int
i
,
j
;
unsigned
int
pos
,
args
,
flags
;
int
i
;
/* first the table of entry point offsets */
...
...
@@ -120,33 +201,10 @@ static void output_relay_debug( DLLSPEC *spec )
output
(
"
\t
.long 0
\n
"
);
}
/* then the table of argument types */
output
(
"
\t
.align %d
\n
"
,
get_alignment
(
4
)
);
output
(
".L__wine_spec_relay_arg_types:
\n
"
);
for
(
i
=
spec
->
base
;
i
<=
spec
->
limit
;
i
++
)
{
ORDDEF
*
odp
=
spec
->
ordinals
[
i
];
unsigned
int
mask
=
0
;
/* then the strings of argument types */
if
(
needs_relay
(
odp
))
{
for
(
j
=
pos
=
0
;
pos
<
16
&&
j
<
odp
->
u
.
func
.
nb_args
;
j
++
)
{
switch
(
odp
->
u
.
func
.
args
[
j
])
{
case
ARG_STR
:
mask
|=
1
<<
(
2
*
pos
++
);
break
;
case
ARG_WSTR
:
mask
|=
2
<<
(
2
*
pos
++
);
break
;
case
ARG_INT64
:
case
ARG_DOUBLE
:
pos
+=
8
/
get_ptr_size
();
break
;
case
ARG_INT128
:
pos
+=
(
target_cpu
==
CPU_x86
)
?
4
:
1
;
break
;
default:
pos
++
;
break
;
}
}
}
output
(
"
\t
.long 0x%08x
\n
"
,
mask
);
}
output
(
".L__wine_spec_relay_args_string:
\n
"
);
output
(
"
\t
%s
\"
%s
\"\n
"
,
get_asm_string_keyword
(),
build_args_string
(
spec
));
/* then the relay thunks */
...
...
@@ -164,9 +222,6 @@ static void output_relay_debug( DLLSPEC *spec )
output
(
".L__wine_spec_relay_entry_point_%d:
\n
"
,
i
);
output_cfi
(
".cfi_startproc"
);
args
=
get_args_size
(
odp
)
/
get_ptr_size
();
flags
=
0
;
switch
(
target_cpu
)
{
case
CPU_x86
:
...
...
@@ -175,13 +230,8 @@ static void output_relay_debug( DLLSPEC *spec )
output
(
"
\t
popl %%eax
\n
"
);
output
(
"
\t
pushl %%ecx
\n
"
);
output
(
"
\t
pushl %%eax
\n
"
);
flags
|=
2
;
}
output
(
"
\t
pushl %%esp
\n
"
);
output_cfi
(
".cfi_adjust_cfa_offset 4"
);
if
(
odp
->
flags
&
FLAG_RET64
)
flags
|=
1
;
output
(
"
\t
pushl $%u
\n
"
,
(
flags
<<
24
)
|
(
args
<<
16
)
|
(
i
-
spec
->
base
)
);
output
(
"
\t
pushl $%u
\n
"
,
(
odp
->
u
.
func
.
args_str_offset
<<
16
)
|
(
i
-
spec
->
base
)
);
output_cfi
(
".cfi_adjust_cfa_offset 4"
);
if
(
UsePIC
)
...
...
@@ -195,9 +245,9 @@ static void output_relay_debug( DLLSPEC *spec )
output_cfi
(
".cfi_adjust_cfa_offset 4"
);
output
(
"
\t
call *4(%%eax)
\n
"
);
output_cfi
(
".cfi_adjust_cfa_offset -
12
"
);
output_cfi
(
".cfi_adjust_cfa_offset -
8
"
);
if
(
odp
->
type
==
TYPE_STDCALL
||
odp
->
type
==
TYPE_THISCALL
)
output
(
"
\t
ret $%u
\n
"
,
args
*
get_ptr_size
()
);
output
(
"
\t
ret $%u
\n
"
,
get_args_size
(
odp
)
);
else
output
(
"
\t
ret
\n
"
);
break
;
...
...
@@ -205,18 +255,17 @@ static void output_relay_debug( DLLSPEC *spec )
case
CPU_ARM
:
{
unsigned
int
mask
,
val
,
count
=
0
;
unsigned
int
stack_size
=
min
(
16
,
(
args
*
4
+
7
)
&
~
7
);
unsigned
int
stack_size
=
min
(
16
,
(
get_args_size
(
odp
)
+
7
)
&
~
7
);
if
(
odp
->
flags
&
FLAG_RET64
)
flags
|=
1
;
val
=
(
flags
<<
24
)
|
(
args
<<
16
)
|
(
i
-
spec
->
base
);
val
=
(
odp
->
u
.
func
.
args_str_offset
<<
16
)
|
(
i
-
spec
->
base
);
switch
(
stack_size
)
{
case
16
:
output
(
"
\t
push {r0-r3}
\n
"
);
break
;
case
8
:
output
(
"
\t
push {r0-r1}
\n
"
);
break
;
case
0
:
break
;
}
output
(
"
\t
push {LR}
\n
"
);
output
(
"
\t
mov r2, SP
\n
"
);
output
(
"
\t
push {LR}
\n
"
);
output
(
"
\t
sub SP, #4
\n
"
);
for
(
mask
=
0xff
;
mask
;
mask
<<=
8
)
if
(
val
&
mask
)
output
(
"
\t
%s r1,#%u
\n
"
,
count
++
?
"add"
:
"mov"
,
val
&
mask
);
...
...
@@ -233,7 +282,7 @@ static void output_relay_debug( DLLSPEC *spec )
}
case
CPU_ARM64
:
switch
(
args
)
switch
(
odp
->
u
.
func
.
nb_
args
)
{
default:
case
8
:
...
...
@@ -250,12 +299,10 @@ static void output_relay_debug( DLLSPEC *spec )
/* fall through */
case
0
:
break
;
}
output
(
"
\t
mov x2, SP
\n
"
);
output
(
"
\t
stp x29, x30, [SP,#-16]!
\n
"
);
output
(
"
\t
stp x8, x9, [SP,#-16]!
\n
"
);
output
(
"
\t
mov x2, SP
\n
"
);
if
(
odp
->
flags
&
FLAG_RET64
)
flags
|=
1
;
output
(
"
\t
mov w1, #%u
\n
"
,
(
flags
<<
24
)
);
if
(
args
)
output
(
"
\t
add w1, w1, #%u
\n
"
,
(
args
<<
16
)
);
output
(
"
\t
mov w1, #%u
\n
"
,
odp
->
u
.
func
.
args_str_offset
<<
16
);
if
(
i
-
spec
->
base
)
output
(
"
\t
add w1, w1, #%u
\n
"
,
i
-
spec
->
base
);
output
(
"
\t
adrp x0, .L__wine_spec_relay_descr
\n
"
);
output
(
"
\t
add x0, x0, #:lo12:.L__wine_spec_relay_descr
\n
"
);
...
...
@@ -263,31 +310,27 @@ static void output_relay_debug( DLLSPEC *spec )
output
(
"
\t
blr x3
\n
"
);
output
(
"
\t
add SP, SP, #16
\n
"
);
output
(
"
\t
ldp x29, x30, [SP], #16
\n
"
);
if
(
args
)
output
(
"
\t
add SP, SP, #%u
\n
"
,
8
*
((
min
(
args
,
8
)
+
1
)
&
0xe
)
);
if
(
odp
->
u
.
func
.
nb_args
)
output
(
"
\t
add SP, SP, #%u
\n
"
,
8
*
((
min
(
odp
->
u
.
func
.
nb_args
,
8
)
+
1
)
&
~
1
)
);
output
(
"
\t
ret
\n
"
);
break
;
case
CPU_x86_64
:
output
(
"
\t
subq $40,%%rsp
\n
"
);
output_cfi
(
".cfi_adjust_cfa_offset 40"
);
switch
(
args
)
switch
(
odp
->
u
.
func
.
nb_args
)
{
default:
output
(
"
\t
movq %%%s,
7
2(%%rsp)
\n
"
,
is_float_arg
(
odp
,
3
)
?
"xmm3"
:
"r9"
);
default:
output
(
"
\t
movq %%%s,
3
2(%%rsp)
\n
"
,
is_float_arg
(
odp
,
3
)
?
"xmm3"
:
"r9"
);
/* fall through */
case
3
:
output
(
"
\t
movq %%%s,
6
4(%%rsp)
\n
"
,
is_float_arg
(
odp
,
2
)
?
"xmm2"
:
"r8"
);
case
3
:
output
(
"
\t
movq %%%s,
2
4(%%rsp)
\n
"
,
is_float_arg
(
odp
,
2
)
?
"xmm2"
:
"r8"
);
/* fall through */
case
2
:
output
(
"
\t
movq %%%s,
5
6(%%rsp)
\n
"
,
is_float_arg
(
odp
,
1
)
?
"xmm1"
:
"rdx"
);
case
2
:
output
(
"
\t
movq %%%s,
1
6(%%rsp)
\n
"
,
is_float_arg
(
odp
,
1
)
?
"xmm1"
:
"rdx"
);
/* fall through */
case
1
:
output
(
"
\t
movq %%%s,
4
8(%%rsp)
\n
"
,
is_float_arg
(
odp
,
0
)
?
"xmm0"
:
"rcx"
);
case
1
:
output
(
"
\t
movq %%%s,8(%%rsp)
\n
"
,
is_float_arg
(
odp
,
0
)
?
"xmm0"
:
"rcx"
);
/* fall through */
case
0
:
break
;
}
output
(
"
\t
leaq 40(%%rsp),%%r8
\n
"
);
output
(
"
\t
movq $%u,%%rdx
\n
"
,
(
flags
<<
24
)
|
(
args
<<
16
)
|
(
i
-
spec
->
base
)
);
output
(
"
\t
movl $%u,%%edx
\n
"
,
(
odp
->
u
.
func
.
args_str_offset
<<
16
)
|
(
i
-
spec
->
base
)
);
output
(
"
\t
leaq .L__wine_spec_relay_descr(%%rip),%%rcx
\n
"
);
output
(
"
\t
callq *8(%%rcx)
\n
"
);
output
(
"
\t
addq $40,%%rsp
\n
"
);
output_cfi
(
".cfi_adjust_cfa_offset -40"
);
output
(
"
\t
ret
\n
"
);
break
;
...
...
@@ -432,12 +475,12 @@ void output_exports( DLLSPEC *spec )
}
output
(
".L__wine_spec_relay_descr:
\n
"
);
output
(
"
\t
%s 0xdeb9000
1
\n
"
,
get_asm_ptr_keyword
()
);
/* magic */
output
(
"
\t
%s 0
,0
\n
"
,
get_asm_ptr_keyword
()
);
/* relay funcs
*/
output
(
"
\t
%s 0xdeb9000
2
\n
"
,
get_asm_ptr_keyword
()
);
/* magic */
output
(
"
\t
%s 0
\n
"
,
get_asm_ptr_keyword
()
);
/* relay func
*/
output
(
"
\t
%s 0
\n
"
,
get_asm_ptr_keyword
()
);
/* private data */
output
(
"
\t
%s __wine_spec_relay_entry_points
\n
"
,
get_asm_ptr_keyword
()
);
output
(
"
\t
%s .L__wine_spec_relay_entry_point_offsets
\n
"
,
get_asm_ptr_keyword
()
);
output
(
"
\t
%s .L__wine_spec_relay_arg
_types
\n
"
,
get_asm_ptr_keyword
()
);
output
(
"
\t
%s .L__wine_spec_relay_arg
s_string
\n
"
,
get_asm_ptr_keyword
()
);
output_relay_debug
(
spec
);
}
...
...
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