aboutsummaryrefslogtreecommitdiff
path: root/bfd/linker.c
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2004-07-21 15:42:58 +0000
committerH.J. Lu <hjl.tools@gmail.com>2004-07-21 15:42:58 +0000
commit082b7297014d9ccc3990c3c6be689dd18946d826 (patch)
treebf2953f69a75e2f3bc6151c1d81070af422e7f53 /bfd/linker.c
parent76d7af2d04354fe7225eba82b02a16bfb5772e80 (diff)
downloadfsf-binutils-gdb-082b7297014d9ccc3990c3c6be689dd18946d826.zip
fsf-binutils-gdb-082b7297014d9ccc3990c3c6be689dd18946d826.tar.gz
fsf-binutils-gdb-082b7297014d9ccc3990c3c6be689dd18946d826.tar.bz2
bfd/
2004-07-21 H.J. Lu <hongjiu.lu@intel.com> * aout-adobe.c (aout_32_section_already_linked): Defined. * aout-target.h (MY_section_already_linked): Likewise. * aout-tic30.c (MY_section_already_linked): Likewise. * binary.c (binary_section_already_linked): Likewise. * bout.c (b_out_section_already_linked): Likewise. * coff-alpha.c (_bfd_ecoff_section_already_linked): Likewise. * coff-mips.c (_bfd_ecoff_section_already_linked): Likewise. * coffcode.h (coff_section_already_linked): Likewise. * i386msdos.c (msdos_section_already_linked): Likewise. * i386os9k.c (os9k_section_already_linked): Likewise. * ieee.c (ieee_section_already_linked): Likewise. * ihex.c (ihex_section_already_linked): Likewise. * mach-o.c (bfd_mach_o_section_already_linked): Likewise. * mmo.c (mmo_section_already_linked): Likewise. * nlm-target.h (nlm_section_already_linked): Likewise. * oasys.c (oasys_section_already_linked): Likewise. * pef.c (bfd_pef_section_already_linked): Likewise. * ppcboot.c (ppcboot_section_already_linked): Likewise. * som.c (som_bfd_discard_group): Likewise. * srec.c (srec_section_already_linked): Likewise. * tekhex.c (tekhex_section_already_linked): Likewise. * versados.c (versados_section_already_linked): Likewise. * vms.c (vms_section_already_linked): Likewise. * coff-target.h (_bfd_xcoff_section_already_linked): Likewise. * xsym.c (bfd_sym_section_already_linked): Likewise. * bfd-in.h (bfd_section_already_linked_table_init): New. (bfd_section_already_linked_table_free): Likewise. * coff-rs6000.c (rs6000coff_vec): Add _bfd_generic_section_already_linked. (pmac_xcoff_vec): Likewise. * coff64-rs6000.c (rs6000coff64_vec): Likewise. (aix5coff64_vec): Likewise. * elf-bfd.h (_bfd_elf_section_already_linked): New prototype. * elflink.c (_bfd_elf_section_already_linked): New function. * elfxx-target.h (bfd_elfNN_section_already_linked): Defined. * libbfd-in.h (_bfd_nolink_section_already_linked): Defined. (_bfd_generic_section_already_linked): New. (bfd_section_already_linked_hash_entry): Likewise. (bfd_section_already_linked): Likewise. (bfd_section_already_linked_table_lookup): Likewise. (bfd_section_already_linked_table_insert): Likewise. * linker.c (bfd_section_already_linked): New. (_bfd_section_already_linked_table): Likewise. (bfd_section_already_linked_table_lookup): Likewise. (bfd_section_already_linked_table_insert): Likewise. (already_linked_newfunc): Likewise. (bfd_section_already_linked_table_init): Likewise. (bfd_section_already_linked_table_free): Likewise. (_bfd_generic_section_already_linked): Likewise. * section.c (bfd_section): Remove comdat. (bfd_comdat_info): Moved to ... * bfd-in.h (coff_comdat_info): Here. (bfd_coff_get_comdat_section): New. * coffgen.c (bfd_coff_get_comdat_section): Likewise. * libcoff-in.h (coff_section_tdata): Add comdat. * coffcode.h (handle_COMDAT): Updated. * cofflink.c (coff_link_add_symbols): Likewise. * ecoff.c (bfd_debug_section): Likewise. * targets.c (bfd_target): Add _section_already_linked. (BFD_JUMP_TABLE_LINK): Updated. * bfd-in2.h: Regenerated. * libbfd.h: Likewise. * libcoff.h: Likewise. binutils/ 2004-07-21 H.J. Lu <hongjiu.lu@intel.com> * objcopy.c (filter_symbols): Use bfd_coff_get_comdat_section to access comdat. * objdump.c (dump_section_header): Likewise. ld/ 2004-07-21 H.J. Lu <hongjiu.lu@intel.com> * ldlang.c (already_linked_hash_entry): Removed. (already_linked): Likewise. (already_linked_table): Likewise. (section_already_linked): Call bfd_section_already_linked. (lang_process): Replace already_linked_table_init with bfd_section_already_linked_table_init and check return. Replace already_linked_table_free with bfd_section_already_linked_table_free.
Diffstat (limited to 'bfd/linker.c')
-rw-r--r--bfd/linker.c194
1 files changed, 194 insertions, 0 deletions
diff --git a/bfd/linker.c b/bfd/linker.c
index 10b4467..cd2adb5 100644
--- a/bfd/linker.c
+++ b/bfd/linker.c
@@ -2827,3 +2827,197 @@ _bfd_generic_link_split_section (bfd *abfd ATTRIBUTE_UNUSED,
{
return FALSE;
}
+
+/*
+FUNCTION
+ bfd_section_already_linked
+
+SYNOPSIS
+ void bfd_section_already_linked (bfd *abfd, asection *sec);
+
+DESCRIPTION
+ Check if @var{sec} has been already linked during a reloceatable
+ or final link.
+
+.#define bfd_section_already_linked(abfd, sec) \
+. BFD_SEND (abfd, _section_already_linked, (abfd, sec))
+.
+
+*/
+
+/* Sections marked with the SEC_LINK_ONCE flag should only be linked
+ once into the output. This routine checks each section, and
+ arrange to discard it if a section of the same name has already
+ been linked. This code assumes that all relevant sections have the
+ SEC_LINK_ONCE flag set; that is, it does not depend solely upon the
+ section name. bfd_section_already_linked is called via
+ bfd_map_over_sections. */
+
+/* The hash table. */
+
+static struct bfd_hash_table _bfd_section_already_linked_table;
+
+/* Support routines for the hash table used by section_already_linked,
+ initialize the table, lookup, fill in an entry and remove the
+ table. */
+
+struct bfd_section_already_linked_hash_entry *
+bfd_section_already_linked_table_lookup (const char *name)
+{
+ return ((struct bfd_section_already_linked_hash_entry *)
+ bfd_hash_lookup (&_bfd_section_already_linked_table, name,
+ TRUE, FALSE));
+}
+
+void
+bfd_section_already_linked_table_insert
+ (struct bfd_section_already_linked_hash_entry *already_linked_list,
+ asection *sec)
+{
+ struct bfd_section_already_linked *l;
+
+ /* Allocate the memory from the same obstack as the hash table is
+ kept in. */
+ l = bfd_hash_allocate (&_bfd_section_already_linked_table, sizeof *l);
+ l->sec = sec;
+ l->next = already_linked_list->entry;
+ already_linked_list->entry = l;
+}
+
+static struct bfd_hash_entry *
+already_linked_newfunc (struct bfd_hash_entry *entry ATTRIBUTE_UNUSED,
+ struct bfd_hash_table *table,
+ const char *string ATTRIBUTE_UNUSED)
+{
+ struct bfd_section_already_linked_hash_entry *ret =
+ bfd_hash_allocate (table, sizeof *ret);
+
+ ret->entry = NULL;
+
+ return &ret->root;
+}
+
+bfd_boolean
+bfd_section_already_linked_table_init (void)
+{
+ return bfd_hash_table_init_n (&_bfd_section_already_linked_table,
+ already_linked_newfunc, 42);
+}
+
+void
+bfd_section_already_linked_table_free (void)
+{
+ bfd_hash_table_free (&_bfd_section_already_linked_table);
+}
+
+/* This is used on non-ELF inputs. */
+
+void
+_bfd_generic_section_already_linked (bfd *abfd, asection *sec)
+{
+ flagword flags;
+ const char *name;
+ struct bfd_section_already_linked *l;
+ struct bfd_section_already_linked_hash_entry *already_linked_list;
+
+ flags = sec->flags;
+ if ((flags & SEC_LINK_ONCE) == 0)
+ return;
+
+ /* FIXME: When doing a relocatable link, we may have trouble
+ copying relocations in other sections that refer to local symbols
+ in the section being discarded. Those relocations will have to
+ be converted somehow; as of this writing I'm not sure that any of
+ the backends handle that correctly.
+
+ It is tempting to instead not discard link once sections when
+ doing a relocatable link (technically, they should be discarded
+ whenever we are building constructors). However, that fails,
+ because the linker winds up combining all the link once sections
+ into a single large link once section, which defeats the purpose
+ of having link once sections in the first place. */
+
+ name = bfd_get_section_name (abfd, sec);
+
+ already_linked_list = bfd_section_already_linked_table_lookup (name);
+
+ for (l = already_linked_list->entry; l != NULL; l = l->next)
+ {
+ bfd_boolean skip = FALSE;
+ struct coff_comdat_info *s_comdat
+ = bfd_coff_get_comdat_section (abfd, sec);
+ struct coff_comdat_info *l_comdat
+ = bfd_coff_get_comdat_section (l->sec->owner, l->sec);
+
+ /* We may have 3 different sections on the list: group section,
+ comdat section and linkonce section. SEC may be a linkonce or
+ comdat section. We always ignore group section. For non-COFF
+ inputs, we also ignore comdat section.
+
+ FIXME: Is that safe to match a linkonce section with a comdat
+ section for COFF inputs? */
+ if ((l->sec->flags & SEC_GROUP) != 0)
+ skip = TRUE;
+ else if (bfd_get_flavour (abfd) == bfd_target_coff_flavour)
+ {
+ if (s_comdat != NULL
+ && l_comdat != NULL
+ && strcmp (s_comdat->name, l_comdat->name) != 0)
+ skip = TRUE;
+ }
+ else if (l_comdat != NULL)
+ skip = TRUE;
+
+ if (!skip)
+ {
+ /* The section has already been linked. See if we should
+ issue a warning. */
+ switch (flags & SEC_LINK_DUPLICATES)
+ {
+ default:
+ abort ();
+
+ case SEC_LINK_DUPLICATES_DISCARD:
+ break;
+
+ case SEC_LINK_DUPLICATES_ONE_ONLY:
+ if (s_comdat == NULL)
+ (*_bfd_error_handler)
+ (_("%s: %s: warning: ignoring duplicate section `%s'\n"),
+ bfd_archive_filename (abfd), name);
+ else
+ (*_bfd_error_handler)
+ (_("%s: %s: warning: ignoring duplicate `%s' section symbol `%s'\n"),
+ bfd_archive_filename (abfd), name, s_comdat->name);
+ break;
+
+ case SEC_LINK_DUPLICATES_SAME_CONTENTS:
+ /* FIXME: We should really dig out the contents of both
+ sections and memcmp them. The COFF/PE spec says that
+ the Microsoft linker does not implement this
+ correctly, so I'm not going to bother doing it
+ either. */
+ /* Fall through. */
+ case SEC_LINK_DUPLICATES_SAME_SIZE:
+ if (sec->size != l->sec->size)
+ (*_bfd_error_handler)
+ (_("%s: %s: warning: duplicate section `%s' has different size\n"),
+ bfd_archive_filename (abfd), name);
+ break;
+ }
+
+ /* Set the output_section field so that lang_add_section
+ does not create a lang_input_section structure for this
+ section. Since there might be a symbol in the section
+ being discarded, we must retain a pointer to the section
+ which we are really going to use. */
+ sec->output_section = bfd_abs_section_ptr;
+ sec->kept_section = l->sec;
+
+ return;
+ }
+ }
+
+ /* This is the first section with this name. Record it. */
+ bfd_section_already_linked_table_insert (already_linked_list, sec);
+}