one line fix by Gregory Lielens <Gregory.Lielens@fft.be> to fix a problem
[deliverable/binutils-gdb.git] / ld / ldlang.c
index eab4b5f6394f6fcb88fcc190c11cd4506b75891d..d43140f06b2fa4970b3833e848110fb1dd2df06f 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.
@@ -58,7 +58,6 @@ static lang_output_section_statement_type *default_common_section;
 static boolean map_option_f;
 static bfd_vma print_dot;
 static lang_input_statement_type *first_file;
-static lang_statement_list_type lang_output_section_statement;
 static CONST char *current_target;
 static CONST char *output_target;
 static lang_statement_list_type statement_list;
@@ -73,6 +72,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 *,
@@ -161,6 +165,7 @@ static char * get_first_input_target PARAMS ((void));
                                        
 /* EXPORTS */
 lang_output_section_statement_type *abs_output_section;
+lang_statement_list_type lang_output_section_statement;
 lang_statement_list_type *stat_ptr = &statement_list;
 lang_statement_list_type file_chain = { NULL, NULL };
 const char *entry_symbol = NULL;
@@ -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)
@@ -673,6 +682,7 @@ lang_output_section_statement_lookup (name)
       lookup = (lang_output_section_statement_type *)
        new_stat (lang_output_section_statement, stat_ptr);
       lookup->region = (lang_memory_region_type *) NULL;
+      lookup->lma_region = (lang_memory_region_type *) NULL;
       lookup->fill = 0;
       lookup->block_value = 1;
       lookup->name = name;
@@ -858,13 +868,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 +907,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 +945,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 +966,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 +990,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 +1186,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 +1716,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);
@@ -1786,8 +1864,10 @@ open_input_bfds (s, force)
 
              /* If we are being called from within a group, and this
                  is an archive which has already been searched, then
-                 force it to be researched.  */
+                 force it to be researched unless the whole archive
+                has been loaded already.  */
              if (force
+                 && !s->input_statement.whole_archive
                  && s->input_statement.loaded
                  && bfd_check_format (s->input_statement.the_bfd,
                                       bfd_archive))
@@ -2091,7 +2171,8 @@ print_input_section (in)
 {
   asection *i = in->section;
   bfd_size_type size = i->_cooked_size != 0 ? i->_cooked_size : i->_raw_size;
-
+  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
+                                               ldfile_output_machine);
   if (size != 0)
     {
       print_space ();
@@ -2115,7 +2196,7 @@ print_input_section (in)
            }
 
          minfo ("0x%V %W %B\n",
-                i->output_section->vma + i->output_offset, size,
+                i->output_section->vma + i->output_offset, size / opb,
                 i->owner);
 
          if (i->_cooked_size != 0 && i->_cooked_size != i->_raw_size)
@@ -2137,7 +2218,7 @@ print_input_section (in)
 
          bfd_link_hash_traverse (link_info.hash, print_one_symbol, (PTR) i);
 
-         print_dot = i->output_section->vma + i->output_offset + size;
+         print_dot = i->output_section->vma + i->output_offset + size / opb;
        }
     }
 }
@@ -2157,6 +2238,8 @@ print_data_statement (data)
   bfd_vma addr;
   bfd_size_type size;
   const char *name;
+  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
+                                               ldfile_output_machine);
 
   for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
     print_space ();
@@ -2201,7 +2284,8 @@ print_data_statement (data)
 
   print_nl ();
 
-  print_dot = addr + size;
+  print_dot = addr + size / opb;
+
 }
 
 /* Print an address statement.  These are generated by options like
@@ -2225,6 +2309,8 @@ print_reloc_statement (reloc)
   int i;
   bfd_vma addr;
   bfd_size_type size;
+  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
+                                               ldfile_output_machine); 
 
   for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
     print_space ();
@@ -2246,7 +2332,7 @@ print_reloc_statement (reloc)
 
   print_nl ();
 
-  print_dot = addr + size;
+  print_dot = addr + size / opb;
 }  
 
 static void
@@ -2255,6 +2341,8 @@ print_padding_statement (s)
 {
   int len;
   bfd_vma addr;
+  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
+                                               ldfile_output_machine); 
 
   minfo (" *fill*");
 
@@ -2275,7 +2363,7 @@ print_padding_statement (s)
 
   print_nl ();
 
-  print_dot = addr + s->size;
+  print_dot = addr + s->size / opb;
 }
 
 static void
@@ -2287,9 +2375,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 ("*");
@@ -2464,6 +2558,8 @@ insert_pad (this_ptr, fill, power, output_section_statement, dot)
      inserting a magic 'padding' statement.
      */
 
+  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
+                                               ldfile_output_machine); 
   unsigned int alignment_needed = align_power (dot, power) - dot;
 
   if (alignment_needed != 0)
@@ -2480,7 +2576,7 @@ insert_pad (this_ptr, fill, power, output_section_statement, dot)
       new->padding_statement.output_offset =
        dot - output_section_statement->vma;
       new->padding_statement.fill = fill;
-      new->padding_statement.size = alignment_needed;
+      new->padding_statement.size = alignment_needed * opb;
     }
 
 
@@ -2489,9 +2585,9 @@ insert_pad (this_ptr, fill, power, output_section_statement, dot)
     {
       output_section_statement->alignment_power = power;
     }
-  output_section_statement->_raw_size += alignment_needed;
-  return alignment_needed + dot;
+  output_section_statement->_raw_size += alignment_needed * opb;
 
+  return dot + alignment_needed;
 }
 
 /* Work out how much this section will move the dot point */
@@ -2505,6 +2601,8 @@ size_input_section (this_ptr, output_section_statement, fill, dot, relax)
 {
   lang_input_section_type *is = &((*this_ptr)->input_section);
   asection *i = is->section;
+  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
+                                               ldfile_output_machine); 
 
   if (is->ifile->just_syms_flag == false)
     {
@@ -2522,10 +2620,11 @@ size_input_section (this_ptr, output_section_statement, fill, dot, relax)
       /* Mark how big the output section must be to contain this now
         */
       if (i->_cooked_size != 0)
-       dot += i->_cooked_size;
+       dot += i->_cooked_size / opb;
       else
-       dot += i->_raw_size;
-      output_section_statement->bfd_section->_raw_size = dot - output_section_statement->bfd_section->vma;
+       dot += i->_raw_size / opb;
+      output_section_statement->bfd_section->_raw_size = 
+        (dot - output_section_statement->bfd_section->vma) * opb;
     }
   else
     {
@@ -2535,6 +2634,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.  */
@@ -2542,52 +2645,52 @@ static void
 lang_check_section_addresses ()
 {
   asection * s;
+  unsigned opb = bfd_octets_per_byte (output_bfd);
 
   /* 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) / opb - 1;
+         os_end   = os_start + bfd_section_size (output_bfd, os) / opb - 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
@@ -2595,6 +2698,43 @@ _("%X%P: section %s [%V -> %V] overlaps section %s [%V -> %V]\n"),
 
 static boolean relax_again;
 
+/* 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 address is
+   non-zero, in case the region is at the end of addressable memory and the
+   calculation wraps around.  */ 
+
+static void
+os_region_check (os, region, tree, base)
+  lang_output_section_statement_type *os;
+  struct memory_region_struct *region;
+  etree_type *tree;
+  bfd_vma base;
+{
+  if ((region->current < region->origin
+       || (region->current - region->origin > region->length))
+      && ((region->current != region->origin + region->length)
+           || base == 0))
+    {
+      if (tree != (etree_type *) NULL)
+        {
+          einfo (_("%X%P: address 0x%v of %B section %s is not within region %s\n"),
+                 region->current,
+                 os->bfd_section->owner,
+                 os->bfd_section->name,
+                 region->name);
+        }
+      else
+        {
+          einfo (_("%X%P: region %s is full (%B section %s)\n"),
+                 region->name,
+                 os->bfd_section->owner,
+                 os->bfd_section->name);
+        }
+      /* Reset the region pointer.  */
+      region->current = region->origin;
+    }
+}
+
 /* Set the sizes for all the output sections.  */
 
 bfd_vma
@@ -2606,6 +2746,9 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
      bfd_vma dot;
      boolean relax;
 {
+  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
+                                               ldfile_output_machine);
+
   /* Size up the sections from their constituent parts.  */
   for (; s != (lang_statement_union_type *) NULL; s = s->next)
     {
@@ -2719,54 +2862,66 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
            (void) lang_size_sections (os->children.head, os, &os->children.head,
                                       os->fill, dot, relax);
            
-           /* Ignore the size of the input sections, use the vma and size to
-              align against.  */
-
-           after = ALIGN_N (os->bfd_section->vma +
-                            os->bfd_section->_raw_size,
+            /* put the section within the requested block size, or align at
+               the block boundary */
+           after = ALIGN_N (os->bfd_section->vma
+                            + os->bfd_section->_raw_size / opb,
                             /* The coercion here is important, see ld.h.  */
                             (bfd_vma) os->block_value);
 
            if (bfd_is_abs_section (os->bfd_section))
              ASSERT (after == os->bfd_section->vma);
            else
-             os->bfd_section->_raw_size = after - os->bfd_section->vma;
-           dot = os->bfd_section->vma + os->bfd_section->_raw_size;
+             os->bfd_section->_raw_size = 
+                (after - os->bfd_section->vma) * opb;
+           dot = os->bfd_section->vma + os->bfd_section->_raw_size / opb;
            os->processed = true;
 
            /* 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.  */
+              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))
-                 {
-                   if (os->addr_tree != (etree_type *) NULL)
-                     {
-                       einfo (_("%X%P: address 0x%v of %B section %s is not within region %s\n"),
-                              os->region->current,
-                              os->bfd_section->owner,
-                              os->bfd_section->name,
-                              os->region->name);
-                     }
-                   else
-                     {
-                       einfo (_("%X%P: region %s is full (%B section %s)\n"),
-                              os->region->name,
-                              os->bfd_section->owner,
-                              os->bfd_section->name);
-                     }
-                   /* Reset the region pointer.  */
-                   os->region->current = os->region->origin;
-                 }
+               /* Make sure the new address is within the region.  */
+                os_region_check (os, os->region, os->addr_tree, 
+                                 os->bfd_section->vma);
+
+                /* if there's no load address specified, use the run region as
+                   the load region */
+                if (os->lma_region == NULL && os->load_base == NULL)
+                    os->lma_region = os->region;
+
+                if (os->lma_region != NULL)
+                  {
+                    if (os->load_base != NULL)
+                      {
+                        einfo (_("%X%P: use an absolute load address or a load memory region, not both\n"));
+                      }
+                    else
+                      {
+                        /* don't allocate twice */
+                        if (os->lma_region != os->region)
+                          {
+                            /* set load_base, which will be handled later */
+                            os->load_base = exp_intop (os->lma_region->current);
+                            os->lma_region->current += 
+                              os->bfd_section->_raw_size / opb;
+                            os_region_check (os, os->lma_region, NULL,
+                                             os->bfd_section->lma);
+                          }
+                      }
+                  }
              }
          }
          break;
@@ -2789,6 +2944,8 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
 
            switch (s->data_statement.type)
              {
+              default:
+                abort();
              case QUAD:
              case SQUAD:
                size = QUAD_SIZE;
@@ -2803,8 +2960,9 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
                size = BYTE_SIZE;
                break;
              }
-
-           dot += size;
+            if (size < opb)
+              size = opb;
+           dot += size / opb;
            output_section_statement->bfd_section->_raw_size += size;
            /* The output section gets contents, and then we inspect for
               any flags set in the input script which override any ALLOC.  */
@@ -2824,7 +2982,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
            s->reloc_statement.output_section =
              output_section_statement->bfd_section;
            size = bfd_get_reloc_size (s->reloc_statement.howto);
-           dot += size;
+           dot += size / opb;
            output_section_statement->bfd_section->_raw_size += size;
          }
          break;
@@ -2912,7 +3070,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
                    new->padding_statement.output_offset =
                      dot - output_section_statement->bfd_section->vma;
                    new->padding_statement.fill = fill;
-                   new->padding_statement.size = newdot - dot;
+                   new->padding_statement.size = (newdot - dot) * opb;
                    output_section_statement->bfd_section->_raw_size +=
                      new->padding_statement.size;
                  }
@@ -2930,7 +3088,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
             pass than it did at this point in the previous pass.  */
          s->padding_statement.output_offset =
            dot - output_section_statement->bfd_section->vma;
-         dot += s->padding_statement.size;
+         dot += s->padding_statement.size / opb;
          output_section_statement->bfd_section->_raw_size +=
            s->padding_statement.size;
          break;
@@ -2963,6 +3121,9 @@ lang_do_assignments (s, output_section_statement, fill, dot)
      fill_type fill;
      bfd_vma dot;
 {
+  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
+                                               ldfile_output_machine); 
+
   for (; s != (lang_statement_union_type *) NULL; s = s->next)
     {
       switch (s->header.type)
@@ -2984,7 +3145,8 @@ lang_do_assignments (s, output_section_statement, fill, dot)
                dot = os->bfd_section->vma;
                (void) lang_do_assignments (os->children.head, os,
                                            os->fill, dot);
-               dot = os->bfd_section->vma + os->bfd_section->_raw_size;
+               dot = os->bfd_section->vma + os->bfd_section->_raw_size / opb;
+
              }
            if (os->load_base) 
              {
@@ -3024,22 +3186,30 @@ lang_do_assignments (s, output_section_statement, fill, dot)
            if (value.valid_p == false)
              einfo (_("%F%P: invalid data statement\n"));
          }
-         switch (s->data_statement.type)
-           {
-           case QUAD:
-           case SQUAD:
-             dot += QUAD_SIZE;
-             break;
-           case LONG:
-             dot += LONG_SIZE;
-             break;
-           case SHORT:
-             dot += SHORT_SIZE;
-             break;
-           case BYTE:
-             dot += BYTE_SIZE;
-             break;
-           }
+          {
+            unsigned int size;
+            switch (s->data_statement.type)
+              {
+              default:
+                abort();
+              case QUAD:
+              case SQUAD:
+                size = QUAD_SIZE;
+                break;
+              case LONG:
+                size = LONG_SIZE;
+                break;
+              case SHORT:
+                size = SHORT_SIZE;
+                break;
+              case BYTE:
+                size = BYTE_SIZE;
+                break;
+              }
+            if (size < opb)
+              size = opb;
+            dot += size / opb;
+          }
          break;
 
        case lang_reloc_statement_enum:
@@ -3053,7 +3223,7 @@ lang_do_assignments (s, output_section_statement, fill, dot)
            if (value.valid_p == false)
              einfo (_("%F%P: invalid reloc statement\n"));
          }
-         dot += bfd_get_reloc_size (s->reloc_statement.howto);
+         dot += bfd_get_reloc_size (s->reloc_statement.howto) / opb;
          break;
 
        case lang_input_section_enum:
@@ -3061,9 +3231,9 @@ lang_do_assignments (s, output_section_statement, fill, dot)
            asection *in = s->input_section.section;
 
            if (in->_cooked_size != 0)
-             dot += in->_cooked_size;
+             dot += in->_cooked_size / opb;
            else
-             dot += in->_raw_size;
+             dot += in->_raw_size / opb;
          }
          break;
 
@@ -3083,7 +3253,7 @@ lang_do_assignments (s, output_section_statement, fill, dot)
 
          break;
        case lang_padding_statement_enum:
-         dot += s->padding_statement.size;
+         dot += s->padding_statement.size / opb;
          break;
 
        case lang_group_statement_enum:
@@ -3141,11 +3311,13 @@ lang_set_startof ()
       h = bfd_link_hash_lookup (link_info.hash, buf, false, false, true);
       if (h != NULL && h->type == bfd_link_hash_undefined)
        {
+          unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
+                                                       ldfile_output_machine);
          h->type = bfd_link_hash_defined;
          if (s->_cooked_size != 0)
-           h->u.def.value = s->_cooked_size;
+           h->u.def.value = s->_cooked_size / opb;
          else
-           h->u.def.value = s->_raw_size;
+           h->u.def.value = s->_raw_size / opb;
          h->u.def.section = bfd_abs_section_ptr;
        }
 
@@ -3322,6 +3494,8 @@ lang_one_common (h, info)
   unsigned int power_of_two;
   bfd_vma size;
   asection *section;
+  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, 
+                                               ldfile_output_machine); 
 
   if (h->type != bfd_link_hash_common)
     return true;
@@ -3336,8 +3510,8 @@ lang_one_common (h, info)
   section = h->u.c.p->section;
 
   /* Increase the size of the section.  */
-  section->_cooked_size = ALIGN_N (section->_cooked_size,
-                                  (bfd_size_type) (1 << power_of_two));
+  section->_cooked_size = ALIGN_N ((section->_cooked_size + opb - 1) / opb,
+                                  (bfd_size_type) (1 << power_of_two)) * opb;
 
   /* Adjust the alignment if necessary.  */
   if (power_of_two > section->alignment_power)
@@ -3641,7 +3815,7 @@ topower (x)
   return 0;
 }
 
-void
+lang_output_section_statement_type *
 lang_enter_output_section_statement (output_section_statement_name,
                                     address_exp, sectype, block_value,
                                     align, subalign, ebase)
@@ -3689,6 +3863,7 @@ lang_enter_output_section_statement (output_section_statement_name,
                     "section alignment", 0));
 
   os->load_base = ebase;
+  return os;
 }
 
 
@@ -3826,12 +4001,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
@@ -3941,13 +4120,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);
@@ -3965,7 +4144,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);
 }
 
@@ -4119,13 +4298,22 @@ lang_float (maybe)
 }
 
 void
-lang_leave_output_section_statement (fill, memspec, phdrs)
+lang_leave_output_section_statement (fill, memspec, phdrs, lma_memspec)
      bfd_vma fill;
      const char *memspec;
      struct lang_output_section_phdr_list *phdrs;
+     const char *lma_memspec;
 {
   current_section->fill = fill;
   current_section->region = lang_memory_region_lookup (memspec);
+  if (strcmp (lma_memspec, "*default*") != 0)
+    {
+      current_section->lma_region = lang_memory_region_lookup (lma_memspec);
+      /* if no runtime region has been given, but the load region has been,
+         use the load region */
+      if (strcmp (memspec, "*default*") == 0)
+        current_section->region = lang_memory_region_lookup (lma_memspec);
+    }
   current_section->phdrs = phdrs;
   stat_ptr = &statement_list;
 }
@@ -4193,7 +4381,8 @@ lang_abs_symbol_at_end_of (secname, name)
        h->u.def.value = 0;
       else
        h->u.def.value = (bfd_get_section_vma (output_bfd, sec)
-                         + bfd_section_size (output_bfd, sec));
+                         + bfd_section_size (output_bfd, sec) /
+                          bfd_octets_per_byte (output_bfd));
 
       h->u.def.section = bfd_abs_section_ptr;
     }
@@ -4503,7 +4692,8 @@ lang_leave_overlay_section (fill, phdrs)
 
   name = current_section->name;
 
-  lang_leave_output_section_statement (fill, "*default*", phdrs);
+  lang_leave_output_section_statement (fill, "*default*", 
+                                       phdrs, "*default*");
 
   /* Define the magic symbols.  */
 
@@ -4533,12 +4723,14 @@ lang_leave_overlay_section (fill, phdrs)
    looks through all the sections in the overlay and sets them.  */
 
 void
-lang_leave_overlay (fill, memspec, phdrs)
+lang_leave_overlay (fill, memspec, phdrs, lma_memspec)
      bfd_vma fill;
      const char *memspec;
      struct lang_output_section_phdr_list *phdrs;
+     const char *lma_memspec;
 {
   lang_memory_region_type *region;
+  lang_memory_region_type *lma_region;
   struct overlay_list *l;
   struct lang_nocrossref *nocrossref;
 
@@ -4547,6 +4739,11 @@ lang_leave_overlay (fill, memspec, phdrs)
   else
     region = lang_memory_region_lookup (memspec);
 
+  if (lma_memspec == NULL)
+    lma_region = NULL;
+  else
+    lma_region = lang_memory_region_lookup (lma_memspec);
+
   nocrossref = NULL;
 
   l = overlay_list;
@@ -4558,6 +4755,8 @@ lang_leave_overlay (fill, memspec, phdrs)
        l->os->fill = fill;
       if (region != NULL && l->os->region == NULL)
        l->os->region = region;
+      if (lma_region != NULL && l->os->lma_region == NULL)
+        l->os->lma_region = lma_region;
       if (phdrs != NULL && l->os->phdrs == NULL)
        l->os->phdrs = phdrs;
 
This page took 0.039696 seconds and 4 git commands to generate.