X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felflink.c;h=a9d95bd1b0a7c0bef7956d632f90d06a98c63fae;hb=ffbc01ccf0e0c923db2ffa3a6b3ca6b4f6d08ac5;hp=3614575d23dbecbdaaa7f7ed46843849c1c7d415;hpb=8b127cbcc36cb65ef13eb756d02fe84aa120effb;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elflink.c b/bfd/elflink.c index 3614575d23..a9d95bd1b0 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -1216,15 +1216,15 @@ _bfd_elf_merge_symbol (bfd *abfd, h = *sym_hash; } - if ((h->root.u.undef.next || info->hash->undefs_tail == &h->root) - && bfd_is_und_section (sec)) - { - /* 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. */ + /* 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) + { h->root.type = bfd_link_hash_undefined; h->root.u.undef.abfd = abfd; } @@ -1234,11 +1234,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; @@ -5584,17 +5591,9 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, && ! (*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; @@ -5897,11 +5896,15 @@ 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; @@ -7400,6 +7403,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. */ @@ -7408,6 +7413,8 @@ struct elf_outext_info { bfd_boolean failed; bfd_boolean localsyms; + bfd_boolean need_second_pass; + bfd_boolean second_pass; struct elf_final_link_info *flinfo; }; @@ -8602,6 +8609,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 { @@ -8756,6 +8768,19 @@ 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 (flinfo->output_bfd, input_sec->output_section); @@ -9108,6 +9133,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, 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 = flinfo->output_bfd; bed = get_elf_backend_data (output_bfd); @@ -9243,6 +9269,29 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) && 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. */ @@ -10315,6 +10364,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) 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 @@ -10789,6 +10839,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 @@ -10798,10 +10859,25 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) eoinfo.failed = FALSE; 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) @@ -12002,12 +12078,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); @@ -12482,17 +12560,14 @@ 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"); @@ -12522,8 +12597,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, @@ -12531,6 +12606,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