Wed Jan 28 16:37:27 1998 J.J. van der Heijden <J.J.vanderHeijden@student.utwente.nl>
[deliverable/binutils-gdb.git] / ld / ldlang.c
index 1ae91d2068fcffb69365dead71f0fb12a5797d85..b364f9dea071d908c985028300bd66d5e363be52 100644 (file)
@@ -1,5 +1,5 @@
 /* Linker command language support.
-   Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+   Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
 
 This file is part of GLD, the Gnu Linker.
 
@@ -14,12 +14,14 @@ 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.  */
+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"
 #include "libiberty.h"
+#include "obstack.h"
 #include "bfdlink.h"
 
 #include "ld.h"
@@ -32,6 +34,9 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307
 #include "ldmisc.h"
 #include "ldctor.h"
 #include "ldfile.h"
+#include "fnmatch.h"
+
+#include <ctype.h>
 
 /* FORWARDS */
 static lang_statement_union_type *new_statement PARAMS ((enum statement_enum,
@@ -64,7 +69,9 @@ static lang_input_statement_type *new_afile
   PARAMS ((const char *name, lang_input_file_enum_type file_type,
           const char *target, boolean add_to_list));
 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 boolean wildcardp PARAMS ((const char *));
 static void wild_section PARAMS ((lang_wild_statement_type *ptr,
                                  const char *section,
                                  lang_input_statement_type *file,
@@ -72,6 +79,9 @@ static void wild_section PARAMS ((lang_wild_statement_type *ptr,
 static lang_input_statement_type *lookup_name PARAMS ((const char *name));
 static void load_symbols PARAMS ((lang_input_statement_type *entry,
                                  lang_statement_list_type *));
+static void wild_file PARAMS ((lang_wild_statement_type *, const char *,
+                              lang_input_statement_type *,
+                              lang_output_section_statement_type *));
 static void wild PARAMS ((lang_wild_statement_type *s,
                          const char *section, const char *file,
                          const char *target,
@@ -92,6 +102,7 @@ static void print_assignment
   PARAMS ((lang_assignment_statement_type *assignment,
           lang_output_section_statement_type *output_section));
 static void print_input_statement PARAMS ((lang_input_statement_type *statm));
+static boolean print_one_symbol PARAMS ((struct bfd_link_hash_entry *, PTR));
 static void print_input_section PARAMS ((lang_input_section_type *in));
 static void print_fill_statement PARAMS ((lang_fill_statement_type *fill));
 static void print_data_statement PARAMS ((lang_data_statement_type *data));
@@ -117,6 +128,7 @@ static bfd_vma size_input_section
           lang_output_section_statement_type *output_section_statement,
           fill_type fill, bfd_vma dot, boolean relax));
 static void lang_finish PARAMS ((void));
+static void ignore_bfd_errors PARAMS ((const char *, ...));
 static void lang_check PARAMS ((void));
 static void lang_common PARAMS ((void));
 static boolean lang_one_common PARAMS ((struct bfd_link_hash_entry *, PTR));
@@ -136,6 +148,7 @@ boolean lang_has_input_file = false;
 boolean had_output_filename = false;
 boolean lang_float_flag = false;
 boolean delete_output_file_on_failure = false;
+struct lang_nocrossrefs *nocrossref_list;
 
 etree_type *base; /* Relocation base - or null */
 
@@ -283,7 +296,6 @@ new_afile (name, file_type, target, add_to_list)
 
   lang_has_input_file = true;
   p->target = target;
-  p->complained = false;
   switch (file_type)
     {
     case lang_input_file_is_symbols_only_enum:
@@ -342,7 +354,6 @@ new_afile (name, file_type, target, add_to_list)
   p->next_real_file = (lang_statement_union_type *) NULL;
   p->next = (lang_statement_union_type *) NULL;
   p->symbol_count = 0;
-  p->common_output_section = (asection *) NULL;
   p->dynamic = config.dynamic_link;
   p->whole_archive = whole_archive;
   p->loaded = false;
@@ -402,8 +413,7 @@ lang_memory_region_type *
 lang_memory_region_lookup (name)
      CONST char *CONST name;
 {
-
-  lang_memory_region_type *p = lang_memory_region_list;
+  lang_memory_region_type *p;
 
   for (p = lang_memory_region_list;
        p != (lang_memory_region_type *) NULL;
@@ -441,6 +451,8 @@ lang_memory_region_lookup (name)
     *lang_memory_region_list_tail = new;
     lang_memory_region_list_tail = &new->next;
     new->origin = 0;
+    new->flags = 0;
+    new->not_flags = 0;
     new->length = ~(bfd_size_type)0;
     new->current = 0;
     new->had_full_message = false;
@@ -450,6 +462,31 @@ lang_memory_region_lookup (name)
 }
 
 
+lang_memory_region_type *
+lang_memory_default (section)
+     asection *section;
+{
+  lang_memory_region_type *p;
+
+  flagword sec_flags = section->flags;
+
+  /* Override SEC_DATA to mean a writable section.  */
+  if (sec_flags & (SEC_ALLOC | SEC_READONLY | SEC_CODE) == SEC_ALLOC)
+    sec_flags |= SEC_DATA;
+
+  for (p = lang_memory_region_list;
+       p != (lang_memory_region_type *) NULL;
+       p = p->next)
+    {
+      if ((p->flags & sec_flags) != 0
+         && (p->not_flags & sec_flags) == 0)
+       {
+         return p;
+       }
+    }
+  return lang_memory_region_lookup ("*default*");
+}
+
 lang_output_section_statement_type *
 lang_output_section_find (name)
      CONST char *CONST name;
@@ -490,7 +527,7 @@ lang_output_section_statement_lookup (name)
       lookup->next = (lang_statement_union_type *) NULL;
       lookup->bfd_section = (asection *) NULL;
       lookup->processed = false;
-      lookup->loadable = 1;
+      lookup->sectype = normal_section;
       lookup->addr_tree = (etree_type *) NULL;
       lang_list_init (&lookup->children);
 
@@ -508,14 +545,34 @@ lang_output_section_statement_lookup (name)
   return lookup;
 }
 
+static void
+lang_map_flags (flag)
+     flagword flag;
+{
+  if (flag & SEC_ALLOC)
+    minfo ("a");
+
+  if (flag & SEC_CODE)
+    minfo ("x");
+
+  if (flag & SEC_READONLY)
+    minfo ("r");
+
+  if (flag & SEC_DATA)
+    minfo ("w");
+
+  if (flag & SEC_LOAD)
+    minfo ("l");
+}
+
 void
 lang_map ()
 {
   lang_memory_region_type *m;
 
   minfo ("\nMemory Configuration\n\n");
-  fprintf (config.map_file, "%-16s %-18s %-18s\n",
-          "Name", "Origin", "Length");
+  fprintf (config.map_file, "%-16s %-18s %-18s %s\n",
+          "Name", "Origin", "Length", "Attributes");
 
   for (m = lang_memory_region_list;
        m != (lang_memory_region_type *) NULL;
@@ -535,7 +592,26 @@ lang_map ()
          ++len;
        }
 
-      minfo ("0x%V\n", m->length);
+      minfo ("0x%V", m->length);
+      if (m->flags || m->not_flags)
+       {
+#ifndef BFD64
+         minfo ("        ");
+#endif
+         if (m->flags)
+           {
+             print_space ();
+             lang_map_flags (m->flags);
+           }
+
+         if (m->not_flags)
+           {
+             minfo (" !");
+             lang_map_flags (m->not_flags);
+           }
+       }
+
+      print_nl ();
     }
 
   fprintf (config.map_file, "\nLinker script and memory map\n\n");
@@ -543,15 +619,17 @@ lang_map ()
   print_statements ();
 }
 
-/*
- *
- */
+/* Initialize an output section.  */
+
 static void
 init_os (s)
-     lang_output_section_statement_type * s;
+     lang_output_section_statement_type *s;
 {
   section_userdata_type *new;
 
+  if (s->bfd_section != NULL)
+    return;
+
   if (strcmp (s->name, DISCARD_SECTION_NAME) == 0)
     einfo ("%P%F: Illegal use of `%s' section", DISCARD_SECTION_NAME);
 
@@ -572,6 +650,60 @@ init_os (s)
   /* vma to allow us to output a section through itself */
   s->bfd_section->output_offset = 0;
   get_userdata (s->bfd_section) = (PTR) new;
+
+  /* If there is a base address, make sure that any sections it might
+     mention are initialized.  */
+  if (s->addr_tree != NULL)
+    exp_init_os (s->addr_tree);
+}
+
+/* Make sure that all output sections mentioned in an expression are
+   initialized.  */
+
+static void
+exp_init_os (exp)
+     etree_type *exp;
+{
+  switch (exp->type.node_class)
+    {
+    case etree_assign:
+      exp_init_os (exp->assign.src);
+      break;
+
+    case etree_binary:
+      exp_init_os (exp->binary.lhs);
+      exp_init_os (exp->binary.rhs);
+      break;
+
+    case etree_trinary:
+      exp_init_os (exp->trinary.cond);
+      exp_init_os (exp->trinary.lhs);
+      exp_init_os (exp->trinary.rhs);
+      break;
+
+    case etree_unary:
+      exp_init_os (exp->unary.child);
+      break;
+
+    case etree_name:
+      switch (exp->type.node_code)
+       {
+       case ADDR:
+       case LOADADDR:
+       case SIZEOF:
+         {
+           lang_output_section_statement_type *os;
+
+           os = lang_output_section_find (exp->name.name);
+           if (os != NULL && os->bfd_section == NULL)
+             init_os (os);
+         }
+       }
+      break;
+
+    default:
+      break;
+    }
 }
 
 /* Sections marked with the SEC_LINK_ONCE flag should only be linked
@@ -583,11 +715,12 @@ init_os (s)
 
 /*ARGSUSED*/
 static void
-section_already_linked (abfd, sec, ignore)
+section_already_linked (abfd, sec, data)
      bfd *abfd;
      asection *sec;
-     PTR ignore;
+     PTR data;
 {
+  lang_input_statement_type *entry = (lang_input_statement_type *) data;
   struct sec_link_once
     {
       struct sec_link_once *next;
@@ -598,6 +731,15 @@ section_already_linked (abfd, sec, ignore)
   const char *name;
   struct sec_link_once *l;
 
+  /* If we are only reading symbols from this object, then we want to
+     discard all sections.  */
+  if (entry->just_syms_flag)
+    {
+      sec->output_section = bfd_abs_section_ptr;
+      sec->output_offset = sec->vma;
+      return;
+    }
+
   flags = bfd_get_section_flags (abfd, sec);
 
   if ((flags & SEC_LINK_ONCE) == 0)
@@ -620,7 +762,7 @@ section_already_linked (abfd, sec, ignore)
              break;
 
            case SEC_LINK_DUPLICATES_ONE_ONLY:
-             einfo ("%P: %B: warning: ignoring duplicate section `%s'",
+             einfo ("%P: %B: warning: ignoring duplicate section `%s'\n",
                     abfd, name);
              break;
 
@@ -634,8 +776,8 @@ section_already_linked (abfd, sec, ignore)
            case SEC_LINK_DUPLICATES_SAME_SIZE:
              if (bfd_section_size (abfd, sec)
                  != bfd_section_size (l->sec->owner, l->sec))
-               einfo ("%P: %B: warning: duplicate section `%s' has different size",
-                      abfd, sec);
+               einfo ("%P: %B: warning: duplicate section `%s' has different size\n",
+                      abfd, name);
              break;
            }
 
@@ -661,6 +803,26 @@ section_already_linked (abfd, sec, ignore)
    explicit actions, like foo.o(.text), bar.o(.text) and
    foo.o(.text, .data).  */
 
+/* Return true if the PATTERN argument is a wildcard pattern.
+   Although backslashes are treated specially if a pattern contains
+   wildcards, we do not consider the mere presence of a backslash to
+   be enough to cause the the pattern to be treated as a wildcard.
+   That lets us handle DOS filenames more naturally.  */
+
+static boolean
+wildcardp (pattern)
+     const char *pattern;
+{
+  const char *s;
+
+  for (s = pattern; *s != '\0'; ++s)
+    if (*s == '?'
+       || *s == '*'
+       || *s == '[')
+      return true;
+  return false;
+}
+
 /* Add SECTION to the output section OUTPUT.  Do this by creating a
    lang_input_section statement which is placed at PTR.  FILE is the
    input file which holds SECTION.  */
@@ -708,10 +870,17 @@ wild_doit (ptr, section, output, file)
 
   if (section->output_section == NULL)
     {
+      boolean first;
       lang_input_section_type *new;
+      flagword flags;
 
       if (output->bfd_section == NULL)
-       init_os (output);
+       {
+         init_os (output);
+         first = true;
+       }
+      else
+       first = false;
 
       /* Add a section reference to the list */
       new = new_stat (lang_input_section, ptr);
@@ -720,20 +889,53 @@ wild_doit (ptr, section, output, file)
       new->ifile = file;
       section->output_section = output->bfd_section;
 
+      flags = section->flags;
+
       /* We don't copy the SEC_NEVER_LOAD flag from an input section
         to an output section, because we want to be able to include a
         SEC_NEVER_LOAD section in the middle of an otherwise loaded
         section (I don't know why we want to do this, but we do).
         build_link_order in ldwrite.c handles this case by turning
         the embedded SEC_NEVER_LOAD section into a fill.  */
-      section->output_section->flags |=
-       section->flags & (flagword) (~ SEC_NEVER_LOAD);
 
-      if (! output->loadable) 
+      flags &= ~ SEC_NEVER_LOAD;
+
+      /* If final link, don't copy the SEC_LINK_ONCE flags, they've
+        already been processed.  One reason to do this is that on pe
+        format targets, .text$foo sections go into .text and it's odd
+        to see .text with SEC_LINK_ONCE set.  */
+
+      if (! link_info.relocateable)
+       flags &= ~ (SEC_LINK_ONCE | SEC_LINK_DUPLICATES);
+
+      /* If this is not the first input section, and the SEC_READONLY
+         flag is not currently set, then don't set it just because the
+         input section has it set.  */
+
+      if (! first && (section->output_section->flags & SEC_READONLY) == 0)
+       flags &= ~ SEC_READONLY;
+
+      section->output_section->flags |= flags;
+
+      /* If SEC_READONLY is not set in the input section, then clear
+         it from the output section.  */
+      if ((section->flags & SEC_READONLY) == 0)
+       section->output_section->flags &= ~SEC_READONLY;
+
+      switch (output->sectype)
        {
-         /* Turn off load flag */
+       case normal_section:
+         break;
+       case dsect_section:
+       case copy_section:
+       case info_section:
+       case overlay_section:
+         output->bfd_section->flags &= ~SEC_ALLOC;
+         break;
+       case noload_section:
          output->bfd_section->flags &= ~SEC_LOAD;
          output->bfd_section->flags |= SEC_NEVER_LOAD;
+         break;
        }
 
       if (section->alignment_power > output->bfd_section->alignment_power)
@@ -758,9 +960,17 @@ wild_section (ptr, section, file, output)
   if (file->just_syms_flag == false)
     {
       register asection *s;
+      boolean wildcard;
+
+      if (section == NULL)
+       wildcard = false;
+      else
+       wildcard = wildcardp (section);
 
       for (s = file->the_bfd->sections; s != NULL; s = s->next)
        {
+         boolean match;
+
          /* Attach all sections named SECTION.  If SECTION is NULL,
             then attach all sections.
 
@@ -769,9 +979,19 @@ wild_section (ptr, section, file, output)
             section.  I did not understand that, and I took it out.
             --ian@cygnus.com.  */
 
-         if (section == NULL
-             || strcmp (bfd_get_section_name (file->the_bfd, s),
-                        section) == 0)
+         if (section == NULL)
+           match = true;
+         else
+           {
+             const char *name;
+
+             name = bfd_get_section_name (file->the_bfd, s);
+             if (wildcard)
+               match = fnmatch (section, name, 0) == 0 ? true : false;
+             else
+               match = strcmp (section, name) == 0 ? true : false;
+           }
+         if (match)
            wild_doit (&ptr->children, s, output, file);
        }
     }
@@ -922,6 +1142,44 @@ load_symbols (entry, place)
   entry->loaded = true;
 }
 
+/* Handle a wild statement for a single file F.  */
+
+static void
+wild_file (s, section, f, output)
+     lang_wild_statement_type *s;
+     const char *section;
+     lang_input_statement_type *f;
+     lang_output_section_statement_type *output;
+{
+  if (f->the_bfd == NULL
+      || ! bfd_check_format (f->the_bfd, bfd_archive))
+    wild_section (s, section, f, output);
+  else
+    {
+      bfd *member;
+
+      /* This is an archive file.  We must map each member of the
+        archive separately.  */
+      member = bfd_openr_next_archived_file (f->the_bfd, (bfd *) NULL);
+      while (member != NULL)
+       {
+         /* When lookup_name is called, it will call the add_symbols
+            entry point for the archive.  For each element of the
+            archive which is included, BFD will call ldlang_add_file,
+            which will set the usrdata field of the member to the
+            lang_input_statement.  */
+         if (member->usrdata != NULL)
+           {
+             wild_section (s, section,
+                           (lang_input_statement_type *) member->usrdata,
+                           output);
+           }
+
+         member = bfd_openr_next_archived_file (f->the_bfd, member);
+       }
+    }
+}
+
 /* Handle a wild statement.  SECTION or FILE or both may be NULL,
    indicating that it is a wildcard.  Separate lang_input_section
    statements are created for each part of the expansion; they are
@@ -944,40 +1202,24 @@ wild (s, section, file, target, output)
           f != (lang_input_statement_type *) NULL;
           f = (lang_input_statement_type *) f->next)
        {
-         wild_section (s, section, f, output);
+         wild_file (s, section, f, output);
+       }
+    }
+  else if (wildcardp (file))
+    {
+      for (f = (lang_input_statement_type *) file_chain.head;
+          f != (lang_input_statement_type *) NULL;
+          f = (lang_input_statement_type *) f->next)
+       {
+         if (fnmatch (file, f->filename, FNM_FILE_NAME) == 0)
+           wild_file (s, section, f, output);
        }
     }
   else
     {
       /* Perform the iteration over a single file */
       f = lookup_name (file);
-      if (f->the_bfd == NULL
-         || ! bfd_check_format (f->the_bfd, bfd_archive))
-       wild_section (s, section, f, output);
-      else
-       {
-         bfd *member;
-
-         /* This is an archive file.  We must map each member of the
-             archive separately.  */
-         member = bfd_openr_next_archived_file (f->the_bfd, (bfd *) NULL);
-         while (member != NULL)
-           {
-             /* When lookup_name is called, it will call the
-                 add_symbols entry point for the archive.  For each
-                 element of the archive which is included, BFD will
-                 call ldlang_add_file, which will set the usrdata
-                 field of the member to the lang_input_statement.  */
-             if (member->usrdata != NULL)
-               {
-                 wild_section (s, section,
-                               (lang_input_statement_type *) member->usrdata,
-                               output);
-               }
-
-             member = bfd_openr_next_archived_file (f->the_bfd, member);
-           }
-       }
+      wild_file (s, section, f, output);
     }
 
   if (section != (char *) NULL
@@ -1016,7 +1258,7 @@ open_output (name)
       einfo ("%P%F: cannot open output file %s: %E\n", name);
     }
 
-  delete_output_file_on_failure = 1;
+  delete_output_file_on_failure = true;
 
   /*  output->flags |= D_PAGED;*/
 
@@ -1089,7 +1331,8 @@ open_input_bfds (s, force)
          break;
        case lang_wild_statement_enum:
          /* Maybe we should load the file's symbols */
-         if (s->wild_statement.filename)
+         if (s->wild_statement.filename
+             && ! wildcardp (s->wild_statement.filename))
            (void) lookup_name (s->wild_statement.filename);
          open_input_bfds (s->wild_statement.children.head, force);
          break;
@@ -1215,7 +1458,7 @@ lang_place_undefineds ()
 
       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");
+       einfo ("%P%F: bfd_link_hash_lookup failed: %E\n");
       if (h->type == bfd_link_hash_new)
        {
          h->type = bfd_link_hash_undefined;
@@ -1269,13 +1512,21 @@ map_input_to_output_sections (s, target, output_section_statement)
        case lang_object_symbols_statement_enum:
        case lang_data_statement_enum:
        case lang_reloc_statement_enum:
-       case lang_assignment_statement_enum:
        case lang_padding_statement_enum:
        case lang_input_statement_enum:
          if (output_section_statement != NULL
              && output_section_statement->bfd_section == NULL)
            init_os (output_section_statement);
          break;
+       case lang_assignment_statement_enum:
+         if (output_section_statement != NULL
+             && output_section_statement->bfd_section == NULL)
+           init_os (output_section_statement);
+
+         /* Make sure that any sections mentioned in the assignment
+             are initialized.  */
+         exp_init_os (s->assignment_statement.exp);
+         break;
        case lang_afile_asection_pair_statement_enum:
          FAIL ();
          break;
@@ -1512,6 +1763,10 @@ print_data_statement (data)
       size = QUAD_SIZE;
       name = "QUAD";
       break;
+    case SQUAD:
+      size = QUAD_SIZE;
+      name = "SQUAD";
+      break;
     }
 
   minfo ("0x%V %W %s 0x%v", addr, size, name, data->value);
@@ -1594,7 +1849,7 @@ print_padding_statement (s)
   minfo ("0x%V %W", addr, s->size);
 
   if (s->fill != 0)
-    minfo (" 0x%x", s->fill);
+    minfo (" %u", s->fill);
 
   print_nl ();
 
@@ -1746,7 +2001,7 @@ dprint_statement (s, n)
     print_statement_list (s, abs_output_section);
   else
     {
-      while (--n >= 0)
+      while (s && --n >= 0)
        {
          print_statement (s, abs_output_section);
          s = s->next;
@@ -1887,7 +2142,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
           if (os->children.head == NULL
               || os->children.head->next != NULL
               || os->children.head->header.type != lang_input_section_enum)
-            einfo ("%P%X: Internal error on COFF shared library section %s",
+            einfo ("%P%X: Internal error on COFF shared library section %s\n",
                    os->name);
 
           input = os->children.head->input_section.section;
@@ -1912,11 +2167,19 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
              */
           if (os->region == (lang_memory_region_type *) NULL)
           {
-            os->region = lang_memory_region_lookup ("*default*");
+            os->region = lang_memory_default (os->bfd_section);
           }
           dot = os->region->current;
           if (os->section_alignment == -1)
-            dot = align_power (dot, os->bfd_section->alignment_power);
+            {
+              bfd_vma olddot;
+
+              olddot = dot;
+              dot = align_power (dot, os->bfd_section->alignment_power);
+              if (dot != olddot && config.warn_section_align)
+                einfo ("%P: warning: changing start of section %s by %u bytes\n",
+                       os->name, (unsigned int) (dot - olddot));
+            }
         }
         else
         {
@@ -1931,7 +2194,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
             einfo ("%F%S: non constant address expression for section %s\n",
                    os->name);
           }
-          dot = r.value;
+          dot = r.value + r.section->bfd_section->vma;
         }
         /* The section starts here */
         /* First, align to what the section needs */
@@ -2009,21 +2272,22 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
        output_section_statement->bfd_section;
 
        switch (s->data_statement.type)
-       {
-        case QUAD:
-        size = QUAD_SIZE;
-        break;
-       case LONG:
-        size = LONG_SIZE;
-        break;
-       case SHORT:
-        size = SHORT_SIZE;
-        break;
-       case BYTE:
-        size = BYTE_SIZE;
-        break;
+        {
+        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;
+        }
 
-       }
        dot += size;
        output_section_statement->bfd_section->_raw_size += size;
        /* The output section gets contents, and then we inspect for
@@ -2247,6 +2511,7 @@ lang_do_assignments (s, output_section_statement, fill, dot)
          switch (s->data_statement.type)
            {
            case QUAD:
+           case SQUAD:
              dot += QUAD_SIZE;
              break;
            case LONG:
@@ -2431,6 +2696,20 @@ lang_finish ()
     }
 }
 
+/* This is a small function used when we want to ignore errors from
+   BFD.  */
+
+static void
+#ifdef ANSI_PROTOTYPES
+ignore_bfd_errors (const char *s, ...)
+#else
+ignore_bfd_errors (s)
+     const char *s;
+#endif
+{
+  /* Don't do anything.  */
+}
+
 /* Check that the architecture of all the input files is compatible
    with the output file.  Also call the backend to let it do any
    other checking that is needed.  */
@@ -2450,12 +2729,32 @@ lang_check ()
       compatible = bfd_arch_get_compatible (input_bfd,
                                            output_bfd);
       if (compatible == NULL)
-       einfo ("%P: warning: %s architecture of input file `%B' is incompatible with %s output\n",
-              bfd_printable_name (input_bfd), input_bfd,
-              bfd_printable_name (output_bfd));
-
+       {
+         if (command_line.warn_mismatch)
+           einfo ("%P: warning: %s architecture of input file `%B' is incompatible with %s output\n",
+                  bfd_printable_name (input_bfd), input_bfd,
+                  bfd_printable_name (output_bfd));
+       }
       else
-       bfd_merge_private_bfd_data (input_bfd, output_bfd);
+       {
+         bfd_error_handler_type pfn;
+
+         /* If we aren't supposed to warn about mismatched input
+             files, temporarily set the BFD error handler to a
+             function which will do nothing.  We still want to call
+             bfd_merge_private_bfd_data, since it may set up
+             information which is needed in the output file.  */
+         if (! command_line.warn_mismatch)
+           pfn = bfd_set_error_handler (ignore_bfd_errors);
+         if (! bfd_merge_private_bfd_data (input_bfd, output_bfd))
+           {
+             if (command_line.warn_mismatch)
+               einfo ("%E%X: failed to merge target specific data of file %B\n",
+                      input_bfd);
+           }
+         if (! command_line.warn_mismatch)
+           bfd_set_error_handler (pfn);
+       }
     }
 }
 
@@ -2521,8 +2820,10 @@ lang_one_common (h, info)
   /* Increase the size of the section.  */
   section->_raw_size += size;
 
-  /* Make sure the section is allocated in memory.  */
+  /* Make sure the section is allocated in memory, and make sure that
+     it is no longer a common section.  */
   section->flags |= SEC_ALLOC;
+  section->flags &= ~ SEC_IS_COMMON;
 
   if (config.map_file != NULL)
     {
@@ -2609,19 +2910,22 @@ lang_place_orphans ()
                  s->output_section = bfd_abs_section_ptr;
                  s->output_offset = s->vma;
                }
-             else if (file->common_section == s)
+             else if (strcmp (s->name, "COMMON") == 0)
                {
-                 /* This is a lonely common section which must
-                    have come from an archive. We attatch to the
-                    section with the wildcard  */
+                 /* This is a lonely common section which must have
+                    come from an archive.  We attach to the section
+                    with the wildcard.  */
                  if (! link_info.relocateable
-                     && ! command_line.force_common_definition)
+                     || command_line.force_common_definition)
                    {
-                     if (default_common_section ==
-                         (lang_output_section_statement_type *) NULL)
+                     if (default_common_section == NULL)
                        {
+#if 0
+                         /* This message happens when using the
+                             svr3.ifile linker script, so I have
+                             disabled it.  */
                          info_msg ("%P: no [COMMON] command, defaulting to .bss\n");
-
+#endif
                          default_common_section =
                            lang_output_section_statement_lookup (".bss");
 
@@ -2647,36 +2951,41 @@ lang_place_orphans ()
 
 void
 lang_set_flags (ptr, flags)
-     int *ptr;
+     lang_memory_region_type *ptr;
      CONST char *flags;
 {
-  boolean state = false;
+  flagword *ptr_flags = &ptr->flags;
 
-  *ptr = 0;
+  ptr->flags = ptr->not_flags = 0;
   while (*flags)
     {
-      if (*flags == '!')
-       {
-         state = false;
-         flags++;
-       }
-      else
-       state = true;
       switch (*flags)
        {
-       case 'R':
-         /*      ptr->flag_read = state; */
+       case '!':
+         ptr_flags = (ptr_flags == &ptr->flags) ? &ptr->not_flags : &ptr->flags;
          break;
-       case 'W':
-         /*      ptr->flag_write = state; */
+
+       case 'A': case 'a':
+         *ptr_flags |= SEC_ALLOC;
+         break;
+
+       case 'R': case 'r':
+         *ptr_flags |= SEC_READONLY;
+         break;
+
+       case 'W': case 'w':
+         *ptr_flags |= SEC_DATA;
          break;
-       case 'X':
-         /*      ptr->flag_executable= state;*/
+
+       case 'X': case 'x':
+         *ptr_flags |= SEC_CODE;
          break;
-       case 'L':
-       case 'I':
-         /*      ptr->flag_loadable= state;*/
+
+       case 'L': case 'l':
+       case 'I': case 'i':
+         *ptr_flags |= SEC_LOAD;
          break;
+
        default:
          einfo ("%P%F: invalid syntax in flags\n");
          break;
@@ -2777,7 +3086,7 @@ ldlang_add_file (entry)
      each backend which might set the SEC_LINK_ONCE flag.  If we do
      this, we should probably handle SEC_EXCLUDE in the same way.  */
 
-  bfd_map_over_sections (entry->the_bfd, section_already_linked, (PTR) NULL);
+  bfd_map_over_sections (entry->the_bfd, section_already_linked, (PTR) entry);
 }
 
 void
@@ -2815,13 +3124,14 @@ topower (x)
 
   return 0;
 }
+
 void
 lang_enter_output_section_statement (output_section_statement_name,
-                                    address_exp, flags, block_value,
+                                    address_exp, sectype, block_value,
                                     align, subalign, ebase)
      const char *output_section_statement_name;
      etree_type * address_exp;
-     int flags;
+     enum section_type sectype;
      bfd_vma block_value;
      etree_type *align;
      etree_type *subalign;
@@ -2846,11 +3156,11 @@ lang_enter_output_section_statement (output_section_statement_name,
     os->addr_tree =
      address_exp;
   }
-  os->flags = flags;
-  if (flags & SEC_NEVER_LOAD)
-   os->loadable = 0;
+  os->sectype = sectype;
+  if (sectype != noload_section)
+    os->flags = SEC_NO_FLAGS;
   else
-   os->loadable = 1;
+    os->flags = SEC_NEVER_LOAD;
   os->block_value = block_value ? block_value : 1;
   stat_ptr = &os->children;
 
@@ -2909,6 +3219,13 @@ lang_process ()
 
   ldemul_after_open ();
 
+  /* 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
+     does on the output file will be known during the rest of the
+     link.  */
+  lang_check ();
+
   /* Build all sets based on the information gathered from the input
      files.  */
   ldctor_build_sets ();
@@ -2916,14 +3233,14 @@ lang_process ()
   /* Size up the common data */
   lang_common ();
 
-  /* Run through the contours of the script and attatch input sections
+  /* Run through the contours of the script and attach input sections
      to the correct output sections
      */
   map_input_to_output_sections (statement_list.head, (char *) NULL,
                                (lang_output_section_statement_type *) NULL);
 
 
-  /* Find any sections not attatched explicitly and handle them */
+  /* Find any sections not attached explicitly and handle them */
   lang_place_orphans ();
 
   ldemul_before_allocation ();
@@ -2984,10 +3301,6 @@ lang_process ()
                       abs_output_section,
                       (fill_type) 0, (bfd_vma) 0);
 
-  /* Make sure that we're not mixing architectures */
-
-  lang_check ();
-
   /* Final stuffs */
 
   ldemul_finish ();
@@ -3189,12 +3502,14 @@ lang_float (maybe)
 }
 
 void
-lang_leave_output_section_statement (fill, memspec)
+lang_leave_output_section_statement (fill, memspec, phdrs)
      bfd_vma fill;
-     CONST char *memspec;
+     const char *memspec;
+     struct lang_output_section_phdr_list *phdrs;
 {
   current_section->fill = fill;
   current_section->region = lang_memory_region_lookup (memspec);
+  current_section->phdrs = phdrs;
   stat_ptr = &statement_list;
 }
 
@@ -3352,22 +3667,6 @@ lang_new_phdr (name, type, filehdr, phdrs, at, flags)
   *pp = n;
 }
 
-/* Record that a section should be placed in a phdr.  */
-
-void
-lang_section_in_phdr (name)
-     const char *name;
-{
-  struct lang_output_section_phdr_list *n;
-
-  n = ((struct lang_output_section_phdr_list *)
-       stat_alloc (sizeof (struct lang_output_section_phdr_list)));
-  n->name = name;
-  n->used = false;
-  n->next = current_section->phdrs;
-  current_section->phdrs = n;
-}
-
 /* Record the program header information in the output BFD.  FIXME: We
    should not be calling an ELF specific function here.  */
 
@@ -3381,7 +3680,7 @@ lang_record_phdrs ()
   lang_statement_union_type *u;
 
   alc = 10;
-  secs = xmalloc (alc * sizeof (asection *));
+  secs = (asection **) xmalloc (alc * sizeof (asection *));
   last = NULL;
   for (l = lang_phdr_list; l != NULL; l = l->next)
     {
@@ -3404,7 +3703,7 @@ lang_record_phdrs ()
            last = pl;
          else
            {
-             if (! os->loadable
+             if (os->sectype == noload_section
                  || os->bfd_section == NULL
                  || (os->bfd_section->flags & SEC_ALLOC) == 0)
                continue;
@@ -3421,7 +3720,8 @@ lang_record_phdrs ()
                  if (c >= alc)
                    {
                      alc *= 2;
-                     secs = xrealloc (secs, alc * sizeof (asection *));
+                     secs = ((asection **)
+                             xrealloc (secs, alc * sizeof (asection *)));
                    }
                  secs[c] = os->bfd_section;
                  ++c;
@@ -3470,3 +3770,335 @@ lang_record_phdrs ()
                 u->output_section_statement.name, pl->name);
     }
 }
+
+/* Record a list of sections which may not be cross referenced.  */
+
+void
+lang_add_nocrossref (l)
+     struct lang_nocrossref *l;
+{
+  struct lang_nocrossrefs *n;
+
+  n = (struct lang_nocrossrefs *) xmalloc (sizeof *n);
+  n->next = nocrossref_list;
+  n->list = l;
+  nocrossref_list = n;
+
+  /* Set notice_all so that we get informed about all symbols.  */
+  link_info.notice_all = true;
+}
+\f
+/* Overlay handling.  We handle overlays with some static variables.  */
+
+/* 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;
+
+/* A list of all the sections in this overlay.  */
+
+struct overlay_list
+{
+  struct overlay_list *next;
+  lang_output_section_statement_type *os;
+};
+
+static struct overlay_list *overlay_list;
+
+/* Start handling an overlay.  */
+
+void
+lang_enter_overlay (vma_expr, lma_expr, nocrossrefs)
+     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);
+
+  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.  */
+
+void
+lang_enter_overlay_section (name)
+     const char *name;
+{
+  struct overlay_list *n;
+  etree_type *size;
+
+  lang_enter_output_section_statement (name, overlay_vma, normal_section,
+                                      0, 0, 0, overlay_lma);
+
+  /* If this is the first section, then base the VMA and LMA 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);
+    }
+
+  /* Remember the section.  */
+  n = (struct overlay_list *) xmalloc (sizeof *n);
+  n->os = current_section;
+  n->next = overlay_list;
+  overlay_list = n;
+
+  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;
+  else
+    overlay_max = exp_binop (MAX, overlay_max, size);
+}
+
+/* Finish a section in an overlay.  There isn't any special to do
+   here.  */
+
+void
+lang_leave_overlay_section (fill, phdrs)
+     bfd_vma fill;
+     struct lang_output_section_phdr_list *phdrs;
+{
+  const char *name;
+  char *clean, *s2;
+  const char *s1;
+  char *buf;
+
+  name = current_section->name;
+
+  lang_leave_output_section_statement (fill, "*default*", phdrs);
+
+  /* Define the magic symbols.  */
+
+  clean = xmalloc (strlen (name) + 1);
+  s2 = clean;
+  for (s1 = name; *s1 != '\0'; s1++)
+    if (isalnum (*s1) || *s1 == '_')
+      *s2++ = *s1;
+  *s2 = '\0';
+
+  buf = xmalloc (strlen (clean) + sizeof "__load_start_");
+  sprintf (buf, "__load_start_%s", clean);
+  lang_add_assignment (exp_assop ('=', buf,
+                                 exp_nameop (LOADADDR, name)));
+
+  buf = xmalloc (strlen (clean) + sizeof "__load_stop_");
+  sprintf (buf, "__load_stop_%s", clean);
+  lang_add_assignment (exp_assop ('=', buf,
+                                 exp_binop ('+',
+                                            exp_nameop (LOADADDR, name),
+                                            exp_nameop (SIZEOF, name))));
+
+  free (clean);
+}
+
+/* Finish an overlay.  If there are any overlay wide settings, this
+   looks through all the sections in the overlay and sets them.  */
+
+void
+lang_leave_overlay (fill, memspec, phdrs)
+     bfd_vma fill;
+     const char *memspec;
+     struct lang_output_section_phdr_list *phdrs;
+{
+  lang_memory_region_type *region;
+  struct overlay_list *l;
+  struct lang_nocrossref *nocrossref;
+
+  if (memspec == NULL)
+    region = NULL;
+  else
+    region = lang_memory_region_lookup (memspec);
+
+  nocrossref = NULL;
+
+  l = overlay_list;
+  while (l != NULL)
+    {
+      struct overlay_list *next;
+
+      if (fill != 0 && l->os->fill == 0)
+       l->os->fill = fill;
+      if (region != NULL && l->os->region == NULL)
+       l->os->region = region;
+      if (phdrs != NULL && l->os->phdrs == NULL)
+       l->os->phdrs = phdrs;
+
+      if (overlay_nocrossrefs)
+       {
+         struct lang_nocrossref *nc;
+
+         nc = (struct lang_nocrossref *) xmalloc (sizeof *nc);
+         nc->name = l->os->name;
+         nc->next = nocrossref;
+         nocrossref = nc;
+       }
+
+      next = l->next;
+      free (l);
+      l = next;
+    }
+
+  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;
+}
+\f
+/* Version handling.  This is only useful for ELF.  */
+
+/* This global variable holds the version tree that we build.  */
+
+struct bfd_elf_version_tree *lang_elf_version_info;
+
+/* This is called for each variable name or match expression.  */
+
+struct bfd_elf_version_expr *
+lang_new_vers_regex (orig, new)
+     struct bfd_elf_version_expr *orig;
+     const char *new;
+{
+  struct bfd_elf_version_expr *ret;
+
+  ret = (struct bfd_elf_version_expr *) xmalloc (sizeof *ret);
+  ret->next = orig;
+  ret->match = new;
+  return ret;
+}
+
+/* This is called for each set of variable names and match
+   expressions.  */
+
+struct bfd_elf_version_tree *
+lang_new_vers_node (globals, locals)
+     struct bfd_elf_version_expr *globals;
+     struct bfd_elf_version_expr *locals;
+{
+  struct bfd_elf_version_tree *ret;
+
+  ret = (struct bfd_elf_version_tree *) xmalloc (sizeof *ret);
+  ret->next = NULL;
+  ret->name = NULL;
+  ret->vernum = 0;
+  ret->globals = globals;
+  ret->locals = locals;
+  ret->deps = NULL;
+  ret->name_indx = (unsigned int) -1;
+  ret->used = 0;
+  return ret;
+}
+
+/* This static variable keeps track of version indices.  */
+
+static int version_index;
+
+/* This is called when we know the name and dependencies of the
+   version.  */
+
+void
+lang_register_vers_node (name, version, deps)
+     const char *name;
+     struct bfd_elf_version_tree *version;
+     struct bfd_elf_version_deps *deps;
+{
+  struct bfd_elf_version_tree *t, **pp;
+  struct bfd_elf_version_expr *e1;
+
+  /* Make sure this node has a unique name.  */
+  for (t = lang_elf_version_info; t != NULL; t = t->next)
+    if (strcmp (t->name, name) == 0)
+      einfo ("%X%P: duplicate version tag `%s'\n", name);
+
+  /* Check the global and local match names, and make sure there
+     aren't any duplicates.  */
+
+  for (e1 = version->globals; e1 != NULL; e1 = e1->next)
+    {
+      for (t = lang_elf_version_info; t != NULL; t = t->next)
+       {
+         struct bfd_elf_version_expr *e2;
+
+         for (e2 = t->locals; e2 != NULL; e2 = e2->next)
+           if (strcmp (e1->match, e2->match) == 0)
+             einfo ("%X%P: duplicate expression `%s' in version information\n",
+                    e1->match);
+       }
+    }
+
+  for (e1 = version->locals; e1 != NULL; e1 = e1->next)
+    {
+      for (t = lang_elf_version_info; t != NULL; t = t->next)
+       {
+         struct bfd_elf_version_expr *e2;
+
+         for (e2 = t->globals; e2 != NULL; e2 = e2->next)
+           if (strcmp (e1->match, e2->match) == 0)
+             einfo ("%X%P: duplicate expression `%s' in version information\n",
+                    e1->match);
+       }
+    }
+
+  version->deps = deps;
+  version->name = name;
+  ++version_index;
+  version->vernum = version_index;
+
+  for (pp = &lang_elf_version_info; *pp != NULL; pp = &(*pp)->next)
+    ;
+  *pp = version;
+}
+
+/* This is called when we see a version dependency.  */
+
+struct bfd_elf_version_deps *
+lang_add_vers_depend (list, name)
+     struct bfd_elf_version_deps *list;
+     const char *name;
+{
+  struct bfd_elf_version_deps *ret;
+  struct bfd_elf_version_tree *t;
+
+  ret = (struct bfd_elf_version_deps *) xmalloc (sizeof *ret);
+  ret->next = list;
+
+  for (t = lang_elf_version_info; t != NULL; t = t->next)
+    {
+      if (strcmp (t->name, name) == 0)
+       {
+         ret->version_needed = t;
+         return ret;
+       }
+    }
+
+  einfo ("%X%P: unable to find version dependency `%s'\n", name);
+
+  return ret;
+}
This page took 0.039197 seconds and 4 git commands to generate.