X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=ld%2Fpe-dll.c;h=fdadeaf2865d3278194080121a46296a6f791f35;hb=2986367f8eea0dc5febab9c9fd1cf06b3a4a8fdb;hp=d8b4e5e342692cbdae07710ad3699b42842dc648;hpb=6e230cc21758810c07dae89243af1b3f0b718582;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/pe-dll.c b/ld/pe-dll.c index d8b4e5e342..fdadeaf286 100644 --- a/ld/pe-dll.c +++ b/ld/pe-dll.c @@ -1,6 +1,5 @@ /* 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-2015 Free Software Foundation, Inc. Written by DJ Delorie This file is part of the GNU Binutils. @@ -236,6 +235,7 @@ static const autofilter_entry_type autofilter_symbollist_i386[] = { STRING_COMMA_LEN ("_impure_ptr") }, { STRING_COMMA_LEN ("_fmode") }, { STRING_COMMA_LEN ("environ") }, + { STRING_COMMA_LEN ("__dso_handle") }, { NULL, 0 } }; @@ -655,7 +655,7 @@ process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info * /* First, run around to all the objects looking for the .drectve sections, and push those into the def file too. */ - for (b = info->input_bfds; b; b = b->link_next) + for (b = info->input_bfds; b; b = b->link.next) { s = bfd_get_section_by_name (b, ".drectve"); if (s) @@ -693,7 +693,7 @@ process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info * /* 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 + if (bfd_link_executable (info) && pe_def_file->num_exports == 0 && (!pe_dll_export_everything || pe_dll_exclude_all_symbols)) return; @@ -701,7 +701,7 @@ process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info * 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) + for (b = info->input_bfds; b; b = b->link.next) { asymbol **symbols; int nsyms; @@ -720,9 +720,10 @@ process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info * /* 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, @@ -781,14 +782,17 @@ process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_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; @@ -1166,9 +1170,6 @@ fill_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED) unsigned char *enameptrs; unsigned char *eordinals; char *enamestr; - time_t now; - - time (&now); edata_d = xmalloc (edata_sz); @@ -1183,7 +1184,10 @@ fill_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED) + 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); @@ -1264,7 +1268,7 @@ pe_walk_relocs_of_symbol (struct bfd_link_info *info, bfd *b; asection *s; - for (b = info->input_bfds; b; b = b->link_next) + for (b = info->input_bfds; b; b = b->link.next) { asymbol **symbols; @@ -1327,7 +1331,7 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info) struct bfd_section *s; total_relocs = 0; - for (b = info->input_bfds; b; b = b->link_next) + for (b = info->input_bfds; b; b = b->link.next) for (s = b->sections; s; s = s->next) total_relocs += s->reloc_count; @@ -1335,7 +1339,7 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info) total_relocs = 0; bi = 0; - for (bi = 0, b = info->input_bfds; b; bi++, b = b->link_next) + for (bi = 0, b = info->input_bfds; b; bi++, b = b->link.next) { arelent **relocs; int relsize, nrelocs; @@ -1351,7 +1355,7 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info) /* 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) @@ -1408,7 +1412,7 @@ generate_reloc (bfd *abfd, struct bfd_link_info *info) 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) @@ -1767,7 +1771,7 @@ static int tmp_seq2; 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) @@ -2587,7 +2591,7 @@ pe_create_runtime_relocator_reference (bfd *parent) 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); @@ -2712,8 +2716,9 @@ pe_dll_generate_implib (def_file *def, const char *impfilename, struct bfd_link_ 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; @@ -2722,7 +2727,7 @@ pe_dll_generate_implib (def_file *def, const char *impfilename, struct bfd_link_ 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) + for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link.next) { /* Iterate the exclude list. */ struct exclude_list_struct *ex; @@ -2817,36 +2822,160 @@ pe_dll_generate_implib (def_file *def, const char *impfilename, struct bfd_link_ } } -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 @@ -2878,6 +3007,8 @@ pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *linfo) imp = pe_def_file->imports; + pe_create_undef_table (); + for (module = pe_def_file->modules; module; module = module->next) { int do_this_dll = 0; @@ -2903,6 +3034,8 @@ pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *linfo) 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; @@ -2926,20 +3059,27 @@ pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *linfo) 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. */ @@ -2970,6 +3110,13 @@ pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *linfo) 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 @@ -3222,7 +3369,7 @@ pe_dll_build_sections (bfd *abfd, struct bfd_link_info *info) pe_output_file_set_long_section_names (abfd); process_def_file_and_drectve (abfd, info); - if (pe_def_file->num_exports == 0 && !info->shared) + if (pe_def_file->num_exports == 0 && !bfd_link_pic (info)) return; generate_edata (abfd, info); @@ -3264,7 +3411,7 @@ pe_dll_fill_sections (bfd *abfd, struct bfd_link_info *info) fill_edata (abfd, info); - if (info->shared && !info->pie) + if (bfd_link_dll (info)) pe_data (abfd)->dll = 1; edata_s->contents = edata_d;