* configure.tgt (mips*-sgi-irix[56]*): Use elf32bsmip rather than
[deliverable/binutils-gdb.git] / ld / ldlang.c
index 94f58f9a56d9f1d878f441edaff18d02ffc22fed..ad582081898a4cce83f05f31601beaaa692989bb 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"
@@ -34,6 +36,8 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307
 #include "ldfile.h"
 #include "fnmatch.h"
 
+#include <ctype.h>
+
 /* FORWARDS */
 static lang_statement_union_type *new_statement PARAMS ((enum statement_enum,
                                                         size_t,
@@ -98,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));
@@ -142,6 +147,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 */
 
@@ -617,6 +623,7 @@ exp_init_os (exp)
       switch (exp->type.node_code)
        {
        case ADDR:
+       case LOADADDR:
        case SIZEOF:
          {
            lang_output_section_statement_type *os;
@@ -642,11 +649,12 @@ exp_init_os (exp)
 
 /*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;
@@ -657,6 +665,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)
@@ -720,7 +737,11 @@ 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.  */
+/* 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)
@@ -730,7 +751,6 @@ wildcardp (pattern)
 
   for (s = pattern; *s != '\0'; ++s)
     if (*s == '?'
-       || *s == '\\'
        || *s == '*'
        || *s == '[')
       return true;
@@ -825,7 +845,7 @@ wild_doit (ptr, section, output, file)
          output->bfd_section->flags &= ~SEC_ALLOC;
          break;
        case noload_section:
-         output->bfd_section->flags &= ~SEC_LOAD;
+         output->bfd_section->flags &= ~ (SEC_LOAD | SEC_HAS_CONTENTS);
          output->bfd_section->flags |= SEC_NEVER_LOAD;
          break;
        }
@@ -1350,7 +1370,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;
@@ -1655,6 +1675,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);
@@ -2030,7 +2054,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;
@@ -2059,7 +2083,15 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
           }
           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
         {
@@ -2074,7 +2106,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 */
@@ -2152,21 +2184,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
@@ -2390,6 +2423,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:
@@ -2597,8 +2631,10 @@ lang_check ()
               bfd_printable_name (input_bfd), input_bfd,
               bfd_printable_name (output_bfd));
 
-      else
-       bfd_merge_private_bfd_data (input_bfd, output_bfd);
+      else if (! bfd_merge_private_bfd_data (input_bfd, output_bfd))
+       {
+         einfo ("%E%X: failed to merge target specific data of file %B\n", input_bfd);
+       }
     }
 }
 
@@ -2664,8 +2700,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)
     {
@@ -2923,7 +2961,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
@@ -3056,6 +3094,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 ();
@@ -3063,14 +3108,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 ();
@@ -3131,10 +3176,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 ();
@@ -3336,12 +3377,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;
 }
 
@@ -3499,22 +3542,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.  */
 
@@ -3528,7 +3555,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)
     {
@@ -3568,7 +3595,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;
@@ -3617,3 +3645,345 @@ 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->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);
+
+         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);
+
+         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);
+       }
+    }
+
+  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.030825 seconds and 4 git commands to generate.