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
dd224781
Commit
dd224781
authored
Feb 16, 2001
by
Jon Griffiths
Committed by
Alexandre Julliard
Feb 16, 2001
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
- Create entries for ordinal only exports, use ordinals if non-standard.
- Improve C++ demangler, recognise data types, fix some bugs.
parent
d52e1c4b
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
419 additions
and
150 deletions
+419
-150
README
tools/specmaker/README
+1
-1
dll.c
tools/specmaker/dll.c
+68
-17
main.c
tools/specmaker/main.c
+7
-3
msmangle.c
tools/specmaker/msmangle.c
+196
-69
output.c
tools/specmaker/output.c
+101
-35
search.c
tools/specmaker/search.c
+13
-3
specmaker.h
tools/specmaker/specmaker.h
+13
-4
symbol.c
tools/specmaker/symbol.c
+20
-18
No files found.
tools/specmaker/README
View file @
dd224781
...
...
@@ -148,7 +148,7 @@ specmaker -d zipextra (Note: this assumes specmaker is in your path)
The output will look something like the following:
22
exported symbols in DLL
...
22
named symbols in DLL, 22 in total
...
Export 1 - '_OpenZipFile' ... [Ignoring]
Export 2 - '_UnZipFile' ... [Ignoring]
...
...
...
tools/specmaker/dll.c
View file @
dd224781
...
...
@@ -18,6 +18,9 @@
#define SECTION_ADDR_OFFSET 12
#define SECTION_ADDR_SIZE SECTION_ADDR_OFFSET + 4
#define SECTION_POS_OFFSET SECTION_ADDR_SIZE + 4
#define ORDINAL_BASE_OFFSET 16
#define ORDINAL_COUNT_OFFSET 20
#define ORDINAL_NAME_OFFSET ORDINAL_COUNT_OFFSET + 16
#define EXPORT_COUNT_OFFSET 24
#define EXPORT_NAME_OFFSET EXPORT_COUNT_OFFSET + 8
...
...
@@ -28,10 +31,19 @@
#define REBASE(x) ((x) - exports)
/* Module globals */
typedef
struct
_dll_symbol
{
size_t
ordinal
;
char
*
symbol
;
}
dll_symbol
;
static
FILE
*
dll_file
=
NULL
;
static
char
*
*
dll_symbols
=
NULL
;
static
dll_symbol
*
dll_symbols
=
NULL
;
static
size_t
dll_num_exports
=
0
;
static
size_t
dll_num_ordinals
=
0
;
static
int
dll_ordinal_base
=
0
;
static
dll_symbol
*
dll_current_symbol
=
NULL
;
static
unsigned
int
dll_current_export
=
0
;
/* Get a short from a memory block */
static
inline
size_t
get_short
(
const
char
*
mem
)
...
...
@@ -47,6 +59,12 @@ static inline size_t get_int (const char *mem)
return
get_short
(
mem
)
+
(
get_short
(
mem
+
2
)
<<
16
);
}
/* Compare symbols by ordinal for qsort */
static
int
symbol_cmp
(
const
void
*
left
,
const
void
*
right
)
{
return
((
dll_symbol
*
)
left
)
->
ordinal
>
((
dll_symbol
*
)
right
)
->
ordinal
;
}
static
void
dll_close
(
void
);
...
...
@@ -58,6 +76,7 @@ static void dll_close (void);
void
dll_open
(
const
char
*
dll_name
)
{
size_t
code
=
0
,
code_len
=
0
,
exports
,
exports_len
,
count
,
symbol_data
;
size_t
ordinal_data
;
char
*
buff
=
NULL
;
dll_file
=
open_file
(
dll_name
,
".dll"
,
"r"
);
...
...
@@ -127,37 +146,55 @@ void dll_open (const char *dll_name)
dll_close
();
/* Locate symbol names */
/* Locate symbol names
/ordinals
*/
symbol_data
=
REBASE
(
get_int
(
buff
+
EXPORT_NAME_OFFSET
));
ordinal_data
=
REBASE
(
get_int
(
buff
+
ORDINAL_NAME_OFFSET
));
if
(
symbol_data
>
code_len
)
fatal
(
"Corrupt exports section"
);
if
(
!
(
dll_num_ordinals
=
get_int
(
buff
+
ORDINAL_COUNT_OFFSET
)))
fatal
(
"No ordinal count"
);
if
(
!
(
dll_num_exports
=
get_int
(
buff
+
EXPORT_COUNT_OFFSET
)))
fatal
(
"No export count"
);
if
(
!
(
dll_symbols
=
(
char
**
)
malloc
(
dll_num_exports
*
sizeof
(
char
*
))))
if
(
!
(
dll_symbols
=
(
dll_symbol
*
)
malloc
((
dll_num_exports
+
1
)
*
sizeof
(
dll_symbol
))))
fatal
(
"Out of memory"
);
dll_ordinal_base
=
get_int
(
buff
+
ORDINAL_BASE_OFFSET
);
if
(
dll_num_exports
!=
dll_num_ordinals
||
dll_ordinal_base
>
1
)
globals
.
do_ordinals
=
1
;
/* Read symbol names into 'dll_symbols' */
count
=
0
;
while
(
count
<
dll_num_exports
)
{
const
int
symbol_offset
=
get_int
(
buff
+
symbol_data
+
count
*
4
);
const
char
*
symbol_name_ptr
=
REBASE
(
buff
+
symbol_offset
);
const
int
ordinal_offset
=
get_short
(
buff
+
ordinal_data
+
count
*
2
);
assert
(
symbol_name_ptr
);
dll_symbols
[
count
]
=
strdup
(
symbol_name_ptr
);
assert
(
dll_symbols
[
count
]);
dll_symbols
[
count
].
symbol
=
strdup
(
symbol_name_ptr
);
assert
(
dll_symbols
[
count
].
symbol
);
dll_symbols
[
count
].
ordinal
=
ordinal_offset
+
dll_ordinal_base
;
count
++
;
}
if
(
NORMAL
)
printf
(
"%d
exported symbols in DLL
\n
"
,
dll_num_export
s
);
printf
(
"%d
named symbols in DLL, %d total
\n
"
,
dll_num_exports
,
dll_num_ordinal
s
);
free
(
buff
);
qsort
(
dll_symbols
,
dll_num_exports
,
sizeof
(
dll_symbol
),
symbol_cmp
);
dll_symbols
[
dll_num_exports
].
symbol
=
NULL
;
dll_current_symbol
=
dll_symbols
;
dll_current_export
=
dll_ordinal_base
;
/* Set DLL output names */
if
((
buff
=
strrchr
(
globals
.
input_name
,
'/'
)))
globals
.
input_name
=
buff
+
1
;
/* Strip path */
...
...
@@ -171,19 +208,33 @@ void dll_open (const char *dll_name)
*
* Get next exported symbol from dll
*/
char
*
dll_next_symbol
(
)
int
dll_next_symbol
(
parsed_symbol
*
sym
)
{
static
unsigned
int
current_export
=
0
;
assert
(
current_export
<=
dll_num_exports
);
if
(
current_export
==
dll_num_exports
)
return
NULL
;
char
ordinal_text
[
256
];
if
(
dll_current_export
>
dll_num_ordinals
)
return
1
;
assert
(
dll_symbols
);
assert
(
dll_symbols
[
current_export
]);
return
strdup
(
dll_symbols
[
current_export
++
]);
if
(
!
dll_current_symbol
->
symbol
||
dll_current_export
<
dll_current_symbol
->
ordinal
)
{
assert
(
globals
.
do_ordinals
);
/* Ordinal only entry */
snprintf
(
ordinal_text
,
sizeof
(
ordinal_text
),
"%s_%d"
,
globals
.
forward_dll
?
globals
.
forward_dll
:
OUTPUT_UC_DLL_NAME
,
dll_current_export
);
str_toupper
(
ordinal_text
);
sym
->
symbol
=
strdup
(
ordinal_text
);
}
else
{
sym
->
symbol
=
strdup
(
dll_current_symbol
->
symbol
);
dll_current_symbol
++
;
}
sym
->
ordinal
=
dll_current_export
;
dll_current_export
++
;
return
0
;
}
...
...
@@ -205,8 +256,8 @@ static void dll_close (void)
if
(
dll_symbols
)
{
for
(
i
=
0
;
i
<
dll_num_exports
;
i
++
)
if
(
dll_symbols
[
i
])
free
(
dll_symbols
[
i
]);
if
(
dll_symbols
[
i
]
.
symbol
)
free
(
dll_symbols
[
i
]
.
symbol
);
free
(
dll_symbols
);
dll_symbols
=
NULL
;
}
...
...
tools/specmaker/main.c
View file @
dd224781
...
...
@@ -220,9 +220,13 @@ int main (int argc, char *argv[])
{
int
result
;
globals
.
uc_dll_name
=
""
;
VERBOSE
=
1
;
symbol
.
symbol
=
strdup
(
globals
.
input_name
);
result
=
symbol_demangle
(
&
symbol
);
output_prototype
(
stdout
,
&
symbol
);
if
(
symbol
.
flags
&
SYM_DATA
)
printf
(
symbol
.
arg_text
[
0
]);
else
output_prototype
(
stdout
,
&
symbol
);
fputc
(
'\n'
,
stdout
);
return
result
?
1
:
0
;
}
...
...
@@ -233,7 +237,7 @@ int main (int argc, char *argv[])
output_header_preamble
();
output_c_preamble
();
while
(
(
symbol
.
symbol
=
dll_next_symbol
()
))
while
(
!
dll_next_symbol
(
&
symbol
))
{
count
++
;
...
...
@@ -250,7 +254,7 @@ int main (int argc, char *argv[])
if
(
result
)
result
=
symbol_search
(
&
symbol
);
if
(
!
result
)
if
(
!
result
&&
symbol
.
function_name
)
/* Clean up the prototype */
symbol_clean_string
(
symbol
.
function_name
);
...
...
tools/specmaker/msmangle.c
View file @
dd224781
...
...
@@ -21,6 +21,8 @@ typedef struct _compound_type
/* free the memory used by a compound structure */
#define FREE_CT(ct) do { if (ct.expression) free (ct.expression); } while (0)
/* Flags for data types */
#define DATA_VTABLE 0x1
/* Internal functions */
static
char
*
demangle_datatype
(
char
**
str
,
compound_type
*
ct
,
...
...
@@ -49,8 +51,9 @@ int symbol_demangle (parsed_symbol *sym)
int
is_static
=
0
,
is_const
=
0
;
char
*
function_name
=
NULL
;
char
*
class_name
=
NULL
;
char
*
name
;
char
*
name
,
*
const_status
;
static
unsigned
int
hash
=
0
;
/* In case of overloaded functions */
unsigned
int
data_flags
=
0
;
assert
(
globals
.
do_code
);
assert
(
sym
&&
sym
->
symbol
);
...
...
@@ -96,6 +99,7 @@ int symbol_demangle (parsed_symbol *sym)
case
'N'
:
function_name
=
strdup
(
"operator_lessthanequal"
);
break
;
case
'O'
:
function_name
=
strdup
(
"operator_greaterthan"
);
break
;
case
'P'
:
function_name
=
strdup
(
"operator_greaterthanequal"
);
break
;
case
'Q'
:
function_name
=
strdup
(
"operator_comma"
);
break
;
case
'R'
:
function_name
=
strdup
(
"operator_functioncall"
);
break
;
case
'S'
:
function_name
=
strdup
(
"operator_compliment"
);
break
;
case
'T'
:
function_name
=
strdup
(
"operator_xor"
);
break
;
...
...
@@ -115,9 +119,28 @@ int symbol_demangle (parsed_symbol *sym)
case
'4'
:
function_name
=
strdup
(
"operator_andequals"
);
break
;
case
'5'
:
function_name
=
strdup
(
"operator_orequals"
);
break
;
case
'6'
:
function_name
=
strdup
(
"operator_xorequals"
);
break
;
/* FIXME: These look like static vtable/rtti information ? */
case
'E'
:
function_name
=
strdup
(
"_unknown_E"
);
break
;
case
'G'
:
function_name
=
strdup
(
"_unknown_G"
);
break
;
case
'7'
:
function_name
=
strdup
(
"vftable"
);
data_flags
=
DATA_VTABLE
;
break
;
case
'8'
:
function_name
=
strdup
(
"vbtable"
);
data_flags
=
DATA_VTABLE
;
break
;
case
'9'
:
function_name
=
strdup
(
"vcall"
);
data_flags
=
DATA_VTABLE
;
break
;
case
'A'
:
function_name
=
strdup
(
"typeof"
);
data_flags
=
DATA_VTABLE
;
break
;
case
'B'
:
function_name
=
strdup
(
"local_static_guard"
);
data_flags
=
DATA_VTABLE
;
break
;
case
'C'
:
function_name
=
strdup
(
"string"
);
data_flags
=
DATA_VTABLE
;
break
;
case
'D'
:
function_name
=
strdup
(
"vbase_dtor"
);
data_flags
=
DATA_VTABLE
;
break
;
case
'E'
:
function_name
=
strdup
(
"vector_dtor"
);
break
;
case
'G'
:
function_name
=
strdup
(
"scalar_dtor"
);
break
;
case
'H'
:
function_name
=
strdup
(
"vector_ctor_iter"
);
break
;
case
'I'
:
function_name
=
strdup
(
"vector_dtor_iter"
);
break
;
case
'J'
:
function_name
=
strdup
(
"vector_vbase_ctor_iter"
);
break
;
case
'L'
:
function_name
=
strdup
(
"eh_vector_ctor_iter"
);
break
;
case
'M'
:
function_name
=
strdup
(
"eh_vector_dtor_iter"
);
break
;
case
'N'
:
function_name
=
strdup
(
"eh_vector_vbase_ctor_iter"
);
break
;
case
'O'
:
function_name
=
strdup
(
"copy_ctor_closure"
);
break
;
case
'S'
:
function_name
=
strdup
(
"local_vftable"
);
data_flags
=
DATA_VTABLE
;
break
;
case
'T'
:
function_name
=
strdup
(
"local_vftable_ctor_closure"
);
break
;
case
'U'
:
function_name
=
strdup
(
"operator_new_vector"
);
break
;
case
'V'
:
function_name
=
strdup
(
"operator_delete_vector"
);
break
;
case
'X'
:
function_name
=
strdup
(
"placement_new_closure"
);
break
;
case
'Y'
:
function_name
=
strdup
(
"placement_delete_closure"
);
break
;
default:
return
-
1
;
}
...
...
@@ -154,22 +177,72 @@ int symbol_demangle (parsed_symbol *sym)
class_name
=
str_substring
(
class_name
,
name
-
2
);
}
/* Note: This is guesswork on my part, but it seems to work:
* 'Q' Means the function is passed an implicit 'this' pointer.
* 'S' Means static member function, i.e. no implicit 'this' pointer.
* 'Y' Is used for datatypes and functions, so there is no 'this' pointer.
* This character also implies some other things:
* 'Y','S' = The character after the calling convention is always the
* start of the return type code.
* 'Q' Character after the calling convention is 'const'ness code
* (only non static member functions can be const).
* 'U' also occurs, it seems to behave like Q, but probably implies
* something else.
*/
/* Function/Data type and access level */
/* FIXME: why 2 possible letters for each option? */
switch
(
*
name
++
)
{
case
'U'
:
case
'Q'
:
/* Data */
case
'0'
:
/* private static */
case
'1'
:
/* protected static */
case
'2'
:
/* public static */
is_static
=
1
;
/* Fall through */
case
'3'
:
/* non static */
case
'4'
:
/* non static */
/* Data members need to be implemented: report */
INIT_CT
(
ct
);
if
(
!
demangle_datatype
(
&
name
,
&
ct
,
sym
))
{
if
(
VERBOSE
)
printf
(
"/*FIXME: %s: unknown data*/
\n
"
,
sym
->
symbol
);
return
-
1
;
}
sym
->
flags
|=
SYM_DATA
;
sym
->
argc
=
1
;
sym
->
arg_name
[
0
]
=
str_create
(
5
,
OUTPUT_UC_DLL_NAME
,
"_"
,
class_name
,
is_static
?
"static_"
:
"_"
,
function_name
);
sym
->
arg_text
[
0
]
=
str_create
(
3
,
ct
.
expression
,
" "
,
sym
->
arg_name
[
0
]);
FREE_CT
(
ct
);
return
0
;
break
;
case
'6'
:
/* compiler generated static */
case
'7'
:
/* compiler generated static */
if
(
data_flags
&
DATA_VTABLE
)
{
sym
->
flags
|=
SYM_DATA
;
sym
->
argc
=
1
;
sym
->
arg_name
[
0
]
=
str_create
(
5
,
OUTPUT_UC_DLL_NAME
,
"_"
,
class_name
,
"_"
,
function_name
);
sym
->
arg_text
[
0
]
=
str_create
(
2
,
"void *"
,
sym
->
arg_name
[
0
]);
if
(
VERBOSE
)
puts
(
"Demangled symbol OK [vtable]"
);
return
0
;
}
return
-
1
;
break
;
/* Functions */
case
'E'
:
/* private virtual */
case
'F'
:
/* private virtual */
case
'M'
:
/* protected virtual */
case
'N'
:
/* protected virtual */
case
'U'
:
/* public virtual */
case
'V'
:
/* public virtual */
/* Virtual functions need to be added to the exported vtable: report */
if
(
VERBOSE
)
printf
(
"/*FIXME %s: %s::%s is virtual-add to vftable*/
\n
"
,
sym
->
symbol
,
class_name
,
function_name
);
/* Fall through */
case
'A'
:
/* private */
case
'B'
:
/* private */
case
'I'
:
/* protected */
case
'J'
:
/* protected */
case
'Q'
:
/* public */
case
'R'
:
/* public */
/* Implicit 'this' pointer */
sym
->
arg_text
[
sym
->
argc
]
=
str_create
(
3
,
"struct "
,
class_name
,
" *"
);
sym
->
arg_type
[
sym
->
argc
]
=
ARG_POINTER
;
...
...
@@ -177,42 +250,67 @@ int symbol_demangle (parsed_symbol *sym)
sym
->
arg_name
[
sym
->
argc
++
]
=
strdup
(
"_this"
);
/* New struct definitions can be 'grep'ed out for making a fixup header */
if
(
VERBOSE
)
printf
(
"struct %s {
int _FIXME;
};
\n
"
,
class_name
);
printf
(
"struct %s {
void **vtable; /*FIXME: class definition */
};
\n
"
,
class_name
);
break
;
case
'S'
:
is_static
=
1
;
case
'C'
:
/* private: static */
case
'D'
:
/* private: static */
case
'K'
:
/* protected: static */
case
'L'
:
/* protected: static */
case
'S'
:
/* public: static */
case
'T'
:
/* public: static */
is_static
=
1
;
/* No implicit this pointer */
break
;
case
'Y'
:
case
'Z'
:
break
;
/* FIXME: G,H / O,P / W,X are private / protected / public thunks */
default:
return
-
1
;
}
/* If there is an implicit this pointer, const status follows */
if
(
sym
->
argc
)
{
switch
(
*
name
++
)
{
case
'A'
:
break
;
/* non-const */
case
'B'
:
is_const
=
CT_CONST
;
break
;
case
'C'
:
is_const
=
CT_VOLATILE
;
break
;
case
'D'
:
is_const
=
(
CT_CONST
|
CT_VOLATILE
);
break
;
default:
return
-
1
;
}
}
/* Next is the calling convention */
switch
(
*
name
++
)
{
case
'A'
:
sym
->
calling_convention
=
strdup
(
"__cdecl"
);
break
;
case
'B'
:
/* FIXME: Something to do with __declspec(dllexport)? */
case
'A'
:
/* __cdecl */
case
'B'
:
/* __cdecl __declspec(dllexport) */
if
(
!
sym
->
argc
)
{
sym
->
flags
|=
SYM_CDECL
;
break
;
}
/* Else fall through */
case
'C'
:
/* __pascal */
case
'D'
:
/* __pascal __declspec(dllexport) */
case
'E'
:
/* __thiscall */
case
'F'
:
/* __thiscall __declspec(dllexport) */
case
'G'
:
/* __stdcall */
case
'H'
:
/* __stdcall __declspec(dllexport) */
case
'I'
:
/* __fastcall */
case
'G'
:
sym
->
calling_convention
=
strdup
(
"__stdcall"
);
case
'J'
:
/* __fastcall __declspec(dllexport)*/
case
'K'
:
/* default (none given) */
if
(
sym
->
argc
)
sym
->
flags
|=
SYM_THISCALL
;
else
sym
->
flags
|=
SYM_STDCALL
;
break
;
default:
return
-
1
;
}
/* If the symbol is associated with a class, its 'const' status follows */
if
(
sym
->
argc
)
{
if
(
*
name
==
'B'
)
is_const
=
1
;
else
if
(
*
name
!=
'E'
)
return
-
1
;
name
++
;
}
/* Return type, or @ if 'void' */
if
(
*
name
==
'@'
)
{
...
...
@@ -272,11 +370,18 @@ int symbol_demangle (parsed_symbol *sym)
/* Create the function name. Include a unique number because otherwise
* overloaded functions could have the same c signature.
*/
switch
(
is_const
)
{
case
(
CT_CONST
|
CT_VOLATILE
):
const_status
=
"_const_volatile"
;
break
;
case
CT_CONST
:
const_status
=
"_const"
;
break
;
case
CT_VOLATILE
:
const_status
=
"_volatile"
;
break
;
default:
const_status
=
"_"
;
break
;
}
sym
->
function_name
=
str_create_num
(
4
,
hash
,
class_name
,
"_"
,
function_name
,
is_static
?
"_static"
:
is_const
?
"_const"
:
"_"
);
function_name
,
is_static
?
"_static"
:
const_status
);
assert
(
sym
->
return_text
);
assert
(
sym
->
calling_convention
);
assert
(
sym
->
flags
);
assert
(
sym
->
function_name
);
free
(
class_name
);
...
...
@@ -312,17 +417,15 @@ static char *demangle_datatype (char **str, compound_type *ct,
if
(
!
get_constraints_convention_1
(
&
iter
,
ct
))
return
NULL
;
if
(
*
iter
==
'_'
)
{
/* MS type: __int8,__int16 etc */
ct
->
flags
|=
CT_EXTENDED
;
iter
++
;
}
switch
(
*
iter
)
{
case
'_'
:
if
(
*++
iter
!=
'N'
)
/* _N = bool */
return
NULL
;
iter
++
;
ct
->
dest_type
=
'I'
;
/* treat as int */
if
(
!
get_constraints_convention_2
(
&
iter
,
ct
))
return
NULL
;
ct
->
expression
=
get_type_string
(
ct
->
dest_type
,
ct
->
flags
);
break
;
case
'C'
:
case
'D'
:
case
'E'
:
case
'F'
:
case
'G'
:
case
'H'
:
case
'I'
:
case
'J'
:
case
'K'
:
case
'M'
:
case
'N'
:
case
'O'
:
case
'X'
:
case
'Z'
:
...
...
@@ -357,10 +460,10 @@ static char *demangle_datatype (char **str, compound_type *ct,
ct
->
flags
&
CT_VOLATILE
?
"volatile "
:
""
,
stripped
);
free
(
stripped
);
}
else
if
(
*
iter
==
'_
'
)
else
if
(
*
iter
!=
'@
'
)
{
/* The name of the class/struct, followed by '@@' */
char
*
struct_name
=
++
iter
;
char
*
struct_name
=
iter
;
while
(
*
iter
&&
*
iter
++
!=
'@'
)
;
if
(
*
iter
++
!=
'@'
)
return
NULL
;
...
...
@@ -519,26 +622,50 @@ static char *get_type_string (const char c, const int constraints)
{
char
*
type_string
;
switch
(
c
)
if
(
constraints
&
CT_EXTENDED
)
{
case
'C'
:
/* Signed char, fall through */
case
'D'
:
type_string
=
"char"
;
break
;
case
'E'
:
type_string
=
"unsigned char"
;
break
;
case
'F'
:
type_string
=
"short int"
;
break
;
case
'G'
:
type_string
=
"unsigned short int"
;
break
;
case
'H'
:
type_string
=
"int"
;
break
;
case
'I'
:
type_string
=
"unsigned int"
;
break
;
case
'J'
:
type_string
=
"long"
;
break
;
case
'K'
:
type_string
=
"unsigned long"
;
break
;
case
'M'
:
type_string
=
"float"
;
break
;
case
'N'
:
type_string
=
"double"
;
break
;
case
'O'
:
type_string
=
"long double"
;
break
;
case
'U'
:
case
'V'
:
type_string
=
"struct"
;
break
;
case
'X'
:
return
strdup
(
"void"
);
case
'Z'
:
return
strdup
(
"..."
);
default:
return
NULL
;
switch
(
c
)
{
case
'D'
:
type_string
=
"__int8"
;
break
;
case
'E'
:
type_string
=
"__uint8"
;
break
;
case
'F'
:
type_string
=
"__int16"
;
break
;
case
'G'
:
type_string
=
"__uint16"
;
break
;
case
'H'
:
type_string
=
"__int32"
;
break
;
case
'I'
:
type_string
=
"__uint32"
;
break
;
case
'J'
:
type_string
=
"__int64"
;
break
;
case
'K'
:
type_string
=
"__uint64"
;
break
;
case
'L'
:
type_string
=
"__int128"
;
break
;
case
'M'
:
type_string
=
"__uint128"
;
break
;
case
'N'
:
type_string
=
"int"
;
break
;
/* bool */
case
'W'
:
type_string
=
"WCHAR"
;
break
;
/* wchar_t */
default:
return
NULL
;
}
}
else
{
switch
(
c
)
{
case
'C'
:
/* Signed char, fall through */
case
'D'
:
type_string
=
"char"
;
break
;
case
'E'
:
type_string
=
"unsigned char"
;
break
;
case
'F'
:
type_string
=
"short int"
;
break
;
case
'G'
:
type_string
=
"unsigned short int"
;
break
;
case
'H'
:
type_string
=
"int"
;
break
;
case
'I'
:
type_string
=
"unsigned int"
;
break
;
case
'J'
:
type_string
=
"long"
;
break
;
case
'K'
:
type_string
=
"unsigned long"
;
break
;
case
'M'
:
type_string
=
"float"
;
break
;
case
'N'
:
type_string
=
"double"
;
break
;
case
'O'
:
type_string
=
"long double"
;
break
;
/* FIXME: T = union */
case
'U'
:
case
'V'
:
type_string
=
"struct"
;
break
;
case
'X'
:
return
strdup
(
"void"
);
case
'Z'
:
return
strdup
(
"..."
);
default:
return
NULL
;
}
}
return
str_create
(
3
,
constraints
&
CT_CONST
?
"const "
:
...
...
tools/specmaker/output.c
View file @
dd224781
...
...
@@ -52,34 +52,58 @@ void output_spec_preamble (void)
*/
void
output_spec_symbol
(
const
parsed_symbol
*
sym
)
{
char
ord_spec
[
16
];
assert
(
specfile
);
assert
(
sym
&&
sym
->
symbol
);
if
(
globals
.
do_ordinals
)
snprintf
(
ord_spec
,
8
,
"%d"
,
sym
->
ordinal
);
else
{
ord_spec
[
0
]
=
'@'
;
ord_spec
[
1
]
=
'\0'
;
}
if
(
sym
->
flags
&
SYM_THISCALL
)
strcat
(
ord_spec
,
" -i386"
);
/* For binary compatability only */
if
(
!
globals
.
do_code
||
!
sym
->
function_name
)
{
if
(
sym
->
flags
&
SYM_DATA
)
{
if
(
globals
.
forward_dll
)
fprintf
(
specfile
,
"%s forward %s %s.%s #"
,
ord_spec
,
sym
->
symbol
,
globals
.
forward_dll
,
sym
->
symbol
);
fprintf
(
specfile
,
"%s extern %s %s
\n
"
,
ord_spec
,
sym
->
symbol
,
sym
->
arg_name
[
0
]);
return
;
}
if
(
globals
.
forward_dll
)
fprintf
(
specfile
,
"
@ forward %s %s.%s
\n
"
,
sym
->
symbol
,
fprintf
(
specfile
,
"
%s forward %s %s.%s
\n
"
,
ord_spec
,
sym
->
symbol
,
globals
.
forward_dll
,
sym
->
symbol
);
else
{
if
(
!
symbol_is_valid_c
(
sym
))
fputc
(
'#'
,
specfile
);
fprintf
(
specfile
,
"@ stub %s
\n
"
,
sym
->
symbol
);
}
fprintf
(
specfile
,
"%s stub %s
\n
"
,
ord_spec
,
sym
->
symbol
);
}
else
{
unsigned
int
i
;
unsigned
int
i
=
sym
->
flags
&
SYM_THISCALL
?
1
:
0
;
fprintf
(
specfile
,
"
@ %s %s("
,
sym
->
varargs
?
"varargs"
:
symbol_
is_cdecl
(
sym
)
?
"cdecl"
:
"stdcall"
,
sym
->
symbol
);
fprintf
(
specfile
,
"
%s %s %s("
,
ord_spec
,
sym
->
varargs
?
"varargs"
:
symbol_
get_call_convention
(
sym
)
,
sym
->
symbol
);
for
(
i
=
0
;
i
<
sym
->
argc
;
i
++
)
for
(;
i
<
sym
->
argc
;
i
++
)
fprintf
(
specfile
,
" %s"
,
symbol_get_spec_type
(
sym
,
i
));
if
(
sym
->
argc
)
fputc
(
' '
,
specfile
);
fprintf
(
specfile
,
") %s_%s
\n
"
,
OUTPUT_UC_DLL_NAME
,
sym
->
function_name
);
fprintf
(
specfile
,
") %s_%s"
,
OUTPUT_UC_DLL_NAME
,
sym
->
function_name
);
if
(
sym
->
flags
&
SYM_THISCALL
)
fputs
(
" # __thiscall"
,
specfile
);
fputc
(
'\n'
,
specfile
);
}
}
...
...
@@ -132,8 +156,11 @@ void output_header_symbol (const parsed_symbol *sym)
if
(
!
globals
.
do_code
)
return
;
if
(
sym
->
flags
&
SYM_DATA
)
return
;
if
(
!
sym
->
function_name
)
fprintf
(
hfile
,
"/*
%s %s_%s(); */
\n
"
,
CALLING_CONVENTION
,
fprintf
(
hfile
,
"/*
__%s %s_%s(); */
\n
"
,
symbol_get_call_convention
(
sym
)
,
OUTPUT_UC_DLL_NAME
,
sym
->
symbol
);
else
{
...
...
@@ -183,9 +210,12 @@ void output_c_preamble (void)
if
(
VERBOSE
)
puts
(
"Creating a forwarding DLL"
);
fputs
(
"
\n
HMODULE hDLL=0;
\t
/* DLL to call */
\n\n
\n
"
,
cfile
);
fputs
(
"
\n
HMODULE hDLL=0;
\t
/* DLL to call */
\n\n
"
,
cfile
);
}
fputs
(
"#ifdef __i386__
\n
#define GET_THIS(t,p) t p;
\\\n
__asm__ __volatile__"
" (
\"
movl %%ecx, %0
\"
:
\"
=m
\"
(p))
\n
#endif
\n\n\n
"
,
cfile
);
fprintf
(
cfile
,
"BOOL WINAPI %s_Init(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID "
"lpvReserved)
\n
{
\n\t
TRACE(
\"
(0x%%08x, %%ld, %%p)
\\
n
\"
,hinstDLL,"
...
...
@@ -219,6 +249,11 @@ void output_c_preamble (void)
}
#define CPP_END if (sym->flags & SYM_THISCALL) \
fputs ("#endif\n", cfile); fputs ("\n\n", cfile)
#define GET_THIS if (sym->flags & SYM_THISCALL) \
fprintf (cfile, "\tGET_THIS(%s,%s);\n", sym->arg_text[0],sym->arg_name[0])
/*******************************************************************
* output_c_symbol
*
...
...
@@ -226,7 +261,7 @@ void output_c_preamble (void)
*/
void
output_c_symbol
(
const
parsed_symbol
*
sym
)
{
unsigned
int
i
;
unsigned
int
i
,
start
=
sym
->
flags
&
SYM_THISCALL
?
1
:
0
;
int
is_void
;
assert
(
cfile
);
...
...
@@ -235,14 +270,25 @@ void output_c_symbol (const parsed_symbol *sym)
if
(
!
globals
.
do_code
)
return
;
if
(
sym
->
flags
&
SYM_DATA
)
{
fprintf
(
cfile
,
"/* FIXME: Move to top of file */
\n
%s;
\n\n
"
,
sym
->
arg_text
[
0
]);
return
;
}
if
(
sym
->
flags
&
SYM_THISCALL
)
fputs
(
"#ifdef __i386__
\n
"
,
cfile
);
output_c_banner
(
sym
);
if
(
!
sym
->
function_name
)
{
/* #ifdef'd dummy */
fprintf
(
cfile
,
"#if 0
\n
%s %s_%s()
\n
{
\n\t
/* %s in .spec */
\n
}
\n
#endif
\n\n
\n
"
,
CALLING_CONVENTION
,
OUTPUT_UC_DLL_NAME
,
sym
->
symbol
,
fprintf
(
cfile
,
"#if 0
\n
__%s %s_%s()
\n
{
\n\t
/* %s in .spec */
\n
}
\n
#endif
\n
"
,
symbol_get_call_convention
(
sym
)
,
OUTPUT_UC_DLL_NAME
,
sym
->
symbol
,
globals
.
forward_dll
?
"@forward"
:
"@stub"
);
CPP_END
;
return
;
}
...
...
@@ -253,10 +299,12 @@ void output_c_symbol (const parsed_symbol *sym)
if
(
!
globals
.
do_trace
)
{
GET_THIS
;
fputs
(
"
\t
FIXME(
\"
:stub
\\
n
\"
);
\n
"
,
cfile
);
if
(
!
is_void
)
fprintf
(
cfile
,
"
\t
return (%s) 0;
\n
"
,
sym
->
return_text
);
fputs
(
"}
\n\n\n
"
,
cfile
);
fputs
(
"}
\n
"
,
cfile
);
CPP_END
;
return
;
}
...
...
@@ -264,18 +312,25 @@ void output_c_symbol (const parsed_symbol *sym)
if
(
globals
.
forward_dll
)
{
/* Write variables for calling */
fprintf
(
cfile
,
"
\t
%s (%s *pFunc)("
,
sym
->
return_text
,
sym
->
calling_convention
);
if
(
sym
->
varargs
)
fputs
(
"
\t
va_list valist;
\n
"
,
cfile
);
fprintf
(
cfile
,
"
\t
%s (__%s *pFunc)("
,
sym
->
return_text
,
symbol_get_call_convention
(
sym
));
for
(
i
=
0
;
i
<
sym
->
argc
;
i
++
)
fprintf
(
cfile
,
"%s%s"
,
i
?
", "
:
""
,
sym
->
arg_text
[
i
]);
for
(
i
=
start
;
i
<
sym
->
argc
;
i
++
)
fprintf
(
cfile
,
"%s%s"
,
i
>
start
?
", "
:
""
,
sym
->
arg_text
[
i
]);
fprintf
(
cfile
,
"%s)=(void*)GetProcAddress(hDLL,
\"
%s
\"
);
\n
%s"
,
sym
->
varargs
?
",..."
:
sym
->
argc
?
""
:
"void"
,
sym
->
symbol
,
sym
->
varargs
?
"
\t
va_list valist;
\n
"
:
""
);
fprintf
(
cfile
,
"%s);
\n
"
,
sym
->
varargs
?
",..."
:
sym
->
argc
==
1
&&
sym
->
flags
&
SYM_THISCALL
?
""
:
sym
->
argc
?
""
:
"void"
);
if
(
!
is_void
)
fprintf
(
cfile
,
"
\t
%s retVal;
\n
"
,
sym
->
return_text
);
GET_THIS
;
fprintf
(
cfile
,
"
\t
pFunc=(void*)GetProcAddress(hDLL,
\"
%s
\"
);
\n
"
,
sym
->
symbol
);
}
/* TRACE input arguments */
...
...
@@ -301,7 +356,8 @@ void output_c_symbol (const parsed_symbol *sym)
{
if
(
!
is_void
)
fprintf
(
cfile
,
"
\t
return (%s) 0;
\n
"
,
sym
->
return_text
);
fputs
(
"}
\n\n\n
"
,
cfile
);
fputs
(
"}
\n
"
,
cfile
);
CPP_END
;
return
;
}
...
...
@@ -332,7 +388,8 @@ void output_c_symbol (const parsed_symbol *sym)
else
fputs
(
");
\n
"
,
cfile
);
fputs
(
"}
\n\n\n
"
,
cfile
);
fputs
(
"}
\n
"
,
cfile
);
CPP_END
;
}
...
...
@@ -436,16 +493,16 @@ void output_install_script (void)
*/
void
output_prototype
(
FILE
*
file
,
const
parsed_symbol
*
sym
)
{
unsigned
int
i
;
unsigned
int
i
,
start
=
sym
->
flags
&
SYM_THISCALL
?
1
:
0
;
fprintf
(
file
,
"%s
%s %s_%s("
,
sym
->
return_text
,
sym
->
calling_convention
,
fprintf
(
file
,
"%s
__%s %s_%s("
,
sym
->
return_text
,
symbol_get_call_convention
(
sym
)
,
OUTPUT_UC_DLL_NAME
,
sym
->
function_name
);
if
(
!
sym
->
argc
)
if
(
!
sym
->
argc
||
(
sym
->
argc
==
1
&&
sym
->
flags
&
SYM_THISCALL
)
)
fputs
(
"void"
,
file
);
else
for
(
i
=
0
;
i
<
sym
->
argc
;
i
++
)
fprintf
(
file
,
"%s%s %s"
,
i
?
", "
:
""
,
sym
->
arg_text
[
i
],
for
(
i
=
start
;
i
<
sym
->
argc
;
i
++
)
fprintf
(
file
,
"%s%s %s"
,
i
>
start
?
", "
:
""
,
sym
->
arg_text
[
i
],
sym
->
arg_name
[
i
]);
if
(
sym
->
varargs
)
fputs
(
", ..."
,
file
);
...
...
@@ -460,11 +517,20 @@ void output_prototype (FILE *file, const parsed_symbol *sym)
*/
void
output_c_banner
(
const
parsed_symbol
*
sym
)
{
char
ord_spec
[
16
];
size_t
i
;
if
(
globals
.
do_ordinals
)
snprintf
(
ord_spec
,
sizeof
(
ord_spec
),
"%d"
,
sym
->
ordinal
);
else
{
ord_spec
[
0
]
=
'@'
;
ord_spec
[
1
]
=
'\0'
;
}
fprintf
(
cfile
,
"/*********************************************************"
"*********
\n
*
\t\t
%s (%s.
@
)
\n
*
\n
"
,
sym
->
symbol
,
OUTPUT_UC_DLL_NAME
);
"*********
\n
*
\t\t
%s (%s.
%s
)
\n
*
\n
"
,
sym
->
symbol
,
OUTPUT_UC_DLL_NAME
,
ord_spec
);
if
(
globals
.
do_documentation
&&
sym
->
function_name
)
{
...
...
@@ -478,7 +544,7 @@ void output_c_banner (const parsed_symbol *sym)
fprintf
(
cfile
,
" * %s [%s]%s
\n
"
,
sym
->
arg_name
[
i
],
get_in_or_out
(
sym
,
i
),
strcmp
(
sym
->
arg_name
[
i
],
"_this"
)
?
""
:
" Pointer to the class object"
);
" Pointer to the class object
(in ECX)
"
);
if
(
sym
->
varargs
)
fputs
(
" * ...[I]
\n
"
,
cfile
);
...
...
@@ -522,7 +588,7 @@ static const char *get_format_str (int type)
/*******************************************************************
* get_in_or_out
*
* Determin if a parameter is In or In/Out
* Determin
e
if a parameter is In or In/Out
*/
static
const
char
*
get_in_or_out
(
const
parsed_symbol
*
sym
,
size_t
arg
)
{
...
...
tools/specmaker/search.c
View file @
dd224781
...
...
@@ -103,7 +103,7 @@ int symbol_search (parsed_symbol *sym)
iter
[
strlen
(
sym
->
symbol
)]
==
'('
))
{
if
(
VERBOSE
)
p
uts
(
"Prototype looks OK, processing"
);
p
rintf
(
"Prototype '%s' looks OK, processing
\n
"
,
grep_buff
);
if
(
!
symbol_from_prototype
(
sym
,
grep_buff
))
{
...
...
@@ -146,20 +146,30 @@ static int symbol_from_prototype (parsed_symbol *sym, const char *proto)
if
(
!
found
)
{
char
*
call
;
/* Calling Convention */
iter
=
strchr
(
iter
,
' '
);
if
(
!
iter
)
return
-
1
;
sym
->
calling_convention
=
str_substring
(
proto
,
iter
);
call
=
str_substring
(
proto
,
iter
);
if
(
!
strcasecmp
(
call
,
"cdecl"
)
||
!
strcasecmp
(
call
,
"__cdecl"
))
sym
->
flags
|=
SYM_CDECL
;
else
sym
->
flags
|=
SYM_STDCALL
;
free
(
call
);
iter
=
(
char
*
)
str_match
(
iter
,
sym
->
symbol
,
&
found
);
if
(
!
found
)
return
-
1
;
if
(
VERBOSE
)
printf
(
"Using %s calling convention
\n
"
,
sym
->
flags
&
SYM_CDECL
?
"cdecl"
:
"stdcall"
);
}
else
sym
->
calling_convention
=
strdup
(
CALLING_CONVENTION
)
;
sym
->
flags
=
CALLING_CONVENTION
;
sym
->
function_name
=
strdup
(
sym
->
symbol
);
proto
=
iter
;
...
...
tools/specmaker/specmaker.h
View file @
dd224781
...
...
@@ -50,17 +50,25 @@
#define CT_BY_REFERENCE 0x1
#define CT_VOLATILE 0x2
#define CT_CONST 0x4
#define CT_EXTENDED 0x8
/* symbol flags */
#define SYM_CDECL 0x1
#define SYM_STDCALL 0x2
#define SYM_THISCALL 0x4
#define SYM_DATA 0x8
/* Data, not a function */
/* Structure holding a parsed symbol */
typedef
struct
__parsed_symbol
{
char
*
symbol
;
int
ordinal
;
char
*
return_text
;
char
return_type
;
char
*
calling_convention
;
char
*
function_name
;
unsigned
int
varargs
;
unsigned
int
argc
;
unsigned
int
flags
;
char
arg_type
[
MAX_FUNCTION_ARGS
];
char
arg_flag
[
MAX_FUNCTION_ARGS
];
char
*
arg_text
[
MAX_FUNCTION_ARGS
];
...
...
@@ -87,6 +95,7 @@ typedef struct __globals
const
char
*
forward_dll
;
/* -f */
const
char
*
dll_name
;
/* -o */
char
*
uc_dll_name
;
/* -o */
int
do_ordinals
;
}
_globals
;
extern
_globals
globals
;
...
...
@@ -102,13 +111,13 @@ extern _globals globals;
#define VERBOSE (globals.do_verbose)
/* Default calling convention */
#define CALLING_CONVENTION (globals.do_cdecl ?
"__cdecl" : "__stdcall"
)
#define CALLING_CONVENTION (globals.do_cdecl ?
SYM_CDECL : SYM_STDCALL
)
/* DLL functions */
void
dll_open
(
const
char
*
dll_name
);
char
*
dll_next_symbol
(
void
);
int
dll_next_symbol
(
parsed_symbol
*
sym
);
/* Symbol functions */
int
symbol_demangle
(
parsed_symbol
*
symbol
);
...
...
@@ -119,7 +128,7 @@ void symbol_clear(parsed_symbol *sym);
int
symbol_is_valid_c
(
const
parsed_symbol
*
sym
);
int
symbol_is_cdecl
(
const
parsed_symbol
*
sym
);
const
char
*
symbol_get_call_convention
(
const
parsed_symbol
*
sym
);
const
char
*
symbol_get_spec_type
(
const
parsed_symbol
*
sym
,
size_t
arg
);
...
...
tools/specmaker/symbol.c
View file @
dd224781
...
...
@@ -69,7 +69,7 @@ static const char *ascii_chars[] =
static
const
char
*
known_longs
[]
=
{
"char"
,
"CHAR"
,
"float"
,
"int"
,
"INT"
,
"short"
,
"SHORT"
,
"long"
,
"LONG"
,
"WCHAR"
,
"BOOL"
,
"bool"
,
"INT16"
,
NULL
"WCHAR"
,
"BOOL"
,
"bool"
,
"INT16"
,
"WORD"
,
"DWORD"
,
NULL
};
...
...
@@ -90,9 +90,6 @@ void symbol_clear(parsed_symbol *sym)
if
(
sym
->
return_text
)
free
(
sym
->
return_text
);
if
(
sym
->
calling_convention
)
free
(
sym
->
calling_convention
);
if
(
sym
->
function_name
)
free
(
sym
->
function_name
);
...
...
@@ -132,21 +129,20 @@ int symbol_is_valid_c(const parsed_symbol *sym)
/*******************************************************************
* symbol_
is_cdecl
* symbol_
get_call_convention
*
*
Check if a symbol is cdec
l
*
Return the calling convention of a symbo
l
*/
int
symbol_is_cdecl
(
const
parsed_symbol
*
sym
)
const
char
*
symbol_get_call_convention
(
const
parsed_symbol
*
sym
)
{
int
call
=
sym
->
flags
?
sym
->
flags
:
CALLING_CONVENTION
;
assert
(
sym
);
assert
(
sym
->
symbol
);
if
(
sym
->
calling_convention
&&
(
strstr
(
sym
->
calling_convention
,
"cdecl"
)
||
strstr
(
sym
->
calling_convention
,
"CDECL"
)))
return
1
;
else
if
(
!
sym
->
calling_convention
)
return
globals
.
do_cdecl
;
return
0
;
if
(
call
&
SYM_CDECL
)
return
"cdecl"
;
return
"stdcall"
;
}
...
...
@@ -184,6 +180,12 @@ int symbol_get_type (const char *string)
const
char
**
tab
;
int
ptrs
=
0
;
while
(
*
iter
&&
isspace
(
*
iter
))
iter
++
;
if
(
*
iter
==
'P'
||
*
iter
==
'H'
)
ptrs
++
;
/* Win32 type pointer */
iter
=
string
;
while
(
*
iter
)
{
if
(
*
iter
==
'*'
||
(
*
iter
==
'L'
&&
iter
[
1
]
==
'P'
)
...
...
@@ -199,8 +201,8 @@ int symbol_get_type (const char *string)
while
(
*
tab
++
)
if
(
strstr
(
string
,
tab
[
-
1
]))
{
if
(
!
ptrs
)
return
ARG_WIDE_STRING
;
else
return
ARG_POINTER
;
if
(
ptrs
<
2
)
return
ARG_WIDE_STRING
;
else
return
ARG_POINTER
;
}
tab
=
wide_chars
;
while
(
*
tab
++
)
...
...
@@ -213,8 +215,8 @@ int symbol_get_type (const char *string)
while
(
*
tab
++
)
if
(
strstr
(
string
,
tab
[
-
1
]))
{
if
(
!
ptrs
)
return
ARG_STRING
;
else
return
ARG_POINTER
;
if
(
ptrs
<
2
)
return
ARG_STRING
;
else
return
ARG_POINTER
;
}
tab
=
ascii_chars
;
while
(
*
tab
++
)
...
...
@@ -234,7 +236,7 @@ int symbol_get_type (const char *string)
if
(
strstr
(
string
,
"double"
))
return
ARG_DOUBLE
;
if
(
strstr
(
string
,
"void"
))
if
(
strstr
(
string
,
"void"
)
||
strstr
(
string
,
"VOID"
)
)
return
ARG_VOID
;
if
(
strstr
(
string
,
"struct"
)
||
strstr
(
string
,
"union"
))
...
...
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