Added --identify option to dlltool.

This commit is contained in:
Charles Wilson 2008-11-15 18:15:18 +00:00
parent da8bd9a3c5
commit d4732f7c88
3 changed files with 239 additions and 6 deletions

View File

@ -1,3 +1,16 @@
2008-11-15 Charles Wilson <cygwin@cwilson.fastmail.fm>
Added --identify option to dlltool.
* binutils/dlltool.c: Add new global variables
identify_imp_name and identify_dll_name.
(identify_dll_for_implib, identify_search_archive,
identify_search_member, identify_process_section_p,
identify_search_section): New functions.
(usage): Added --identify.
(long_options): Added --identify.
(main): Handle --identify option.
* binutils/doc/binutils.texi: Document --identify.
2008-11-14 Tristan Gingold <gingold@adacore.com>
Remove outdated mach-o specific tests.

View File

@ -352,6 +352,8 @@ static int no_idata4;
static int no_idata5;
static char *exp_name;
static char *imp_name;
static char *identify_imp_name;
static char *identify_dll_name;
static char *head_label;
static char *imp_name_lab;
static char *dll_name;
@ -724,6 +726,11 @@ static bfd *make_one_lib_file (export_type *, int);
static bfd *make_head (void);
static bfd *make_tail (void);
static void gen_lib_file (void);
static void identify_dll_for_implib (void);
static void identify_search_archive (bfd*);
static void identify_search_member (bfd*, bfd*);
static bfd_boolean identify_process_section_p (asection *);
static void identify_search_section (bfd *, asection *, void *);
static int pfunc (const void *, const void *);
static int nfunc (const void *, const void *);
static void remove_null_names (export_type **);
@ -2918,6 +2925,193 @@ gen_lib_file (void)
inform (_("Created lib file"));
}
/* identify_dll_for_implib
This is the main implementation for the --identify option.
Given the name of an import library in identify_imp_name,
search all archive members for an .idata$7 section
(.idata$6 on PPC). This section will consist of a single
char* constant, indicating the name of the DLL represented
by the import library.
It is possible to construct an import library that has
two members with a non-empty .idata$7 section, but these
are not often seen in normal operation. In this case,
an error is flagged.
*/
static void
identify_dll_for_implib (void)
{
bfd* abfd = NULL;
bfd_init ();
abfd = bfd_openr (identify_imp_name, 0);
if (abfd == NULL)
{
bfd_fatal (identify_imp_name);
}
if (!bfd_check_format (abfd, bfd_archive))
{
if (!bfd_close (abfd))
bfd_fatal (identify_imp_name);
fatal ("%s is not a library", identify_imp_name);
}
identify_search_archive (abfd);
if (!bfd_close (abfd))
bfd_fatal (identify_imp_name);
if (identify_dll_name && *identify_dll_name)
{
printf ("%s\n",identify_dll_name);
free (identify_dll_name);
identify_dll_name = NULL;
}
else
{
fatal ("Unable to determine dll name for %s (not an import library?)", identify_imp_name);
}
}
/* identify_search_archive
Loop over all members of the archive, inspecting
each for the presence of an .idata$7 (.idata$6 on PPC)
section with non-empty contents.
*/
static void
identify_search_archive (bfd* abfd)
{
bfd *arfile = NULL;
bfd *last_arfile = NULL;
char **matching;
while (1)
{
arfile = bfd_openr_next_archived_file (abfd, arfile);
if (arfile == NULL)
{
if (bfd_get_error () != bfd_error_no_more_archived_files)
bfd_fatal (bfd_get_filename (abfd));
break;
}
if (bfd_check_format_matches (arfile, bfd_object, &matching))
{
identify_search_member (arfile, abfd);
}
else
{
bfd_nonfatal (bfd_get_filename (arfile));
free (matching);
}
if (last_arfile != NULL)
{
bfd_close (last_arfile);
}
last_arfile = arfile;
}
if (last_arfile != NULL)
{
bfd_close (last_arfile);
}
}
/* identify_search_member
Search all sections of an archive member for the
one with section name of .idata$7 (.idata$6 on PPC)
and non-empty contents.
*/
static void
identify_search_member (bfd* abfd, bfd* archive_bfd ATTRIBUTE_UNUSED)
{
bfd_map_over_sections (abfd, identify_search_section, NULL);
}
/* identify_process_section_p
This predicate returns true if section->name
is .idata$7 (.idata$6 on PPC).
*/
static bfd_boolean
identify_process_section_p (asection * section)
{
static const char * SECTION_NAME =
#ifdef DLLTOOL_PPC
/* dllname is stored in idata$6 on PPC */
".idata$6";
#else
".idata$7";
#endif
if (strcmp (SECTION_NAME, section->name) == 0)
return TRUE;
return FALSE;
}
/* identify_search_section
If *section has contents and its name is .idata$7
(.data$6 on PPC) then store the contents in
identify_dll_name as an xmalloc'ed array.
However, if identify_dll_name already has
a value, flag an error. We don't know how to handle
import libraries that directly reference more than
one DLL. (This is different than forwarded symbols.
Such import libraries are not seen in normal operation,
and must be specifically constructed.)
*/
static void
identify_search_section (bfd *abfd, asection *section, void *dummy ATTRIBUTE_UNUSED)
{
bfd_byte *data = 0;
bfd_size_type datasize;
if ((section->flags & SEC_HAS_CONTENTS) == 0)
return;
if (! identify_process_section_p (section))
return;
if ((datasize = bfd_section_size (abfd, section)) == 0)
return;
data = (bfd_byte*) xmalloc (datasize + 1);
data[0] = '\0';
bfd_get_section_contents (abfd, section, data, 0, datasize);
data[datasize] = '\0';
if (data[0] != '\0')
{
if (identify_dll_name != NULL)
{
if (*identify_dll_name != '\0')
{
/* The import library specifies two different DLLs.
Treat this as an error. */
fatal ("Import library `%s' specifies two or more dlls: `%s' and `%s'",
identify_imp_name, identify_dll_name, data);
}
else
{
/* For some reason memory was allocated, but the
contents were empty. Free the memory and continue. */
free (identify_dll_name);
}
}
identify_dll_name = (char*) xstrdup (data);
}
free (data);
}
/* Run through the information gathered from the .o files and the
.def file and work out the best stuff. */
@ -3171,6 +3365,7 @@ usage (FILE *file, int status)
fprintf (file, _(" -C --compat-implib Create backward compatible import library.\n"));
fprintf (file, _(" -n --no-delete Keep temp files (repeat for extra preservation).\n"));
fprintf (file, _(" -t --temp-prefix <prefix> Use <prefix> to construct temp file names.\n"));
fprintf (file, _(" -I --identify <implib> Report the name of the DLL associated with <implib>.\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"));
@ -3211,6 +3406,7 @@ static const struct option long_options[] =
{"kill-at", no_argument, NULL, 'k'},
{"add-stdcall-alias", no_argument, NULL, 'A'},
{"ext-prefix-alias", required_argument, NULL, 'p'},
{"identify", required_argument, NULL, 'I'},
{"verbose", no_argument, NULL, 'v'},
{"version", no_argument, NULL, 'V'},
{"help", no_argument, NULL, 'h'},
@ -3249,9 +3445,9 @@ main (int ac, char **av)
while ((c = getopt_long (ac, av,
#ifdef DLLTOOL_MCORE_ELF
"m:e:l:aD:d:z:b:xp:cCuUkAS:f:nvVHhM:L:F:",
"m:e:l:aD:d:z:b:xp:cCuUkAS:f:nI:vVHhM:L:F:",
#else
"m:e:l:aD:d:z:b:xp:cCuUkAS:f:nvVHh",
"m:e:l:aD:d:z:b:xp:cCuUkAS:f:nI:vVHh",
#endif
long_options, 0))
!= EOF)
@ -3317,6 +3513,9 @@ main (int ac, char **av)
case 'm':
mname = optarg;
break;
case 'I':
identify_imp_name = optarg;
break;
case 'v':
verbose = 1;
break;
@ -3440,6 +3639,11 @@ main (int ac, char **av)
if (output_def)
gen_def_file ();
if (identify_imp_name)
{
identify_dll_for_implib ();
}
#ifdef DLLTOOL_MCORE_ELF
if (mcore_elf_out_file)
mcore_elf_gen_out_file ();

View File

@ -3371,7 +3371,8 @@ dlltool [@option{-d}|@option{--input-def} @var{def-file-name}]
[@option{-U}|@option{--add-underscore}] [@option{--add-stdcall-underscore}]
[@option{-k}|@option{--kill-at}] [@option{-A}|@option{--add-stdcall-alias}]
[@option{-p}|@option{--ext-prefix-alias} @var{prefix}]
[@option{-x}|@option{--no-idata4}] [@option{-c}|@option{--no-idata5}] [@option{-i}|@option{--interwork}]
[@option{-x}|@option{--no-idata4}] [@option{-c}|@option{--no-idata5}]
[@option{-I}|@option{--identify} @var{library-file-name}] [@option{-i}|@option{--interwork}]
[@option{-n}|@option{--nodelete}] [@option{-t}|@option{--temp-prefix} @var{prefix}]
[@option{-v}|@option{--verbose}]
[@option{-h}|@option{--help}] [@option{-V}|@option{--version}]
@ -3421,9 +3422,9 @@ binary file and it can be created by giving the @option{-e} option to
@command{dlltool} when it is creating or reading in a @file{.def} file.
The third file needed for DLL creation is the library file that programs
will link with in order to access the functions in the DLL. This file
can be created by giving the @option{-l} option to dlltool when it
is creating or reading in a @file{.def} file.
will link with in order to access the functions in the DLL (an `import
library'). This file can be created by giving the @option{-l} option to
dlltool when it is creating or reading in a @file{.def} file.
@command{dlltool} builds the library file by hand, but it builds the
exports file by creating temporary files containing assembler statements
@ -3446,6 +3447,11 @@ that uses that DLL:
gcc program.o dll.lib -o program
@end smallexample
@command{dlltool} may also be used to query an existing import library
to determine the name of the DLL to which it is associated. See the
description of the @option{-I} or @option{--identify} option.
@c man end
@c man begin OPTIONS dlltool
@ -3585,6 +3591,16 @@ Specifies that when @command{dlltool} is creating the exports and library
files it should omit the @code{.idata5} section. This is for compatibility
with certain operating systems.
@item -I @var{filename}
@itemx --identify @var{filename}
Specifies that @command{dlltool} should inspect the import library
indicated by @var{filename} and report, on @code{stdout}, the name of
the associated DLL. This can be performed in addition to any other
operations indicated by the other options and arguments. @command{dlltool}
@option{--identify} fails if the import library does not exist, is not
actually an import library, or (rarely) if the import library somehow
specifies more than one associated DLL.
@item -i
@itemx --interwork
Specifies that @command{dlltool} should mark the objects in the library