2 * Option processing and main()
4 * Copyright 2000 Jon Griffiths
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.
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.
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
25 _globals globals
; /* All global variables */
28 static void do_include (const char *arg
)
30 if (!globals
.directory
)
31 globals
.directory
= xstrdup(arg
);
33 globals
.directory
= strmake( "%s %s", globals
.directory
, arg
);
34 globals
.do_code
= TRUE
;
38 static inline const char* strip_ext (const char *str
)
40 int len
= strlen(str
);
41 if (len
>4 && strcmp(str
+len
-4,".dll") == 0)
42 return str_substring (str
, str
+len
-4);
48 static void do_name (const char *arg
)
50 globals
.dll_name
= strip_ext (arg
);
54 static void do_spec (const char *arg
)
56 if (globals
.mode
!= NONE
) fatal("Only one mode can be specified\n");
61 static void do_demangle (const char *arg
)
63 if (globals
.mode
!= NONE
) fatal("Only one mode can be specified\n");
65 globals
.do_code
= TRUE
;
66 globals
.do_demangle
= TRUE
;
70 static void do_dump (const char *arg
)
72 if (globals
.mode
!= NONE
) fatal("Only one mode can be specified\n");
74 globals
.do_code
= TRUE
;
78 static void do_code (const char *arg
)
80 globals
.do_code
= TRUE
;
84 static void do_trace (const char *arg
)
86 globals
.do_trace
= TRUE
;
87 globals
.do_code
= TRUE
;
91 static void do_forward (const char *arg
)
93 globals
.forward_dll
= arg
;
94 globals
.do_trace
= TRUE
;
95 globals
.do_code
= TRUE
;
98 static void do_document (const char *arg
)
100 globals
.do_documentation
= TRUE
;
103 static void do_cdecl (const char *arg
)
105 globals
.do_cdecl
= TRUE
;
109 static void do_quiet (const char *arg
)
111 globals
.do_quiet
= TRUE
;
115 static void do_start (const char *arg
)
117 globals
.start_ordinal
= atoi (arg
);
118 if (!globals
.start_ordinal
)
119 fatal ("Invalid -s option (must be numeric)");
123 static void do_end (const char *arg
)
125 globals
.end_ordinal
= atoi (arg
);
126 if (!globals
.end_ordinal
)
127 fatal ("Invalid -e option (must be numeric)");
131 static void do_symfile (const char *arg
)
134 char symstring
[256]; /* keep count with "%<width>s" below */
135 search_symbol
*symbolp
,**symbolptail
= &globals
.search_symbol
;
137 if (!(f
= fopen(arg
, "rt")))
138 fatal ("Cannot open <symfile>");
139 while (1 == fscanf(f
, "%255s", symstring
)) /* keep count with [<width>] above */
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
;
150 fatal ("Cannot close <symfile>");
154 static void do_verbose (const char *arg
)
156 globals
.do_verbose
= TRUE
;
160 static void do_symdmngl (const char *arg
)
162 globals
.do_demangle
= TRUE
;
165 static void do_dumphead (const char *arg
)
167 globals
.do_dumpheader
= TRUE
;
170 static void do_dumpsect (const char* arg
)
176 for (p
= (char*)arg
; (p
= strchr(p
, ',')) != NULL
; p
++, count
++);
177 out
= malloc(count
* sizeof(char*));
178 globals
.dumpsect
= out
;
191 static void do_rawdebug (const char *arg
)
193 globals
.do_debug
= TRUE
;
196 static void do_dumpall(const char *arg
)
198 globals
.do_dumpheader
= TRUE
;
199 globals
.do_dump_rawdata
= TRUE
;
200 globals
.do_symbol_table
= TRUE
;
204 static void do_symtable(const char* arg
)
206 globals
.do_symbol_table
= TRUE
;
214 void (*func
)(const char *arg
);
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)"},
232 {"-t", DUMP
, 0, do_symtable
, "-t Dump symbol table"},
233 {"-x", DUMP
, 0, do_dumpall
, "-x Dump everything"},
234 {"sym", DMGL
, 0, do_demangle
, "sym <sym> Demangle C++ symbol <sym> and exit"},
235 {"spec", SPEC
, 0, do_spec
, "spec <dll> Use 'dll' for input file and generate implementation code"},
236 {"-I", SPEC
, 1, do_include
, "-I <dir> Look for prototypes in 'dir' (implies -c)"},
237 {"-c", SPEC
, 0, do_code
, "-c Generate skeleton code (requires -I)"},
238 {"-t", SPEC
, 0, do_trace
, "-t TRACE arguments (implies -c)"},
239 {"-f", SPEC
, 1, do_forward
, "-f <dll> Forward calls to 'dll' (implies -t)"},
240 {"-D", SPEC
, 0, do_document
, "-D Generate documentation"},
241 {"-o", SPEC
, 1, do_name
, "-o <name> Set the output dll name (default: dll). Note: strips .dll extensions"},
242 {"-C", SPEC
, 0, do_cdecl
, "-C Assume __cdecl calls (default: __stdcall)"},
243 {"-s", SPEC
, 1, do_start
, "-s <num> Start prototype search after symbol 'num'"},
244 {"-e", SPEC
, 1, do_end
, "-e <num> End prototype search after symbol 'num'"},
245 {"-S", SPEC
, 1, do_symfile
, "-S <symfile> Search only prototype names found in 'symfile'"},
246 {"-q", SPEC
, 0, do_quiet
, "-q Don't show progress (quiet)."},
247 {"-v", SPEC
, 0, do_verbose
, "-v Show lots of detail while working (verbose)."},
248 {NULL
, NONE
, 0, NULL
, NULL
}
251 void do_usage (const char *arg
)
253 const struct my_option
*opt
;
254 printf ("Usage: winedump [-h | sym <sym> | spec <dll> | dump <file>]\n");
255 printf ("Mode options (can be put as the mode (sym/spec/dump...) is declared):\n");
256 printf (" When used in --help mode\n");
257 for (opt
= option_table
; opt
->name
; opt
++)
258 if (opt
->mode
== NONE
)
259 printf (" %s\n", opt
->usage
);
260 printf (" When used in sym mode\n");
261 for (opt
= option_table
; opt
->name
; opt
++)
262 if (opt
->mode
== DMGL
)
263 printf (" %s\n", opt
->usage
);
264 printf (" When used in spec mode\n");
265 for (opt
= option_table
; opt
->name
; opt
++)
266 if (opt
->mode
== SPEC
)
267 printf (" %s\n", opt
->usage
);
268 printf (" When used in dump mode\n");
269 for (opt
= option_table
; opt
->name
; opt
++)
270 if (opt
->mode
== DUMP
)
271 printf (" %s\n", opt
->usage
);
278 /*******************************************************************
281 * Parse options from the argv array
283 static void parse_cmdline (char *argv
[])
285 const struct my_option
*opt
;
287 const char *arg
= NULL
;
293 for (opt
= option_table
; opt
->name
; opt
++)
295 if (globals
.mode
!= NONE
&& opt
->mode
!= NONE
&& globals
.mode
!= opt
->mode
)
297 if (((opt
->has_arg
== 1) && !strncmp (*ptr
, opt
->name
, strlen (opt
->name
))) ||
298 ((opt
->has_arg
== 2) && !strcmp (*ptr
, opt
->name
)))
300 arg
= *ptr
+ strlen (opt
->name
);
301 if (*arg
== '\0') arg
= *++ptr
;
304 if (!strcmp (*ptr
, opt
->name
))
313 if ((*ptr
)[0] == '-')
314 fatal ("Unrecognized option");
315 if (globals
.input_name
!= NULL
)
316 fatal ("Only one file can be treated at once");
317 globals
.input_name
= *ptr
;
319 else if (opt
->has_arg
&& arg
!= NULL
)
327 if (globals
.mode
== SPEC
&& globals
.do_code
&& !globals
.directory
)
328 fatal ("-I must be used if generating code");
330 if (VERBOSE
&& QUIET
)
331 fatal ("Options -v and -q are mutually exclusive");
333 if (globals
.mode
== NONE
)
337 static void set_module_name(BOOL setUC
)
339 /* FIXME: we shouldn't assume all module extensions are .dll in winedump
340 * in some cases, we could have some .drv for example
342 globals
.input_module
= replace_extension( get_basename( globals
.input_name
), ".dll", "" );
343 OUTPUT_UC_DLL_NAME
= (setUC
) ? str_toupper( xstrdup (OUTPUT_DLL_NAME
)) : "";
346 /* Marks the symbol as 'found'! */
347 /* return: perform-search */
348 static BOOL
symbol_searched(int count
, const char *symbolname
)
350 search_symbol
*search_symbol
;
352 if (!(count
>= globals
.start_ordinal
353 && (!globals
.end_ordinal
|| count
<= globals
.end_ordinal
)))
355 if (!globals
.search_symbol
)
357 for (search_symbol
= globals
.search_symbol
;
359 search_symbol
= search_symbol
->next
)
361 if (!strcmp(symbolname
, search_symbol
->symbolname
))
363 search_symbol
->found
= TRUE
;
370 /* return: some symbols weren't found */
371 static BOOL
symbol_finish(void)
373 const search_symbol
*search_symbol
;
374 BOOL started
= FALSE
;
376 for (search_symbol
= globals
.search_symbol
;
378 search_symbol
= search_symbol
->next
)
380 if (search_symbol
->found
)
384 /* stderr? not a practice here */
385 puts("These requested <symfile> symbols weren't found:");
388 printf("\t%s\n",search_symbol
->symbolname
);
393 BOOL
globals_dump_sect(const char* s
)
397 if (!s
|| !globals
.dumpsect
) return FALSE
;
398 for (sect
= globals
.dumpsect
; *sect
; sect
++)
399 if (!strcmp(*sect
, s
) || !strcmp(*sect
, "ALL")) return TRUE
;
403 /*******************************************************************
407 int main (int argc
__attribute__((unused
)), char *argv
[])
409 int main (int argc
, char *argv
[])
412 parsed_symbol symbol
;
416 globals
.forward_dll
= NULL
;
417 globals
.input_name
= NULL
;
418 globals
.dumpsect
= NULL
;
420 parse_cmdline (argv
);
422 memset (&symbol
, 0, sizeof (parsed_symbol
));
424 switch (globals
.mode
)
429 if (globals
.input_name
== NULL
)
430 fatal("No symbol name has been given\n");
431 printf("%s\n", get_symbol_str(globals
.input_name
));
435 if (globals
.input_name
== NULL
)
436 fatal("No file name has been given\n");
437 set_module_name(TRUE
);
438 if (!dll_open (globals
.input_name
))
441 output_spec_preamble ();
442 output_header_preamble ();
443 output_c_preamble ();
445 while (dll_next_symbol (&symbol
))
450 printf ("Export %3d - '%s' ...%c", count
, symbol
.symbol
,
451 VERBOSE
? '\n' : ' ');
453 if (globals
.do_code
&& symbol_searched(count
, symbol
.symbol
))
455 /* Attempt to get information about the symbol */
456 BOOL result
= symbol_demangle (&symbol
) || symbol_search(&symbol
);
458 if (result
&& symbol
.function_name
)
459 /* Clean up the prototype */
460 symbol_clean_string (symbol
.function_name
);
463 puts (result
? "[OK]" : "[Not Found]");
468 output_spec_symbol (&symbol
);
469 output_header_symbol (&symbol
);
470 output_c_symbol (&symbol
);
472 symbol_clear (&symbol
);
478 puts ("Finished, Cleaning up...");
486 if (globals
.input_name
== NULL
)
487 fatal("No file name has been given\n");
488 set_module_name(FALSE
);
489 dump_file(globals
.input_name
);