summaryrefslogtreecommitdiff
path: root/ld/pe-dll.c
diff options
context:
space:
mode:
authorDave Korn <dave.korn@artimi.com>2009-01-03 18:04:16 +0000
committerDave Korn <dave.korn@artimi.com>2009-01-03 18:04:16 +0000
commita8b22e5a7bf872776422befd0e76150c7c9f8df4 (patch)
treec914f35d7f24a2de5b3558669d4dbcd48d710813 /ld/pe-dll.c
parenta6d3f51237b75f07958c16cd5892b6f447b29920 (diff)
downloadbinutils-redhat-a8b22e5a7bf872776422befd0e76150c7c9f8df4.tar.gz
* NEWS: Mention new feature --exclude-modules-for-implib.
* ld.texinfo: Document new --exclude-modules-for-implib option. * pe-dll.c (exclude_list_struct): Change type member from int to new enumeration exclude_type. (pe_dll_add_excludes): Accept exclude_type instead of int param. (auto_export): Replace magic constants by exclude_type values and handle new choice EXCLUDEFORIMPLIB. (pe_dll_generate_implib): Accept a pointer to the link_info and iterate all input BFDs looking for EXCLUDEFORIMPLIB modules; re-open fresh BFDs for any found and link into import lib archive chain. * pe-dll.h (exclude_type): Add new enumerated type to replace magic constants previously used for exclude_list_struct type member. (pe_dll_add_excludes, pe_dll_generate_implib): Update prototypes. * pep-dll.h (exclude_type, pe_dll_add_excludes, pe_dll_generate_implib): Likewise to all the above. * emultempl/pe.em (OPTION_EXCLUDE_MODULES_FOR_IMPLIB): Define new getopts long option code for new --exclude-modules-for-implib option. (gld${EMULATION_NAME}_add_options): Add new entry to xtra_long[]. (gld_${EMULATION_NAME}_list_options): List usage for it. (gld${EMULATION_NAME}_handle_option): Use exclude_type enumerated values when calling pe_dll_add_excludes, and handle EXCLUDEFORIMPLIB. (gld_${EMULATION_NAME}_finish): Pass pointer to link_info when calling pe_dll_generate_implib. * emultempl/pep.em (options): Define new enumerated value for getopts long option code for new --exclude-modules-for-implib option. (gld${EMULATION_NAME}_add_options, gld_${EMULATION_NAME}_list_options, gld${EMULATION_NAME}_handle_option, gld_${EMULATION_NAME}_finish): Again, likewise to all the above.
Diffstat (limited to 'ld/pe-dll.c')
-rw-r--r--ld/pe-dll.c69
1 files changed, 65 insertions, 4 deletions
diff --git a/ld/pe-dll.c b/ld/pe-dll.c
index de43e34329..d76d0cfc34 100644
--- a/ld/pe-dll.c
+++ b/ld/pe-dll.c
@@ -463,14 +463,14 @@ typedef struct exclude_list_struct
{
char *string;
struct exclude_list_struct *next;
- int type;
+ exclude_type type;
}
exclude_list_struct;
static struct exclude_list_struct *excludes = 0;
void
-pe_dll_add_excludes (const char *new_excludes, const int type)
+pe_dll_add_excludes (const char *new_excludes, const exclude_type type)
{
char *local_copy;
char *exclude_string;
@@ -593,13 +593,18 @@ auto_export (bfd *abfd, def_file *d, const char *n)
for (ex = excludes; ex; ex = ex->next)
{
- if (ex->type == 1) /* exclude-libs */
+ if (ex->type == EXCLUDELIBS)
{
if (libname
&& ((strcmp (libname, ex->string) == 0)
|| (strcasecmp ("ALL", ex->string) == 0)))
return 0;
}
+ else if (ex->type == EXCLUDEFORIMPLIB)
+ {
+ if (strcmp (abfd->filename, ex->string) == 0)
+ return 0;
+ }
else if (strcmp (n, ex->string) == 0)
return 0;
}
@@ -2480,12 +2485,13 @@ pe_create_import_fixup (arelent *rel, asection *s, bfd_vma addend)
void
-pe_dll_generate_implib (def_file *def, const char *impfilename)
+pe_dll_generate_implib (def_file *def, const char *impfilename, struct bfd_link_info *info)
{
int i;
bfd *ar_head;
bfd *ar_tail;
bfd *outarch;
+ bfd *ibfd;
bfd *head = 0;
dll_filename = (def->name) ? def->name : dll_name;
@@ -2514,6 +2520,61 @@ pe_dll_generate_implib (def_file *def, const char *impfilename)
/* Work out a reasonable size of things to put onto one line. */
ar_head = make_head (outarch);
+ /* Iterate the input BFDs, looking for exclude-modules-for-implib. */
+ for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link_next)
+ {
+ /* Iterate the exclude list. */
+ struct exclude_list_struct *ex;
+ char found;
+ for (ex = excludes, found = 0; ex && !found; ex = ex->next)
+ {
+ if (ex->type != EXCLUDEFORIMPLIB)
+ continue;
+ found = (strcmp (ex->string, ibfd->filename) == 0);
+ }
+ /* If it matched, we must open a fresh BFD for it (the original
+ input BFD is still needed for the DLL's final link) and add
+ it into the archive member chain. */
+ if (found)
+ {
+ bfd *newbfd = bfd_openr (ibfd->my_archive
+ ? ibfd->my_archive->filename : ibfd->filename, NULL);
+ if (!newbfd)
+ {
+ einfo (_("%Xbfd_openr %s: %E\n"), ibfd->filename);
+ return;
+ }
+ if (ibfd->my_archive)
+ {
+ /* Must now iterate through archive until we find the
+ required member. A minor shame that we'll open the
+ archive once per member that we require from it, and
+ leak those archive bfds rather than reuse them. */
+ bfd *arbfd = newbfd;
+ if (!bfd_check_format_matches (arbfd, bfd_archive, NULL))
+ {
+ einfo (_("%X%s(%s): can't find member in non-archive file"),
+ ibfd->my_archive->filename, ibfd->filename);
+ return;
+ }
+ newbfd = NULL;
+ while ((newbfd = bfd_openr_next_archived_file (arbfd, newbfd)) != 0)
+ {
+ if (strcmp (newbfd->filename, ibfd->filename) == 0)
+ break;
+ }
+ if (!newbfd)
+ {
+ einfo (_("%X%s(%s): can't find member in archive"),
+ ibfd->my_archive->filename, ibfd->filename);
+ return;
+ }
+ }
+ newbfd->archive_next = head;
+ head = newbfd;
+ }
+ }
+
for (i = 0; i < def->num_exports; i++)
{
/* The import library doesn't know about the internal name. */