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
31 char *get_export_names(int fd
);
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
;
65 for (i
= 1; i
< argc
; ++i
) {
66 const char *a
= argv
[i
];
68 if (0 == strcmp(a
, "-v")) {
70 } else if (0 == strcmp(a
, "-o")) {
73 strcpy(outfile
, argv
[i
]);
76 } else if (0 == infile
[0])
85 "tiny_impdef: create export definition file (.def) from a dll\n"
86 "Usage: tiny_impdef library.dll [-o outputfile]\n"
93 strcpy(outfile
, file_basename(infile
));
94 q
= strrchr(outfile
, '.');
96 q
= strchr(outfile
, 0);
104 do if (SearchPath(NULL
, file
, *pp
, sizeof path
, path
, NULL
)) {
110 fp
= fopen(file
, "rb");
112 fprintf(stderr
, "tiny_impdef: no such file: %s\n", infile
);
116 printf("--> %s\n", file
);
118 p
= get_export_names(fileno(fp
));
120 fprintf(stderr
, "tiny_impdef: could not get exported function names.\n");
124 op
= fopen(outfile
, "w");
126 fprintf(stderr
, "tiny_impdef: could not create output file: %s\n", outfile
);
130 fprintf(op
, "LIBRARY %s\n\nEXPORTS\n", file_basename(file
));
131 for (q
= p
, i
= 0; *q
; ++i
) {
132 fprintf(op
, "%s\n", q
);
137 printf("<-- %s\n", outfile
);
138 printf("%d symbol(s) found\n", i
);
153 int read_mem(int fd
, unsigned offset
, void *buffer
, unsigned len
)
155 lseek(fd
, offset
, SEEK_SET
);
156 return len
== read(fd
, buffer
, len
);
159 /* -------------------------------------------------------------- */
161 #if defined TCC_TARGET_X86_64
162 # define IMAGE_FILE_MACHINE 0x8664
163 #elif defined TCC_TARGET_ARM
164 # define IMAGE_FILE_MACHINE 0x01C0
165 #elif 1 /* defined TCC_TARGET_I386 */
166 # define IMAGE_FILE_MACHINE 0x014C
169 /* -------------------------------------------------------------- */
172 char *get_export_names(int fd
)
177 IMAGE_SECTION_HEADER ish
;
178 IMAGE_EXPORT_DIRECTORY ied
;
180 IMAGE_FILE_HEADER ih
;
181 DWORD sig
, ref
, addr
, ptr
, namep
;
182 #ifdef TCC_TARGET_X86_64
183 IMAGE_OPTIONAL_HEADER64 oh
;
185 IMAGE_OPTIONAL_HEADER32 oh
;
187 int pef_hdroffset
, opt_hdroffset
, sec_hdroffset
;
192 if (!read_mem(fd
, 0, &dh
, sizeof dh
))
194 if (!read_mem(fd
, dh
.e_lfanew
, &sig
, sizeof sig
))
196 if (sig
!= 0x00004550)
198 pef_hdroffset
= dh
.e_lfanew
+ sizeof sig
;
199 if (!read_mem(fd
, pef_hdroffset
, &ih
, sizeof ih
))
201 if (IMAGE_FILE_MACHINE
!= ih
.Machine
)
203 opt_hdroffset
= pef_hdroffset
+ sizeof ih
;
204 sec_hdroffset
= opt_hdroffset
+ sizeof oh
;
205 if (!read_mem(fd
, opt_hdroffset
, &oh
, sizeof oh
))
208 if (IMAGE_DIRECTORY_ENTRY_EXPORT
>= oh
.NumberOfRvaAndSizes
)
211 addr
= oh
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
;
212 //printf("addr: %08x\n", addr);
213 for (i
= 0; i
< ih
.NumberOfSections
; ++i
) {
214 if (!read_mem(fd
, sec_hdroffset
+ i
* sizeof ish
, &ish
, sizeof ish
))
216 //printf("vaddr: %08x\n", ish.VirtualAddress);
217 if (addr
>= ish
.VirtualAddress
&& addr
< ish
.VirtualAddress
+ ish
.SizeOfRawData
)
223 ref
= ish
.VirtualAddress
- ish
.PointerToRawData
;
224 if (!read_mem(fd
, addr
- ref
, &ied
, sizeof ied
))
227 namep
= ied
.AddressOfNames
- ref
;
228 for (i
= 0; i
< ied
.NumberOfNames
; ++i
) {
229 if (!read_mem(fd
, namep
, &ptr
, sizeof ptr
))
234 p
= tcc_realloc(p
, n0
= n0
? n0
* 2 : 256);
235 if (!read_mem(fd
, ptr
- ref
+ l
++, p
+ n
, 1)) {
236 tcc_free(p
), p
= NULL
;
249 /* -------------------------------------------------------------- */