X-Git-Url: http://drtracing.org/?a=blobdiff_plain;ds=sidebyside;f=bfd%2Felflink.c;h=5bc57408e47056d8c393f7247ab6312927c598cc;hb=c88960d081f0b37ec03c66a13115e2a68e40d1ad;hp=89a6dea761407612cd4a2ffa0956918554093c9a;hpb=1a6e6083b69dcb695e175b5dc02342391da6ba22;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elflink.c b/bfd/elflink.c index 89a6dea761..5bc57408e4 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -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. */ @@ -204,7 +208,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 +472,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 +523,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 +546,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 +578,19 @@ bfd_elf_record_link_assignment (bfd *output_bfd, if (h == NULL) return provide; + 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: @@ -632,9 +668,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 +702,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 +757,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; @@ -874,11 +909,11 @@ _bfd_elf_link_renumber_dynsyms (bfd *output_bfd, 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. We always create the dynsym - section, even if it is empty, with dynamic sections. */ - if (elf_hash_table (info)->dynamic_sections_created) - ++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 +1206,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; @@ -1450,10 +1484,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 +1504,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 +1643,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 +1784,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. */ @@ -2049,7 +2108,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 +2197,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; @@ -3058,9 +3116,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 +3128,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 +3246,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 +3296,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 +3421,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 +3453,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 +3531,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 +3603,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 +3628,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; @@ -3604,8 +3750,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) make a shared library. */ if (!just_syms && (bfd_link_pic (info) - || info->export_dynamic - || info->dynamic) + || (!bfd_link_relocatable (info) + && (info->export_dynamic || info->dynamic))) && is_elf_hash_table (htab) && info->output_bfd->xvec == abfd->xvec && !htab->dynamic_sections_created) @@ -3847,7 +3993,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; @@ -3926,8 +4073,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++) { @@ -3969,6 +4117,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; @@ -3979,6 +4128,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) @@ -4029,6 +4179,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) @@ -4264,6 +4415,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. */ @@ -4272,6 +4428,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; @@ -4409,7 +4570,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) @@ -4552,7 +4714,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. */ @@ -4576,7 +4738,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); @@ -4638,7 +4801,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; @@ -4651,9 +4816,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 @@ -4714,7 +4876,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) { @@ -4785,7 +4947,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; @@ -4918,57 +5081,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. */ @@ -5023,6 +5138,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) @@ -5204,7 +5321,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; @@ -5693,14 +5810,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; @@ -5781,7 +5898,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; } @@ -5795,12 +5912,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; @@ -5810,11 +5927,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; } @@ -5825,11 +5942,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; } @@ -5837,22 +5954,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; } @@ -6160,7 +6277,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); @@ -6170,13 +6287,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; } @@ -6395,7 +6512,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) @@ -6408,7 +6525,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); @@ -6427,7 +6544,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) @@ -6540,8 +6657,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); @@ -6562,17 +6678,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; @@ -7210,7 +7323,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; }; @@ -7244,12 +7357,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) @@ -7296,7 +7409,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)); @@ -7314,12 +7427,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; @@ -7382,7 +7495,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; @@ -7734,10 +7847,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; @@ -7750,6 +7868,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); @@ -7760,7 +7879,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; } @@ -7842,7 +7961,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)) { @@ -7855,7 +7974,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; @@ -8079,8 +8198,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: " @@ -8112,8 +8231,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; } @@ -8450,6 +8569,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; @@ -8465,7 +8585,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 @@ -8486,8 +8606,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; } @@ -8503,8 +8624,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; } @@ -8516,9 +8638,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; } @@ -8540,8 +8663,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; } @@ -8557,8 +8681,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; } @@ -8570,9 +8695,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; } @@ -8648,8 +8774,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) { @@ -8685,6 +8810,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) { @@ -8693,8 +8847,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; @@ -8783,7 +8936,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; @@ -8804,8 +8958,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) { @@ -8900,7 +9054,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; @@ -8922,9 +9077,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; @@ -9026,6 +9181,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 @@ -9045,6 +9222,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) const struct elf_backend_data *bed; long indx; int ret; + unsigned int type; /* 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. */ @@ -9097,19 +9275,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 @@ -9179,35 +9353,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: @@ -9282,6 +9442,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 (local_bind) + { + 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 @@ -9318,7 +9514,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) @@ -10473,11 +10669,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. */ @@ -10595,9 +10793,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; } } @@ -10632,17 +10829,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; @@ -10824,9 +11020,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; } @@ -10834,6 +11029,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) { @@ -11618,7 +11915,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; @@ -11636,6 +11933,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) { @@ -11732,18 +12036,18 @@ 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); + (_("could not find section %s"), name); goto error_return; } if (o->size == 0) @@ -11754,13 +12058,15 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) 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"; @@ -11783,11 +12089,12 @@ 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); + (_("could not find section %s"), name); goto error_return; } if (elf_section_data (o->output_section)->this_hdr.sh_type == SHT_NOTE) @@ -11797,7 +12104,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) 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: @@ -11886,10 +12193,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) 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; } @@ -12113,6 +12420,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. */ @@ -12151,34 +12507,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; } } @@ -12826,7 +13167,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 @@ -13099,7 +13440,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)