X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felflink.c;h=07b79013d90c710def29183b29a3b2d3541b8305;hb=65ac99a581582031008a48b70fcf6952dee26af2;hp=1cfdd313569ae80addfe461dfb8f2894d95b5b72;hpb=1cce69b9dc8c58884c3cc4a8928fb234294e6886;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elflink.c b/bfd/elflink.c index 1cfdd31356..07b79013d9 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -1,5 +1,5 @@ /* ELF linking support for BFD. - Copyright (C) 1995-2015 Free Software Foundation, Inc. + Copyright (C) 1995-2016 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -28,6 +28,10 @@ #include "safe-ctype.h" #include "libiberty.h" #include "objalloc.h" +#if BFD_SUPPORTS_PLUGINS +#include "plugin-api.h" +#include "plugin.h" +#endif /* This struct is used to pass information to routines called via elf_link_hash_traverse which must return failure. */ @@ -145,8 +149,7 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info) struct elf_link_hash_table *htab = elf_hash_table (info); /* This function may be called more than once. */ - s = bfd_get_linker_section (abfd, ".got"); - if (s != NULL) + if (htab->sgot != NULL) return TRUE; flags = bed->dynamic_sec_flags; @@ -204,7 +207,24 @@ _bfd_elf_link_create_dynstrtab (bfd *abfd, struct bfd_link_info *info) hash_table = elf_hash_table (info); if (hash_table->dynobj == NULL) - hash_table->dynobj = abfd; + { + /* We may not set dynobj, an input file holding linker created + dynamic sections to abfd, which may be a dynamic object with + its own dynamic sections. We need to find a normal input file + to hold linker created sections if possible. */ + if ((abfd->flags & (DYNAMIC | BFD_PLUGIN)) != 0) + { + bfd *ibfd; + for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link.next) + if ((ibfd->flags + & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0) + { + abfd = ibfd; + break; + } + } + hash_table->dynobj = abfd; + } if (hash_table->dynstr == NULL) { @@ -451,7 +471,7 @@ bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *info, struct elf_strtab_hash *dynstr; char *p; const char *name; - bfd_size_type indx; + size_t indx; /* XXX: The ABI draft says the linker must turn hidden and internal symbols into STB_LOCAL symbols when producing the @@ -502,7 +522,7 @@ bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *info, if (p != NULL) *p = ELF_VER_CHR; - if (indx == (bfd_size_type) -1) + if (indx == (size_t) -1) return FALSE; h->dynstr_index = indx; } @@ -525,8 +545,10 @@ bfd_elf_link_mark_dynamic_symbol (struct bfd_link_info *info, if ((info->dynamic_data && (h->type == STT_OBJECT + || h->type == STT_COMMON || (sym != NULL - && ELF_ST_TYPE (sym->st_info) == STT_OBJECT))) + && (ELF_ST_TYPE (sym->st_info) == STT_OBJECT + || ELF_ST_TYPE (sym->st_info) == STT_COMMON)))) || (d != NULL && h->root.type == bfd_link_hash_new && (*d->match) (&d->head, NULL, h->root.root.string))) @@ -555,6 +577,22 @@ bfd_elf_record_link_assignment (bfd *output_bfd, if (h == NULL) return provide; + if (h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + + if (h->versioned == unknown) + { + /* Set versioned if symbol version is unknown. */ + char *version = strrchr (name, ELF_VER_CHR); + if (version) + { + if (version > name && version[-1] != ELF_VER_CHR) + h->versioned = versioned_hidden; + else + h->versioned = versioned; + } + } + switch (h->root.type) { case bfd_link_hash_defined: @@ -589,9 +627,9 @@ bfd_elf_record_link_assignment (bfd *output_bfd, hv->root.u.i.link = (struct bfd_link_hash_entry *) h; (*bed->elf_backend_copy_indirect_symbol) (info, h, hv); break; - case bfd_link_hash_warning: - abort (); - break; + default: + BFD_FAIL (); + return FALSE; } /* If this symbol is being provided by the linker script, and it is @@ -632,9 +670,8 @@ bfd_elf_record_link_assignment (bfd *output_bfd, if ((h->def_dynamic || h->ref_dynamic - || bfd_link_pic (info) - || (bfd_link_pde (info) - && elf_hash_table (info)->is_relocatable_executable)) + || bfd_link_dll (info) + || elf_hash_table (info)->is_relocatable_executable) && h->dynindx == -1) { if (! bfd_elf_link_record_dynamic_symbol (info, h)) @@ -667,7 +704,7 @@ bfd_elf_link_record_local_dynamic_symbol (struct bfd_link_info *info, struct elf_link_local_dynamic_entry *entry; struct elf_link_hash_table *eht; struct elf_strtab_hash *dynstr; - unsigned long dynstr_index; + size_t dynstr_index; char *name; Elf_External_Sym_Shndx eshndx; char esym[sizeof (Elf64_External_Sym)]; @@ -722,7 +759,7 @@ bfd_elf_link_record_local_dynamic_symbol (struct bfd_link_info *info, } dynstr_index = _bfd_elf_strtab_add (dynstr, name, FALSE); - if (dynstr_index == (unsigned long) -1) + if (dynstr_index == (size_t) -1) return 0; entry->isym.st_name = dynstr_index; @@ -869,16 +906,17 @@ _bfd_elf_link_renumber_dynsyms (bfd *output_bfd, for (p = elf_hash_table (info)->dynlocal; p ; p = p->next) p->dynindx = ++dynsymcount; } + elf_hash_table (info)->local_dynsymcount = dynsymcount; elf_link_hash_traverse (elf_hash_table (info), elf_link_renumber_hash_table_dynsyms, &dynsymcount); - /* There is an unused NULL entry at the head of the table which - we must account for in our count. Unless there weren't any - symbols, which means we'll have no table at all. */ - if (dynsymcount != 0) - ++dynsymcount; + /* There is an unused NULL entry at the head of the table which we + must account for in our count even if the table is empty since it + is intended for the mandatory DT_SYMTAB tag (.dynsym section) in + .dynamic section. */ + dynsymcount++; elf_hash_table (info)->dynsymcount = dynsymcount; return dynsymcount; @@ -1171,21 +1209,20 @@ _bfd_elf_merge_symbol (bfd *abfd, oldfunc = (h->type != STT_NOTYPE && bed->is_function_type (h->type)); - /* When we try to create a default indirect symbol from the dynamic - definition with the default version, we skip it if its type and - the type of existing regular definition mismatch. */ + /* If creating a default indirect symbol ("foo" or "foo@") from a + dynamic versioned definition ("foo@@") skip doing so if there is + an existing regular definition with a different type. We don't + want, for example, a "time" variable in the executable overriding + a "time" function in a shared library. */ if (pold_alignment == NULL && newdyn && newdef && !olddyn - && (((olddef || h->root.type == bfd_link_hash_common) - && ELF_ST_TYPE (sym->st_info) != h->type - && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE - && h->type != STT_NOTYPE - && !(newfunc && oldfunc)) - || (olddef - && ((h->type == STT_GNU_IFUNC) - != (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC))))) + && (olddef || h->root.type == bfd_link_hash_common) + && ELF_ST_TYPE (sym->st_info) != h->type + && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE + && h->type != STT_NOTYPE + && !(newfunc && oldfunc)) { *skip = TRUE; return TRUE; @@ -1224,22 +1261,26 @@ _bfd_elf_merge_symbol (bfd *abfd, } if (tdef && ntdef) - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%s: TLS definition in %B section %A " "mismatches non-TLS definition in %B section %A"), tbfd, tsec, ntbfd, ntsec, h->root.root.string); else if (!tdef && !ntdef) - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%s: TLS reference in %B " "mismatches non-TLS reference in %B"), tbfd, ntbfd, h->root.root.string); else if (tdef) - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%s: TLS definition in %B section %A " "mismatches non-TLS reference in %B"), tbfd, tsec, ntbfd, h->root.root.string); else - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%s: TLS reference in %B " "mismatches non-TLS definition in %B section %A"), tbfd, ntbfd, ntsec, h->root.root.string); @@ -1450,10 +1491,8 @@ _bfd_elf_merge_symbol (bfd *abfd, the old symbol override the new one as normally happens with symbols defined in dynamic objects. */ - if (! ((*info->callbacks->multiple_common) - (info, &h->root, abfd, bfd_link_hash_common, sym->st_size))) - return FALSE; - + (*info->callbacks->multiple_common) (info, &h->root, abfd, + bfd_link_hash_common, sym->st_size); if (sym->st_size > h->size) h->size = sym->st_size; @@ -1472,13 +1511,16 @@ _bfd_elf_merge_symbol (bfd *abfd, represent variables; this can cause confusion in principle, but any such confusion would seem to indicate an erroneous program or shared library. We also permit a common symbol in a regular - object to override a weak symbol in a shared object. */ + object to override a weak symbol in a shared object. A common + symbol in executable also overrides a symbol in a shared object. */ if (newdyn && newdef && (olddef || (h->root.type == bfd_link_hash_common - && (newweak || newfunc)))) + && (newweak + || newfunc + || (!olddyn && bfd_link_executable (info)))))) { *override = TRUE; newdef = FALSE; @@ -1608,9 +1650,8 @@ _bfd_elf_merge_symbol (bfd *abfd, /* It would be best if we could set the hash table entry to a common symbol, but we don't know what to use for the section or the alignment. */ - if (! ((*info->callbacks->multiple_common) - (info, &h->root, abfd, bfd_link_hash_common, sym->st_size))) - return FALSE; + (*info->callbacks->multiple_common) (info, &h->root, abfd, + bfd_link_hash_common, sym->st_size); /* If the presumed common symbol in the dynamic object is larger, pretend that the new symbol has its size. */ @@ -1750,6 +1791,31 @@ _bfd_elf_add_default_symbol (bfd *abfd, if (skip) goto nondefault; + if (hi->def_regular) + { + /* If the undecorated symbol will have a version added by a + script different to H, then don't indirect to/from the + undecorated symbol. This isn't ideal because we may not yet + have seen symbol versions, if given by a script on the + command line rather than via --version-script. */ + if (hi->verinfo.vertree == NULL && info->version_info != NULL) + { + bfd_boolean hide; + + hi->verinfo.vertree + = bfd_find_version_for_sym (info->version_info, + hi->root.root.string, &hide); + if (hi->verinfo.vertree != NULL && hide) + { + (*bed->elf_backend_hide_symbol) (info, hi, TRUE); + goto nondefault; + } + } + if (hi->verinfo.vertree != NULL + && strcmp (p + 1 + (p[1] == '@'), hi->verinfo.vertree->name) != 0) + goto nondefault; + } + if (! override) { /* Add the default symbol if not performing a relocatable link. */ @@ -1877,7 +1943,8 @@ nondefault: overridden by a versioned definition. */ if (hi->root.type != bfd_link_hash_defined && hi->root.type != bfd_link_hash_defweak) - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: unexpected redefinition of indirect versioned symbol `%s'"), abfd, shortname); } @@ -2049,7 +2116,6 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) const struct elf_backend_data *bed; struct elf_info_failed eif; char *p; - bfd_size_type amt; sinfo = (struct elf_info_failed *) data; info = sinfo->info; @@ -2139,8 +2205,8 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) if (h->dynindx == -1) return TRUE; - amt = sizeof *t; - t = (struct bfd_elf_version_tree *) bfd_zalloc (info->output_bfd, amt); + t = (struct bfd_elf_version_tree *) bfd_zalloc (info->output_bfd, + sizeof *t); if (t == NULL) { sinfo->failed = TRUE; @@ -2170,7 +2236,8 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) { /* We could not find the version for a symbol when generating a shared archive. Return an error. */ - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: version node not found for symbol %s"), info->output_bfd, h->root.root.string); bfd_set_error (bfd_error_bad_value); @@ -2258,7 +2325,8 @@ elf_link_read_relocs_from_section (bfd *abfd, { if ((size_t) r_symndx >= nsyms) { - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: bad reloc symbol index (0x%lx >= 0x%lx)" " for offset 0x%lx in section `%A'"), abfd, sec, @@ -2269,7 +2337,8 @@ elf_link_read_relocs_from_section (bfd *abfd, } else if (r_symndx != STN_UNDEF) { - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: non-zero symbol index (0x%lx) for offset 0x%lx in section `%A'" " when the object file has no symbol table"), abfd, sec, @@ -2459,7 +2528,8 @@ _bfd_elf_link_output_relocs (bfd *output_bfd, } else { - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: relocation size mismatch in %B section %A"), output_bfd, input_section->owner, input_section); bfd_set_error (bfd_error_wrong_format); @@ -2587,18 +2657,35 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h, && (h->root.u.def.section->owner->flags & (DYNAMIC | BFD_PLUGIN)) == 0) h->def_regular = 1; + /* If a weak undefined symbol has non-default visibility, we also + hide it from the dynamic linker. */ + if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT + && h->root.type == bfd_link_hash_undefweak) + (*bed->elf_backend_hide_symbol) (eif->info, h, TRUE); + + /* A hidden versioned symbol in executable should be forced local if + it is is locally defined, not referenced by shared library and not + exported. */ + else if (bfd_link_executable (eif->info) + && h->versioned == versioned_hidden + && !eif->info->export_dynamic + && !h->dynamic + && !h->ref_dynamic + && h->def_regular) + (*bed->elf_backend_hide_symbol) (eif->info, h, TRUE); + /* If -Bsymbolic was used (which means to bind references to global symbols to the definition within the shared object), and this symbol was defined in a regular object, then it actually doesn't need a PLT entry. Likewise, if the symbol has non-default visibility. If the symbol has hidden or internal visibility, we will force it local. */ - if (h->needs_plt - && bfd_link_pic (eif->info) - && is_elf_hash_table (eif->info->hash) - && (SYMBOLIC_BIND (eif->info, h) - || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) - && h->def_regular) + else if (h->needs_plt + && bfd_link_pic (eif->info) + && is_elf_hash_table (eif->info->hash) + && (SYMBOLIC_BIND (eif->info, h) + || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) + && h->def_regular) { bfd_boolean force_local; @@ -2607,12 +2694,6 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h, (*bed->elf_backend_hide_symbol) (eif->info, h, force_local); } - /* If a weak undefined symbol has non-default visibility, we also - hide it from the dynamic linker. */ - if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT - && h->root.type == bfd_link_hash_undefweak) - (*bed->elf_backend_hide_symbol) (eif->info, h, TRUE); - /* If this is a weak defined symbol in a dynamic object, and we know the real definition in the dynamic object, copy interesting flags over to the real definition. */ @@ -2741,7 +2822,7 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data) if (h->size == 0 && h->type == STT_NOTYPE && !h->needs_plt) - (*_bfd_error_handler) + _bfd_error_handler (_("warning: type and size of dynamic symbol `%s' are not defined"), h->root.root.string); @@ -3058,9 +3139,9 @@ static bfd_boolean elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef) { Elf_Internal_Shdr * hdr; - bfd_size_type symcount; - bfd_size_type extsymcount; - bfd_size_type extsymoff; + size_t symcount; + size_t extsymcount; + size_t extsymoff; Elf_Internal_Sym *isymbuf; Elf_Internal_Sym *isym; Elf_Internal_Sym *isymend; @@ -3070,15 +3151,25 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef) if (abfd == NULL) return FALSE; - /* Return FALSE if the object has been claimed by plugin. */ - if (abfd->plugin_format == bfd_plugin_yes) - return FALSE; - if (! bfd_check_format (abfd, bfd_object)) return FALSE; - /* Select the appropriate symbol table. */ - if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0) + /* Select the appropriate symbol table. If we don't know if the + object file is an IR object, give linker LTO plugin a chance to + get the correct symbol table. */ + if (abfd->plugin_format == bfd_plugin_yes +#if BFD_SUPPORTS_PLUGINS + || (abfd->plugin_format == bfd_plugin_unknown + && bfd_link_plugin_object_p (abfd)) +#endif + ) + { + /* Use the IR symbol table if the object has been claimed by + plugin. */ + abfd = abfd->plugin_dummy_bfd; + hdr = &elf_tdata (abfd)->symtab_hdr; + } + else if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0) hdr = &elf_tdata (abfd)->symtab_hdr; else hdr = &elf_tdata (abfd)->dynsymtab_hdr; @@ -3178,14 +3269,14 @@ elf_add_dt_needed_tag (bfd *abfd, bfd_boolean do_it) { struct elf_link_hash_table *hash_table; - bfd_size_type strindex; + size_t strindex; if (!_bfd_elf_link_create_dynstrtab (abfd, info)) return -1; hash_table = elf_hash_table (info); strindex = _bfd_elf_strtab_add (hash_table->dynstr, soname, FALSE); - if (strindex == (bfd_size_type) -1) + if (strindex == (size_t) -1) return -1; if (_bfd_elf_strtab_refcount (hash_table->dynstr, strindex) != 1) @@ -3228,12 +3319,26 @@ elf_add_dt_needed_tag (bfd *abfd, return 0; } +/* Return true if SONAME is on the needed list between NEEDED and STOP + (or the end of list if STOP is NULL), and needed by a library that + will be loaded. */ + static bfd_boolean -on_needed_list (const char *soname, struct bfd_link_needed_list *needed) -{ - for (; needed != NULL; needed = needed->next) - if ((elf_dyn_lib_class (needed->by) & DYN_AS_NEEDED) == 0 - && strcmp (soname, needed->name) == 0) +on_needed_list (const char *soname, + struct bfd_link_needed_list *needed, + struct bfd_link_needed_list *stop) +{ + struct bfd_link_needed_list *look; + for (look = needed; look != stop; look = look->next) + if (strcmp (soname, look->name) == 0 + && ((elf_dyn_lib_class (look->by) & DYN_AS_NEEDED) == 0 + /* If needed by a library that itself is not directly + needed, recursively check whether that library is + indirectly needed. Since we add DT_NEEDED entries to + the end of the list, library dependencies appear after + the library. Therefore search prior to the current + LOOK, preventing possible infinite recursion. */ + || on_needed_list (elf_dt_name (look->by), needed, look))) return TRUE; return FALSE; @@ -3339,7 +3444,7 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info) { asection *s; bfd_byte *p; - bfd_size_type i; + size_t i; Elf_Internal_Verdef def; Elf_Internal_Verdaux defaux; @@ -3371,7 +3476,7 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info) { asection *s; bfd_byte *p; - bfd_size_type i; + size_t i; Elf_Internal_Verneed need; Elf_Internal_Vernaux needaux; @@ -3449,6 +3554,71 @@ _bfd_elf_notice_as_needed (bfd *ibfd, return (*info->callbacks->notice) (info, NULL, NULL, ibfd, NULL, act, 0); } +/* Check relocations an ELF object file. */ + +bfd_boolean +_bfd_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info) +{ + const struct elf_backend_data *bed = get_elf_backend_data (abfd); + struct elf_link_hash_table *htab = elf_hash_table (info); + + /* If this object is the same format as the output object, and it is + not a shared library, then let the backend look through the + relocs. + + This is required to build global offset table entries and to + arrange for dynamic relocs. It is not required for the + particular common case of linking non PIC code, even when linking + against shared libraries, but unfortunately there is no way of + knowing whether an object file has been compiled PIC or not. + Looking through the relocs is not particularly time consuming. + The problem is that we must either (1) keep the relocs in memory, + which causes the linker to require additional runtime memory or + (2) read the relocs twice from the input file, which wastes time. + This would be a good case for using mmap. + + I have no idea how to handle linking PIC code into a file of a + different format. It probably can't be done. */ + if ((abfd->flags & DYNAMIC) == 0 + && is_elf_hash_table (htab) + && bed->check_relocs != NULL + && elf_object_id (abfd) == elf_hash_table_id (htab) + && (*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec)) + { + asection *o; + + for (o = abfd->sections; o != NULL; o = o->next) + { + Elf_Internal_Rela *internal_relocs; + bfd_boolean ok; + + /* Don't check relocations in excluded sections. */ + if ((o->flags & SEC_RELOC) == 0 + || (o->flags & SEC_EXCLUDE) != 0 + || o->reloc_count == 0 + || ((info->strip == strip_all || info->strip == strip_debugger) + && (o->flags & SEC_DEBUGGING) != 0) + || bfd_is_abs_section (o->output_section)) + continue; + + internal_relocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, + info->keep_memory); + if (internal_relocs == NULL) + return FALSE; + + ok = (*bed->check_relocs) (abfd, info, o, internal_relocs); + + if (elf_section_data (o)->relocs != internal_relocs) + free (internal_relocs); + + if (! ok) + return FALSE; + } + } + + return TRUE; +} + /* Add symbols from an ELF object file to the linker hash table. */ static bfd_boolean @@ -3456,16 +3626,16 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) { Elf_Internal_Ehdr *ehdr; Elf_Internal_Shdr *hdr; - bfd_size_type symcount; - bfd_size_type extsymcount; - bfd_size_type extsymoff; + size_t symcount; + size_t extsymcount; + size_t extsymoff; struct elf_link_hash_entry **sym_hash; bfd_boolean dynamic; Elf_External_Versym *extversym = NULL; Elf_External_Versym *ever; struct elf_link_hash_entry *weaks; struct elf_link_hash_entry **nondeflt_vers = NULL; - bfd_size_type nondeflt_vers_cnt = 0; + size_t nondeflt_vers_cnt = 0; Elf_Internal_Sym *isymbuf = NULL; Elf_Internal_Sym *isym; Elf_Internal_Sym *isymend; @@ -3481,8 +3651,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) void *old_ent; struct bfd_link_hash_entry *old_undefs = NULL; struct bfd_link_hash_entry *old_undefs_tail = NULL; - long old_dynsymcount = 0; - bfd_size_type old_dynstr_size = 0; + void *old_strtab = NULL; size_t tabsize = 0; asection *s; bfd_boolean just_syms; @@ -3519,6 +3688,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) || (bed->elf_machine_alt2 != 0 && ehdr->e_machine == bed->elf_machine_alt2))) info->callbacks->einfo + /* xgettext:c-format */ (_("%P: alternate ELF machine code found (%d) in %B, expecting %d\n"), ehdr->e_machine, abfd, bed->elf_machine_code); @@ -3598,11 +3768,14 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) /* If we are creating a shared library, create all the dynamic sections immediately. We need to attach them to something, so we attach them to this BFD, provided it is the right - format and is not from ld --just-symbols. FIXME: If there + format and is not from ld --just-symbols. Always create the + dynamic sections for -E/--dynamic-list. FIXME: If there are no input BFD's of the same format as the output, we can't make a shared library. */ if (!just_syms - && bfd_link_pic (info) + && (bfd_link_pic (info) + || (!bfd_link_relocatable (info) + && (info->export_dynamic || info->dynamic))) && is_elf_hash_table (htab) && info->output_bfd->xvec == abfd->xvec && !htab->dynamic_sections_created) @@ -3844,7 +4017,8 @@ error_free_dyn: { /* We store a pointer to the hash table entry for each external symbol. */ - amt = extsymcount * sizeof (struct elf_link_hash_entry *); + amt = extsymcount; + amt *= sizeof (struct elf_link_hash_entry *); sym_hash = (struct elf_link_hash_entry **) bfd_zalloc (abfd, amt); if (sym_hash == NULL) goto error_free_sym; @@ -3923,8 +4097,9 @@ error_free_dyn: old_table = htab->root.table.table; old_size = htab->root.table.size; old_count = htab->root.table.count; - old_dynsymcount = htab->dynsymcount; - old_dynstr_size = _bfd_elf_strtab_size (htab->dynstr); + old_strtab = _bfd_elf_strtab_save (htab->dynstr); + if (old_strtab == NULL) + goto error_free_vers; for (i = 0; i < htab->root.table.size; i++) { @@ -3966,6 +4141,7 @@ error_free_dyn: bfd_boolean old_weak; bfd_boolean override; bfd_boolean common; + bfd_boolean discarded; unsigned int old_alignment; bfd *old_bfd; bfd_boolean matched; @@ -3976,6 +4152,7 @@ error_free_dyn: sec = NULL; value = isym->st_value; common = bed->common_definition (isym); + discarded = FALSE; bind = ELF_ST_BIND (isym->st_info); switch (bind) @@ -4026,6 +4203,7 @@ error_free_dyn: /* Symbols from discarded section are undefined. We keep its visibility. */ sec = bfd_und_section_ptr; + discarded = TRUE; isym->st_shndx = SHN_UNDEF; } else if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) @@ -4153,7 +4331,8 @@ error_free_dyn: if (verstr == NULL) { - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: %s: invalid version %u (max %d)"), abfd, name, vernum, elf_tdata (abfd)->cverdefs); @@ -4189,7 +4368,8 @@ error_free_dyn: } if (verstr == NULL) { - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: %s: invalid needed version %d"), abfd, name, vernum); bfd_set_error (bfd_error_bad_value); @@ -4261,6 +4441,11 @@ error_free_dyn: (struct bfd_link_hash_entry **) sym_hash))) goto error_free_vers; + if ((flags & BSF_GNU_UNIQUE) + && (abfd->flags & DYNAMIC) == 0 + && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) + elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_unique; + h = *sym_hash; /* We need to make sure that indirect symbol dynamic flags are updated. */ @@ -4269,6 +4454,11 @@ error_free_dyn: || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; + /* Setting the index to -3 tells elf_link_output_extsym that + this symbol is defined in a discarded section. */ + if (discarded) + h->indx = -3; + *sym_hash = h; new_weak = (flags & BSF_WEAK) != 0; @@ -4406,7 +4596,8 @@ error_free_dyn: symbol_align = ffs (h->root.u.def.value) - 1; if (h->root.u.def.section->owner != NULL - && (h->root.u.def.section->owner->flags & DYNAMIC) == 0) + && (h->root.u.def.section->owner->flags + & (DYNAMIC | BFD_PLUGIN)) == 0) { normal_align = h->root.u.def.section->alignment_power; if (normal_align > symbol_align) @@ -4432,13 +4623,15 @@ error_free_dyn: { /* PR binutils/2735 */ if (normal_bfd == NULL) - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("Warning: alignment %u of common symbol `%s' in %B is" " greater than the alignment (%u) of its section %A"), common_bfd, h->root.u.def.section, 1 << common_align, name, 1 << normal_align); else - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("Warning: alignment %u of symbol `%s' in %B" " is smaller than %u in %B"), normal_bfd, common_bfd, @@ -4454,7 +4647,8 @@ error_free_dyn: if (h->size != 0 && h->size != isym->st_size && ! size_change_ok) - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("Warning: size of symbol `%s' changed" " from %lu in %B to %lu in %B"), old_bfd, abfd, @@ -4489,7 +4683,8 @@ error_free_dyn: if (h->type != type) { if (h->type != STT_NOTYPE && ! type_change_ok) - (*_bfd_error_handler) + /* xgettext:c-format */ + _bfd_error_handler (_("Warning: type of symbol `%s' changed" " from %d to %d in %B"), abfd, name, h->type, type); @@ -4549,7 +4744,7 @@ error_free_dyn: goto error_free_vers; } } - else if (dynsym && h->dynindx != -1) + else if (h->dynindx != -1) /* If the symbol already has a dynamic index, but visibility says it should not be visible, turn it into a local symbol. */ @@ -4562,8 +4757,10 @@ error_free_dyn: break; } - /* Don't add DT_NEEDED for references from the dummy bfd. */ + /* Don't add DT_NEEDED for references from the dummy bfd nor + for unmatched symbol. */ if (!add_needed + && matched && definition && ((dynsym && h->ref_regular_nonweak @@ -4571,7 +4768,8 @@ error_free_dyn: || (old_bfd->flags & BFD_PLUGIN) == 0)) || (h->ref_dynamic_nonweak && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0 - && !on_needed_list (elf_dt_name (abfd), htab->needed)))) + && !on_needed_list (elf_dt_name (abfd), + htab->needed, NULL)))) { int ret; const char *soname = elf_dt_name (abfd); @@ -4587,7 +4785,8 @@ error_free_dyn: if (old_bfd != NULL && (elf_dyn_lib_class (abfd) & DYN_NO_NEEDED) != 0) { - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: undefined reference to symbol '%s'"), old_bfd, name); bfd_set_error (bfd_error_missing_dso); @@ -4633,7 +4832,9 @@ error_free_dyn: memcpy (htab->root.table.table, old_tab, tabsize); htab->root.undefs = old_undefs; htab->root.undefs_tail = old_undefs_tail; - _bfd_elf_strtab_restore_size (htab->dynstr, old_dynstr_size); + _bfd_elf_strtab_restore (htab->dynstr, old_strtab); + free (old_strtab); + old_strtab = NULL; for (i = 0; i < htab->root.table.size; i++) { struct bfd_hash_entry *p; @@ -4646,9 +4847,6 @@ error_free_dyn: h = (struct elf_link_hash_entry *) p; if (h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; - if (h->dynindx >= old_dynsymcount - && h->dynstr_index < old_dynstr_size) - _bfd_elf_strtab_delref (htab->dynstr, h->dynstr_index); /* Preserve the maximum alignment and size for common symbols even if this dynamic lib isn't on DT_NEEDED @@ -4709,7 +4907,7 @@ error_free_dyn: such that any relocs against foo become foo@BAR. */ if (!bfd_link_relocatable (info) && nondeflt_vers != NULL) { - bfd_size_type cnt, symidx; + size_t cnt, symidx; for (cnt = 0; cnt < nondeflt_vers_cnt; ++cnt) { @@ -4780,7 +4978,8 @@ error_free_dyn: /* Since we have to search the whole symbol list for each weak defined symbol, search time for N weak defined symbols will be O(N^2). Binary search will cut it down to O(NlogN). */ - amt = extsymcount * sizeof (struct elf_link_hash_entry *); + amt = extsymcount; + amt *= sizeof (struct elf_link_hash_entry *); sorted_sym_hash = (struct elf_link_hash_entry **) bfd_malloc (amt); if (sorted_sym_hash == NULL) goto error_return; @@ -4913,57 +5112,9 @@ error_free_dyn: && !(*bed->check_directives) (abfd, info)) return FALSE; - /* If this object is the same format as the output object, and it is - not a shared library, then let the backend look through the - relocs. - - This is required to build global offset table entries and to - arrange for dynamic relocs. It is not required for the - particular common case of linking non PIC code, even when linking - against shared libraries, but unfortunately there is no way of - knowing whether an object file has been compiled PIC or not. - Looking through the relocs is not particularly time consuming. - The problem is that we must either (1) keep the relocs in memory, - which causes the linker to require additional runtime memory or - (2) read the relocs twice from the input file, which wastes time. - This would be a good case for using mmap. - - I have no idea how to handle linking PIC code into a file of a - different format. It probably can't be done. */ - if (! dynamic - && is_elf_hash_table (htab) - && bed->check_relocs != NULL - && elf_object_id (abfd) == elf_hash_table_id (htab) - && (*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec)) - { - asection *o; - - for (o = abfd->sections; o != NULL; o = o->next) - { - Elf_Internal_Rela *internal_relocs; - bfd_boolean ok; - - if ((o->flags & SEC_RELOC) == 0 - || o->reloc_count == 0 - || ((info->strip == strip_all || info->strip == strip_debugger) - && (o->flags & SEC_DEBUGGING) != 0) - || bfd_is_abs_section (o->output_section)) - continue; - - internal_relocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, - info->keep_memory); - if (internal_relocs == NULL) - goto error_return; - - ok = (*bed->check_relocs) (abfd, info, o, internal_relocs); - - if (elf_section_data (o)->relocs != internal_relocs) - free (internal_relocs); - - if (! ok) - goto error_return; - } - } + if (!info->check_relocs_after_open_input + && !_bfd_elf_link_check_relocs (abfd, info)) + return FALSE; /* If this is a non-traditional link, try to optimize the handling of the .stab/.stabstr sections. */ @@ -5018,6 +5169,8 @@ error_free_dyn: error_free_vers: if (old_tab != NULL) free (old_tab); + if (old_strtab != NULL) + free (old_strtab); if (nondeflt_vers != NULL) free (nondeflt_vers); if (extversym != NULL) @@ -5199,7 +5352,7 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info) if (!(*info->callbacks ->add_archive_element) (info, element, symdef->name, &element)) - goto error_return; + continue; if (!bfd_link_add_symbols (element, info)) goto error_return; @@ -5637,11 +5790,13 @@ bfd_elf_stack_segment_size (bfd *output_bfd, /* The symbol has no type if specified on the command line. */ h->type = STT_OBJECT; if (info->stacksize) - (*_bfd_error_handler) (_("%B: stack size specified and %s set"), - output_bfd, legacy_symbol); + /* xgettext:c-format */ + _bfd_error_handler (_("%B: stack size specified and %s set"), + output_bfd, legacy_symbol); else if (h->root.u.def.section != bfd_abs_section_ptr) - (*_bfd_error_handler) (_("%B: %s not absolute"), - output_bfd, legacy_symbol); + /* xgettext:c-format */ + _bfd_error_handler (_("%B: %s not absolute"), + output_bfd, legacy_symbol); else info->stacksize = h->root.u.def.value; } @@ -5688,14 +5843,14 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info, asection **sinterpptr) { - bfd_size_type soname_indx; + size_t soname_indx; bfd *dynobj; const struct elf_backend_data *bed; struct elf_info_failed asvinfo; *sinterpptr = NULL; - soname_indx = (bfd_size_type) -1; + soname_indx = (size_t) -1; if (!is_elf_hash_table (info->hash)) return TRUE; @@ -5776,7 +5931,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, { soname_indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, soname, TRUE); - if (soname_indx == (bfd_size_type) -1 + if (soname_indx == (size_t) -1 || !_bfd_elf_add_dynamic_entry (info, DT_SONAME, soname_indx)) return FALSE; } @@ -5790,12 +5945,12 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, if (rpath != NULL) { - bfd_size_type indx; + size_t indx; bfd_vma tag; indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, rpath, TRUE); - if (indx == (bfd_size_type) -1) + if (indx == (size_t) -1) return FALSE; tag = info->new_dtags ? DT_RUNPATH : DT_RPATH; @@ -5805,11 +5960,11 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, if (filter_shlib != NULL) { - bfd_size_type indx; + size_t indx; indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, filter_shlib, TRUE); - if (indx == (bfd_size_type) -1 + if (indx == (size_t) -1 || !_bfd_elf_add_dynamic_entry (info, DT_FILTER, indx)) return FALSE; } @@ -5820,11 +5975,11 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, for (p = auxiliary_filters; *p != NULL; p++) { - bfd_size_type indx; + size_t indx; indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, *p, TRUE); - if (indx == (bfd_size_type) -1 + if (indx == (size_t) -1 || !_bfd_elf_add_dynamic_entry (info, DT_AUXILIARY, indx)) return FALSE; } @@ -5832,22 +5987,22 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, if (audit != NULL) { - bfd_size_type indx; + size_t indx; indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, audit, TRUE); - if (indx == (bfd_size_type) -1 + if (indx == (size_t) -1 || !_bfd_elf_add_dynamic_entry (info, DT_AUDIT, indx)) return FALSE; } if (depaudit != NULL) { - bfd_size_type indx; + size_t indx; indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, depaudit, TRUE); - if (indx == (bfd_size_type) -1 + if (indx == (size_t) -1 || !_bfd_elf_add_dynamic_entry (info, DT_DEPAUDIT, indx)) return FALSE; } @@ -5937,7 +6092,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, for (d = t->globals.list; d != NULL; d = d->next) if (d->literal && !d->symver && !d->script) { - (*_bfd_error_handler) + _bfd_error_handler (_("%s: undefined version: %s"), d->pattern, t->name); all_defined = FALSE; @@ -6005,7 +6160,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, if (elf_section_data (o)->this_hdr.sh_type == SHT_PREINIT_ARRAY) { - (*_bfd_error_handler) + _bfd_error_handler (_("%B: .preinit_array section is not allowed in DSO"), sub); break; @@ -6155,7 +6310,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, + sizeof (Elf_External_Verdaux)); } - if (soname_indx != (bfd_size_type) -1) + if (soname_indx != (size_t) -1) { _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr, soname_indx); @@ -6165,13 +6320,13 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, } else { - bfd_size_type indx; + size_t indx; name = lbasename (output_bfd->filename); def.vd_hash = bfd_elf_hash (name); indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, name, FALSE); - if (indx == (bfd_size_type) -1) + if (indx == (size_t) -1) return FALSE; defaux.vda_name = indx; } @@ -6390,7 +6545,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, { unsigned int caux; Elf_Internal_Vernaux *a; - bfd_size_type indx; + size_t indx; caux = 0; for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr) @@ -6403,7 +6558,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, ? elf_dt_name (t->vn_bfd) : lbasename (t->vn_bfd->filename), FALSE); - if (indx == (bfd_size_type) -1) + if (indx == (size_t) -1) return FALSE; t->vn_file = indx; t->vn_aux = sizeof (Elf_External_Verneed); @@ -6422,7 +6577,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, a->vna_hash = bfd_elf_hash (a->vna_nodename); indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, a->vna_nodename, FALSE); - if (indx == (bfd_size_type) -1) + if (indx == (size_t) -1) return FALSE; a->vna_name = indx; if (a->vna_nextptr == NULL) @@ -6535,8 +6690,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) /* Work out the size of the symbol version section. */ s = bfd_get_linker_section (dynobj, ".gnu.version"); BFD_ASSERT (s != NULL); - if (dynsymcount != 0 - && (s->flags & SEC_EXCLUDE) == 0) + if ((s->flags & SEC_EXCLUDE) == 0) { s->size = dynsymcount * sizeof (Elf_External_Versym); s->contents = (unsigned char *) bfd_zalloc (output_bfd, s->size); @@ -6557,17 +6711,14 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) BFD_ASSERT (s != NULL); s->size = dynsymcount * bed->s->sizeof_sym; - if (dynsymcount != 0) - { - s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size); - if (s->contents == NULL) - return FALSE; + s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size); + if (s->contents == NULL) + return FALSE; - /* The first entry in .dynsym is a dummy symbol. - Clear all the section syms, in case we don't output them all. */ - ++section_sym_count; - memset (s->contents, 0, section_sym_count * bed->s->sizeof_sym); - } + /* The first entry in .dynsym is a dummy symbol. Clear all the + section syms, in case we don't output them all. */ + ++section_sym_count; + memset (s->contents, 0, section_sym_count * bed->s->sizeof_sym); elf_hash_table (info)->bucketcount = 0; @@ -7205,7 +7356,7 @@ struct elf_symbuf_symbol struct elf_symbuf_head { struct elf_symbuf_symbol *ssym; - bfd_size_type count; + size_t count; unsigned int st_shndx; }; @@ -7239,12 +7390,12 @@ elf_sym_name_compare (const void *arg1, const void *arg2) } static struct elf_symbuf_head * -elf_create_symbuf (bfd_size_type symcount, Elf_Internal_Sym *isymbuf) +elf_create_symbuf (size_t symcount, Elf_Internal_Sym *isymbuf) { Elf_Internal_Sym **ind, **indbufend, **indbuf; struct elf_symbuf_symbol *ssym; struct elf_symbuf_head *ssymbuf, *ssymhead; - bfd_size_type i, shndx_count, total_size; + size_t i, shndx_count, total_size; indbuf = (Elf_Internal_Sym **) bfd_malloc2 (symcount, sizeof (*indbuf)); if (indbuf == NULL) @@ -7291,7 +7442,7 @@ elf_create_symbuf (bfd_size_type symcount, Elf_Internal_Sym *isymbuf) ssym->st_other = (*ind)->st_other; ssymhead->count++; } - BFD_ASSERT ((bfd_size_type) (ssymhead - ssymbuf) == shndx_count + BFD_ASSERT ((size_t) (ssymhead - ssymbuf) == shndx_count && (((bfd_hostptr_t) ssym - (bfd_hostptr_t) ssymbuf) == total_size)); @@ -7309,12 +7460,12 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2, bfd *bfd1, *bfd2; const struct elf_backend_data *bed1, *bed2; Elf_Internal_Shdr *hdr1, *hdr2; - bfd_size_type symcount1, symcount2; + size_t symcount1, symcount2; Elf_Internal_Sym *isymbuf1, *isymbuf2; struct elf_symbuf_head *ssymbuf1, *ssymbuf2; Elf_Internal_Sym *isym, *isymend; struct elf_symbol *symtable1 = NULL, *symtable2 = NULL; - bfd_size_type count1, count2, i; + size_t count1, count2, i; unsigned int shndx1, shndx2; bfd_boolean result; @@ -7377,7 +7528,7 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2, if (ssymbuf1 != NULL && ssymbuf2 != NULL) { /* Optimized faster version. */ - bfd_size_type lo, hi, mid; + size_t lo, hi, mid; struct elf_symbol *symp; struct elf_symbuf_symbol *ssym, *ssymend; @@ -7729,10 +7880,15 @@ resolve_symbol (const char *name, return FALSE; } +/* Looks up NAME in SECTIONS. If found sets RESULT to NAME's address (in + bytes) and returns TRUE, otherwise returns FALSE. Accepts pseudo-section + names like "foo.end" which is the end address of section "foo". */ + static bfd_boolean resolve_section (const char *name, asection *sections, - bfd_vma *result) + bfd_vma *result, + bfd * abfd) { asection *curr; unsigned int len; @@ -7745,6 +7901,7 @@ resolve_section (const char *name, } /* Hmm. still haven't found it. try pseudo-section names. */ + /* FIXME: This could be coded more efficiently... */ for (curr = sections; curr; curr = curr->next) { len = strlen (curr->name); @@ -7755,7 +7912,7 @@ resolve_section (const char *name, { if (strncmp (".end", name + len, 4) == 0) { - *result = curr->vma + curr->size; + *result = curr->vma + curr->size / bfd_octets_per_byte (abfd); return TRUE; } @@ -7769,6 +7926,7 @@ resolve_section (const char *name, static void undefined_reference (const char *reftype, const char *name) { + /* xgettext:c-format */ _bfd_error_handler (_("undefined %s reference in complex symbol: %s"), reftype, name); } @@ -7815,6 +7973,7 @@ eval_symbol (bfd_vma *result, case 'S': symbol_is_section = TRUE; + /* Fall through. */ case 's': ++sym; symlen = strtol (sym, (char **) symp, 10); @@ -7837,7 +7996,7 @@ eval_symbol (bfd_vma *result, if (symbol_is_section) { - if (!resolve_section (symbuf, flinfo->output_bfd->sections, result) + if (!resolve_section (symbuf, flinfo->output_bfd->sections, result, input_bfd) && !resolve_symbol (symbuf, input_bfd, flinfo, result, isymbuf, locsymcount)) { @@ -7850,7 +8009,7 @@ eval_symbol (bfd_vma *result, if (!resolve_symbol (symbuf, input_bfd, flinfo, result, isymbuf, locsymcount) && !resolve_section (symbuf, flinfo->output_bfd->sections, - result)) + result, input_bfd)) { undefined_reference ("symbol", symbuf); return FALSE; @@ -8074,8 +8233,8 @@ bfd_elf_perform_complex_relocation (bfd *input_bfd, else shift = (8 * wordsz) - (start + len); - /* FIXME: octets_per_byte. */ - x = get_value (wordsz, chunksz, input_bfd, contents + rel->r_offset); + x = get_value (wordsz, chunksz, input_bfd, + contents + rel->r_offset * bfd_octets_per_byte (input_bfd)); #ifdef DEBUG printf ("Doing complex reloc: " @@ -8107,8 +8266,8 @@ bfd_elf_perform_complex_relocation (bfd *input_bfd, (unsigned long) relocation, (unsigned long) (mask << shift), (unsigned long) ((relocation & mask) << shift), (unsigned long) x); #endif - /* FIXME: octets_per_byte. */ - put_value (wordsz, chunksz, input_bfd, x, contents + rel->r_offset); + put_value (wordsz, chunksz, input_bfd, x, + contents + rel->r_offset * bfd_octets_per_byte (input_bfd)); return r; } @@ -8205,6 +8364,7 @@ ext64b_r_offset (const void *p) static bfd_boolean elf_link_adjust_relocs (bfd *abfd, + asection *sec, struct bfd_elf_section_reloc_data *reldata, bfd_boolean sort) { @@ -8263,6 +8423,9 @@ elf_link_adjust_relocs (bfd *abfd, (*swap_out) (abfd, irela, erela); } + if (bed->elf_backend_update_relocs) + (*bed->elf_backend_update_relocs) (sec, reldata); + if (sort && count != 0) { bfd_vma (*ext_r_off) (const void *); @@ -8445,6 +8608,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) struct elf_link_sort_rela *sq; const struct elf_backend_data *bed = get_elf_backend_data (abfd); int i2e = bed->s->int_rels_per_ext_rel; + unsigned int opb = bfd_octets_per_byte (abfd); void (*swap_in) (bfd *, const bfd_byte *, Elf_Internal_Rela *); void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *); struct bfd_link_order *lo; @@ -8460,7 +8624,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) bfd_boolean use_rela_initialised = FALSE; /* This is just here to stop gcc from complaining. - It's initialization checking code is not perfect. */ + Its initialization checking code is not perfect. */ use_rela = TRUE; /* Both sections are present. Examine the sizes @@ -8481,8 +8645,9 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) /* Section size is only divisible by rela. */ if (use_rela_initialised && (use_rela == FALSE)) { - _bfd_error_handler - (_("%B: Unable to sort relocs - they are in more than one size"), abfd); + _bfd_error_handler (_("%B: Unable to sort relocs - " + "they are in more than one size"), + abfd); bfd_set_error (bfd_error_invalid_operation); return 0; } @@ -8498,8 +8663,9 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) /* Section size is only divisible by rel. */ if (use_rela_initialised && (use_rela == TRUE)) { - _bfd_error_handler - (_("%B: Unable to sort relocs - they are in more than one size"), abfd); + _bfd_error_handler (_("%B: Unable to sort relocs - " + "they are in more than one size"), + abfd); bfd_set_error (bfd_error_invalid_operation); return 0; } @@ -8511,9 +8677,10 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) } else { - /* The section size is not divisible by either - something is wrong. */ - _bfd_error_handler - (_("%B: Unable to sort relocs - they are of an unknown size"), abfd); + /* The section size is not divisible by either - + something is wrong. */ + _bfd_error_handler (_("%B: Unable to sort relocs - " + "they are of an unknown size"), abfd); bfd_set_error (bfd_error_invalid_operation); return 0; } @@ -8535,8 +8702,9 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) /* Section size is only divisible by rela. */ if (use_rela_initialised && (use_rela == FALSE)) { - _bfd_error_handler - (_("%B: Unable to sort relocs - they are in more than one size"), abfd); + _bfd_error_handler (_("%B: Unable to sort relocs - " + "they are in more than one size"), + abfd); bfd_set_error (bfd_error_invalid_operation); return 0; } @@ -8552,8 +8720,9 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) /* Section size is only divisible by rel. */ if (use_rela_initialised && (use_rela == TRUE)) { - _bfd_error_handler - (_("%B: Unable to sort relocs - they are in more than one size"), abfd); + _bfd_error_handler (_("%B: Unable to sort relocs - " + "they are in more than one size"), + abfd); bfd_set_error (bfd_error_invalid_operation); return 0; } @@ -8565,9 +8734,10 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) } else { - /* The section size is not divisible by either - something is wrong. */ - _bfd_error_handler - (_("%B: Unable to sort relocs - they are of an unknown size"), abfd); + /* The section size is not divisible by either - + something is wrong. */ + _bfd_error_handler (_("%B: Unable to sort relocs - " + "they are of an unknown size"), abfd); bfd_set_error (bfd_error_invalid_operation); return 0; } @@ -8643,8 +8813,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) } erel = o->contents; erelend = o->contents + o->size; - /* FIXME: octets_per_byte. */ - p = sort + o->output_offset / ext_size * sort_elt; + p = sort + o->output_offset * opb / ext_size * sort_elt; while (erel < erelend) { @@ -8680,6 +8849,35 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) qsort (s_non_relative, count - ret, sort_elt, elf_link_sort_cmp2); + struct elf_link_hash_table *htab = elf_hash_table (info); + if (htab->srelplt && htab->srelplt->output_section == dynamic_relocs) + { + /* We have plt relocs in .rela.dyn. */ + sq = (struct elf_link_sort_rela *) sort; + for (i = 0; i < count; i++) + if (sq[count - i - 1].type != reloc_class_plt) + break; + if (i != 0 && htab->srelplt->size == i * ext_size) + { + struct bfd_link_order **plo; + /* Put srelplt link_order last. This is so the output_offset + set in the next loop is correct for DT_JMPREL. */ + for (plo = &dynamic_relocs->map_head.link_order; *plo != NULL; ) + if ((*plo)->type == bfd_indirect_link_order + && (*plo)->u.indirect.section == htab->srelplt) + { + lo = *plo; + *plo = lo->next; + } + else + plo = &(*plo)->next; + *plo = lo; + lo->next = NULL; + dynamic_relocs->map_tail.link_order = lo; + } + } + + p = sort; for (lo = dynamic_relocs->map_head.link_order; lo != NULL; lo = lo->next) if (lo->type == bfd_indirect_link_order) { @@ -8688,8 +8886,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) erel = o->contents; erelend = o->contents + o->size; - /* FIXME: octets_per_byte. */ - p = sort + o->output_offset / ext_size * sort_elt; + o->output_offset = (p - sort) / sort_elt * ext_size / opb; while (erel < erelend) { struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p; @@ -8778,7 +8975,8 @@ static bfd_boolean elf_link_swap_symbols_out (struct elf_final_link_info *flinfo) { struct elf_link_hash_table *hash_table = elf_hash_table (flinfo->info); - bfd_size_type amt, i; + bfd_size_type amt; + size_t i; const struct elf_backend_data *bed; bfd_byte *symbuf; Elf_Internal_Shdr *hdr; @@ -8799,8 +8997,8 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo) if (flinfo->symshndxbuf) { - amt = (sizeof (Elf_External_Sym_Shndx) - * (bfd_get_symcount (flinfo->output_bfd))); + amt = sizeof (Elf_External_Sym_Shndx); + amt *= bfd_get_symcount (flinfo->output_bfd); flinfo->symshndxbuf = (Elf_External_Sym_Shndx *) bfd_zmalloc (amt); if (flinfo->symshndxbuf == NULL) { @@ -8856,7 +9054,8 @@ check_dynsym (bfd *abfd, Elf_Internal_Sym *sym) { /* The gABI doesn't support dynamic symbols in output sections beyond 64k. */ - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: Too many sections: %d (>= %d)"), abfd, bfd_count_sections (abfd), SHN_LORESERVE & 0xffff); bfd_set_error (bfd_error_nonrepresentable_section); @@ -8895,7 +9094,8 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info, case bfd_link_hash_undefined: case bfd_link_hash_undefweak: abfd = h->root.u.undef.abfd; - if ((abfd->flags & DYNAMIC) == 0 + if (abfd == NULL + || (abfd->flags & DYNAMIC) == 0 || (elf_dyn_lib_class (abfd) & DYN_DT_NEEDED) == 0) return FALSE; break; @@ -8917,9 +9117,9 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info, { bfd *input; Elf_Internal_Shdr *hdr; - bfd_size_type symcount; - bfd_size_type extsymcount; - bfd_size_type extsymoff; + size_t symcount; + size_t extsymcount; + size_t extsymoff; Elf_Internal_Shdr *versymhdr; Elf_Internal_Sym *isym; Elf_Internal_Sym *isymend; @@ -9021,6 +9221,28 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info, return FALSE; } +/* Convert ELF common symbol TYPE. */ + +static int +elf_link_convert_common_type (struct bfd_link_info *info, int type) +{ + /* Commom symbol can only appear in relocatable link. */ + if (!bfd_link_relocatable (info)) + abort (); + switch (info->elf_stt_common) + { + case unchanged: + break; + case elf_stt_common: + type = STT_COMMON; + break; + case no_elf_stt_common: + type = STT_OBJECT; + break; + } + return type; +} + /* Add an external symbol to the symbol table. This is called from the hash table traversal routine. When generating a shared object, we go through the symbol table twice. The first time we output @@ -9040,16 +9262,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) const struct elf_backend_data *bed; long indx; int ret; - /* A symbol is bound locally if it is forced local or it is locally - defined, hidden versioned, not referenced by shared library and - not exported when linking executable. */ - bfd_boolean local_bind = (h->forced_local - || (bfd_link_executable (flinfo->info) - && !flinfo->info->export_dynamic - && !h->dynamic - && !h->ref_dynamic - && h->def_regular - && h->versioned == versioned_hidden)); + unsigned int type; if (h->root.type == bfd_link_hash_warning) { @@ -9061,12 +9274,12 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) /* Decide whether to output this symbol in this pass. */ if (eoinfo->localsyms) { - if (!local_bind) + if (!h->forced_local) return TRUE; } else { - if (local_bind) + if (h->forced_local) return TRUE; } @@ -9092,19 +9305,15 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) && (!h->ref_regular || flinfo->info->gc_sections) && !elf_link_check_versioned_symbol (flinfo->info, bed, h) && flinfo->info->unresolved_syms_in_shared_libs != RM_IGNORE) - { - if (!(flinfo->info->callbacks->undefined_symbol - (flinfo->info, h->root.root.string, - h->ref_regular ? NULL : h->root.u.undef.abfd, - NULL, 0, - (flinfo->info->unresolved_syms_in_shared_libs - == RM_GENERATE_ERROR)))) - { - bfd_set_error (bfd_error_bad_value); - eoinfo->failed = TRUE; - return FALSE; - } - } + (*flinfo->info->callbacks->undefined_symbol) + (flinfo->info, h->root.root.string, + h->ref_regular ? NULL : h->root.u.undef.abfd, + NULL, 0, + flinfo->info->unresolved_syms_in_shared_libs == RM_GENERATE_ERROR); + + /* Strip a global symbol defined in a discarded section. */ + if (h->indx == -3) + return TRUE; } /* We should also warn if a forced local symbol is referenced from @@ -9126,16 +9335,19 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) hi = (struct elf_link_hash_entry *) hi->root.u.i.link; if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL) + /* xgettext:c-format */ msg = _("%B: internal symbol `%s' in %B is referenced by DSO"); else if (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN) + /* xgettext:c-format */ msg = _("%B: hidden symbol `%s' in %B is referenced by DSO"); else + /* xgettext:c-format */ msg = _("%B: local symbol `%s' in %B is referenced by DSO"); def_bfd = flinfo->output_bfd; if (hi->root.u.def.section != bfd_abs_section_ptr) def_bfd = hi->root.u.def.section->owner; - (*_bfd_error_handler) (msg, flinfo->output_bfd, def_bfd, - h->root.root.string); + _bfd_error_handler (msg, flinfo->output_bfd, def_bfd, + h->root.root.string); bfd_set_error (bfd_error_bad_value); eoinfo->failed = TRUE; return FALSE; @@ -9174,35 +9386,21 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) && (h->root.u.undef.abfd->flags & BFD_PLUGIN) != 0) strip = TRUE; + type = h->type; + /* If we're stripping it, and it's not a dynamic symbol, there's nothing else to do. However, if it is a forced local symbol or an ifunc symbol we need to give the backend finish_dynamic_symbol function a chance to make it dynamic. */ if (strip && h->dynindx == -1 - && h->type != STT_GNU_IFUNC + && type != STT_GNU_IFUNC && !h->forced_local) return TRUE; sym.st_value = 0; sym.st_size = h->size; sym.st_other = h->other; - if (local_bind) - { - sym.st_info = ELF_ST_INFO (STB_LOCAL, h->type); - /* Turn off visibility on local symbol. */ - sym.st_other &= ~ELF_ST_VISIBILITY (-1); - } - /* Set STB_GNU_UNIQUE only if symbol is defined in regular object. */ - else if (h->unique_global && h->def_regular) - sym.st_info = ELF_ST_INFO (STB_GNU_UNIQUE, h->type); - else if (h->root.type == bfd_link_hash_undefweak - || h->root.type == bfd_link_hash_defweak) - sym.st_info = ELF_ST_INFO (STB_WEAK, h->type); - else - sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type); - sym.st_target_internal = h->target_internal; - switch (h->root.type) { default: @@ -9228,7 +9426,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) input_sec->output_section); if (sym.st_shndx == SHN_BAD) { - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: could not find output section %A for input section %A"), flinfo->output_bfd, input_sec->output_section, input_sec); bfd_set_error (bfd_error_nonrepresentable_section); @@ -9277,6 +9476,42 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) return TRUE; } + if (type == STT_COMMON || type == STT_OBJECT) + switch (h->root.type) + { + case bfd_link_hash_common: + type = elf_link_convert_common_type (flinfo->info, type); + break; + case bfd_link_hash_defined: + case bfd_link_hash_defweak: + if (bed->common_definition (&sym)) + type = elf_link_convert_common_type (flinfo->info, type); + else + type = STT_OBJECT; + break; + case bfd_link_hash_undefined: + case bfd_link_hash_undefweak: + break; + default: + abort (); + } + + if (h->forced_local) + { + sym.st_info = ELF_ST_INFO (STB_LOCAL, type); + /* Turn off visibility on local symbol. */ + sym.st_other &= ~ELF_ST_VISIBILITY (-1); + } + /* Set STB_GNU_UNIQUE only if symbol is defined in regular object. */ + else if (h->unique_global && h->def_regular) + sym.st_info = ELF_ST_INFO (STB_GNU_UNIQUE, type); + else if (h->root.type == bfd_link_hash_undefweak + || h->root.type == bfd_link_hash_defweak) + sym.st_info = ELF_ST_INFO (STB_WEAK, type); + else + sym.st_info = ELF_ST_INFO (STB_GLOBAL, type); + sym.st_target_internal = h->target_internal; + /* Give the processor backend a chance to tweak the symbol value, and also to finish up anything that needs to be done for this symbol. FIXME: Not calling elf_backend_finish_dynamic_symbol for @@ -9313,7 +9548,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) || ELF_ST_BIND (sym.st_info) == STB_WEAK)) { int bindtype; - unsigned int type = ELF_ST_TYPE (sym.st_info); + type = ELF_ST_TYPE (sym.st_info); /* Turn an undefined IFUNC symbol into a normal FUNC symbol. */ if (type == STT_GNU_IFUNC) @@ -9346,12 +9581,15 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) const char *msg; if (ELF_ST_VISIBILITY (sym.st_other) == STV_PROTECTED) + /* xgettext:c-format */ msg = _("%B: protected symbol `%s' isn't defined"); else if (ELF_ST_VISIBILITY (sym.st_other) == STV_INTERNAL) + /* xgettext:c-format */ msg = _("%B: internal symbol `%s' isn't defined"); else + /* xgettext:c-format */ msg = _("%B: hidden symbol `%s' isn't defined"); - (*_bfd_error_handler) (msg, flinfo->output_bfd, h->root.root.string); + _bfd_error_handler (msg, flinfo->output_bfd, h->root.root.string); bfd_set_error (bfd_error_bad_value); eoinfo->failed = TRUE; return FALSE; @@ -9369,10 +9607,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) /* Since there is no version information in the dynamic string, if there is no version info in symbol version section, we will have a run-time problem if not linking executable, referenced - by shared library, not locally defined, or not bound locally. - */ + by shared library, or not bound locally. */ if (h->verinfo.verdef == NULL - && !local_bind && (!bfd_link_executable (flinfo->info) || h->ref_dynamic || !h->def_regular)) @@ -9381,7 +9617,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) if (p && p [1] != '\0') { - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: No symbol version section for versioned symbol `%s'"), flinfo->output_bfd, h->root.root.string); eoinfo->failed = TRUE; @@ -9985,7 +10222,8 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) { if (o->size != o->reloc_count * address_size) { - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("error: %B: size of section %A is not " "multiple of address size"), input_bfd, o); @@ -10032,7 +10270,8 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) char buffer [32]; sprintf_vma (buffer, rel->r_info); - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("error: %B contains a reloc (0x%s) for section %A " "that references a non-existent global symbol"), input_bfd, o, buffer); @@ -10117,6 +10356,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) BFD_ASSERT (r_symndx != STN_UNDEF); if (action_discarded & COMPLAIN) (*flinfo->info->callbacks->einfo) + /* xgettext:c-format */ (_("%X`%s' referenced in section `%A' of %B: " "defined in discarded section `%A' of %B\n"), sym_name, o, input_bfd, sec, sec->owner); @@ -10468,11 +10708,13 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) break; default: { - /* FIXME: octets_per_byte. */ if (! (o->flags & SEC_EXCLUDE)) { file_ptr offset = (file_ptr) o->output_offset; bfd_size_type todo = o->size; + + offset *= bfd_octets_per_byte (output_bfd); + if ((o->flags & SEC_ELF_REVERSE_COPY)) { /* Reverse-copy input section to output. */ @@ -10590,9 +10832,8 @@ elf_reloc_link_order (bfd *output_bfd, } else { - 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); indx = 0; } } @@ -10627,17 +10868,16 @@ elf_reloc_link_order (bfd *output_bfd, link_order->u.reloc.p->u.section); else sym_name = link_order->u.reloc.p->u.name; - if (! ((*info->callbacks->reloc_overflow) - (info, NULL, sym_name, howto->name, addend, NULL, - NULL, (bfd_vma) 0))) - { - free (buf); - return FALSE; - } + (*info->callbacks->reloc_overflow) (info, NULL, sym_name, + howto->name, addend, NULL, NULL, + (bfd_vma) 0); break; } + ok = bfd_set_section_contents (output_bfd, output_section, buf, - link_order->offset, size); + link_order->offset + * bfd_octets_per_byte (output_bfd), + size); free (buf); if (! ok) return FALSE; @@ -10705,6 +10945,7 @@ elf_get_linked_section_vma (struct bfd_link_order *p) = get_elf_backend_data (s->owner); if (bed->link_order_error_handler) bed->link_order_error_handler + /* xgettext:c-format */ (_("%B: warning: sh_link not set for section `%A'"), s->owner, s); return 0; } @@ -10784,13 +11025,16 @@ elf_fixup_link_order (bfd *abfd, asection *o) if (seen_other && seen_linkorder) { if (other_sec && linkorder_sec) - (*_bfd_error_handler) (_("%A has both ordered [`%A' in %B] and unordered [`%A' in %B] sections"), - o, linkorder_sec, - linkorder_sec->owner, other_sec, - other_sec->owner); + _bfd_error_handler + /* xgettext:c-format */ + (_("%A has both ordered [`%A' in %B] " + "and unordered [`%A' in %B] sections"), + o, linkorder_sec, + linkorder_sec->owner, other_sec, + other_sec->owner); else - (*_bfd_error_handler) (_("%A has both ordered and unordered sections"), - o); + _bfd_error_handler + (_("%A has both ordered and unordered sections"), o); bfd_set_error (bfd_error_bad_value); return FALSE; } @@ -10819,9 +11063,8 @@ elf_fixup_link_order (bfd *abfd, asection *o) { s = sections[n]->u.indirect.section; offset &= ~(bfd_vma) 0 << s->alignment_power; - s->output_offset = offset; + s->output_offset = offset / bfd_octets_per_byte (abfd); sections[n]->offset = offset; - /* FIXME: octets_per_byte. */ offset += sections[n]->size; } @@ -10829,6 +11072,108 @@ elf_fixup_link_order (bfd *abfd, asection *o) return TRUE; } +/* Generate an import library in INFO->implib_bfd from symbols in ABFD. + Returns TRUE upon success, FALSE otherwise. */ + +static bfd_boolean +elf_output_implib (bfd *abfd, struct bfd_link_info *info) +{ + bfd_boolean ret = FALSE; + bfd *implib_bfd; + const struct elf_backend_data *bed; + flagword flags; + enum bfd_architecture arch; + unsigned int mach; + asymbol **sympp = NULL; + long symsize; + long symcount; + long src_count; + elf_symbol_type *osymbuf; + + implib_bfd = info->out_implib_bfd; + bed = get_elf_backend_data (abfd); + + if (!bfd_set_format (implib_bfd, bfd_object)) + return FALSE; + + flags = bfd_get_file_flags (abfd); + flags &= ~HAS_RELOC; + if (!bfd_set_start_address (implib_bfd, 0) + || !bfd_set_file_flags (implib_bfd, flags)) + return FALSE; + + /* Copy architecture of output file to import library file. */ + arch = bfd_get_arch (abfd); + mach = bfd_get_mach (abfd); + if (!bfd_set_arch_mach (implib_bfd, arch, mach) + && (abfd->target_defaulted + || bfd_get_arch (abfd) != bfd_get_arch (implib_bfd))) + return FALSE; + + /* Get symbol table size. */ + symsize = bfd_get_symtab_upper_bound (abfd); + if (symsize < 0) + return FALSE; + + /* Read in the symbol table. */ + sympp = (asymbol **) xmalloc (symsize); + symcount = bfd_canonicalize_symtab (abfd, sympp); + if (symcount < 0) + goto free_sym_buf; + + /* Allow the BFD backend to copy any private header data it + understands from the output BFD to the import library BFD. */ + if (! bfd_copy_private_header_data (abfd, implib_bfd)) + goto free_sym_buf; + + /* Filter symbols to appear in the import library. */ + if (bed->elf_backend_filter_implib_symbols) + symcount = bed->elf_backend_filter_implib_symbols (abfd, info, sympp, + symcount); + else + symcount = _bfd_elf_filter_global_symbols (abfd, info, sympp, symcount); + if (symcount == 0) + { + bfd_set_error (bfd_error_no_symbols); + _bfd_error_handler (_("%B: no symbol found for import library"), + implib_bfd); + goto free_sym_buf; + } + + + /* Make symbols absolute. */ + osymbuf = (elf_symbol_type *) bfd_alloc2 (implib_bfd, symcount, + sizeof (*osymbuf)); + for (src_count = 0; src_count < symcount; src_count++) + { + memcpy (&osymbuf[src_count], (elf_symbol_type *) sympp[src_count], + sizeof (*osymbuf)); + osymbuf[src_count].symbol.section = bfd_abs_section_ptr; + osymbuf[src_count].internal_elf_sym.st_shndx = SHN_ABS; + osymbuf[src_count].symbol.value += sympp[src_count]->section->vma; + osymbuf[src_count].internal_elf_sym.st_value = + osymbuf[src_count].symbol.value; + sympp[src_count] = &osymbuf[src_count].symbol; + } + + bfd_set_symtab (implib_bfd, sympp, symcount); + + /* Allow the BFD backend to copy any private data it understands + from the output BFD to the import library BFD. This is done last + to permit the routine to look at the filtered symbol table. */ + if (! bfd_copy_private_bfd_data (abfd, implib_bfd)) + goto free_sym_buf; + + if (!bfd_close (implib_bfd)) + goto free_sym_buf; + + ret = TRUE; + +free_sym_buf: + free (sympp); + return ret; +} + static void elf_final_link_free (bfd *obfd, struct elf_final_link_info *flinfo) { @@ -10894,15 +11239,16 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) asection *attr_section = NULL; bfd_vma attr_size = 0; const char *std_attrs_section; + struct elf_link_hash_table *htab = elf_hash_table (info); - if (! is_elf_hash_table (info->hash)) + if (!is_elf_hash_table (htab)) return FALSE; if (bfd_link_pic (info)) abfd->flags |= DYNAMIC; - dynamic = elf_hash_table (info)->dynamic_sections_created; - dynobj = elf_hash_table (info)->dynobj; + dynamic = htab->dynamic_sections_created; + dynobj = htab->dynobj; emit_relocs = (bfd_link_relocatable (info) || info->emitrelocations); @@ -10988,6 +11334,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) for (p = o->map_head.link_order; p != NULL; p = p->next) { unsigned int reloc_count = 0; + unsigned int additional_reloc_count = 0; struct bfd_elf_section_data *esdi = NULL; if (p->type == bfd_section_reloc_link_order @@ -10998,7 +11345,6 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) asection *sec; sec = p->u.indirect.section; - esdi = elf_section_data (sec); /* Mark all sections which are to be included in the link. This will normally be every section. We need @@ -11009,29 +11355,18 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (sec->flags & SEC_MERGE) merged = TRUE; - if (esdo->this_hdr.sh_type == SHT_REL - || esdo->this_hdr.sh_type == SHT_RELA) - /* Some backends use reloc_count in relocation sections - to count particular types of relocs. Of course, - reloc sections themselves can't have relocations. */ - reloc_count = 0; - else if (emit_relocs) - reloc_count = sec->reloc_count; - else if (bed->elf_backend_count_relocs) - reloc_count = (*bed->elf_backend_count_relocs) (info, sec); - if (sec->rawsize > max_contents_size) max_contents_size = sec->rawsize; if (sec->size > max_contents_size) max_contents_size = sec->size; - /* We are interested in just local symbols, not all - symbols. */ if (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour && (sec->owner->flags & DYNAMIC) == 0) { size_t sym_count; + /* We are interested in just local symbols, not all + symbols. */ if (elf_bad_symtab (sec->owner)) sym_count = (elf_tdata (sec->owner)->symtab_hdr.sh_size / bed->s->sizeof_sym); @@ -11045,6 +11380,27 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) && elf_symtab_shndx_list (sec->owner) != NULL) max_sym_shndx_count = sym_count; + if (esdo->this_hdr.sh_type == SHT_REL + || esdo->this_hdr.sh_type == SHT_RELA) + /* Some backends use reloc_count in relocation sections + to count particular types of relocs. Of course, + reloc sections themselves can't have relocations. */ + ; + else if (emit_relocs) + { + reloc_count = sec->reloc_count; + if (bed->elf_backend_count_additional_relocs) + { + int c; + c = (*bed->elf_backend_count_additional_relocs) (sec); + additional_reloc_count += c; + } + } + else if (bed->elf_backend_count_relocs) + reloc_count = (*bed->elf_backend_count_relocs) (info, sec); + + esdi = elf_section_data (sec); + if ((sec->flags & SEC_RELOC) != 0) { size_t ext_size = 0; @@ -11065,14 +11421,21 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (reloc_count == 0) continue; + reloc_count += additional_reloc_count; o->reloc_count += reloc_count; if (p->type == bfd_indirect_link_order && emit_relocs) { if (esdi->rel.hdr) - esdo->rel.count += NUM_SHDR_ENTRIES (esdi->rel.hdr); + { + esdo->rel.count += NUM_SHDR_ENTRIES (esdi->rel.hdr); + esdo->rel.count += additional_reloc_count; + } if (esdi->rela.hdr) - esdo->rela.count += NUM_SHDR_ENTRIES (esdi->rela.hdr); + { + esdo->rela.count += NUM_SHDR_ENTRIES (esdi->rela.hdr); + esdo->rela.count += additional_reloc_count; + } } else { @@ -11103,8 +11466,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) } if (! bfd_link_relocatable (info) && merged) - elf_link_hash_traverse (elf_hash_table (info), - _bfd_elf_link_sec_merge_syms, abfd); + elf_link_hash_traverse (htab, _bfd_elf_link_sec_merge_syms, abfd); /* Figure out the file positions for everything but the symbol table and the relocs. We set symcount to force assign_section_numbers @@ -11167,11 +11529,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (max_sym_count < 20) max_sym_count = 20; - elf_hash_table (info)->strtabsize = max_sym_count; + htab->strtabsize = max_sym_count; amt = max_sym_count * sizeof (struct elf_sym_strtab); - elf_hash_table (info)->strtab - = (struct elf_sym_strtab *) bfd_malloc (amt); - if (elf_hash_table (info)->strtab == NULL) + htab->strtab = (struct elf_sym_strtab *) bfd_malloc (amt); + if (htab->strtab == NULL) goto error_return; /* The real buffer will be allocated in elf_link_swap_symbols_out. */ flinfo.symshndxbuf @@ -11283,12 +11644,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) goto error_return; } - if (elf_hash_table (info)->tls_sec) + if (htab->tls_sec) { bfd_vma base, end = 0; asection *sec; - for (sec = elf_hash_table (info)->tls_sec; + for (sec = htab->tls_sec; sec && (sec->flags & SEC_THREAD_LOCAL); sec = sec->next) { @@ -11304,13 +11665,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) } end = sec->vma + size; } - base = elf_hash_table (info)->tls_sec->vma; + base = htab->tls_sec->vma; /* Only align end of TLS section if static TLS doesn't have special alignment requirements. */ if (bed->static_tls_alignment == 1) - end = align_power (end, - elf_hash_table (info)->tls_sec->alignment_power); - elf_hash_table (info)->tls_size = end - base; + end = align_power (end, htab->tls_sec->alignment_power); + htab->tls_size = end - base; } /* Reorder SHF_LINK_ORDER sections. */ @@ -11379,19 +11739,25 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) { const char *iclass, *oclass; - if (bed->s->elfclass == ELFCLASS64) + switch (bed->s->elfclass) { - iclass = "ELFCLASS32"; - oclass = "ELFCLASS64"; + case ELFCLASS64: oclass = "ELFCLASS64"; break; + case ELFCLASS32: oclass = "ELFCLASS32"; break; + case ELFCLASSNONE: oclass = "ELFCLASSNONE"; break; + default: abort (); } - else + + switch (elf_elfheader (sub)->e_ident[EI_CLASS]) { - iclass = "ELFCLASS64"; - oclass = "ELFCLASS32"; + case ELFCLASS64: iclass = "ELFCLASS64"; break; + case ELFCLASS32: iclass = "ELFCLASS32"; break; + case ELFCLASSNONE: iclass = "ELFCLASSNONE"; break; + default: abort (); } bfd_set_error (bfd_error_wrong_format); - (*_bfd_error_handler) + _bfd_error_handler + /* xgettext:c-format */ (_("%B: file class %s incompatible with %s"), sub, iclass, oclass); } @@ -11452,17 +11818,18 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) symtab_hdr->sh_info = bfd_get_symcount (abfd); if (dynamic - && elf_hash_table (info)->dynsym != NULL - && (elf_hash_table (info)->dynsym->output_section - != bfd_abs_section_ptr)) + && htab->dynsym != NULL + && htab->dynsym->output_section != bfd_abs_section_ptr) { Elf_Internal_Sym sym; - bfd_byte *dynsym = elf_hash_table (info)->dynsym->contents; - long last_local = 0; + bfd_byte *dynsym = htab->dynsym->contents; + + o = htab->dynsym->output_section; + elf_section_data (o)->this_hdr.sh_info = htab->local_dynsymcount + 1; /* Write out the section symbols for the output sections. */ if (bfd_link_pic (info) - || elf_hash_table (info)->is_relocatable_executable) + || htab->is_relocatable_executable) { asection *s; @@ -11488,17 +11855,15 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) return FALSE; sym.st_value = s->vma; dest = dynsym + dynindx * bed->s->sizeof_sym; - if (last_local < dynindx) - last_local = dynindx; bed->s->swap_symbol_out (abfd, &sym, dest, 0); } } /* Write out the local dynsyms. */ - if (elf_hash_table (info)->dynlocal) + if (htab->dynlocal) { struct elf_link_local_dynamic_entry *e; - for (e = elf_hash_table (info)->dynlocal; e ; e = e->next) + for (e = htab->dynlocal; e ; e = e->next) { asection *s; bfd_byte *dest; @@ -11522,16 +11887,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) + e->isym.st_value); } - if (last_local < e->dynindx) - last_local = e->dynindx; - dest = dynsym + e->dynindx * bed->s->sizeof_sym; bed->s->swap_symbol_out (abfd, &sym, dest, 0); } } - - elf_section_data (elf_hash_table (info)->dynsym->output_section)->this_hdr.sh_info = - last_local + 1; } /* We get the global symbols from the hash table. */ @@ -11592,7 +11951,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr; /* sh_name was set in prep_headers. */ symstrtab_hdr->sh_type = SHT_STRTAB; - symstrtab_hdr->sh_flags = 0; + symstrtab_hdr->sh_flags = bed->elf_strtab_flags; symstrtab_hdr->sh_addr = 0; symstrtab_hdr->sh_size = _bfd_elf_strtab_size (flinfo.symstrtab); symstrtab_hdr->sh_entsize = 0; @@ -11610,6 +11969,13 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) return FALSE; } + if (info->out_implib_bfd && !elf_output_implib (abfd, info)) + { + _bfd_error_handler (_("%B: failed to generate import library"), + info->out_implib_bfd); + return FALSE; + } + /* Adjust the relocs to have the correct symbol indices. */ for (o = abfd->sections; o != NULL; o = o->next) { @@ -11620,10 +11986,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) sort = bed->sort_relocs_p == NULL || (*bed->sort_relocs_p) (o); if (esdo->rel.hdr != NULL - && !elf_link_adjust_relocs (abfd, &esdo->rel, sort)) + && !elf_link_adjust_relocs (abfd, o, &esdo->rel, sort)) return FALSE; if (esdo->rela.hdr != NULL - && !elf_link_adjust_relocs (abfd, &esdo->rela, sort)) + && !elf_link_adjust_relocs (abfd, o, &esdo->rela, sort)) return FALSE; /* Set the reloc_count field to 0 to prevent write_relocs from @@ -11682,8 +12048,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) { struct elf_link_hash_entry *h; - h = elf_link_hash_lookup (elf_hash_table (info), name, - FALSE, FALSE, TRUE); + h = elf_link_hash_lookup (htab, name, FALSE, FALSE, TRUE); if (h != NULL && (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak)) @@ -11706,35 +12071,37 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) case DT_PREINIT_ARRAYSZ: name = ".preinit_array"; - goto get_size; + goto get_out_size; case DT_INIT_ARRAYSZ: name = ".init_array"; - goto get_size; + goto get_out_size; case DT_FINI_ARRAYSZ: name = ".fini_array"; - get_size: + get_out_size: o = bfd_get_section_by_name (abfd, name); if (o == NULL) { - (*_bfd_error_handler) - (_("%B: could not find output section %s"), abfd, name); + _bfd_error_handler + (_("could not find section %s"), name); goto error_return; } if (o->size == 0) - (*_bfd_error_handler) + _bfd_error_handler (_("warning: %s section has zero size"), name); dyn.d_un.d_val = o->size; break; case DT_PREINIT_ARRAY: name = ".preinit_array"; - goto get_vma; + goto get_out_vma; case DT_INIT_ARRAY: name = ".init_array"; - goto get_vma; + goto get_out_vma; case DT_FINI_ARRAY: name = ".fini_array"; - goto get_vma; + get_out_vma: + o = bfd_get_section_by_name (abfd, name); + goto do_vma; case DT_HASH: name = ".hash"; @@ -11757,21 +12124,22 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) case DT_VERSYM: name = ".gnu.version"; get_vma: - o = bfd_get_section_by_name (abfd, name); + o = bfd_get_linker_section (dynobj, name); + do_vma: if (o == NULL) { - (*_bfd_error_handler) - (_("%B: could not find output section %s"), abfd, name); + _bfd_error_handler + (_("could not find section %s"), name); goto error_return; } if (elf_section_data (o->output_section)->this_hdr.sh_type == SHT_NOTE) { - (*_bfd_error_handler) + _bfd_error_handler (_("warning: section '%s' is being made into a note"), name); bfd_set_error (bfd_error_nonrepresentable_section); goto error_return; } - dyn.d_un.d_ptr = o->vma; + dyn.d_un.d_ptr = o->output_section->vma + o->output_offset; break; case DT_REL: @@ -11802,6 +12170,18 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) } } } + if (bed->dtrel_excludes_plt && htab->srelplt != NULL) + { + /* Don't count procedure linkage table relocs in the + overall reloc count. */ + if (dyn.d_tag == DT_RELSZ || dyn.d_tag == DT_RELASZ) + dyn.d_un.d_val -= htab->srelplt->size; + /* If .rela.plt is the first .rela section, exclude + it from DT_RELA. */ + else if (dyn.d_un.d_ptr == (htab->srelplt->output_section->vma + + htab->srelplt->output_offset)) + dyn.d_un.d_ptr += htab->srelplt->size; + } break; } bed->s->swap_dyn_out (dynobj, &dyn, dyncon); @@ -11854,16 +12234,16 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) created by _bfd_elf_link_create_dynamic_sections. */ continue; } - if (elf_hash_table (info)->stab_info.stabstr == o) + if (htab->stab_info.stabstr == o) continue; - if (elf_hash_table (info)->eh_info.hdr_sec == o) + if (htab->eh_info.hdr_sec == o) continue; if (strcmp (o->name, ".dynstr") != 0) { - /* FIXME: octets_per_byte. */ if (! bfd_set_section_contents (abfd, o->output_section, o->contents, - (file_ptr) o->output_offset, + (file_ptr) o->output_offset + * bfd_octets_per_byte (abfd), o->size)) goto error_return; } @@ -11875,8 +12255,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) off = elf_section_data (o->output_section)->this_hdr.sh_offset; if (bfd_seek (abfd, off, SEEK_SET) != 0 - || ! _bfd_elf_strtab_emit (abfd, - elf_hash_table (info)->dynstr)) + || !_bfd_elf_strtab_emit (abfd, htab->dynstr)) goto error_return; } } @@ -11892,9 +12271,9 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) } /* If we have optimized stabs strings, output them. */ - if (elf_hash_table (info)->stab_info.stabstr != NULL) + if (htab->stab_info.stabstr != NULL) { - if (! _bfd_write_stab_strings (abfd, &elf_hash_table (info)->stab_info)) + if (!_bfd_write_stab_strings (abfd, &htab->stab_info)) goto error_return; } @@ -12087,6 +12466,55 @@ _bfd_elf_gc_mark_hook (asection *sec, return NULL; } +/* For undefined __start_ and __stop_ symbols, return the + first input section matching . Return NULL otherwise. */ + +asection * +_bfd_elf_is_start_stop (const struct bfd_link_info *info, + struct elf_link_hash_entry *h) +{ + asection *s; + const char *sec_name; + + if (h->root.type != bfd_link_hash_undefined + && h->root.type != bfd_link_hash_undefweak) + return NULL; + + s = h->root.u.undef.section; + if (s != NULL) + { + if (s == (asection *) 0 - 1) + return NULL; + return s; + } + + sec_name = NULL; + if (strncmp (h->root.root.string, "__start_", 8) == 0) + sec_name = h->root.root.string + 8; + else if (strncmp (h->root.root.string, "__stop_", 7) == 0) + sec_name = h->root.root.string + 7; + + if (sec_name != NULL && *sec_name != '\0') + { + bfd *i; + + for (i = info->input_bfds; i != NULL; i = i->link.next) + { + s = bfd_get_section_by_name (i, sec_name); + if (s != NULL) + { + h->root.u.undef.section = s; + break; + } + } + } + + if (s == NULL) + h->root.u.undef.section = (asection *) 0 - 1; + + return s; +} + /* COOKIE->rel describes a relocation against section SEC, which is a section we've decided to keep. Return the section that contains the relocation symbol, or NULL if no section contains it. */ @@ -12125,34 +12553,19 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec, if (h->u.weakdef != NULL) h->u.weakdef->mark = 1; - if (start_stop != NULL - && (h->root.type == bfd_link_hash_undefined - || h->root.type == bfd_link_hash_undefweak)) + if (start_stop != NULL) { /* To work around a glibc bug, mark all XXX input sections when there is an as yet undefined reference to __start_XXX or __stop_XXX symbols. The linker will later define such symbols for orphan input sections that have a name representable as a C identifier. */ - const char *sec_name = NULL; - if (strncmp (h->root.root.string, "__start_", 8) == 0) - sec_name = h->root.root.string + 8; - else if (strncmp (h->root.root.string, "__stop_", 7) == 0) - sec_name = h->root.root.string + 7; + asection *s = _bfd_elf_is_start_stop (info, h); - if (sec_name != NULL && *sec_name != '\0') + if (s != NULL) { - bfd *i; - - for (i = info->input_bfds; i != NULL; i = i->link.next) - { - asection *s = bfd_get_section_by_name (i, sec_name); - if (s != NULL && !s->gc_mark) - { - *start_stop = TRUE; - return s; - } - } + *start_stop = !s->gc_mark; + return s; } } @@ -12179,8 +12592,6 @@ _bfd_elf_gc_mark_reloc (struct bfd_link_info *info, rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie, &start_stop); while (rsec != NULL) { - asection *s; - if (!rsec->gc_mark) { if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour @@ -12191,22 +12602,7 @@ _bfd_elf_gc_mark_reloc (struct bfd_link_info *info, } if (!start_stop) break; - s = bfd_get_next_section_by_name (rsec); - if (s == NULL) - { - bfd *i = rsec->owner; - - if (i != NULL) - { - while ((i = i->link.next) != NULL) - { - s = bfd_get_section_by_name (i, rsec->name); - if (s != NULL) - break; - } - } - } - rsec = s; + rsec = bfd_get_next_section_by_name (rsec->owner, rsec); } return TRUE; } @@ -12489,6 +12885,7 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info) o->flags |= SEC_EXCLUDE; if (info->print_gc_sections && o->size != 0) + /* xgettext:c-format */ _bfd_error_handler (_("Removing unused section '%s' in file '%B'"), sub, o->name); /* But we also have to update some of the relocation @@ -12654,6 +13051,7 @@ bfd_elf_gc_mark_dynamic_ref_symbol (struct elf_link_hash_entry *h, void *inf) && ELF_ST_VISIBILITY (h->other) != STV_INTERNAL && ELF_ST_VISIBILITY (h->other) != STV_HIDDEN && (!bfd_link_executable (info) + || info->gc_keep_exported || info->export_dynamic || (h->dynamic && d != NULL @@ -12684,7 +13082,8 @@ _bfd_elf_gc_keep (struct bfd_link_info *info) if (h != NULL && (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) - && !bfd_is_abs_section (h->root.u.def.section)) + && !bfd_is_abs_section (h->root.u.def.section) + && !bfd_is_und_section (h->root.u.def.section)) h->root.u.def.section->flags |= SEC_KEEP; } } @@ -12733,7 +13132,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info) if (!bed->can_gc_sections || !is_elf_hash_table (info->hash)) { - (*_bfd_error_handler)(_("Warning: gc-sections option ignored")); + _bfd_error_handler(_("Warning: gc-sections option ignored")); return TRUE; } @@ -12757,7 +13156,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info) && (sec->flags & SEC_LINKER_CREATED) == 0) elf_eh_frame_section (sub) = sec; fini_reloc_cookie_for_section (&cookie, sec); - sec = bfd_get_next_section_by_name (sec); + sec = bfd_get_next_section_by_name (NULL, sec); } } @@ -12772,7 +13171,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info) return FALSE; /* Mark dynamically referenced symbols. */ - if (htab->dynamic_sections_created) + if (htab->dynamic_sections_created || info->gc_keep_exported) elf_link_hash_traverse (htab, bed->gc_mark_dynamic_ref, info); /* Grovel through relocs to find out who stays ... */ @@ -12817,7 +13216,7 @@ bfd_elf_gc_record_vtinherit (bfd *abfd, { struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; struct elf_link_hash_entry **search, *child; - bfd_size_type extsymcount; + size_t extsymcount; const struct elf_backend_data *bed = get_elf_backend_data (abfd); /* The sh_info field of the symtab header tells us where the @@ -12842,8 +13241,9 @@ bfd_elf_gc_record_vtinherit (bfd *abfd, goto win; } - (*_bfd_error_handler) ("%B: %A+%lu: No symbol found for INHERIT", - abfd, sec, (unsigned long) offset); + /* xgettext:c-format */ + _bfd_error_handler (_("%B: %A+%lu: No symbol found for INHERIT"), + abfd, sec, (unsigned long) offset); bfd_set_error (bfd_error_invalid_operation); return FALSE; @@ -13090,7 +13490,7 @@ bfd_elf_gc_common_finalize_got_offsets (bfd *abfd, for (i = info->input_bfds; i; i = i->link.next) { bfd_signed_vma *local_got; - bfd_size_type j, locsymcount; + size_t j, locsymcount; Elf_Internal_Shdr *symtab_hdr; if (bfd_get_flavour (i) != bfd_target_elf_flavour)