X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felflink.c;h=6d80109c47bbadf97ddc61c5816e51aa045571ae;hb=fb098a1efcc97442a25ec05fb705089095ca5f3f;hp=1d1ca0bce44987d3383ea7e0188cc85719a4a1ef;hpb=6673f753c019918af9fc3eb97543e2c3a90460b9;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elflink.c b/bfd/elflink.c index 1d1ca0bce4..6d80109c47 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -1,6 +1,6 @@ /* ELF linking support for BFD. Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005, 2006, 2007, 2008, 2009, 2010, 2011 + 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -104,8 +104,8 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info) struct elf_link_hash_table *htab = elf_hash_table (info); /* This function may be called more than once. */ - s = bfd_get_section_by_name (abfd, ".got"); - if (s != NULL && (s->flags & SEC_LINKER_CREATED) != 0) + s = bfd_get_linker_section (abfd, ".got"); + if (s != NULL) return TRUE; flags = bed->dynamic_sec_flags; @@ -187,6 +187,7 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) flagword flags; asection *s; const struct elf_backend_data *bed; + struct elf_link_hash_entry *h; if (! is_elf_hash_table (info->hash)) return FALSE; @@ -254,7 +255,9 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) section. We don't want to define it if there is no .dynamic section, since on some ELF platforms the start up code examines it to decide how to initialize the process. */ - if (!_bfd_elf_define_linkage_sym (abfd, info, s, "_DYNAMIC")) + h = _bfd_elf_define_linkage_sym (abfd, info, s, "_DYNAMIC"); + elf_hash_table (info)->hdynamic = h; + if (h == NULL) return FALSE; if (info->emit_hash) @@ -569,7 +572,7 @@ bfd_elf_record_link_assignment (bfd *output_bfd, h->def_regular = 1; - if (provide && hidden) + if (hidden) { bed = get_elf_backend_data (output_bfd); h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN; @@ -779,8 +782,7 @@ _bfd_elf_link_omit_section_dynsym (bfd *output_bfd ATTRIBUTE_UNUSED, asection *ip; if (htab->dynobj != NULL - && (ip = bfd_get_section_by_name (htab->dynobj, p->name)) != NULL - && (ip->flags & SEC_LINKER_CREATED) + && (ip = bfd_get_linker_section (htab->dynobj, p->name)) != NULL && ip->output_section == p) return TRUE; } @@ -893,6 +895,33 @@ elf_merge_st_other (bfd *abfd, struct elf_link_hash_entry *h, } } +/* Mark if a symbol has a definition in a dynamic object or is + weak in all dynamic objects. */ + +static void +_bfd_elf_mark_dynamic_def_weak (struct elf_link_hash_entry *h, + asection *sec, int bind) +{ + if (!h->dynamic_def) + { + if (!bfd_is_und_section (sec)) + h->dynamic_def = 1; + else + { + /* Check if this symbol is weak in all dynamic objects. If it + is the first time we see it in a dynamic object, we mark + if it is weak. Otherwise, we clear it. */ + if (!h->ref_dynamic) + { + if (bind == STB_WEAK) + h->dynamic_weak = 1; + } + else if (bind != STB_WEAK) + h->dynamic_weak = 0; + } + } +} + /* This function is called when we want to define a new symbol. It handles the various cases which arise when we find a definition in a dynamic object, or when there is already a definition in a @@ -912,6 +941,7 @@ _bfd_elf_merge_symbol (bfd *abfd, Elf_Internal_Sym *sym, asection **psec, bfd_vma *pvalue, + bfd_boolean *pold_weak, unsigned int *pold_alignment, struct elf_link_hash_entry **sym_hash, bfd_boolean *skip, @@ -921,6 +951,7 @@ _bfd_elf_merge_symbol (bfd *abfd, { asection *sec, *oldsec; struct elf_link_hash_entry *h; + struct elf_link_hash_entry *hi; struct elf_link_hash_entry *flip; int bind; bfd *oldbfd; @@ -937,7 +968,7 @@ _bfd_elf_merge_symbol (bfd *abfd, /* Silently discard TLS symbols from --just-syms. There's no way to combine a static TLS block with a new TLS block for this executable. */ if (ELF_ST_TYPE (sym->st_info) == STT_TLS - && sec->sec_info_type == ELF_INFO_TYPE_JUST_SYMS) + && sec->sec_info_type == SEC_INFO_TYPE_JUST_SYMS) { *skip = TRUE; return TRUE; @@ -959,8 +990,9 @@ _bfd_elf_merge_symbol (bfd *abfd, if (!(*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec)) return TRUE; - /* For merging, we only care about real symbols. */ - + /* For merging, we only care about real symbols. But we need to make + sure that indirect symbol dynamic flags are updated. */ + hi = h; while (h->root.type == bfd_link_hash_indirect || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; @@ -1012,6 +1044,8 @@ _bfd_elf_merge_symbol (bfd *abfd, newweak = bind == STB_WEAK; oldweak = (h->root.type == bfd_link_hash_defweak || h->root.type == bfd_link_hash_undefweak); + if (pold_weak) + *pold_weak = oldweak; /* In cases involving weak versioned symbols, we may wind up trying to merge a symbol with itself. Catch that here, to avoid the @@ -1136,23 +1170,11 @@ _bfd_elf_merge_symbol (bfd *abfd, /* We need to remember if a symbol has a definition in a dynamic object or is weak in all dynamic objects. Internal and hidden visibility will make it unavailable to dynamic objects. */ - if (newdyn && !h->dynamic_def) + if (newdyn) { - if (!bfd_is_und_section (sec)) - h->dynamic_def = 1; - else - { - /* Check if this symbol is weak in all dynamic objects. If it - is the first time we see it in a dynamic object, we mark - if it is weak. Otherwise, we clear it. */ - if (!h->ref_dynamic) - { - if (bind == STB_WEAK) - h->dynamic_weak = 1; - } - else if (bind != STB_WEAK) - h->dynamic_weak = 0; - } + _bfd_elf_mark_dynamic_def_weak (h, sec, bind); + if (h != hi) + _bfd_elf_mark_dynamic_def_weak (hi, sec, bind); } /* If the old symbol has non-default visibility, we ignore the new @@ -1164,6 +1186,7 @@ _bfd_elf_merge_symbol (bfd *abfd, *skip = TRUE; /* Make sure this symbol is dynamic. */ h->ref_dynamic = 1; + hi->ref_dynamic = 1; /* A protected symbol has external availability. Make sure it is recorded as dynamic. @@ -1193,38 +1216,40 @@ _bfd_elf_merge_symbol (bfd *abfd, vh->root.type = h->root.type; h->root.type = bfd_link_hash_indirect; (*bed->elf_backend_copy_indirect_symbol) (info, vh, h); - /* Protected symbols will override the dynamic definition - with default version. */ - if (ELF_ST_VISIBILITY (sym->st_other) == STV_PROTECTED) + + h->root.u.i.link = (struct bfd_link_hash_entry *) vh; + if (ELF_ST_VISIBILITY (sym->st_other) != STV_PROTECTED) { - h->root.u.i.link = (struct bfd_link_hash_entry *) vh; - vh->dynamic_def = 1; - vh->ref_dynamic = 1; + /* If the new symbol is hidden or internal, completely undo + any dynamic link state. */ + (*bed->elf_backend_hide_symbol) (info, h, TRUE); + h->forced_local = 0; + h->ref_dynamic = 0; } else - { - h->root.type = vh->root.type; - vh->ref_dynamic = 0; - /* We have to hide it here since it was made dynamic - global with extra bits when the symbol info was - copied from the old dynamic definition. */ - (*bed->elf_backend_hide_symbol) (info, vh, TRUE); - } + h->ref_dynamic = 1; + + h->def_dynamic = 0; + h->dynamic_def = 0; + /* FIXME: Should we check type and size for protected symbol? */ + h->size = 0; + h->type = 0; + h = vh; } else h = *sym_hash; } - if ((h->root.u.undef.next || info->hash->undefs_tail == &h->root) - && bfd_is_und_section (sec)) + /* If the old symbol was undefined before, then it will still be + on the undefs list. If the new symbol is undefined or + common, we can't make it bfd_link_hash_new here, because new + undefined or common symbols will be added to the undefs list + by _bfd_generic_link_add_one_symbol. Symbols may not be + added twice to the undefs list. Also, if the new symbol is + undefweak then we don't want to lose the strong undef. */ + if (h->root.u.undef.next || info->hash->undefs_tail == &h->root) { - /* If the new symbol is undefined and the old symbol was - also undefined before, we need to make sure - _bfd_generic_link_add_one_symbol doesn't mess - up the linker hash table undefs list. Since the old - definition came from a dynamic object, it is still on the - undefs list. */ h->root.type = bfd_link_hash_undefined; h->root.u.undef.abfd = abfd; } @@ -1234,11 +1259,18 @@ _bfd_elf_merge_symbol (bfd *abfd, h->root.u.undef.abfd = NULL; } - if (h->def_dynamic) + if (ELF_ST_VISIBILITY (sym->st_other) != STV_PROTECTED) { - h->def_dynamic = 0; - h->ref_dynamic = 1; + /* If the new symbol is hidden or internal, completely undo + any dynamic link state. */ + (*bed->elf_backend_hide_symbol) (info, h, TRUE); + h->forced_local = 0; + h->ref_dynamic = 0; } + else + h->ref_dynamic = 1; + h->def_dynamic = 0; + h->dynamic_def = 0; /* FIXME: Should we check type and size for protected symbol? */ h->size = 0; h->type = 0; @@ -1636,7 +1668,7 @@ _bfd_elf_add_default_symbol (bfd *abfd, size_change_ok = FALSE; sec = *psec; if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &sec, value, - NULL, &hi, &skip, &override, + NULL, NULL, &hi, &skip, &override, &type_change_ok, &size_change_ok)) return FALSE; @@ -1717,6 +1749,7 @@ _bfd_elf_add_default_symbol (bfd *abfd, if (! dynamic) { if (! info->executable + || hi->def_dynamic || hi->ref_dynamic) *dynsym = TRUE; } @@ -1744,7 +1777,7 @@ nondefault: size_change_ok = FALSE; sec = *psec; if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &sec, value, - NULL, &hi, &skip, &override, + NULL, NULL, &hi, &skip, &override, &type_change_ok, &size_change_ok)) return FALSE; @@ -2510,23 +2543,21 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h, over to the real definition. */ if (h->u.weakdef != NULL) { - struct elf_link_hash_entry *weakdef; - - weakdef = h->u.weakdef; - while (h->root.type == bfd_link_hash_indirect) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - - BFD_ASSERT (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak); - BFD_ASSERT (weakdef->def_dynamic); - /* If the real definition is defined by a regular object file, don't do anything special. See the longer description in _bfd_elf_adjust_dynamic_symbol, below. */ - if (weakdef->def_regular) + if (h->u.weakdef->def_regular) h->u.weakdef = NULL; else { + struct elf_link_hash_entry *weakdef = h->u.weakdef; + + while (h->root.type == bfd_link_hash_indirect) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + + BFD_ASSERT (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak); + BFD_ASSERT (weakdef->def_dynamic); BFD_ASSERT (weakdef->root.type == bfd_link_hash_defined || weakdef->root.type == bfd_link_hash_defweak); (*bed->elf_backend_copy_indirect_symbol) (eif->info, weakdef, h); @@ -2708,7 +2739,7 @@ _bfd_elf_link_sec_merge_syms (struct elf_link_hash_entry *h, void *data) if ((h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) && ((sec = h->root.u.def.section)->flags & SEC_MERGE) - && sec->sec_info_type == ELF_INFO_TYPE_MERGE) + && sec->sec_info_type == SEC_INFO_TYPE_MERGE) { bfd *output_bfd = (bfd *) data; @@ -3031,7 +3062,7 @@ _bfd_elf_add_dynamic_entry (struct bfd_link_info *info, return FALSE; bed = get_elf_backend_data (hash_table->dynobj); - s = bfd_get_section_by_name (hash_table->dynobj, ".dynamic"); + s = bfd_get_linker_section (hash_table->dynobj, ".dynamic"); BFD_ASSERT (s != NULL); newsize = s->size + bed->s->sizeof_dyn; @@ -3079,7 +3110,7 @@ elf_add_dt_needed_tag (bfd *abfd, bfd_byte *extdyn; bed = get_elf_backend_data (hash_table->dynobj); - sdyn = bfd_get_section_by_name (hash_table->dynobj, ".dynamic"); + sdyn = bfd_get_linker_section (hash_table->dynobj, ".dynamic"); if (sdyn != NULL) for (extdyn = sdyn->contents; extdyn < sdyn->contents + sdyn->size; @@ -3122,7 +3153,7 @@ on_needed_list (const char *soname, struct bfd_link_needed_list *needed) return FALSE; } -/* Sort symbol by value and section. */ +/* Sort symbol by value, section, and size. */ static int elf_sort_symbol (const void *arg1, const void *arg2) { @@ -3141,7 +3172,8 @@ elf_sort_symbol (const void *arg1, const void *arg2) if (sdiff != 0) return sdiff > 0 ? 1 : -1; } - return 0; + vdiff = h1->size - h2->size; + return vdiff == 0 ? 0 : vdiff > 0 ? 1 : -1; } /* This function is used to adjust offsets into .dynstr for @@ -3176,7 +3208,7 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info) size = _bfd_elf_strtab_size (dynstr); bed = get_elf_backend_data (dynobj); - sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); + sdyn = bfd_get_linker_section (dynobj, ".dynamic"); BFD_ASSERT (sdyn != NULL); /* Update all .dynamic entries referencing .dynstr strings. */ @@ -3225,7 +3257,7 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info) Elf_Internal_Verdef def; Elf_Internal_Verdaux defaux; - s = bfd_get_section_by_name (dynobj, ".gnu.version_d"); + s = bfd_get_linker_section (dynobj, ".gnu.version_d"); p = s->contents; do { @@ -3257,7 +3289,7 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info) Elf_Internal_Verneed need; Elf_Internal_Vernaux needaux; - s = bfd_get_section_by_name (dynobj, ".gnu.version_r"); + s = bfd_get_linker_section (dynobj, ".gnu.version_r"); p = s->contents; do { @@ -3499,7 +3531,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) /* ld --just-symbols and dynamic objects don't mix very well. ld shouldn't allow it. */ if ((s = abfd->sections) != NULL - && s->sec_info_type == ELF_INFO_TYPE_JUST_SYMS) + && s->sec_info_type == SEC_INFO_TYPE_JUST_SYMS) abort (); /* If this dynamic lib was specified on the command line with @@ -3834,10 +3866,13 @@ error_free_dyn: flagword flags; const char *name; struct elf_link_hash_entry *h; + struct elf_link_hash_entry *hi; bfd_boolean definition; bfd_boolean size_change_ok; bfd_boolean type_change_ok; bfd_boolean new_weakdef; + bfd_boolean new_weak; + bfd_boolean old_weak; bfd_boolean override; bfd_boolean common; unsigned int old_alignment; @@ -3896,7 +3931,7 @@ error_free_dyn: sec = bfd_section_from_elf_index (abfd, isym->st_shndx); if (sec == NULL) sec = bfd_abs_section_ptr; - else if (elf_discarded_section (sec)) + else if (discarded_section (sec)) { /* Symbols from discarded section are undefined. We keep its visibility. */ @@ -3970,6 +4005,7 @@ error_free_dyn: size_change_ok = FALSE; type_change_ok = bed->type_change_ok; + old_weak = FALSE; old_alignment = 0; old_bfd = NULL; new_sec = sec; @@ -4115,7 +4151,7 @@ error_free_dyn: } if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec, - &value, &old_alignment, + &value, &old_weak, &old_alignment, sym_hash, &skip, &override, &type_change_ok, &size_change_ok)) goto error_free_vers; @@ -4166,6 +4202,9 @@ error_free_dyn: goto error_free_vers; h = *sym_hash; + /* We need to make sure that indirect symbol dynamic flags are + updated. */ + hi = h; while (h->root.type == bfd_link_hash_indirect || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; @@ -4174,10 +4213,11 @@ error_free_dyn: if (is_elf_hash_table (htab)) h->unique_global = (flags & BSF_GNU_UNIQUE) != 0; + new_weak = (flags & BSF_WEAK) != 0; new_weakdef = FALSE; if (dynamic && definition - && (flags & BSF_WEAK) != 0 + && new_weak && !bed->is_function_type (ELF_ST_TYPE (isym->st_info)) && is_elf_hash_table (htab) && h->u.weakdef == NULL) @@ -4306,7 +4346,9 @@ error_free_dyn: h->size = h->root.u.c.size; if (ELF_ST_TYPE (isym->st_info) != STT_NOTYPE - && (definition || h->type == STT_NOTYPE)) + && ((definition && !new_weak) + || (old_weak && h->root.type == bfd_link_hash_common) + || h->type == STT_NOTYPE)) { unsigned int type = ELF_ST_TYPE (isym->st_info); @@ -4354,25 +4396,38 @@ error_free_dyn: h->ref_dynamic = 1; } } - if (! info->executable - || h->def_dynamic - || h->ref_dynamic) + + /* If the indirect symbol has been forced local, don't + make the real symbol dynamic. */ + if ((h == hi || !hi->forced_local) + && (! info->executable + || h->def_dynamic + || h->ref_dynamic)) dynsym = TRUE; } else { if (! definition) - h->ref_dynamic = 1; + { + h->ref_dynamic = 1; + hi->ref_dynamic = 1; + } else { h->def_dynamic = 1; h->dynamic_def = 1; + hi->def_dynamic = 1; + hi->dynamic_def = 1; } - if (h->def_regular - || h->ref_regular - || (h->u.weakdef != NULL - && ! new_weakdef - && h->u.weakdef->dynindx != -1)) + + /* If the indirect symbol has been forced local, don't + make the real symbol dynamic. */ + if ((h == hi || !hi->forced_local) + && (h->def_regular + || h->ref_regular + || (h->u.weakdef != NULL + && ! new_weakdef + && h->u.weakdef->dynindx != -1))) dynsym = TRUE; } @@ -4686,7 +4741,6 @@ error_free_dyn: struct elf_link_hash_entry *hlook; asection *slook; bfd_vma vlook; - long ilook; size_t i, j, idx; hlook = weaks; @@ -4700,14 +4754,13 @@ error_free_dyn: slook = hlook->root.u.def.section; vlook = hlook->root.u.def.value; - ilook = -1; i = 0; j = sym_count; - while (i < j) + while (i != j) { bfd_signed_vma vdiff; idx = (i + j) / 2; - h = sorted_sym_hash [idx]; + h = sorted_sym_hash[idx]; vdiff = vlook - h->root.u.def.value; if (vdiff < 0) j = idx; @@ -4721,24 +4774,36 @@ error_free_dyn: else if (sdiff > 0) i = idx + 1; else - { - ilook = idx; - break; - } + break; } } /* We didn't find a value/section match. */ - if (ilook == -1) + if (i == j) continue; - for (i = ilook; i < sym_count; i++) + /* With multiple aliases, or when the weak symbol is already + strongly defined, we have multiple matching symbols and + the binary search above may land on any of them. Step + one past the matching symbol(s). */ + while (++idx != j) { - h = sorted_sym_hash [i]; + h = sorted_sym_hash[idx]; + if (h->root.u.def.section != slook + || h->root.u.def.value != vlook) + break; + } + + /* Now look back over the aliases. Since we sorted by size + as well as value and section, we'll choose the one with + the largest size. */ + while (idx-- != i) + { + h = sorted_sym_hash[idx]; /* Stop if value or section doesn't match. */ - if (h->root.u.def.value != vlook - || h->root.u.def.section != slook) + if (h->root.u.def.section != slook + || h->root.u.def.value != vlook) break; else if (h != hlook) { @@ -4861,7 +4926,7 @@ error_free_dyn: &string_offset)) goto error_return; if (secdata->sec_info) - stab->sec_info_type = ELF_INFO_TYPE_STABS; + stab->sec_info_type = SEC_INFO_TYPE_STABS; } } } @@ -5502,6 +5567,65 @@ _bfd_elf_size_group_sections (struct bfd_link_info *info) return TRUE; } +/* Set a default stack segment size. The value in INFO wins. If it + is unset, LEGACY_SYMBOL's value is used, and if that symbol is + undefined it is initialized. */ + +bfd_boolean +bfd_elf_stack_segment_size (bfd *output_bfd, + struct bfd_link_info *info, + const char *legacy_symbol, + bfd_vma default_size) +{ + struct elf_link_hash_entry *h = NULL; + + /* Look for legacy symbol. */ + if (legacy_symbol) + h = elf_link_hash_lookup (elf_hash_table (info), legacy_symbol, + FALSE, FALSE, FALSE); + if (h && (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && h->def_regular + && (h->type == STT_NOTYPE || h->type == STT_OBJECT)) + { + /* The symbol has no type if specified on the command line. */ + h->type = STT_OBJECT; + if (info->stacksize) + (*_bfd_error_handler) (_("%B: stack size specified and %s set"), + output_bfd, legacy_symbol); + else if (h->root.u.def.section != bfd_abs_section_ptr) + (*_bfd_error_handler) (_("%B: %s not absolute"), + output_bfd, legacy_symbol); + else + info->stacksize = h->root.u.def.value; + } + + if (!info->stacksize) + /* If the user didn't set a size, or explicitly inhibit the + size, set it now. */ + info->stacksize = default_size; + + /* Provide the legacy symbol, if it is referenced. */ + if (h && (h->root.type == bfd_link_hash_undefined + || h->root.type == bfd_link_hash_undefweak)) + { + struct bfd_link_hash_entry *bh = NULL; + + if (!(_bfd_generic_link_add_one_symbol + (info, output_bfd, legacy_symbol, + BSF_GLOBAL, bfd_abs_section_ptr, + info->stacksize >= 0 ? info->stacksize : 0, + NULL, FALSE, get_elf_backend_data (output_bfd)->collect, &bh))) + return FALSE; + + h = (struct elf_link_hash_entry *) bh; + h->def_regular = 1; + h->type = STT_OBJECT; + } + + return TRUE; +} + /* 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 @@ -5531,6 +5655,26 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, return TRUE; bed = get_elf_backend_data (output_bfd); + + /* Any syms created from now on start with -1 in + got.refcount/offset and plt.refcount/offset. */ + elf_hash_table (info)->init_got_refcount + = elf_hash_table (info)->init_got_offset; + elf_hash_table (info)->init_plt_refcount + = elf_hash_table (info)->init_plt_offset; + + if (info->relocatable + && !_bfd_elf_size_group_sections (info)) + return FALSE; + + /* The backend may have to create some sections regardless of whether + we're dynamic or not. */ + if (bed->elf_backend_always_size_sections + && ! (*bed->elf_backend_always_size_sections) (output_bfd, info)) + return FALSE; + + /* Determine any GNU_STACK segment requirements, after the backend + has had a chance to set a default segment size. */ if (info->execstack) elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | PF_X; else if (info->noexecstack) @@ -5560,43 +5704,16 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, else if (bed->default_execstack) exec = PF_X; } - if (notesec) - { - elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | exec; - if (exec && info->relocatable - && notesec->output_section != bfd_abs_section_ptr) - notesec->output_section->flags |= SEC_CODE; - } + if (notesec || info->stacksize > 0) + elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | exec; + if (notesec && exec && info->relocatable + && notesec->output_section != bfd_abs_section_ptr) + notesec->output_section->flags |= SEC_CODE; } - /* Any syms created from now on start with -1 in - got.refcount/offset and plt.refcount/offset. */ - elf_hash_table (info)->init_got_refcount - = elf_hash_table (info)->init_got_offset; - elf_hash_table (info)->init_plt_refcount - = elf_hash_table (info)->init_plt_offset; - - if (info->relocatable - && !_bfd_elf_size_group_sections (info)) - return FALSE; - - /* The backend may have to create some sections regardless of whether - we're dynamic or not. */ - if (bed->elf_backend_always_size_sections - && ! (*bed->elf_backend_always_size_sections) (output_bfd, info)) - return FALSE; - - if (! _bfd_elf_maybe_strip_eh_frame_hdr (info)) - return FALSE; - dynobj = elf_hash_table (info)->dynobj; - /* If there were no dynamic objects in the link, there is nothing to - do here. */ - if (dynobj == NULL) - return TRUE; - - if (elf_hash_table (info)->dynamic_sections_created) + if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created) { struct elf_info_failed eif; struct elf_link_hash_entry *h; @@ -5606,7 +5723,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, asection *s; bfd_boolean all_defined; - *sinterpptr = bfd_get_section_by_name (dynobj, ".interp"); + *sinterpptr = bfd_get_linker_section (dynobj, ".interp"); BFD_ASSERT (*sinterpptr != NULL || !info->executable); if (soname != NULL) @@ -5874,7 +5991,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, return FALSE; } - dynstr = bfd_get_section_by_name (dynobj, ".dynstr"); + dynstr = bfd_get_linker_section (dynobj, ".dynstr"); /* If .dynstr is excluded from the link, we don't want any of these tags. Strictly, we should be checking each section individually; This quick check covers for the case where @@ -5899,18 +6016,22 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, /* The backend must work out the sizes of all the other dynamic sections. */ - if (bed->elf_backend_size_dynamic_sections + if (dynobj != NULL + && bed->elf_backend_size_dynamic_sections != NULL && ! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info)) return FALSE; - if (elf_hash_table (info)->dynamic_sections_created) + if (! _bfd_elf_maybe_strip_eh_frame_hdr (info)) + return FALSE; + + if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created) { unsigned long section_sym_count; struct bfd_elf_version_tree *verdefs; asection *s; /* Set up the version definition section. */ - s = bfd_get_section_by_name (dynobj, ".gnu.version_d"); + s = bfd_get_linker_section (dynobj, ".gnu.version_d"); BFD_ASSERT (s != NULL); /* We may have created additional version definitions if we are @@ -6173,7 +6294,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, /* Work out the size of the version reference section. */ - s = bfd_get_section_by_name (dynobj, ".gnu.version_r"); + s = bfd_get_linker_section (dynobj, ".gnu.version_r"); BFD_ASSERT (s != NULL); { struct elf_find_verdep_info sinfo; @@ -6285,7 +6406,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, || _bfd_elf_link_renumber_dynsyms (output_bfd, info, §ion_sym_count) == 0) { - s = bfd_get_section_by_name (dynobj, ".gnu.version"); + s = bfd_get_linker_section (dynobj, ".gnu.version"); s->flags |= SEC_EXCLUDE; } } @@ -6369,7 +6490,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) §ion_sym_count); /* Work out the size of the symbol version section. */ - s = bfd_get_section_by_name (dynobj, ".gnu.version"); + s = bfd_get_linker_section (dynobj, ".gnu.version"); BFD_ASSERT (s != NULL); if (dynsymcount != 0 && (s->flags & SEC_EXCLUDE) == 0) @@ -6389,7 +6510,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) the final symbol table, because until then we do not know the correct value to give the symbols. We built the .dynstr section as we went along in elf_link_add_object_symbols. */ - s = bfd_get_section_by_name (dynobj, ".dynsym"); + s = bfd_get_linker_section (dynobj, ".dynsym"); BFD_ASSERT (s != NULL); s->size = dynsymcount * bed->s->sizeof_sym; @@ -6447,7 +6568,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) elf_hash_table (info)->bucketcount = bucketcount; - s = bfd_get_section_by_name (dynobj, ".hash"); + s = bfd_get_linker_section (dynobj, ".hash"); BFD_ASSERT (s != NULL); hash_entry_size = elf_section_data (s)->this_hdr.sh_entsize; s->size = ((2 + bucketcount + dynsymcount) * hash_entry_size); @@ -6501,7 +6622,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) return FALSE; } - s = bfd_get_section_by_name (dynobj, ".gnu.hash"); + s = bfd_get_linker_section (dynobj, ".gnu.hash"); BFD_ASSERT (s != NULL); if (cinfo.nsyms == 0) @@ -6629,7 +6750,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) } } - s = bfd_get_section_by_name (dynobj, ".dynstr"); + s = bfd_get_linker_section (dynobj, ".dynstr"); BFD_ASSERT (s != NULL); elf_finalize_dynstr (output_bfd, info); @@ -6644,25 +6765,14 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) return TRUE; } -/* Indicate that we are only retrieving symbol values from this - section. */ - -void -_bfd_elf_link_just_syms (asection *sec, struct bfd_link_info *info) -{ - if (is_elf_hash_table (info->hash)) - sec->sec_info_type = ELF_INFO_TYPE_JUST_SYMS; - _bfd_generic_link_just_syms (sec, info); -} - /* Make sure sec_info_type is cleared if sec_info is cleared too. */ static void merge_sections_remove_hook (bfd *abfd ATTRIBUTE_UNUSED, asection *sec) { - BFD_ASSERT (sec->sec_info_type == ELF_INFO_TYPE_MERGE); - sec->sec_info_type = ELF_INFO_TYPE_NONE; + BFD_ASSERT (sec->sec_info_type == SEC_INFO_TYPE_MERGE); + sec->sec_info_type = SEC_INFO_TYPE_NONE; } /* Finish SHF_MERGE section merging. */ @@ -6690,7 +6800,7 @@ _bfd_elf_merge_sections (bfd *abfd, struct bfd_link_info *info) sec, &secdata->sec_info)) return FALSE; else if (secdata->sec_info) - sec->sec_info_type = ELF_INFO_TYPE_MERGE; + sec->sec_info_type = SEC_INFO_TYPE_MERGE; } if (elf_hash_table (info)->merge_info != NULL) @@ -7413,6 +7523,8 @@ struct elf_final_link_info size_t symbuf_size; /* And same for symshndxbuf. */ size_t shndxbuf_size; + /* Number of STT_FILE syms seen. */ + size_t filesym_count; }; /* This struct is used to pass information to elf_link_output_extsym. */ @@ -7421,7 +7533,9 @@ struct elf_outext_info { bfd_boolean failed; bfd_boolean localsyms; - struct elf_final_link_info *finfo; + bfd_boolean need_second_pass; + bfd_boolean second_pass; + struct elf_final_link_info *flinfo; }; @@ -7498,7 +7612,7 @@ set_symbol_value (bfd *bfd_with_globals, static bfd_boolean resolve_symbol (const char *name, bfd *input_bfd, - struct elf_final_link_info *finfo, + struct elf_final_link_info *flinfo, bfd_vma *result, Elf_Internal_Sym *isymbuf, size_t locsymcount) @@ -7527,7 +7641,7 @@ resolve_symbol (const char *name, #endif if (candidate && strcmp (candidate, name) == 0) { - asection *sec = finfo->sections [i]; + asection *sec = flinfo->sections [i]; *result = _bfd_elf_rel_local_sym (input_bfd, sym, &sec, 0); *result += sec->output_offset + sec->output_section->vma; @@ -7540,7 +7654,7 @@ resolve_symbol (const char *name, } /* Hmm, haven't found it yet. perhaps it is a global. */ - global_entry = bfd_link_hash_lookup (finfo->info->hash, name, + global_entry = bfd_link_hash_lookup (flinfo->info->hash, name, FALSE, FALSE, TRUE); if (!global_entry) return FALSE; @@ -7609,7 +7723,7 @@ static bfd_boolean eval_symbol (bfd_vma *result, const char **symp, bfd *input_bfd, - struct elf_final_link_info *finfo, + struct elf_final_link_info *flinfo, bfd_vma dot, Elf_Internal_Sym *isymbuf, size_t locsymcount, @@ -7669,8 +7783,8 @@ eval_symbol (bfd_vma *result, if (symbol_is_section) { - if (!resolve_section (symbuf, finfo->output_bfd->sections, result) - && !resolve_symbol (symbuf, input_bfd, finfo, result, + if (!resolve_section (symbuf, flinfo->output_bfd->sections, result) + && !resolve_symbol (symbuf, input_bfd, flinfo, result, isymbuf, locsymcount)) { undefined_reference ("section", symbuf); @@ -7679,9 +7793,9 @@ eval_symbol (bfd_vma *result, } else { - if (!resolve_symbol (symbuf, input_bfd, finfo, result, + if (!resolve_symbol (symbuf, input_bfd, flinfo, result, isymbuf, locsymcount) - && !resolve_section (symbuf, finfo->output_bfd->sections, + && !resolve_section (symbuf, flinfo->output_bfd->sections, result)) { undefined_reference ("symbol", symbuf); @@ -7700,7 +7814,7 @@ eval_symbol (bfd_vma *result, if (*sym == ':') \ ++sym; \ *symp = sym; \ - if (!eval_symbol (&a, symp, input_bfd, finfo, dot, \ + if (!eval_symbol (&a, symp, input_bfd, flinfo, dot, \ isymbuf, locsymcount, signed_p)) \ return FALSE; \ if (signed_p) \ @@ -7717,11 +7831,11 @@ eval_symbol (bfd_vma *result, if (*sym == ':') \ ++sym; \ *symp = sym; \ - if (!eval_symbol (&a, symp, input_bfd, finfo, dot, \ + if (!eval_symbol (&a, symp, input_bfd, flinfo, dot, \ isymbuf, locsymcount, signed_p)) \ return FALSE; \ ++*symp; \ - if (!eval_symbol (&b, symp, input_bfd, finfo, dot, \ + if (!eval_symbol (&b, symp, input_bfd, flinfo, dot, \ isymbuf, locsymcount, signed_p)) \ return FALSE; \ if (signed_p) \ @@ -7803,31 +7917,49 @@ get_value (bfd_vma size, bfd *input_bfd, bfd_byte *location) { + int shift; bfd_vma x = 0; + /* Sanity checks. */ + BFD_ASSERT (chunksz <= sizeof (x) + && size >= chunksz + && chunksz != 0 + && (size % chunksz) == 0 + && input_bfd != NULL + && location != NULL); + + if (chunksz == sizeof (x)) + { + BFD_ASSERT (size == chunksz); + + /* Make sure that we do not perform an undefined shift operation. + We know that size == chunksz so there will only be one iteration + of the loop below. */ + shift = 0; + } + else + shift = 8 * chunksz; + for (; size; size -= chunksz, location += chunksz) { switch (chunksz) { - default: - case 0: - abort (); case 1: - x = (x << (8 * chunksz)) | bfd_get_8 (input_bfd, location); + x = (x << shift) | bfd_get_8 (input_bfd, location); break; case 2: - x = (x << (8 * chunksz)) | bfd_get_16 (input_bfd, location); + x = (x << shift) | bfd_get_16 (input_bfd, location); break; case 4: - x = (x << (8 * chunksz)) | bfd_get_32 (input_bfd, location); + x = (x << shift) | bfd_get_32 (input_bfd, location); break; - case 8: #ifdef BFD64 - x = (x << (8 * chunksz)) | bfd_get_64 (input_bfd, location); -#else - abort (); -#endif + case 8: + x = (x << shift) | bfd_get_64 (input_bfd, location); break; +#endif + default: + abort (); } } return x; @@ -8319,24 +8451,24 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) /* Flush the output symbols to the file. */ static bfd_boolean -elf_link_flush_output_syms (struct elf_final_link_info *finfo, +elf_link_flush_output_syms (struct elf_final_link_info *flinfo, const struct elf_backend_data *bed) { - if (finfo->symbuf_count > 0) + if (flinfo->symbuf_count > 0) { Elf_Internal_Shdr *hdr; file_ptr pos; bfd_size_type amt; - hdr = &elf_tdata (finfo->output_bfd)->symtab_hdr; + hdr = &elf_tdata (flinfo->output_bfd)->symtab_hdr; pos = hdr->sh_offset + hdr->sh_size; - amt = finfo->symbuf_count * bed->s->sizeof_sym; - if (bfd_seek (finfo->output_bfd, pos, SEEK_SET) != 0 - || bfd_bwrite (finfo->symbuf, amt, finfo->output_bfd) != amt) + amt = flinfo->symbuf_count * bed->s->sizeof_sym; + if (bfd_seek (flinfo->output_bfd, pos, SEEK_SET) != 0 + || bfd_bwrite (flinfo->symbuf, amt, flinfo->output_bfd) != amt) return FALSE; hdr->sh_size += amt; - finfo->symbuf_count = 0; + flinfo->symbuf_count = 0; } return TRUE; @@ -8345,7 +8477,7 @@ elf_link_flush_output_syms (struct elf_final_link_info *finfo, /* Add a symbol to the output symbol table. */ static int -elf_link_output_sym (struct elf_final_link_info *finfo, +elf_link_output_sym (struct elf_final_link_info *flinfo, const char *name, Elf_Internal_Sym *elfsym, asection *input_sec, @@ -8358,11 +8490,11 @@ elf_link_output_sym (struct elf_final_link_info *finfo, struct elf_link_hash_entry *); const struct elf_backend_data *bed; - bed = get_elf_backend_data (finfo->output_bfd); + bed = get_elf_backend_data (flinfo->output_bfd); output_symbol_hook = bed->elf_backend_link_output_symbol_hook; if (output_symbol_hook != NULL) { - int ret = (*output_symbol_hook) (finfo->info, name, elfsym, input_sec, h); + int ret = (*output_symbol_hook) (flinfo->info, name, elfsym, input_sec, h); if (ret != 1) return ret; } @@ -8373,41 +8505,41 @@ elf_link_output_sym (struct elf_final_link_info *finfo, elfsym->st_name = 0; else { - elfsym->st_name = (unsigned long) _bfd_stringtab_add (finfo->symstrtab, + elfsym->st_name = (unsigned long) _bfd_stringtab_add (flinfo->symstrtab, name, TRUE, FALSE); if (elfsym->st_name == (unsigned long) -1) return 0; } - if (finfo->symbuf_count >= finfo->symbuf_size) + if (flinfo->symbuf_count >= flinfo->symbuf_size) { - if (! elf_link_flush_output_syms (finfo, bed)) + if (! elf_link_flush_output_syms (flinfo, bed)) return 0; } - dest = finfo->symbuf + finfo->symbuf_count * bed->s->sizeof_sym; - destshndx = finfo->symshndxbuf; + dest = flinfo->symbuf + flinfo->symbuf_count * bed->s->sizeof_sym; + destshndx = flinfo->symshndxbuf; if (destshndx != NULL) { - if (bfd_get_symcount (finfo->output_bfd) >= finfo->shndxbuf_size) + if (bfd_get_symcount (flinfo->output_bfd) >= flinfo->shndxbuf_size) { bfd_size_type amt; - amt = finfo->shndxbuf_size * sizeof (Elf_External_Sym_Shndx); + amt = flinfo->shndxbuf_size * sizeof (Elf_External_Sym_Shndx); destshndx = (Elf_External_Sym_Shndx *) bfd_realloc (destshndx, amt * 2); if (destshndx == NULL) return 0; - finfo->symshndxbuf = destshndx; + flinfo->symshndxbuf = destshndx; memset ((char *) destshndx + amt, 0, amt); - finfo->shndxbuf_size *= 2; + flinfo->shndxbuf_size *= 2; } - destshndx += bfd_get_symcount (finfo->output_bfd); + destshndx += bfd_get_symcount (flinfo->output_bfd); } - bed->s->swap_symbol_out (finfo->output_bfd, elfsym, dest, destshndx); - finfo->symbuf_count += 1; - bfd_get_symcount (finfo->output_bfd) += 1; + bed->s->swap_symbol_out (flinfo->output_bfd, elfsym, dest, destshndx); + flinfo->symbuf_count += 1; + bfd_get_symcount (flinfo->output_bfd) += 1; return 1; } @@ -8448,6 +8580,10 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info, if (!is_elf_hash_table (info->hash)) return FALSE; + /* Check indirect symbol. */ + while (h->root.type == bfd_link_hash_indirect) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + switch (h->root.type) { default: @@ -8595,7 +8731,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) { struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) bh; struct elf_outext_info *eoinfo = (struct elf_outext_info *) data; - struct elf_final_link_info *finfo = eoinfo->finfo; + struct elf_final_link_info *flinfo = eoinfo->flinfo; bfd_boolean strip; Elf_Internal_Sym sym; asection *input_sec; @@ -8615,6 +8751,11 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) { if (!h->forced_local) return TRUE; + if (eoinfo->second_pass + && !((h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && h->root.u.def.section->output_section != NULL)) + return TRUE; } else { @@ -8622,7 +8763,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) return TRUE; } - bed = get_elf_backend_data (finfo->output_bfd); + bed = get_elf_backend_data (flinfo->output_bfd); if (h->root.type == bfd_link_hash_undefined) { @@ -8641,14 +8782,16 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) /* If we are reporting errors for this situation then do so now. */ if (!ignore_undef && h->ref_dynamic - && (!h->ref_regular || finfo->info->gc_sections) - && ! elf_link_check_versioned_symbol (finfo->info, bed, h) - && finfo->info->unresolved_syms_in_shared_libs != RM_IGNORE) - { - if (! (finfo->info->callbacks->undefined_symbol - (finfo->info, h->root.root.string, - h->ref_regular ? NULL : h->root.u.undef.abfd, - NULL, 0, finfo->info->unresolved_syms_in_shared_libs == RM_GENERATE_ERROR))) + && (!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; @@ -8659,17 +8802,22 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) /* We should also warn if a forced local symbol is referenced from shared libraries. */ - if (!finfo->info->relocatable - && finfo->info->executable + if (!flinfo->info->relocatable + && flinfo->info->executable && h->forced_local && h->ref_dynamic && h->def_regular && !h->dynamic_def && !h->dynamic_weak - && ! elf_link_check_versioned_symbol (finfo->info, bed, h)) + && !elf_link_check_versioned_symbol (flinfo->info, bed, h)) { bfd *def_bfd; const char *msg; + struct elf_link_hash_entry *hi = h; + + /* Check indirect symbol. */ + while (hi->root.type == bfd_link_hash_indirect) + hi = (struct elf_link_hash_entry *) hi->root.u.i.link; if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL) msg = _("%B: internal symbol `%s' in %B is referenced by DSO"); @@ -8677,10 +8825,10 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) msg = _("%B: hidden symbol `%s' in %B is referenced by DSO"); else msg = _("%B: local symbol `%s' in %B is referenced by DSO"); - def_bfd = finfo->output_bfd; - if (h->root.u.def.section != bfd_abs_section_ptr) - def_bfd = h->root.u.def.section->owner; - (*_bfd_error_handler) (msg, finfo->output_bfd, def_bfd, + def_bfd = flinfo->output_bfd; + if (hi->root.u.def.section != bfd_abs_section_ptr) + def_bfd = hi->root.u.def.section->owner; + (*_bfd_error_handler) (msg, flinfo->output_bfd, def_bfd, h->root.root.string); bfd_set_error (bfd_error_bad_value); eoinfo->failed = TRUE; @@ -8699,16 +8847,16 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) && !h->def_regular && !h->ref_regular) strip = TRUE; - else if (finfo->info->strip == strip_all) + else if (flinfo->info->strip == strip_all) strip = TRUE; - else if (finfo->info->strip == strip_some - && bfd_hash_lookup (finfo->info->keep_hash, + else if (flinfo->info->strip == strip_some + && bfd_hash_lookup (flinfo->info->keep_hash, h->root.root.string, FALSE, FALSE) == NULL) strip = TRUE; else if ((h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) - && ((finfo->info->strip_discarded - && elf_discarded_section (h->root.u.def.section)) + && ((flinfo->info->strip_discarded + && discarded_section (h->root.u.def.section)) || (h->root.u.def.section->owner != NULL && (h->root.u.def.section->owner->flags & BFD_PLUGIN) != 0))) strip = TRUE; @@ -8767,14 +8915,27 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) input_sec = h->root.u.def.section; if (input_sec->output_section != NULL) { + if (eoinfo->localsyms && flinfo->filesym_count == 1) + { + bfd_boolean second_pass_sym + = (input_sec->owner == flinfo->output_bfd + || input_sec->owner == NULL + || (input_sec->flags & SEC_LINKER_CREATED) != 0 + || (input_sec->owner->flags & BFD_LINKER_CREATED) != 0); + + eoinfo->need_second_pass |= second_pass_sym; + if (eoinfo->second_pass != second_pass_sym) + return TRUE; + } + sym.st_shndx = - _bfd_elf_section_from_bfd_section (finfo->output_bfd, + _bfd_elf_section_from_bfd_section (flinfo->output_bfd, input_sec->output_section); if (sym.st_shndx == SHN_BAD) { (*_bfd_error_handler) (_("%B: could not find output section %A for input section %A"), - finfo->output_bfd, input_sec->output_section, input_sec); + flinfo->output_bfd, input_sec->output_section, input_sec); bfd_set_error (bfd_error_nonrepresentable_section); eoinfo->failed = TRUE; return FALSE; @@ -8784,18 +8945,18 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) but in nonrelocatable files they are virtual addresses. */ sym.st_value = h->root.u.def.value + input_sec->output_offset; - if (! finfo->info->relocatable) + if (!flinfo->info->relocatable) { sym.st_value += input_sec->output_section->vma; if (h->type == STT_TLS) { - asection *tls_sec = elf_hash_table (finfo->info)->tls_sec; + asection *tls_sec = elf_hash_table (flinfo->info)->tls_sec; if (tls_sec != NULL) sym.st_value -= tls_sec->vma; else { /* The TLS section may have been garbage collected. */ - BFD_ASSERT (finfo->info->gc_sections + BFD_ASSERT (flinfo->info->gc_sections && !input_sec->gc_mark); } } @@ -8834,17 +8995,17 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) STT_GNU_IFUNC symbol must go through PLT. */ if ((h->type == STT_GNU_IFUNC && h->def_regular - && !finfo->info->relocatable) + && !flinfo->info->relocatable) || ((h->dynindx != -1 || h->forced_local) - && ((finfo->info->shared + && ((flinfo->info->shared && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak)) || !h->forced_local) - && elf_hash_table (finfo->info)->dynamic_sections_created)) + && elf_hash_table (flinfo->info)->dynamic_sections_created)) { if (! ((*bed->elf_backend_finish_dynamic_symbol) - (finfo->output_bfd, finfo->info, h, &sym))) + (flinfo->output_bfd, flinfo->info, h, &sym))) { eoinfo->failed = TRUE; return FALSE; @@ -8887,7 +9048,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) /* If a non-weak symbol with non-default visibility is not defined locally, it is a fatal error. */ - if (! finfo->info->relocatable + if (!flinfo->info->relocatable && ELF_ST_VISIBILITY (sym.st_other) != STV_DEFAULT && ELF_ST_BIND (sym.st_info) != STB_WEAK && h->root.type == bfd_link_hash_undefined @@ -8901,7 +9062,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) msg = _("%B: internal symbol `%s' isn't defined"); else msg = _("%B: hidden symbol `%s' isn't defined"); - (*_bfd_error_handler) (msg, finfo->output_bfd, h->root.root.string); + (*_bfd_error_handler) (msg, flinfo->output_bfd, h->root.root.string); bfd_set_error (bfd_error_bad_value); eoinfo->failed = TRUE; return FALSE; @@ -8910,21 +9071,39 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) /* If this symbol should be put in the .dynsym section, then put it there now. We already know the symbol index. We also fill in the entry in the .hash section. */ - if (h->dynindx != -1 - && elf_hash_table (finfo->info)->dynamic_sections_created) + if (flinfo->dynsym_sec != NULL + && h->dynindx != -1 + && elf_hash_table (flinfo->info)->dynamic_sections_created) { bfd_byte *esym; + /* Since there is no version information in the dynamic string, + if there is no version info in symbol version section, we will + have a run-time problem. */ + if (h->verinfo.verdef == NULL) + { + char *p = strrchr (h->root.root.string, ELF_VER_CHR); + + if (p && p [1] != '\0') + { + (*_bfd_error_handler) + (_("%B: No symbol version section for versioned symbol `%s'"), + flinfo->output_bfd, h->root.root.string); + eoinfo->failed = TRUE; + return FALSE; + } + } + sym.st_name = h->dynstr_index; - esym = finfo->dynsym_sec->contents + h->dynindx * bed->s->sizeof_sym; - if (! check_dynsym (finfo->output_bfd, &sym)) + esym = flinfo->dynsym_sec->contents + h->dynindx * bed->s->sizeof_sym; + if (!check_dynsym (flinfo->output_bfd, &sym)) { eoinfo->failed = TRUE; return FALSE; } - bed->s->swap_symbol_out (finfo->output_bfd, &sym, esym, 0); + bed->s->swap_symbol_out (flinfo->output_bfd, &sym, esym, 0); - if (finfo->hash_sec != NULL) + if (flinfo->hash_sec != NULL) { size_t hash_entry_size; bfd_byte *bucketpos; @@ -8932,21 +9111,22 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) size_t bucketcount; size_t bucket; - bucketcount = elf_hash_table (finfo->info)->bucketcount; + bucketcount = elf_hash_table (flinfo->info)->bucketcount; bucket = h->u.elf_hash_value % bucketcount; hash_entry_size - = elf_section_data (finfo->hash_sec)->this_hdr.sh_entsize; - bucketpos = ((bfd_byte *) finfo->hash_sec->contents + = elf_section_data (flinfo->hash_sec)->this_hdr.sh_entsize; + bucketpos = ((bfd_byte *) flinfo->hash_sec->contents + (bucket + 2) * hash_entry_size); - chain = bfd_get (8 * hash_entry_size, finfo->output_bfd, bucketpos); - bfd_put (8 * hash_entry_size, finfo->output_bfd, h->dynindx, bucketpos); - bfd_put (8 * hash_entry_size, finfo->output_bfd, chain, - ((bfd_byte *) finfo->hash_sec->contents + chain = bfd_get (8 * hash_entry_size, flinfo->output_bfd, bucketpos); + bfd_put (8 * hash_entry_size, flinfo->output_bfd, h->dynindx, + bucketpos); + bfd_put (8 * hash_entry_size, flinfo->output_bfd, chain, + ((bfd_byte *) flinfo->hash_sec->contents + (bucketcount + 2 + h->dynindx) * hash_entry_size)); } - if (finfo->symver_sec != NULL && finfo->symver_sec->contents != NULL) + if (flinfo->symver_sec != NULL && flinfo->symver_sec->contents != NULL) { Elf_Internal_Versym iversym; Elf_External_Versym *eversym; @@ -8964,16 +9144,16 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) iversym.vs_vers = 1; else iversym.vs_vers = h->verinfo.vertree->vernum + 1; - if (finfo->info->create_default_symver) + if (flinfo->info->create_default_symver) iversym.vs_vers++; } if (h->hidden) iversym.vs_vers |= VERSYM_HIDDEN; - eversym = (Elf_External_Versym *) finfo->symver_sec->contents; + eversym = (Elf_External_Versym *) flinfo->symver_sec->contents; eversym += h->dynindx; - _bfd_elf_swap_versym_out (finfo->output_bfd, &iversym, eversym); + _bfd_elf_swap_versym_out (flinfo->output_bfd, &iversym, eversym); } } @@ -8982,8 +9162,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) if (strip || (input_sec->flags & SEC_EXCLUDE) != 0) return TRUE; - indx = bfd_get_symcount (finfo->output_bfd); - ret = elf_link_output_sym (finfo, h->root.root.string, &sym, input_sec, h); + indx = bfd_get_symcount (flinfo->output_bfd); + ret = elf_link_output_sym (flinfo, h->root.root.string, &sym, input_sec, h); if (ret == 0) { eoinfo->failed = TRUE; @@ -9007,8 +9187,8 @@ elf_section_ignore_discarded_relocs (asection *sec) switch (sec->sec_info_type) { - case ELF_INFO_TYPE_STABS: - case ELF_INFO_TYPE_EH_FRAME: + case SEC_INFO_TYPE_STABS: + case SEC_INFO_TYPE_EH_FRAME: return TRUE; default: break; @@ -9097,7 +9277,7 @@ _bfd_elf_check_kept_section (asection *sec, struct bfd_link_info *info) don't have to keep them in memory. */ static bfd_boolean -elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) +elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) { int (*relocate_section) (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, @@ -9117,8 +9297,9 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) bfd_size_type address_size; bfd_vma r_type_mask; int r_sym_shift; + bfd_boolean have_file_sym = FALSE; - output_bfd = finfo->output_bfd; + output_bfd = flinfo->output_bfd; bed = get_elf_backend_data (output_bfd); relocate_section = bed->elf_backend_relocate_section; @@ -9145,9 +9326,9 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) if (isymbuf == NULL && locsymcount != 0) { isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, locsymcount, 0, - finfo->internal_syms, - finfo->external_syms, - finfo->locsym_shndx); + flinfo->internal_syms, + flinfo->external_syms, + flinfo->locsym_shndx); if (isymbuf == NULL) return FALSE; } @@ -9156,7 +9337,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) SEC_MERGE sections. Write out those local symbols we know are going into the output file. */ isymend = isymbuf + locsymcount; - for (isym = isymbuf, pindex = finfo->indices, ppsection = finfo->sections; + for (isym = isymbuf, pindex = flinfo->indices, ppsection = flinfo->sections; isym < isymend; isym++, pindex++, ppsection++) { @@ -9193,7 +9374,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) *ppsection = NULL; continue; } - else if (isec->sec_info_type == ELF_INFO_TYPE_MERGE + else if (isec->sec_info_type == SEC_INFO_TYPE_MERGE && ELF_ST_TYPE (isym->st_info) != STT_SECTION) isym->st_value = _bfd_merged_section_offset (output_bfd, &isec, @@ -9204,7 +9385,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) *ppsection = isec; /* Don't output the first, undefined, symbol. */ - if (ppsection == finfo->sections) + if (ppsection == flinfo->sections) continue; if (ELF_ST_TYPE (isym->st_info) == STT_SECTION) @@ -9217,7 +9398,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) /* If we are stripping all symbols, we don't want to output this one. */ - if (finfo->info->strip == strip_all) + if (flinfo->info->strip == strip_all) continue; /* If we are discarding all local symbols, we don't want to @@ -9225,7 +9406,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) file, then some of the local symbols may be required by relocs; we output them below as we discover that they are needed. */ - if (finfo->info->discard == discard_all) + if (flinfo->info->discard == discard_all) continue; /* If this symbol is defined in a section which we are @@ -9243,15 +9424,38 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) return FALSE; /* See if we are discarding symbols with this name. */ - if ((finfo->info->strip == strip_some - && (bfd_hash_lookup (finfo->info->keep_hash, name, FALSE, FALSE) + if ((flinfo->info->strip == strip_some + && (bfd_hash_lookup (flinfo->info->keep_hash, name, FALSE, FALSE) == NULL)) - || (((finfo->info->discard == discard_sec_merge - && (isec->flags & SEC_MERGE) && ! finfo->info->relocatable) - || finfo->info->discard == discard_l) + || (((flinfo->info->discard == discard_sec_merge + && (isec->flags & SEC_MERGE) && !flinfo->info->relocatable) + || flinfo->info->discard == discard_l) && bfd_is_local_label_name (input_bfd, name))) continue; + if (ELF_ST_TYPE (isym->st_info) == STT_FILE) + { + have_file_sym = TRUE; + flinfo->filesym_count += 1; + } + if (!have_file_sym) + { + /* In the absence of debug info, bfd_find_nearest_line uses + FILE symbols to determine the source file for local + function symbols. Provide a FILE symbol here if input + files lack such, so that their symbols won't be + associated with a previous input file. It's not the + source file, but the best we can do. */ + have_file_sym = TRUE; + flinfo->filesym_count += 1; + memset (&osym, 0, sizeof (osym)); + osym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE); + osym.st_shndx = SHN_ABS; + if (!elf_link_output_sym (flinfo, input_bfd->filename, &osym, + bfd_abs_section_ptr, NULL)) + return FALSE; + } + osym = *isym; /* Adjust the section index for the output file. */ @@ -9268,19 +9472,19 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) output_section. Any special sections must be set up to meet these requirements. */ osym.st_value += isec->output_offset; - if (! finfo->info->relocatable) + if (!flinfo->info->relocatable) { osym.st_value += isec->output_section->vma; if (ELF_ST_TYPE (osym.st_info) == STT_TLS) { /* STT_TLS symbols are relative to PT_TLS segment base. */ - BFD_ASSERT (elf_hash_table (finfo->info)->tls_sec != NULL); - osym.st_value -= elf_hash_table (finfo->info)->tls_sec->vma; + BFD_ASSERT (elf_hash_table (flinfo->info)->tls_sec != NULL); + osym.st_value -= elf_hash_table (flinfo->info)->tls_sec->vma; } } indx = bfd_get_symcount (output_bfd); - ret = elf_link_output_sym (finfo, name, &osym, isec, NULL); + ret = elf_link_output_sym (flinfo, name, &osym, isec, NULL); if (ret == 0) return FALSE; else if (ret == 1) @@ -9312,7 +9516,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) continue; } - if (finfo->info->relocatable + if (flinfo->info->relocatable && (o->flags & (SEC_LINKER_CREATED | SEC_GROUP)) == SEC_GROUP) { /* Deal with the group signature symbol. */ @@ -9322,7 +9526,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) if (symndx >= locsymcount || (elf_bad_symtab (input_bfd) - && finfo->sections[symndx] == NULL)) + && flinfo->sections[symndx] == NULL)) { struct elf_link_hash_entry *h = sym_hashes[symndx - extsymoff]; while (h->root.type == bfd_link_hash_indirect @@ -9335,16 +9539,16 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) else if (ELF_ST_TYPE (isymbuf[symndx].st_info) == STT_SECTION) { /* We'll use the output section target_index. */ - asection *sec = finfo->sections[symndx]->output_section; + asection *sec = flinfo->sections[symndx]->output_section; elf_section_data (osec)->this_hdr.sh_info = sec->target_index; } else { - if (finfo->indices[symndx] == -1) + if (flinfo->indices[symndx] == -1) { /* Otherwise output the local symbol now. */ Elf_Internal_Sym sym = isymbuf[symndx]; - asection *sec = finfo->sections[symndx]->output_section; + asection *sec = flinfo->sections[symndx]->output_section; const char *name; long indx; int ret; @@ -9363,16 +9567,16 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) sym.st_value += o->output_offset; indx = bfd_get_symcount (output_bfd); - ret = elf_link_output_sym (finfo, name, &sym, o, NULL); + ret = elf_link_output_sym (flinfo, name, &sym, o, NULL); if (ret == 0) return FALSE; else if (ret == 1) - finfo->indices[symndx] = indx; + flinfo->indices[symndx] = indx; else abort (); } elf_section_data (osec)->this_hdr.sh_info - = finfo->indices[symndx]; + = flinfo->indices[symndx]; } } @@ -9395,7 +9599,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) contents = elf_section_data (o)->this_hdr.contents; else { - contents = finfo->contents; + contents = flinfo->contents; if (! bfd_get_full_section_contents (input_bfd, o, &contents)) return FALSE; } @@ -9409,8 +9613,8 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) /* Get the swapped relocs. */ internal_relocs - = _bfd_elf_link_read_relocs (input_bfd, o, finfo->external_relocs, - finfo->internal_relocs, FALSE); + = _bfd_elf_link_read_relocs (input_bfd, o, flinfo->external_relocs, + flinfo->internal_relocs, FALSE); if (internal_relocs == NULL && o->reloc_count > 0) return FALSE; @@ -9463,7 +9667,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) if (r_symndx >= locsymcount || (elf_bad_symtab (input_bfd) - && finfo->sections[r_symndx] == NULL)) + && flinfo->sections[r_symndx] == NULL)) { h = sym_hashes[r_symndx - extsymoff]; @@ -9501,13 +9705,13 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) Elf_Internal_Sym *sym = isymbuf + r_symndx; s_type = ELF_ST_TYPE (sym->st_info); - ps = &finfo->sections[r_symndx]; + ps = &flinfo->sections[r_symndx]; sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, *ps); } if ((s_type == STT_RELC || s_type == STT_SRELC) - && !finfo->info->relocatable) + && !flinfo->info->relocatable) { bfd_vma val; bfd_vma dot = (rel->r_offset @@ -9523,7 +9727,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) (unsigned long) rel->r_info, (unsigned long) rel->r_offset); #endif - if (!eval_symbol (&val, &sym_name, input_bfd, finfo, dot, + if (!eval_symbol (&val, &sym_name, input_bfd, flinfo, dot, isymbuf, locsymcount, s_type == STT_SRELC)) return FALSE; @@ -9537,11 +9741,11 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) { /* Complain if the definition comes from a discarded section. */ - if ((sec = *ps) != NULL && elf_discarded_section (sec)) + if ((sec = *ps) != NULL && discarded_section (sec)) { BFD_ASSERT (r_symndx != STN_UNDEF); if (action_discarded & COMPLAIN) - (*finfo->info->callbacks->einfo) + (*flinfo->info->callbacks->einfo) (_("%X`%s' referenced in section `%A' of %B: " "defined in discarded section `%A' of %B\n"), sym_name, o, input_bfd, sec, sec->owner); @@ -9557,7 +9761,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) asection *kept; kept = _bfd_elf_check_kept_section (sec, - finfo->info); + flinfo->info); if (kept != NULL) { *ps = kept; @@ -9588,17 +9792,17 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) corresponding to the output section, which will require the addend to be adjusted. */ - ret = (*relocate_section) (output_bfd, finfo->info, + ret = (*relocate_section) (output_bfd, flinfo->info, input_bfd, o, contents, internal_relocs, isymbuf, - finfo->sections); + flinfo->sections); if (!ret) return FALSE; if (ret == 2 - || finfo->info->relocatable - || finfo->info->emitrelocations) + || flinfo->info->relocatable + || flinfo->info->emitrelocations) { Elf_Internal_Rela *irela; Elf_Internal_Rela *irelaend, *irelamid; @@ -9628,7 +9832,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) rel_hash_list = rel_hash; rela_hash_list = NULL; last_offset = o->output_offset; - if (!finfo->info->relocatable) + if (!flinfo->info->relocatable) last_offset += o->output_section->vma; for (next_erel = 0; irela < irelaend; irela++, next_erel++) { @@ -9650,7 +9854,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) } irela->r_offset = _bfd_elf_section_offset (output_bfd, - finfo->info, o, + flinfo->info, o, irela->r_offset); if (irela->r_offset >= (bfd_vma) -2) { @@ -9668,7 +9872,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) irela->r_offset += o->output_offset; /* Relocs in an executable have to be virtual addresses. */ - if (!finfo->info->relocatable) + if (!flinfo->info->relocatable) irela->r_offset += o->output_section->vma; last_offset = irela->r_offset; @@ -9679,7 +9883,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) if (r_symndx >= locsymcount || (elf_bad_symtab (input_bfd) - && finfo->sections[r_symndx] == NULL)) + && flinfo->sections[r_symndx] == NULL)) { struct elf_link_hash_entry *rh; unsigned long indx; @@ -9712,7 +9916,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) *rel_hash = NULL; sym = isymbuf[r_symndx]; - sec = finfo->sections[r_symndx]; + sec = flinfo->sections[r_symndx]; if (ELF_ST_TYPE (sym.st_info) == STT_SECTION) { /* I suppose the backend ought to fill in the @@ -9749,23 +9953,12 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) r_symndx = osec->target_index; if (r_symndx == STN_UNDEF) { - struct elf_link_hash_table *htab; - asection *oi; - - htab = elf_hash_table (finfo->info); - oi = htab->text_index_section; - if ((osec->flags & SEC_READONLY) == 0 - && htab->data_index_section != NULL) - oi = htab->data_index_section; - - if (oi != NULL) - { - irela->r_addend += osec->vma - oi->vma; - r_symndx = oi->target_index; - } + irela->r_addend += osec->vma; + osec = _bfd_nearby_section (output_bfd, osec, + osec->vma); + irela->r_addend -= osec->vma; + r_symndx = osec->target_index; } - - BFD_ASSERT (r_symndx != STN_UNDEF); } } @@ -9776,14 +9969,14 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) } else { - if (finfo->indices[r_symndx] == -1) + if (flinfo->indices[r_symndx] == -1) { unsigned long shlink; const char *name; asection *osec; long indx; - if (finfo->info->strip == strip_all) + if (flinfo->info->strip == strip_all) { /* You can't do ld -r -s. */ bfd_set_error (bfd_error_invalid_operation); @@ -9807,32 +10000,32 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) return FALSE; sym.st_value += sec->output_offset; - if (! finfo->info->relocatable) + if (!flinfo->info->relocatable) { sym.st_value += osec->vma; if (ELF_ST_TYPE (sym.st_info) == STT_TLS) { /* STT_TLS symbols are relative to PT_TLS segment base. */ - BFD_ASSERT (elf_hash_table (finfo->info) + BFD_ASSERT (elf_hash_table (flinfo->info) ->tls_sec != NULL); - sym.st_value -= (elf_hash_table (finfo->info) + sym.st_value -= (elf_hash_table (flinfo->info) ->tls_sec->vma); } } indx = bfd_get_symcount (output_bfd); - ret = elf_link_output_sym (finfo, name, &sym, sec, + ret = elf_link_output_sym (flinfo, name, &sym, sec, NULL); if (ret == 0) return FALSE; else if (ret == 1) - finfo->indices[r_symndx] = indx; + flinfo->indices[r_symndx] = indx; else abort (); } - r_symndx = finfo->indices[r_symndx]; + r_symndx = flinfo->indices[r_symndx]; } irela->r_info = ((bfd_vma) r_symndx << r_sym_shift @@ -9867,28 +10060,28 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) /* Write out the modified section contents. */ if (bed->elf_backend_write_section - && (*bed->elf_backend_write_section) (output_bfd, finfo->info, o, + && (*bed->elf_backend_write_section) (output_bfd, flinfo->info, o, contents)) { /* Section written out. */ } else switch (o->sec_info_type) { - case ELF_INFO_TYPE_STABS: + case SEC_INFO_TYPE_STABS: if (! (_bfd_write_section_stabs (output_bfd, - &elf_hash_table (finfo->info)->stab_info, + &elf_hash_table (flinfo->info)->stab_info, o, &elf_section_data (o)->sec_info, contents))) return FALSE; break; - case ELF_INFO_TYPE_MERGE: + case SEC_INFO_TYPE_MERGE: if (! _bfd_write_merged_section (output_bfd, o, elf_section_data (o)->sec_info)) return FALSE; break; - case ELF_INFO_TYPE_EH_FRAME: + case SEC_INFO_TYPE_EH_FRAME: { - if (! _bfd_elf_write_section_eh_frame (output_bfd, finfo->info, + if (! _bfd_elf_write_section_eh_frame (output_bfd, flinfo->info, o, contents)) return FALSE; } @@ -10265,7 +10458,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) bfd_boolean dynamic; bfd_boolean emit_relocs; bfd *dynobj; - struct elf_final_link_info finfo; + struct elf_final_link_info flinfo; asection *o; struct bfd_link_order *p; bfd *sub; @@ -10302,39 +10495,40 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) emit_relocs = (info->relocatable || info->emitrelocations); - finfo.info = info; - finfo.output_bfd = abfd; - finfo.symstrtab = _bfd_elf_stringtab_init (); - if (finfo.symstrtab == NULL) + flinfo.info = info; + flinfo.output_bfd = abfd; + flinfo.symstrtab = _bfd_elf_stringtab_init (); + if (flinfo.symstrtab == NULL) return FALSE; if (! dynamic) { - finfo.dynsym_sec = NULL; - finfo.hash_sec = NULL; - finfo.symver_sec = NULL; + flinfo.dynsym_sec = NULL; + flinfo.hash_sec = NULL; + flinfo.symver_sec = NULL; } else { - finfo.dynsym_sec = bfd_get_section_by_name (dynobj, ".dynsym"); - finfo.hash_sec = bfd_get_section_by_name (dynobj, ".hash"); - BFD_ASSERT (finfo.dynsym_sec != NULL); - finfo.symver_sec = bfd_get_section_by_name (dynobj, ".gnu.version"); + flinfo.dynsym_sec = bfd_get_linker_section (dynobj, ".dynsym"); + flinfo.hash_sec = bfd_get_linker_section (dynobj, ".hash"); + /* Note that dynsym_sec can be NULL (on VMS). */ + flinfo.symver_sec = bfd_get_linker_section (dynobj, ".gnu.version"); /* Note that it is OK if symver_sec is NULL. */ } - finfo.contents = NULL; - finfo.external_relocs = NULL; - finfo.internal_relocs = NULL; - finfo.external_syms = NULL; - finfo.locsym_shndx = NULL; - finfo.internal_syms = NULL; - finfo.indices = NULL; - finfo.sections = NULL; - finfo.symbuf = NULL; - finfo.symshndxbuf = NULL; - finfo.symbuf_count = 0; - finfo.shndxbuf_size = 0; + flinfo.contents = NULL; + flinfo.external_relocs = NULL; + flinfo.internal_relocs = NULL; + flinfo.external_syms = NULL; + flinfo.locsym_shndx = NULL; + flinfo.internal_syms = NULL; + flinfo.indices = NULL; + flinfo.sections = NULL; + flinfo.symbuf = NULL; + flinfo.symshndxbuf = NULL; + flinfo.symbuf_count = 0; + flinfo.shndxbuf_size = 0; + flinfo.filesym_count = 0; /* The object attributes have been merged. Remove the input sections from the link, and set the contents of the output @@ -10408,7 +10602,13 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (sec->flags & SEC_MERGE) merged = TRUE; - if (info->relocatable || info->emitrelocations) + if (esdo->this_hdr.sh_type == SHT_REL + || esdo->this_hdr.sh_type == SHT_RELA) + /* Some backends use reloc_count in relocation sections + to count particular types of relocs. Of course, + reloc sections themselves can't have relocations. */ + reloc_count = 0; + else if (info->relocatable || info->emitrelocations) reloc_count = sec->reloc_count; else if (bed->elf_backend_count_relocs) reloc_count = (*bed->elf_backend_count_relocs) (info, sec); @@ -10556,22 +10756,22 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* Allocate a buffer to hold swapped out symbols. This is to avoid continuously seeking to the right position in the file. */ if (! info->keep_memory || max_sym_count < 20) - finfo.symbuf_size = 20; + flinfo.symbuf_size = 20; else - finfo.symbuf_size = max_sym_count; - amt = finfo.symbuf_size; + flinfo.symbuf_size = max_sym_count; + amt = flinfo.symbuf_size; amt *= bed->s->sizeof_sym; - finfo.symbuf = (bfd_byte *) bfd_malloc (amt); - if (finfo.symbuf == NULL) + flinfo.symbuf = (bfd_byte *) bfd_malloc (amt); + if (flinfo.symbuf == NULL) goto error_return; if (elf_numsections (abfd) > (SHN_LORESERVE & 0xFFFF)) { /* Wild guess at number of output symbols. realloc'd as needed. */ amt = 2 * max_sym_count + elf_numsections (abfd) + 1000; - finfo.shndxbuf_size = amt; + flinfo.shndxbuf_size = amt; amt *= sizeof (Elf_External_Sym_Shndx); - finfo.symshndxbuf = (Elf_External_Sym_Shndx *) bfd_zmalloc (amt); - if (finfo.symshndxbuf == NULL) + flinfo.symshndxbuf = (Elf_External_Sym_Shndx *) bfd_zmalloc (amt); + if (flinfo.symshndxbuf == NULL) goto error_return; } @@ -10586,7 +10786,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) elfsym.st_other = 0; elfsym.st_shndx = SHN_UNDEF; elfsym.st_target_internal = 0; - if (elf_link_output_sym (&finfo, NULL, &elfsym, bfd_und_section_ptr, + if (elf_link_output_sym (&flinfo, NULL, &elfsym, bfd_und_section_ptr, NULL) != 1) goto error_return; } @@ -10613,7 +10813,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) elfsym.st_shndx = i; if (!info->relocatable) elfsym.st_value = o->vma; - if (elf_link_output_sym (&finfo, NULL, &elfsym, o, NULL) != 1) + if (elf_link_output_sym (&flinfo, NULL, &elfsym, o, NULL) != 1) goto error_return; } } @@ -10623,15 +10823,15 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) files. */ if (max_contents_size != 0) { - finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size); - if (finfo.contents == NULL) + flinfo.contents = (bfd_byte *) bfd_malloc (max_contents_size); + if (flinfo.contents == NULL) goto error_return; } if (max_external_reloc_size != 0) { - finfo.external_relocs = bfd_malloc (max_external_reloc_size); - if (finfo.external_relocs == NULL) + flinfo.external_relocs = bfd_malloc (max_external_reloc_size); + if (flinfo.external_relocs == NULL) goto error_return; } @@ -10639,39 +10839,39 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) { amt = max_internal_reloc_count * bed->s->int_rels_per_ext_rel; amt *= sizeof (Elf_Internal_Rela); - finfo.internal_relocs = (Elf_Internal_Rela *) bfd_malloc (amt); - if (finfo.internal_relocs == NULL) + flinfo.internal_relocs = (Elf_Internal_Rela *) bfd_malloc (amt); + if (flinfo.internal_relocs == NULL) goto error_return; } if (max_sym_count != 0) { amt = max_sym_count * bed->s->sizeof_sym; - finfo.external_syms = (bfd_byte *) bfd_malloc (amt); - if (finfo.external_syms == NULL) + flinfo.external_syms = (bfd_byte *) bfd_malloc (amt); + if (flinfo.external_syms == NULL) goto error_return; amt = max_sym_count * sizeof (Elf_Internal_Sym); - finfo.internal_syms = (Elf_Internal_Sym *) bfd_malloc (amt); - if (finfo.internal_syms == NULL) + flinfo.internal_syms = (Elf_Internal_Sym *) bfd_malloc (amt); + if (flinfo.internal_syms == NULL) goto error_return; amt = max_sym_count * sizeof (long); - finfo.indices = (long int *) bfd_malloc (amt); - if (finfo.indices == NULL) + flinfo.indices = (long int *) bfd_malloc (amt); + if (flinfo.indices == NULL) goto error_return; amt = max_sym_count * sizeof (asection *); - finfo.sections = (asection **) bfd_malloc (amt); - if (finfo.sections == NULL) + flinfo.sections = (asection **) bfd_malloc (amt); + if (flinfo.sections == NULL) goto error_return; } if (max_sym_shndx_count != 0) { amt = max_sym_shndx_count * sizeof (Elf_External_Sym_Shndx); - finfo.locsym_shndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (finfo.locsym_shndx == NULL) + flinfo.locsym_shndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt); + if (flinfo.locsym_shndx == NULL) goto error_return; } @@ -10745,7 +10945,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) { if (! sub->output_has_begun) { - if (! elf_link_input_bfd (&finfo, sub)) + if (! elf_link_input_bfd (&flinfo, sub)) goto error_return; sub->output_has_begun = TRUE; } @@ -10803,6 +11003,17 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) } } + /* Output a FILE symbol so that following locals are not associated + with the wrong input file. */ + memset (&elfsym, 0, sizeof (elfsym)); + elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE); + elfsym.st_shndx = SHN_ABS; + + if (flinfo.filesym_count > 1 + && !elf_link_output_sym (&flinfo, NULL, &elfsym, + bfd_und_section_ptr, NULL)) + return FALSE; + /* Output any global symbols that got converted to local in a version script or due to symbol visibility. We do this in a separate step since ELF requires all local symbols to appear @@ -10810,12 +11021,27 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) some global symbols were, in fact, converted to become local. FIXME: Will this work correctly with the Irix 5 linker? */ eoinfo.failed = FALSE; - eoinfo.finfo = &finfo; + eoinfo.flinfo = &flinfo; eoinfo.localsyms = TRUE; + eoinfo.need_second_pass = FALSE; + eoinfo.second_pass = FALSE; bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo); if (eoinfo.failed) return FALSE; + if (flinfo.filesym_count == 1 + && !elf_link_output_sym (&flinfo, NULL, &elfsym, + bfd_und_section_ptr, NULL)) + return FALSE; + + if (eoinfo.need_second_pass) + { + eoinfo.second_pass = TRUE; + bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo); + if (eoinfo.failed) + return FALSE; + } + /* If backend needs to output some local symbols not present in the hash table, do it now. */ if (bed->elf_backend_output_arch_local_syms) @@ -10825,7 +11051,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) struct elf_link_hash_entry *); if (! ((*bed->elf_backend_output_arch_local_syms) - (abfd, info, &finfo, (out_sym_func) elf_link_output_sym))) + (abfd, info, &flinfo, (out_sym_func) elf_link_output_sym))) return FALSE; } @@ -10838,10 +11064,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) symtab_hdr->sh_info = bfd_get_symcount (abfd); if (dynamic - && finfo.dynsym_sec->output_section != bfd_abs_section_ptr) + && flinfo.dynsym_sec != NULL + && flinfo.dynsym_sec->output_section != bfd_abs_section_ptr) { Elf_Internal_Sym sym; - bfd_byte *dynsym = finfo.dynsym_sec->contents; + bfd_byte *dynsym = flinfo.dynsym_sec->contents; long last_local = 0; /* Write out the section symbols for the output sections. */ @@ -10913,14 +11140,14 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) } } - elf_section_data (finfo.dynsym_sec->output_section)->this_hdr.sh_info = + elf_section_data (flinfo.dynsym_sec->output_section)->this_hdr.sh_info = last_local + 1; } /* We get the global symbols from the hash table. */ eoinfo.failed = FALSE; eoinfo.localsyms = FALSE; - eoinfo.finfo = &finfo; + eoinfo.flinfo = &flinfo; bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo); if (eoinfo.failed) return FALSE; @@ -10934,12 +11161,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) struct elf_link_hash_entry *); if (! ((*bed->elf_backend_output_arch_syms) - (abfd, info, &finfo, (out_sym_func) elf_link_output_sym))) + (abfd, info, &flinfo, (out_sym_func) elf_link_output_sym))) return FALSE; } /* Flush all symbols to the file. */ - if (! elf_link_flush_output_syms (&finfo, bed)) + if (! elf_link_flush_output_syms (&flinfo, bed)) return FALSE; /* Now we know the size of the symtab section. */ @@ -10958,7 +11185,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) off, TRUE); if (bfd_seek (abfd, symtab_shndx_hdr->sh_offset, SEEK_SET) != 0 - || (bfd_bwrite (finfo.symshndxbuf, amt, abfd) != amt)) + || (bfd_bwrite (flinfo.symshndxbuf, amt, abfd) != amt)) return FALSE; } @@ -10970,7 +11197,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) symstrtab_hdr->sh_type = SHT_STRTAB; symstrtab_hdr->sh_flags = 0; symstrtab_hdr->sh_addr = 0; - symstrtab_hdr->sh_size = _bfd_stringtab_size (finfo.symstrtab); + symstrtab_hdr->sh_size = _bfd_stringtab_size (flinfo.symstrtab); symstrtab_hdr->sh_entsize = 0; symstrtab_hdr->sh_link = 0; symstrtab_hdr->sh_info = 0; @@ -10983,7 +11210,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (bfd_get_symcount (abfd) > 0) { if (bfd_seek (abfd, symstrtab_hdr->sh_offset, SEEK_SET) != 0 - || ! _bfd_stringtab_emit (abfd, finfo.symstrtab)) + || ! _bfd_stringtab_emit (abfd, flinfo.symstrtab)) return FALSE; } @@ -11014,7 +11241,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) bfd_byte *dyncon, *dynconend; /* Fix up .dynamic entries. */ - o = bfd_get_section_by_name (dynobj, ".dynamic"); + o = bfd_get_linker_section (dynobj, ".dynamic"); BFD_ASSERT (o != NULL); dyncon = o->contents; @@ -11190,7 +11417,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) /* Check for DT_TEXTREL (late, in case the backend removes it). */ if (((info->warn_shared_textrel && info->shared) || info->error_textrel) - && (o = bfd_get_section_by_name (dynobj, ".dynamic")) != NULL) + && (o = bfd_get_linker_section (dynobj, ".dynamic")) != NULL) { bfd_byte *dyncon, *dynconend; @@ -11231,9 +11458,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) continue; if (elf_hash_table (info)->eh_info.hdr_sec == o) continue; - if ((elf_section_data (o->output_section)->this_hdr.sh_type - != SHT_STRTAB) - && (strcmp (bfd_get_section_name (abfd, o), ".dynstr") != 0)) + if (strcmp (o->name, ".dynstr") != 0) { /* FIXME: octets_per_byte. */ if (! bfd_set_section_contents (abfd, o->output_section, @@ -11277,28 +11502,28 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) goto error_return; } - if (finfo.symstrtab != NULL) - _bfd_stringtab_free (finfo.symstrtab); - if (finfo.contents != NULL) - free (finfo.contents); - if (finfo.external_relocs != NULL) - free (finfo.external_relocs); - if (finfo.internal_relocs != NULL) - free (finfo.internal_relocs); - if (finfo.external_syms != NULL) - free (finfo.external_syms); - if (finfo.locsym_shndx != NULL) - free (finfo.locsym_shndx); - if (finfo.internal_syms != NULL) - free (finfo.internal_syms); - if (finfo.indices != NULL) - free (finfo.indices); - if (finfo.sections != NULL) - free (finfo.sections); - if (finfo.symbuf != NULL) - free (finfo.symbuf); - if (finfo.symshndxbuf != NULL) - free (finfo.symshndxbuf); + if (flinfo.symstrtab != NULL) + _bfd_stringtab_free (flinfo.symstrtab); + if (flinfo.contents != NULL) + free (flinfo.contents); + if (flinfo.external_relocs != NULL) + free (flinfo.external_relocs); + if (flinfo.internal_relocs != NULL) + free (flinfo.internal_relocs); + if (flinfo.external_syms != NULL) + free (flinfo.external_syms); + if (flinfo.locsym_shndx != NULL) + free (flinfo.locsym_shndx); + if (flinfo.internal_syms != NULL) + free (flinfo.internal_syms); + if (flinfo.indices != NULL) + free (flinfo.indices); + if (flinfo.sections != NULL) + free (flinfo.sections); + if (flinfo.symbuf != NULL) + free (flinfo.symbuf); + if (flinfo.symshndxbuf != NULL) + free (flinfo.symshndxbuf); for (o = abfd->sections; o != NULL; o = o->next) { struct bfd_elf_section_data *esdo = elf_section_data (o); @@ -11323,28 +11548,28 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) return TRUE; error_return: - if (finfo.symstrtab != NULL) - _bfd_stringtab_free (finfo.symstrtab); - if (finfo.contents != NULL) - free (finfo.contents); - if (finfo.external_relocs != NULL) - free (finfo.external_relocs); - if (finfo.internal_relocs != NULL) - free (finfo.internal_relocs); - if (finfo.external_syms != NULL) - free (finfo.external_syms); - if (finfo.locsym_shndx != NULL) - free (finfo.locsym_shndx); - if (finfo.internal_syms != NULL) - free (finfo.internal_syms); - if (finfo.indices != NULL) - free (finfo.indices); - if (finfo.sections != NULL) - free (finfo.sections); - if (finfo.symbuf != NULL) - free (finfo.symbuf); - if (finfo.symshndxbuf != NULL) - free (finfo.symshndxbuf); + if (flinfo.symstrtab != NULL) + _bfd_stringtab_free (flinfo.symstrtab); + if (flinfo.contents != NULL) + free (flinfo.contents); + if (flinfo.external_relocs != NULL) + free (flinfo.external_relocs); + if (flinfo.internal_relocs != NULL) + free (flinfo.internal_relocs); + if (flinfo.external_syms != NULL) + free (flinfo.external_syms); + if (flinfo.locsym_shndx != NULL) + free (flinfo.locsym_shndx); + if (flinfo.internal_syms != NULL) + free (flinfo.internal_syms); + if (flinfo.indices != NULL) + free (flinfo.indices); + if (flinfo.sections != NULL) + free (flinfo.sections); + if (flinfo.symbuf != NULL) + free (flinfo.symbuf); + if (flinfo.symshndxbuf != NULL) + free (flinfo.symshndxbuf); for (o = abfd->sections; o != NULL; o = o->next) { struct bfd_elf_section_data *esdo = elf_section_data (o); @@ -11575,6 +11800,12 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec, || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; h->mark = 1; + /* If this symbol is weak and there is a non-weak definition, we + keep the non-weak definition because many backends put + dynamic reloc info on the non-weak definition for code + handling copy relocs. */ + if (h->u.weakdef != NULL) + h->u.weakdef->mark = 1; return (*gc_mark_hook) (sec, info, cookie->rel, h, NULL); } @@ -11597,7 +11828,8 @@ _bfd_elf_gc_mark_reloc (struct bfd_link_info *info, rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie); if (rsec && !rsec->gc_mark) { - if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour) + if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour + || (rsec->owner->flags & DYNAMIC) != 0) rsec->gc_mark = 1; else if (!_bfd_elf_gc_mark (info, rsec, gc_mark_hook)) return FALSE; @@ -12008,12 +12240,14 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info) struct elf_reloc_cookie cookie; sec = bfd_get_section_by_name (sub, ".eh_frame"); - if (sec && init_reloc_cookie_for_section (&cookie, info, sec)) + while (sec && init_reloc_cookie_for_section (&cookie, info, sec)) { _bfd_elf_parse_eh_frame (sub, info, sec, &cookie); - if (elf_section_data (sec)->sec_info) + if (elf_section_data (sec)->sec_info + && (sec->flags & SEC_LINKER_CREATED) == 0) elf_eh_frame_section (sub) = sec; fini_reloc_cookie_for_section (&cookie, sec); + sec = bfd_get_next_section_by_name (sec); } } _bfd_elf_end_eh_frame_parsing (info); @@ -12229,58 +12463,73 @@ static elf_flags_to_name_table elf_flags_to_names [] = { "SHF_EXCLUDE", SHF_EXCLUDE }, }; -void +/* Returns TRUE if the section is to be included, otherwise FALSE. */ +bfd_boolean bfd_elf_lookup_section_flags (struct bfd_link_info *info, - struct flag_info *finfo) + struct flag_info *flaginfo, + asection *section) { - bfd *output_bfd = info->output_bfd; - const struct elf_backend_data *bed = get_elf_backend_data (output_bfd); - struct flag_info_list *tf = finfo->flag_list; - int with_hex = 0; - int without_hex = 0; + const bfd_vma sh_flags = elf_section_flags (section); - for (tf = finfo->flag_list; tf != NULL; tf = tf->next) + if (!flaginfo->flags_initialized) { - int i; - if (bed->elf_backend_lookup_section_flags_hook) + bfd *obfd = info->output_bfd; + const struct elf_backend_data *bed = get_elf_backend_data (obfd); + struct flag_info_list *tf = flaginfo->flag_list; + int with_hex = 0; + int without_hex = 0; + + for (tf = flaginfo->flag_list; tf != NULL; tf = tf->next) { - flagword hexval = - (*bed->elf_backend_lookup_section_flags_hook) ((char *) tf->name); + unsigned i; + flagword (*lookup) (char *); - if (hexval != 0) + lookup = bed->elf_backend_lookup_section_flags_hook; + if (lookup != NULL) { - if (tf->with == with_flags) - with_hex |= hexval; - else if (tf->with == without_flags) - without_hex |= hexval; - tf->valid = TRUE; - continue; + flagword hexval = (*lookup) ((char *) tf->name); + + if (hexval != 0) + { + if (tf->with == with_flags) + with_hex |= hexval; + else if (tf->with == without_flags) + without_hex |= hexval; + tf->valid = TRUE; + continue; + } } - } - for (i = 0; i < 12; i++) - { - if (!strcmp (tf->name, elf_flags_to_names[i].flag_name)) + for (i = 0; i < ARRAY_SIZE (elf_flags_to_names); ++i) { - if (tf->with == with_flags) - with_hex |= elf_flags_to_names[i].flag_value; - else if (tf->with == without_flags) - without_hex |= elf_flags_to_names[i].flag_value; - tf->valid = TRUE; - continue; + if (strcmp (tf->name, elf_flags_to_names[i].flag_name) == 0) + { + if (tf->with == with_flags) + with_hex |= elf_flags_to_names[i].flag_value; + else if (tf->with == without_flags) + without_hex |= elf_flags_to_names[i].flag_value; + tf->valid = TRUE; + break; + } } - } - if (tf->valid == FALSE) - { - info->callbacks->einfo + if (!tf->valid) + { + info->callbacks->einfo (_("Unrecognized INPUT_SECTION_FLAG %s\n"), tf->name); - return; + return FALSE; + } } + flaginfo->flags_initialized = TRUE; + flaginfo->only_with_flags |= with_hex; + flaginfo->not_with_flags |= without_hex; } - finfo->flags_initialized = TRUE; - finfo->only_with_flags |= with_hex; - finfo->not_with_flags |= without_hex; - return; + if ((flaginfo->only_with_flags & sh_flags) != flaginfo->only_with_flags) + return FALSE; + + if ((flaginfo->not_with_flags & sh_flags) != 0) + return FALSE; + + return TRUE; } struct alloc_got_off_arg { @@ -12423,7 +12672,7 @@ bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie) if ((h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) - && elf_discarded_section (h->root.u.def.section)) + && discarded_section (h->root.u.def.section)) return TRUE; else return FALSE; @@ -12439,7 +12688,7 @@ bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie) /* Need to: get the symbol; get the section. */ isym = &rcookie->locsyms[r_symndx]; isec = bfd_section_from_elf_index (rcookie->abfd, isym->st_shndx); - if (isec != NULL && elf_discarded_section (isec)) + if (isec != NULL && discarded_section (isec)) return TRUE; } return FALSE; @@ -12473,24 +12722,21 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) bed = get_elf_backend_data (abfd); - if ((abfd->flags & DYNAMIC) != 0) - continue; - eh = NULL; if (!info->relocatable) { eh = bfd_get_section_by_name (abfd, ".eh_frame"); - if (eh != NULL - && (eh->size == 0 - || bfd_is_abs_section (eh->output_section))) - eh = NULL; + while (eh != NULL + && (eh->size == 0 + || bfd_is_abs_section (eh->output_section))) + eh = bfd_get_next_section_by_name (eh); } stab = bfd_get_section_by_name (abfd, ".stab"); if (stab != NULL && (stab->size == 0 || bfd_is_abs_section (stab->output_section) - || stab->sec_info_type != ELF_INFO_TYPE_STABS)) + || stab->sec_info_type != SEC_INFO_TYPE_STABS)) stab = NULL; if (stab == NULL @@ -12513,8 +12759,8 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) fini_reloc_cookie_rels (&cookie, stab); } - if (eh != NULL - && init_reloc_cookie_rels (&cookie, info, abfd, eh)) + while (eh != NULL + && init_reloc_cookie_rels (&cookie, info, abfd, eh)) { _bfd_elf_parse_eh_frame (abfd, info, eh, &cookie); if (_bfd_elf_discard_section_eh_frame (abfd, info, eh, @@ -12522,6 +12768,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) &cookie)) ret = TRUE; fini_reloc_cookie_rels (&cookie, eh); + eh = bfd_get_next_section_by_name (eh); } if (bed->elf_backend_discard_info != NULL @@ -12757,7 +13004,7 @@ _bfd_elf_get_dynamic_reloc_section (bfd * abfd, if (name != NULL) { - reloc_sec = bfd_get_section_by_name (abfd, name); + reloc_sec = bfd_get_linker_section (abfd, name); if (reloc_sec != NULL) elf_section_data (sec)->sreloc = reloc_sec; @@ -12793,17 +13040,16 @@ _bfd_elf_make_dynamic_reloc_section (asection * sec, if (name == NULL) return NULL; - reloc_sec = bfd_get_section_by_name (dynobj, name); + reloc_sec = bfd_get_linker_section (dynobj, name); if (reloc_sec == NULL) { - flagword flags; - - flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_IN_MEMORY | SEC_LINKER_CREATED); + flagword flags = (SEC_HAS_CONTENTS | SEC_READONLY + | SEC_IN_MEMORY | SEC_LINKER_CREATED); if ((sec->flags & SEC_ALLOC) != 0) flags |= SEC_ALLOC | SEC_LOAD; - reloc_sec = bfd_make_section_with_flags (dynobj, name, flags); + reloc_sec = bfd_make_section_anyway_with_flags (dynobj, name, flags); if (reloc_sec != NULL) { if (! bfd_set_section_alignment (dynobj, reloc_sec, alignment)) @@ -12849,5 +13095,5 @@ elf_append_rel (bfd *abfd, asection *s, Elf_Internal_Rela *rel) const struct elf_backend_data *bed = get_elf_backend_data (abfd); bfd_byte *loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rel); BFD_ASSERT (loc + bed->s->sizeof_rel <= s->contents + s->size); - bed->s->swap_reloca_out (abfd, rel, loc); + bed->s->swap_reloc_out (abfd, rel, loc); }