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
}
u
;
}
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
{
char
*
src_name
;
/* file name of the source spec file */
...
...
@@ -133,6 +161,7 @@ typedef struct
ORDDEF
**
names
;
/* array of entry point names (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
apiset
apiset
;
/* list of defined api sets */
}
DLLSPEC
;
extern
char
*
target_alias
;
...
...
@@ -285,6 +314,7 @@ 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
output_apiset_lib
(
DLLSPEC
*
spec
,
const
struct
apiset
*
apiset
);
extern
void
load_res16_file
(
const
char
*
name
,
DLLSPEC
*
spec
);
extern
void
output_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 )
*
* 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
;
const
char
*
token
;
do
{
if
(
!
(
token
=
GetToken
(
0
)))
break
;
token
++
;
if
(
!
strncmp
(
token
,
"arch="
,
5
))
{
char
*
args
=
xstrdup
(
token
+
5
);
...
...
@@ -578,7 +577,7 @@ static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
}
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
))
{
...
...
@@ -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
)
{
const
ORDDEF
*
odp1
=
*
(
const
ORDDEF
*
const
*
)
ptr1
;
...
...
@@ -898,7 +1023,7 @@ int parse_spec_file( FILE *file, DLLSPEC *spec )
current_line
=
0
;
comment_chars
=
"#;"
;
separator_chars
=
"()
-
"
;
separator_chars
=
"()"
;
while
(
get_next_line
())
{
...
...
@@ -911,6 +1036,10 @@ int parse_spec_file( FILE *file, DLLSPEC *spec )
{
if
(
!
parse_spec_ordinal
(
atoi
(
token
),
spec
))
continue
;
}
else
if
(
strcmp
(
token
,
"apiset"
)
==
0
)
{
if
(
!
parse_spec_apiset
(
spec
))
continue
;
}
else
{
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 )
}
/* 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
]
)
{
const
unsigned
int
lfanew
=
0x40
+
32
;
...
...
@@ -1136,6 +1248,7 @@ void output_data_module( DLLSPEC *spec )
pe
.
section_align
=
pe
.
file_align
=
get_page_size
();
output_pe_exports
(
spec
);
if
(
spec
->
apiset
.
count
)
output_apiset_section
(
&
spec
->
apiset
);
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.
will be the name available for dynamic linking.
.I data
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
.B winebuild
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