X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Flinker.c;h=d4057461a3f4a358f138f3d1b74694160e3c553a;hb=refs%2Fheads%2Fconcurrent-displaced-stepping-2020-04-01;hp=86a7a1945ba7527b4280045c51472d1a9dc44435;hpb=7b7e7f1da28585cfa49cbced50dbbd75a143cd20;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/linker.c b/bfd/linker.c index 86a7a1945b..d4057461a3 100644 --- a/bfd/linker.c +++ b/bfd/linker.c @@ -1,5 +1,5 @@ /* linker.c -- BFD linker routines - Copyright (C) 1993-2015 Free Software Foundation, Inc. + Copyright (C) 1993-2020 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. @@ -403,21 +403,12 @@ SUBSUBSECTION */ static bfd_boolean generic_link_add_object_symbols - (bfd *, struct bfd_link_info *, bfd_boolean collect); -static bfd_boolean generic_link_add_symbols - (bfd *, struct bfd_link_info *, bfd_boolean); -static bfd_boolean generic_link_check_archive_element_no_collect - (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, const char *, - bfd_boolean *); -static bfd_boolean generic_link_check_archive_element_collect - (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, const char *, - bfd_boolean *); + (bfd *, struct bfd_link_info *); static bfd_boolean generic_link_check_archive_element (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, const char *, - bfd_boolean *, bfd_boolean); + bfd_boolean *); static bfd_boolean generic_link_add_symbol_list - (bfd *, struct bfd_link_info *, bfd_size_type count, asymbol **, - bfd_boolean); + (bfd *, struct bfd_link_info *, bfd_size_type count, asymbol **); static bfd_boolean generic_add_output_symbol (bfd *, size_t *psymalloc, asymbol *); static bfd_boolean default_data_link_order @@ -442,7 +433,7 @@ _bfd_link_hash_newfunc (struct bfd_hash_entry *entry, if (entry == NULL) { entry = (struct bfd_hash_entry *) - bfd_hash_allocate (table, sizeof (struct bfd_link_hash_entry)); + bfd_hash_allocate (table, sizeof (struct bfd_link_hash_entry)); if (entry == NULL) return entry; } @@ -493,7 +484,20 @@ _bfd_link_hash_table_init /* Look up a symbol in a link hash table. If follow is TRUE, we follow bfd_link_hash_indirect and bfd_link_hash_warning links to - the real symbol. */ + the real symbol. + +.{* Return TRUE if the symbol described by a linker hash entry H +. is going to be absolute. Linker-script defined symbols can be +. converted from absolute to section-relative ones late in the +. link. Use this macro to correctly determine whether the symbol +. will actually end up absolute in output. *} +.#define bfd_is_abs_symbol(H) \ +. (((H)->type == bfd_link_hash_defined \ +. || (H)->type == bfd_link_hash_defweak) \ +. && bfd_is_abs_section ((H)->u.def.section) \ +. && !(H)->rel_from_abs) +. +*/ struct bfd_link_hash_entry * bfd_link_hash_lookup (struct bfd_link_hash_table *table, @@ -504,6 +508,9 @@ bfd_link_hash_lookup (struct bfd_link_hash_table *table, { struct bfd_link_hash_entry *ret; + if (table == NULL || string == NULL) + return NULL; + ret = ((struct bfd_link_hash_entry *) bfd_hash_lookup (&table->table, string, create, copy)); @@ -529,7 +536,7 @@ bfd_wrapped_link_hash_lookup (bfd *abfd, bfd_boolean copy, bfd_boolean follow) { - bfd_size_type amt; + size_t amt; if (info->wrap_hash != NULL) { @@ -552,7 +559,7 @@ bfd_wrapped_link_hash_lookup (bfd *abfd, struct bfd_link_hash_entry *h; /* This symbol is being wrapped. We want to replace all - references to SYM with references to __wrap_SYM. */ + references to SYM with references to __wrap_SYM. */ amt = strlen (l) + sizeof WRAP + 1; n = (char *) bfd_malloc (amt); @@ -580,8 +587,8 @@ bfd_wrapped_link_hash_lookup (bfd *abfd, struct bfd_link_hash_entry *h; /* This is a reference to __real_SYM, where SYM is being - wrapped. We want to replace all references to __real_SYM - with references to SYM. */ + wrapped. We want to replace all references to __real_SYM + with references to SYM. */ amt = strlen (l + sizeof REAL - 1) + 2; n = (char *) bfd_malloc (amt); @@ -641,7 +648,7 @@ unwrap_hash_lookup (struct bfd_link_info *info, /* Traverse a generic link hash table. Differs from bfd_hash_traverse in the treatment of warning symbols. When warning symbols are created they replace the real symbol, so you don't get to see the - real symbol in a bfd_hash_travere. This traversal calls func with + real symbol in a bfd_hash_traverse. This traversal calls func with the real symbol. */ void @@ -757,7 +764,7 @@ struct bfd_link_hash_table * _bfd_generic_link_hash_table_create (bfd *abfd) { struct generic_link_hash_table *ret; - bfd_size_type amt = sizeof (struct generic_link_hash_table); + size_t amt = sizeof (struct generic_link_hash_table); ret = (struct generic_link_hash_table *) bfd_malloc (amt); if (ret == NULL) @@ -803,42 +810,18 @@ bfd_generic_link_read_symbols (bfd *abfd) symsize = bfd_get_symtab_upper_bound (abfd); if (symsize < 0) return FALSE; - bfd_get_outsymbols (abfd) = (struct bfd_symbol **) bfd_alloc (abfd, - symsize); + abfd->outsymbols = bfd_alloc (abfd, symsize); if (bfd_get_outsymbols (abfd) == NULL && symsize != 0) return FALSE; symcount = bfd_canonicalize_symtab (abfd, bfd_get_outsymbols (abfd)); if (symcount < 0) return FALSE; - bfd_get_symcount (abfd) = symcount; + abfd->symcount = symcount; } return TRUE; } -/* Generic function to add symbols to from an object file to the - global hash table. This version does not automatically collect - constructors by name. */ - -bfd_boolean -_bfd_generic_link_add_symbols (bfd *abfd, struct bfd_link_info *info) -{ - return generic_link_add_symbols (abfd, info, FALSE); -} - -/* Generic function to add symbols from an object file to the global - hash table. This version automatically collects constructors by - name, as the collect2 program does. It should be used for any - target which does not provide some other mechanism for setting up - constructors and destructors; these are approximately those targets - for which gcc uses collect2 and do not support stabs. */ - -bfd_boolean -_bfd_generic_link_add_symbols_collect (bfd *abfd, struct bfd_link_info *info) -{ - return generic_link_add_symbols (abfd, info, TRUE); -} - /* Indicate that we are only retrieving symbol values from this section. We want the symbols to act as though the values in the file are absolute. */ @@ -862,26 +845,22 @@ _bfd_generic_copy_link_hash_symbol_type (bfd *abfd ATTRIBUTE_UNUSED, { } -/* Add symbols from an object file to the global hash table. */ +/* Generic function to add symbols from an object file to the + global hash table. */ -static bfd_boolean -generic_link_add_symbols (bfd *abfd, - struct bfd_link_info *info, - bfd_boolean collect) +bfd_boolean +_bfd_generic_link_add_symbols (bfd *abfd, struct bfd_link_info *info) { bfd_boolean ret; switch (bfd_get_format (abfd)) { case bfd_object: - ret = generic_link_add_object_symbols (abfd, info, collect); + ret = generic_link_add_object_symbols (abfd, info); break; case bfd_archive: ret = (_bfd_generic_link_add_archive_symbols - (abfd, info, - (collect - ? generic_link_check_archive_element_collect - : generic_link_check_archive_element_no_collect))); + (abfd, info, generic_link_check_archive_element)); break; default: bfd_set_error (bfd_error_wrong_format); @@ -895,8 +874,7 @@ generic_link_add_symbols (bfd *abfd, static bfd_boolean generic_link_add_object_symbols (bfd *abfd, - struct bfd_link_info *info, - bfd_boolean collect) + struct bfd_link_info *info) { bfd_size_type symcount; struct bfd_symbol **outsyms; @@ -905,7 +883,7 @@ generic_link_add_object_symbols (bfd *abfd, return FALSE; symcount = _bfd_generic_link_get_symcount (abfd); outsyms = _bfd_generic_link_get_symbols (abfd); - return generic_link_add_symbol_list (abfd, info, symcount, outsyms, collect); + return generic_link_add_symbol_list (abfd, info, symcount, outsyms); } /* Generic function to add symbols from an archive file to the global @@ -978,6 +956,9 @@ _bfd_generic_link_add_archive_symbols continue; } + if (arsym->name == NULL) + goto error_return; + h = bfd_link_hash_lookup (info->hash, arsym->name, FALSE, FALSE, TRUE); @@ -1044,47 +1025,14 @@ _bfd_generic_link_add_archive_symbols return FALSE; } -/* See if we should include an archive element. This version is used - when we do not want to automatically collect constructors based on - the symbol name, presumably because we have some other mechanism - for finding them. */ - -static bfd_boolean -generic_link_check_archive_element_no_collect (bfd *abfd, - struct bfd_link_info *info, - struct bfd_link_hash_entry *h, - const char *name, - bfd_boolean *pneeded) -{ - return generic_link_check_archive_element (abfd, info, h, name, pneeded, - FALSE); -} - -/* See if we should include an archive element. This version is used - when we want to automatically collect constructors based on the - symbol name, as collect2 does. */ - -static bfd_boolean -generic_link_check_archive_element_collect (bfd *abfd, - struct bfd_link_info *info, - struct bfd_link_hash_entry *h, - const char *name, - bfd_boolean *pneeded) -{ - return generic_link_check_archive_element (abfd, info, h, name, pneeded, - TRUE); -} - -/* See if we should include an archive element. Optionally collect - constructors. */ +/* See if we should include an archive element. */ static bfd_boolean generic_link_check_archive_element (bfd *abfd, struct bfd_link_info *info, struct bfd_link_hash_entry *h, const char *name ATTRIBUTE_UNUSED, - bfd_boolean *pneeded, - bfd_boolean collect) + bfd_boolean *pneeded) { asymbol **pp, **ppend; @@ -1134,7 +1082,7 @@ generic_link_check_archive_element (bfd *abfd, return FALSE; /* Potentially, the add_archive_element hook may have set a substitute BFD for us. */ - return generic_link_add_object_symbols (abfd, info, collect); + return bfd_link_add_symbols (abfd, info); } /* P is a common symbol. */ @@ -1192,16 +1140,13 @@ generic_link_check_archive_element (bfd *abfd, /* Add the symbols from an object file to the global hash table. ABFD is the object file. INFO is the linker information. SYMBOL_COUNT - is the number of symbols. SYMBOLS is the list of symbols. COLLECT - is TRUE if constructors should be automatically collected by name - as is done by collect2. */ + is the number of symbols. SYMBOLS is the list of symbols. */ static bfd_boolean generic_link_add_symbol_list (bfd *abfd, struct bfd_link_info *info, bfd_size_type symbol_count, - asymbol **symbols, - bfd_boolean collect) + asymbol **symbols) { asymbol **pp, **ppend; @@ -1218,9 +1163,9 @@ generic_link_add_symbol_list (bfd *abfd, | BSF_GLOBAL | BSF_CONSTRUCTOR | BSF_WEAK)) != 0 - || bfd_is_und_section (bfd_get_section (p)) - || bfd_is_com_section (bfd_get_section (p)) - || bfd_is_ind_section (bfd_get_section (p))) + || bfd_is_und_section (bfd_asymbol_section (p)) + || bfd_is_com_section (bfd_asymbol_section (p)) + || bfd_is_ind_section (bfd_asymbol_section (p))) { const char *name; const char *string; @@ -1246,15 +1191,15 @@ generic_link_add_symbol_list (bfd *abfd, bh = NULL; if (! (_bfd_generic_link_add_one_symbol - (info, abfd, name, p->flags, bfd_get_section (p), - p->value, string, FALSE, collect, &bh))) + (info, abfd, name, p->flags, bfd_asymbol_section (p), + p->value, string, FALSE, FALSE, &bh))) return FALSE; h = (struct generic_link_hash_entry *) bh; /* If this is a constructor symbol, and the linker didn't do - anything with it, then we want to just pass the symbol - through to the output file. This will happen when - linking with -r. */ + anything with it, then we want to just pass the symbol + through to the output file. This will happen when + linking with -r. */ if ((p->flags & BSF_CONSTRUCTOR) != 0 && (h == NULL || h->root.type == bfd_link_hash_new)) { @@ -1273,15 +1218,15 @@ generic_link_add_symbol_list (bfd *abfd, if (info->output_bfd->xvec == abfd->xvec) { if (h->sym == NULL - || (! bfd_is_und_section (bfd_get_section (p)) - && (! bfd_is_com_section (bfd_get_section (p)) - || bfd_is_und_section (bfd_get_section (h->sym))))) + || (! bfd_is_und_section (bfd_asymbol_section (p)) + && (! bfd_is_com_section (bfd_asymbol_section (p)) + || bfd_is_und_section (bfd_asymbol_section (h->sym))))) { h->sym = p; /* BSF_OLD_COMMON is a hack to support COFF reloc reading, and it should go away when the COFF linker is switched to the new version. */ - if (bfd_is_com_section (bfd_get_section (p))) + if (bfd_is_com_section (bfd_asymbol_section (p))) p->flags |= BSF_OLD_COMMON; } } @@ -1354,10 +1299,10 @@ enum link_action static const enum link_action link_action[8][8] = { /* current\prev new undef undefw def defw com indr warn */ - /* UNDEF_ROW */ {UND, NOACT, UND, REF, REF, NOACT, REFC, WARNC }, + /* UNDEF_ROW */ {UND, NOACT, UND, REF, REF, NOACT, REFC, WARNC }, /* UNDEFW_ROW */ {WEAK, NOACT, NOACT, REF, REF, NOACT, REFC, WARNC }, - /* DEF_ROW */ {DEF, DEF, DEF, MDEF, DEF, CDEF, MDEF, CYCLE }, - /* DEFW_ROW */ {DEFW, DEFW, DEFW, NOACT, NOACT, NOACT, NOACT, CYCLE }, + /* DEF_ROW */ {DEF, DEF, DEF, MDEF, DEF, CDEF, MDEF, CYCLE }, + /* 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, WARN, WARN, WARN, WARN, NOACT }, @@ -1475,10 +1420,12 @@ _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) - (*_bfd_error_handler) - (_("%s: plugin needed to handle lto object"), - bfd_get_filename (abfd)); + if (!bfd_link_relocatable (info) + && name[0] == '_' + && name[1] == '_' + && strcmp (name + (name[2] == '_'), "__gnu_lto_slim") == 0) + _bfd_error_handler + (_("%pB: plugin needed to handle lto object"), abfd); } else row = DEF_ROW; @@ -1514,9 +1461,14 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, do { enum link_action action; + int prev; + prev = h->type; + /* Treat symbols defined by early linker script pass as undefined. */ + if (h->ldscript_def) + prev = bfd_link_hash_undefined; cycle = FALSE; - action = link_action[(int) row][(int) h->type]; + action = link_action[(int) row][prev]; switch (action) { case FAIL: @@ -1543,9 +1495,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: @@ -1561,6 +1512,7 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, h->u.def.section = section; h->u.def.value = value; h->linker_def = 0; + h->ldscript_def = 0; /* If we have been asked to, we act like collect2 and identify all functions that might be global @@ -1593,19 +1545,18 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, && s[CONS_PREFIX_LEN] == s[CONS_PREFIX_LEN + 2]) { /* If this is a definition of a symbol which - was previously weakly defined, we are in - trouble. We have already added a - constructor entry for the weak defined - symbol, and now we are trying to add one - for the new symbol. Fortunately, this case - should never arise in practice. */ + was previously weakly defined, we are in + trouble. We have already added a + constructor entry for the weak defined + symbol, and now we are trying to add one + for the new symbol. Fortunately, this case + should never arise in practice. */ 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); } } } @@ -1627,7 +1578,7 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, h->u.c.size = value; /* Select a default alignment based on the size. This may - be overridden by the caller. */ + be overridden by the caller. */ { unsigned int power; @@ -1638,15 +1589,15 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, } /* The section of a common symbol is only used if the common - symbol is actually allocated. It basically provides a - hook for the linker script to decide which output section - the common symbols should be put in. In most cases, the - section of a common symbol will be bfd_com_section_ptr, - the code here will choose a common symbol section named - "COMMON", and the linker script will contain *(COMMON) in - the appropriate place. A few targets use separate common - sections for small symbols, and they require special - handling. */ + symbol is actually allocated. It basically provides a + hook for the linker script to decide which output section + the common symbols should be put in. In most cases, the + section of a common symbol will be bfd_com_section_ptr, + the code here will choose a common symbol section named + "COMMON", and the linker script will contain *(COMMON) in + the appropriate place. A few targets use separate common + sections for small symbols, and they require special + handling. */ if (section == bfd_com_section_ptr) { h->u.c.p->section = bfd_make_section_old_way (abfd, "COMMON"); @@ -1661,6 +1612,7 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, else h->u.c.p->section = section; h->linker_def = 0; + h->ldscript_def = 0; break; case REF: @@ -1674,9 +1626,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; @@ -1714,9 +1665,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: @@ -1727,24 +1677,23 @@ _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: if (inh->type == bfd_link_hash_indirect && inh->u.i.link == h) { - (*_bfd_error_handler) - (_("%B: indirect symbol `%s' to `%s' is a loop"), + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: indirect symbol `%s' to `%s' is a loop"), abfd, name, string); bfd_set_error (bfd_error_invalid_operation); return FALSE; @@ -1778,9 +1727,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, 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: @@ -1789,10 +1737,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, 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; } @@ -1816,11 +1762,11 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, otherwise add a warning. */ if ((!info->lto_plugin_active && (h->u.undef.next != NULL || info->hash->undefs_tail == h)) - || h->non_ir_ref) + || h->non_ir_ref_regular + || h->non_ir_ref_dynamic) { - 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. */ @@ -1877,8 +1823,8 @@ _bfd_generic_final_link (bfd *abfd, struct bfd_link_info *info) size_t outsymalloc; struct generic_write_global_symbol_info wginfo; - bfd_get_outsymbols (abfd) = NULL; - bfd_get_symcount (abfd) = 0; + abfd->outsymbols = NULL; + abfd->symcount = 0; outsymalloc = 0; /* Mark all sections which will be included in the output file. */ @@ -2011,12 +1957,12 @@ generic_add_output_symbol (bfd *output_bfd, size_t *psymalloc, asymbol *sym) newsyms = (asymbol **) bfd_realloc (bfd_get_outsymbols (output_bfd), amt); if (newsyms == NULL) return FALSE; - bfd_get_outsymbols (output_bfd) = newsyms; + output_bfd->outsymbols = newsyms; } - bfd_get_outsymbols (output_bfd) [bfd_get_symcount (output_bfd)] = sym; + output_bfd->outsymbols[output_bfd->symcount] = sym; if (sym != NULL) - ++ bfd_get_symcount (output_bfd); + ++output_bfd->symcount; return TRUE; } @@ -2049,7 +1995,7 @@ _bfd_generic_link_output_symbols (bfd *output_bfd, newsym = bfd_make_empty_symbol (input_bfd); if (!newsym) return FALSE; - newsym->name = input_bfd->filename; + newsym->name = bfd_get_filename (input_bfd); newsym->value = 0; newsym->flags = BSF_LOCAL | BSF_FILE; newsym->section = sec; @@ -2080,25 +2026,25 @@ _bfd_generic_link_output_symbols (bfd *output_bfd, | BSF_GLOBAL | BSF_CONSTRUCTOR | BSF_WEAK)) != 0 - || bfd_is_und_section (bfd_get_section (sym)) - || bfd_is_com_section (bfd_get_section (sym)) - || bfd_is_ind_section (bfd_get_section (sym))) + || bfd_is_und_section (bfd_asymbol_section (sym)) + || bfd_is_com_section (bfd_asymbol_section (sym)) + || bfd_is_ind_section (bfd_asymbol_section (sym))) { if (sym->udata.p != NULL) h = (struct generic_link_hash_entry *) sym->udata.p; else if ((sym->flags & BSF_CONSTRUCTOR) != 0) { /* This case normally means that the main linker code - deliberately ignored this constructor symbol. We - should just pass it through. This will screw up if - the constructor symbol is from a different, - non-generic, object file format, but the case will - only arise when linking with -r, which will probably - fail anyhow, since there will be no way to represent - the relocs in the output format being used. */ + deliberately ignored this constructor symbol. We + should just pass it through. This will screw up if + the constructor symbol is from a different, + non-generic, object file format, but the case will + only arise when linking with -r, which will probably + fail anyhow, since there will be no way to represent + the relocs in the output format being used. */ h = NULL; } - else if (bfd_is_und_section (bfd_get_section (sym))) + else if (bfd_is_und_section (bfd_asymbol_section (sym))) h = ((struct generic_link_hash_entry *) bfd_wrapped_link_hash_lookup (output_bfd, info, bfd_asymbol_name (sym), @@ -2165,14 +2111,13 @@ _bfd_generic_link_output_symbols (bfd *output_bfd, } } - /* This switch is straight from the old code in - write_file_locals in ldsym.c. */ - if (info->strip == strip_all - || (info->strip == strip_some - && bfd_hash_lookup (info->keep_hash, bfd_asymbol_name (sym), - FALSE, FALSE) == NULL)) + if ((sym->flags & BSF_KEEP) == 0 + && (info->strip == strip_all + || (info->strip == strip_some + && bfd_hash_lookup (info->keep_hash, bfd_asymbol_name (sym), + FALSE, FALSE) == NULL))) output = FALSE; - else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0) + else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0) { /* If this symbol is marked as occurring now, rather than at the end, output it now. This is used for @@ -2184,6 +2129,8 @@ _bfd_generic_link_output_symbols (bfd *output_bfd, else output = FALSE; } + else if ((sym->flags & BSF_KEEP) != 0) + output = TRUE; else if (bfd_is_ind_section (sym->section)) output = FALSE; else if ((sym->flags & BSF_DEBUGGING) != 0) @@ -2275,7 +2222,7 @@ set_symbol_from_hash (asymbol *sym, struct bfd_link_hash_entry *h) break; case bfd_link_hash_new: /* This can happen when a constructor symbol is seen but we are - not building constructors. */ + not building constructors. */ if (sym->section != NULL) { BFD_ASSERT ((sym->flags & BSF_CONSTRUCTOR) != 0); @@ -2411,9 +2358,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; } @@ -2447,20 +2393,16 @@ _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 (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); + loc = link_order->offset * bfd_octets_per_byte (abfd, sec); ok = bfd_set_section_contents (abfd, sec, buf, loc, size); free (buf); if (! ok) @@ -2480,7 +2422,7 @@ _bfd_generic_reloc_link_order (bfd *abfd, struct bfd_link_order * bfd_new_link_order (bfd *abfd, asection *section) { - bfd_size_type amt = sizeof (struct bfd_link_order); + size_t amt = sizeof (struct bfd_link_order); struct bfd_link_order *new_lo; new_lo = (struct bfd_link_order *) bfd_zalloc (abfd, amt); @@ -2527,7 +2469,7 @@ _bfd_default_link_order (bfd *abfd, static bfd_boolean default_data_link_order (bfd *abfd, - struct bfd_link_info *info ATTRIBUTE_UNUSED, + struct bfd_link_info *info, asection *sec, struct bfd_link_order *link_order) { @@ -2547,7 +2489,7 @@ default_data_link_order (bfd *abfd, fill_size = link_order->u.data.size; if (fill_size == 0) { - fill = abfd->arch_info->fill (size, bfd_big_endian (abfd), + fill = abfd->arch_info->fill (size, info->big_endian, (sec->flags & SEC_CODE) != 0); if (fill == NULL) return FALSE; @@ -2576,7 +2518,7 @@ default_data_link_order (bfd *abfd, } } - loc = link_order->offset * bfd_octets_per_byte (abfd); + loc = link_order->offset * bfd_octets_per_byte (abfd, sec); result = bfd_set_section_contents (abfd, sec, fill, loc, size); if (fill != link_order->u.data.contents) @@ -2620,8 +2562,9 @@ default_indirect_link_order (bfd *output_bfd, because somebody is attempting to link together different types of object files. Handling this case correctly is difficult, and sometimes impossible. */ - (*_bfd_error_handler) - (_("Attempt to do relocatable link with %s input and %s output"), + _bfd_error_handler + /* xgettext:c-format */ + (_("attempt to do relocatable link with %s input and %s output"), bfd_get_target (input_bfd), bfd_get_target (output_bfd)); bfd_set_error (bfd_error_wrong_format); return FALSE; @@ -2658,15 +2601,15 @@ default_indirect_link_order (bfd *output_bfd, | BSF_GLOBAL | BSF_CONSTRUCTOR | BSF_WEAK)) != 0 - || bfd_is_und_section (bfd_get_section (sym)) - || bfd_is_com_section (bfd_get_section (sym)) - || bfd_is_ind_section (bfd_get_section (sym))) + || bfd_is_und_section (bfd_asymbol_section (sym)) + || bfd_is_com_section (bfd_asymbol_section (sym)) + || bfd_is_ind_section (bfd_asymbol_section (sym))) { /* sym->udata may have been set by generic_link_add_symbol_list. */ if (sym->udata.p != NULL) h = (struct bfd_link_hash_entry *) sym->udata.p; - else if (bfd_is_und_section (bfd_get_section (sym))) + else if (bfd_is_und_section (bfd_asymbol_section (sym))) h = bfd_wrapped_link_hash_lookup (output_bfd, info, bfd_asymbol_name (sym), FALSE, FALSE, TRUE); @@ -2712,18 +2655,17 @@ default_indirect_link_order (bfd *output_bfd, } /* Output the section contents. */ - loc = input_section->output_offset * bfd_octets_per_byte (output_bfd); + loc = (input_section->output_offset + * bfd_octets_per_byte (output_bfd, output_section)); if (! bfd_set_section_contents (output_bfd, output_section, new_contents, loc, input_section->size)) goto error_return; - if (contents != NULL) - free (contents); + free (contents); return TRUE; error_return: - if (contents != NULL) - free (contents); + free (contents); return FALSE; } @@ -2752,14 +2694,14 @@ FUNCTION bfd_link_split_section SYNOPSIS - bfd_boolean bfd_link_split_section (bfd *abfd, asection *sec); + bfd_boolean bfd_link_split_section (bfd *abfd, asection *sec); DESCRIPTION Return nonzero if @var{sec} should be split during a reloceatable or final link. .#define bfd_link_split_section(abfd, sec) \ -. BFD_SEND (abfd, _bfd_link_split_section, (abfd, sec)) +. BFD_SEND (abfd, _bfd_link_split_section, (abfd, sec)) . */ @@ -2776,7 +2718,7 @@ FUNCTION bfd_section_already_linked SYNOPSIS - bfd_boolean bfd_section_already_linked (bfd *abfd, + bfd_boolean bfd_section_already_linked (bfd *abfd, asection *sec, struct bfd_link_info *info); @@ -2785,7 +2727,7 @@ DESCRIPTION or final link. Return TRUE if it has. .#define bfd_section_already_linked(abfd, sec, info) \ -. BFD_SEND (abfd, _section_already_linked, (abfd, sec, info)) +. BFD_SEND (abfd, _section_already_linked, (abfd, sec, info)) . */ @@ -2906,7 +2848,8 @@ _bfd_handle_already_linked (asection *sec, case SEC_LINK_DUPLICATES_ONE_ONLY: info->callbacks->einfo - (_("%B: ignoring duplicate section `%A'\n"), + /* xgettext:c-format */ + (_("%pB: ignoring duplicate section `%pA'\n"), sec->owner, sec); break; @@ -2915,7 +2858,8 @@ _bfd_handle_already_linked (asection *sec, ; else if (sec->size != l->sec->size) info->callbacks->einfo - (_("%B: duplicate section `%A' has different size\n"), + /* xgettext:c-format */ + (_("%pB: duplicate section `%pA' has different size\n"), sec->owner, sec); break; @@ -2924,7 +2868,8 @@ _bfd_handle_already_linked (asection *sec, ; else if (sec->size != l->sec->size) info->callbacks->einfo - (_("%B: duplicate section `%A' has different size\n"), + /* xgettext:c-format */ + (_("%pB: duplicate section `%pA' has different size\n"), sec->owner, sec); else if (sec->size != 0) { @@ -2932,22 +2877,23 @@ _bfd_handle_already_linked (asection *sec, if (!bfd_malloc_and_get_section (sec->owner, sec, &sec_contents)) info->callbacks->einfo - (_("%B: could not read contents of section `%A'\n"), + /* xgettext:c-format */ + (_("%pB: could not read contents of section `%pA'\n"), sec->owner, sec); else if (!bfd_malloc_and_get_section (l->sec->owner, l->sec, &l_sec_contents)) info->callbacks->einfo - (_("%B: could not read contents of section `%A'\n"), + /* xgettext:c-format */ + (_("%pB: could not read contents of section `%pA'\n"), l->sec->owner, l->sec); else if (memcmp (sec_contents, l_sec_contents, sec->size) != 0) info->callbacks->einfo - (_("%B: duplicate section `%A' has different contents\n"), + /* xgettext:c-format */ + (_("%pB: duplicate section `%pA' has different contents\n"), sec->owner, sec); - if (sec_contents) - free (sec_contents); - if (l_sec_contents) - free (l_sec_contents); + free (sec_contents); + free (l_sec_contents); } break; } @@ -2993,7 +2939,7 @@ _bfd_generic_section_already_linked (bfd *abfd ATTRIBUTE_UNUSED, into a single large link once section, which defeats the purpose of having link once sections in the first place. */ - name = bfd_get_section_name (abfd, sec); + name = bfd_section_name (sec); already_linked_list = bfd_section_already_linked_table_lookup (name); @@ -3129,7 +3075,7 @@ DESCRIPTION Return TRUE on success and FALSE on failure. .#define bfd_define_common_symbol(output_bfd, info, h) \ -. BFD_SEND (output_bfd, _bfd_define_common_symbol, (output_bfd, info, h)) +. BFD_SEND (output_bfd, _bfd_define_common_symbol, (output_bfd, info, h)) . */ @@ -3150,7 +3096,7 @@ bfd_generic_define_common_symbol (bfd *output_bfd, /* Increase the size of the section to align the common symbol. The alignment must be a power of two. */ - alignment = bfd_octets_per_byte (output_bfd) << power_of_two; + alignment = bfd_octets_per_byte (output_bfd, section) << power_of_two; BFD_ASSERT (alignment != 0 && (alignment & -alignment) == alignment); section->size += alignment - 1; section->size &= -alignment; @@ -3170,10 +3116,73 @@ bfd_generic_define_common_symbol (bfd *output_bfd, /* Make sure the section is allocated in memory, and make sure that it is no longer a common section. */ section->flags |= SEC_ALLOC; - section->flags &= ~SEC_IS_COMMON; + section->flags &= ~(SEC_IS_COMMON | SEC_HAS_CONTENTS); return TRUE; } +/* +FUNCTION + _bfd_generic_link_hide_symbol + +SYNOPSIS + void _bfd_generic_link_hide_symbol + (bfd *output_bfd, struct bfd_link_info *info, + struct bfd_link_hash_entry *h); + +DESCRIPTION + Hide symbol @var{h}. + This is an internal function. It should not be called from + outside the BFD library. + +.#define bfd_link_hide_symbol(output_bfd, info, h) \ +. BFD_SEND (output_bfd, _bfd_link_hide_symbol, (output_bfd, info, h)) +. +*/ + +void +_bfd_generic_link_hide_symbol (bfd *output_bfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED, + struct bfd_link_hash_entry *h ATTRIBUTE_UNUSED) +{ +} + +/* +FUNCTION + bfd_generic_define_start_stop + +SYNOPSIS + struct bfd_link_hash_entry *bfd_generic_define_start_stop + (struct bfd_link_info *info, + const char *symbol, asection *sec); + +DESCRIPTION + Define a __start, __stop, .startof. or .sizeof. symbol. + Return the symbol or NULL if no such undefined symbol exists. + +.#define bfd_define_start_stop(output_bfd, info, symbol, sec) \ +. BFD_SEND (output_bfd, _bfd_define_start_stop, (info, symbol, sec)) +. +*/ + +struct bfd_link_hash_entry * +bfd_generic_define_start_stop (struct bfd_link_info *info, + const char *symbol, asection *sec) +{ + struct bfd_link_hash_entry *h; + + h = bfd_link_hash_lookup (info->hash, symbol, FALSE, FALSE, TRUE); + if (h != NULL + && (h->type == bfd_link_hash_undefined + || h->type == bfd_link_hash_undefweak)) + { + h->type = bfd_link_hash_defined; + h->u.def.section = sec; + h->u.def.value = 0; + return h; + } + return NULL; +} + /* FUNCTION bfd_find_version_for_sym @@ -3303,3 +3312,211 @@ 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; +} + +/* +FUNCTION + bfd_merge_private_bfd_data + +SYNOPSIS + bfd_boolean bfd_merge_private_bfd_data + (bfd *ibfd, struct bfd_link_info *info); + +DESCRIPTION + Merge private BFD information from the BFD @var{ibfd} to the + the output file BFD when linking. Return <> on success, + <> on error. Possible error returns are: + + o <> - + Not enough memory exists to create private data for @var{obfd}. + +.#define bfd_merge_private_bfd_data(ibfd, info) \ +. BFD_SEND ((info)->output_bfd, _bfd_merge_private_bfd_data, \ +. (ibfd, info)) +*/ + +/* +INTERNAL_FUNCTION + _bfd_generic_verify_endian_match + +SYNOPSIS + bfd_boolean _bfd_generic_verify_endian_match + (bfd *ibfd, struct bfd_link_info *info); + +DESCRIPTION + Can be used from / for bfd_merge_private_bfd_data to check that + endianness matches between input and output file. Returns + TRUE for a match, otherwise returns FALSE and emits an error. +*/ + +bfd_boolean +_bfd_generic_verify_endian_match (bfd *ibfd, struct bfd_link_info *info) +{ + bfd *obfd = info->output_bfd; + + if (ibfd->xvec->byteorder != obfd->xvec->byteorder + && ibfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN + && obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN) + { + if (bfd_big_endian (ibfd)) + _bfd_error_handler (_("%pB: compiled for a big endian system " + "and target is little endian"), ibfd); + else + _bfd_error_handler (_("%pB: compiled for a little endian system " + "and target is big endian"), ibfd); + bfd_set_error (bfd_error_wrong_format); + return FALSE; + } + + return TRUE; +} + +int +_bfd_nolink_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) +{ + return 0; +} + +bfd_boolean +_bfd_nolink_bfd_relax_section (bfd *abfd, + asection *section ATTRIBUTE_UNUSED, + struct bfd_link_info *link_info ATTRIBUTE_UNUSED, + bfd_boolean *again ATTRIBUTE_UNUSED) +{ + return _bfd_bool_bfd_false_error (abfd); +} + +bfd_byte * +_bfd_nolink_bfd_get_relocated_section_contents + (bfd *abfd, + struct bfd_link_info *link_info ATTRIBUTE_UNUSED, + struct bfd_link_order *link_order ATTRIBUTE_UNUSED, + bfd_byte *data ATTRIBUTE_UNUSED, + bfd_boolean relocatable ATTRIBUTE_UNUSED, + asymbol **symbols ATTRIBUTE_UNUSED) +{ + return (bfd_byte *) _bfd_ptr_bfd_null_error (abfd); +} + +bfd_boolean +_bfd_nolink_bfd_lookup_section_flags + (struct bfd_link_info *info ATTRIBUTE_UNUSED, + struct flag_info *flaginfo ATTRIBUTE_UNUSED, + asection *section) +{ + return _bfd_bool_bfd_false_error (section->owner); +} + +bfd_boolean +_bfd_nolink_bfd_is_group_section (bfd *abfd, + const asection *sec ATTRIBUTE_UNUSED) +{ + return _bfd_bool_bfd_false_error (abfd); +} + +const char * +_bfd_nolink_bfd_group_name (bfd *abfd, + const asection *sec ATTRIBUTE_UNUSED) +{ + return _bfd_ptr_bfd_null_error (abfd); +} + +bfd_boolean +_bfd_nolink_bfd_discard_group (bfd *abfd, asection *sec ATTRIBUTE_UNUSED) +{ + return _bfd_bool_bfd_false_error (abfd); +} + +struct bfd_link_hash_table * +_bfd_nolink_bfd_link_hash_table_create (bfd *abfd) +{ + return (struct bfd_link_hash_table *) _bfd_ptr_bfd_null_error (abfd); +} + +void +_bfd_nolink_bfd_link_just_syms (asection *sec ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) +{ +} + +void +_bfd_nolink_bfd_copy_link_hash_symbol_type + (bfd *abfd ATTRIBUTE_UNUSED, + struct bfd_link_hash_entry *from ATTRIBUTE_UNUSED, + struct bfd_link_hash_entry *to ATTRIBUTE_UNUSED) +{ +} + +bfd_boolean +_bfd_nolink_bfd_link_split_section (bfd *abfd, asection *sec ATTRIBUTE_UNUSED) +{ + return _bfd_bool_bfd_false_error (abfd); +} + +bfd_boolean +_bfd_nolink_section_already_linked (bfd *abfd, + asection *sec ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) +{ + return _bfd_bool_bfd_false_error (abfd); +} + +bfd_boolean +_bfd_nolink_bfd_define_common_symbol + (bfd *abfd, + struct bfd_link_info *info ATTRIBUTE_UNUSED, + struct bfd_link_hash_entry *h ATTRIBUTE_UNUSED) +{ + return _bfd_bool_bfd_false_error (abfd); +} + +struct bfd_link_hash_entry * +_bfd_nolink_bfd_define_start_stop (struct bfd_link_info *info ATTRIBUTE_UNUSED, + const char *name ATTRIBUTE_UNUSED, + asection *sec) +{ + return (struct bfd_link_hash_entry *) _bfd_ptr_bfd_null_error (sec->owner); +}