X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Flinker.c;h=533eff8715d5375e462ce20a20e1816203ef3b94;hb=8b8c7c9f49992750f66f81b4601d593a3858d98c;hp=a31e473417175aa07ac702ec5b42827f8dabc7c2;hpb=13e570f80cbfb299a8858ce6830e91a6cb40ab7b;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/linker.c b/bfd/linker.c index a31e473417..533eff8715 100644 --- a/bfd/linker.c +++ b/bfd/linker.c @@ -1,5 +1,5 @@ /* linker.c -- BFD linker routines - Copyright (C) 1993-2014 Free Software Foundation, Inc. + Copyright (C) 1993-2016 Free Software Foundation, Inc. Written by Steve Chamberlain and Ian Lance Taylor, Cygnus Support This file is part of BFD, the Binary File Descriptor library. @@ -1120,29 +1120,21 @@ generic_link_check_archive_element (bfd *abfd, /* P is a symbol we are looking for. */ - if (! bfd_is_com_section (p->section)) + if (! bfd_is_com_section (p->section) + || (h->type == bfd_link_hash_undefined + && h->u.undef.abfd == NULL)) { - bfd_size_type symcount; - asymbol **symbols; - bfd *oldbfd = abfd; - - /* This object file defines this symbol, so pull it in. */ + /* P is not a common symbol, or an undefined reference was + created from outside BFD such as from a linker -u option. + This object file defines the symbol, so pull it in. */ + *pneeded = TRUE; if (!(*info->callbacks ->add_archive_element) (info, abfd, bfd_asymbol_name (p), &abfd)) return FALSE; /* Potentially, the add_archive_element hook may have set a substitute BFD for us. */ - if (abfd != oldbfd - && !bfd_generic_link_read_symbols (abfd)) - return FALSE; - symcount = _bfd_generic_link_get_symcount (abfd); - symbols = _bfd_generic_link_get_symbols (abfd); - if (! generic_link_add_symbol_list (abfd, info, symcount, - symbols, collect)) - return FALSE; - *pneeded = TRUE; - return TRUE; + return generic_link_add_object_symbols (abfd, info, collect); } /* P is a common symbol. */ @@ -1153,23 +1145,6 @@ generic_link_check_archive_element (bfd *abfd, bfd_vma size; unsigned int power; - symbfd = h->u.undef.abfd; - if (symbfd == NULL) - { - /* This symbol was created as undefined from outside - BFD. We assume that we should link in the object - file. This is for the -u option in the linker. */ - if (!(*info->callbacks - ->add_archive_element) (info, abfd, bfd_asymbol_name (p), - &abfd)) - return FALSE; - /* Potentially, the add_archive_element hook may have set a - substitute BFD for us. But no symbols are going to get - registered by anything we're returning to from here. */ - *pneeded = TRUE; - return TRUE; - } - /* Turn the symbol into a common symbol but do not link in the object file. This is how a.out works. Object formats that require different semantics must implement @@ -1177,6 +1152,7 @@ generic_link_check_archive_element (bfd *abfd, undefs list. We add the section to a common section attached to symbfd to ensure that it is in a BFD which will be linked in. */ + symbfd = h->u.undef.abfd; h->type = bfd_link_hash_common; h->u.c.p = (struct bfd_link_hash_common_entry *) bfd_hash_allocate (&info->hash->table, @@ -1366,8 +1342,7 @@ enum link_action CIND, /* Make indirect symbol from existing common symbol. */ SET, /* Add value to set. */ MWARN, /* Make warning symbol. */ - WARN, /* Issue warning. */ - CWARN, /* Warn if referenced, else MWARN. */ + WARN, /* Warn if referenced, else MWARN. */ CYCLE, /* Repeat with symbol pointed to. */ REFC, /* Mark indirect symbol referenced and then CYCLE. */ WARNC /* Issue warning and then CYCLE. */ @@ -1385,7 +1360,7 @@ static const enum link_action link_action[8][8] = /* DEFW_ROW */ {DEFW, DEFW, DEFW, NOACT, NOACT, NOACT, NOACT, CYCLE }, /* COMMON_ROW */ {COM, COM, COM, CREF, COM, BIG, REFC, WARNC }, /* INDR_ROW */ {IND, IND, IND, MDEF, IND, CIND, MIND, CYCLE }, - /* WARN_ROW */ {MWARN, WARN, WARN, CWARN, CWARN, WARN, CWARN, NOACT }, + /* WARN_ROW */ {MWARN, WARN, WARN, WARN, WARN, WARN, WARN, NOACT }, /* SET_ROW */ {SET, SET, SET, SET, SET, SET, CYCLE, CYCLE } }; @@ -1467,13 +1442,23 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, { enum link_row row; struct bfd_link_hash_entry *h; + struct bfd_link_hash_entry *inh = NULL; bfd_boolean cycle; BFD_ASSERT (section != NULL); if (bfd_is_ind_section (section) || (flags & BSF_INDIRECT) != 0) - row = INDR_ROW; + { + row = INDR_ROW; + /* Create the indirect symbol here. This is for the benefit of + the plugin "notice" function. + STRING is the name of the symbol we want to indirect to. */ + inh = bfd_wrapped_link_hash_lookup (abfd, info, string, TRUE, + copy, FALSE); + if (inh == NULL) + return FALSE; + } else if ((flags & BSF_WARNING) != 0) row = WARN_ROW; else if ((flags & BSF_CONSTRUCTOR) != 0) @@ -1490,7 +1475,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, else if (bfd_is_com_section (section)) { row = COMMON_ROW; - if (strcmp (name, "__gnu_lto_slim") == 0) + if (!bfd_link_relocatable (info) + && strcmp (name, "__gnu_lto_slim") == 0) (*_bfd_error_handler) (_("%s: plugin needed to handle lto object"), bfd_get_filename (abfd)); @@ -1518,8 +1504,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, || (info->notice_hash != NULL && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL)) { - if (! (*info->callbacks->notice) (info, h, - abfd, section, value, flags, string)) + if (! (*info->callbacks->notice) (info, h, inh, + abfd, section, value, flags)) return FALSE; } @@ -1558,9 +1544,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, /* We have found a definition for a symbol which was previously common. */ BFD_ASSERT (h->type == bfd_link_hash_common); - if (! ((*info->callbacks->multiple_common) - (info, h, abfd, bfd_link_hash_defined, 0))) - return FALSE; + (*info->callbacks->multiple_common) (info, h, abfd, + bfd_link_hash_defined, 0); /* Fall through. */ case DEF: case DEFW: @@ -1575,6 +1560,7 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, h->type = bfd_link_hash_defined; h->u.def.section = section; h->u.def.value = value; + h->linker_def = 0; /* If we have been asked to, we act like collect2 and identify all functions that might be global @@ -1616,10 +1602,9 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, if (oldtype == bfd_link_hash_defweak) abort (); - if (! ((*info->callbacks->constructor) - (info, c == 'I', - h->root.string, abfd, section, value))) - return FALSE; + (*info->callbacks->constructor) (info, c == 'I', + h->root.string, abfd, + section, value); } } } @@ -1674,6 +1659,7 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, } else h->u.c.p->section = section; + h->linker_def = 0; break; case REF: @@ -1687,9 +1673,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, already had a common definition. Use the maximum of the two sizes, and use the section required by the larger symbol. */ BFD_ASSERT (h->type == bfd_link_hash_common); - if (! ((*info->callbacks->multiple_common) - (info, h, abfd, bfd_link_hash_common, value))) - return FALSE; + (*info->callbacks->multiple_common) (info, h, abfd, + bfd_link_hash_common, value); if (value > h->u.c.size) { unsigned int power; @@ -1727,9 +1712,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, case CREF: /* We have found a common definition for a symbol which was already defined. */ - if (! ((*info->callbacks->multiple_common) - (info, h, abfd, bfd_link_hash_common, value))) - return FALSE; + (*info->callbacks->multiple_common) (info, h, abfd, + bfd_link_hash_common, value); break; case MIND: @@ -1740,74 +1724,67 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, /* Fall through. */ case MDEF: /* Handle a multiple definition. */ - if (! ((*info->callbacks->multiple_definition) - (info, h, abfd, section, value))) - return FALSE; + (*info->callbacks->multiple_definition) (info, h, + abfd, section, value); break; case CIND: /* Create an indirect symbol from an existing common symbol. */ BFD_ASSERT (h->type == bfd_link_hash_common); - if (! ((*info->callbacks->multiple_common) - (info, h, abfd, bfd_link_hash_indirect, 0))) - return FALSE; + (*info->callbacks->multiple_common) (info, h, abfd, + bfd_link_hash_indirect, 0); /* Fall through. */ case IND: - /* Create an indirect symbol. */ - { - struct bfd_link_hash_entry *inh; - - /* STRING is the name of the symbol we want to indirect - to. */ - inh = bfd_wrapped_link_hash_lookup (abfd, info, string, TRUE, - copy, FALSE); - if (inh == NULL) + if (inh->type == bfd_link_hash_indirect + && inh->u.i.link == h) + { + (*_bfd_error_handler) + (_("%B: indirect symbol `%s' to `%s' is a loop"), + abfd, name, string); + bfd_set_error (bfd_error_invalid_operation); return FALSE; - if (inh->type == bfd_link_hash_indirect - && inh->u.i.link == h) - { - (*_bfd_error_handler) - (_("%B: indirect symbol `%s' to `%s' is a loop"), - abfd, name, string); - bfd_set_error (bfd_error_invalid_operation); - return FALSE; - } - if (inh->type == bfd_link_hash_new) - { - inh->type = bfd_link_hash_undefined; - inh->u.undef.abfd = abfd; - bfd_link_add_undef (info->hash, inh); - } + } + if (inh->type == bfd_link_hash_new) + { + inh->type = bfd_link_hash_undefined; + inh->u.undef.abfd = abfd; + bfd_link_add_undef (info->hash, inh); + } - /* If the indirect symbol has been referenced, we need to - push the reference down to the symbol we are - referencing. */ - if (h->type != bfd_link_hash_new) - { - row = UNDEF_ROW; - cycle = TRUE; - } + /* If the indirect symbol has been referenced, we need to + push the reference down to the symbol we are referencing. */ + if (h->type != bfd_link_hash_new) + { + /* ??? If inh->type == bfd_link_hash_undefweak this + converts inh to bfd_link_hash_undefined. */ + row = UNDEF_ROW; + cycle = TRUE; + } - h->type = bfd_link_hash_indirect; - h->u.i.link = inh; - } + h->type = bfd_link_hash_indirect; + h->u.i.link = inh; + /* Not setting h = h->u.i.link here means that when cycle is + set above we'll always go to REFC, and then cycle again + to the indirected symbol. This means that any successful + change of an existing symbol to indirect counts as a + reference. ??? That may not be correct when the existing + symbol was defweak. */ break; case SET: /* Add an entry to a set. */ - if (! (*info->callbacks->add_to_set) (info, h, BFD_RELOC_CTOR, - abfd, section, value)) - return FALSE; + (*info->callbacks->add_to_set) (info, h, BFD_RELOC_CTOR, + abfd, section, value); break; case WARNC: - /* Issue a warning and cycle. */ - if (h->u.i.warning != NULL) + /* Issue a warning and cycle, except when the reference is + in LTO IR. */ + if (h->u.i.warning != NULL + && (abfd->flags & BFD_PLUGIN) == 0) { - if (! (*info->callbacks->warning) (info, h->u.i.warning, - h->root.string, abfd, - NULL, 0)) - return FALSE; + (*info->callbacks->warning) (info, h->u.i.warning, + h->root.string, abfd, NULL, 0); /* Only issue a warning once. */ h->u.i.warning = NULL; } @@ -1827,23 +1804,14 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, break; case WARN: - /* Issue a warning. */ - if (! (*info->callbacks->warning) (info, string, h->root.string, - hash_entry_bfd (h), NULL, 0)) - return FALSE; - break; - - case CWARN: - /* Warn if this symbol has been referenced already, - otherwise add a warning. A symbol has been referenced if - the u.undef.next field is not NULL, or it is the tail of the - undefined symbol list. The REF case above helps to - ensure this. */ - if (h->u.undef.next != NULL || info->hash->undefs_tail == h) + /* Warn if this symbol has been referenced already from non-IR, + otherwise add a warning. */ + if ((!info->lto_plugin_active + && (h->u.undef.next != NULL || info->hash->undefs_tail == h)) + || h->non_ir_ref) { - if (! (*info->callbacks->warning) (info, string, h->root.string, - hash_entry_bfd (h), NULL, 0)) - return FALSE; + (*info->callbacks->warning) (info, string, h->root.string, + hash_entry_bfd (h), NULL, 0); break; } /* Fall through. */ @@ -1929,7 +1897,7 @@ _bfd_generic_final_link (bfd *abfd, struct bfd_link_info *info) if (! generic_add_output_symbol (abfd, &outsymalloc, NULL)) return FALSE; - if (info->relocatable) + if (bfd_link_relocatable (info)) { /* Allocate space for the output relocs for each section. */ for (o = abfd->sections; o != NULL; o = o->next) @@ -2159,7 +2127,7 @@ _bfd_generic_link_output_symbols (bfd *output_bfd, /* fall through */ case bfd_link_hash_defined: sym->flags |= BSF_GLOBAL; - sym->flags &=~ BSF_CONSTRUCTOR; + sym->flags &=~ (BSF_WEAK | BSF_CONSTRUCTOR); sym->value = h->root.u.def.value; sym->section = h->root.u.def.section; break; @@ -2233,7 +2201,7 @@ _bfd_generic_link_output_symbols (bfd *output_bfd, break; case discard_sec_merge: output = TRUE; - if (info->relocatable + if (bfd_link_relocatable (info) || ! (sym->section->flags & SEC_MERGE)) break; /* FALLTHROUGH */ @@ -2403,7 +2371,7 @@ _bfd_generic_reloc_link_order (bfd *abfd, { arelent *r; - if (! info->relocatable) + if (! bfd_link_relocatable (info)) abort (); if (sec->orelocation == NULL) abort (); @@ -2434,9 +2402,8 @@ _bfd_generic_reloc_link_order (bfd *abfd, if (h == NULL || ! h->written) { - if (! ((*info->callbacks->unattached_reloc) - (info, link_order->u.reloc.p->u.name, NULL, NULL, 0))) - return FALSE; + (*info->callbacks->unattached_reloc) + (info, link_order->u.reloc.p->u.name, NULL, NULL, 0); bfd_set_error (bfd_error_bad_value); return FALSE; } @@ -2457,7 +2424,7 @@ _bfd_generic_reloc_link_order (bfd *abfd, size = bfd_get_reloc_size (r->howto); buf = (bfd_byte *) bfd_zmalloc (size); - if (buf == NULL) + if (buf == NULL && size != 0) return FALSE; rstat = _bfd_relocate_contents (r->howto, abfd, (bfd_vma) link_order->u.reloc.p->addend, @@ -2470,17 +2437,13 @@ _bfd_generic_reloc_link_order (bfd *abfd, case bfd_reloc_outofrange: abort (); case bfd_reloc_overflow: - if (! ((*info->callbacks->reloc_overflow) - (info, NULL, - (link_order->type == bfd_section_reloc_link_order - ? bfd_section_name (abfd, link_order->u.reloc.p->u.section) - : link_order->u.reloc.p->u.name), - r->howto->name, link_order->u.reloc.p->addend, - NULL, NULL, 0))) - { - free (buf); - return FALSE; - } + (*info->callbacks->reloc_overflow) + (info, NULL, + (link_order->type == bfd_section_reloc_link_order + ? bfd_section_name (abfd, link_order->u.reloc.p->u.section) + : link_order->u.reloc.p->u.name), + r->howto->name, link_order->u.reloc.p->addend, + NULL, NULL, 0); break; } loc = link_order->offset * bfd_octets_per_byte (abfd); @@ -2634,7 +2597,7 @@ default_indirect_link_order (bfd *output_bfd, BFD_ASSERT (input_section->output_offset == link_order->offset); BFD_ASSERT (input_section->size == link_order->size); - if (info->relocatable + if (bfd_link_relocatable (info) && input_section->reloc_count > 0 && output_section->orelocation == NULL) { @@ -2728,7 +2691,7 @@ default_indirect_link_order (bfd *output_bfd, goto error_return; new_contents = (bfd_get_relocated_section_contents (output_bfd, info, link_order, contents, - info->relocatable, + bfd_link_relocatable (info), _bfd_generic_link_get_symbols (input_bfd))); if (!new_contents) goto error_return; @@ -2919,7 +2882,7 @@ _bfd_handle_already_linked (asection *sec, files over IR because the first pass may contain a mix of LTO and normal objects and we must keep the first match, be it IR or real. */ - if (info->loading_lto_outputs + if (sec->owner->lto_output && (l->sec->owner->flags & BFD_PLUGIN) != 0) { l->sec = sec; @@ -3326,3 +3289,46 @@ bfd_hide_sym_by_version (struct bfd_elf_version_tree *verdefs, bfd_find_version_for_sym (verdefs, sym_name, &hidden); return hidden; } + +/* +FUNCTION + bfd_link_check_relocs + +SYNOPSIS + bfd_boolean bfd_link_check_relocs + (bfd *abfd, struct bfd_link_info *info); + +DESCRIPTION + Checks the relocs in ABFD for validity. + Does not execute the relocs. + Return TRUE if everything is OK, FALSE otherwise. + This is the external entry point to this code. +*/ + +bfd_boolean +bfd_link_check_relocs (bfd *abfd, struct bfd_link_info *info) +{ + return BFD_SEND (abfd, _bfd_link_check_relocs, (abfd, info)); +} + +/* +FUNCTION + _bfd_generic_link_check_relocs + +SYNOPSIS + bfd_boolean _bfd_generic_link_check_relocs + (bfd *abfd, struct bfd_link_info *info); + +DESCRIPTION + Stub function for targets that do not implement reloc checking. + Return TRUE. + This is an internal function. It should not be called from + outside the BFD library. +*/ + +bfd_boolean +_bfd_generic_link_check_relocs (bfd *abfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) +{ + return TRUE; +}