diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 495ea9547c..64d98178e1 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,35 @@ +2005-07-25 H.J. Lu + + * elf-bfd.h (elf_backend_data): Add common_definition, + common_section_index, common_section, and merge_symbol. + (_bfd_elf_common_definition): New. + (_bfd_elf_common_section_index): New. + (_bfd_elf_common_section): New. + + * elf.c (elf_fake_sections): Don't clear sh_flags. + + * elflink.c (_bfd_elf_merge_symbol): Call backend merge_symbol + if it is available. + (is_global_data_symbol_definition): Call backend + common_definition instead of checking SHN_COMMON. + (elf_link_add_object_symbols): Likewise. + (elf_link_output_extsym): Call backend common_section_index + for common section index. + (_bfd_elf_common_definition): New. + (_bfd_elf_common_section_index): New. + (_bfd_elf_common_section): New. + + * elfxx-target.h (elf_backend_common_definition): New. + (elf_backend_common_section_index): New. + (elf_backend_common_section): New. + (elf_backend_merge_symbol): New. + (elfNN_bed): Initialize common_definition, common_section_index, + common_section, and merge_symbol. + + * section.c (BFD_FAKE_SECTION): New. + (STD_SECTION): Use it. + * bfd-in2.h: Regenerated. + 2005-07-23 Olaf Hering * elflink.c (elf_link_input_bfd): Add '\n' for linker einfo diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index c9c75c2b8f..7dbfe95cb6 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -1551,6 +1551,47 @@ extern const struct bfd_symbol * const bfd_ind_symbol; #define bfd_section_removed_from_list(ABFD, S) \ ((S)->next == NULL ? (ABFD)->section_last != (S) : (S)->next->prev != (S)) +#define BFD_FAKE_SECTION(SEC, FLAGS, SYM, SYM_PTR, NAME, IDX) \ + /* name, id, index, next, prev, flags, user_set_vma, */ \ + { NAME, IDX, 0, NULL, NULL, FLAGS, 0, \ + \ + /* linker_mark, linker_has_input, gc_mark, gc_mark_from_eh, */ \ + 0, 0, 1, 0, \ + \ + /* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, */ \ + 0, 0, 0, 0, \ + \ + /* has_gp_reloc, need_finalize_relax, reloc_done, */ \ + 0, 0, 0, \ + \ + /* vma, lma, size, rawsize */ \ + 0, 0, 0, 0, \ + \ + /* output_offset, output_section, alignment_power, */ \ + 0, (struct bfd_section *) &SEC, 0, \ + \ + /* relocation, orelocation, reloc_count, filepos, rel_filepos, */ \ + NULL, NULL, 0, 0, 0, \ + \ + /* line_filepos, userdata, contents, lineno, lineno_count, */ \ + 0, NULL, NULL, NULL, 0, \ + \ + /* entsize, kept_section, moving_line_filepos, */ \ + 0, NULL, 0, \ + \ + /* target_index, used_by_bfd, constructor_chain, owner, */ \ + 0, NULL, NULL, NULL, \ + \ + /* symbol, */ \ + (struct bfd_symbol *) SYM, \ + \ + /* symbol_ptr_ptr, */ \ + (struct bfd_symbol **) SYM_PTR, \ + \ + /* map_head, map_tail */ \ + { NULL }, { NULL } \ + } + void bfd_section_list_clear (bfd *); asection *bfd_get_section_by_name (bfd *abfd, const char *name); diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 2bbc1c923d..f7bab5ca82 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -969,6 +969,30 @@ struct elf_backend_data see elf.c. */ bfd_vma (*plt_sym_val) (bfd_vma, const asection *, const arelent *); + /* Is symbol defined in common section? */ + bfd_boolean (*common_definition) (Elf_Internal_Sym *); + + /* Return a common section index for section. */ + unsigned int (*common_section_index) (asection *); + + /* Return a common section for section. */ + asection *(*common_section) (asection *); + + /* Return TRUE if we can merge 2 definitions. */ + bfd_boolean (*merge_symbol) (struct bfd_link_info *, + struct elf_link_hash_entry **, + struct elf_link_hash_entry *, + Elf_Internal_Sym *, asection **, + bfd_vma *, unsigned int *, + bfd_boolean *, bfd_boolean *, + bfd_boolean *, bfd_boolean *, + bfd_boolean *, bfd_boolean *, + bfd_boolean *, bfd_boolean *, + bfd *, asection **, + bfd_boolean *, bfd_boolean *, + bfd_boolean *, bfd_boolean *, + bfd *, asection **); + /* Used to handle bad SHF_LINK_ORDER input. */ bfd_error_handler_type link_order_error_handler; @@ -1741,6 +1765,15 @@ extern int bfd_elf_link_record_local_dynamic_symbol extern bfd_boolean _bfd_elf_close_and_cleanup (bfd *); +extern bfd_boolean _bfd_elf_common_definition + (Elf_Internal_Sym *); + +extern unsigned int _bfd_elf_common_section_index + (asection *); + +extern asection *_bfd_elf_common_section + (asection *); + extern void _bfd_dwarf2_cleanup_debug_info (bfd *); diff --git a/bfd/elf.c b/bfd/elf.c index ff46a5e2ea..3e47b021aa 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -2618,7 +2618,7 @@ elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg) return; } - this_hdr->sh_flags = 0; + /* Don't clear sh_flags. Assembler may set additional bits. */ if ((asect->flags & SEC_ALLOC) != 0 || asect->user_set_vma) diff --git a/bfd/elflink.c b/bfd/elflink.c index 901b528065..f52d3070ca 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -780,6 +780,7 @@ _bfd_elf_merge_symbol (bfd *abfd, bfd *oldbfd; bfd_boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon; bfd_boolean newweak, oldweak; + const struct elf_backend_data *bed; *skip = FALSE; *override = FALSE; @@ -1121,6 +1122,19 @@ _bfd_elf_merge_symbol (bfd *abfd, else olddyncommon = FALSE; + /* We now know everything about the old and new symbols. We ask the + backend to check if we can merge them. */ + bed = get_elf_backend_data (abfd); + if (bed->merge_symbol + && !bed->merge_symbol (info, sym_hash, h, sym, psec, pvalue, + pold_alignment, skip, override, + type_change_ok, size_change_ok, + &newdyn, &newdef, &newdyncommon, &newweak, + abfd, &sec, + &olddyn, &olddef, &olddyncommon, &oldweak, + oldbfd, &oldsec)) + return FALSE; + /* If both the old and the new symbols look like common symbols in a dynamic object, set the size of the symbol to the larger of the two. */ @@ -1197,7 +1211,7 @@ _bfd_elf_merge_symbol (bfd *abfd, newdef = FALSE; newdyncommon = FALSE; *pvalue = sym->st_size; - *psec = sec = bfd_com_section_ptr; + *psec = sec = bed->common_section (oldsec); *size_change_ok = TRUE; } @@ -2641,6 +2655,8 @@ static bfd_boolean is_global_data_symbol_definition (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Sym *sym) { + const struct elf_backend_data *bed; + /* Local symbols do not count, but target specific ones might. */ if (ELF_ST_BIND (sym->st_info) != STB_GLOBAL && ELF_ST_BIND (sym->st_info) < STB_LOOS) @@ -2656,7 +2672,8 @@ is_global_data_symbol_definition (bfd *abfd ATTRIBUTE_UNUSED, /* If the symbol is defined in the common section, then it is a common definition and so does not count. */ - if (sym->st_shndx == SHN_COMMON) + bed = get_elf_backend_data (abfd); + if (bed->common_definition (sym)) return FALSE; /* If the symbol is in a target specific section then we @@ -3548,6 +3565,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) bfd_boolean type_change_ok; bfd_boolean new_weakdef; bfd_boolean override; + bfd_boolean common; unsigned int old_alignment; bfd *old_bfd; @@ -3557,6 +3575,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) sec = NULL; value = isym->st_value; *sym_hash = NULL; + common = bed->common_definition (isym); bind = ELF_ST_BIND (isym->st_info); if (bind == STB_LOCAL) @@ -3569,8 +3588,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) } else if (bind == STB_GLOBAL) { - if (isym->st_shndx != SHN_UNDEF - && isym->st_shndx != SHN_COMMON) + if (isym->st_shndx != SHN_UNDEF && !common) flags = BSF_GLOBAL; } else if (bind == STB_WEAK) @@ -3861,13 +3879,12 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) } /* Set the alignment of a common symbol. */ - if ((isym->st_shndx == SHN_COMMON - || bfd_is_com_section (sec)) + if ((common || bfd_is_com_section (sec)) && h->root.type == bfd_link_hash_common) { unsigned int align; - if (isym->st_shndx == SHN_COMMON) + if (common) align = bfd_log2 (isym->st_value); else { @@ -3893,7 +3910,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) definition or a common symbol is ignored due to the old normal definition. We need to make sure the maximum alignment is maintained. */ - if ((old_alignment || isym->st_shndx == SHN_COMMON) + if ((old_alignment || common) && h->root.type != bfd_link_hash_common) { unsigned int common_align; @@ -6498,7 +6515,7 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) case bfd_link_hash_common: input_sec = h->root.u.c.p->section; - sym.st_shndx = SHN_COMMON; + sym.st_shndx = bed->common_section_index (input_sec); sym.st_value = 1 << h->root.u.c.p->alignment_power; break; @@ -9900,3 +9917,21 @@ _bfd_elf_fix_excluded_sec_syms (bfd *obfd, struct bfd_link_info *info) { bfd_link_hash_traverse (info->hash, fix_syms, obfd); } + +bfd_boolean +_bfd_elf_common_definition (Elf_Internal_Sym *sym) +{ + return sym->st_shndx == SHN_COMMON; +} + +unsigned int +_bfd_elf_common_section_index (asection *sec ATTRIBUTE_UNUSED) +{ + return SHN_COMMON; +} + +asection * +_bfd_elf_common_section (asection *sec ATTRIBUTE_UNUSED) +{ + return bfd_com_section_ptr; +} diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h index cd63244033..0268e62eb3 100644 --- a/bfd/elfxx-target.h +++ b/bfd/elfxx-target.h @@ -521,6 +521,22 @@ #define elf_backend_link_order_error_handler _bfd_default_error_handler #endif +#ifndef elf_backend_common_definition +#define elf_backend_common_definition _bfd_elf_common_definition +#endif + +#ifndef elf_backend_common_section_index +#define elf_backend_common_section_index _bfd_elf_common_section_index +#endif + +#ifndef elf_backend_common_section +#define elf_backend_common_section _bfd_elf_common_section +#endif + +#ifndef elf_backend_merge_symbol +#define elf_backend_merge_symbol NULL +#endif + extern const struct elf_size_info _bfd_elfNN_size_info; #ifndef INCLUDED_TARGET_FILE @@ -590,6 +606,10 @@ static const struct elf_backend_data elfNN_bed = elf_backend_ecoff_debug_swap, elf_backend_bfd_from_remote_memory, elf_backend_plt_sym_val, + elf_backend_common_definition, + elf_backend_common_section_index, + elf_backend_common_section, + elf_backend_merge_symbol, elf_backend_link_order_error_handler, elf_backend_relplt_name, ELF_MACHINE_ALT1, diff --git a/bfd/section.c b/bfd/section.c index aeb63a6742..42554b9a63 100644 --- a/bfd/section.c +++ b/bfd/section.c @@ -635,6 +635,47 @@ CODE_FRAGMENT .#define bfd_section_removed_from_list(ABFD, S) \ . ((S)->next == NULL ? (ABFD)->section_last != (S) : (S)->next->prev != (S)) . +.#define BFD_FAKE_SECTION(SEC, FLAGS, SYM, SYM_PTR, NAME, IDX) \ +. {* name, id, index, next, prev, flags, user_set_vma, *} \ +. { NAME, IDX, 0, NULL, NULL, FLAGS, 0, \ +. \ +. {* linker_mark, linker_has_input, gc_mark, gc_mark_from_eh, *} \ +. 0, 0, 1, 0, \ +. \ +. {* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, *} \ +. 0, 0, 0, 0, \ +. \ +. {* has_gp_reloc, need_finalize_relax, reloc_done, *} \ +. 0, 0, 0, \ +. \ +. {* vma, lma, size, rawsize *} \ +. 0, 0, 0, 0, \ +. \ +. {* output_offset, output_section, alignment_power, *} \ +. 0, (struct bfd_section *) &SEC, 0, \ +. \ +. {* relocation, orelocation, reloc_count, filepos, rel_filepos, *} \ +. NULL, NULL, 0, 0, 0, \ +. \ +. {* line_filepos, userdata, contents, lineno, lineno_count, *} \ +. 0, NULL, NULL, NULL, 0, \ +. \ +. {* entsize, kept_section, moving_line_filepos, *} \ +. 0, NULL, 0, \ +. \ +. {* target_index, used_by_bfd, constructor_chain, owner, *} \ +. 0, NULL, NULL, NULL, \ +. \ +. {* symbol, *} \ +. (struct bfd_symbol *) SYM, \ +. \ +. {* symbol_ptr_ptr, *} \ +. (struct bfd_symbol **) SYM_PTR, \ +. \ +. {* map_head, map_tail *} \ +. { NULL }, { NULL } \ +. } +. */ /* We use a macro to initialize the static asymbol structures because @@ -662,46 +703,8 @@ static const asymbol global_syms[] = #define STD_SECTION(SEC, FLAGS, SYM, NAME, IDX) \ const asymbol * const SYM = (asymbol *) &global_syms[IDX]; \ - asection SEC = \ - /* name, id, index, next, prev, flags, user_set_vma, */ \ - { NAME, IDX, 0, NULL, NULL, FLAGS, 0, \ - \ - /* linker_mark, linker_has_input, gc_mark, gc_mark_from_eh, */ \ - 0, 0, 1, 0, \ - \ - /* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, */ \ - 0, 0, 0, 0, \ - \ - /* has_gp_reloc, need_finalize_relax, reloc_done, */ \ - 0, 0, 0, \ - \ - /* vma, lma, size, rawsize */ \ - 0, 0, 0, 0, \ - \ - /* output_offset, output_section, alignment_power, */ \ - 0, (struct bfd_section *) &SEC, 0, \ - \ - /* relocation, orelocation, reloc_count, filepos, rel_filepos, */ \ - NULL, NULL, 0, 0, 0, \ - \ - /* line_filepos, userdata, contents, lineno, lineno_count, */ \ - 0, NULL, NULL, NULL, 0, \ - \ - /* entsize, kept_section, moving_line_filepos, */ \ - 0, NULL, 0, \ - \ - /* target_index, used_by_bfd, constructor_chain, owner, */ \ - 0, NULL, NULL, NULL, \ - \ - /* symbol, */ \ - (struct bfd_symbol *) &global_syms[IDX], \ - \ - /* symbol_ptr_ptr, */ \ - (struct bfd_symbol **) &SYM, \ - \ - /* map_head, map_tail */ \ - { NULL }, { NULL } \ - } + asection SEC = BFD_FAKE_SECTION(SEC, FLAGS, &global_syms[IDX], &SYM, \ + NAME, IDX) STD_SECTION (bfd_com_section, SEC_IS_COMMON, bfd_com_symbol, BFD_COM_SECTION_NAME, 0);