* config.bfd (sh*eb-*-linux*, sh*-*-linux*): Add the alternative
[deliverable/binutils-gdb.git] / ld / ldlang.c
index 413ccf818d39de3009b143706a8603d84fbdbe28..8ebd1bd2eaad389399db5d6089b99263e30a447f 100644 (file)
@@ -3,22 +3,22 @@
    2001, 2002
    Free Software Foundation, Inc.
 
-This file is part of GLD, the Gnu Linker.
+   This file is part of GLD, the Gnu Linker.
 
-GLD is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+   GLD is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
 
-GLD is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   GLD is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with GLD; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with GLD; see the file COPYING.  If not, write to the Free
+   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
 
 #include "bfd.h"
 #include "sysdep.h"
@@ -40,6 +40,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "fnmatch.h"
 #include "demangle.h"
 
+#ifndef offsetof
+#define offsetof(TYPE,MEMBER) ((size_t)&(((TYPE*)0)->MEMBER))
+#endif
+
 /* FORWARDS */
 static lang_statement_union_type *new_statement
   PARAMS ((enum statement_enum, size_t, lang_statement_list_type *));
@@ -92,10 +96,12 @@ static bfd *open_output PARAMS ((const char *));
 static void ldlang_open_output PARAMS ((lang_statement_union_type *));
 static void open_input_bfds PARAMS ((lang_statement_union_type *, boolean));
 static void lang_reasonable_defaults PARAMS ((void));
+static void insert_undefined PARAMS ((const char *));
 static void lang_place_undefineds PARAMS ((void));
 static void map_input_to_output_sections
   PARAMS ((lang_statement_union_type *, const char *,
           lang_output_section_statement_type *));
+static void strip_excluded_output_sections PARAMS ((void));
 static void print_output_section_statement
   PARAMS ((lang_output_section_statement_type *));
 static void print_assignment
@@ -135,6 +141,9 @@ static void lang_set_startof PARAMS ((void));
 static void gc_section_callback
   PARAMS ((lang_wild_statement_type *, struct wildcard_list *, asection *,
           lang_input_statement_type *, PTR));
+static void lang_get_regions PARAMS ((struct memory_region_struct **,
+                                     struct memory_region_struct **,
+                                     const char *, const char *, int));
 static void lang_record_phdrs PARAMS ((void));
 static void lang_gc_wild PARAMS ((lang_wild_statement_type *));
 static void lang_gc_sections_1 PARAMS ((lang_statement_union_type *));
@@ -180,7 +189,7 @@ 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;
+struct bfd_sym_chain entry_symbol = { NULL, NULL };
 const char *entry_section = ".text";
 boolean entry_from_cmdline;
 boolean lang_has_input_file = false;
@@ -616,6 +625,10 @@ lang_memory_region_lookup (name)
 {
   lang_memory_region_type *p;
 
+  /* NAME is NULL for LMA memspecs if no region was specified.  */
+  if (name == NULL)
+    return NULL;
+
   for (p = lang_memory_region_list;
        p != (lang_memory_region_type *) NULL;
        p = p->next)
@@ -737,6 +750,7 @@ lang_output_section_statement_lookup (name)
       lookup->subsection_alignment = -1;
       lookup->section_alignment = -1;
       lookup->load_base = (union etree_union *) NULL;
+      lookup->update_dot_tree = NULL;
       lookup->phdrs = NULL;
 
       lang_statement_append (&lang_output_section_statement,
@@ -953,8 +967,7 @@ section_already_linked (abfd, sec, data)
      discard all sections.  */
   if (entry->just_syms_flag)
     {
-      sec->output_section = bfd_abs_section_ptr;
-      sec->output_offset = sec->vma;
+      bfd_link_just_syms (sec, &link_info);
       return;
     }
 
@@ -977,7 +990,7 @@ section_already_linked (abfd, sec, data)
      of having link once sections in the first place.
 
      Also, not merging link once sections in a relocatable link
-     causes trouble for MIPS ELF, which relies in link once semantics
+     causes trouble for MIPS ELF, which relies on link once semantics
      to handle the .reginfo section correctly.  */
 
   name = bfd_get_section_name (abfd, sec);
@@ -1031,6 +1044,9 @@ section_already_linked (abfd, sec, data)
             section.  */
          sec->output_section = bfd_abs_section_ptr;
 
+         if (flags & SEC_GROUP)
+           bfd_discard_group (abfd, sec);
+
          return;
        }
     }
@@ -1205,6 +1221,10 @@ lang_add_section (ptr, section, output, file)
          flags &= ~ (SEC_MERGE | SEC_STRINGS);
        }
 
+      /* For now make .tbss normal section.  */
+      if ((flags & SEC_THREAD_LOCAL) && ! link_info.relocateable)
+       flags |= SEC_LOAD;
+
       section->output_section->flags |= flags;
 
       if (flags & SEC_MERGE)
@@ -1473,7 +1493,7 @@ load_symbols (entry, place)
       bfd_error_type err;
       lang_statement_list_type *hold;
       boolean bad_load = true;
-      
+
       err = bfd_get_error ();
 
       /* See if the emulation has some special knowledge.  */
@@ -1495,7 +1515,7 @@ load_symbols (entry, place)
          einfo (_("%F%B: file not recognized: %E\n"), entry->the_bfd);
       else
        bad_load = false;
-      
+
       bfd_close (entry->the_bfd);
       entry->the_bfd = NULL;
 
@@ -1536,7 +1556,7 @@ load_symbols (entry, place)
     case bfd_archive:
       if (entry->whole_archive)
        {
-         bfd * member = NULL;
+         bfd *member = NULL;
          boolean loaded = true;
 
          for (;;)
@@ -1545,7 +1565,7 @@ load_symbols (entry, place)
 
              if (member == NULL)
                break;
-             
+
              if (! bfd_check_format (member, bfd_object))
                {
                  einfo (_("%F%B: member %B in archive is not an object\n"),
@@ -1601,7 +1621,7 @@ wild (s, target, output)
       if (sec->spec.name != NULL && strcmp (sec->spec.name, "COMMON") == 0)
        {
          /* Remember the section that common is going to in case we
-            later get something which doesn't know where to put it.  */ 
+            later get something which doesn't know where to put it.  */
          default_common_section = output;
        }
     }
@@ -1767,6 +1787,29 @@ get_first_input_target ()
   return target;
 }
 
+const char *
+lang_get_output_target ()
+{
+  const char *target;
+
+  /* Has the user told us which output format to use?  */
+  if (output_target != (char *) NULL)
+    return output_target;
+
+  /* No - has the current target been set to something other than
+     the default?  */
+  if (current_target != default_target)
+    return current_target;
+
+  /* No - can we determine the format of the first input file?  */
+  target = get_first_input_target ();
+  if (target != NULL)
+    return target;
+
+  /* Failed - use the default output target.  */
+  return default_target;
+}
+
 /* Open the output file.  */
 
 static bfd *
@@ -1775,24 +1818,7 @@ open_output (name)
 {
   bfd *output;
 
-  /* Has the user told us which output format to use?  */
-  if (output_target == (char *) NULL)
-    {
-      /* No - has the current target been set to something other than
-         the default?  */
-      if (current_target != default_target)
-       output_target = current_target;
-
-      /* No - can we determine the format of the first input file?  */
-      else
-       {
-         output_target = get_first_input_target ();
-
-         /* Failed - use the default output target.  */
-         if (output_target == NULL)
-           output_target = default_target;
-       }
-    }
+  output_target = lang_get_output_target ();
 
   /* Has the user requested a particular endianness on the command
      line?  */
@@ -2010,14 +2036,14 @@ lang_reasonable_defaults ()
 }
 
 /* Add the supplied name to the symbol table as an undefined reference.
-   Remove items from the chain as we open input bfds.  */
-typedef struct ldlang_undef_chain_list
-{
-  struct ldlang_undef_chain_list *next;
-  char *name;
-}                       ldlang_undef_chain_list_type;
+   This is a two step process as the symbol table doesn't even exist at
+   the time the ld command line is processed.  First we put the name
+   on a list, then, once the output file has been opened, transfer the
+   name to the symbol table.  */
+
+typedef struct bfd_sym_chain ldlang_undef_chain_list_type;
 
-static ldlang_undef_chain_list_type *ldlang_undef_chain_list_head;
+#define ldlang_undef_chain_list_head entry_symbol.next
 
 void
 ldlang_add_undef (name)
@@ -2031,6 +2057,28 @@ ldlang_add_undef (name)
   ldlang_undef_chain_list_head = new;
 
   new->name = xstrdup (name);
+
+  if (output_bfd != NULL)
+    insert_undefined (new->name);
+}
+
+/* Insert NAME as undefined in the symbol table.  */
+
+static void
+insert_undefined (name)
+     const char *name;
+{
+  struct bfd_link_hash_entry *h;
+
+  h = bfd_link_hash_lookup (link_info.hash, name, true, false, true);
+  if (h == (struct bfd_link_hash_entry *) NULL)
+    einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
+  if (h->type == bfd_link_hash_new)
+    {
+      h->type = bfd_link_hash_undefined;
+      h->u.undef.abfd = NULL;
+      bfd_link_add_undef (link_info.hash, h);
+    }
 }
 
 /* Run through the list of undefineds created above and place them
@@ -2046,17 +2094,7 @@ lang_place_undefineds ()
        ptr != (ldlang_undef_chain_list_type *) NULL;
        ptr = ptr->next)
     {
-      struct bfd_link_hash_entry *h;
-
-      h = bfd_link_hash_lookup (link_info.hash, ptr->name, true, false, true);
-      if (h == (struct bfd_link_hash_entry *) NULL)
-       einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
-      if (h->type == bfd_link_hash_new)
-       {
-         h->type = bfd_link_hash_undefined;
-         h->u.undef.abfd = NULL;
-         bfd_link_add_undef (link_info.hash, h);
-       }
+      insert_undefined (ptr->name);
     }
 }
 
@@ -2134,6 +2172,41 @@ map_input_to_output_sections (s, target, output_section_statement)
     }
 }
 
+/* An output section might have been removed after its statement was
+   added.  For example, ldemul_before_allocation can remove dynamic
+   sections if they turn out to be not needed.  Clean them up here.  */
+
+static void
+strip_excluded_output_sections ()
+{
+  lang_statement_union_type *u;
+
+  for (u = lang_output_section_statement.head;
+       u != NULL;
+       u = u->output_section_statement.next)
+    {
+      lang_output_section_statement_type *os;
+      asection *s;
+
+      os = &u->output_section_statement;
+      s = os->bfd_section;
+      if (s != NULL && (s->flags & SEC_EXCLUDE) != 0)
+       {
+         asection **p;
+
+         os->bfd_section = NULL;
+
+         for (p = &output_bfd->sections; *p; p = &(*p)->next)
+           if (*p == s)
+             {
+               bfd_section_list_remove (output_bfd, p);
+               output_bfd->section_count--;
+               break;
+             }
+       }
+    }
+}
+
 static void
 print_output_section_statement (output_section_statement)
      lang_output_section_statement_type *output_section_statement;
@@ -2194,7 +2267,17 @@ print_assignment (assignment, output_section)
   result = exp_fold_tree (assignment->exp->assign.src, output_section,
                          lang_final_phase_enum, print_dot, &print_dot);
   if (result.valid_p)
-    minfo ("0x%V", result.value + result.section->bfd_section->vma);
+    {
+      const char *dst;
+      bfd_vma value;
+
+      value = result.value + result.section->bfd_section->vma;
+      dst = assignment->exp->assign.dst;
+
+      minfo ("0x%V", value);
+      if (dst[0] == '.' && dst[1] == 0)
+       print_dot = value;
+    }
   else
     {
       minfo ("*undef*   ");
@@ -2488,10 +2571,10 @@ print_wild_statement (w, os)
       if (sec->spec.exclude_name_list != NULL)
        {
          name_list *tmp;
-         minfo ("EXCLUDE_FILE ( %s", sec->spec.exclude_name_list->name);
+         minfo ("EXCLUDE_FILE(%s", sec->spec.exclude_name_list->name);
          for (tmp = sec->spec.exclude_name_list->next; tmp; tmp = tmp->next)
-           minfo (", %s", tmp->name);
-         minfo (")");
+           minfo (" %s", tmp->name);
+         minfo (") ");
        }
       if (sec->spec.name != NULL)
        minfo ("%s", sec->spec.name);
@@ -2499,6 +2582,8 @@ print_wild_statement (w, os)
        minfo ("*");
       if (sec->spec.sorted)
        minfo (")");
+      if (sec->next)
+       minfo (" ");
     }
   minfo (")");
 
@@ -2815,23 +2900,23 @@ os_region_check (os, region, tree, base)
   if ((region->current < region->origin
        || (region->current - region->origin > region->length))
       && ((region->current != region->origin + region->length)
-           || base == 0))
+         || 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);
-        }
+       {
+         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);
-        }
+       {
+         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;
     }
@@ -2913,6 +2998,8 @@ lang_size_sections_1 (s, output_section_statement, prev, fill, dot, relax)
                       defined, issue a warning.  */
                    if ((bfd_get_section_flags (output_bfd, os->bfd_section)
                         & (SEC_ALLOC | SEC_LOAD)) != 0
+                       && (bfd_get_section_flags (output_bfd, os->bfd_section)
+                           & SEC_NEVER_LOAD) == 0
                        && ! link_info.relocateable
                        && strcmp (os->region->name, "*default*") == 0
                        && lang_memory_region_list != NULL
@@ -2970,19 +3057,27 @@ lang_size_sections_1 (s, output_section_statement, prev, fill, dot, relax)
 
            /* Put the section within the requested block size, or
               align at the block boundary.  */
-           after = ALIGN_N (os->bfd_section->vma
+           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 if ((os->bfd_section->flags & SEC_HAS_CONTENTS) == 0
+                    && (os->bfd_section->flags & SEC_THREAD_LOCAL)
+                    && ! link_info.relocateable)
+             os->bfd_section->_raw_size = 0;
            else
              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;
 
+           if (os->update_dot_tree != 0)
+             exp_fold_tree (os->update_dot_tree, abs_output_section,
+                            lang_allocating_phase_enum, dot, &dot);
+
            /* 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
@@ -3008,26 +3103,14 @@ lang_size_sections_1 (s, output_section_statement, prev, fill, dot, relax)
                if (os->lma_region == NULL && os->load_base == NULL)
                  os->lma_region = os->region;
 
-               if (os->lma_region != NULL)
+               if (os->lma_region != NULL && os->lma_region != os->region)
                  {
-                   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);
-                         }
-                     }
+                   /* 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);
                  }
              }
          }
@@ -3324,8 +3407,8 @@ lang_do_assignments (s, output_section_statement, fill, dot)
            if (value.valid_p == false)
              einfo (_("%F%P: invalid data statement\n"));
          }
-          {
-            unsigned int size;
+         {
+           unsigned int size;
            switch (s->data_statement.type)
              {
              default:
@@ -3449,9 +3532,9 @@ 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;
+         unsigned opb;
 
-          opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
+         opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
                                               ldfile_output_machine);
          h->type = bfd_link_hash_defined;
          if (s->_cooked_size != 0)
@@ -3476,15 +3559,16 @@ lang_finish ()
   else
     warn = true;
 
-  if (entry_symbol == (char *) NULL)
+  if (entry_symbol.name == (const char *) NULL)
     {
       /* No entry has been specified.  Look for start, but don't warn
         if we don't find it.  */
-      entry_symbol = "start";
+      entry_symbol.name = "start";
       warn = false;
     }
 
-  h = bfd_link_hash_lookup (link_info.hash, entry_symbol, false, false, true);
+  h = bfd_link_hash_lookup (link_info.hash, entry_symbol.name,
+                           false, false, true);
   if (h != (struct bfd_link_hash_entry *) NULL
       && (h->type == bfd_link_hash_defined
          || h->type == bfd_link_hash_defweak)
@@ -3497,7 +3581,7 @@ lang_finish ()
                                    h->u.def.section->output_section)
             + h->u.def.section->output_offset);
       if (! bfd_set_start_address (output_bfd, val))
-       einfo (_("%P%F:%s: can't set start address\n"), entry_symbol);
+       einfo (_("%P%F:%s: can't set start address\n"), entry_symbol.name);
     }
   else
     {
@@ -3506,7 +3590,7 @@ lang_finish ()
 
       /* We couldn't find the entry symbol.  Try parsing it as a
          number.  */
-      val = bfd_scan_vma (entry_symbol, &send, 0);
+      val = bfd_scan_vma (entry_symbol.name, &send, 0);
       if (*send == '\0')
        {
          if (! bfd_set_start_address (output_bfd, val))
@@ -3523,7 +3607,8 @@ lang_finish ()
            {
              if (warn)
                einfo (_("%P: warning: cannot find entry symbol %s; defaulting to %V\n"),
-                      entry_symbol, bfd_get_section_vma (output_bfd, ts));
+                      entry_symbol.name,
+                      bfd_get_section_vma (output_bfd, ts));
              if (! bfd_set_start_address (output_bfd,
                                           bfd_get_section_vma (output_bfd,
                                                                ts)))
@@ -3533,7 +3618,7 @@ lang_finish ()
            {
              if (warn)
                einfo (_("%P: warning: cannot find entry symbol %s; not setting start address\n"),
-                      entry_symbol);
+                      entry_symbol.name);
            }
        }
     }
@@ -3569,8 +3654,25 @@ lang_check ()
        file = file->input_statement.next)
     {
       input_bfd = file->input_statement.the_bfd;
-      compatible = bfd_arch_get_compatible (input_bfd,
-                                           output_bfd);
+      compatible = bfd_arch_get_compatible (input_bfd, output_bfd);
+
+      /* In general it is not possible to perform a relocatable
+        link between differing object formats when the input
+        file has relocations, because the relocations in the
+        input format may not have equivalent representations in
+        the output format (and besides BFD does not translate
+        relocs for other link purposes than a final link).  */
+      if ((link_info.relocateable || link_info.emitrelocations)
+         && (compatible == NULL
+             || bfd_get_flavour (input_bfd) != bfd_get_flavour (output_bfd))
+         && (bfd_get_file_flags (input_bfd) & HAS_RELOC) != 0)
+       {
+         einfo (_("%P%F: Relocatable linking with relocations from format %s (%B) to format %s (%B) is not supported\n"),
+                bfd_get_target (input_bfd), input_bfd,
+                bfd_get_target (output_bfd), output_bfd);
+         /* einfo with %F exits.  */
+       }
+
       if (compatible == NULL)
        {
          if (command_line.warn_mismatch)
@@ -3578,22 +3680,10 @@ lang_check ()
                   bfd_printable_name (input_bfd), input_bfd,
                   bfd_printable_name (output_bfd));
        }
-      else if (link_info.relocateable
-              /* In general it is not possible to perform a relocatable
-                 link between differing object formats when the input
-                 file has relocations, because the relocations in the
-                 input format may not have equivalent representations in
-                 the output format (and besides BFD does not translate
-                 relocs for other link purposes than a final link).  */
-              && bfd_get_flavour (input_bfd) != bfd_get_flavour (output_bfd)
-              && (bfd_get_file_flags (input_bfd) & HAS_RELOC) != 0)
-       einfo (_("%P%F: Relocatable linking with relocations from format %s (%B) to format %s (%B) is not supported\n"),
-              bfd_get_target (input_bfd), input_bfd,
-              bfd_get_target (output_bfd), output_bfd);
       else if (bfd_count_sections (input_bfd))
        {
          /* If the input bfd has no contents, it shouldn't set the
-            private data of the output bfd. */
+            private data of the output bfd.  */
 
          bfd_error_handler_type pfn = NULL;
 
@@ -3667,8 +3757,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 + opb - 1) / opb,
-                                  (bfd_size_type) (1 << power_of_two)) * opb;
+  section->_cooked_size = align_n ((section->_cooked_size + opb - 1) / opb,
+                                  (bfd_vma) 1 << power_of_two) * opb;
 
   /* Adjust the alignment if necessary.  */
   if (power_of_two > section->alignment_power)
@@ -3759,11 +3849,7 @@ lang_place_orphans ()
 
              if (file->just_syms_flag)
                {
-                 /* We are only retrieving symbol values from this
-                     file.  We want the symbols to act as though the
-                     values in the file are absolute.  */
-                 s->output_section = bfd_abs_section_ptr;
-                 s->output_offset = s->vma;
+                 abort ();
                }
              else if (strcmp (s->name, "COMMON") == 0)
                {
@@ -4098,25 +4184,16 @@ static void
 lang_gc_sections ()
 {
   struct bfd_link_hash_entry *h;
-  ldlang_undef_chain_list_type *ulist, fake_list_start;
+  ldlang_undef_chain_list_type *ulist;
 
   /* Keep all sections so marked in the link script.  */
 
   lang_gc_sections_1 (statement_list.head);
 
-  /* Keep all sections containing symbols undefined on the command-line.
-     Handle the entry symbol at the same time.  */
-
-  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
-    ulist = ldlang_undef_chain_list_head;
+  /* Keep all sections containing symbols undefined on the command-line,
+     and the section containing the entry symbol.  */
 
-  for (; ulist; ulist = ulist->next)
+  for (ulist = link_info.gc_sym_list; ulist; ulist = ulist->next)
     {
       h = bfd_link_hash_lookup (link_info.hash, ulist->name,
                                false, false, false);
@@ -4153,6 +4230,10 @@ lang_process ()
   current_target = default_target;
   open_input_bfds (statement_list.head, false);
 
+  link_info.gc_sym_list = &entry_symbol;
+  if (entry_symbol.name == NULL)
+    link_info.gc_sym_list = ldlang_undef_chain_list_head;
+
   ldemul_after_open ();
 
   already_linked_table_free ();
@@ -4193,8 +4274,27 @@ lang_process ()
   /* Find any sections not attached explicitly and handle them.  */
   lang_place_orphans ();
 
+  if (! link_info.relocateable)
+    {
+      /* Look for a text section and set the readonly attribute in it.  */
+      asection *found = bfd_get_section_by_name (output_bfd, ".text");
+
+      if (found != (asection *) NULL)
+       {
+         if (config.text_read_only)
+           found->flags |= SEC_READONLY;
+         else
+           found->flags &= ~SEC_READONLY;
+       }
+    }
+
+  /* Do anything special before sizing sections.  This is where ELF
+     and other back-ends size dynamic sections.  */
   ldemul_before_allocation ();
 
+  if (!link_info.relocateable)
+    strip_excluded_output_sections ();
+
   /* We must record the program headers before we try to fix the
      section positions, since they will affect SIZEOF_HEADERS.  */
   lang_record_phdrs ();
@@ -4227,10 +4327,10 @@ lang_process ()
                               (fill_type *) 0, (bfd_vma) 0);
 
          /* Perform another relax pass - this time we know where the
-            globals are, so can make better guess.  */
+            globals are, so can make better guess.  */
          lang_size_sections (statement_list.head,
                              abs_output_section,
-                             &(statement_list.head), 0, (bfd_vma) 0,
+                             &statement_list.head, 0, (bfd_vma) 0,
                              &relax_again);
        }
       while (relax_again);
@@ -4327,11 +4427,11 @@ lang_add_entry (name, cmdline)
      const char *name;
      boolean cmdline;
 {
-  if (entry_symbol == NULL
+  if (entry_symbol.name == NULL
       || cmdline
       || ! entry_from_cmdline)
     {
-      entry_symbol = name;
+      entry_symbol.name = name;
       entry_from_cmdline = cmdline;
     }
 }
@@ -4455,6 +4555,36 @@ lang_float (maybe)
   lang_float_flag = maybe;
 }
 
+
+/* Work out the load- and run-time regions from a script statement, and
+   store them in *LMA_REGION and *REGION respectively.
+
+   MEMSPEC is the name of the run-time region, or "*default*" if the
+   statement didn't specify one.  LMA_MEMSPEC is the name of the
+   load-time region, or null if the statement didn't specify one.
+   HAVE_LMA_P is true if the statement had an explicit load address.
+
+   It is an error to specify both a load region and a load address.  */
+
+static void
+lang_get_regions (region, lma_region, memspec, lma_memspec, have_lma_p)
+     struct memory_region_struct **region, **lma_region;
+     const char *memspec, *lma_memspec;
+     int have_lma_p;
+{
+  *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 (lma_memspec != 0 && strcmp (memspec, "*default*") == 0)
+    *region = *lma_region;
+  else
+    *region = lang_memory_region_lookup (memspec);
+
+  if (have_lma_p && lma_memspec != 0)
+    einfo (_("%X%P:%S: section has both a load address and a load region\n"));
+}
+
 void
 lang_leave_output_section_statement (fill, memspec, phdrs, lma_memspec)
      fill_type *fill;
@@ -4462,16 +4592,11 @@ lang_leave_output_section_statement (fill, memspec, phdrs, lma_memspec)
      struct lang_output_section_phdr_list *phdrs;
      const char *lma_memspec;
 {
+  lang_get_regions (&current_section->region,
+                   &current_section->lma_region,
+                   memspec, lma_memspec,
+                   current_section->load_base != 0);
   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;
 }
@@ -4753,12 +4878,6 @@ lang_add_nocrossref (l)
 /* The overlay virtual address.  */
 static etree_type *overlay_vma;
 
-/* The overlay load address.  */
-static etree_type *overlay_lma;
-
-/* Whether nocrossrefs is set for this overlay.  */
-static int overlay_nocrossrefs;
-
 /* An expression for the maximum section size seen so far.  */
 static etree_type *overlay_max;
 
@@ -4774,24 +4893,18 @@ static struct overlay_list *overlay_list;
 /* Start handling an overlay.  */
 
 void
-lang_enter_overlay (vma_expr, lma_expr, nocrossrefs)
+lang_enter_overlay (vma_expr)
      etree_type *vma_expr;
-     etree_type *lma_expr;
-     int nocrossrefs;
 {
   /* The grammar should prevent nested overlays from occurring.  */
-  ASSERT (overlay_vma == NULL
-         && overlay_lma == NULL
-         && overlay_list == NULL
-         && overlay_max == NULL);
+  ASSERT (overlay_vma == NULL && overlay_max == NULL);
 
   overlay_vma = vma_expr;
-  overlay_lma = lma_expr;
-  overlay_nocrossrefs = nocrossrefs;
 }
 
 /* Start a section in an overlay.  We handle this by calling
-   lang_enter_output_section_statement with the correct VMA and LMA.  */
+   lang_enter_output_section_statement with the correct VMA.
+   lang_leave_overlay sets up the LMA and memory regions.  */
 
 void
 lang_enter_overlay_section (name)
@@ -4801,16 +4914,13 @@ lang_enter_overlay_section (name)
   etree_type *size;
 
   lang_enter_output_section_statement (name, overlay_vma, normal_section,
-                                      0, 0, 0, overlay_lma);
+                                      0, 0, 0, 0);
 
-  /* If this is the first section, then base the VMA and LMA of future
+  /* If this is the first section, then base the VMA of future
      sections on this one.  This will work correctly even if `.' is
      used in the addresses.  */
   if (overlay_list == NULL)
-    {
-      overlay_vma = exp_nameop (ADDR, name);
-      overlay_lma = exp_nameop (LOADADDR, name);
-    }
+    overlay_vma = exp_nameop (ADDR, name);
 
   /* Remember the section.  */
   n = (struct overlay_list *) xmalloc (sizeof *n);
@@ -4820,9 +4930,6 @@ lang_enter_overlay_section (name)
 
   size = exp_nameop (SIZEOF, name);
 
-  /* Adjust the LMA for the next section.  */
-  overlay_lma = exp_binop ('+', overlay_lma, size);
-
   /* Arrange to work out the maximum section end address.  */
   if (overlay_max == NULL)
     overlay_max = size;
@@ -4845,8 +4952,10 @@ lang_leave_overlay_section (fill, phdrs)
 
   name = current_section->name;
 
-  lang_leave_output_section_statement (fill, "*default*",
-                                       phdrs, "*default*");
+  /* For now, assume that "*default*" is the run-time memory region and
+     that no load-time region has been specified.  It doesn't really
+     matter what we say here, since lang_leave_overlay will override it.  */
+  lang_leave_output_section_statement (fill, "*default*", phdrs, 0);
 
   /* Define the magic symbols.  */
 
@@ -4876,32 +4985,31 @@ lang_leave_overlay_section (fill, phdrs)
    looks through all the sections in the overlay and sets them.  */
 
 void
-lang_leave_overlay (fill, memspec, phdrs, lma_memspec)
+lang_leave_overlay (lma_expr, nocrossrefs, fill, memspec, phdrs, lma_memspec)
+     etree_type *lma_expr;
+     int nocrossrefs;
      fill_type *fill;
      const char *memspec;
      struct lang_output_section_phdr_list *phdrs;
      const char *lma_memspec;
 {
   lang_memory_region_type *region;
-  lang_memory_region_type * default_region;
   lang_memory_region_type *lma_region;
   struct overlay_list *l;
   struct lang_nocrossref *nocrossref;
 
-  default_region = lang_memory_region_lookup ("*default*");
-
-  if (memspec == NULL)
-    region = NULL;
-  else
-    region = lang_memory_region_lookup (memspec);
-
-  if (lma_memspec == NULL)
-    lma_region = NULL;
-  else
-    lma_region = lang_memory_region_lookup (lma_memspec);
+  lang_get_regions (&region, &lma_region,
+                   memspec, lma_memspec,
+                   lma_expr != 0);
 
   nocrossref = NULL;
 
+  /* After setting the size of the last section, set '.' to end of the
+     overlay region.  */
+  if (overlay_list != NULL)
+    overlay_list->os->update_dot_tree
+      = exp_assop ('=', ".", exp_binop ('+', overlay_vma, overlay_max));
+
   l = overlay_list;
   while (l != NULL)
     {
@@ -4910,28 +5018,24 @@ lang_leave_overlay (fill, memspec, phdrs, lma_memspec)
       if (fill != (fill_type *) 0 && l->os->fill == (fill_type *) 0)
        l->os->fill = fill;
 
-      /* Assign a region to the sections, if one has been specified.
-        Override the assignment of the default section, but not
-        other sections.  */
-      if (region != NULL &&
-         (l->os->region == NULL ||
-          l->os->region == default_region))
-       l->os->region = region;
-
-      /* We only set lma_region for the first overlay section, as
-        subsequent overlay sections will have load_base set relative
-        to the first section.  Also, don't set lma_region if
-        load_base is specified.  FIXME:  There should really be a test
-        that `AT ( LDADDR )' doesn't conflict with `AT >LMA_REGION'
-        rather than letting LDADDR simply override LMA_REGION.  */
-      if (lma_region != NULL && l->os->lma_region == NULL
-         && l->next == NULL && l->os->load_base == NULL)
-       l->os->lma_region = lma_region;
+      l->os->region = region;
+      l->os->lma_region = lma_region;
+
+      /* The first section has the load address specified in the
+        OVERLAY statement.  The rest are worked out from that.
+        The base address is not needed (and should be null) if
+        an LMA region was specified.  */
+      if (l->next == 0)
+       l->os->load_base = lma_expr;
+      else if (lma_region == 0)
+       l->os->load_base = exp_binop ('+',
+                                     exp_nameop (LOADADDR, l->next->os->name),
+                                     exp_nameop (SIZEOF, l->next->os->name));
 
       if (phdrs != NULL && l->os->phdrs == NULL)
        l->os->phdrs = phdrs;
 
-      if (overlay_nocrossrefs)
+      if (nocrossrefs)
        {
          struct lang_nocrossref *nc;
 
@@ -4949,13 +5053,7 @@ lang_leave_overlay (fill, memspec, phdrs, lma_memspec)
   if (nocrossref != NULL)
     lang_add_nocrossref (nocrossref);
 
-  /* Update . for the end of the overlay.  */
-  lang_add_assignment (exp_assop ('=', ".",
-                                 exp_binop ('+', overlay_vma, overlay_max)));
-
   overlay_vma = NULL;
-  overlay_lma = NULL;
-  overlay_nocrossrefs = 0;
   overlay_list = NULL;
   overlay_max = NULL;
 }
@@ -5043,6 +5141,8 @@ lang_new_vers_pattern (orig, new, lang)
   ret = (struct bfd_elf_version_expr *) xmalloc (sizeof *ret);
   ret->next = orig;
   ret->pattern = new;
+  ret->symver = 0;
+  ret->script = 0;
 
   if (lang == NULL || strcasecmp (lang, "C") == 0)
     ret->match = lang_vers_match_lang_c;
@@ -5057,7 +5157,7 @@ lang_new_vers_pattern (orig, new, lang)
       ret->match = lang_vers_match_lang_c;
     }
 
-  return ret;
+  return ldemul_new_vers_pattern (ret);
 }
 
 /* This is called for each set of variable names and match
@@ -5196,7 +5296,7 @@ lang_do_version_exports_section ()
       bfd_size_type len;
 
       if (sec == NULL)
-        continue;
+       continue;
 
       len = bfd_section_size (is->the_bfd, sec);
       contents = xmalloc (len);
This page took 0.03578 seconds and 4 git commands to generate.