X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felflink.h;h=54577a66b984c1781b4fd817b50e27a279d4c09e;hb=f6af82bd4470673eef9562d4ed3a2717c1d749ab;hp=057dc5e92ad3f31dcfc4ac1699057a36314dbf47;hpb=c7ac6ff835615a523fe86575cd5fae3f93f88430;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elflink.h b/bfd/elflink.h index 057dc5e92a..54577a66b9 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -48,18 +48,17 @@ static boolean elf_link_find_version_dependencies PARAMS ((struct elf_link_hash_entry *, PTR)); static boolean elf_link_assign_sym_version PARAMS ((struct elf_link_hash_entry *, PTR)); -static boolean elf_link_renumber_dynsyms - PARAMS ((struct elf_link_hash_entry *, PTR)); static boolean elf_collect_hash_codes PARAMS ((struct elf_link_hash_entry *, PTR)); static boolean elf_link_read_relocs_from_section PARAMS ((bfd *, Elf_Internal_Shdr *, PTR, Elf_Internal_Rela *)); -static void elf_link_remove_section_and_adjust_dynindices - PARAMS ((struct bfd_link_info *, asection *)); static void elf_link_output_relocs PARAMS ((bfd *, asection *, Elf_Internal_Shdr *, Elf_Internal_Rela *)); static boolean elf_link_size_reloc_section PARAMS ((bfd *, Elf_Internal_Shdr *, asection *)); +static void elf_link_adjust_relocs + PARAMS ((bfd *, Elf_Internal_Shdr *, unsigned int, + struct elf_link_hash_entry **)); /* Given an ELF BFD, add symbols to the global hash table as appropriate. */ @@ -81,6 +80,138 @@ elf_bfd_link_add_symbols (abfd, info) } } +/* Return true iff this is a non-common definition of a symbol. */ +static boolean +is_global_symbol_definition (abfd, sym) + bfd * abfd; + Elf_Internal_Sym * sym; +{ + /* Local symbols do not count, but target specific ones might. */ + if (ELF_ST_BIND (sym->st_info) != STB_GLOBAL + && ELF_ST_BIND (sym->st_info) < STB_LOOS) + return false; + + /* If the section is undefined, then so is the symbol. */ + if (sym->st_shndx == SHN_UNDEF) + return false; + + /* If the symbol is defined in the common section, then + it is a common definition and so does not count. */ + if (sym->st_shndx == SHN_COMMON) + return false; + + /* If the symbol is in a target specific section then we + must rely upon the backend to tell us what it is. */ + if (sym->st_shndx >= SHN_LORESERVE && sym->st_shndx < SHN_ABS) + /* FIXME - this function is not coded yet: + + return _bfd_is_global_symbol_definition (abfd, sym); + + Instead for now assume that the definition is not global, + Even if this is wrong, at least the linker will behave + in the same way that it used to do. */ + return false; + + return true; +} + + +/* Search the symbol table of the archive element of the archive ABFD + whoes archove map contains a mention of SYMDEF, and determine if + the symbol is defined in this element. */ +static boolean +elf_link_is_defined_archive_symbol (abfd, symdef) + bfd * abfd; + carsym * symdef; +{ + Elf_Internal_Shdr * hdr; + Elf_External_Sym * esym; + Elf_External_Sym * esymend; + Elf_External_Sym * buf = NULL; + size_t symcount; + size_t extsymcount; + size_t extsymoff; + boolean result = false; + + abfd = _bfd_get_elt_at_filepos (abfd, symdef->file_offset); + if (abfd == (bfd *) NULL) + return false; + + if (! bfd_check_format (abfd, bfd_object)) + return false; + + /* If we have already included the element containing this symbol in the + link then we do not need to include it again. Just claim that any symbol + it contains is not a definition, so that our caller will not decide to + (re)include this element. */ + if (abfd->archive_pass) + return false; + + /* Select the appropriate symbol table. */ + if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0) + hdr = &elf_tdata (abfd)->symtab_hdr; + else + hdr = &elf_tdata (abfd)->dynsymtab_hdr; + + symcount = hdr->sh_size / sizeof (Elf_External_Sym); + + /* The sh_info field of the symtab header tells us where the + external symbols start. We don't care about the local symbols. */ + if (elf_bad_symtab (abfd)) + { + extsymcount = symcount; + extsymoff = 0; + } + else + { + extsymcount = symcount - hdr->sh_info; + extsymoff = hdr->sh_info; + } + + buf = ((Elf_External_Sym *) + bfd_malloc (extsymcount * sizeof (Elf_External_Sym))); + if (buf == NULL && extsymcount != 0) + return false; + + /* Read in the symbol table. + FIXME: This ought to be cached somewhere. */ + if (bfd_seek (abfd, + hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym), + SEEK_SET) != 0 + || (bfd_read ((PTR) buf, sizeof (Elf_External_Sym), extsymcount, abfd) + != extsymcount * sizeof (Elf_External_Sym))) + { + free (buf); + return false; + } + + /* Scan the symbol table looking for SYMDEF. */ + esymend = buf + extsymcount; + for (esym = buf; + esym < esymend; + esym++) + { + Elf_Internal_Sym sym; + const char * name; + + elf_swap_symbol_in (abfd, esym, & sym); + + name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, sym.st_name); + if (name == (const char *) NULL) + break; + + if (strcmp (name, symdef->name) == 0) + { + result = is_global_symbol_definition (abfd, & sym); + break; + } + } + + free (buf); + + return result; +} + /* Add symbols from an ELF archive file to the linker hash table. We don't use _bfd_generic_link_add_archive_symbols because of a @@ -201,7 +332,24 @@ elf_link_add_archive_symbols (abfd, info) if (h == NULL) continue; - if (h->root.type != bfd_link_hash_undefined) + if (h->root.type == bfd_link_hash_common) + { + /* We currently have a common symbol. The archive map contains + a reference to this symbol, so we may want to include it. We + only want to include it however, if this archive element + contains a definition of the symbol, not just another common + declaration of it. + + Unfortunately some archivers (including GNU ar) will put + declarations of common symbols into their archive maps, as + well as real definitions, so we cannot just go by the archive + map alone. Instead we must read in the element's symbol + table and check that to see what kind of symbol definition + this is. */ + if (! elf_link_is_defined_archive_symbol (abfd, symdef)) + continue; + } + else if (h->root.type != bfd_link_hash_undefined) { if (h->root.type != bfd_link_hash_undefweak) defined[i] = true; @@ -369,8 +517,12 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash, /* In cases involving weak versioned symbols, we may wind up trying to merge a symbol with itself. Catch that here, to avoid the confusion that results if we try to override a symbol with - itself. */ - if (abfd == oldbfd) + itself. The additional tests catch cases like + _GLOBAL_OFFSET_TABLE_, which are regular symbols defined in a + dynamic object, which we do want to handle here. */ + if (abfd == oldbfd + && ((abfd->flags & DYNAMIC) == 0 + || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)) return true; /* NEWDYN and OLDDYN indicate whether the new or old symbol, @@ -381,10 +533,35 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash, else newdyn = false; - if (oldbfd == NULL || (oldbfd->flags & DYNAMIC) == 0) - olddyn = false; + if (oldbfd != NULL) + olddyn = (oldbfd->flags & DYNAMIC) != 0; else - olddyn = true; + { + asection *hsec; + + /* This code handles the special SHN_MIPS_{TEXT,DATA} section + indices used by MIPS ELF. */ + switch (h->root.type) + { + default: + hsec = NULL; + break; + + case bfd_link_hash_defined: + case bfd_link_hash_defweak: + hsec = h->root.u.def.section; + break; + + case bfd_link_hash_common: + hsec = h->root.u.c.p->section; + break; + } + + if (hsec == NULL) + olddyn = false; + else + olddyn = (hsec->symbol->flags & BSF_DYNAMIC) != 0; + } /* NEWDEF and OLDDEF indicate whether the new or old symbol, respectively, appear to be a definition rather than reference. */ @@ -655,8 +832,12 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash, /* To make this work we have to frob the flags so that the rest of the code does not think we are using the regular definition. */ - h->elf_link_hash_flags &= ~ ELF_LINK_HASH_DEF_REGULAR; - h->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR; + if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0) + h->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR; + else if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0) + h->elf_link_hash_flags |= ELF_LINK_HASH_REF_DYNAMIC; + h->elf_link_hash_flags &= ~ (ELF_LINK_HASH_DEF_REGULAR + | ELF_LINK_HASH_DEF_DYNAMIC); /* If H is the target of an indirection, we want the caller to use H rather than the indirect symbol. Otherwise if we are @@ -709,9 +890,11 @@ elf_link_add_object_symbols (abfd, info) struct elf_link_hash_entry *weaks; Elf_External_Sym *esym; Elf_External_Sym *esymend; + struct elf_backend_data *bed; - add_symbol_hook = get_elf_backend_data (abfd)->elf_add_symbol_hook; - collect = get_elf_backend_data (abfd)->collect; + bed = get_elf_backend_data (abfd); + add_symbol_hook = bed->elf_add_symbol_hook; + collect = bed->collect; if ((abfd->flags & DYNAMIC) == 0) dynamic = false; @@ -926,6 +1109,23 @@ elf_link_add_object_symbols (abfd, info) goto error_return; link = elf_elfsections (abfd)[elfsec]->sh_link; + { + /* The shared libraries distributed with hpux11 have a bogus + sh_link field for the ".dynamic" section. This code detects + when LINK refers to a section that is not a string table and + tries to find the string table for the ".dynsym" section + instead. */ + Elf_Internal_Shdr *hdr = elf_elfsections (abfd)[link]; + if (hdr->sh_type != SHT_STRTAB) + { + asection *s = bfd_get_section_by_name (abfd, ".dynsym"); + int elfsec = _bfd_elf_section_from_bfd_section (abfd, s); + if (elfsec == -1) + goto error_return; + link = elf_elfsections (abfd)[elfsec]->sh_link; + } + } + extdyn = dynbuf; extdynend = extdyn + s->_raw_size / sizeof (Elf_External_Dyn); for (; extdyn < extdynend; extdyn++) @@ -1368,9 +1568,24 @@ elf_link_add_object_symbols (abfd, info) h->type = ELF_ST_TYPE (sym.st_info); } - if (sym.st_other != 0 - && (definition || h->other == 0)) - h->other = sym.st_other; + /* If st_other has a processor-specific meaning, specific code + might be needed here. */ + if (sym.st_other != 0) + { + /* Combine visibilities, using the most constraining one. */ + unsigned char hvis = ELF_ST_VISIBILITY (h->other); + unsigned char symvis = ELF_ST_VISIBILITY (sym.st_other); + + if (symvis && (hvis > symvis || hvis == 0)) + h->other = sym.st_other; + + /* If neither has visibility, use the st_other of the + definition. This is an arbitrary choice, since the + other bits have no general meaning. */ + if (!symvis && !hvis + && (definition || h->other == 0)) + h->other = sym.st_other; + } /* Set a flag in the hash table entry indicating the type of reference or definition we just found. Keep a count of @@ -1521,44 +1736,7 @@ elf_link_add_object_symbols (abfd, info) == 0); ht = (struct elf_link_hash_entry *) hi->root.u.i.link; - - /* Copy down any references that we may have - already seen to the symbol which just became - indirect. */ - ht->elf_link_hash_flags |= - (hi->elf_link_hash_flags - & (ELF_LINK_HASH_REF_DYNAMIC - | ELF_LINK_HASH_REF_REGULAR - | ELF_LINK_HASH_REF_REGULAR_NONWEAK)); - - /* Copy over the global and procedure linkage table - offset entries. These may have been already set - up by a check_relocs routine. */ - if (ht->got.offset == (bfd_vma) -1) - { - ht->got.offset = hi->got.offset; - hi->got.offset = (bfd_vma) -1; - } - BFD_ASSERT (hi->got.offset == (bfd_vma) -1); - - if (ht->plt.offset == (bfd_vma) -1) - { - ht->plt.offset = hi->plt.offset; - hi->plt.offset = (bfd_vma) -1; - } - BFD_ASSERT (hi->plt.offset == (bfd_vma) -1); - - if (ht->dynindx == -1) - { - ht->dynindx = hi->dynindx; - ht->dynstr_index = hi->dynstr_index; - hi->dynindx = -1; - hi->dynstr_index = 0; - } - BFD_ASSERT (hi->dynindx == -1); - - /* FIXME: There may be other information to copy - over for particular targets. */ + (*bed->elf_backend_copy_indirect_symbol) (ht, hi); /* See if the new flags lead us to realize that the symbol must be dynamic. */ @@ -1631,43 +1809,7 @@ elf_link_add_object_symbols (abfd, info) | ELF_LINK_HASH_DEF_REGULAR)) == 0); - /* Copy down any references that we may have - already seen to the symbol which just - became indirect. */ - h->elf_link_hash_flags |= - (hi->elf_link_hash_flags - & (ELF_LINK_HASH_REF_DYNAMIC - | ELF_LINK_HASH_REF_REGULAR - | ELF_LINK_HASH_REF_REGULAR_NONWEAK)); - - /* Copy over the global and procedure linkage - table offset entries. These may have been - already set up by a check_relocs routine. */ - if (h->got.offset == (bfd_vma) -1) - { - h->got.offset = hi->got.offset; - hi->got.offset = (bfd_vma) -1; - } - BFD_ASSERT (hi->got.offset == (bfd_vma) -1); - - if (h->plt.offset == (bfd_vma) -1) - { - h->plt.offset = hi->plt.offset; - hi->plt.offset = (bfd_vma) -1; - } - BFD_ASSERT (hi->got.offset == (bfd_vma) -1); - - if (h->dynindx == -1) - { - h->dynindx = hi->dynindx; - h->dynstr_index = hi->dynstr_index; - hi->dynindx = -1; - hi->dynstr_index = 0; - } - BFD_ASSERT (hi->dynindx == -1); - - /* FIXME: There may be other information to - copy over for particular targets. */ + (*bed->elf_backend_copy_indirect_symbol) (h, hi); /* See if the new flags lead us to realize that the symbol must be dynamic. */ @@ -2051,6 +2193,76 @@ elf_add_dynamic_entry (info, tag, val) return true; } + +/* Record a new local dynamic symbol. */ + +boolean +elf_link_record_local_dynamic_symbol (info, input_bfd, input_indx) + struct bfd_link_info *info; + bfd *input_bfd; + long input_indx; +{ + struct elf_link_local_dynamic_entry *entry; + struct elf_link_hash_table *eht; + struct bfd_strtab_hash *dynstr; + Elf_External_Sym esym; + unsigned long dynstr_index; + char *name; + + /* See if the entry exists already. */ + for (entry = elf_hash_table (info)->dynlocal; entry ; entry = entry->next) + if (entry->input_bfd == input_bfd && entry->input_indx == input_indx) + return true; + + entry = (struct elf_link_local_dynamic_entry *) + bfd_alloc (input_bfd, sizeof (*entry)); + if (entry == NULL) + return false; + + /* Go find the symbol, so that we can find it's name. */ + if (bfd_seek (input_bfd, + (elf_tdata (input_bfd)->symtab_hdr.sh_offset + + input_indx * sizeof (Elf_External_Sym)), + SEEK_SET) != 0 + || (bfd_read (&esym, sizeof (Elf_External_Sym), 1, input_bfd) + != sizeof (Elf_External_Sym))) + return false; + elf_swap_symbol_in (input_bfd, &esym, &entry->isym); + + name = (bfd_elf_string_from_elf_section + (input_bfd, elf_tdata (input_bfd)->symtab_hdr.sh_link, + entry->isym.st_name)); + + dynstr = elf_hash_table (info)->dynstr; + if (dynstr == NULL) + { + /* Create a strtab to hold the dynamic symbol names. */ + elf_hash_table (info)->dynstr = dynstr = _bfd_elf_stringtab_init (); + if (dynstr == NULL) + return false; + } + + dynstr_index = _bfd_stringtab_add (dynstr, name, true, false); + if (dynstr_index == (unsigned long) -1) + return false; + entry->isym.st_name = dynstr_index; + + eht = elf_hash_table (info); + + entry->next = eht->dynlocal; + eht->dynlocal = entry; + entry->input_bfd = input_bfd; + entry->input_indx = input_indx; + eht->dynsymcount++; + + /* Whatever binding the symbol had before, it's now local. */ + entry->isym.st_info + = ELF_ST_INFO (STB_LOCAL, ELF_ST_TYPE (entry->isym.st_info)); + + /* The dynindx will be set at the end of size_dynamic_sections. */ + + return true; +} /* Read and swap the relocs from the section indicated by SHDR. This @@ -2102,7 +2314,7 @@ elf_link_read_relocs_from_section (abfd, shdr, external_relocs, * sizeof (Elf_Internal_Rel))); for (; erel < erelend; erel++, irela += bed->s->int_rels_per_ext_rel) { - int i; + unsigned char i; if (bed->s->swap_reloc_in) (*bed->s->swap_reloc_in) (abfd, (bfd_byte *) erel, irel); @@ -2237,7 +2449,7 @@ NAME(_bfd_elf,link_read_relocs) (abfd, o, external_relocs, internal_relocs, /*ARGSUSED*/ boolean NAME(bfd_elf,record_link_assignment) (output_bfd, info, name, provide) - bfd *output_bfd; + bfd *output_bfd ATTRIBUTE_UNUSED; struct bfd_link_info *info; const char *name; boolean provide; @@ -2273,7 +2485,10 @@ NAME(bfd_elf,record_link_assignment) (output_bfd, info, name, provide) h->verinfo.verdef = NULL; h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR; - h->type = STT_OBJECT; + + /* When possible, keep the original type of the symbol */ + if (h->type == STT_NOTYPE) + h->type = STT_OBJECT; if (((h->elf_link_hash_flags & (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_DYNAMIC)) != 0 @@ -2310,8 +2525,6 @@ struct elf_assign_sym_version_info struct bfd_elf_version_tree *verdefs; /* Whether we are exporting all dynamic symbols. */ boolean export_dynamic; - /* Whether we removed any symbols from the dynamic symbol table. */ - boolean removed_dynamic; /* Whether we had a failure. */ boolean failed; }; @@ -2356,7 +2569,7 @@ compute_bucket_count (info) struct bfd_link_info *info; { size_t dynsymcount = elf_hash_table (info)->dynsymcount; - size_t best_size; + size_t best_size = 0; unsigned long int *hashcodes; unsigned long int *hashcodesp; unsigned long int i; @@ -2486,42 +2699,6 @@ compute_bucket_count (info) return best_size; } -/* Remove SECTION from the BFD. If a symbol for SECTION was going to - be put into the dynamic symbol table, remove it, and renumber - subsequent entries. */ - -static void -elf_link_remove_section_and_adjust_dynindices (info, section) - struct bfd_link_info *info; - asection *section; -{ - /* Remove the section from the output list. */ - _bfd_strip_section_from_output (section); - - if (elf_section_data (section->output_section)->dynindx) - { - asection *s; - int increment = -1; - - /* We were going to output an entry in the dynamic symbol table - for the symbol corresponding to this section. Now, the - section is gone. So, we must renumber the dynamic indices of - all subsequent sections and all other entries in the dynamic - symbol table. */ - elf_section_data (section->output_section)->dynindx = 0; - for (s = section->output_section->next; s; s = s->next) - if (elf_section_data (s)->dynindx) - --elf_section_data (s)->dynindx; - - elf_link_hash_traverse (elf_hash_table (info), - _bfd_elf_link_adjust_dynindx, - &increment); - - /* There is one less dynamic symbol than there was before. */ - --elf_hash_table (info)->dynsymcount; - } -} - /* Set up the sizes and contents of the ELF dynamic sections. This is called by the ELF linker emulation before_allocation routine. We must set the sizes of the sections before the linker sets the @@ -2545,7 +2722,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, bfd_size_type soname_indx; bfd *dynobj; struct elf_backend_data *bed; - bfd_size_type old_dynsymcount; struct elf_assign_sym_version_info asvinfo; *sinterpptr = NULL; @@ -2569,20 +2745,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, if (dynobj == NULL) return true; - /* If we are supposed to export all symbols into the dynamic symbol - table (this is not the normal case), then do so. */ - if (export_dynamic) - { - struct elf_info_failed eif; - - eif.failed = false; - eif.info = info; - elf_link_hash_traverse (elf_hash_table (info), elf_export_symbol, - (PTR) &eif); - if (eif.failed) - return false; - } - if (elf_hash_table (info)->dynamic_sections_created) { struct elf_info_failed eif; @@ -2645,12 +2807,25 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, } } + /* If we are supposed to export all symbols into the dynamic symbol + table (this is not the normal case), then do so. */ + if (export_dynamic) + { + struct elf_info_failed eif; + + eif.failed = false; + eif.info = info; + elf_link_hash_traverse (elf_hash_table (info), elf_export_symbol, + (PTR) &eif); + if (eif.failed) + return false; + } + /* Attach all the symbols to their version information. */ asvinfo.output_bfd = output_bfd; asvinfo.info = info; asvinfo.verdefs = verdefs; asvinfo.export_dynamic = export_dynamic; - asvinfo.removed_dynamic = false; asvinfo.failed = false; elf_link_hash_traverse (elf_hash_table (info), @@ -2712,7 +2887,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, /* The backend must work out the sizes of all the other dynamic sections. */ - old_dynsymcount = elf_hash_table (info)->dynsymcount; if (bed->elf_backend_size_dynamic_sections && ! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info)) return false; @@ -2734,7 +2908,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, verdefs = asvinfo.verdefs; if (verdefs == NULL) - elf_link_remove_section_and_adjust_dynindices (info, s); + _bfd_strip_section_from_output (info, s); else { unsigned int cdefs; @@ -2744,23 +2918,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, Elf_Internal_Verdef def; Elf_Internal_Verdaux defaux; - if (asvinfo.removed_dynamic) - { - /* Some dynamic symbols were changed to be local - symbols. In this case, we renumber all of the - dynamic symbols, so that we don't have a hole. If - the backend changed dynsymcount, then assume that the - new symbols are at the start. This is the case on - the MIPS. FIXME: The names of the removed symbols - will still be in the dynamic string table, wasting - space. */ - elf_hash_table (info)->dynsymcount = - 1 + (elf_hash_table (info)->dynsymcount - old_dynsymcount); - elf_link_hash_traverse (elf_hash_table (info), - elf_link_renumber_dynsyms, - (PTR) info); - } - cdefs = 0; size = 0; @@ -2800,7 +2957,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, if (soname_indx != (bfd_size_type) -1) { - def.vd_hash = bfd_elf_hash ((const unsigned char *) soname); + def.vd_hash = bfd_elf_hash (soname); defaux.vda_name = soname_indx; } else @@ -2809,7 +2966,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, bfd_size_type indx; name = output_bfd->filename; - def.vd_hash = bfd_elf_hash ((const unsigned char *) name); + def.vd_hash = bfd_elf_hash (name); indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, name, true, false); if (indx == (bfd_size_type) -1) @@ -2857,7 +3014,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, def.vd_flags |= VER_FLG_WEAK; def.vd_ndx = t->vernum + 1; def.vd_cnt = cdeps + 1; - def.vd_hash = bfd_elf_hash ((const unsigned char *) t->name); + def.vd_hash = bfd_elf_hash (t->name); def.vd_aux = sizeof (Elf_External_Verdef); if (t->next != NULL) def.vd_next = (sizeof (Elf_External_Verdef) @@ -2927,7 +3084,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, (PTR) &sinfo); if (elf_tdata (output_bfd)->verref == NULL) - elf_link_remove_section_and_adjust_dynindices (info, s); + _bfd_strip_section_from_output (info, s); else { Elf_Internal_Verneed *t; @@ -2993,8 +3150,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr) { - a->vna_hash = bfd_elf_hash ((const unsigned char *) - a->vna_nodename); + a->vna_hash = bfd_elf_hash (a->vna_nodename); indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, a->vna_nodename, true, false); if (indx == (bfd_size_type) -1) @@ -3019,7 +3175,12 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, } } - dynsymcount = elf_hash_table (info)->dynsymcount; + /* Assign dynsym indicies. In a shared library we generate a + section symbol for each output section, which come first. + Next come all of the back-end allocated local dynamic syms, + followed by the rest of the global symbols. */ + + dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info); /* Work out the size of the symbol version section. */ s = bfd_get_section_by_name (dynobj, ".gnu.version"); @@ -3027,10 +3188,10 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, if (dynsymcount == 0 || (verdefs == NULL && elf_tdata (output_bfd)->verref == NULL)) { - elf_link_remove_section_and_adjust_dynindices (info, s); + _bfd_strip_section_from_output (info, s); /* The DYNSYMCOUNT might have changed if we were going to output a dynamic symbol table entry for S. */ - dynsymcount = elf_hash_table (info)->dynsymcount; + dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info); } else { @@ -3184,6 +3345,33 @@ elf_fix_symbol_flags (h, eif) h->plt.offset = (bfd_vma) -1; } + /* 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. */ + if (h->weakdef != NULL) + { + struct elf_link_hash_entry *weakdef; + + BFD_ASSERT (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak); + weakdef = h->weakdef; + BFD_ASSERT (weakdef->root.type == bfd_link_hash_defined + || weakdef->root.type == bfd_link_hash_defweak); + BFD_ASSERT (weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC); + + /* If the real definition is defined by a regular object file, + don't do anything special. See the longer description in + elf_adjust_dynamic_symbol, below. */ + if ((weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0) + h->weakdef = NULL; + else + weakdef->elf_link_hash_flags |= + (h->elf_link_hash_flags + & (ELF_LINK_HASH_REF_REGULAR + | ELF_LINK_HASH_REF_REGULAR_NONWEAK + | ELF_LINK_NON_GOT_REF)); + } + return true; } @@ -3266,32 +3454,14 @@ elf_adjust_dynamic_symbol (h, data) if (h->weakdef != NULL) { - struct elf_link_hash_entry *weakdef; + /* If we get to this point, we know there is an implicit + reference by a regular object file via the weak symbol H. + FIXME: Is this really true? What if the traversal finds + H->WEAKDEF before it finds H? */ + h->weakdef->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR; - BFD_ASSERT (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak); - weakdef = h->weakdef; - BFD_ASSERT (weakdef->root.type == bfd_link_hash_defined - || weakdef->root.type == bfd_link_hash_defweak); - BFD_ASSERT (weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC); - if ((weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0) - { - /* This symbol is defined by a regular object file, so we - will not do anything special. Clear weakdef for the - convenience of the processor backend. */ - h->weakdef = NULL; - } - else - { - /* There is an implicit reference by a regular object file - via the weak symbol. */ - weakdef->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR; - if (h->weakdef->elf_link_hash_flags - & ELF_LINK_HASH_REF_REGULAR_NONWEAK) - weakdef->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR_NONWEAK; - if (! elf_adjust_dynamic_symbol (weakdef, (PTR) eif)) - return false; - } + if (! elf_adjust_dynamic_symbol (h->weakdef, (PTR) eif)) + return false; } /* If a symbol has no type and no size and does not require a PLT @@ -3430,6 +3600,7 @@ elf_link_assign_sym_version (h, data) struct elf_assign_sym_version_info *sinfo = (struct elf_assign_sym_version_info *) data; struct bfd_link_info *info = sinfo->info; + struct elf_backend_data *bed; struct elf_info_failed eif; char *p; @@ -3448,6 +3619,7 @@ elf_link_assign_sym_version (h, data) if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) return true; + bed = get_elf_backend_data (sinfo->output_bfd); p = strchr (h->root.root.string, ELF_VER_CHR); if (p != NULL && h->verinfo.vertree == NULL) { @@ -3514,12 +3686,8 @@ elf_link_assign_sym_version (h, data) && info->shared && ! sinfo->export_dynamic) { - sinfo->removed_dynamic = true; h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL; - h->elf_link_hash_flags &=~ - ELF_LINK_HASH_NEEDS_PLT; - h->dynindx = -1; - h->plt.offset = (bfd_vma) -1; + (*bed->elf_backend_hide_symbol) (h); /* FIXME: The name of the symbol has already been recorded in the dynamic string table section. */ @@ -3630,11 +3798,8 @@ elf_link_assign_sym_version (h, data) && info->shared && ! sinfo->export_dynamic) { - sinfo->removed_dynamic = true; h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL; - h->elf_link_hash_flags &=~ ELF_LINK_HASH_NEEDS_PLT; - h->dynindx = -1; - h->plt.offset = (bfd_vma) -1; + (*bed->elf_backend_hide_symbol) (h); /* FIXME: The name of the symbol has already been recorded in the dynamic string table section. */ @@ -3655,11 +3820,8 @@ elf_link_assign_sym_version (h, data) && info->shared && ! sinfo->export_dynamic) { - sinfo->removed_dynamic = true; h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL; - h->elf_link_hash_flags &=~ ELF_LINK_HASH_NEEDS_PLT; - h->dynindx = -1; - h->plt.offset = (bfd_vma) -1; + (*bed->elf_backend_hide_symbol) (h); /* FIXME: The name of the symbol has already been recorded in the dynamic string table section. */ } @@ -3668,26 +3830,6 @@ elf_link_assign_sym_version (h, data) return true; } - -/* This function is used to renumber the dynamic symbols, if some of - them are removed because they are marked as local. This is called - via elf_link_hash_traverse. */ - -static boolean -elf_link_renumber_dynsyms (h, data) - struct elf_link_hash_entry *h; - PTR data; -{ - struct bfd_link_info *info = (struct bfd_link_info *) data; - - if (h->dynindx != -1) - { - h->dynindx = elf_hash_table (info)->dynsymcount; - ++elf_hash_table (info)->dynsymcount; - } - - return true; -} /* Final phase of ELF linker. */ @@ -3765,38 +3907,91 @@ elf_link_size_reloc_section (abfd, rel_hdr, o) asection *o; { register struct elf_link_hash_entry **p, **pend; + unsigned reloc_count; + + /* Figure out how many relocations there will be. */ + if (rel_hdr == &elf_section_data (o)->rel_hdr) + reloc_count = elf_section_data (o)->rel_count; + else + reloc_count = elf_section_data (o)->rel_count2; - /* We are overestimating the size required for the relocation - sections, in the case that we are using both REL and RELA - relocations for a single section. In that case, RELOC_COUNT will - be the total number of relocations required, and we allocate - space for that many REL relocations as well as that many RELA - relocations. This approximation is wasteful of disk space. - However, until we keep track of how many of each kind of - relocation is required, it's difficult to calculate the right - value. */ - rel_hdr->sh_size = rel_hdr->sh_entsize * o->reloc_count; + /* That allows us to calculate the size of the section. */ + rel_hdr->sh_size = rel_hdr->sh_entsize * reloc_count; /* The contents field must last into write_object_contents, so we allocate it with bfd_alloc rather than malloc. */ rel_hdr->contents = (PTR) bfd_alloc (abfd, rel_hdr->sh_size); if (rel_hdr->contents == NULL && rel_hdr->sh_size != 0) return false; + + /* We only allocate one set of hash entries, so we only do it the + first time we are called. */ + if (elf_section_data (o)->rel_hashes == NULL) + { + p = ((struct elf_link_hash_entry **) + bfd_malloc (o->reloc_count + * sizeof (struct elf_link_hash_entry *))); + if (p == NULL && o->reloc_count != 0) + return false; - p = ((struct elf_link_hash_entry **) - bfd_malloc (o->reloc_count - * sizeof (struct elf_link_hash_entry *))); - if (p == NULL && o->reloc_count != 0) - return false; - - elf_section_data (o)->rel_hashes = p; - pend = p + o->reloc_count; - for (; p < pend; p++) - *p = NULL; + elf_section_data (o)->rel_hashes = p; + pend = p + o->reloc_count; + for (; p < pend; p++) + *p = NULL; + } return true; } +/* When performing a relocateable link, the input relocations are + preserved. But, if they reference global symbols, the indices + referenced must be updated. Update all the relocations in + REL_HDR (there are COUNT of them), using the data in REL_HASH. */ + +static void +elf_link_adjust_relocs (abfd, rel_hdr, count, rel_hash) + bfd *abfd; + Elf_Internal_Shdr *rel_hdr; + unsigned int count; + struct elf_link_hash_entry **rel_hash; +{ + unsigned int i; + + for (i = 0; i < count; i++, rel_hash++) + { + if (*rel_hash == NULL) + continue; + + BFD_ASSERT ((*rel_hash)->indx >= 0); + + if (rel_hdr->sh_entsize == sizeof (Elf_External_Rel)) + { + Elf_External_Rel *erel; + Elf_Internal_Rel irel; + + erel = (Elf_External_Rel *) rel_hdr->contents + i; + elf_swap_reloc_in (abfd, erel, &irel); + irel.r_info = ELF_R_INFO ((*rel_hash)->indx, + ELF_R_TYPE (irel.r_info)); + elf_swap_reloc_out (abfd, &irel, erel); + } + else + { + Elf_External_Rela *erela; + Elf_Internal_Rela irela; + + BFD_ASSERT (rel_hdr->sh_entsize + == sizeof (Elf_External_Rela)); + + erela = (Elf_External_Rela *) rel_hdr->contents + i; + elf_swap_reloca_in (abfd, erela, &irela); + irela.r_info = ELF_R_INFO ((*rel_hash)->indx, + ELF_R_TYPE (irela.r_info)); + elf_swap_reloca_out (abfd, &irela, erela); + } + } +} + /* Do the final step of an ELF link. */ boolean @@ -3952,6 +4147,54 @@ elf_bfd_final_link (abfd, info) if (! _bfd_elf_compute_section_file_positions (abfd, info)) goto error_return; + /* Figure out how many relocations we will have in each section. + Just using RELOC_COUNT isn't good enough since that doesn't + maintain a separate value for REL vs. RELA relocations. */ + if (info->relocateable) + for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) + for (o = sub->sections; o != NULL; o = o->next) + { + asection *output_section; + + if (! o->linker_mark) + { + /* This section was omitted from the link. */ + continue; + } + + output_section = o->output_section; + + if (output_section != NULL + && (o->flags & SEC_RELOC) != 0) + { + struct bfd_elf_section_data *esdi + = elf_section_data (o); + struct bfd_elf_section_data *esdo + = elf_section_data (output_section); + unsigned int *rel_count; + unsigned int *rel_count2; + + /* We must be careful to add the relocation froms the + input section to the right output count. */ + if (esdi->rel_hdr.sh_entsize == esdo->rel_hdr.sh_entsize) + { + rel_count = &esdo->rel_count; + rel_count2 = &esdo->rel_count2; + } + else + { + rel_count = &esdo->rel_count2; + rel_count2 = &esdo->rel_count; + } + + *rel_count += (esdi->rel_hdr.sh_size + / esdi->rel_hdr.sh_entsize); + if (esdi->rel_hdr2) + *rel_count2 += (esdi->rel_hdr2->sh_size + / esdi->rel_hdr2->sh_entsize); + } + } + /* That created the reloc sections. Set their sizes, and assign them file positions, and allocate some buffers. */ for (o = abfd->sections; o != NULL; o = o->next) @@ -3969,6 +4212,11 @@ elf_bfd_final_link (abfd, info) o)) goto error_return; } + + /* Now, reset REL_COUNT and REL_COUNT2 so that we can use them + to count upwards while actually outputting the relocations. */ + elf_section_data (o)->rel_count = 0; + elf_section_data (o)->rel_count2 = 0; } _bfd_elf_assign_file_positions_for_relocs (abfd); @@ -4162,11 +4410,79 @@ elf_bfd_final_link (abfd, info) return false; } - /* The sh_info field records the index of the first non local - symbol. */ + /* The sh_info field records the index of the first non local symbol. */ symtab_hdr->sh_info = bfd_get_symcount (abfd); + if (dynamic) - elf_section_data (finfo.dynsym_sec->output_section)->this_hdr.sh_info = 1; + { + Elf_Internal_Sym sym; + Elf_External_Sym *dynsym = + (Elf_External_Sym *)finfo.dynsym_sec->contents; + long last_local = 0; + + /* Write out the section symbols for the output sections. */ + if (info->shared) + { + asection *s; + + sym.st_size = 0; + sym.st_name = 0; + sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); + sym.st_other = 0; + + for (s = abfd->sections; s != NULL; s = s->next) + { + int indx; + indx = elf_section_data (s)->this_idx; + BFD_ASSERT (indx > 0); + sym.st_shndx = indx; + sym.st_value = s->vma; + + elf_swap_symbol_out (abfd, &sym, + dynsym + elf_section_data (s)->dynindx); + } + + last_local = bfd_count_sections (abfd); + } + + /* Write out the local dynsyms. */ + if (elf_hash_table (info)->dynlocal) + { + struct elf_link_local_dynamic_entry *e; + for (e = elf_hash_table (info)->dynlocal; e ; e = e->next) + { + asection *s; + + sym.st_size = e->isym.st_size; + sym.st_other = e->isym.st_other; + + /* Copy the internal symbol as is. + Note that we saved a word of storage and overwrote + the original st_name with the dynstr_index. */ + sym = e->isym; + + if (e->isym.st_shndx > 0 && e->isym.st_shndx < SHN_LORESERVE) + { + s = bfd_section_from_elf_index (e->input_bfd, + e->isym.st_shndx); + + sym.st_shndx = + elf_section_data (s->output_section)->this_idx; + sym.st_value = (s->output_section->vma + + s->output_offset + + e->isym.st_value); + } + + if (last_local < e->dynindx) + last_local = e->dynindx; + + elf_swap_symbol_out (abfd, &sym, dynsym + e->dynindx); + } + } + + elf_section_data (finfo.dynsym_sec->output_section)->this_hdr.sh_info = + last_local + 1; + } /* We get the global symbols from the hash table. */ eoinfo.failed = false; @@ -4177,6 +4493,18 @@ elf_bfd_final_link (abfd, info) if (eoinfo.failed) return false; + /* If backend needs to output some symbols not present in the hash + table, do it now. */ + if (bed->elf_backend_output_arch_syms) + { + if (! (*bed->elf_backend_output_arch_syms) + (abfd, info, (PTR) &finfo, + (boolean (*) PARAMS ((PTR, const char *, + Elf_Internal_Sym *, asection *))) + elf_link_output_sym)) + return false; + } + /* Flush all symbols to the file. */ if (! elf_link_flush_output_syms (&finfo)) return false; @@ -4211,48 +4539,17 @@ elf_bfd_final_link (abfd, info) /* Adjust the relocs to have the correct symbol indices. */ for (o = abfd->sections; o != NULL; o = o->next) { - struct elf_link_hash_entry **rel_hash; - Elf_Internal_Shdr *rel_hdr; - if ((o->flags & SEC_RELOC) == 0) continue; - rel_hash = elf_section_data (o)->rel_hashes; - rel_hdr = &elf_section_data (o)->rel_hdr; - BFD_ASSERT (elf_section_data (o)->rel_count == o->reloc_count); - for (i = 0; i < o->reloc_count; i++, rel_hash++) - { - if (*rel_hash == NULL) - continue; - - BFD_ASSERT ((*rel_hash)->indx >= 0); - - if (rel_hdr->sh_entsize == sizeof (Elf_External_Rel)) - { - Elf_External_Rel *erel; - Elf_Internal_Rel irel; - - erel = (Elf_External_Rel *) rel_hdr->contents + i; - elf_swap_reloc_in (abfd, erel, &irel); - irel.r_info = ELF_R_INFO ((*rel_hash)->indx, - ELF_R_TYPE (irel.r_info)); - elf_swap_reloc_out (abfd, &irel, erel); - } - else - { - Elf_External_Rela *erela; - Elf_Internal_Rela irela; - - BFD_ASSERT (rel_hdr->sh_entsize - == sizeof (Elf_External_Rela)); - - erela = (Elf_External_Rela *) rel_hdr->contents + i; - elf_swap_reloca_in (abfd, erela, &irela); - irela.r_info = ELF_R_INFO ((*rel_hash)->indx, - ELF_R_TYPE (irela.r_info)); - elf_swap_reloca_out (abfd, &irela, erela); - } - } + elf_link_adjust_relocs (abfd, &elf_section_data (o)->rel_hdr, + elf_section_data (o)->rel_count, + elf_section_data (o)->rel_hashes); + if (elf_section_data (o)->rel_hdr2 != NULL) + elf_link_adjust_relocs (abfd, elf_section_data (o)->rel_hdr2, + elf_section_data (o)->rel_count2, + (elf_section_data (o)->rel_hashes + + elf_section_data (o)->rel_count)); /* Set the reloc_count field to 0 to prevent write_relocs from trying to swap the relocs out itself. */ @@ -4749,14 +5046,23 @@ elf_link_output_extsym (h, data) /* If we are marking the symbol as undefined, and there are no non-weak references to this symbol from a regular object, then - mark the symbol as weak undefined. We can't do this earlier, + mark the symbol as weak undefined; if there are non-weak + references, mark the symbol as strong. We can't do this earlier, because it might not be marked as undefined until the finish_dynamic_symbol routine gets through with it. */ if (sym.st_shndx == SHN_UNDEF - && sym.st_info == ELF_ST_INFO (STB_GLOBAL, h->type) && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) != 0 - && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK) == 0) - sym.st_info = ELF_ST_INFO (STB_WEAK, h->type); + && (ELF_ST_BIND(sym.st_info) == STB_GLOBAL + || ELF_ST_BIND(sym.st_info) == STB_WEAK)) + { + int bindtype; + + if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK) != 0) + bindtype = STB_GLOBAL; + else + bindtype = STB_WEAK; + sym.st_info = ELF_ST_INFO (bindtype, ELF_ST_TYPE (sym.st_info)); + } /* If this symbol should be put in the .dynsym section, then put it there now. We have already know the symbol index. We also fill @@ -4850,7 +5156,7 @@ elf_link_output_relocs (output_bfd, input_section, input_rel_hdr, Elf_Internal_Rela *irelaend; Elf_Internal_Shdr *output_rel_hdr; asection *output_section; - unsigned int *rel_countp; + unsigned int *rel_countp = NULL; output_section = input_section->output_section; output_rel_hdr = NULL; @@ -5173,7 +5479,8 @@ elf_link_input_bfd (finfo, input_bfd) irelaend = irela + o->reloc_count * bed->s->int_rels_per_ext_rel; rel_hash = (elf_section_data (o->output_section)->rel_hashes - + elf_section_data (o->output_section)->rel_count); + + elf_section_data (o->output_section)->rel_count + + elf_section_data (o->output_section)->rel_count2); for (; irela < irelaend; irela++, rel_hash++) { unsigned long r_symndx; @@ -5363,7 +5670,8 @@ elf_reloc_link_order (output_bfd, info, output_section, link_order) /* Figure out the symbol index. */ rel_hash_ptr = (elf_section_data (output_section)->rel_hashes - + elf_section_data (output_section)->rel_count); + + elf_section_data (output_section)->rel_count + + elf_section_data (output_section)->rel_count2); if (link_order->type == bfd_section_reloc_link_order) { indx = link_order->u.reloc.p->u.section->target_index; @@ -5894,6 +6202,9 @@ elf_gc_sweep (info, gc_sweep_hook) { asection *o; + if (bfd_get_flavour (sub) != bfd_target_elf_flavour) + continue; + for (o = sub->sections; o != NULL; o = o->next) { /* Keep special sections. Keep .debug sections. */ @@ -6108,6 +6419,10 @@ elf_gc_sections (abfd, info) for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) { asection *o; + + if (bfd_get_flavour (sub) != bfd_target_elf_flavour) + continue; + for (o = sub->sections; o != NULL; o = o->next) { if (o->flags & SEC_KEEP) @@ -6184,8 +6499,8 @@ win: boolean elf_gc_record_vtentry (abfd, sec, h, addend) - bfd *abfd; - asection *sec; + bfd *abfd ATTRIBUTE_UNUSED; + asection *sec ATTRIBUTE_UNUSED; struct elf_link_hash_entry *h; bfd_vma addend; { @@ -6211,30 +6526,31 @@ elf_gc_record_vtentry (abfd, sec, h, addend) /* Allocate one extra entry for use as a "done" flag for the consolidation pass. */ - bytes = (size / FILE_ALIGN + 1) * sizeof(boolean); + bytes = (size / FILE_ALIGN + 1) * sizeof (boolean); if (ptr) { - size_t oldbytes; - - ptr = realloc (ptr-1, bytes); - if (ptr == NULL) - return false; + ptr = bfd_realloc (ptr - 1, bytes); + + if (ptr != NULL) + { + size_t oldbytes; - oldbytes = (h->vtable_entries_size/FILE_ALIGN + 1) * sizeof(boolean); - memset (ptr + oldbytes, 0, bytes - oldbytes); + oldbytes = (h->vtable_entries_size/FILE_ALIGN + 1) * sizeof (boolean); + memset (((char *)ptr) + oldbytes, 0, bytes - oldbytes); + } } else - { - ptr = calloc (1, bytes); - if (ptr == NULL) - return false; - } + ptr = bfd_zmalloc (bytes); + if (ptr == NULL) + return false; + /* And arrange for that done flag to be at index -1. */ - h->vtable_entries_used = ptr+1; + h->vtable_entries_used = ptr + 1; h->vtable_entries_size = size; } + h->vtable_entries_used[addend / FILE_ALIGN] = true; return true; @@ -6262,10 +6578,14 @@ elf_gc_common_finalize_got_offsets (abfd, info) /* Do the local .got entries first. */ for (i = info->input_bfds; i; i = i->link_next) { - bfd_signed_vma *local_got = elf_local_got_refcounts (i); + bfd_signed_vma *local_got; bfd_size_type j, locsymcount; Elf_Internal_Shdr *symtab_hdr; + if (bfd_get_flavour (i) != bfd_target_elf_flavour) + continue; + + local_got = elf_local_got_refcounts (i); if (!local_got) continue;