* configure.tgt: Remove *-*-aout, *-*-coff, and *-*-netware.
[deliverable/binutils-gdb.git] / ld / ldlang.c
index 56a00540103c06d0fa7af70e12243c49a64712d6..d40ff07a5b339dcd89422dada5e11e589f84d6f6 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)
@@ -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,15 +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
+   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 +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.  */
@@ -919,12 +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
-         && (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 +1002,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);
 }
 \f
 /* The wild routines.
@@ -2105,7 +2169,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 ();
@@ -2129,7 +2194,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)
@@ -2151,7 +2216,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;
        }
     }
 }
@@ -2171,6 +2236,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 ();
@@ -2215,7 +2282,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
@@ -2239,6 +2307,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 ();
@@ -2260,7 +2330,7 @@ print_reloc_statement (reloc)
 
   print_nl ();
 
-  print_dot = addr + size;
+  print_dot = addr + size / opb;
 }  
 
 static void
@@ -2269,6 +2339,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*");
 
@@ -2289,7 +2361,7 @@ print_padding_statement (s)
 
   print_nl ();
 
-  print_dot = addr + s->size;
+  print_dot = addr + s->size / opb;
 }
 
 static void
@@ -2301,9 +2373,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 ("*");
@@ -2478,6 +2556,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)
@@ -2494,7 +2574,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;
     }
 
 
@@ -2503,9 +2583,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 */
@@ -2519,6 +2599,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)
     {
@@ -2536,10 +2618,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
     {
@@ -2549,6 +2632,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.  */
@@ -2556,52 +2643,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
@@ -2609,6 +2696,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
@@ -2620,6 +2744,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)
     {
@@ -2733,62 +2860,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 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)
-                     {
-                       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;
@@ -2811,6 +2942,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;
@@ -2825,8 +2958,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.  */
@@ -2846,7 +2980,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;
@@ -2934,7 +3068,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;
                  }
@@ -2952,7 +3086,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;
@@ -2985,6 +3119,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)
@@ -3006,7 +3143,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) 
              {
@@ -3046,22 +3184,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:
@@ -3075,7 +3221,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:
@@ -3083,9 +3229,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;
 
@@ -3105,7 +3251,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:
@@ -3163,11 +3309,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;
        }
 
@@ -3344,6 +3492,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;
@@ -3358,8 +3508,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)
@@ -3848,12 +3998,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
@@ -3963,13 +4117,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);
@@ -3987,7 +4141,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);
 }
 
@@ -4141,13 +4295,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;
 }
@@ -4215,7 +4378,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;
     }
@@ -4525,7 +4689,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.  */
 
@@ -4555,12 +4720,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;
 
@@ -4569,6 +4736,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;
@@ -4580,6 +4752,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.033783 seconds and 4 git commands to generate.