aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog32
-rw-r--r--bfd/bfd-in2.h41
-rw-r--r--bfd/elf-bfd.h33
-rw-r--r--bfd/elf.c2
-rw-r--r--bfd/elflink.c53
-rw-r--r--bfd/elfxx-target.h20
-rw-r--r--bfd/section.c83
7 files changed, 214 insertions, 50 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 495ea95..64d9817 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,35 @@
+2005-07-25 H.J. Lu <hongjiu.lu@intel.com>
+
+ * 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 <olh@suse.de>
* elflink.c (elf_link_input_bfd): Add '\n' for linker einfo
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index c9c75c2..7dbfe95 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 2bbc1c9..f7bab5c 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 ff46a5e..3e47b02 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 901b528..f52d307 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 cd63244..0268e62 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 aeb63a6..42554b9 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);