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