aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1999-11-01 23:37:48 +0000
committerIan Lance Taylor <ian@airs.com>1999-11-01 23:37:48 +0000
commit9503fd8735ec438fcb2fca34afa276e3e6ca94f5 (patch)
treec11a325558742324f26d022d24ed65514fd21e93
parent2bd7f1f332946c3baeef11111d1dfb1994ce9942 (diff)
1999-11-01 Steve Chamberlain <sac@pobox.com>
* ldlang.c (section_already_linked): Rework to use hash table. (already_linked_newfunc): New function. (already_linked_table_init): New function. (already_linked_table_free): New function. (lang_process): Initialize and free the already_linked hash table.
-rw-r--r--ld/ChangeLog8
-rw-r--r--ld/ldlang.c105
2 files changed, 92 insertions, 21 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 99f59627b33..ed7519d4e03 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,11 @@
+1999-11-01 Steve Chamberlain <sac@pobox.com>
+
+ * ldlang.c (section_already_linked): Rework to use hash table.
+ (already_linked_newfunc): New function.
+ (already_linked_table_init): New function.
+ (already_linked_table_free): New function.
+ (lang_process): Initialize and free the already_linked hash table.
+
1999-10-27 Andreas Jaeger <aj@suse.de>
* ld/configure.host: Added HOSTING_CRT0, HOSTING_LIBS for
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 56a00540103..33dc573c0d7 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -73,6 +73,11 @@ static lang_input_statement_type *new_afile
static void init_os PARAMS ((lang_output_section_statement_type *s));
static void exp_init_os PARAMS ((etree_type *));
static void section_already_linked PARAMS ((bfd *, asection *, PTR));
+static struct bfd_hash_entry *already_linked_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
+ const char *string));
+static void already_linked_table_init PARAMS ((void));
+static void already_linked_table_free PARAMS ((void));
static boolean wildcardp PARAMS ((const char *));
static lang_statement_union_type *wild_sort
PARAMS ((lang_wild_statement_type *, lang_input_statement_type *,
@@ -858,15 +863,36 @@ exp_init_os (exp)
break;
}
}
-
+
/* Sections marked with the SEC_LINK_ONCE flag should only be linked
- once into the output. This routine checks each sections, and
- arranges to discard it if a section of the same name has already
+ 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. If the section has COMDAT information, then it uses
that to decide whether the section should be included. 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. This is
- called via bfd_map_over_sections. */
+ that is, it does not depend solely upon the section name.
+ section_already_linked is called via bfd_map_over_sections. */
+
+/* This is the shape of the elements inside the already_linked hash
+ table. It maps a name onto a list of already_linked elements with
+ the same name. It's possible to get more than one element in a
+ list if the COMDAT sections have different names. */
+
+struct already_linked_hash_entry
+{
+ struct bfd_hash_entry root;
+ struct already_linked *entry;
+};
+
+struct already_linked
+{
+ struct already_linked *next;
+ asection *sec;
+};
+
+/* The hash table. */
+
+static struct bfd_hash_table already_linked_table;
/*ARGSUSED*/
static void
@@ -876,15 +902,10 @@ section_already_linked (abfd, sec, data)
PTR data;
{
lang_input_statement_type *entry = (lang_input_statement_type *) data;
- struct sec_link_once
- {
- struct sec_link_once *next;
- asection *sec;
- };
- static struct sec_link_once *sec_link_once_list;
flagword flags;
const char *name;
- struct sec_link_once *l;
+ struct already_linked *l;
+ struct already_linked_hash_entry *already_linked_list;
/* If we are only reading symbols from this object, then we want to
discard all sections. */
@@ -919,12 +940,15 @@ section_already_linked (abfd, sec, data)
name = bfd_get_section_name (abfd, sec);
- for (l = sec_link_once_list; l != NULL; l = l->next)
+ already_linked_list =
+ ((struct already_linked_hash_entry *)
+ bfd_hash_lookup (&already_linked_table, name, true, false));
+
+ for (l = already_linked_list->entry; l != NULL; l = l->next)
{
- if (strcmp (name, bfd_get_section_name (l->sec->owner, l->sec)) == 0
- && (sec->comdat == NULL
- || l->sec->comdat == NULL
- || strcmp (sec->comdat->name, l->sec->comdat->name) == 0))
+ if (sec->comdat == NULL
+ || l->sec->comdat == NULL
+ || strcmp (sec->comdat->name, l->sec->comdat->name) == 0)
{
/* The section has already been linked. See if we should
issue a warning. */
@@ -973,12 +997,47 @@ section_already_linked (abfd, sec, data)
}
}
- /* This is the first section with this name. Record it. */
+ /* This is the first section with this name. Record it. Allocate
+ the memory from the same obstack as the hash table is kept in. */
+
+ l = ((struct already_linked *)
+ bfd_hash_allocate (&already_linked_table, sizeof *l));
- l = (struct sec_link_once *) xmalloc (sizeof *l);
l->sec = sec;
- l->next = sec_link_once_list;
- sec_link_once_list = l;
+ l->next = already_linked_list->entry;
+ already_linked_list->entry = l;
+}
+
+/* Support routines for the hash table used by section_already_linked,
+ initialize the table, fill in an entry and remove the table. */
+
+static struct bfd_hash_entry *
+already_linked_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry ATTRIBUTE_UNUSED;
+ struct bfd_hash_table *table;
+ const char *string ATTRIBUTE_UNUSED;
+{
+ struct already_linked_hash_entry *ret =
+ bfd_hash_allocate (table, sizeof (struct already_linked_hash_entry));
+
+ ret->entry = NULL;
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+static void
+already_linked_table_init ()
+{
+ if (! bfd_hash_table_init_n (&already_linked_table,
+ already_linked_newfunc,
+ 42))
+ einfo (_("%P%F: Failed to create hash table\n"));
+}
+
+static void
+already_linked_table_free ()
+{
+ bfd_hash_table_free (&already_linked_table);
}
/* The wild routines.
@@ -3848,12 +3907,16 @@ lang_process ()
/* Add to the hash table all undefineds on the command line */
lang_place_undefineds ();
+ already_linked_table_init ();
+
/* Create a bfd for each input file */
current_target = default_target;
open_input_bfds (statement_list.head, false);
ldemul_after_open ();
+ already_linked_table_free ();
+
/* Make sure that we're not mixing architectures. We call this
after all the input files have been opened, but before we do any
other processing, so that any operations merge_private_bfd_data