@end quotation
@smallexample
-dlltool [-d|--input-def <def-file-name>]
- [-b|--base-file <base-file-name>]
- [-e|--output-exp <exports-file-name>]
- [-z|--output-def <def-file-name>]
- [-l|--output-lib <library-file-name>]
- [-S|--as <path-to-assembler>] [-f|--as-flags <options>]
- [-D|--dllname <name>] [-m|--machine <machine>]
+dlltool [-d|--input-def @var{def-file-name}]
+ [-b|--base-file @var{base-file-name}]
+ [-e|--output-exp @var{exports-file-name}]
+ [-z|--output-def @var{def-file-name}]
+ [-l|--output-lib @var{library-file-name}]
+ [--export-all-symbols] [--no-export-all-symbols]
+ [--exclude-symbols @var{list}]
+ [--no-default-excludes]
+ [-S|--as @var{path-to-assembler}] [-f|--as-flags @var{options}]
+ [-D|--dllname @var{name}] [-m|--machine @var{machine}]
[-a|--add-indirect] [-U|--add-underscore] [-k|--kill-at]
[-x|--no-idata4] [-c|--no-idata5] [-i|--interwork]
[-n|--nodelete] [-v|--verbose] [-h|--help] [-V|--version]
put entries for them in the .def file it creates.
In order to mark a function as being exported from a DLL, it needs to
-have an @samp{-export:<name_of_function>} entry in the @samp{.drective}
+have an @samp{-export:<name_of_function>} entry in the @samp{.drectve}
section of the object file. This can be done in C by using the
asm() operator:
@smallexample
- asm (".section .drective");
+ asm (".section .drectve");
asm (".ascii \"-export:my_func\"");
int my_func (void) @{ @dots{} @}
@table @code
-@item -d FILENAME
-@itemx --input-def FILENAME
+@item -d @var{filename}
+@itemx --input-def @var{filename}
@cindex input .def file
Specifies the name of a .def file to be read in and processed.
-@item -b FILENAME
-@itemx --base-file FILENAME
+@item -b @var{filename}
+@itemx --base-file @var{filename}
@cindex base files
Specifies the name of a base file to be read in and processed. The
contents of this file will be added to the relocation section in the
exports file generated by dlltool.
-@item -e FILENAME
-@itemx --output-exp FILENAME
+@item -e @var{filename}
+@itemx --output-exp @var{filename}
Specifies the name of the export file to be created by dlltool.
-@item -z FILENAME
-@itemx --output-def FILENAME
+@item -z @var{filename}
+@itemx --output-def @var{filename}
Specifies the name of the .def file to be created by dlltool.
-@item -l FILENAME
-@itemx --output-lib FILENAME
+@item -l @var{filename}
+@itemx --output-lib @var{filename}
Specifies the name of the library file to be created by dlltool.
-@item -S PATH
-@itemx --as PATH
+@item --export-all-symbols
+Treat all global and weak defined symbols found in the input object
+files as symbols to be exported. There is a small list of symbols which
+are not exported by default; see the @code{--no-default-excludes}
+option. You may add to the list of symbols to not export by using the
+@code{--exclude-symbols} option.
+
+@item --no-export-all-symbols
+Only export symbols explicitly listed in an input .def file or in
+@samp{.drectve} sections in the input object files. This is the default
+behaviour. The @samp{.drectve} sections are created by @samp{dllexport}
+attributes in the source code.
+
+@item --exclude-symbols @var{list}
+Do not export the symbols in @var{list}. This is a list of symbol names
+separated by comma or colon characters. The symbol names should not
+contain a leading underscore. This is only meaningful when
+@code{--export-all-symbols} is used.
+
+@item --no-default-excludes
+When @code{--export-all-symbols} is used, it will by default avoid
+exporting certain special symbols. The current list of symbols to avoid
+exporting is @samp{DllMain@@12}, @samp{DllEntryPoint@@0},
+@samp{impure_ptr}. You may use the @code{--no-default-excludes} option
+to go ahead and export these special symbols. This is only meaningful
+when @code{--export-all-symbols} is used.
+
+@item -S @var{path}
+@itemx --as @var{path}
Specifies the path, including the filename, of the assembler to be used
to create the exports file.
-@item -f SWITCHES
-@itemx --as-flags SWITCHES
+@item -f @var{switches}
+@itemx --as-flags @var{switches}
Specifies any specific command line switches to be passed to the
assembler when building the exports file. This option will work even if
the @samp{-S} option is not used. This option only takes one argument,
pass multiple switches to the assembler they should be enclosed in
double quotes.
-@item -D NAME
-@itemx --dll-name NAME
+@item -D @var{name}
+@itemx --dll-name @var{name}
Specifies the name to be stored in the .def file as the name of the DLL
when the @samp{-e} option is used. If this option is not present, then
the filename given to the @samp{-e} option will be used as the name of
the DLL.
-@item -m MACHINE
-@itemx -machine MACHINE
+@item -m @var{machine}
+@itemx -machine @var{machine}
Specifies the type of machine for which the library file should be
built. @code{dlltool} has a built in default type, depending upon how
it was created, but this option can be used to override that. This is
static int interwork = 0;
#endif
+/* True if we should export all symbols. Otherwise, we only export
+ symbols listed in .drectve sections or in the def file. */
+static boolean export_all_symbols;
+
+/* True if we should exclude the symbols in DEFAULT_EXCLUDES when
+ exporting all symbols. */
+static boolean do_default_excludes;
+
+/* Default symbols to exclude when exporting all the symbols. */
+static const char *default_excludes = "DllMain@12,DllEntryPoint@0,impure_ptr";
+
static char *def_file;
extern char * program_name;
}
export_type;
+/* A list of symbols which we should not export. */
+
+struct string_list
+{
+ struct string_list *next;
+ char *string;
+};
+
+static struct string_list *excludes;
+
static const char *rvaafter PARAMS ((int));
static const char *rvabefore PARAMS ((int));
static const char *asm_prefix PARAMS ((int));
static void append_import PARAMS ((const char *, const char *, int));
static void run PARAMS ((const char *, char *));
+static void scan_drectve_symbols PARAMS ((bfd *));
+static void scan_filtered_symbols PARAMS ((bfd *, PTR, long, unsigned int));
+static void add_excludes PARAMS ((const char *));
+static boolean match_exclude PARAMS ((const char *));
+static void set_default_excludes PARAMS ((void));
+static long filter_symbols PARAMS ((bfd *, PTR, long, unsigned int));
+static void scan_all_symbols PARAMS ((bfd *));
static void scan_open_obj_file PARAMS ((bfd *));
static void scan_obj_file PARAMS ((const char *));
static void dump_def_info PARAMS ((FILE *));
static void generate_idata_ofile PARAMS ((FILE *));
static void gen_exp_file PARAMS ((void));
static const char *xlate PARAMS ((const char *));
+#if 0
static void dump_iat PARAMS ((FILE *, export_type *));
+#endif
static char *make_label PARAMS ((const char *, const char *));
static bfd *make_one_lib_file PARAMS ((export_type *, int));
static bfd *make_head PARAMS ((void));
static void fill_ordinals PARAMS ((export_type **));
static int alphafunc PARAMS ((const void *, const void *));
static void mangle_defs PARAMS ((void));
-static void usage PARAMS ((int));
-static void tell PARAMS ((const char *, va_list));
+static void usage PARAMS ((FILE *, int));
+static void display PARAMS ((const char *, va_list));
static void inform PARAMS ((const char *, ...));
static void warn PARAMS ((const char *, ...));
static void
-tell (message, args)
+display (message, args)
const char * message;
va_list args;
{
va_start (args);
#endif
- tell (message, args);
+ display (message, args);
va_end (args);
}
va_start (args);
#endif
- tell (message, args);
+ display (message, args);
va_end (args);
}
abort ();
}
+/* Look for a list of symbols to export in the .drectve section of
+ ABFD. Pass each one to def_exports. */
+
static void
-scan_open_obj_file (abfd)
+scan_drectve_symbols (abfd)
bfd *abfd;
{
asection * s;
p++;
}
free (buf);
+}
+
+/* Look through the symbols in MINISYMS, and add each one to list of
+ symbols to export. */
+
+static void
+scan_filtered_symbols (abfd, minisyms, symcount, size)
+ bfd *abfd;
+ PTR minisyms;
+ long symcount;
+ unsigned int size;
+{
+ asymbol *store;
+ bfd_byte *from, *fromend;
+
+ store = bfd_make_empty_symbol (abfd);
+ if (store == NULL)
+ bfd_fatal (bfd_get_filename (abfd));
+
+ from = (bfd_byte *) minisyms;
+ fromend = from + symcount * size;
+ for (; from < fromend; from += size)
+ {
+ asymbol *sym;
+ const char *symbol_name;
+
+ sym = bfd_minisymbol_to_symbol (abfd, false, from, store);
+ if (sym == NULL)
+ bfd_fatal (bfd_get_filename (abfd));
+
+ symbol_name = bfd_asymbol_name (sym);
+ if (bfd_get_symbol_leading_char (abfd) == symbol_name[0])
+ ++symbol_name;
+
+ def_exports (xstrdup (symbol_name), 0, -1, 0, 0, 0);
+ }
+}
+
+/* Add a list of symbols to exclude. */
+static void
+add_excludes (new_excludes)
+ const char *new_excludes;
+{
+ char *local_copy;
+ char *exclude_string;
+
+ local_copy = xstrdup (new_excludes);
+
+ exclude_string = strtok (local_copy, ",:");
+ for (; exclude_string; exclude_string = strtok (NULL, ",:"))
+ {
+ struct string_list *new_exclude;
+
+ new_exclude = ((struct string_list *)
+ xmalloc (sizeof (struct string_list)));
+ new_exclude->string = (char *) xmalloc (strlen (exclude_string) + 2);
+ /* FIXME: Is it always right to add a leading underscore? */
+ sprintf (new_exclude->string, "_%s", exclude_string);
+ new_exclude->next = excludes;
+ excludes = new_exclude;
+
+ /* xgettext:c-format */
+ inform (_("Excluding symbol: %s\n"), exclude_string);
+ }
+
+ free (local_copy);
+}
+
+/* See if STRING is on the list of symbols to exclude. */
+
+static boolean
+match_exclude (string)
+ const char *string;
+{
+ struct string_list *excl_item;
+
+ for (excl_item = excludes; excl_item; excl_item = excl_item->next)
+ if (strcmp (string, excl_item->string) == 0)
+ return true;
+ return false;
+}
+
+/* Add the default list of symbols to exclude. */
+
+static void
+set_default_excludes (void)
+{
+ add_excludes (default_excludes);
+}
+
+/* Choose which symbols to export. */
+
+static long
+filter_symbols (abfd, minisyms, symcount, size)
+ bfd *abfd;
+ PTR minisyms;
+ long symcount;
+ unsigned int size;
+{
+ bfd_byte *from, *fromend, *to;
+ asymbol *store;
+
+ store = bfd_make_empty_symbol (abfd);
+ if (store == NULL)
+ bfd_fatal (bfd_get_filename (abfd));
+
+ from = (bfd_byte *) minisyms;
+ fromend = from + symcount * size;
+ to = (bfd_byte *) minisyms;
+
+ for (; from < fromend; from += size)
+ {
+ int keep = 0;
+ asymbol *sym;
+
+ sym = bfd_minisymbol_to_symbol (abfd, false, (const PTR) from, store);
+ if (sym == NULL)
+ bfd_fatal (bfd_get_filename (abfd));
+
+ /* Check for external and defined only symbols. */
+ keep = (((sym->flags & BSF_GLOBAL) != 0
+ || (sym->flags & BSF_WEAK) != 0
+ || bfd_is_com_section (sym->section))
+ && ! bfd_is_und_section (sym->section));
+
+ keep = keep && ! match_exclude (sym->name);
+
+ if (keep)
+ {
+ memcpy (to, from, size);
+ to += size;
+ }
+ }
+
+ return (to - (bfd_byte *) minisyms) / size;
+}
+
+/* Export all symbols in ABFD, except for ones we were told not to
+ export. */
+
+static void
+scan_all_symbols (abfd)
+ bfd *abfd;
+{
+ long symcount;
+ PTR minisyms;
+ unsigned int size;
+
+ if (! (bfd_get_file_flags (abfd) & HAS_SYMS))
+ {
+ /* xgettext:c-format */
+ warn (_("%s: no symbols\n"), bfd_get_filename (abfd));
+ return;
+ }
+
+ symcount = bfd_read_minisymbols (abfd, false, &minisyms, &size);
+ if (symcount < 0)
+ bfd_fatal (bfd_get_filename (abfd));
+
+ if (symcount == 0)
+ {
+ /* xgettext:c-format */
+ warn (_("%s: no symbols\n"), bfd_get_filename (abfd));
+ return;
+ }
+
+ /* Discard the symbols we don't want to export. It's OK to do this
+ in place; we'll free the storage anyway. */
+
+ symcount = filter_symbols (abfd, minisyms, symcount, size);
+ scan_filtered_symbols (abfd, minisyms, symcount, size);
+
+ free (minisyms);
+}
+
+/* Look at the object file to decide which symbols to export. */
+
+static void
+scan_open_obj_file (abfd)
+ bfd *abfd;
+{
+ if (export_all_symbols)
+ scan_all_symbols (abfd);
+ else
+ scan_drectve_symbols (abfd);
+
/* FIXME: we ought to read in and block out the base relocations */
- inform (_("%s: Done reading\n"));
+ /* xgettext:c-format */
+ inform (_("%s: Done reading %s\n"), bfd_get_filename (abfd));
}
static void
for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
{
char *quote = strchr (exp->name, '.') ? "\"" : "";
+ char *res = cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS);
+
fprintf (output_def, "\t%s%s%s @ %d%s%s ; %s\n",
quote,
exp->name,
exp->ordinal,
exp->noname ? " NONAME" : "",
exp->data ? " DATA" : "",
- cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS));
+ res ? res : "");
+ if (res)
+ free (res);
}
inform (_("Added exports to output file"));
/**********************************************************************/
+#if 0
+
static void
dump_iat (f, exp)
FILE *f;
}
}
+#endif
+
typedef struct
{
int id;
/**********************************************************************/
static void
-usage (status)
+usage (file, status)
+ FILE *file;
int status;
{
/* xgetext:c-format */
- fprintf (stderr, _("Usage %s <options> <object-files>\n"), program_name);
+ fprintf (file, _("Usage %s <options> <object-files>\n"), program_name);
/* xgetext:c-format */
- fprintf (stderr, _(" -m --machine <machine> Create {arm, i386, ppc, thumb} DLL. [default: %s]\n"), mname);
- fprintf (stderr, _(" -e --output-exp <outname> Generate an export file.\n"));
- fprintf (stderr, _(" -l --output-lib <outname> Generate an interface library.\n"));
- fprintf (stderr, _(" -a --add-indirect Add dll indirects to export file.\n"));
- fprintf (stderr, _(" -D --dllname <name> Name of input dll to put into interface lib.\n"));
- fprintf (stderr, _(" -d --input-def <deffile> Name of .def file to be read in.\n"));
- fprintf (stderr, _(" -z --output-def <deffile> Name of .def file to be created.\n"));
- fprintf (stderr, _(" -b --base-file <basefile> Read linker generated base file.\n"));
- fprintf (stderr, _(" -x --no-idata4 Don't generate idata$4 section.\n"));
- fprintf (stderr, _(" -c --no-idata5 Don't generate idata$5 section.\n"));
- fprintf (stderr, _(" -U --add-underscore Add underscores to symbols in interface library.\n"));
- fprintf (stderr, _(" -k --kill-at Kill @<n> from exported names.\n"));
- fprintf (stderr, _(" -S --as <name> Use <name> for assembler.\n"));
- fprintf (stderr, _(" -f --as-flags <flags> Pass <flags> to the assembler.\n"));
+ fprintf (file, _(" -m --machine <machine> Create {arm, i386, ppc, thumb} DLL. [default: %s]\n"), mname);
+ fprintf (file, _(" -e --output-exp <outname> Generate an export file.\n"));
+ fprintf (file, _(" -l --output-lib <outname> Generate an interface library.\n"));
+ fprintf (file, _(" -a --add-indirect Add dll indirects to export file.\n"));
+ fprintf (file, _(" -D --dllname <name> Name of input dll to put into interface lib.\n"));
+ fprintf (file, _(" -d --input-def <deffile> Name of .def file to be read in.\n"));
+ fprintf (file, _(" -z --output-def <deffile> Name of .def file to be created.\n"));
+ fprintf (file, _(" --export-all-symbols Export all symbols to .def\n"));
+ fprintf (file, _(" --no-export-all-symbols Only export listed symbols\n"));
+ fprintf (file, _(" --exclude-symbols <list> Don't export <list>\n"));
+ fprintf (file, _(" --no-default-excludes Clear default exclude symbols\n"));
+ fprintf (file, _(" -b --base-file <basefile> Read linker generated base file.\n"));
+ fprintf (file, _(" -x --no-idata4 Don't generate idata$4 section.\n"));
+ fprintf (file, _(" -c --no-idata5 Don't generate idata$5 section.\n"));
+ fprintf (file, _(" -U --add-underscore Add underscores to symbols in interface library.\n"));
+ fprintf (file, _(" -k --kill-at Kill @<n> from exported names.\n"));
+ fprintf (file, _(" -S --as <name> Use <name> for assembler.\n"));
+ fprintf (file, _(" -f --as-flags <flags> Pass <flags> to the assembler.\n"));
#ifdef DLLTOOL_ARM
- fprintf (stderr, _(" -i --interwork Support ARM/Thumb interworking.\n"));
+ fprintf (file, _(" -i --interwork Support ARM/Thumb interworking.\n"));
#endif
- fprintf (stderr, _(" -n --no-delete Keep temp files (repeat for extra preservation).\n"));
- fprintf (stderr, _(" -v --verbose Be verbose.\n"));
- fprintf (stderr, _(" -V --version Display the program version.\n"));
- fprintf (stderr, _(" -h --help Display this information.\n"));
+ fprintf (file, _(" -n --no-delete Keep temp files (repeat for extra preservation).\n"));
+ fprintf (file, _(" -v --verbose Be verbose.\n"));
+ fprintf (file, _(" -V --version Display the program version.\n"));
+ fprintf (file, _(" -h --help Display this information.\n"));
exit (status);
}
-#define OPTION_NO_IDATA4 'x'
-#define OPTION_NO_IDATA5 'c'
+#define OPTION_EXPORT_ALL_SYMS 150
+#define OPTION_NO_EXPORT_ALL_SYMS (OPTION_EXPORT_ALL_SYMS + 1)
+#define OPTION_EXCLUDE_SYMS (OPTION_NO_EXPORT_ALL_SYMS + 1)
+#define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1)
+#define OPTION_NO_IDATA4 'x'
+#define OPTION_NO_IDATA5 'c'
+
static const struct option long_options[] =
{
{"no-delete", no_argument, NULL, 'n'},
{"no-idata5", no_argument, NULL, OPTION_NO_IDATA5},
{"output-exp", required_argument, NULL, 'e'},
{"output-def", required_argument, NULL, 'z'},
+ {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS},
+ {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS},
+ {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS},
+ {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
{"output-lib", required_argument, NULL, 'l'},
{"def", required_argument, NULL, 'd'}, /* for compatiblity with older versions */
{"input-def", required_argument, NULL, 'd'},
case OPTION_NO_IDATA5:
no_idata5 = 1;
break;
+ case OPTION_EXPORT_ALL_SYMS:
+ export_all_symbols = true;
+ break;
+ case OPTION_NO_EXPORT_ALL_SYMS:
+ export_all_symbols = false;
+ break;
+ case OPTION_EXCLUDE_SYMS:
+ add_excludes (optarg);
+ break;
+ case OPTION_NO_DEFAULT_EXCLUDES:
+ do_default_excludes = false;
+ break;
case 'S':
as_name = optarg;
break;
exp_name = optarg;
break;
case 'h':
- case '?':
- usage (0);
+ usage (stdout, 0);
break;
case 'm':
mname = optarg;
break;
default:
- usage (1);
+ usage (stderr, 1);
+ break;
}
}
strcat (dll_name, ".dll");
}
+ /* Don't use the default exclude list if we're reading only the
+ symbols in the .drectve section. The default excludes are meant
+ to avoid exporting DLL entry point and Cygwin32 impure_ptr. */
+ if (! export_all_symbols)
+ do_default_excludes = false;
+
+ if (do_default_excludes)
+ set_default_excludes ();
+
if (def_file)
process_def_file (def_file);