Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/tools/winedump/main.c
4389 views
1
/*
2
* Option processing and main()
3
*
4
* Copyright 2000 Jon Griffiths
5
*
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2.1 of the License, or (at your option) any later version.
10
*
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with this library; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19
*/
20
21
#include "config.h"
22
23
#include "winedump.h"
24
25
_globals globals; /* All global variables */
26
27
28
static void do_include (const char *arg)
29
{
30
if (!globals.directory)
31
globals.directory = xstrdup(arg);
32
else
33
globals.directory = strmake( "%s %s", globals.directory, arg );
34
globals.do_code = TRUE;
35
}
36
37
38
static inline const char* strip_ext (const char *str)
39
{
40
int len = strlen(str);
41
if (len>4 && strcmp(str+len-4,".dll") == 0)
42
return str_substring (str, str+len-4);
43
else
44
return xstrdup (str);
45
}
46
47
48
static void do_name (const char *arg)
49
{
50
globals.dll_name = strip_ext (arg);
51
}
52
53
54
static void do_spec (const char *arg)
55
{
56
if (globals.mode != NONE) fatal("Only one mode can be specified\n");
57
globals.mode = SPEC;
58
}
59
60
61
static void do_demangle (const char *arg)
62
{
63
if (globals.mode != NONE) fatal("Only one mode can be specified\n");
64
globals.mode = DMGL;
65
globals.do_code = TRUE;
66
globals.do_demangle = TRUE;
67
}
68
69
70
static void do_dump (const char *arg)
71
{
72
if (globals.mode != NONE) fatal("Only one mode can be specified\n");
73
globals.mode = DUMP;
74
globals.do_code = TRUE;
75
}
76
77
78
static void do_code (const char *arg)
79
{
80
globals.do_code = TRUE;
81
}
82
83
84
static void do_trace (const char *arg)
85
{
86
globals.do_trace = TRUE;
87
globals.do_code = TRUE;
88
}
89
90
91
static void do_forward (const char *arg)
92
{
93
globals.forward_dll = arg;
94
globals.do_trace = TRUE;
95
globals.do_code = TRUE;
96
}
97
98
static void do_document (const char *arg)
99
{
100
globals.do_documentation = TRUE;
101
}
102
103
static void do_cdecl (const char *arg)
104
{
105
globals.do_cdecl = TRUE;
106
}
107
108
109
static void do_quiet (const char *arg)
110
{
111
globals.do_quiet = TRUE;
112
}
113
114
115
static void do_start (const char *arg)
116
{
117
globals.start_ordinal = atoi (arg);
118
if (!globals.start_ordinal)
119
fatal ("Invalid -s option (must be numeric)");
120
}
121
122
123
static void do_end (const char *arg)
124
{
125
globals.end_ordinal = atoi (arg);
126
if (!globals.end_ordinal)
127
fatal ("Invalid -e option (must be numeric)");
128
}
129
130
131
static void do_symfile (const char *arg)
132
{
133
FILE *f;
134
char symstring[256]; /* keep count with "%<width>s" below */
135
search_symbol *symbolp,**symbolptail = &globals.search_symbol;
136
137
if (!(f = fopen(arg, "rt")))
138
fatal ("Cannot open <symfile>");
139
while (1 == fscanf(f, "%255s", symstring)) /* keep count with [<width>] above */
140
{
141
symstring[sizeof(symstring)-1] = '\0';
142
symbolp = xmalloc(sizeof(*symbolp) + strlen(symstring));
143
strcpy(symbolp->symbolname, symstring);
144
symbolp->found = FALSE;
145
symbolp->next = NULL;
146
*symbolptail = symbolp;
147
symbolptail = &symbolp->next;
148
}
149
if (fclose(f))
150
fatal ("Cannot close <symfile>");
151
}
152
153
154
static void do_verbose (const char *arg)
155
{
156
globals.do_verbose = TRUE;
157
}
158
159
160
static void do_symdmngl (const char *arg)
161
{
162
globals.do_demangle = TRUE;
163
}
164
165
static void do_dumphead (const char *arg)
166
{
167
globals.do_dumpheader = TRUE;
168
}
169
170
static void do_dumpsect (const char* arg)
171
{
172
unsigned count = 2;
173
char* p;
174
const char** out;
175
176
for (p = (char*)arg; (p = strchr(p, ',')) != NULL; p++, count++);
177
out = malloc(count * sizeof(char*));
178
globals.dumpsect = out;
179
count = 0;
180
p = strdup(arg);
181
for (;;)
182
{
183
out[count++] = p;
184
p = strchr(p, ',');
185
if (!p) break;
186
*p++ = '\0';
187
}
188
out[count] = NULL;
189
}
190
191
static void do_rawdebug (const char *arg)
192
{
193
globals.do_debug = TRUE;
194
}
195
196
static void do_dumpall(const char *arg)
197
{
198
globals.do_dumpheader = TRUE;
199
globals.do_dump_rawdata = TRUE;
200
globals.do_symbol_table = TRUE;
201
do_dumpsect ("ALL");
202
}
203
204
static void do_symtable(const char* arg)
205
{
206
globals.do_symbol_table = TRUE;
207
}
208
209
struct my_option
210
{
211
const char *name;
212
Mode mode;
213
int has_arg;
214
void (*func)(const char *arg);
215
const char *usage;
216
};
217
218
static const struct my_option option_table[] = {
219
{"--help",NONE, 0, do_usage, "--help Display this help message"},
220
{"-h", NONE, 0, do_usage, "-h Synonym for --help"},
221
{"-?", NONE, 0, do_usage, "-? Synonym for --help"},
222
{"dump", DUMP, 0, do_dump, "dump <file> Dump the contents of 'file' (dll, exe, lib...)"},
223
{"-C", DUMP, 0, do_symdmngl, "-C Turn on symbol demangling"},
224
{"-f", DUMP, 0, do_dumphead, "-f Dump file header information"},
225
{"-G", DUMP, 0, do_rawdebug, "-G Dump raw debug information"},
226
{"-j", DUMP, 1, do_dumpsect, "-j <sect_name> Dump the content of section 'sect_name'\n"
227
" (use '-j sect_name,sect_name2' to dump several sections)\n"
228
" for NE: export, resource\n"
229
" for PE: import, export, debug, resource, tls, loadcfg, clr, reloc, dynreloc, except, apiset\n"
230
" for PDB: PDB, TPI, DBI, IPI, public, image\n"
231
" and suboptions: hash (PDB, TPI, TPI, DBI, public) and line (DBI)\n"
232
" for minidump: exception, handle, info, memory, module, system, thread, token\n"
233
" and suboptions: content (memory, module, thread, token)\n"},
234
{"-t", DUMP, 0, do_symtable, "-t Dump symbol table"},
235
{"-x", DUMP, 0, do_dumpall, "-x Dump everything"},
236
{"sym", DMGL, 0, do_demangle, "sym <sym> Demangle C++ symbol <sym> and exit"},
237
{"spec", SPEC, 0, do_spec, "spec <dll> Use 'dll' for input file and generate implementation code"},
238
{"-I", SPEC, 1, do_include, "-I <dir> Look for prototypes in 'dir' (implies -c)"},
239
{"-c", SPEC, 0, do_code, "-c Generate skeleton code (requires -I)"},
240
{"-t", SPEC, 0, do_trace, "-t TRACE arguments (implies -c)"},
241
{"-f", SPEC, 1, do_forward, "-f <dll> Forward calls to 'dll' (implies -t)"},
242
{"-D", SPEC, 0, do_document, "-D Generate documentation"},
243
{"-o", SPEC, 1, do_name, "-o <name> Set the output dll name (default: dll). Note: strips .dll extensions"},
244
{"-C", SPEC, 0, do_cdecl, "-C Assume __cdecl calls (default: __stdcall)"},
245
{"-s", SPEC, 1, do_start, "-s <num> Start prototype search after symbol 'num'"},
246
{"-e", SPEC, 1, do_end, "-e <num> End prototype search after symbol 'num'"},
247
{"-S", SPEC, 1, do_symfile, "-S <symfile> Search only prototype names found in 'symfile'"},
248
{"-q", SPEC, 0, do_quiet, "-q Don't show progress (quiet)."},
249
{"-v", SPEC, 0, do_verbose, "-v Show lots of detail while working (verbose)."},
250
{NULL, NONE, 0, NULL, NULL}
251
};
252
253
void do_usage (const char *arg)
254
{
255
const struct my_option *opt;
256
printf ("Usage: winedump [-h | sym <sym> | spec <dll> | dump <file>]\n");
257
printf ("Mode options (can be put as the mode (sym/spec/dump...) is declared):\n");
258
printf (" When used in --help mode\n");
259
for (opt = option_table; opt->name; opt++)
260
if (opt->mode == NONE)
261
printf (" %s\n", opt->usage);
262
printf (" When used in sym mode\n");
263
for (opt = option_table; opt->name; opt++)
264
if (opt->mode == DMGL)
265
printf (" %s\n", opt->usage);
266
printf (" When used in spec mode\n");
267
for (opt = option_table; opt->name; opt++)
268
if (opt->mode == SPEC)
269
printf (" %s\n", opt->usage);
270
printf (" When used in dump mode\n");
271
for (opt = option_table; opt->name; opt++)
272
if (opt->mode == DUMP)
273
printf (" %s\n", opt->usage);
274
275
puts ("");
276
exit (1);
277
}
278
279
280
/*******************************************************************
281
* parse_cmdline
282
*
283
* Parse options from the argv array
284
*/
285
static void parse_cmdline (char *argv[])
286
{
287
const struct my_option *opt;
288
char *const *ptr;
289
const char *arg = NULL;
290
291
ptr = argv + 1;
292
293
while (*ptr != NULL)
294
{
295
for (opt = option_table; opt->name; opt++)
296
{
297
if (globals.mode != NONE && opt->mode != NONE && globals.mode != opt->mode)
298
continue;
299
if (((opt->has_arg == 1) && !strncmp (*ptr, opt->name, strlen (opt->name))) ||
300
((opt->has_arg == 2) && !strcmp (*ptr, opt->name)))
301
{
302
arg = *ptr + strlen (opt->name);
303
if (*arg == '\0') arg = *++ptr;
304
break;
305
}
306
if (!strcmp (*ptr, opt->name))
307
{
308
arg = NULL;
309
break;
310
}
311
}
312
313
if (!opt->name)
314
{
315
if ((*ptr)[0] == '-')
316
fatal ("Unrecognized option");
317
if (globals.input_name != NULL)
318
fatal ("Only one file can be treated at once");
319
globals.input_name = *ptr;
320
}
321
else if (opt->has_arg && arg != NULL)
322
opt->func (arg);
323
else
324
opt->func ("");
325
326
ptr++;
327
}
328
329
if (globals.mode == SPEC && globals.do_code && !globals.directory)
330
fatal ("-I must be used if generating code");
331
332
if (VERBOSE && QUIET)
333
fatal ("Options -v and -q are mutually exclusive");
334
335
if (globals.mode == NONE)
336
do_dump("");
337
}
338
339
static void set_module_name(BOOL setUC)
340
{
341
/* FIXME: we shouldn't assume all module extensions are .dll in winedump
342
* in some cases, we could have some .drv for example
343
*/
344
globals.input_module = replace_extension( get_basename( globals.input_name ), ".dll", "" );
345
OUTPUT_UC_DLL_NAME = (setUC) ? str_toupper( xstrdup (OUTPUT_DLL_NAME)) : "";
346
}
347
348
/* Marks the symbol as 'found'! */
349
/* return: perform-search */
350
static BOOL symbol_searched(int count, const char *symbolname)
351
{
352
search_symbol *search_symbol;
353
354
if (!(count >= globals.start_ordinal
355
&& (!globals.end_ordinal || count <= globals.end_ordinal)))
356
return FALSE;
357
if (!globals.search_symbol)
358
return TRUE;
359
for (search_symbol = globals.search_symbol;
360
search_symbol;
361
search_symbol = search_symbol->next)
362
{
363
if (!strcmp(symbolname, search_symbol->symbolname))
364
{
365
search_symbol->found = TRUE;
366
return TRUE;
367
}
368
}
369
return FALSE;
370
}
371
372
/* return: some symbols weren't found */
373
static BOOL symbol_finish(void)
374
{
375
const search_symbol *search_symbol;
376
BOOL started = FALSE;
377
378
for (search_symbol = globals.search_symbol;
379
search_symbol;
380
search_symbol = search_symbol->next)
381
{
382
if (search_symbol->found)
383
continue;
384
if (!started)
385
{
386
/* stderr? not a practice here */
387
puts("These requested <symfile> symbols weren't found:");
388
started = TRUE;
389
}
390
printf("\t%s\n",search_symbol->symbolname);
391
}
392
return started;
393
}
394
395
BOOL globals_dump_sect(const char* s)
396
{
397
const char** sect;
398
399
if (!s || !globals.dumpsect) return FALSE;
400
for (sect = globals.dumpsect; *sect; sect++)
401
if (!strcmp(*sect, s) || !strcmp(*sect, "ALL")) return TRUE;
402
return FALSE;
403
}
404
405
/*******************************************************************
406
* main
407
*/
408
#ifdef __GNUC__
409
int main (int argc __attribute__((unused)), char *argv[])
410
#else
411
int main (int argc, char *argv[])
412
#endif
413
{
414
parsed_symbol symbol;
415
int count = 0;
416
417
globals.mode = NONE;
418
globals.forward_dll = NULL;
419
globals.input_name = NULL;
420
globals.dumpsect = NULL;
421
422
parse_cmdline (argv);
423
424
memset (&symbol, 0, sizeof (parsed_symbol));
425
426
switch (globals.mode)
427
{
428
case DMGL:
429
VERBOSE = TRUE;
430
431
if (globals.input_name == NULL)
432
fatal("No symbol name has been given\n");
433
printf("%s\n", get_symbol_str(globals.input_name));
434
break;
435
436
case SPEC:
437
if (globals.input_name == NULL)
438
fatal("No file name has been given\n");
439
set_module_name(TRUE);
440
if (!dll_open (globals.input_name))
441
break;
442
443
output_spec_preamble ();
444
output_header_preamble ();
445
output_c_preamble ();
446
447
while (dll_next_symbol (&symbol))
448
{
449
count++;
450
451
if (NORMAL)
452
printf ("Export %3d - '%s' ...%c", count, symbol.symbol,
453
VERBOSE ? '\n' : ' ');
454
455
if (globals.do_code && symbol_searched(count, symbol.symbol))
456
{
457
/* Attempt to get information about the symbol */
458
BOOL result = symbol_search(&symbol);
459
460
if (result && symbol.function_name)
461
/* Clean up the prototype */
462
symbol_clean_string (symbol.function_name);
463
464
if (NORMAL)
465
puts (result ? "[OK]" : "[Not Found]");
466
}
467
else if (NORMAL)
468
puts ("[Ignoring]");
469
470
output_spec_symbol (&symbol);
471
output_header_symbol (&symbol);
472
output_c_symbol (&symbol);
473
474
symbol_clear (&symbol);
475
}
476
477
output_makefile ();
478
479
if (VERBOSE)
480
puts ("Finished, Cleaning up...");
481
if (symbol_finish())
482
return 1;
483
break;
484
case NONE:
485
do_usage(0);
486
break;
487
case DUMP:
488
if (globals.input_name == NULL)
489
fatal("No file name has been given\n");
490
set_module_name(FALSE);
491
dump_file(globals.input_name);
492
break;
493
}
494
495
return 0;
496
}
497
498