1 /* -------------------------------------------------------------- */
3 * tiny_impdef creates an export definition file (.def) from a dll
4 * on MS-Windows. Usage: tiny_impdef library.dll [-o outputfile]"
6 * Copyright (c) 2005,2007 grischka
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #ifndef TINY_IMPDEF_GET_EXPORT_NAMES_ONLY
25 #define WIN32_LEAN_AND_MEAN
29 #include "../../config.h"
31 char *get_export_names(FILE *fp
);
33 #define tcc_realloc realloc
35 /* extract the basename of a file */
36 static char *file_basename(const char *name
)
38 const char *p
= strchr(name
, 0);
47 int main(int argc
, char **argv
)
50 char infile
[MAX_PATH
];
51 char outfile
[MAX_PATH
];
53 static const char *ext
[] = { ".dll", ".exe", NULL
};
54 const char *file
, **pp
;
55 char path
[MAX_PATH
], *p
, *q
;
64 for (i
= 1; i
< argc
; ++i
) {
65 const char *a
= argv
[i
];
67 if (0 == strcmp(a
, "-v")) {
69 } else if (0 == strcmp(a
, "-o")) {
72 strcpy(outfile
, argv
[i
]);
75 } else if (0 == infile
[0])
84 "tiny_impdef: create export definition file (.def) from a dll\n"
85 "Usage: tiny_impdef library.dll [-o outputfile]\n"
92 strcpy(outfile
, file_basename(infile
));
93 p
= strrchr(outfile
, '.');
95 p
= strchr(outfile
, 0);
101 for (pp
= ext
; *pp
; ++pp
)
102 if (SearchPath(NULL
, file
, *pp
, sizeof path
, path
, NULL
)) {
108 fp
= fopen(file
, "rb");
110 fprintf(stderr
, "tiny_impdef: no such file: %s\n", infile
);
114 op
= fopen(outfile
, "w");
116 fprintf(stderr
, "tiny_impdef: could not create output file: %s\n", outfile
);
121 printf("--> %s\n", infile
);
123 fprintf(op
, "LIBRARY %s\n\nEXPORTS\n", file_basename(infile
));
124 p
= get_export_names(fp
);
126 fprintf(stderr
, "tiny_impdef: could not get exported function names.\n");
130 for (q
= p
, i
= 0; *q
; ++i
) {
131 fprintf(op
, "%s\n", q
);
137 printf("<-- %s\n", outfile
);
138 printf("%d symbol(s) found\n", i
);
151 /* -------------------------------------------------------------- */
153 int read_mem(FILE *fp
, unsigned offset
, void *buffer
, unsigned len
)
155 fseek(fp
, offset
, 0);
156 return len
== fread(buffer
, 1, len
, fp
);
159 /* -------------------------------------------------------------- */
162 char *get_export_names(FILE *fp
)
167 IMAGE_SECTION_HEADER ish
;
168 IMAGE_EXPORT_DIRECTORY ied
;
170 IMAGE_FILE_HEADER ih
;
171 DWORD sig
, ref
, addr
, ptr
, namep
;
172 #ifdef TCC_TARGET_X86_64
173 IMAGE_OPTIONAL_HEADER64 oh
;
174 const int MACHINE
= 0x8664;
176 IMAGE_OPTIONAL_HEADER32 oh
;
177 const int MACHINE
= 0x014C;
179 int pef_hdroffset
, opt_hdroffset
, sec_hdroffset
;
184 if (!read_mem(fp
, 0, &dh
, sizeof dh
))
186 if (!read_mem(fp
, dh
.e_lfanew
, &sig
, sizeof sig
))
188 if (sig
!= 0x00004550)
190 pef_hdroffset
= dh
.e_lfanew
+ sizeof sig
;
191 if (!read_mem(fp
, pef_hdroffset
, &ih
, sizeof ih
))
193 if (MACHINE
!= ih
.Machine
)
195 opt_hdroffset
= pef_hdroffset
+ sizeof ih
;
196 sec_hdroffset
= opt_hdroffset
+ sizeof oh
;
197 if (!read_mem(fp
, opt_hdroffset
, &oh
, sizeof oh
))
200 if (IMAGE_DIRECTORY_ENTRY_EXPORT
>= oh
.NumberOfRvaAndSizes
)
203 addr
= oh
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
204 //printf("addr: %08x\n", addr);
205 for (i
= 0; i
< ih
.NumberOfSections
; ++i
) {
206 if (!read_mem(fp
, sec_hdroffset
+ i
* sizeof ish
, &ish
, sizeof ish
))
208 //printf("vaddr: %08x\n", ish.VirtualAddress);
209 if (addr
>= ish
.VirtualAddress
&& addr
< ish
.VirtualAddress
+ ish
.SizeOfRawData
)
215 ref
= ish
.VirtualAddress
- ish
.PointerToRawData
;
216 if (!read_mem(fp
, addr
- ref
, &ied
, sizeof ied
))
219 namep
= ied
.AddressOfNames
- ref
;
220 for (i
= 0; i
< ied
.NumberOfNames
; ++i
) {
221 if (!read_mem(fp
, namep
, &ptr
, sizeof ptr
))
226 p
= tcc_realloc(p
, n0
= n0
? n0
* 2 : 256);
227 if (!read_mem(fp
, ptr
- ref
+ l
, p
+ n
, 1) || ++l
>= 80) {
228 tcc_free(p
), p
= NULL
;
241 /* -------------------------------------------------------------- */