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
39f6ab55
Commit
39f6ab55
authored
Feb 16, 2022
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winebuild: Add support for generating data-only DLLs.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
3eca3516
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
194 additions
and
74 deletions
+194
-74
build.h
tools/winebuild/build.h
+2
-0
main.c
tools/winebuild/main.c
+12
-0
parser.c
tools/winebuild/parser.c
+6
-0
spec32.c
tools/winebuild/spec32.c
+168
-73
utils.c
tools/winebuild/utils.c
+1
-1
winebuild.man.in
tools/winebuild/winebuild.man.in
+5
-0
No files found.
tools/winebuild/build.h
View file @
39f6ab55
...
...
@@ -283,6 +283,7 @@ extern void output_resources( DLLSPEC *spec );
extern
void
output_bin_resources
(
DLLSPEC
*
spec
,
unsigned
int
start_rva
);
extern
void
output_spec32_file
(
DLLSPEC
*
spec
);
extern
void
output_fake_module
(
DLLSPEC
*
spec
);
extern
void
output_data_module
(
DLLSPEC
*
spec
);
extern
void
output_def_file
(
DLLSPEC
*
spec
,
int
import_only
);
extern
void
load_res16_file
(
const
char
*
name
,
DLLSPEC
*
spec
);
extern
void
output_res16_data
(
DLLSPEC
*
spec
);
...
...
@@ -329,6 +330,7 @@ extern int use_msvcrt;
extern
int
unix_lib
;
extern
int
safe_seh
;
extern
int
prefer_native
;
extern
int
data_only
;
extern
char
*
input_file_name
;
extern
char
*
spec_file_name
;
...
...
tools/winebuild/main.c
View file @
39f6ab55
...
...
@@ -46,6 +46,7 @@ int use_msvcrt = 0;
int
unix_lib
=
0
;
int
safe_seh
=
0
;
int
prefer_native
=
0
;
int
data_only
=
0
;
struct
target
target
=
{
0
};
...
...
@@ -198,6 +199,7 @@ static const char usage_str[] =
" -b, --target=TARGET Specify target CPU and platform for cross-compiling
\n
"
" -B PREFIX Look for build tools in the PREFIX directory
\n
"
" --cc-cmd=CC C compiler to use for assembling (default: fall back to --as-cmd)
\n
"
" --data-only Generate a data-only dll (i.e. without any executable code)
\n
"
" -d, --delay-lib=LIB Import the specified library in delayed mode
\n
"
" -D SYM Ignored for C flags compatibility
\n
"
" -e, --entry=FUNC Set the DLL entry point function (default: DllMain)
\n
"
...
...
@@ -251,6 +253,7 @@ enum long_options_values
LONG_OPT_BUILTIN
,
LONG_OPT_ASCMD
,
LONG_OPT_CCCMD
,
LONG_OPT_DATA_ONLY
,
LONG_OPT_EXTERNAL_SYMS
,
LONG_OPT_FAKE_MODULE
,
LONG_OPT_FIXUP_CTORS
,
...
...
@@ -284,6 +287,7 @@ static const struct long_option long_options[] =
/* other long options */
{
"as-cmd"
,
1
,
LONG_OPT_ASCMD
},
{
"cc-cmd"
,
1
,
LONG_OPT_CCCMD
},
{
"data-only"
,
0
,
LONG_OPT_DATA_ONLY
},
{
"external-symbols"
,
0
,
LONG_OPT_EXTERNAL_SYMS
},
{
"fake-module"
,
0
,
LONG_OPT_FAKE_MODULE
},
{
"large-address-aware"
,
0
,
LONG_OPT_LARGE_ADDRESS_AWARE
},
...
...
@@ -483,6 +487,9 @@ static void option_callback( int optc, char *optarg )
case
LONG_OPT_CCCMD
:
cc_command
=
strarray_fromstring
(
optarg
,
" "
);
break
;
case
LONG_OPT_DATA_ONLY
:
data_only
=
1
;
break
;
case
LONG_OPT_FAKE_MODULE
:
fake_module
=
1
;
break
;
...
...
@@ -637,6 +644,11 @@ int main(int argc, char **argv)
output_fake_module
(
spec
);
break
;
}
if
(
data_only
)
{
output_data_module
(
spec
);
break
;
}
if
(
!
is_pe
())
{
files
=
load_import_libs
(
files
);
...
...
tools/winebuild/parser.c
View file @
39f6ab55
...
...
@@ -628,6 +628,12 @@ static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
return
1
;
}
if
(
data_only
&&
!
(
odp
->
flags
&
FLAG_FORWARD
))
{
error
(
"Only forwarded entry points are allowed in data-only mode
\n
"
);
goto
error
;
}
if
(
ordinal
!=
-
1
)
{
if
(
!
ordinal
)
...
...
tools/winebuild/spec32.c
View file @
39f6ab55
...
...
@@ -796,6 +796,7 @@ static struct
unsigned
int
file_align
;
unsigned
int
sec_count
;
unsigned
int
exp_count
;
unsigned
int
code_size
;
struct
dir_data
dir
[
16
];
struct
sec_data
sec
[
8
];
struct
exp_data
exp
[
8
];
...
...
@@ -846,96 +847,99 @@ static unsigned int flush_output_to_section( const char *name, int dir_idx, unsi
return
sec
->
size
;
}
/*******************************************************************
* output_fake_module
*
* Build a fake binary module from a spec file.
*/
void
output_fake_module
(
DLLSPEC
*
spec
)
static
void
output_pe_exports
(
DLLSPEC
*
spec
)
{
static
const
unsigned
char
dll_code_section
[]
=
{
0x31
,
0xc0
,
/* xor %eax,%eax */
0xc2
,
0x0c
,
0x00
};
/* ret $12 */
unsigned
int
i
,
exp_count
=
get_exports_count
(
spec
);
unsigned
int
exp_rva
=
current_rva
()
+
40
;
/* sizeof(IMAGE_EXPORT_DIRECTORY) */
unsigned
int
pos
,
str_rva
=
exp_rva
+
4
*
exp_count
+
6
*
spec
->
nb_names
;
static
const
unsigned
char
exe_code_section
[]
=
{
0xb8
,
0x01
,
0x00
,
0x00
,
0x00
,
/* movl $1,%eax */
0xc2
,
0x04
,
0x00
};
/* ret $4 */
const
unsigned
int
page_size
=
get_page_size
();
const
unsigned
int
lfanew
=
0x40
+
sizeof
(
fakedll_signature
);
unsigned
int
i
;
if
(
!
spec
->
nb_entry_points
)
return
;
resolve_imports
(
spec
);
init_output_buffer
();
p
e
.
section_align
=
page_size
;
p
e
.
file_align
=
0x200
;
/* .text section
*/
if
(
spec
->
characteristics
&
IMAGE_FILE_DLL
)
put_data
(
dll_code_section
,
sizeof
(
dll_code_section
)
);
else
put_data
(
exe_code_section
,
sizeof
(
exe_code_section
)
);
flush_output_to_section
(
".text"
,
-
1
,
0x60000020
/* CNT_CODE|MEM_EXECUTE|MEM_READ */
);
if
(
spec
->
type
==
SPEC_WIN16
)
put_dword
(
0
);
/* Characteristics */
p
ut_dword
(
hash_filename
(
spec
->
file_name
)
);
/* TimeDateStamp */
p
ut_word
(
0
);
/* MajorVersion */
put_word
(
0
);
/* MinorVersion */
put_dword
(
str_rva
);
/* Name
*/
put_dword
(
spec
->
base
);
/* Base */
put_dword
(
exp_count
);
/* NumberOfFunctions */
put_dword
(
spec
->
nb_names
);
/* NumberOfNames */
put_dword
(
exp_rva
);
/* AddressOfFunctions */
if
(
spec
->
nb_names
)
{
add_export
(
current_rva
(),
"__wine_spec_dos_header"
);
put_dword
(
exp_rva
+
4
*
exp_count
);
/* AddressOfNames */
put_dword
(
exp_rva
+
4
*
exp_count
+
4
*
spec
->
nb_names
);
/* AddressOfNameOrdinals */
}
else
{
put_dword
(
0
);
/* AddressOfNames */
put_dword
(
0
);
/* AddressOfNameOrdinals */
}
/* .rodata section */
output_fake_module16
(
spec
);
if
(
spec
->
main_module
)
/* functions */
for
(
i
=
0
,
pos
=
str_rva
+
strlen
(
spec
->
file_name
)
+
1
;
i
<
spec
->
nb_names
;
i
++
)
pos
+=
strlen
(
spec
->
names
[
i
]
->
name
)
+
1
;
for
(
i
=
spec
->
base
;
i
<=
spec
->
limit
;
i
++
)
{
ORDDEF
*
odp
=
spec
->
ordinals
[
i
];
if
(
odp
&&
(
odp
->
flags
&
FLAG_FORWARD
))
{
add_export
(
current_rva
()
+
output_buffer_pos
,
"__wine_spec_main_module"
);
p
ut_data
(
spec
->
main_module
,
strlen
(
spec
->
main_module
)
+
1
)
;
put_dword
(
pos
);
p
os
+=
strlen
(
odp
->
link_name
)
+
1
;
}
flush_output_to_section
(
".rodata"
,
-
1
,
0x40000040
/* CNT_INITIALIZED_DATA|MEM_READ */
);
else
put_dword
(
0
);
}
if
(
pe
.
exp_count
)
/* names */
for
(
i
=
0
,
pos
=
str_rva
+
strlen
(
spec
->
file_name
)
+
1
;
i
<
spec
->
nb_names
;
i
++
)
{
/* .edata section */
unsigned
int
exp_rva
=
current_rva
()
+
40
;
/* sizeof(IMAGE_EXPORT_DIRECTORY) */
unsigned
int
pos
,
str_rva
=
exp_rva
+
10
*
pe
.
exp_count
;
put_dword
(
pos
);
pos
+=
strlen
(
spec
->
names
[
i
]
->
name
)
+
1
;
}
put_dword
(
0
);
/* Characteristics */
put_dword
(
hash_filename
(
spec
->
file_name
)
);
/* TimeDateStamp */
put_word
(
0
);
/* MajorVersion */
put_word
(
0
);
/* MinorVersion */
put_dword
(
str_rva
);
/* Name */
put_dword
(
1
);
/* Base */
put_dword
(
pe
.
exp_count
);
/* NumberOfFunctions */
put_dword
(
pe
.
exp_count
);
/* NumberOfNames */
put_dword
(
exp_rva
);
/* AddressOfFunctions */
put_dword
(
exp_rva
+
4
*
pe
.
exp_count
);
/* AddressOfNames */
put_dword
(
exp_rva
+
8
*
pe
.
exp_count
);
/* AddressOfNameOrdinals */
/* ordinals */
for
(
i
=
0
;
i
<
spec
->
nb_names
;
i
++
)
put_word
(
spec
->
names
[
i
]
->
ordinal
-
spec
->
base
);
/* functions */
for
(
i
=
0
;
i
<
pe
.
exp_count
;
i
++
)
put_dword
(
pe
.
exp
[
i
].
rva
);
/* names */
for
(
i
=
0
,
pos
=
str_rva
+
strlen
(
spec
->
file_name
)
+
1
;
i
<
pe
.
exp_count
;
i
++
)
{
put_dword
(
pos
);
pos
+=
strlen
(
pe
.
exp
[
i
].
name
)
+
1
;
}
/* ordinals */
for
(
i
=
0
;
i
<
pe
.
exp_count
;
i
++
)
put_word
(
i
);
/* strings */
put_data
(
spec
->
file_name
,
strlen
(
spec
->
file_name
)
+
1
);
for
(
i
=
0
;
i
<
pe
.
exp_count
;
i
++
)
put_data
(
pe
.
exp
[
i
].
name
,
strlen
(
pe
.
exp
[
i
].
name
)
+
1
);
flush_output_to_section
(
".edata"
,
0
/* IMAGE_DIRECTORY_ENTRY_EXPORT */
,
0x40000040
/* CNT_INITIALIZED_DATA|MEM_READ */
);
/* strings */
put_data
(
spec
->
file_name
,
strlen
(
spec
->
file_name
)
+
1
);
for
(
i
=
0
;
i
<
spec
->
nb_names
;
i
++
)
put_data
(
spec
->
names
[
i
]
->
name
,
strlen
(
spec
->
names
[
i
]
->
name
)
+
1
);
for
(
i
=
spec
->
base
;
i
<=
spec
->
limit
;
i
++
)
{
ORDDEF
*
odp
=
spec
->
ordinals
[
i
];
if
(
odp
&&
(
odp
->
flags
&
FLAG_FORWARD
))
put_data
(
odp
->
link_name
,
strlen
(
odp
->
link_name
)
+
1
);
}
/* .reloc section */
put_dword
(
0
);
/* VirtualAddress */
put_dword
(
0
);
/* Size */
flush_output_to_section
(
".reloc"
,
5
/* IMAGE_DIRECTORY_ENTRY_BASERELOC */
,
0x42000040
/* CNT_INITIALIZED_DATA|MEM_DISCARDABLE|MEM_READ */
);
flush_output_to_section
(
".edata"
,
0
/* IMAGE_DIRECTORY_ENTRY_EXPORT */
,
0x40000040
/* CNT_INITIALIZED_DATA|MEM_READ */
);
}
static
void
output_pe_file
(
DLLSPEC
*
spec
,
const
char
signature
[
32
]
)
{
const
unsigned
int
lfanew
=
0x40
+
32
;
unsigned
int
i
;
init_output_buffer
();
/* .rsrc section */
if
(
spec
->
type
==
SPEC_WIN32
)
{
/* .rsrc section */
output_bin_resources
(
spec
,
current_rva
()
);
flush_output_to_section
(
".rsrc"
,
2
/* IMAGE_DIRECTORY_ENTRY_RESOURCE */
,
0x40000040
/* CNT_INITIALIZED_DATA|MEM_READ */
);
}
/* .reloc section */
if
(
pe
.
code_size
)
{
put_dword
(
0
);
/* VirtualAddress */
put_dword
(
0
);
/* Size */
flush_output_to_section
(
".reloc"
,
5
/* IMAGE_DIRECTORY_ENTRY_BASERELOC */
,
0x42000040
/* CNT_INITIALIZED_DATA|MEM_DISCARDABLE|MEM_READ */
);
}
put_word
(
0x5a4d
);
/* e_magic */
put_word
(
0x40
);
/* e_cblp */
put_word
(
0x01
);
/* e_cp */
...
...
@@ -961,7 +965,7 @@ void output_fake_module( DLLSPEC *spec )
put_dword
(
0
);
put_dword
(
lfanew
);
put_data
(
fakedll_signature
,
sizeof
(
fakedll_signature
)
);
put_data
(
signature
,
32
);
put_dword
(
0x4550
);
/* Signature */
switch
(
target
.
cpu
)
...
...
@@ -984,11 +988,11 @@ void output_fake_module( DLLSPEC *spec )
IMAGE_NT_OPTIONAL_HDR32_MAGIC
);
/* Magic */
put_byte
(
7
);
/* MajorLinkerVersion */
put_byte
(
10
);
/* MinorLinkerVersion */
put_dword
(
pe
.
sec
[
0
].
size
);
/* SizeOfCode */
put_dword
(
pe
.
code_size
);
/* SizeOfCode */
put_dword
(
0
);
/* SizeOfInitializedData */
put_dword
(
0
);
/* SizeOfUninitializedData */
put_dword
(
pe
.
sec
[
0
].
rva
);
/* AddressOfEntryPoint */
put_dword
(
pe
.
sec
[
0
].
rva
);
/* BaseOfCode */
put_dword
(
pe
.
code_size
?
pe
.
sec
[
0
].
rva
:
0
);
/* AddressOfEntryPoint */
put_dword
(
pe
.
code_size
?
pe
.
sec
[
0
].
rva
:
0
);
/* BaseOfCode */
if
(
get_ptr_size
()
==
4
)
put_dword
(
0
);
/* BaseOfData */
put_pword
(
0x10000000
);
/* ImageBase */
put_dword
(
pe
.
section_align
);
/* SectionAlignment */
...
...
@@ -1006,9 +1010,9 @@ void output_fake_module( DLLSPEC *spec )
put_word
(
spec
->
subsystem
);
/* Subsystem */
put_word
(
spec
->
dll_characteristics
);
/* DllCharacteristics */
put_pword
(
(
spec
->
stack_size
?
spec
->
stack_size
:
1024
)
*
1024
);
/* SizeOfStackReserve */
put_pword
(
p
age_size
);
/* SizeOfStackCommit */
put_pword
(
p
e
.
section_align
);
/* SizeOfStackCommit */
put_pword
(
(
spec
->
heap_size
?
spec
->
heap_size
:
1024
)
*
1024
);
/* SizeOfHeapReserve */
put_pword
(
p
age_size
);
/* SizeOfHeapCommit */
put_pword
(
p
e
.
section_align
);
/* SizeOfHeapCommit */
put_dword
(
0
);
/* LoaderFlags */
put_dword
(
16
);
/* NumberOfRvaAndSizes */
...
...
@@ -1044,6 +1048,97 @@ void output_fake_module( DLLSPEC *spec )
flush_output_buffer
(
output_file_name
?
output_file_name
:
spec
->
file_name
);
}
/*******************************************************************
* output_fake_module
*
* Build a fake binary module from a spec file.
*/
void
output_fake_module
(
DLLSPEC
*
spec
)
{
static
const
unsigned
char
dll_code_section
[]
=
{
0x31
,
0xc0
,
/* xor %eax,%eax */
0xc2
,
0x0c
,
0x00
};
/* ret $12 */
static
const
unsigned
char
exe_code_section
[]
=
{
0xb8
,
0x01
,
0x00
,
0x00
,
0x00
,
/* movl $1,%eax */
0xc2
,
0x04
,
0x00
};
/* ret $4 */
unsigned
int
i
;
resolve_imports
(
spec
);
pe
.
section_align
=
get_page_size
();
pe
.
file_align
=
0x200
;
init_output_buffer
();
/* .text section */
if
(
spec
->
characteristics
&
IMAGE_FILE_DLL
)
put_data
(
dll_code_section
,
sizeof
(
dll_code_section
)
);
else
put_data
(
exe_code_section
,
sizeof
(
exe_code_section
)
);
pe
.
code_size
=
output_buffer_pos
;
flush_output_to_section
(
".text"
,
-
1
,
0x60000020
/* CNT_CODE|MEM_EXECUTE|MEM_READ */
);
if
(
spec
->
type
==
SPEC_WIN16
)
{
add_export
(
current_rva
(),
"__wine_spec_dos_header"
);
/* .rdata section */
output_fake_module16
(
spec
);
if
(
spec
->
main_module
)
{
add_export
(
current_rva
()
+
output_buffer_pos
,
"__wine_spec_main_module"
);
put_data
(
spec
->
main_module
,
strlen
(
spec
->
main_module
)
+
1
);
}
flush_output_to_section
(
".rdata"
,
-
1
,
0x40000040
/* CNT_INITIALIZED_DATA|MEM_READ */
);
}
/* .edata section */
if
(
pe
.
exp_count
)
{
unsigned
int
exp_rva
=
current_rva
()
+
40
;
/* sizeof(IMAGE_EXPORT_DIRECTORY) */
unsigned
int
pos
,
str_rva
=
exp_rva
+
10
*
pe
.
exp_count
;
put_dword
(
0
);
/* Characteristics */
put_dword
(
hash_filename
(
spec
->
file_name
)
);
/* TimeDateStamp */
put_word
(
0
);
/* MajorVersion */
put_word
(
0
);
/* MinorVersion */
put_dword
(
str_rva
);
/* Name */
put_dword
(
1
);
/* Base */
put_dword
(
pe
.
exp_count
);
/* NumberOfFunctions */
put_dword
(
pe
.
exp_count
);
/* NumberOfNames */
put_dword
(
exp_rva
);
/* AddressOfFunctions */
put_dword
(
exp_rva
+
4
*
pe
.
exp_count
);
/* AddressOfNames */
put_dword
(
exp_rva
+
8
*
pe
.
exp_count
);
/* AddressOfNameOrdinals */
/* functions */
for
(
i
=
0
;
i
<
pe
.
exp_count
;
i
++
)
put_dword
(
pe
.
exp
[
i
].
rva
);
/* names */
for
(
i
=
0
,
pos
=
str_rva
+
strlen
(
spec
->
file_name
)
+
1
;
i
<
pe
.
exp_count
;
i
++
)
{
put_dword
(
pos
);
pos
+=
strlen
(
pe
.
exp
[
i
].
name
)
+
1
;
}
/* ordinals */
for
(
i
=
0
;
i
<
pe
.
exp_count
;
i
++
)
put_word
(
i
);
/* strings */
put_data
(
spec
->
file_name
,
strlen
(
spec
->
file_name
)
+
1
);
for
(
i
=
0
;
i
<
pe
.
exp_count
;
i
++
)
put_data
(
pe
.
exp
[
i
].
name
,
strlen
(
pe
.
exp
[
i
].
name
)
+
1
);
flush_output_to_section
(
".edata"
,
0
/* IMAGE_DIRECTORY_ENTRY_EXPORT */
,
0x40000040
/* CNT_INITIALIZED_DATA|MEM_READ */
);
}
output_pe_file
(
spec
,
fakedll_signature
);
}
/*******************************************************************
* output_data_module
*
* Build a data-only module from a spec file.
*/
void
output_data_module
(
DLLSPEC
*
spec
)
{
pe
.
section_align
=
pe
.
file_align
=
get_page_size
();
output_pe_exports
(
spec
);
output_pe_file
(
spec
,
builtin_signature
);
}
/*******************************************************************
* output_def_file
...
...
tools/winebuild/utils.c
View file @
39f6ab55
...
...
@@ -644,7 +644,7 @@ DLLSPEC *alloc_dll_spec(void)
spec
->
type
=
SPEC_WIN32
;
spec
->
base
=
MAX_ORDINALS
;
spec
->
characteristics
=
IMAGE_FILE_EXECUTABLE_IMAGE
;
spec
->
subsystem
=
0
;
spec
->
subsystem
=
IMAGE_SUBSYSTEM_WINDOWS_CUI
;
spec
->
subsystem_major
=
4
;
spec
->
subsystem_minor
=
0
;
spec
->
syscall_table
=
0
;
...
...
tools/winebuild/winebuild.man.in
View file @
39f6ab55
...
...
@@ -89,6 +89,11 @@ like \fBas\fR, \fBnm\fR and \fBld\fR.
Specify the C compiler to use to compile assembly files; the default
is to instead use the assembler specified with \fB--as-cmd\fR.
.TP
.B \--data-only
Build a module that contains only data and resources, and no
executable code. With this option, \fBwinebuild\fR directly outputs a
PE file, instead of an assembly or object file.
.TP
.BI \-d,\ --delay-lib= name
Set the delayed import mode for the specified library, which must be
one of the libraries imported with the \fB-l\fR option. Delayed mode
...
...
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