* ldlang.c (struct output_statement_hash_entry): Don't indirect to os.
authorAlan Modra <amodra@gmail.com>
Fri, 4 Nov 2005 13:26:53 +0000 (13:26 +0000)
committerAlan Modra <amodra@gmail.com>
Fri, 4 Nov 2005 13:26:53 +0000 (13:26 +0000)
(output_statement_newfunc): Rewrite.
(lang_output_section_find_1): Merge into..
(lang_output_section_find): ..here.
(lang_output_section_statement_lookup_1): Rewrite to handle
multiple sections with the same name.
(output_statement_table_init): Commonise error message.
(lang_init, open_output): Likewise.

ld/ChangeLog
ld/ldlang.c

index 1ae1a08623af993d667b9162de4288be3c614709..22383ac15308b0130208eafa7caf25d1d8f813fb 100644 (file)
@@ -1,3 +1,14 @@
+2005-11-04  Alan Modra  <amodra@bigpond.net.au>
+
+       * ldlang.c (struct output_statement_hash_entry): Don't indirect to os.
+       (output_statement_newfunc): Rewrite.
+       (lang_output_section_find_1): Merge into..
+       (lang_output_section_find): ..here.
+       (lang_output_section_statement_lookup_1): Rewrite to handle
+       multiple sections with the same name.
+       (output_statement_table_init): Commonise error message.
+       (lang_init, open_output): Likewise.
+
 2005-11-03  Paul Brook  <paul@codesourcery.com>
 
        * scripttempl/elf.sc: Add .init_array.* and .fini_array.*.
        * ldmain.c (main): Use expandargv.
 
 2005-09-30  Catherine Moore  <clm@cm00re.com>
-       
+
        * Makefile.am: Bfin support.
        * Makefile.in: Regenerated.
        * aclocal.m4: Regenerated.
index c4b1b9cc73971f02de5cd2f709d7705510244187..496e9f86d62ba607ad4c68889505f2b20d386104 100644 (file)
@@ -871,26 +871,54 @@ lang_add_input_file (const char *name,
 struct output_statement_hash_entry
 {
   struct bfd_hash_entry root;
-  lang_output_section_statement_type *entry;
+  lang_output_section_statement_type os;
 };
 
 /* The hash table.  */
 
 static struct bfd_hash_table output_statement_table;
 
-/* Support routines for the hash table used by lang_output_section_find_1,
+/* Support routines for the hash table used by lang_output_section_find,
    initialize the table, fill in an entry and remove the table.  */
 
 static struct bfd_hash_entry *
-output_statement_newfunc (struct bfd_hash_entry *entry ATTRIBUTE_UNUSED
+output_statement_newfunc (struct bfd_hash_entry *entry, 
                          struct bfd_hash_table *table,
-                         const char *string ATTRIBUTE_UNUSED)
+                         const char *string)
 {
-  struct output_statement_hash_entry *ret
-    = bfd_hash_allocate (table,
-                        sizeof (struct output_statement_hash_entry));
-  ret->entry = NULL;
-  return (struct bfd_hash_entry *) ret;
+  lang_output_section_statement_type **nextp;
+  struct output_statement_hash_entry *ret;
+
+  if (entry == NULL)
+    {
+      entry = bfd_hash_allocate (table, sizeof (*ret));
+      if (entry == NULL)
+       return entry;
+    }
+
+  entry = bfd_hash_newfunc (entry, table, string);
+  if (entry == NULL)
+    return entry;
+
+  ret = (struct output_statement_hash_entry *) entry;
+  memset (&ret->os, 0, sizeof (ret->os));
+  ret->os.header.type = lang_output_section_statement_enum;
+  ret->os.subsection_alignment = -1;
+  ret->os.section_alignment = -1;
+  ret->os.block_value = 1;
+  lang_list_init (&ret->os.children);
+  lang_statement_append (stat_ptr,
+                        (lang_statement_union_type *) &ret->os,
+                        &ret->os.header.next);
+
+  /* GCC's strict aliasing rules prevent us from just casting the
+     address, so we store the pointer in a variable and cast that
+     instead.  */
+  nextp = &ret->os.next;
+  lang_statement_append (&lang_output_section_statement,
+                        (lang_statement_union_type *) &ret->os,
+                        (lang_statement_union_type **) nextp);
+  return &ret->root;
 }
 
 static void
@@ -898,7 +926,7 @@ output_statement_table_init (void)
 {
   if (! bfd_hash_table_init_n (&output_statement_table,
                               output_statement_newfunc, 61))
-    einfo (_("%P%F: Failed to create hash table\n"));
+    einfo (_("%P%F: can not create hash table: %E\n"));
 }
 
 static void
@@ -938,7 +966,7 @@ lang_init (void)
      looks like other code here.  */
   if (!bfd_hash_table_init_n (&lang_definedness_table,
                              lang_definedness_newfunc, 3))
-    einfo (_("%P%F: out of memory during initialization"));
+    einfo (_("%P%F: can not create hash table: %E\n"));
 }
 
 void
@@ -1028,96 +1056,79 @@ lang_memory_default (asection *section)
   return lang_memory_region_lookup (DEFAULT_MEMORY_REGION, FALSE);
 }
 
-static lang_output_section_statement_type *
-lang_output_section_find_1 (const char *const name, int constraint)
+lang_output_section_statement_type *
+lang_output_section_find (const char *const name)
 {
-  lang_output_section_statement_type *lookup;
   struct output_statement_hash_entry *entry;
   unsigned long hash;
 
   entry = ((struct output_statement_hash_entry *)
-          bfd_hash_lookup (&output_statement_table, name, FALSE,
-                           FALSE));
-  if (entry == NULL || (lookup = entry->entry) == NULL)
+          bfd_hash_lookup (&output_statement_table, name, FALSE, FALSE));
+  if (entry == NULL)
     return NULL;
 
   hash = entry->root.hash;
   do
     {
-      if (lookup->constraint != -1
-         && (constraint == 0
-             || (constraint == lookup->constraint
-                 && constraint != SPECIAL)))
-       return lookup;
+      if (entry->os.constraint != -1)
+       return &entry->os;
       entry = (struct output_statement_hash_entry *) entry->root.next;
-      lookup = entry ? entry->entry : NULL;
     }
   while (entry != NULL
         && entry->root.hash == hash
-        && strcmp (name, lookup->name) == 0);
+        && strcmp (name, entry->os.name) == 0);
 
   return NULL;
 }
 
-lang_output_section_statement_type *
-lang_output_section_find (const char *const name)
-{
-  return lang_output_section_find_1 (name, 0);
-}
-
 static lang_output_section_statement_type *
 lang_output_section_statement_lookup_1 (const char *const name, int constraint)
 {
-  lang_output_section_statement_type *lookup;
-  lang_output_section_statement_type **nextp;
+  struct output_statement_hash_entry *entry;
+  struct output_statement_hash_entry *last_ent;
+  unsigned long hash;
+
+  entry = ((struct output_statement_hash_entry *)
+          bfd_hash_lookup (&output_statement_table, name, TRUE, FALSE));
+  if (entry == NULL)
+    {
+      einfo (_("%P%F: failed creating section `%s': %E\n"), name);
+      return NULL;
+    }
 
-  lookup = lang_output_section_find_1 (name, constraint);
-  if (lookup == NULL)
-    {
-      struct output_statement_hash_entry *entry;
-
-      lookup = new_stat (lang_output_section_statement, stat_ptr);
-      lookup->region = NULL;
-      lookup->lma_region = NULL;
-      lookup->fill = 0;
-      lookup->block_value = 1;
-      lookup->name = name;
-
-      lookup->next = NULL;
-      lookup->bfd_section = NULL;
-      lookup->processed = FALSE;
-      lookup->constraint = constraint;
-      lookup->all_input_readonly = FALSE;
-      lookup->ignored = FALSE;
-      lookup->sectype = normal_section;
-      lookup->addr_tree = NULL;
-      lang_list_init (&lookup->children);
-
-      lookup->flags = 0;
-      lookup->subsection_alignment = -1;
-      lookup->section_alignment = -1;
-      lookup->load_base = NULL;
-      lookup->update_dot_tree = NULL;
-      lookup->phdrs = NULL;
+  if (entry->os.name != NULL)
+    {
+      /* We have a section of this name, but it might not have the correct
+        constraint.  */
+      hash = entry->root.hash;
+      do
+       {
+         if (entry->os.constraint != -1
+             && (constraint == 0
+                 || (constraint == entry->os.constraint
+                     && constraint != SPECIAL)))
+           return &entry->os;
+         last_ent = entry;
+         entry = (struct output_statement_hash_entry *) entry->root.next;
+       }
+      while (entry != NULL
+            && entry->root.hash == hash
+            && strcmp (name, entry->os.name) == 0);
 
       entry = ((struct output_statement_hash_entry *)
-              bfd_hash_lookup (&output_statement_table, name, TRUE,
-                               FALSE));
+              output_statement_newfunc (NULL, &output_statement_table, name));
       if (entry == NULL)
-       einfo (_("%P%F: bfd_hash_lookup failed creating section `%s'\n"),
-              name);
-
-      entry->entry = lookup;
-
-      /* GCC's strict aliasing rules prevent us from just casting the
-        address, so we store the pointer in a variable and cast that
-        instead.  */
-      nextp = &lookup->next;
-      lang_statement_append (&lang_output_section_statement,
-                            (lang_statement_union_type *) lookup,
-                            (lang_statement_union_type **) nextp);
+       {
+         einfo (_("%P%F: failed creating section `%s': %E\n"), name);
+         return NULL;
+       }
+      entry->root = last_ent->root;
+      last_ent->root.next = &entry->root;
     }
-  return lookup;
+
+  entry->os.name = name;
+  entry->os.constraint = constraint;
+  return &entry->os;
 }
 
 lang_output_section_statement_type *
@@ -2671,7 +2682,7 @@ open_output (const char *name)
 
   link_info.hash = bfd_link_hash_table_create (output);
   if (link_info.hash == NULL)
-    einfo (_("%P%F: can not create link hash table: %E\n"));
+    einfo (_("%P%F: can not create hash table: %E\n"));
 
   bfd_set_gp_size (output, g_switch_value);
   return output;