/* Routines to help build PEI-format DLLs (Win32 etc)
Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
- 2008, 2009 Free Software Foundation, Inc.
+ 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
Written by DJ Delorie <dj@cygnus.com>
This file is part of the GNU Binutils.
#include "bfd.h"
#include "bfdlink.h"
#include "libiberty.h"
+#include "filenames.h"
#include "safe-ctype.h"
#include <time.h>
def_file * pe_def_file = 0;
int pe_dll_export_everything = 0;
+int pe_dll_exclude_all_symbols = 0;
int pe_dll_do_default_excludes = 1;
int pe_dll_kill_ats = 0;
int pe_dll_stdcall_aliases = 0;
int pe_dll_extra_pe_debug = 0;
int pe_use_nul_prefixed_import_tables = 0;
int pe_use_coff_long_section_names = -1;
+int pe_leading_underscore = -1;
/* Static variables and types. */
int pe_arch;
int bfd_arch;
bfd_boolean underscored;
- const autofilter_entry_type* autofilter_symbollist;
+ const autofilter_entry_type* autofilter_symbollist;
}
pe_details_type;
{ STRING_COMMA_LEN ("_cygwin_crt0_common@8") },
{ STRING_COMMA_LEN ("_cygwin_noncygwin_dll_entry@12") },
{ STRING_COMMA_LEN ("cygwin_attach_dll") },
-#endif
+#endif
{ STRING_COMMA_LEN ("cygwin_premain0") },
{ STRING_COMMA_LEN ("cygwin_premain1") },
{ STRING_COMMA_LEN ("cygwin_premain2") },
#define PE_ARCH_arm_epoc 5
#define PE_ARCH_arm_wince 6
-static const pe_details_type pe_detail_list[] =
+/* Don't make it constant as underscore mode gets possibly overriden
+ by target or -(no-)leading-underscore option. */
+static pe_details_type pe_detail_list[] =
{
{
#ifdef pe_use_x86_64
#endif
PE_ARCH_i386,
bfd_arch_i386,
+#ifdef pe_use_x86_64
+ FALSE,
+#else
TRUE,
+#endif
autofilter_symbollist_i386
},
{
returning zero if so or -1 if not. */
static int libnamencmp (const char *libname, const autofilter_entry_type *afptr)
{
- if (strncmp (libname, afptr->name, afptr->len))
+ if (filename_ncmp (libname, afptr->name, afptr->len))
return -1;
libname += afptr->len;
{ STRING_COMMA_LEN ("__rtti_") },
{ STRING_COMMA_LEN ("__builtin_") },
/* Don't re-export auto-imported symbols. */
- { STRING_COMMA_LEN ("_nm_") },
+ { STRING_COMMA_LEN ("__nm_") },
/* Don't export symbols specifying internal DLL layout. */
{ STRING_COMMA_LEN ("_head_") },
{ STRING_COMMA_LEN ("_IMPORT_DESCRIPTOR_") },
if (strcmp (pe_detail_list[i].target_name, target) == 0
|| strcmp (pe_detail_list[i].object_target, target) == 0)
{
+ int u = pe_leading_underscore; /* Underscoring mode. -1 for use default. */
+ if (u == -1)
+ bfd_get_target_info (target, NULL, NULL, &u, NULL);
+ if (u == -1)
+ abort ();
+ pe_detail_list[i].underscored = (u != 0 ? TRUE : FALSE);
pe_details = pe_detail_list + i;
+ pe_leading_underscore = (u != 0 ? 1 : 0);
return;
}
einfo (_("%XUnsupported PEI architecture: %s\n"), target);
{
const def_file_export *a = va;
const def_file_export *b = vb;
-
- return strcmp (a->name, b->name);
+ char *an = a->name;
+ char *bn = b->name;
+ if (a->its_name)
+ an = a->its_name;
+ if (b->its_name)
+ bn = b->its_name;
+
+ return strcmp (an, bn);
}
/* Read and process the .DEF file. */
that begin with '__'; this was tried and
it is too restrictive. Instead we have
a target specific list to use: */
- afptr = pe_details->autofilter_symbollist;
+ afptr = pe_details->autofilter_symbollist;
while (afptr->name)
{
if (ex->type == EXCLUDELIBS)
{
if (libname
- && ((strcmp (libname, ex->string) == 0)
+ && ((filename_cmp (libname, ex->string) == 0)
|| (strcasecmp ("ALL", ex->string) == 0)))
return 0;
}
else if (ex->type == EXCLUDEFORIMPLIB)
{
- if (strcmp (abfd->filename, ex->string) == 0)
+ if (filename_cmp (abfd->filename, ex->string) == 0)
return 0;
}
else if (strcmp (n, ex->string) == 0)
}
static void
-process_def_file (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
+process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
{
int i, j;
struct bfd_link_hash_entry *blhe;
}
}
- /* If we are not building a DLL, when there are no exports
- we do not build an export table at all. */
- if (!pe_dll_export_everything && pe_def_file->num_exports == 0
- && info->executable)
+ /* Process aligned common symbol information from the
+ .drectve sections now; common symbol allocation is
+ done before final link, so it will be too late to
+ process them in process_embedded_commands() called
+ from _bfd_coff_link_input_bfd(). */
+ if (pe_def_file->aligncomms)
+ {
+ def_file_aligncomm *ac = pe_def_file->aligncomms;
+ while (ac)
+ {
+ struct coff_link_hash_entry *sym_hash;
+ sym_hash = coff_link_hash_lookup (coff_hash_table (info),
+ ac->symbol_name, FALSE, FALSE, FALSE);
+ if (sym_hash && sym_hash->root.type == bfd_link_hash_common
+ && sym_hash->root.u.c.p->alignment_power < (unsigned) ac->alignment)
+ {
+ sym_hash->root.u.c.p->alignment_power = (unsigned) ac->alignment;
+ }
+ ac = ac->next;
+ }
+ }
+
+ /* If we are building an executable and there is nothing
+ to export, we do not build an export table at all. */
+ if (info->executable && pe_def_file->num_exports == 0
+ && (!pe_dll_export_everything || pe_dll_exclude_all_symbols))
return;
/* Now, maybe export everything else the default way. */
- if (pe_dll_export_everything || pe_def_file->num_exports == 0)
+ if ((pe_dll_export_everything || pe_def_file->num_exports == 0)
+ && !pe_dll_exclude_all_symbols)
{
for (b = info->input_bfds; b; b = b->link_next)
{
/* We should export symbols which are either global or not
anything at all. (.bss data is the latter)
We should not export undefined symbols. */
- if (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
+ && ((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,
+ symbols[j]->name);
+ if (would_export)
{
const char *sn = symbols[j]->name;
if (auto_export (b, pe_def_file, sn))
{
+ int is_dup = 0;
def_file_export *p;
- p=def_file_add_export (pe_def_file, sn, 0, -1);
+ p = def_file_add_export (pe_def_file, sn, 0, -1,
+ NULL, &is_dup);
/* Fill data flag properly, from dlltool.c. */
- p->flag_data = !(symbols[j]->flags & BSF_FUNCTION);
+ if (!is_dup)
+ p->flag_data = !(symbols[j]->flags & BSF_FUNCTION);
}
}
}
#undef NE
#define NE pe_def_file->num_exports
+ /* Don't create an empty export table. */
+ if (NE == 0)
+ return;
+
/* Canonicalize the export list. */
if (pe_dll_kill_ats)
{
if (strchr (pe_def_file->exports[i].name, '@'))
{
+ int is_dup = 1;
int lead_at = (*pe_def_file->exports[i].name == '@');
char *tmp = xstrdup (pe_def_file->exports[i].name + lead_at);
if (auto_export (NULL, pe_def_file, tmp))
def_file_add_export (pe_def_file, tmp,
pe_def_file->exports[i].internal_name,
- -1);
- else
- free (tmp);
+ -1, NULL, &is_dup);
+ if (is_dup)
+ free (tmp);
}
}
}
for (i = 0; i < NE; i++)
{
char *name;
-
- /* Check for forward exports */
- if (strchr (pe_def_file->exports[i].internal_name, '.'))
- {
- count_exported++;
- if (!pe_def_file->exports[i].flag_noname)
- count_exported_byname++;
-
- pe_def_file->exports[i].flag_forward = 1;
-
- if (pe_def_file->exports[i].ordinal != -1)
- {
- if (max_ordinal < pe_def_file->exports[i].ordinal)
- max_ordinal = pe_def_file->exports[i].ordinal;
- if (min_ordinal > pe_def_file->exports[i].ordinal)
- min_ordinal = pe_def_file->exports[i].ordinal;
- count_with_ordinals++;
- }
-
- continue;
- }
-
name = xmalloc (strlen (pe_def_file->exports[i].internal_name) + 2);
if (pe_details->underscored
&& (*pe_def_file->exports[i].internal_name != '@'))
else
exported_symbol_sections[i] = blhe->u.c.p->section;
+ if (pe_def_file->exports[i].ordinal != -1)
+ {
+ if (max_ordinal < pe_def_file->exports[i].ordinal)
+ max_ordinal = pe_def_file->exports[i].ordinal;
+ if (min_ordinal > pe_def_file->exports[i].ordinal)
+ min_ordinal = pe_def_file->exports[i].ordinal;
+ count_with_ordinals++;
+ }
+ }
+ /* Check for forward exports. These are indicated in DEF files by an
+ export directive of the form NAME1 = MODULE-NAME.EXTERNAL-NAME
+ but we must take care not to be fooled when the user wants to export
+ a symbol that actually really has a dot in it, so we only check
+ for them here, after real defined symbols have already been matched. */
+ else if (strchr (pe_def_file->exports[i].internal_name, '.'))
+ {
+ count_exported++;
+ if (!pe_def_file->exports[i].flag_noname)
+ count_exported_byname++;
+
+ pe_def_file->exports[i].flag_forward = 1;
+
if (pe_def_file->exports[i].ordinal != -1)
{
if (max_ordinal < pe_def_file->exports[i].ordinal)
}
exported_symbols[ei] = i;
}
- name_table_size += strlen (pe_def_file->exports[i].name) + 1;
+ if (pe_def_file->exports[i].its_name)
+ name_table_size += strlen (pe_def_file->exports[i].its_name) + 1;
+ else
+ name_table_size += strlen (pe_def_file->exports[i].name) + 1;
}
/* Reserve space for the forward name. */
}
/* Fill the exported symbol offsets. The preliminary work has already
- been done in process_def_file(). */
+ been done in process_def_file_and_drectve(). */
static void
fill_exported_offsets (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
/* Note use of array pointer math here. */
edirectory = edata_d;
- eaddresses = edata_d + 40;
+ eaddresses = edirectory + 40;
enameptrs = eaddresses + 4 * export_table_size;
eordinals = enameptrs + 4 * count_exported_byname;
enamestr = (char *) eordinals + 2 * count_exported_byname;
if (!pe_def_file->exports[s].flag_noname)
{
char *ename = pe_def_file->exports[s].name;
+ if (pe_def_file->exports[s].its_name)
+ ename = pe_def_file->exports[s].its_name;
bfd_put_32 (abfd, ERVA (enamestr), enameptrs);
enameptrs += 4;
for (b = info->input_bfds; b; b = b->link_next)
{
asymbol **symbols;
- int nsyms;
if (!bfd_generic_link_read_symbols (b))
{
}
symbols = bfd_get_outsymbols (b);
- nsyms = bfd_get_symcount (b);
for (s = b->sections; s; s = s->next)
{
for (bi = 0, b = info->input_bfds; b; bi++, b = b->link_next)
{
arelent **relocs;
- int relsize, nrelocs, i;
+ int relsize, nrelocs;
for (s = b->sections; s; s = s->next)
{
bfd_vma sec_vma = s->output_section->vma + s->output_offset;
asymbol **symbols;
- int nsyms;
/* If it's not loaded, we don't need to relocate it this way. */
if (!(s->output_section->flags & SEC_LOAD))
}
symbols = bfd_get_outsymbols (b);
- nsyms = bfd_get_symcount (b);
relsize = bfd_get_reloc_upper_bound (b, s);
relocs = xmalloc (relsize);
nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols);
if (!relocs[i]->howto->pc_relative
&& relocs[i]->howto->type != pe_details->imagebase_reloc)
{
- bfd_vma sym_vma;
struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
- /* Don't create relocs for undefined weak symbols. */
+ /* Don't create relocs for undefined weak symbols. */
if (sym->flags == BSF_WEAK)
{
struct bfd_link_hash_entry *blhe
- = bfd_link_hash_lookup (info->hash, sym->name,
+ = bfd_wrapped_link_hash_lookup (abfd, info, sym->name,
FALSE, FALSE, FALSE);
- if (!blhe || blhe->type != bfd_link_hash_defined)
- continue;
+ if (blhe && blhe->type == bfd_link_hash_undefweak)
+ {
+ /* Check aux sym and see if it is defined or not. */
+ struct coff_link_hash_entry *h, *h2;
+ h = (struct coff_link_hash_entry *)blhe;
+ if (h->symbol_class != C_NT_WEAK || h->numaux != 1)
+ continue;
+ h2 = h->auxbfd->tdata.coff_obj_data->sym_hashes
+ [h->aux->x_sym.x_tagndx.l];
+ /* We don't want a base reloc if the aux sym is not
+ found, undefined, or if it is the constant ABS
+ zero default value. (We broaden that slightly by
+ not testing the value, just the section; there's
+ 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)
+ continue;
+ }
+ else if (!blhe || blhe->type != bfd_link_hash_defined)
+ continue;
}
- sym_vma = (relocs[i]->addend
- + sym->value
- + sym->section->vma
- + sym->section->output_offset
- + sym->section->output_section->vma);
reloc_data[total_relocs].vma = sec_vma + relocs[i]->address;
#define BITS_AND_SHIFT(bits, shift) (bits * 1000 | shift)
else
fprintf (out, "%d", im->ordinal);
+ if (im->its_name)
+ {
+ fprintf (out, " == ");
+ quoteput (im->its_name, out, 0);
+ }
+
fprintf (out, "\n");
}
}
bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
symptr = 0;
- symtab = xmalloc (11 * sizeof (asymbol *));
- tx = quick_section (abfd, ".text", SEC_CODE|SEC_HAS_CONTENTS, 2);
+ symtab = xmalloc (12 * sizeof (asymbol *));
+
+ tx = quick_section (abfd, ".text", SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY, 2);
id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2);
id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);
id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
/* Symbol to reference ord/name of imported
data symbol, used to implement auto-import. */
if (exp->flag_data)
- quick_symbol (abfd, U ("_nm_"), U (""), exp->internal_name, id6,
+ quick_symbol (abfd, "__nm_", U (""), exp->internal_name, id6,
BSF_GLOBAL,0);
}
if (pe_dll_compat_implib)
- quick_symbol (abfd, U ("__imp_"), exp->internal_name, "", id5,
+ quick_symbol (abfd, "___imp_", exp->internal_name, "", id5,
BSF_GLOBAL, 0);
if (include_jmp_stub)
#ifdef pe_use_x86_64
quick_reloc (abfd, 2, BFD_RELOC_32_PCREL, 2);
#else
+ /* Mark this object as SAFESEH compatible. */
+ quick_symbol (abfd, "", "@feat.00", "", bfd_abs_section_ptr,
+ BSF_LOCAL, 1);
quick_reloc (abfd, 2, BFD_RELOC_32, 2);
#endif
break;
else
{
/* { short, asciz } */
- len = 2 + strlen (exp->name) + 1;
+ if (exp->its_name)
+ len = 2 + strlen (exp->its_name) + 1;
+ else
+ len = 2 + strlen (exp->name) + 1;
if (len & 1)
len++;
bfd_set_section_size (abfd, id6, len);
memset (d6, 0, len);
d6[0] = exp->hint & 0xff;
d6[1] = exp->hint >> 8;
- strcpy ((char *) d6 + 2, exp->name);
+ if (exp->its_name)
+ strcpy ((char*) d6 + 2, exp->its_name);
+ else
+ strcpy ((char *) d6 + 2, exp->name);
}
bfd_set_symtab (abfd, symtab, symptr);
symptr = 0;
symtab = xmalloc (3 * sizeof (asymbol *));
id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);
- quick_symbol (abfd, U ("_imp_"), import, "", id5, BSF_GLOBAL, 0);
+ quick_symbol (abfd, "__imp_", import, "", id5, BSF_GLOBAL, 0);
/* We need space for the real thunk and for the null terminator. */
bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE * 2);
symptr = 0;
symtab = xmalloc (3 * sizeof (asymbol *));
id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
- quick_symbol (abfd, U ("_nm_thnk_"), import, "", id4, BSF_GLOBAL, 0);
- quick_symbol (abfd, U ("_nm_"), import, "", UNDSEC, BSF_GLOBAL, 0);
+ quick_symbol (abfd, "__nm_thnk_", import, "", id4, BSF_GLOBAL, 0);
+ quick_symbol (abfd, "__nm_", import, "", UNDSEC, BSF_GLOBAL, 0);
/* We need space for the real thunk and for the null terminator. */
bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE * 2);
static bfd *
make_import_fixup_entry (const char *name,
const char *fixup_name,
- const char *dll_symname,
+ const char *symname,
bfd *parent)
{
asection *id2;
symtab = xmalloc (6 * sizeof (asymbol *));
id2 = quick_section (abfd, ".idata$2", SEC_HAS_CONTENTS, 2);
- quick_symbol (abfd, U ("_nm_thnk_"), name, "", UNDSEC, BSF_GLOBAL, 0);
- quick_symbol (abfd, U (""), dll_symname, "_iname", UNDSEC, BSF_GLOBAL, 0);
- /* For relocator v2 we have to use the .idata$5 element and not
+ quick_symbol (abfd, "__nm_thnk_", name, "", UNDSEC, BSF_GLOBAL, 0);
+ quick_symbol (abfd, U (""), symname, "_iname", UNDSEC, BSF_GLOBAL, 0);
+ /* For relocator v2 we have to use the .idata$5 element and not
fixup_name. */
if (link_info.pei386_runtime_pseudo_reloc == 2)
- quick_symbol (abfd, U ("_imp_"), name, "", UNDSEC, BSF_GLOBAL, 0);
+ quick_symbol (abfd, "__imp_", name, "", UNDSEC, BSF_GLOBAL, 0);
else
quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0);
size += 12;
runtime_pseudp_reloc_v2_init = 1;
}
- quick_symbol (abfd, U ("_imp_"), name, "", UNDSEC, BSF_GLOBAL, 0);
+ quick_symbol (abfd, "__imp_", name, "", UNDSEC, BSF_GLOBAL, 0);
bfd_set_section_size (abfd, rt_rel, size);
rt_rel_d = xmalloc (size);
bfd *b;
int need_import_table = 1;
- sprintf (buf, U ("_imp_%s"), name);
+ sprintf (buf, "__imp_%s", name);
name_imp_sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
- sprintf (buf, U ("_nm_thnk_%s"), name);
+ sprintf (buf, "__nm_thnk_%s", name);
name_thunk_sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
if (need_import_table == 1
&& (!name_thunk_sym || name_thunk_sym->type != bfd_link_hash_defined))
{
- bfd *b = make_singleton_name_thunk (name, link_info.output_bfd);
+ b = make_singleton_name_thunk (name, link_info.output_bfd);
add_bfd_to_link (b, b->filename, &link_info);
/* If we ever use autoimport, we have to cast text section writable.
&& need_import_table == 1)
{
extern char * pe_data_import_dll;
- char * dll_symname = pe_data_import_dll ? pe_data_import_dll : "unknown";
+ char * symname = pe_data_import_dll ? pe_data_import_dll : "unknown";
- b = make_import_fixup_entry (name, fixup_name, dll_symname,
+ b = make_import_fixup_entry (name, fixup_name, symname,
link_info.output_bfd);
add_bfd_to_link (b, b->filename, &link_info);
}
{
if (ex->type != EXCLUDEFORIMPLIB)
continue;
- found = (strcmp (ex->string, ibfd->filename) == 0);
+ found = (filename_cmp (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
newbfd = NULL;
while ((newbfd = bfd_openr_next_archived_file (arbfd, newbfd)) != 0)
{
- if (strcmp (newbfd->filename, ibfd->filename) == 0)
+ if (filename_cmp (newbfd->filename, ibfd->filename) == 0)
break;
}
if (!newbfd)
}
}
+static struct bfd_link_hash_entry *found_sym;
+
+static bfd_boolean
+pe_undef_alias_cdecl_match (struct bfd_link_hash_entry *h, void *inf)
+{
+ 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;
+ }
+ return TRUE;
+}
+
+static struct bfd_link_hash_entry *
+pe_find_cdecl_alias_match (char *name)
+{
+ found_sym = 0;
+ bfd_link_hash_traverse (link_info.hash, pe_undef_alias_cdecl_match,
+ (char *) name);
+ return found_sym;
+}
+
static void
-add_bfd_to_link (bfd *abfd, const char *name, struct bfd_link_info *link_info)
+add_bfd_to_link (bfd *abfd, const char *name, struct bfd_link_info *linfo)
{
lang_input_statement_type *fake_file;
fake_file->the_bfd = abfd;
ldlang_add_file (fake_file);
- if (!bfd_link_add_symbols (abfd, link_info))
+ if (!bfd_link_add_symbols (abfd, linfo))
einfo ("%Xaddsym %s: %E\n", name);
}
void
-pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *link_info)
+pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *linfo)
{
def_file_module *module;
size_t len = strlen (pe_def_file->imports[i].internal_name);
char *name = xmalloc (len + 2 + 6);
bfd_boolean include_jmp_stub = FALSE;
+ bfd_boolean is_cdecl = FALSE;
+ if (!lead_at && strchr (pe_def_file->imports[i].internal_name, '@') == NULL)
+ is_cdecl = TRUE;
if (lead_at)
sprintf (name, "%s",
sprintf (name, "%s%s",U (""),
pe_def_file->imports[i].internal_name);
- blhe = bfd_link_hash_lookup (link_info->hash, name,
+ blhe = bfd_link_hash_lookup (linfo->hash, name,
FALSE, FALSE, FALSE);
/* Include the jump stub for <sym> only if the <sym>
sprintf (name, "%s%s%s", "__imp_", U (""),
pe_def_file->imports[i].internal_name);
- blhe = bfd_link_hash_lookup (link_info->hash, name,
+ blhe = bfd_link_hash_lookup (linfo->hash, name,
FALSE, FALSE, FALSE);
}
else
include_jmp_stub = TRUE;
+ if (is_cdecl && !blhe)
+ {
+ sprintf (name, "%s%s",U (""),
+ pe_def_file->imports[i].internal_name);
+ blhe = pe_find_cdecl_alias_match (name);
+ include_jmp_stub = TRUE;
+ }
+
free (name);
if (blhe && blhe->type == bfd_link_hash_undefined)
if (!do_this_dll)
{
bfd *ar_head = make_head (output_bfd);
- add_bfd_to_link (ar_head, ar_head->filename, link_info);
+ add_bfd_to_link (ar_head, ar_head->filename, linfo);
do_this_dll = 1;
}
exp.internal_name = pe_def_file->imports[i].internal_name;
exp.name = pe_def_file->imports[i].name;
+ exp.its_name = pe_def_file->imports[i].its_name;
exp.ordinal = pe_def_file->imports[i].ordinal;
exp.hint = exp.ordinal >= 0 ? exp.ordinal : 0;
exp.flag_private = 0;
exp.flag_data = pe_def_file->imports[i].data;
exp.flag_noname = exp.name ? 0 : 1;
one = make_one (&exp, output_bfd, (! exp.flag_data) && include_jmp_stub);
- add_bfd_to_link (one, one->filename, link_info);
+ add_bfd_to_link (one, one->filename, linfo);
}
}
if (do_this_dll)
{
bfd *ar_tail = make_tail (output_bfd);
- add_bfd_to_link (ar_tail, ar_tail->filename, link_info);
+ add_bfd_to_link (ar_tail, ar_tail->filename, linfo);
}
free (dll_symname);
bfd_vma exp_funcbase;
unsigned char *expdata;
char *erva;
- bfd_vma name_rvas, ordinals, nexp, ordbase;
- const char *dll_name;
+ bfd_vma name_rvas, nexp;
+ const char *dllname;
/* Initialization with start > end guarantees that is_data
will not be set by mistake, and avoids compiler warning. */
bfd_vma data_start = 1;
return FALSE;
}
- /* Get pe_header, optional header and numbers of export entries. */
+ /* Get pe_header, optional header and numbers of directory entries. */
pe_header_offset = pe_get32 (dll, 0x3c);
opthdr_ofs = pe_header_offset + 4 + 20;
#ifdef pe_use_x86_64
num_entries = pe_get32 (dll, opthdr_ofs + 92);
#endif
- if (num_entries < 1) /* No exports. */
+ /* No import or export directory entry. */
+ if (num_entries < 1)
return FALSE;
#ifdef pe_use_x86_64
export_size = pe_get32 (dll, opthdr_ofs + 100);
#endif
+ /* No export table - nothing to export. */
+ if (export_size == 0)
+ return FALSE;
+
nsections = pe_get16 (dll, pe_header_offset + 4 + 2);
secptr = (pe_header_offset + 4 + 20 +
pe_get16 (dll, pe_header_offset + 4 + 16));
nexp = pe_as32 (expdata + 24);
name_rvas = pe_as32 (expdata + 32);
- ordinals = pe_as32 (expdata + 36);
- ordbase = pe_as32 (expdata + 16);
exp_funcbase = pe_as32 (expdata + 28);
/* Use internal dll name instead of filename
to enable symbolic dll linking. */
- dll_name = erva + pe_as32 (expdata + 12);
+ dllname = erva + pe_as32 (expdata + 12);
/* Check to see if the dll has already been added to
the definition list and if so return without error.
This avoids multiple symbol definitions. */
- if (def_get_module (pe_def_file, dll_name))
+ if (def_get_module (pe_def_file, dllname))
{
if (pe_dll_extra_pe_debug)
- printf ("%s is already loaded\n", dll_name);
+ printf ("%s is already loaded\n", dllname);
return TRUE;
}
/* Skip unwanted symbols, which are
exported in buggy auto-import releases. */
- if (! CONST_STRNEQ (erva + name_rva, "_nm_"))
+ if (! CONST_STRNEQ (erva + name_rva, "__nm_"))
{
+ int is_dup = 0;
/* is_data is true if the address is in the data, rdata or bss
segment. */
is_data =
|| (func_rva >= bss_start && func_rva < bss_end);
imp = def_file_add_import (pe_def_file, erva + name_rva,
- dll_name, i, 0);
+ dllname, i, 0, NULL, &is_dup);
/* Mark symbol type. */
- imp->data = is_data;
+ if (!is_dup)
+ imp->data = is_data;
if (pe_dll_extra_pe_debug)
printf ("%s dll-name: %s sym: %s addr: 0x%lx %s\n",
- __FUNCTION__, dll_name, erva + name_rva,
+ __FUNCTION__, dllname, erva + name_rva,
(unsigned long) func_rva, is_data ? "(data)" : "");
}
}
{
pe_dll_id_target (bfd_get_target (abfd));
pe_output_file_set_long_section_names (abfd);
- process_def_file (abfd, info);
+ process_def_file_and_drectve (abfd, info);
if (pe_def_file->num_exports == 0 && !info->shared)
return;
ldemul_after_allocation ();
/* Do the assignments again. */
- lang_do_assignments ();
+ lang_do_assignments (lang_final_phase_enum);
}
fill_edata (abfd, info);
ldemul_after_allocation ();
/* Do the assignments again. */
- lang_do_assignments ();
+ lang_do_assignments (lang_final_phase_enum);
}
reloc_s->contents = reloc_d;
}