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
b2d09cbb
Commit
b2d09cbb
authored
Jul 07, 2020
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winebuild: Add generation of system call thunks.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
a0266339
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
183 additions
and
21 deletions
+183
-21
build.h
tools/winebuild/build.h
+2
-0
import.c
tools/winebuild/import.c
+164
-0
spec16.c
tools/winebuild/spec16.c
+0
-21
spec32.c
tools/winebuild/spec32.c
+1
-0
utils.c
tools/winebuild/utils.c
+16
-0
No files found.
tools/winebuild/build.h
View file @
b2d09cbb
...
...
@@ -276,6 +276,7 @@ extern void free_dll_spec( DLLSPEC *spec );
extern
char
*
make_c_identifier
(
const
char
*
str
);
extern
const
char
*
get_stub_name
(
const
ORDDEF
*
odp
,
const
DLLSPEC
*
spec
);
extern
const
char
*
get_link_name
(
const
ORDDEF
*
odp
);
extern
int
sort_func_list
(
ORDDEF
**
list
,
int
count
,
int
(
*
compare
)(
const
void
*
,
const
void
*
)
);
extern
int
get_cpu_from_name
(
const
char
*
name
);
extern
unsigned
int
get_alignment
(
unsigned
int
align
);
extern
unsigned
int
get_page_size
(
void
);
...
...
@@ -303,6 +304,7 @@ extern int has_imports(void);
extern
void
output_get_pc_thunk
(
void
);
extern
void
output_module
(
DLLSPEC
*
spec
);
extern
void
output_stubs
(
DLLSPEC
*
spec
);
extern
void
output_syscalls
(
DLLSPEC
*
spec
);
extern
void
output_imports
(
DLLSPEC
*
spec
);
extern
void
output_static_lib
(
DLLSPEC
*
spec
,
char
**
argv
);
extern
void
output_exports
(
DLLSPEC
*
spec
);
...
...
tools/winebuild/import.c
View file @
b2d09cbb
...
...
@@ -563,6 +563,7 @@ static void check_undefined_exports( DLLSPEC *spec )
spec
->
src_name
,
odp
->
lineno
,
odp
->
link_name
);
break
;
default:
if
(
!
strcmp
(
odp
->
link_name
,
"__wine_syscall_dispatcher"
))
break
;
error
(
"%s:%d: external symbol '%s' is not a function
\n
"
,
spec
->
src_name
,
odp
->
lineno
,
odp
->
link_name
);
break
;
...
...
@@ -1402,6 +1403,169 @@ void output_stubs( DLLSPEC *spec )
}
}
static
int
cmp_link_name
(
const
void
*
e1
,
const
void
*
e2
)
{
const
ORDDEF
*
odp1
=
*
(
const
ORDDEF
*
const
*
)
e1
;
const
ORDDEF
*
odp2
=
*
(
const
ORDDEF
*
const
*
)
e2
;
return
strcmp
(
odp1
->
link_name
,
odp2
->
link_name
);
}
/* output the functions for system calls */
void
output_syscalls
(
DLLSPEC
*
spec
)
{
const
unsigned
int
invalid_param
=
0xc000000d
;
/* STATUS_INVALID_PARAMETER */
int
i
,
count
;
ORDDEF
**
syscalls
=
NULL
;
for
(
i
=
count
=
0
;
i
<
spec
->
nb_entry_points
;
i
++
)
{
ORDDEF
*
odp
=
&
spec
->
entry_points
[
i
];
if
(
!
(
odp
->
flags
&
FLAG_SYSCALL
))
continue
;
if
(
!
syscalls
)
syscalls
=
xmalloc
(
(
spec
->
nb_entry_points
-
i
)
*
sizeof
(
*
syscalls
)
);
syscalls
[
count
++
]
=
odp
;
}
if
(
!
count
)
return
;
count
=
sort_func_list
(
syscalls
,
count
,
cmp_link_name
);
output
(
"
\n
/* system calls */
\n\n
"
);
output
(
"
\t
.text
\n
"
);
if
(
unix_lib
)
{
output
(
"
\t
.align %d
\n
"
,
get_alignment
(
4
)
);
output
(
"
\t
%s
\n
"
,
func_declaration
(
"__wine_syscall_dispatcher"
)
);
output
(
"%s
\n
"
,
asm_globl
(
"__wine_syscall_dispatcher"
)
);
output_cfi
(
".cfi_startproc"
);
switch
(
target_cpu
)
{
case
CPU_x86
:
output
(
"
\t
cmpl $%u,%%eax
\n
"
,
count
);
output
(
"
\t
jae 1f
\n
"
);
output
(
"
\t
addl $4,%%esp
\n
"
);
if
(
UsePIC
)
{
output
(
"
\t
movl %%eax,%%edx
\n
"
);
output
(
"
\t
call %s
\n
"
,
asm_name
(
"__wine_spec_get_pc_thunk_eax"
)
);
output
(
"1:
\t
jmp *.Lsyscall_table-1b(%%eax,%%edx,4)
\n
"
);
needs_get_pc_thunk
=
1
;
}
else
output
(
"
\t
jmp *.Lsyscall_table(,%%eax,4)
\n
"
);
output
(
"1:
\t
movl $0x%x,%%eax
\n
"
,
invalid_param
);
output
(
"
\t
ret
\n
"
);
break
;
case
CPU_x86_64
:
output
(
"
\t
cmpq $%u,%%rax
\n
"
,
count
);
output
(
"
\t
jae 1f
\n
"
);
output
(
"
\t
leaq .Lsyscall_table(%%rip),%%r10
\n
"
);
output
(
"
\t
jmpq *(%%r10,%%rax,8)
\n
"
);
output
(
"1:
\t
movl $0x%x,%%eax
\n
"
,
invalid_param
);
output
(
"
\t
ret
\n
"
);
break
;
case
CPU_ARM
:
output
(
"
\t
ldr r1, 4f
\n
"
);
output
(
"
\t
cmp r0, r1
\n
"
);
output
(
"
\t
bcs 2f
\n
"
);
output
(
"
\t
ldr r1, 3f
\n
"
);
output
(
"
\t
add r1, pc
\n
"
);
output
(
"
\t
ldr ip, [r1, r0, lsl #2]
\n
"
);
output
(
"1:
\t
pop {r0-r1}
\n
"
);
output
(
"
\t
bx ip
\n
"
);
output
(
"2:
\t
pop {r0-r1}
\n
"
);
output
(
"
\t
ldr r0,5f
\n
"
);
output
(
"bx lr
\n
"
);
output
(
"3:
\t
.long .Lsyscall_table-1b
\n
"
);
output
(
"4:
\t
.long %u
\n
"
,
count
);
output
(
"5:
\t
.long 0x%x
\n
"
,
invalid_param
);
break
;
case
CPU_ARM64
:
output
(
"
\t
cmp x8, %u
\n
"
,
count
);
output
(
"
\t
bcs 1f
\n
"
);
output
(
"
\t
adrp x16, .Lsyscall_table
\n
"
);
output
(
"
\t
add x16, x16, #:lo12:.Lsyscall_table
\n
"
);
output
(
"
\t
ldr x16, [x16, x8, lsl 3]
\n
"
);
output
(
"
\t
br x16
\n
"
);
output
(
"1:
\t
mov x0, #0x%x
\n
"
,
invalid_param
&
0xffff0000
);
output
(
"
\t
movk x0, #0x%x
\n
"
,
invalid_param
&
0x0000ffff
);
output
(
"
\t
ret
\n
"
);
break
;
default:
assert
(
0
);
}
output_cfi
(
".cfi_endproc"
);
output_function_size
(
"__wine_syscall_dispatcher"
);
output
(
"
\t
.data
\n
"
);
output
(
"
\t
.align %d
\n
"
,
get_alignment
(
get_ptr_size
()
)
);
output
(
".Lsyscall_table:
\n
"
);
for
(
i
=
0
;
i
<
count
;
i
++
)
output
(
"
\t
%s %s
\n
"
,
get_asm_ptr_keyword
(),
asm_name
(
get_link_name
(
syscalls
[
i
]
)));
return
;
}
for
(
i
=
0
;
i
<
count
;
i
++
)
{
ORDDEF
*
odp
=
syscalls
[
i
];
const
char
*
name
=
get_link_name
(
odp
);
output
(
"
\t
.align %d
\n
"
,
get_alignment
(
16
)
);
output
(
"
\t
%s
\n
"
,
func_declaration
(
name
)
);
output
(
"%s
\n
"
,
asm_globl
(
name
)
);
output_cfi
(
".cfi_startproc"
);
switch
(
target_cpu
)
{
case
CPU_x86
:
/* FIXME: syscall thunks not binary-compatible yet */
if
(
UsePIC
)
{
output
(
"
\t
call %s
\n
"
,
asm_name
(
"__wine_spec_get_pc_thunk_eax"
)
);
output
(
"1:
\t
movl %s-1b(%%eax),%%edx
\n
"
,
asm_name
(
"__wine_syscall_dispatcher"
)
);
output
(
"
\t
movl $%u,%%eax
\n
"
,
i
);
output
(
"
\t
call *%%edx
\n
"
);
needs_get_pc_thunk
=
1
;
}
else
{
output
(
"
\t
movl $%u,%%eax
\n
"
,
i
);
output
(
"
\t
call *(%s)
\n
"
,
asm_name
(
"__wine_syscall_dispatcher"
)
);
}
output
(
"
\t
ret $%u
\n
"
,
get_args_size
(
odp
));
break
;
case
CPU_x86_64
:
/* FIXME: syscall thunks not binary-compatible yet */
output
(
"
\t
movl $%u,%%eax
\n
"
,
i
);
output
(
"
\t
jmpq *%s(%%rip)
\n
"
,
asm_name
(
"__wine_syscall_dispatcher"
)
);
break
;
case
CPU_ARM
:
output
(
"
\t
push {r0-r1}
\n
"
);
output
(
"
\t
ldr r0, 3f
\n
"
);
output
(
"
\t
ldr r1, 2f
\n
"
);
output
(
"
\t
add r1, pc
\n
"
);
output
(
"
\t
ldr ip, [r1]
\n
"
);
output
(
"1:
\t
bx ip
\n
"
);
output
(
"2:
\t
.long %s-1b
\n
"
,
asm_name
(
"__wine_syscall_dispatcher"
)
);
output
(
"3:
\t
.long %u
\n
"
,
i
);
break
;
case
CPU_ARM64
:
output
(
"
\t
mov x8, #%u
\n
"
,
i
);
output
(
"
\t
adrp x16, %s
\n
"
,
asm_name
(
"__wine_syscall_dispatcher"
)
);
output
(
"
\t
ldr x16, [x16, #:lo12:%s]
\n
"
,
asm_name
(
"__wine_syscall_dispatcher"
)
);
output
(
"
\t
br x16
\n
"
);
break
;
default:
assert
(
0
);
}
output_cfi
(
".cfi_endproc"
);
output_function_size
(
name
);
}
output
(
"
\t
.data
\n
"
);
output
(
"
\t
.align %d
\n
"
,
get_alignment
(
get_ptr_size
()
)
);
output
(
"%s
\n
"
,
asm_globl
(
"__wine_syscall_dispatcher"
)
);
output
(
"
\t
%s 0
\n
"
,
get_asm_ptr_keyword
()
);
}
/* output the import and delayed import tables of a Win32 module */
void
output_imports
(
DLLSPEC
*
spec
)
{
...
...
tools/winebuild/spec16.c
View file @
b2d09cbb
...
...
@@ -496,27 +496,6 @@ static int relay_type_compare( const void *e1, const void *e2 )
/*******************************************************************
* sort_func_list
*
* Sort a list of functions, removing duplicates.
*/
static
int
sort_func_list
(
ORDDEF
**
list
,
int
count
,
int
(
*
compare
)(
const
void
*
,
const
void
*
)
)
{
int
i
,
j
;
if
(
!
count
)
return
0
;
qsort
(
list
,
count
,
sizeof
(
*
list
),
compare
);
for
(
i
=
j
=
0
;
i
<
count
;
i
++
)
{
if
(
compare
(
&
list
[
j
],
&
list
[
i
]
))
list
[
++
j
]
=
list
[
i
];
}
return
j
+
1
;
}
/*******************************************************************
* output_module16
*
* Output code for a 16-bit module.
...
...
tools/winebuild/spec32.c
View file @
b2d09cbb
...
...
@@ -739,6 +739,7 @@ void output_spec32_file( DLLSPEC *spec )
output_stubs
(
spec
);
output_exports
(
spec
);
output_imports
(
spec
);
output_syscalls
(
spec
);
if
(
needs_get_pc_thunk
)
output_get_pc_thunk
();
output_resources
(
spec
);
output_gnu_stack_note
();
...
...
tools/winebuild/utils.c
View file @
b2d09cbb
...
...
@@ -960,6 +960,22 @@ const char *get_link_name( const ORDDEF *odp )
return
ret
;
}
/*******************************************************************
* sort_func_list
*
* Sort a list of functions, removing duplicates.
*/
int
sort_func_list
(
ORDDEF
**
list
,
int
count
,
int
(
*
compare
)(
const
void
*
,
const
void
*
)
)
{
int
i
,
j
;
if
(
!
count
)
return
0
;
qsort
(
list
,
count
,
sizeof
(
*
list
),
compare
);
for
(
i
=
j
=
0
;
i
<
count
;
i
++
)
if
(
compare
(
&
list
[
j
],
&
list
[
i
]
))
list
[
++
j
]
=
list
[
i
];
return
j
+
1
;
}
/* parse a cpu name and return the corresponding value */
int
get_cpu_from_name
(
const
char
*
name
)
{
...
...
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