X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Fcofflink.c;h=16ba0acb10346df3da87dd47cec8755f65517759;hb=2fd158eb7bd4059478086143dd58edcc5ea44864;hp=b3908018ee04b0a902c3a8c7f3e9aeedc350ca14;hpb=a29a8af823af0415dae4d3b2ffd60cb3b53ec011;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/cofflink.c b/bfd/cofflink.c index b3908018ee..16ba0acb10 100644 --- a/bfd/cofflink.c +++ b/bfd/cofflink.c @@ -1,6 +1,5 @@ /* COFF specific linker code. - Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005, 2006, 2007, 2008, 2009, 2011 Free Software Foundation, Inc. + Copyright (C) 1994-2015 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -30,9 +29,11 @@ #include "libcoff.h" #include "safe-ctype.h" -static bfd_boolean coff_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info); -static bfd_boolean coff_link_check_archive_element (bfd *abfd, struct bfd_link_info *info, bfd_boolean *pneeded); -static bfd_boolean coff_link_add_symbols (bfd *abfd, struct bfd_link_info *info); +static bfd_boolean coff_link_add_object_symbols (bfd *, struct bfd_link_info *); +static bfd_boolean coff_link_check_archive_element + (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, const char *, + bfd_boolean *); +static bfd_boolean coff_link_add_symbols (bfd *, struct bfd_link_info *); /* Return TRUE if SYM is a weak, external symbol. */ #define IS_WEAK_EXTERNAL(abfd, sym) \ @@ -191,74 +192,6 @@ coff_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) return TRUE; } -/* Look through the symbols to see if this object file should be - included in the link. */ - -static bfd_boolean -coff_link_check_ar_symbols (bfd *abfd, - struct bfd_link_info *info, - bfd_boolean *pneeded, - bfd **subsbfd) -{ - bfd_size_type symesz; - bfd_byte *esym; - bfd_byte *esym_end; - - *pneeded = FALSE; - - symesz = bfd_coff_symesz (abfd); - esym = (bfd_byte *) obj_coff_external_syms (abfd); - esym_end = esym + obj_raw_syment_count (abfd) * symesz; - while (esym < esym_end) - { - struct internal_syment sym; - enum coff_symbol_classification classification; - - bfd_coff_swap_sym_in (abfd, esym, &sym); - - classification = bfd_coff_classify_symbol (abfd, &sym); - if (classification == COFF_SYMBOL_GLOBAL - || classification == COFF_SYMBOL_COMMON) - { - const char *name; - char buf[SYMNMLEN + 1]; - struct bfd_link_hash_entry *h; - - /* This symbol is externally visible, and is defined by this - object file. */ - name = _bfd_coff_internal_syment_name (abfd, &sym, buf); - if (name == NULL) - return FALSE; - h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE); - - /* Auto import. */ - if (!h - && info->pei386_auto_import - && CONST_STRNEQ (name, "__imp_")) - h = bfd_link_hash_lookup (info->hash, name + 6, FALSE, FALSE, TRUE); - - /* We are only interested in symbols that are currently - undefined. If a symbol is currently known to be common, - COFF linkers do not bring in an object file which defines - it. */ - if (h != (struct bfd_link_hash_entry *) NULL - && h->type == bfd_link_hash_undefined) - { - if (!(*info->callbacks - ->add_archive_element) (info, abfd, name, subsbfd)) - return FALSE; - *pneeded = TRUE; - return TRUE; - } - } - - esym += (sym.n_numaux + 1) * symesz; - } - - /* We do not need this object file. */ - return TRUE; -} - /* Check a single archive element to see if we need to include it in the link. *PNEEDED is set according to whether this element is needed in the link or not. This is called via @@ -267,41 +200,23 @@ coff_link_check_ar_symbols (bfd *abfd, static bfd_boolean coff_link_check_archive_element (bfd *abfd, struct bfd_link_info *info, + struct bfd_link_hash_entry *h, + const char *name, bfd_boolean *pneeded) { - bfd *oldbfd; - bfd_boolean needed; + *pneeded = FALSE; - if (!_bfd_coff_get_external_symbols (abfd)) - return FALSE; + /* We are only interested in symbols that are currently undefined. + If a symbol is currently known to be common, COFF linkers do not + bring in an object file which defines it. */ + if (h->type != bfd_link_hash_undefined) + return TRUE; - oldbfd = abfd; - if (!coff_link_check_ar_symbols (abfd, info, pneeded, &abfd)) + if (!(*info->callbacks->add_archive_element) (info, abfd, name, &abfd)) return FALSE; + *pneeded = TRUE; - needed = *pneeded; - if (needed) - { - /* Potentially, the add_archive_element hook may have set a - substitute BFD for us. */ - if (abfd != oldbfd) - { - if (!info->keep_memory - && !_bfd_coff_free_symbols (oldbfd)) - return FALSE; - if (!_bfd_coff_get_external_symbols (abfd)) - return FALSE; - } - if (!coff_link_add_symbols (abfd, info)) - return FALSE; - } - - if (!info->keep_memory || !needed) - { - if (!_bfd_coff_free_symbols (abfd)) - return FALSE; - } - return TRUE; + return coff_link_add_object_symbols (abfd, info); } /* Add all the symbols from an object file to the hash table. */ @@ -592,7 +507,7 @@ coff_link_add_symbols (bfd *abfd, /* If this is a non-traditional, non-relocatable link, try to optimize the handling of any .stab/.stabstr sections. */ - if (! info->relocatable + if (! bfd_link_relocatable (info) && ! info->traditional_format && bfd_get_flavour (info->output_bfd) == bfd_get_flavour (abfd) && (info->strip != strip_all && info->strip != strip_debugger)) @@ -605,7 +520,7 @@ coff_link_add_symbols (bfd *abfd, { bfd_size_type string_offset = 0; asection *stab; - + for (stab = abfd->sections; stab; stab = stab->next) if (CONST_STRNEQ (stab->name, ".stab") && (!stab->name[5] @@ -614,7 +529,7 @@ coff_link_add_symbols (bfd *abfd, struct coff_link_hash_table *table; struct coff_section_tdata *secdata = coff_section_data (abfd, stab); - + if (secdata == NULL) { amt = sizeof (struct coff_section_tdata); @@ -737,7 +652,7 @@ _bfd_coff_final_link (bfd *abfd, || info->strip == strip_some) o->lineno_count += sec->lineno_count; - if (info->relocatable) + if (bfd_link_relocatable (info)) o->reloc_count += sec->reloc_count; if (sec->rawsize > max_contents_size) @@ -749,7 +664,7 @@ _bfd_coff_final_link (bfd *abfd, if (sec->reloc_count > max_reloc_count) max_reloc_count = sec->reloc_count; } - else if (info->relocatable + else if (bfd_link_relocatable (info) && (p->type == bfd_section_reloc_link_order || p->type == bfd_symbol_reloc_link_order)) ++o->reloc_count; @@ -784,7 +699,7 @@ _bfd_coff_final_link (bfd *abfd, /* If doing a relocatable link, allocate space for the pointers we need to keep. */ - if (info->relocatable) + if (bfd_link_relocatable (info)) { unsigned int i; @@ -832,7 +747,7 @@ _bfd_coff_final_link (bfd *abfd, memory until the end of the link. This wastes memory, but only when doing a relocatable link, which is not the common case. */ - BFD_ASSERT (info->relocatable); + BFD_ASSERT (bfd_link_relocatable (info)); amt = o->reloc_count; amt *= sizeof (struct internal_reloc); flaginfo.section_info[o->target_index].relocs = @@ -861,7 +776,7 @@ _bfd_coff_final_link (bfd *abfd, the opportunity to clear the output_has_begun fields of all the input BFD's. */ max_sym_count = 0; - for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) + for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) { size_t sz; @@ -884,7 +799,7 @@ _bfd_coff_final_link (bfd *abfd, flaginfo.contents = (bfd_byte *) bfd_malloc (max_contents_size); amt = max_reloc_count * relsz; flaginfo.external_relocs = (bfd_byte *) bfd_malloc (amt); - if (! info->relocatable) + if (! bfd_link_relocatable (info)) { amt = max_reloc_count * sizeof (struct internal_reloc); flaginfo.internal_relocs = (struct internal_reloc *) bfd_malloc (amt); @@ -896,7 +811,7 @@ _bfd_coff_final_link (bfd *abfd, || (flaginfo.linenos == NULL && max_lineno_count > 0) || (flaginfo.contents == NULL && max_contents_size > 0) || (flaginfo.external_relocs == NULL && max_reloc_count > 0) - || (! info->relocatable + || (! bfd_link_relocatable (info) && flaginfo.internal_relocs == NULL && max_reloc_count > 0)) goto error_return; @@ -946,7 +861,7 @@ _bfd_coff_final_link (bfd *abfd, if (flaginfo.info->strip != strip_all && flaginfo.info->discard != discard_all) { /* Add local symbols from foreign inputs. */ - for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) + for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) { unsigned int i; @@ -957,9 +872,10 @@ _bfd_coff_final_link (bfd *abfd, asymbol *sym = bfd_get_outsymbols (sub) [i]; file_ptr pos; struct internal_syment isym; - bfd_size_type string_size = 0; + union internal_auxent iaux; + bfd_size_type string_size = 0, indx; bfd_vma written = 0; - bfd_boolean rewrite = FALSE; + bfd_boolean rewrite = FALSE, hash; if (! (sym->flags & BSF_LOCAL) || (sym->flags & (BSF_SECTION_SYM | BSF_DEBUGGING_RELOC @@ -976,7 +892,7 @@ _bfd_coff_final_link (bfd *abfd, == NULL)) || (((flaginfo.info->discard == discard_sec_merge && (bfd_get_section (sym)->flags & SEC_MERGE) - && ! flaginfo.info->relocatable) + && ! bfd_link_relocatable (flaginfo.info)) || flaginfo.info->discard == discard_l) && bfd_is_local_label_name (sub, bfd_asymbol_name(sym)))) continue; @@ -985,23 +901,52 @@ _bfd_coff_final_link (bfd *abfd, * symesz; if (bfd_seek (abfd, pos, SEEK_SET) != 0) goto error_return; - if (! coff_write_alien_symbol(abfd, sym, &isym, &written, + if (! coff_write_alien_symbol(abfd, sym, &isym, &iaux, &written, &string_size, NULL, NULL)) goto error_return; - if (string_size) + hash = !flaginfo.info->traditional_format; + + if (string_size >= 6 && isym.n_sclass == C_FILE + && ! isym._n._n_n._n_zeroes && isym.n_numaux) { - bfd_boolean hash = ! (abfd->flags & BFD_TRADITIONAL_FORMAT); - bfd_size_type indx; + indx = _bfd_stringtab_add (flaginfo.strtab, ".file", hash, + FALSE); + if (indx == (bfd_size_type) -1) + goto error_return; + isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx; + bfd_coff_swap_sym_out (abfd, &isym, flaginfo.outsyms); + if (bfd_seek (abfd, pos, SEEK_SET) != 0 + || bfd_bwrite (flaginfo.outsyms, symesz, + abfd) != symesz) + goto error_return; + string_size -= 6; + } + if (string_size) + { indx = _bfd_stringtab_add (flaginfo.strtab, bfd_asymbol_name (sym), hash, FALSE); if (indx == (bfd_size_type) -1) goto error_return; - isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx; - bfd_coff_swap_sym_out (abfd, &isym, flaginfo.outsyms); - rewrite = TRUE; + if (isym.n_sclass != C_FILE) + { + isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx; + bfd_coff_swap_sym_out (abfd, &isym, flaginfo.outsyms); + rewrite = TRUE; + } + else + { + BFD_ASSERT (isym.n_numaux == 1); + iaux.x_file.x_n.x_offset = STRING_SIZE_SIZE + indx; + bfd_coff_swap_aux_out (abfd, &iaux, isym.n_type, C_FILE, + 0, 1, flaginfo.outsyms + symesz); + if (bfd_seek (abfd, pos + symesz, SEEK_SET) != 0 + || bfd_bwrite (flaginfo.outsyms + symesz, symesz, + abfd) != symesz) + goto error_return; + } } if (isym.n_sclass == C_FILE) @@ -1116,7 +1061,7 @@ _bfd_coff_final_link (bfd *abfd, flaginfo.outsyms = NULL; } - if (info->relocatable && max_output_reloc_count > 0) + if (bfd_link_relocatable (info) && max_output_reloc_count > 0) { /* Now that we have written out all the global symbols, we know the symbol indices to use for relocs against them, and we can @@ -1159,7 +1104,7 @@ _bfd_coff_final_link (bfd *abfd, elsewhere. */ struct internal_reloc incount; bfd_byte *excount = (bfd_byte *)bfd_malloc (relsz); - + memset (&incount, 0, sizeof (incount)); incount.r_vaddr = o->reloc_count + 1; bfd_coff_swap_reloc_out (abfd, &incount, excount); @@ -1435,8 +1380,8 @@ mark_relocs (struct coff_final_link_info *flaginfo, bfd *input_bfd) internal_relocs = _bfd_coff_read_internal_relocs (input_bfd, a, FALSE, flaginfo->external_relocs, - flaginfo->info->relocatable, - (flaginfo->info->relocatable + bfd_link_relocatable (flaginfo->info), + (bfd_link_relocatable (flaginfo->info) ? (flaginfo->section_info[ a->output_section->target_index ].relocs + a->output_section->reloc_count) : flaginfo->internal_relocs) ); @@ -1498,7 +1443,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *flaginfo, bfd *input_bfd) if (! flaginfo->info->keep_memory) copy = TRUE; hash = TRUE; - if ((output_bfd->flags & BFD_TRADITIONAL_FORMAT) != 0) + if (flaginfo->info->traditional_format) hash = FALSE; if (! _bfd_coff_get_external_symbols (input_bfd)) @@ -1521,7 +1466,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *flaginfo, bfd *input_bfd) symbols that are going to be involved in the relocations. */ if (( flaginfo->info->strip != strip_none || flaginfo->info->discard != discard_none) - && flaginfo->info->relocatable) + && bfd_link_relocatable (flaginfo->info)) { /* Mark the symbol array as 'not-used'. */ memset (indexp, 0, obj_raw_syment_count (input_bfd) * sizeof * indexp); @@ -1568,7 +1513,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *flaginfo, bfd *input_bfd) relocation. */ if ((flaginfo->info->strip != strip_none || flaginfo->info->discard != discard_none) - && flaginfo->info->relocatable) + && bfd_link_relocatable (flaginfo->info)) dont_skip_symbol = *indexp; else dont_skip_symbol = FALSE; @@ -1676,7 +1621,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *flaginfo, bfd *input_bfd) /* If this is an enum, struct, or union tag, see if we have already output an identical type. */ if (! skip - && (flaginfo->output_bfd->flags & BFD_TRADITIONAL_FORMAT) == 0 + && !flaginfo->info->traditional_format && (isym.n_sclass == C_ENTAG || isym.n_sclass == C_STRTAG || isym.n_sclass == C_UNTAG) @@ -2088,7 +2033,10 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *flaginfo, bfd *input_bfd) if (strings == NULL) return FALSE; } - filename = strings + auxp->x_file.x_n.x_offset; + if ((bfd_size_type) auxp->x_file.x_n.x_offset >= obj_coff_strings_len (input_bfd)) + filename = _(""); + else + filename = strings + auxp->x_file.x_n.x_offset; indx = _bfd_stringtab_add (flaginfo->strtab, filename, hash, copy); if (indx == (bfd_size_type) -1) @@ -2442,8 +2390,8 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *flaginfo, bfd *input_bfd) target_index = o->output_section->target_index; internal_relocs = (_bfd_coff_read_internal_relocs (input_bfd, o, FALSE, flaginfo->external_relocs, - flaginfo->info->relocatable, - (flaginfo->info->relocatable + bfd_link_relocatable (flaginfo->info), + (bfd_link_relocatable (flaginfo->info) ? (flaginfo->section_info[target_index].relocs + o->output_section->reloc_count) : flaginfo->internal_relocs))); @@ -2490,7 +2438,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *flaginfo, bfd *input_bfd) flaginfo->sec_ptrs)) return FALSE; - if (flaginfo->info->relocatable) + if (bfd_link_relocatable (flaginfo->info)) { bfd_vma offset; struct internal_reloc *irelend; @@ -2684,7 +2632,7 @@ _bfd_coff_write_global_sym (struct bfd_hash_entry *bh, void *data) bfd_size_type indx; hash = TRUE; - if ((output_bfd->flags & BFD_TRADITIONAL_FORMAT) != 0) + if (flaginfo->info->traditional_format) hash = FALSE; indx = _bfd_stringtab_add (flaginfo->strtab, h->root.root.string, hash, FALSE); @@ -2718,8 +2666,8 @@ _bfd_coff_write_global_sym (struct bfd_hash_entry *bh, void *data) /* When a weak symbol is not overridden by a strong one, turn it into an external symbol when not building a shared or relocatable object. */ - if (! flaginfo->info->shared - && ! flaginfo->info->relocatable + if (! bfd_link_pic (flaginfo->info) + && ! bfd_link_relocatable (flaginfo->info) && IS_WEAK_EXTERNAL (flaginfo->output_bfd, isym)) isym.n_sclass = C_EXT; @@ -2772,7 +2720,7 @@ _bfd_coff_write_global_sym (struct bfd_hash_entry *bh, void *data) not matter. FIXME: Why not? */ if (sec->reloc_count > 0xffff && (! obj_pe (output_bfd) - || flaginfo->info->relocatable)) + || bfd_link_relocatable (flaginfo->info))) (*_bfd_error_handler) (_("%s: %s: reloc overflow: 0x%lx > 0xffff"), bfd_get_filename (output_bfd), @@ -2781,7 +2729,7 @@ _bfd_coff_write_global_sym (struct bfd_hash_entry *bh, void *data) if (sec->lineno_count > 0xffff && (! obj_pe (output_bfd) - || flaginfo->info->relocatable)) + || bfd_link_relocatable (flaginfo->info))) (*_bfd_error_handler) (_("%s: warning: %s: line number overflow: 0x%lx > 0xffff"), bfd_get_filename (output_bfd), @@ -2871,7 +2819,7 @@ _bfd_coff_reloc_link_order (bfd *output_bfd, size = bfd_get_reloc_size (howto); buf = (bfd_byte *) bfd_zmalloc (size); - if (buf == NULL) + if (buf == NULL && size != 0) return FALSE; rstat = _bfd_relocate_contents (howto, output_bfd, @@ -2997,6 +2945,7 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd, struct internal_syment *sym; bfd_vma addend; bfd_vma val; + asection *sec; reloc_howto_type *howto; bfd_reloc_status_type rstat; @@ -3040,18 +2989,16 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd, then we should ignore the symbol value. */ if (howto->pc_relative && howto->pcrel_offset) { - if (info->relocatable) + if (bfd_link_relocatable (info)) continue; if (sym != NULL && sym->n_scnum != 0) addend += sym->n_value; } val = 0; - + sec = NULL; if (h == NULL) { - asection *sec; - if (symndx == -1) { sec = bfd_abs_section_ptr; @@ -3073,8 +3020,6 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd, || h->root.type == bfd_link_hash_defweak) { /* Defined weak symbols are a GNU extension. */ - asection *sec; - sec = h->root.u.def.section; val = (h->root.u.def.value + sec->output_section->vma @@ -3095,7 +3040,6 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd, will resolve a weak external only if a normal external causes the library member to be linked. See also linker.c: generic_link_check_archive_element. */ - asection *sec; struct coff_link_hash_entry *h2 = h->auxbfd->tdata.coff_obj_data->sym_hashes[ h->aux->x_sym.x_tagndx.l]; @@ -3117,7 +3061,7 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd, val = 0; } - else if (! info->relocatable) + else if (! bfd_link_relocatable (info)) { if (! ((*info->callbacks->undefined_symbol) (info, h->root.root.string, input_bfd, input_section, @@ -3126,6 +3070,15 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd, } } + /* If the input section defining the symbol has been discarded + then zero this reloc field. */ + if (sec != NULL && discarded_section (sec)) + { + _bfd_clear_contents (howto, input_bfd, input_section, + contents + (rel->r_vaddr - input_section->vma)); + continue; + } + if (info->base_file) { /* Emit a reloc if the backend thinks it needs it. */