Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
8a306489
Commit
8a306489
authored
Feb 18, 2022
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winebuild: Add support for building apiset data.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
6f1fd16f
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
296 additions
and
5 deletions
+296
-5
build.h
tools/winebuild/build.h
+30
-0
parser.c
tools/winebuild/parser.c
+134
-5
spec32.c
tools/winebuild/spec32.c
+113
-0
winebuild.man.in
tools/winebuild/winebuild.man.in
+19
-0
No files found.
tools/winebuild/build.h
View file @
8a306489
...
@@ -105,6 +105,34 @@ typedef struct
...
@@ -105,6 +105,34 @@ typedef struct
}
u
;
}
u
;
}
ORDDEF
;
}
ORDDEF
;
struct
apiset_entry
{
unsigned
int
name_off
;
unsigned
int
name_len
;
unsigned
int
hash
;
unsigned
int
hash_len
;
unsigned
int
val_count
;
struct
apiset_value
{
unsigned
int
name_off
;
unsigned
int
name_len
;
unsigned
int
val_off
;
unsigned
int
val_len
;
}
values
[
4
];
};
struct
apiset
{
unsigned
int
count
;
unsigned
int
size
;
struct
apiset_entry
*
entries
;
unsigned
int
str_pos
;
unsigned
int
str_size
;
char
*
strings
;
};
static
const
unsigned
int
apiset_hash_factor
=
31
;
typedef
struct
typedef
struct
{
{
char
*
src_name
;
/* file name of the source spec file */
char
*
src_name
;
/* file name of the source spec file */
...
@@ -133,6 +161,7 @@ typedef struct
...
@@ -133,6 +161,7 @@ typedef struct
ORDDEF
**
names
;
/* array of entry point names (points into entry_points) */
ORDDEF
**
names
;
/* array of entry point names (points into entry_points) */
ORDDEF
**
ordinals
;
/* array of dll ordinals (points into entry_points) */
ORDDEF
**
ordinals
;
/* array of dll ordinals (points into entry_points) */
struct
resource
*
resources
;
/* array of dll resources (format differs between Win16/Win32) */
struct
resource
*
resources
;
/* array of dll resources (format differs between Win16/Win32) */
struct
apiset
apiset
;
/* list of defined api sets */
}
DLLSPEC
;
}
DLLSPEC
;
extern
char
*
target_alias
;
extern
char
*
target_alias
;
...
@@ -285,6 +314,7 @@ extern void output_spec32_file( DLLSPEC *spec );
...
@@ -285,6 +314,7 @@ extern void output_spec32_file( DLLSPEC *spec );
extern
void
output_fake_module
(
DLLSPEC
*
spec
);
extern
void
output_fake_module
(
DLLSPEC
*
spec
);
extern
void
output_data_module
(
DLLSPEC
*
spec
);
extern
void
output_data_module
(
DLLSPEC
*
spec
);
extern
void
output_def_file
(
DLLSPEC
*
spec
,
int
import_only
);
extern
void
output_def_file
(
DLLSPEC
*
spec
,
int
import_only
);
extern
void
output_apiset_lib
(
DLLSPEC
*
spec
,
const
struct
apiset
*
apiset
);
extern
void
load_res16_file
(
const
char
*
name
,
DLLSPEC
*
spec
);
extern
void
load_res16_file
(
const
char
*
name
,
DLLSPEC
*
spec
);
extern
void
output_res16_data
(
DLLSPEC
*
spec
);
extern
void
output_res16_data
(
DLLSPEC
*
spec
);
extern
void
output_bin_res16_data
(
DLLSPEC
*
spec
);
extern
void
output_bin_res16_data
(
DLLSPEC
*
spec
);
...
...
tools/winebuild/parser.c
View file @
8a306489
...
@@ -471,14 +471,13 @@ static int parse_spec_extern( ORDDEF *odp, DLLSPEC *spec )
...
@@ -471,14 +471,13 @@ static int parse_spec_extern( ORDDEF *odp, DLLSPEC *spec )
*
*
* Parse the optional flags for an entry point in a .spec file.
* Parse the optional flags for an entry point in a .spec file.
*/
*/
static
const
char
*
parse_spec_flags
(
DLLSPEC
*
spec
,
ORDDEF
*
odp
)
static
const
char
*
parse_spec_flags
(
DLLSPEC
*
spec
,
ORDDEF
*
odp
,
const
char
*
token
)
{
{
unsigned
int
i
,
cpu_mask
=
0
;
unsigned
int
i
,
cpu_mask
=
0
;
const
char
*
token
;
do
do
{
{
if
(
!
(
token
=
GetToken
(
0
)))
break
;
token
++
;
if
(
!
strncmp
(
token
,
"arch="
,
5
))
if
(
!
strncmp
(
token
,
"arch="
,
5
))
{
{
char
*
args
=
xstrdup
(
token
+
5
);
char
*
args
=
xstrdup
(
token
+
5
);
...
@@ -578,7 +577,7 @@ static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
...
@@ -578,7 +577,7 @@ static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
}
}
if
(
!
(
token
=
GetToken
(
0
)))
goto
error
;
if
(
!
(
token
=
GetToken
(
0
)))
goto
error
;
if
(
*
token
==
'-'
&&
!
(
token
=
parse_spec_flags
(
spec
,
odp
)))
goto
error
;
if
(
*
token
==
'-'
&&
!
(
token
=
parse_spec_flags
(
spec
,
odp
,
token
)))
goto
error
;
if
(
ordinal
==
-
1
&&
spec
->
type
!=
SPEC_WIN32
&&
!
(
odp
->
flags
&
FLAG_EXPORT32
))
if
(
ordinal
==
-
1
&&
spec
->
type
!=
SPEC_WIN32
&&
!
(
odp
->
flags
&
FLAG_EXPORT32
))
{
{
...
@@ -703,6 +702,132 @@ error:
...
@@ -703,6 +702,132 @@ error:
}
}
static
unsigned
int
apiset_hash_len
(
const
char
*
str
)
{
return
strrchr
(
str
,
'-'
)
-
str
;
}
static
unsigned
int
apiset_hash
(
const
char
*
str
)
{
unsigned
int
ret
=
0
,
len
=
apiset_hash_len
(
str
);
while
(
len
--
)
ret
=
ret
*
apiset_hash_factor
+
*
str
++
;
return
ret
;
}
static
unsigned
int
apiset_add_str
(
struct
apiset
*
apiset
,
const
char
*
str
,
unsigned
int
len
)
{
char
*
ret
;
if
(
!
apiset
->
strings
||
!
(
ret
=
strstr
(
apiset
->
strings
,
str
)))
{
if
(
apiset
->
str_pos
+
len
>=
apiset
->
str_size
)
{
apiset
->
str_size
=
max
(
apiset
->
str_size
*
2
,
1024
);
apiset
->
strings
=
xrealloc
(
apiset
->
strings
,
apiset
->
str_size
);
}
ret
=
apiset
->
strings
+
apiset
->
str_pos
;
memcpy
(
ret
,
str
,
len
);
ret
[
len
]
=
0
;
apiset
->
str_pos
+=
len
;
}
return
ret
-
apiset
->
strings
;
}
static
void
add_apiset
(
struct
apiset
*
apiset
,
const
char
*
api
)
{
struct
apiset_entry
*
entry
;
if
(
apiset
->
count
==
apiset
->
size
)
{
apiset
->
size
=
max
(
apiset
->
size
*
2
,
64
);
apiset
->
entries
=
xrealloc
(
apiset
->
entries
,
apiset
->
size
*
sizeof
(
*
apiset
->
entries
)
);
}
entry
=
&
apiset
->
entries
[
apiset
->
count
++
];
entry
->
name_len
=
strlen
(
api
);
entry
->
name_off
=
apiset_add_str
(
apiset
,
api
,
entry
->
name_len
);
entry
->
hash
=
apiset_hash
(
api
);
entry
->
hash_len
=
apiset_hash_len
(
api
);
entry
->
val_count
=
0
;
}
static
void
add_apiset_value
(
struct
apiset
*
apiset
,
const
char
*
value
)
{
struct
apiset_entry
*
entry
=
&
apiset
->
entries
[
apiset
->
count
-
1
];
if
(
entry
->
val_count
<
ARRAY_SIZE
(
entry
->
values
)
-
1
)
{
struct
apiset_value
*
val
=
&
entry
->
values
[
entry
->
val_count
++
];
char
*
sep
=
strchr
(
value
,
':'
);
if
(
sep
)
{
val
->
name_len
=
sep
-
value
;
val
->
name_off
=
apiset_add_str
(
apiset
,
value
,
val
->
name_len
);
val
->
val_len
=
strlen
(
sep
+
1
);
val
->
val_off
=
apiset_add_str
(
apiset
,
sep
+
1
,
val
->
val_len
);
}
else
{
val
->
name_len
=
val
->
name_off
=
0
;
val
->
val_len
=
strlen
(
value
);
val
->
val_off
=
apiset_add_str
(
apiset
,
value
,
val
->
val_len
);
}
}
else
error
(
"Too many values for api '%.*s'
\n
"
,
entry
->
name_len
,
apiset
->
strings
+
entry
->
name_off
);
}
/*******************************************************************
* parse_spec_apiset
*/
static
int
parse_spec_apiset
(
DLLSPEC
*
spec
)
{
struct
apiset_entry
*
entry
;
const
char
*
token
;
unsigned
int
i
,
hash
;
if
(
!
data_only
)
{
error
(
"Apiset definitions are only allowed in data-only mode
\n
"
);
return
0
;
}
if
(
!
(
token
=
GetToken
(
0
)))
return
0
;
if
(
!
strncmp
(
token
,
"api-"
,
4
)
&&
!
strncmp
(
token
,
"ext-"
,
4
))
{
error
(
"Unrecognized API set name '%s'
\n
"
,
token
);
return
0
;
}
hash
=
apiset_hash
(
token
);
for
(
i
=
0
,
entry
=
spec
->
apiset
.
entries
;
i
<
spec
->
apiset
.
count
;
i
++
,
entry
++
)
{
if
(
entry
->
name_len
==
strlen
(
token
)
&&
!
strncmp
(
spec
->
apiset
.
strings
+
entry
->
name_off
,
token
,
entry
->
name_len
))
{
error
(
"Duplicate API set '%s'
\n
"
,
token
);
return
0
;
}
if
(
entry
->
hash
==
hash
)
{
error
(
"Duplicate hash code '%.*s' and '%s'
\n
"
,
entry
->
name_len
,
spec
->
apiset
.
strings
+
entry
->
name_off
,
token
);
return
0
;
}
}
add_apiset
(
&
spec
->
apiset
,
token
);
if
(
!
(
token
=
GetToken
(
0
))
||
strcmp
(
token
,
"="
))
{
error
(
"Syntax error near '%s'
\n
"
,
token
);
return
0
;
}
while
((
token
=
GetToken
(
1
)))
add_apiset_value
(
&
spec
->
apiset
,
token
);
return
1
;
}
static
int
name_compare
(
const
void
*
ptr1
,
const
void
*
ptr2
)
static
int
name_compare
(
const
void
*
ptr1
,
const
void
*
ptr2
)
{
{
const
ORDDEF
*
odp1
=
*
(
const
ORDDEF
*
const
*
)
ptr1
;
const
ORDDEF
*
odp1
=
*
(
const
ORDDEF
*
const
*
)
ptr1
;
...
@@ -898,7 +1023,7 @@ int parse_spec_file( FILE *file, DLLSPEC *spec )
...
@@ -898,7 +1023,7 @@ int parse_spec_file( FILE *file, DLLSPEC *spec )
current_line
=
0
;
current_line
=
0
;
comment_chars
=
"#;"
;
comment_chars
=
"#;"
;
separator_chars
=
"()
-
"
;
separator_chars
=
"()"
;
while
(
get_next_line
())
while
(
get_next_line
())
{
{
...
@@ -911,6 +1036,10 @@ int parse_spec_file( FILE *file, DLLSPEC *spec )
...
@@ -911,6 +1036,10 @@ int parse_spec_file( FILE *file, DLLSPEC *spec )
{
{
if
(
!
parse_spec_ordinal
(
atoi
(
token
),
spec
))
continue
;
if
(
!
parse_spec_ordinal
(
atoi
(
token
),
spec
))
continue
;
}
}
else
if
(
strcmp
(
token
,
"apiset"
)
==
0
)
{
if
(
!
parse_spec_apiset
(
spec
))
continue
;
}
else
else
{
{
error
(
"Expected ordinal declaration, got '%s'
\n
"
,
token
);
error
(
"Expected ordinal declaration, got '%s'
\n
"
,
token
);
...
...
tools/winebuild/spec32.c
View file @
8a306489
...
@@ -916,6 +916,118 @@ static void output_pe_exports( DLLSPEC *spec )
...
@@ -916,6 +916,118 @@ static void output_pe_exports( DLLSPEC *spec )
}
}
/* apiset hash table */
struct
apiset_hash_entry
{
unsigned
int
hash
;
unsigned
int
index
;
};
static
int
apiset_hash_cmp
(
const
void
*
h1
,
const
void
*
h2
)
{
const
struct
apiset_hash_entry
*
entry1
=
h1
;
const
struct
apiset_hash_entry
*
entry2
=
h2
;
if
(
entry1
->
hash
>
entry2
->
hash
)
return
1
;
if
(
entry1
->
hash
<
entry2
->
hash
)
return
-
1
;
return
0
;
}
static
void
output_apiset_section
(
const
struct
apiset
*
apiset
)
{
struct
apiset_hash_entry
*
hash
;
struct
apiset_entry
*
e
;
unsigned
int
i
,
j
,
str_pos
,
value_pos
,
hash_pos
,
size
;
init_output_buffer
();
value_pos
=
0x1c
/* header */
+
apiset
->
count
*
0x18
;
/* names */
str_pos
=
value_pos
;
for
(
i
=
0
,
e
=
apiset
->
entries
;
i
<
apiset
->
count
;
i
++
,
e
++
)
str_pos
+=
0x14
*
max
(
1
,
e
->
val_count
);
/* values */
hash_pos
=
str_pos
+
((
apiset
->
str_pos
*
2
+
3
)
&
~
3
);
size
=
hash_pos
+
apiset
->
count
*
8
;
/* hashes */
/* header */
put_dword
(
6
);
/* Version */
put_dword
(
size
);
/* Size */
put_dword
(
0
);
/* Flags */
put_dword
(
apiset
->
count
);
/* Count */
put_dword
(
0x1c
);
/* EntryOffset */
put_dword
(
hash_pos
);
/* HashOffset */
put_dword
(
apiset_hash_factor
);
/* HashFactor */
/* name entries */
value_pos
=
0x1c
/* header */
+
apiset
->
count
*
0x18
;
/* names */
for
(
i
=
0
,
e
=
apiset
->
entries
;
i
<
apiset
->
count
;
i
++
,
e
++
)
{
put_dword
(
1
);
/* Flags */
put_dword
(
str_pos
+
e
->
name_off
*
2
);
/* NameOffset */
put_dword
(
e
->
name_len
*
2
);
/* NameLength */
put_dword
(
e
->
hash_len
*
2
);
/* HashedLength */
put_dword
(
value_pos
);
/* ValueOffset */
put_dword
(
max
(
1
,
e
->
val_count
));
/* ValueCount */
value_pos
+=
0x14
*
max
(
1
,
e
->
val_count
);
}
/* values */
for
(
i
=
0
,
e
=
apiset
->
entries
;
i
<
apiset
->
count
;
i
++
,
e
++
)
{
if
(
!
e
->
val_count
)
{
put_dword
(
0
);
/* Flags */
put_dword
(
0
);
/* NameOffset */
put_dword
(
0
);
/* NameLength */
put_dword
(
0
);
/* ValueOffset */
put_dword
(
0
);
/* ValueLength */
}
else
for
(
j
=
0
;
j
<
e
->
val_count
;
j
++
)
{
put_dword
(
0
);
/* Flags */
if
(
e
->
values
[
j
].
name_off
)
{
put_dword
(
str_pos
+
e
->
values
[
j
].
name_off
*
2
);
/* NameOffset */
put_dword
(
e
->
values
[
j
].
name_len
*
2
);
/* NameLength */
}
else
{
put_dword
(
0
);
/* NameOffset */
put_dword
(
0
);
/* NameLength */
}
put_dword
(
str_pos
+
e
->
values
[
j
].
val_off
*
2
);
/* ValueOffset */
put_dword
(
e
->
values
[
j
].
val_len
*
2
);
/* ValueLength */
}
}
/* strings */
for
(
i
=
0
;
i
<
apiset
->
str_pos
;
i
++
)
put_word
(
apiset
->
strings
[
i
]
);
align_output
(
4
);
/* hash table */
hash
=
xmalloc
(
apiset
->
count
*
sizeof
(
*
hash
)
);
for
(
i
=
0
,
e
=
apiset
->
entries
;
i
<
apiset
->
count
;
i
++
,
e
++
)
{
hash
[
i
].
hash
=
e
->
hash
;
hash
[
i
].
index
=
i
;
}
qsort
(
hash
,
apiset
->
count
,
sizeof
(
*
hash
),
apiset_hash_cmp
);
for
(
i
=
0
;
i
<
apiset
->
count
;
i
++
)
{
put_dword
(
hash
[
i
].
hash
);
put_dword
(
hash
[
i
].
index
);
}
free
(
hash
);
flush_output_to_section
(
".apiset"
,
-
1
,
0x40000040
/* CNT_INITIALIZED_DATA|MEM_READ */
);
}
static
void
output_pe_file
(
DLLSPEC
*
spec
,
const
char
signature
[
32
]
)
static
void
output_pe_file
(
DLLSPEC
*
spec
,
const
char
signature
[
32
]
)
{
{
const
unsigned
int
lfanew
=
0x40
+
32
;
const
unsigned
int
lfanew
=
0x40
+
32
;
...
@@ -1136,6 +1248,7 @@ void output_data_module( DLLSPEC *spec )
...
@@ -1136,6 +1248,7 @@ void output_data_module( DLLSPEC *spec )
pe
.
section_align
=
pe
.
file_align
=
get_page_size
();
pe
.
section_align
=
pe
.
file_align
=
get_page_size
();
output_pe_exports
(
spec
);
output_pe_exports
(
spec
);
if
(
spec
->
apiset
.
count
)
output_apiset_section
(
&
spec
->
apiset
);
output_pe_file
(
spec
,
builtin_signature
);
output_pe_file
(
spec
,
builtin_signature
);
}
}
...
...
tools/winebuild/winebuild.man.in
View file @
8a306489
...
@@ -539,6 +539,25 @@ This declaration defines an ordinal as an absolute value.
...
@@ -539,6 +539,25 @@ This declaration defines an ordinal as an absolute value.
will be the name available for dynamic linking.
will be the name available for dynamic linking.
.I data
.I data
can be a decimal number or a hex number preceded by "0x".
can be a decimal number or a hex number preceded by "0x".
.SS "Api sets"
Syntax:
.br
.BI apiset\ apiset_dll\ =\ target.dll\ [host.dll:target.dll]
.PP
This declaration defines that the \fIapiset_dll\fR (of the form
api-ms-*) resolves to the \fItarget\fR dll. Optionally other targets
can be specified to resolve differently for specific host dlls. For
example:
.IP
api-ms-win-core-processenvironment-l1-1-0 = kernelbase.dll
.br
api-ms-win-core-processthreads-l1-1-0 = kernel32.dll \\
.br
kernel32.dll:kernelbase.dll
.PP
If apisets are defined, a corresponding .apiset section will be
generated in the PE binary. This requires building the module with the
--data-only option.
.SH AUTHORS
.SH AUTHORS
.B winebuild
.B winebuild
has been worked on by many people over the years. The main authors are
has been worked on by many people over the years. The main authors are
...
...
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