Line 1... |
Line 1... |
/* Routines to help build PEI-format DLLs (Win32 etc)
|
/* Routines to help build PEI-format DLLs (Win32 etc)
|
Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
|
Written by DJ Delorie <dj@cygnus.com>
|
Written by DJ Delorie <dj@cygnus.com>
|
|
|
This file is part of the GNU Binutils.
|
This file is part of the GNU Binutils.
|
|
|
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
Line 527... |
Line 527... |
It can be used for contextual checks. */
|
It can be used for contextual checks. */
|
|
|
static int
|
static int
|
auto_export (bfd *abfd, def_file *d, const char *n)
|
auto_export (bfd *abfd, def_file *d, const char *n)
|
{
|
{
|
int i;
|
def_file_export key;
|
struct exclude_list_struct *ex;
|
struct exclude_list_struct *ex;
|
const autofilter_entry_type *afptr;
|
const autofilter_entry_type *afptr;
|
const char * libname = 0;
|
const char * libname = NULL;
|
|
|
if (abfd && abfd->my_archive)
|
if (abfd && abfd->my_archive)
|
libname = lbasename (abfd->my_archive->filename);
|
libname = lbasename (abfd->my_archive->filename);
|
|
|
for (i = 0; i < d->num_exports; i++)
|
key.name = key.its_name = (char *) n;
|
if (strcmp (d->exports[i].name, n) == 0)
|
|
|
/* Return false if n is in the d->exports table. */
|
|
if (bsearch (&key, d->exports, d->num_exports,
|
|
sizeof (pe_def_file->exports[0]), pe_export_sort))
|
return 0;
|
return 0;
|
|
|
if (pe_dll_do_default_excludes)
|
if (pe_dll_do_default_excludes)
|
{
|
{
|
const char * p;
|
const char * p;
|
Line 642... |
Line 646... |
int i, j;
|
int i, j;
|
struct bfd_link_hash_entry *blhe;
|
struct bfd_link_hash_entry *blhe;
|
bfd *b;
|
bfd *b;
|
struct bfd_section *s;
|
struct bfd_section *s;
|
def_file_export *e = 0;
|
def_file_export *e = 0;
|
|
bfd_boolean resort_needed;
|
|
|
if (!pe_def_file)
|
if (!pe_def_file)
|
pe_def_file = def_file_empty ();
|
pe_def_file = def_file_empty ();
|
|
|
/* First, run around to all the objects looking for the .drectve
|
/* First, run around to all the objects looking for the .drectve
|
Line 748... |
Line 753... |
|
|
if (auto_export (b, pe_def_file, sn))
|
if (auto_export (b, pe_def_file, sn))
|
{
|
{
|
int is_dup = 0;
|
int is_dup = 0;
|
def_file_export *p;
|
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);
|
NULL, &is_dup);
|
/* Fill data flag properly, from dlltool.c. */
|
/* Fill data flag properly, from dlltool.c. */
|
if (!is_dup)
|
if (!is_dup)
|
p->flag_data = !(symbols[j]->flags & BSF_FUNCTION);
|
p->flag_data = !(symbols[j]->flags & BSF_FUNCTION);
|
Line 766... |
Line 772... |
|
|
/* Don't create an empty export table. */
|
/* Don't create an empty export table. */
|
if (NE == 0)
|
if (NE == 0)
|
return;
|
return;
|
|
|
|
resort_needed = FALSE;
|
|
|
/* Canonicalize the export list. */
|
/* Canonicalize the export list. */
|
if (pe_dll_kill_ats)
|
if (pe_dll_kill_ats)
|
{
|
{
|
for (i = 0; i < NE; i++)
|
for (i = 0; i < NE; i++)
|
{
|
{
|
Line 786... |
Line 794... |
*tmp_at = 0;
|
*tmp_at = 0;
|
else
|
else
|
einfo (_("%XCannot export %s: invalid export name\n"),
|
einfo (_("%XCannot export %s: invalid export name\n"),
|
pe_def_file->exports[i].name);
|
pe_def_file->exports[i].name);
|
pe_def_file->exports[i].name = tmp;
|
pe_def_file->exports[i].name = tmp;
|
|
resort_needed = TRUE;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
|
/* Re-sort the exports table as we have possibly changed the order
|
|
by removing leading @. */
|
|
if (resort_needed)
|
|
qsort (pe_def_file->exports, NE, sizeof (pe_def_file->exports[0]),
|
|
pe_export_sort);
|
|
|
if (pe_dll_stdcall_aliases)
|
if (pe_dll_stdcall_aliases)
|
{
|
{
|
for (i = 0; i < NE; i++)
|
for (i = 0; i < NE; i++)
|
{
|
{
|
if (is_import (pe_def_file->exports[i].name))
|
if (is_import (pe_def_file->exports[i].name))
|
Line 817... |
Line 832... |
}
|
}
|
|
|
/* Convenience, but watch out for it changing. */
|
/* Convenience, but watch out for it changing. */
|
e = pe_def_file->exports;
|
e = pe_def_file->exports;
|
|
|
exported_symbol_offsets = xmalloc (NE * sizeof (bfd_vma));
|
|
exported_symbol_sections = xmalloc (NE * sizeof (struct bfd_section *));
|
|
|
|
memset (exported_symbol_sections, 0, NE * sizeof (struct bfd_section *));
|
|
max_ordinal = 0;
|
|
min_ordinal = 65536;
|
|
count_exported = 0;
|
|
count_exported_byname = 0;
|
|
count_with_ordinals = 0;
|
|
|
|
qsort (pe_def_file->exports, NE, sizeof (pe_def_file->exports[0]),
|
|
pe_export_sort);
|
|
for (i = 0, j = 0; i < NE; i++)
|
for (i = 0, j = 0; i < NE; i++)
|
{
|
{
|
if (i > 0 && strcmp (e[i].name, e[i - 1].name) == 0)
|
if (i > 0 && strcmp (e[i].name, e[i - 1].name) == 0)
|
{
|
{
|
/* This is a duplicate. */
|
/* This is a duplicate. */
|
Line 857... |
Line 860... |
e[j - 1].ordinal = e[i].ordinal;
|
e[j - 1].ordinal = e[i].ordinal;
|
e[j - 1].flag_private |= e[i].flag_private;
|
e[j - 1].flag_private |= e[i].flag_private;
|
e[j - 1].flag_constant |= e[i].flag_constant;
|
e[j - 1].flag_constant |= e[i].flag_constant;
|
e[j - 1].flag_noname |= e[i].flag_noname;
|
e[j - 1].flag_noname |= e[i].flag_noname;
|
e[j - 1].flag_data |= e[i].flag_data;
|
e[j - 1].flag_data |= e[i].flag_data;
|
|
if (e[i].name)
|
|
free (e[i].name);
|
|
if (e[i].internal_name)
|
|
free (e[i].internal_name);
|
|
if (e[i].its_name)
|
|
free (e[i].its_name);
|
}
|
}
|
else
|
else
|
{
|
{
|
if (i != j)
|
if (i != j)
|
e[j] = e[i];
|
e[j] = e[i];
|
j++;
|
j++;
|
}
|
}
|
}
|
}
|
pe_def_file->num_exports = j; /* == NE */
|
pe_def_file->num_exports = j; /* == NE */
|
|
|
|
exported_symbol_offsets = xmalloc (NE * sizeof (bfd_vma));
|
|
exported_symbol_sections = xmalloc (NE * sizeof (struct bfd_section *));
|
|
|
|
memset (exported_symbol_sections, 0, NE * sizeof (struct bfd_section *));
|
|
max_ordinal = 0;
|
|
min_ordinal = 65536;
|
|
count_exported = 0;
|
|
count_exported_byname = 0;
|
|
count_with_ordinals = 0;
|
|
|
for (i = 0; i < NE; i++)
|
for (i = 0; i < NE; i++)
|
{
|
{
|
char *name;
|
char *name;
|
name = xmalloc (strlen (pe_def_file->exports[i].internal_name) + 2);
|
name = xmalloc (strlen (pe_def_file->exports[i].internal_name) + 2);
|
if (pe_details->underscored
|
if (pe_details->underscored
|
Line 2846... |
Line 2865... |
}
|
}
|
|
|
void
|
void
|
pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *linfo)
|
pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *linfo)
|
{
|
{
|
|
int i, j;
|
def_file_module *module;
|
def_file_module *module;
|
|
def_file_import *imp;
|
|
|
pe_dll_id_target (bfd_get_target (output_bfd));
|
pe_dll_id_target (bfd_get_target (output_bfd));
|
|
|
if (!pe_def_file)
|
if (!pe_def_file)
|
return;
|
return;
|
|
|
|
imp = pe_def_file->imports;
|
|
|
for (module = pe_def_file->modules; module; module = module->next)
|
for (module = pe_def_file->modules; module; module = module->next)
|
{
|
{
|
int i, do_this_dll;
|
int do_this_dll = 0;
|
|
|
|
for (i = 0; i < pe_def_file->num_imports && imp[i].module != module; i++)
|
|
;
|
|
if (i >= pe_def_file->num_imports)
|
|
continue;
|
|
|
dll_filename = module->name;
|
dll_filename = module->name;
|
dll_symname = xstrdup (module->name);
|
dll_symname = xstrdup (module->name);
|
for (i = 0; dll_symname[i]; i++)
|
for (j = 0; dll_symname[j]; j++)
|
if (!ISALNUM (dll_symname[i]))
|
if (!ISALNUM (dll_symname[j]))
|
dll_symname[i] = '_';
|
dll_symname[j] = '_';
|
|
|
do_this_dll = 0;
|
for (; i < pe_def_file->num_imports && imp[i].module == module; i++)
|
|
|
for (i = 0; i < pe_def_file->num_imports; i++)
|
|
if (pe_def_file->imports[i].module == module)
|
|
{
|
{
|
def_file_export exp;
|
def_file_export exp;
|
struct bfd_link_hash_entry *blhe;
|
struct bfd_link_hash_entry *blhe;
|
int lead_at = (*pe_def_file->imports[i].internal_name == '@');
|
int lead_at = (*imp[i].internal_name == '@');
|
/* See if we need this import. */
|
/* See if we need this import. */
|
size_t len = strlen (pe_def_file->imports[i].internal_name);
|
size_t len = strlen (imp[i].internal_name);
|
char *name = xmalloc (len + 2 + 6);
|
char *name = xmalloc (len + 2 + 6);
|
bfd_boolean include_jmp_stub = FALSE;
|
bfd_boolean include_jmp_stub = FALSE;
|
bfd_boolean is_cdecl = FALSE;
|
bfd_boolean is_cdecl = FALSE;
|
if (!lead_at && strchr (pe_def_file->imports[i].internal_name, '@') == NULL)
|
if (!lead_at && strchr (imp[i].internal_name, '@') == NULL)
|
is_cdecl = TRUE;
|
is_cdecl = TRUE;
|
|
|
if (lead_at)
|
if (lead_at)
|
sprintf (name, "%s",
|
sprintf (name, "%s", imp[i].internal_name);
|
pe_def_file->imports[i].internal_name);
|
|
else
|
else
|
sprintf (name, "%s%s",U (""),
|
sprintf (name, "%s%s",U (""), imp[i].internal_name);
|
pe_def_file->imports[i].internal_name);
|
|
|
|
blhe = bfd_link_hash_lookup (linfo->hash, name,
|
blhe = bfd_link_hash_lookup (linfo->hash, name,
|
FALSE, FALSE, FALSE);
|
FALSE, FALSE, FALSE);
|
|
|
/* Include the jump stub for <sym> only if the <sym>
|
/* Include the jump stub for <sym> only if the <sym>
|
is undefined. */
|
is undefined. */
|
if (!blhe || (blhe && blhe->type != bfd_link_hash_undefined))
|
if (!blhe || (blhe && blhe->type != bfd_link_hash_undefined))
|
{
|
{
|
if (lead_at)
|
if (lead_at)
|
sprintf (name, "%s%s", "__imp_",
|
sprintf (name, "%s%s", "__imp_", imp[i].internal_name);
|
pe_def_file->imports[i].internal_name);
|
|
else
|
else
|
sprintf (name, "%s%s%s", "__imp_", U (""),
|
sprintf (name, "%s%s%s", "__imp_", U (""),
|
pe_def_file->imports[i].internal_name);
|
imp[i].internal_name);
|
|
|
blhe = bfd_link_hash_lookup (linfo->hash, name,
|
blhe = bfd_link_hash_lookup (linfo->hash, name,
|
FALSE, FALSE, FALSE);
|
FALSE, FALSE, FALSE);
|
}
|
}
|
else
|
else
|
include_jmp_stub = TRUE;
|
include_jmp_stub = TRUE;
|
|
|
if (is_cdecl && !blhe)
|
if (is_cdecl && !blhe)
|
{
|
{
|
sprintf (name, "%s%s",U (""),
|
sprintf (name, "%s%s",U (""), imp[i].internal_name);
|
pe_def_file->imports[i].internal_name);
|
|
blhe = pe_find_cdecl_alias_match (name);
|
blhe = pe_find_cdecl_alias_match (name);
|
include_jmp_stub = TRUE;
|
include_jmp_stub = TRUE;
|
}
|
}
|
|
|
free (name);
|
free (name);
|
Line 2926... |
Line 2947... |
{
|
{
|
bfd *ar_head = make_head (output_bfd);
|
bfd *ar_head = make_head (output_bfd);
|
add_bfd_to_link (ar_head, ar_head->filename, linfo);
|
add_bfd_to_link (ar_head, ar_head->filename, linfo);
|
do_this_dll = 1;
|
do_this_dll = 1;
|
}
|
}
|
exp.internal_name = pe_def_file->imports[i].internal_name;
|
exp.internal_name = imp[i].internal_name;
|
exp.name = pe_def_file->imports[i].name;
|
exp.name = imp[i].name;
|
exp.its_name = pe_def_file->imports[i].its_name;
|
exp.its_name = imp[i].its_name;
|
exp.ordinal = pe_def_file->imports[i].ordinal;
|
exp.ordinal = imp[i].ordinal;
|
exp.hint = exp.ordinal >= 0 ? exp.ordinal : 0;
|
exp.hint = exp.ordinal >= 0 ? exp.ordinal : 0;
|
exp.flag_private = 0;
|
exp.flag_private = 0;
|
exp.flag_constant = 0;
|
exp.flag_constant = 0;
|
exp.flag_data = pe_def_file->imports[i].data;
|
exp.flag_data = imp[i].data;
|
exp.flag_noname = exp.name ? 0 : 1;
|
exp.flag_noname = exp.name ? 0 : 1;
|
one = make_one (&exp, output_bfd, (! exp.flag_data) && include_jmp_stub);
|
one = make_one (&exp, output_bfd, (! exp.flag_data) && include_jmp_stub);
|
add_bfd_to_link (one, one->filename, linfo);
|
add_bfd_to_link (one, one->filename, linfo);
|
}
|
}
|
}
|
}
|
Line 3163... |
Line 3184... |
(func_rva >= data_start && func_rva < data_end)
|
(func_rva >= data_start && func_rva < data_end)
|
|| (func_rva >= rdata_start && func_rva < rdata_end)
|
|| (func_rva >= rdata_start && func_rva < rdata_end)
|
|| (func_rva >= bss_start && func_rva < bss_end);
|
|| (func_rva >= bss_start && func_rva < bss_end);
|
|
|
imp = def_file_add_import (pe_def_file, erva + name_rva,
|
imp = def_file_add_import (pe_def_file, erva + name_rva,
|
dllname, i, 0, NULL, &is_dup);
|
dllname, i, NULL, NULL, &is_dup);
|
/* Mark symbol type. */
|
/* Mark symbol type. */
|
if (!is_dup)
|
if (!is_dup)
|
imp->data = is_data;
|
imp->data = is_data;
|
|
|
if (pe_dll_extra_pe_debug)
|
if (pe_dll_extra_pe_debug)
|