123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465 |
- /*
- * Option processing and main()
- *
- * Copyright 2000 Jon Griffiths
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
- #include "config.h"
- #include "winedump.h"
- _globals globals; /* All global variables */
- static void do_include (const char *arg)
- {
- if (!globals.directory)
- globals.directory = xstrdup(arg);
- else
- globals.directory = strmake( "%s %s", globals.directory, arg );
- globals.do_code = TRUE;
- }
- static inline const char* strip_ext (const char *str)
- {
- int len = strlen(str);
- if (len>4 && strcmp(str+len-4,".dll") == 0)
- return str_substring (str, str+len-4);
- else
- return xstrdup (str);
- }
- static void do_name (const char *arg)
- {
- globals.dll_name = strip_ext (arg);
- }
- static void do_spec (const char *arg)
- {
- if (globals.mode != NONE) fatal("Only one mode can be specified\n");
- globals.mode = SPEC;
- }
- static void do_demangle (const char *arg)
- {
- if (globals.mode != NONE) fatal("Only one mode can be specified\n");
- globals.mode = DMGL;
- globals.do_code = TRUE;
- globals.do_demangle = TRUE;
- }
- static void do_dump (const char *arg)
- {
- if (globals.mode != NONE) fatal("Only one mode can be specified\n");
- globals.mode = DUMP;
- globals.do_code = TRUE;
- }
- static void do_code (const char *arg)
- {
- globals.do_code = TRUE;
- }
- static void do_trace (const char *arg)
- {
- globals.do_trace = TRUE;
- globals.do_code = TRUE;
- }
- static void do_forward (const char *arg)
- {
- globals.forward_dll = arg;
- globals.do_trace = TRUE;
- globals.do_code = TRUE;
- }
- static void do_document (const char *arg)
- {
- globals.do_documentation = TRUE;
- }
- static void do_cdecl (const char *arg)
- {
- globals.do_cdecl = TRUE;
- }
- static void do_quiet (const char *arg)
- {
- globals.do_quiet = TRUE;
- }
- static void do_start (const char *arg)
- {
- globals.start_ordinal = atoi (arg);
- if (!globals.start_ordinal)
- fatal ("Invalid -s option (must be numeric)");
- }
- static void do_end (const char *arg)
- {
- globals.end_ordinal = atoi (arg);
- if (!globals.end_ordinal)
- fatal ("Invalid -e option (must be numeric)");
- }
- static void do_symfile (const char *arg)
- {
- FILE *f;
- char symstring[256]; /* keep count with "%<width>s" below */
- search_symbol *symbolp,**symbolptail = &globals.search_symbol;
- if (!(f = fopen(arg, "rt")))
- fatal ("Cannot open <symfile>");
- while (1 == fscanf(f, "%255s", symstring)) /* keep count with [<width>] above */
- {
- symstring[sizeof(symstring)-1] = '\0';
- symbolp = xmalloc(sizeof(*symbolp) + strlen(symstring));
- strcpy(symbolp->symbolname, symstring);
- symbolp->found = FALSE;
- symbolp->next = NULL;
- *symbolptail = symbolp;
- symbolptail = &symbolp->next;
- }
- if (fclose(f))
- fatal ("Cannot close <symfile>");
- }
- static void do_verbose (const char *arg)
- {
- globals.do_verbose = TRUE;
- }
- static void do_symdmngl (const char *arg)
- {
- globals.do_demangle = TRUE;
- }
- static void do_dumphead (const char *arg)
- {
- globals.do_dumpheader = TRUE;
- }
- static void do_dumpsect (const char* arg)
- {
- globals.dumpsect = arg;
- }
- static void do_rawdebug (const char *arg)
- {
- globals.do_debug = TRUE;
- }
- static void do_dumpall(const char *arg)
- {
- globals.do_dumpheader = TRUE;
- globals.do_dump_rawdata = TRUE;
- globals.do_symbol_table = TRUE;
- globals.dumpsect = "ALL";
- }
- static void do_symtable(const char* arg)
- {
- globals.do_symbol_table = TRUE;
- }
- struct my_option
- {
- const char *name;
- Mode mode;
- int has_arg;
- void (*func)(const char *arg);
- const char *usage;
- };
- static const struct my_option option_table[] = {
- {"--help",NONE, 0, do_usage, "--help Display this help message"},
- {"-h", NONE, 0, do_usage, "-h Synonym for --help"},
- {"-?", NONE, 0, do_usage, "-? Synonym for --help"},
- {"dump", DUMP, 0, do_dump, "dump <file> Dump the contents of 'file' (dll, exe, lib...)"},
- {"-C", DUMP, 0, do_symdmngl, "-C Turn on symbol demangling"},
- {"-f", DUMP, 0, do_dumphead, "-f Dump file header information"},
- {"-G", DUMP, 0, do_rawdebug, "-G Dump raw debug information"},
- {"-j", DUMP, 1, do_dumpsect, "-j <sect_name> Dump only the content of section 'sect_name'\n"
- " (import, export, debug, resource, tls, loadcfg, clr, reloc, except, apiset)"},
- {"-t", DUMP, 0, do_symtable, "-t Dump symbol table"},
- {"-x", DUMP, 0, do_dumpall, "-x Dump everything"},
- {"sym", DMGL, 0, do_demangle, "sym <sym> Demangle C++ symbol <sym> and exit"},
- {"spec", SPEC, 0, do_spec, "spec <dll> Use 'dll' for input file and generate implementation code"},
- {"-I", SPEC, 1, do_include, "-I <dir> Look for prototypes in 'dir' (implies -c)"},
- {"-c", SPEC, 0, do_code, "-c Generate skeleton code (requires -I)"},
- {"-t", SPEC, 0, do_trace, "-t TRACE arguments (implies -c)"},
- {"-f", SPEC, 1, do_forward, "-f <dll> Forward calls to 'dll' (implies -t)"},
- {"-D", SPEC, 0, do_document, "-D Generate documentation"},
- {"-o", SPEC, 1, do_name, "-o <name> Set the output dll name (default: dll). Note: strips .dll extensions"},
- {"-C", SPEC, 0, do_cdecl, "-C Assume __cdecl calls (default: __stdcall)"},
- {"-s", SPEC, 1, do_start, "-s <num> Start prototype search after symbol 'num'"},
- {"-e", SPEC, 1, do_end, "-e <num> End prototype search after symbol 'num'"},
- {"-S", SPEC, 1, do_symfile, "-S <symfile> Search only prototype names found in 'symfile'"},
- {"-q", SPEC, 0, do_quiet, "-q Don't show progress (quiet)."},
- {"-v", SPEC, 0, do_verbose, "-v Show lots of detail while working (verbose)."},
- {NULL, NONE, 0, NULL, NULL}
- };
- void do_usage (const char *arg)
- {
- const struct my_option *opt;
- printf ("Usage: winedump [-h | sym <sym> | spec <dll> | dump <file>]\n");
- printf ("Mode options (can be put as the mode (sym/spec/dump...) is declared):\n");
- printf (" When used in --help mode\n");
- for (opt = option_table; opt->name; opt++)
- if (opt->mode == NONE)
- printf (" %s\n", opt->usage);
- printf (" When used in sym mode\n");
- for (opt = option_table; opt->name; opt++)
- if (opt->mode == DMGL)
- printf (" %s\n", opt->usage);
- printf (" When used in spec mode\n");
- for (opt = option_table; opt->name; opt++)
- if (opt->mode == SPEC)
- printf (" %s\n", opt->usage);
- printf (" When used in dump mode\n");
- for (opt = option_table; opt->name; opt++)
- if (opt->mode == DUMP)
- printf (" %s\n", opt->usage);
- puts ("");
- exit (1);
- }
- /*******************************************************************
- * parse_cmdline
- *
- * Parse options from the argv array
- */
- static void parse_cmdline (char *argv[])
- {
- const struct my_option *opt;
- char *const *ptr;
- const char *arg = NULL;
- ptr = argv + 1;
- while (*ptr != NULL)
- {
- for (opt = option_table; opt->name; opt++)
- {
- if (globals.mode != NONE && opt->mode != NONE && globals.mode != opt->mode)
- continue;
- if (((opt->has_arg == 1) && !strncmp (*ptr, opt->name, strlen (opt->name))) ||
- ((opt->has_arg == 2) && !strcmp (*ptr, opt->name)))
- {
- arg = *ptr + strlen (opt->name);
- if (*arg == '\0') arg = *++ptr;
- break;
- }
- if (!strcmp (*ptr, opt->name))
- {
- arg = NULL;
- break;
- }
- }
- if (!opt->name)
- {
- if ((*ptr)[0] == '-')
- fatal ("Unrecognized option");
- if (globals.input_name != NULL)
- fatal ("Only one file can be treated at once");
- globals.input_name = *ptr;
- }
- else if (opt->has_arg && arg != NULL)
- opt->func (arg);
- else
- opt->func ("");
- ptr++;
- }
- if (globals.mode == SPEC && globals.do_code && !globals.directory)
- fatal ("-I must be used if generating code");
- if (VERBOSE && QUIET)
- fatal ("Options -v and -q are mutually exclusive");
- if (globals.mode == NONE)
- do_dump("");
- }
- static void set_module_name(BOOL setUC)
- {
- /* FIXME: we shouldn't assume all module extensions are .dll in winedump
- * in some cases, we could have some .drv for example
- */
- globals.input_module = replace_extension( get_basename( globals.input_name ), ".dll", "" );
- OUTPUT_UC_DLL_NAME = (setUC) ? str_toupper( xstrdup (OUTPUT_DLL_NAME)) : "";
- }
- /* Marks the symbol as 'found'! */
- /* return: perform-search */
- static BOOL symbol_searched(int count, const char *symbolname)
- {
- search_symbol *search_symbol;
- if (!(count >= globals.start_ordinal
- && (!globals.end_ordinal || count <= globals.end_ordinal)))
- return FALSE;
- if (!globals.search_symbol)
- return TRUE;
- for (search_symbol = globals.search_symbol;
- search_symbol;
- search_symbol = search_symbol->next)
- {
- if (!strcmp(symbolname, search_symbol->symbolname))
- {
- search_symbol->found = TRUE;
- return TRUE;
- }
- }
- return FALSE;
- }
- /* return: some symbols weren't found */
- static BOOL symbol_finish(void)
- {
- const search_symbol *search_symbol;
- BOOL started = FALSE;
- for (search_symbol = globals.search_symbol;
- search_symbol;
- search_symbol = search_symbol->next)
- {
- if (search_symbol->found)
- continue;
- if (!started)
- {
- /* stderr? not a practice here */
- puts("These requested <symfile> symbols weren't found:");
- started = TRUE;
- }
- printf("\t%s\n",search_symbol->symbolname);
- }
- return started;
- }
- /*******************************************************************
- * main
- */
- #ifdef __GNUC__
- int main (int argc __attribute__((unused)), char *argv[])
- #else
- int main (int argc, char *argv[])
- #endif
- {
- parsed_symbol symbol;
- int count = 0;
- globals.mode = NONE;
- globals.forward_dll = NULL;
- globals.input_name = NULL;
- globals.dumpsect = NULL;
- parse_cmdline (argv);
- memset (&symbol, 0, sizeof (parsed_symbol));
- switch (globals.mode)
- {
- case DMGL:
- VERBOSE = TRUE;
- if (globals.input_name == NULL)
- fatal("No symbol name has been given\n");
- printf("%s\n", get_symbol_str(globals.input_name));
- break;
- case SPEC:
- if (globals.input_name == NULL)
- fatal("No file name has been given\n");
- set_module_name(TRUE);
- if (!dll_open (globals.input_name))
- break;
- output_spec_preamble ();
- output_header_preamble ();
- output_c_preamble ();
- while (dll_next_symbol (&symbol))
- {
- count++;
- if (NORMAL)
- printf ("Export %3d - '%s' ...%c", count, symbol.symbol,
- VERBOSE ? '\n' : ' ');
- if (globals.do_code && symbol_searched(count, symbol.symbol))
- {
- /* Attempt to get information about the symbol */
- BOOL result = symbol_demangle (&symbol) || symbol_search(&symbol);
- if (result && symbol.function_name)
- /* Clean up the prototype */
- symbol_clean_string (symbol.function_name);
- if (NORMAL)
- puts (result ? "[OK]" : "[Not Found]");
- }
- else if (NORMAL)
- puts ("[Ignoring]");
- output_spec_symbol (&symbol);
- output_header_symbol (&symbol);
- output_c_symbol (&symbol);
- symbol_clear (&symbol);
- }
- output_makefile ();
- if (VERBOSE)
- puts ("Finished, Cleaning up...");
- if (symbol_finish())
- return 1;
- break;
- case NONE:
- do_usage(0);
- break;
- case DUMP:
- if (globals.input_name == NULL)
- fatal("No file name has been given\n");
- set_module_name(FALSE);
- dump_file(globals.input_name);
- break;
- }
- return 0;
- }
|