/* Routines to help build PEI-format DLLs (Win32 etc)
- Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
- 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+ Copyright (C) 1998-2014 Free Software Foundation, Inc.
Written by DJ Delorie <dj@cygnus.com>
This file is part of the GNU Binutils.
/* We should export symbols which are either global or not
anything at all. (.bss data is the latter)
We should not export undefined symbols. */
- bfd_boolean would_export = symbols[j]->section != &bfd_und_section
- && ((symbols[j]->flags & BSF_GLOBAL)
- || (symbols[j]->flags == 0));
+ bfd_boolean would_export
+ = (symbols[j]->section != bfd_und_section_ptr
+ && ((symbols[j]->flags & BSF_GLOBAL)
+ || (symbols[j]->flags == 0)));
if (link_info.version_info && would_export)
would_export
= !bfd_hide_sym_by_version (link_info.version_info,
{
for (i = 0; i < NE; i++)
{
- if (strchr (pe_def_file->exports[i].name, '@'))
+ /* Check for fastcall/stdcall-decoration, but ignore
+ C++ mangled names. */
+ if (pe_def_file->exports[i].name[0] != '?'
+ && strchr (pe_def_file->exports[i].name, '@'))
{
/* This will preserve internal_name, which may have been
pointing to the same memory as name, or might not
have. */
int lead_at = (*pe_def_file->exports[i].name == '@');
char *tmp = xstrdup (pe_def_file->exports[i].name + lead_at);
- char *tmp_at = strchr (tmp, '@');
+ char *tmp_at = strrchr (tmp, '@');
if (tmp_at)
*tmp_at = 0;
unsigned char *enameptrs;
unsigned char *eordinals;
char *enamestr;
- time_t now;
-
- time (&now);
edata_d = xmalloc (edata_sz);
+ edata_s->output_section->vma - image_base)
memset (edata_d, 0, edata_sz);
- bfd_put_32 (abfd, now, edata_d + 4);
+
+ if (pe_data (abfd)->insert_timestamp)
+ H_PUT_32 (abfd, time (0), edata_d + 4);
+
if (pe_def_file->version_major != -1)
{
bfd_put_16 (abfd, pe_def_file->version_major, edata_d + 8);
/* I don't know why there would be a reloc for these, but I've
seen it happen - DJ */
- if (s->output_section == &bfd_abs_section)
+ if (s->output_section == bfd_abs_section_ptr)
continue;
if (s->output_section->vma == 0)
no reason we'd want a reference to any absolute
address to get relocated during rebasing). */
if (!h2 || h2->root.type == bfd_link_hash_undefined
- || h2->root.u.def.section == &bfd_abs_section)
+ || h2->root.u.def.section == bfd_abs_section_ptr)
continue;
}
else if (!blhe || blhe->type != bfd_link_hash_defined)
static const char *dll_filename;
static char *dll_symname;
-#define UNDSEC (asection *) &bfd_und_section
+#define UNDSEC bfd_und_section_ptr
static asection *
quick_section (bfd *abfd, const char *name, int flags, int align)
BSF_NO_FLAGS, 0);
bfd_set_section_size (abfd, extern_rt_rel, PE_IDATA5_SIZE);
- extern_rt_rel_d = xmalloc (PE_IDATA5_SIZE);
+ extern_rt_rel_d = xcalloc (1, PE_IDATA5_SIZE);
extern_rt_rel->contents = extern_rt_rel_d;
quick_reloc (abfd, 0, BFD_RELOC_RVA, 1);
return;
}
- /* xgettext:c-format */
- info_msg (_("Creating library file: %s\n"), impfilename);
+ if (verbose)
+ /* xgettext:c-format */
+ info_msg (_("Creating library file: %s\n"), impfilename);
bfd_set_format (outarch, bfd_archive);
outarch->has_armap = 1;
}
}
-static struct bfd_link_hash_entry *found_sym;
+static int undef_count = 0;
+
+struct key_value
+{
+ char *key;
+ const char *oname;
+};
+
+static struct key_value *udef_table;
+
+static int undef_sort_cmp (const void *l1, const void *r1)
+{
+ const struct key_value *l = l1;
+ const struct key_value *r = r1;
+
+ return strcmp (l->key, r->key);
+}
+
+static struct bfd_link_hash_entry *
+pe_find_cdecl_alias_match (struct bfd_link_info *linfo, char *name)
+{
+ struct bfd_link_hash_entry *h = NULL;
+ struct key_value *kv;
+ struct key_value key;
+ char *at, *lname = (char *) alloca (strlen (name) + 3);
+
+ strcpy (lname, name);
+
+ at = strchr (lname + (lname[0] == '@'), '@');
+ if (at)
+ at[1] = 0;
+
+ key.key = lname;
+ kv = bsearch (&key, udef_table, undef_count, sizeof (struct key_value),
+ undef_sort_cmp);
+
+ if (kv)
+ {
+ h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE);
+ if (h->type == bfd_link_hash_undefined)
+ return h;
+ }
+ if (lname[0] == '?')
+ return NULL;
+ if (at || lname[0] == '@')
+ {
+ if (lname[0] == '@')
+ {
+ if (pe_details->underscored)
+ lname[0] = '_';
+ else
+ strcpy (lname, lname + 1);
+ key.key = lname;
+ kv = bsearch (&key, udef_table, undef_count,
+ sizeof (struct key_value), undef_sort_cmp);
+ if (kv)
+ {
+ h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE);
+ if (h->type == bfd_link_hash_undefined)
+ return h;
+ }
+ }
+ if (at)
+ *strchr (lname, '@') = 0;
+ key.key = lname;
+ kv = bsearch (&key, udef_table, undef_count,
+ sizeof (struct key_value), undef_sort_cmp);
+ if (kv)
+ {
+ h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE);
+ if (h->type == bfd_link_hash_undefined)
+ return h;
+ }
+ return NULL;
+ }
+
+ strcat (lname, "@");
+ key.key = lname;
+ kv = bsearch (&key, udef_table, undef_count,
+ sizeof (struct key_value), undef_sort_cmp);
+
+ if (kv)
+ {
+ h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE);
+ if (h->type == bfd_link_hash_undefined)
+ return h;
+ }
+
+ if (lname[0] == '_' && pe_details->underscored)
+ lname[0] = '@';
+ else
+ {
+ memmove (lname + 1, lname, strlen (lname) + 1);
+ lname[0] = '@';
+ }
+ key.key = lname;
+
+ kv = bsearch (&key, udef_table, undef_count,
+ sizeof (struct key_value), undef_sort_cmp);
+
+ if (kv)
+ {
+ h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE);
+ if (h->type == bfd_link_hash_undefined)
+ return h;
+ }
+
+ return NULL;
+}
static bfd_boolean
-pe_undef_alias_cdecl_match (struct bfd_link_hash_entry *h, void *inf)
+pe_undef_count (struct bfd_link_hash_entry *h ATTRIBUTE_UNUSED,
+ void *inf ATTRIBUTE_UNUSED)
{
- int sl;
- char *string = inf;
- const char *hs = h->root.string;
-
- sl = strlen (string);
- if (h->type == bfd_link_hash_undefined
- && ((*hs == '@' && (!pe_details->underscored || *string == '_')
- && strncmp (hs + 1, string + (pe_details->underscored != 0),
- sl - (pe_details->underscored != 0)) == 0)
- || strncmp (hs, string, sl) == 0)
- && h->root.string[sl] == '@')
- {
- found_sym = h;
- return FALSE;
+ if (h->type == bfd_link_hash_undefined)
+ undef_count++;
+ return TRUE;
+}
+
+static bfd_boolean
+pe_undef_fill (struct bfd_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
+{
+ if (h->type == bfd_link_hash_undefined)
+ {
+ char *at;
+
+ udef_table[undef_count].key = xstrdup (h->root.string);
+ at = strchr (udef_table[undef_count].key
+ + (udef_table[undef_count].key[0] == '@'), '@');
+ if (at)
+ at[1] = 0;
+ udef_table[undef_count].oname = h->root.string;
+ undef_count++;
}
return TRUE;
}
-static struct bfd_link_hash_entry *
-pe_find_cdecl_alias_match (char *name)
+static void
+pe_create_undef_table (void)
{
- found_sym = 0;
- bfd_link_hash_traverse (link_info.hash, pe_undef_alias_cdecl_match,
- (char *) name);
- return found_sym;
+ undef_count = 0;
+
+ /* count undefined symbols */
+
+ bfd_link_hash_traverse (link_info.hash, pe_undef_count, "");
+
+ /* create and fill the corresponding table */
+ udef_table = xmalloc (undef_count * sizeof (struct key_value));
+
+ undef_count = 0;
+ bfd_link_hash_traverse (link_info.hash, pe_undef_fill, "");
+
+ /* sort items */
+ qsort (udef_table, undef_count, sizeof (struct key_value), undef_sort_cmp);
}
static void
imp = pe_def_file->imports;
+ pe_create_undef_table ();
+
for (module = pe_def_file->modules; module; module = module->next)
{
int do_this_dll = 0;
char *name = xmalloc (len + 2 + 6);
bfd_boolean include_jmp_stub = FALSE;
bfd_boolean is_cdecl = FALSE;
+ bfd_boolean is_undef = FALSE;
+
if (!lead_at && strchr (imp[i].internal_name, '@') == NULL)
is_cdecl = TRUE;
blhe = bfd_link_hash_lookup (linfo->hash, name,
FALSE, FALSE, FALSE);
+ if (blhe)
+ is_undef = (blhe->type == bfd_link_hash_undefined);
}
else
- include_jmp_stub = TRUE;
+ {
+ include_jmp_stub = TRUE;
+ is_undef = (blhe->type == bfd_link_hash_undefined);
+ }
- if (is_cdecl && !blhe)
+ if (is_cdecl && (!blhe || (blhe && blhe->type != bfd_link_hash_undefined)))
{
sprintf (name, "%s%s",U (""), imp[i].internal_name);
- blhe = pe_find_cdecl_alias_match (name);
+ blhe = pe_find_cdecl_alias_match (linfo, name);
include_jmp_stub = TRUE;
+ if (blhe)
+ is_undef = (blhe->type == bfd_link_hash_undefined);
}
free (name);
- if (blhe && blhe->type == bfd_link_hash_undefined)
+ if (is_undef)
{
bfd *one;
/* We do. */
free (dll_symname);
}
+
+ while (undef_count)
+ {
+ --undef_count;
+ free (udef_table[undef_count].key);
+ }
+ free (udef_table);
}
/* We were handed a *.DLL file. Parse it and turn it into a set of