Apply H.J.'s patch to fix NOLOAD section sizes and dot updates
[deliverable/binutils-gdb.git] / ld / ldlang.c
index f2c137978e65d69b6b3fafcb0ac23dfb7127c826..d38d83791403df846eb23f9435b9f965bbb76668 100644 (file)
@@ -1,5 +1,5 @@
 /* Linker command language support.
-   Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 1999
+   Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000
    Free Software Foundation, Inc.
 
 This file is part of GLD, the Gnu Linker.
@@ -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 *,
@@ -208,17 +213,21 @@ walk_wild_section (ptr, section, file, callback, data)
      void *data;
 {
   /* Don't process sections from files which were excluded. */
-  if (ptr->exclude_filename != NULL)
+  if (ptr->exclude_filename_list != NULL)
     {
-      boolean match;
+      struct name_list *list_tmp;
+      for (list_tmp = ptr->exclude_filename_list; list_tmp; list_tmp = list_tmp->next)
+        {
+         boolean match;
 
-      if (wildcardp (ptr->exclude_filename))
-         match = fnmatch (ptr->exclude_filename, file->filename, 0) == 0 ? true : false;
-      else
-         match = strcmp (ptr->exclude_filename, file->filename) == 0 ? true : false;
+         if (wildcardp (list_tmp->name))
+           match = fnmatch (list_tmp->name, file->filename, 0) == 0 ? true : false;
+         else
+           match = strcmp (list_tmp->name, file->filename) == 0 ? true : false;
 
-      if (match)
-        return;
+         if (match)
+           return;
+       }
     }
 
   if (file->just_syms_flag == false)
@@ -858,13 +867,36 @@ exp_init_os (exp)
       break;
     }
 }
-
+\f
 /* 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
-   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.  This is called via bfd_map_over_sections.  */
+   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.
+   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
@@ -874,15 +906,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.  */
@@ -917,9 +944,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)
+      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.  */
@@ -932,8 +965,12 @@ section_already_linked (abfd, sec, data)
              break;
 
            case SEC_LINK_DUPLICATES_ONE_ONLY:
-             einfo (_("%P: %B: warning: ignoring duplicate section `%s'\n"),
-                    abfd, name);
+             if (sec->comdat == NULL)
+               einfo (_("%P: %B: warning: ignoring duplicate section `%s'\n"),
+                      abfd, name);
+             else
+               einfo (_("%P: %B: warning: ignoring duplicate `%s' section symbol `%s'\n"),
+                      abfd, name, sec->comdat->name);
              break;
 
            case SEC_LINK_DUPLICATES_SAME_CONTENTS:
@@ -952,19 +989,59 @@ section_already_linked (abfd, sec, data)
            }
 
          /* Set the output_section field so that wild_doit does not
-            create a lang_input_section structure for this section.  */
+            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;
+         if (sec->comdat != NULL)
+           sec->comdat->sec = l->sec;
 
          return;
        }
     }
 
-  /* 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);
 }
 \f
 /* The wild routines.
@@ -1108,9 +1185,9 @@ wild_doit (ptr, section, output, file)
          break;
        }
 
-      /* Copy over SEC_SHORT.  */
-      if (section->flags & SEC_SHORT)
-       section->output_section->flags |= SEC_SHORT;
+      /* Copy over SEC_SMALL_DATA.  */
+      if (section->flags & SEC_SMALL_DATA)
+       section->output_section->flags |= SEC_SMALL_DATA;
 
       if (section->alignment_power > output->bfd_section->alignment_power)
        output->bfd_section->alignment_power = section->alignment_power;
@@ -1638,7 +1715,7 @@ open_output (name)
   if (command_line.endian != ENDIAN_UNSET)
     {
       const bfd_target * target;
-      int desired_endian;
+      enum bfd_endian desired_endian;
 
       /* Get the chosen target.  */
       target = bfd_search_for_target (get_target, (void *) output_target);
@@ -2287,9 +2364,15 @@ print_wild_statement (w, os)
 
   if (w->filenames_sorted)
     minfo ("SORT(");
-  if (w->exclude_filename != NULL)
-    minfo ("EXCLUDE_FILE ( %s )", w->exclude_filename);
-  if (w->filename != NULL)
+  if (w->exclude_filename_list != NULL)
+    {
+      name_list *tmp;
+      minfo ("EXCLUDE_FILE ( %s", w->exclude_filename_list->name);
+      for (tmp=w->exclude_filename_list->next; tmp; tmp = tmp->next)
+        minfo (", %s", tmp->name);
+      minfo (")");
+     }
+   if (w->filename != NULL)
     minfo ("%s", w->filename);
   else
     minfo ("*");
@@ -2535,6 +2618,10 @@ size_input_section (this_ptr, output_section_statement, fill, dot, relax)
   return dot;
 }
 
+#define IGNORE_SECTION(bfd, s) \
+  (((bfd_get_section_flags (bfd, s) & (SEC_ALLOC | SEC_LOAD)) != (SEC_ALLOC | SEC_LOAD)) \
+   || bfd_section_size (bfd, s) == 0)
+
 /* Check to see if any allocated sections overlap with other allocated
    sections.  This can happen when the linker script specifically specifies
    the output section addresses of the two sections.  */
@@ -2545,49 +2632,48 @@ lang_check_section_addresses ()
 
   /* Scan all sections in the output list.  */
   for (s = output_bfd->sections; s != NULL; s = s->next)
-    /* Ignore sections which are not loaded or which have no contents.  */
-    if ((bfd_get_section_flags (output_bfd, s) & (SEC_ALLOC | SEC_LOAD))
-       && bfd_section_size (output_bfd, s) != 0)
-      {
-       asection * os;
+    {
+      asection * os;
+      
+      /* Ignore sections which are not loaded or which have no contents.  */
+      if (IGNORE_SECTION (output_bfd, s))
+       continue;
+      
+      /* Once we reach section 's' stop our seach.  This prevents two
+        warning messages from being produced, one for 'section A overlaps
+        section B' and one for 'section B overlaps section A'.  */
+      for (os = output_bfd->sections; os != s; os = os->next)
+       {
+         bfd_vma s_start;
+         bfd_vma s_end;
+         bfd_vma os_start;
+         bfd_vma os_end;
+         
+         /* Only consider loadable sections with real contents.  */
+         if (IGNORE_SECTION (output_bfd, os))
+           continue;
 
-       /* Once we reach section 's' stop our seach.  This prevents two
-          warning messages from being produced, one for 'section A overlaps
-          section B' and one for 'section B overlaps section A'.  */
-       for (os = output_bfd->sections; os != s; os = os->next)
-         {
-           bfd_vma s_start;
-           bfd_vma s_end;
-           bfd_vma os_start;
-           bfd_vma os_end;
-
-           /* Only consider loadable sections with real contents.  */
-           if (((bfd_get_section_flags (output_bfd, os)
-                 & (SEC_ALLOC | SEC_LOAD)) == 0)
-               || bfd_section_size (output_bfd, os) == 0)
-             continue;
-
-           /* We must check the sections' LMA addresses not their
-              VMA addresses because overlay sections can have
-              overlapping VMAs but they must have distinct LMAs.  */
-           s_start  = bfd_section_lma (output_bfd, s);
-           os_start = bfd_section_lma (output_bfd, os);
-           s_end    = s_start  + bfd_section_size (output_bfd, s) - 1;
-           os_end   = os_start + bfd_section_size (output_bfd, os) - 1;
-
-           /* Look for an overlap.  */
-           if ((s_end < os_start) || (s_start > os_end))
-             continue;
-           
-           einfo (
+         /* We must check the sections' LMA addresses not their
+            VMA addresses because overlay sections can have
+            overlapping VMAs but they must have distinct LMAs.  */
+         s_start  = bfd_section_lma (output_bfd, s);
+         os_start = bfd_section_lma (output_bfd, os);
+         s_end    = s_start  + bfd_section_size (output_bfd, s) - 1;
+         os_end   = os_start + bfd_section_size (output_bfd, os) - 1;
+         
+         /* Look for an overlap.  */
+         if ((s_end < os_start) || (s_start > os_end))
+           continue;
+         
+         einfo (
 _("%X%P: section %s [%V -> %V] overlaps section %s [%V -> %V]\n"),
-                  s->name, s_start, s_end, os->name, os_start, os_end);
-
-           /* Once we have found one overlap for this section,
-              stop looking for others.  */
-           break;
-         }
-      }
+                s->name, s_start, s_end, os->name, os_start, os_end);
+         
+         /* Once we have found one overlap for this section,
+            stop looking for others.  */
+         break;
+       }
+    }
 }
 
 /* This variable indicates whether bfd_relax_section should be called
@@ -2737,17 +2823,30 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
            /* Update dot in the region ?
               We only do this if the section is going to be allocated,
               since unallocated sections do not contribute to the region's
-              overall size in memory.  */
+              
+              If the SEC_NEVER_LOAD bit is not set, it will affect the
+              addresses of sections after it. We have to update
+              dot.  */
            if (os->region != (lang_memory_region_type *) NULL
-               && (bfd_get_section_flags (output_bfd, os->bfd_section)
-               & (SEC_ALLOC | SEC_LOAD)))
+               && ((bfd_get_section_flags (output_bfd, os->bfd_section)
+                    & SEC_NEVER_LOAD) == 0
+                   || (bfd_get_section_flags (output_bfd, os->bfd_section)
+                       & (SEC_ALLOC | SEC_LOAD))))
              {
                os->region->current = dot;
                
-               /* Make sure this isn't silly.  */
-               if (os->region->current < os->region->origin
-                   || (os->region->current - os->region->origin
-                       > os->region->length))
+               /* Make sure the new address is within the region.  We
+                   explicitly permit the current address to be at the
+                   exact end of the region when the VMA is non-zero,
+                   in case the region is at the end of addressable
+                   memory and the calculation wraps around.  */
+               if ((os->region->current < os->region->origin
+                    || (os->region->current - os->region->origin
+                        > os->region->length))
+                   && ((os->region->current
+                        != os->region->origin + os->region->length)
+                       || os->bfd_section->vma == 0))
+
                  {
                    if (os->addr_tree != (etree_type *) NULL)
                      {
@@ -3786,14 +3885,17 @@ lang_gc_sections ()
 
   /* Keep all sections containing symbols undefined on the command-line.
      Handle the entry symbol at the same time.  */
-
-  fake_list_start.next = ldlang_undef_chain_list_head;
-  if (entry_symbol == NULL)
-    fake_list_start.name = "start";
+  
+  if (entry_symbol != NULL)
+    {
+      fake_list_start.next = ldlang_undef_chain_list_head;
+      fake_list_start.name = (char *) entry_symbol;
+      ulist = &fake_list_start;
+    }
   else
-    fake_list_start.name = (char *) entry_symbol;
+    ulist = ldlang_undef_chain_list_head;
 
-  for (ulist = &fake_list_start; ulist; ulist = ulist->next)
+  for (; ulist; ulist = ulist->next)
     {
       h = bfd_link_hash_lookup (link_info.hash, ulist->name, 
                                false, false, false);
@@ -3823,12 +3925,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
@@ -3938,13 +4044,13 @@ lang_process ()
 
 void
 lang_add_wild (section_name, sections_sorted, filename, filenames_sorted,
-              keep_sections, exclude_filename)
+              keep_sections, exclude_filename_list)
      const char *const section_name;
      boolean sections_sorted;
      const char *const filename;
      boolean filenames_sorted;
      boolean keep_sections;
-     const char *exclude_filename;
+     struct name_list *exclude_filename_list;
 {
   lang_wild_statement_type *new = new_stat (lang_wild_statement,
                                            stat_ptr);
@@ -3962,7 +4068,7 @@ lang_add_wild (section_name, sections_sorted, filename, filenames_sorted,
   new->filename = filename;
   new->filenames_sorted = filenames_sorted;
   new->keep_sections = keep_sections;
-  new->exclude_filename = exclude_filename;
+  new->exclude_filename_list = exclude_filename_list;
   lang_list_init (&new->children);
 }
 
This page took 0.028527 seconds and 4 git commands to generate.