2002-01-29 Chris Demetriou <cgd@broadcom.com>
[deliverable/binutils-gdb.git] / ld / ldlang.c
index 968144a9d69428fec2c43545f07ffc3f599424cc..a7b53dd1b0f6a0c57eaa2f216ab08e48d59f558c 100644 (file)
@@ -1,6 +1,6 @@
 /* Linker command language support.
    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001
+   2001, 2002
    Free Software Foundation, Inc.
 
 This file is part of GLD, the Gnu Linker.
@@ -23,6 +23,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "bfd.h"
 #include "sysdep.h"
 #include "libiberty.h"
+#include "safe-ctype.h"
 #include "obstack.h"
 #include "bfdlink.h"
 
@@ -39,8 +40,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "fnmatch.h"
 #include "demangle.h"
 
-#include <ctype.h>
-
 /* FORWARDS */
 static lang_statement_union_type *new_statement
   PARAMS ((enum statement_enum, size_t, lang_statement_list_type *));
@@ -119,12 +118,12 @@ static void print_statement
 static void print_statement_list
   PARAMS ((lang_statement_union_type *, lang_output_section_statement_type *));
 static void print_statements PARAMS ((void));
-static bfd_vma insert_pad
+static void insert_pad
   PARAMS ((lang_statement_union_type **, fill_type,
           unsigned int, asection *, bfd_vma));
 static bfd_vma size_input_section
   PARAMS ((lang_statement_union_type **, lang_output_section_statement_type *,
-          fill_type, bfd_vma, boolean));
+          fill_type, bfd_vma));
 static void lang_finish PARAMS ((void));
 static void ignore_bfd_errors PARAMS ((const char *, ...));
 static void lang_check PARAMS ((void));
@@ -252,47 +251,59 @@ walk_wild_section (ptr, file, callback, data)
       struct wildcard_list *sec;
 
       sec = ptr->section_list;
-      do
+      if (sec == NULL)
+       (*callback) (ptr, sec, s, file, data);
+
+      while (sec != NULL)
        {
          boolean skip = false;
+         struct name_list *list_tmp;
 
-         if (sec != NULL)
+         /* Don't process sections from files which were
+            excluded.  */
+         for (list_tmp = sec->spec.exclude_name_list;
+              list_tmp;
+              list_tmp = list_tmp->next)
            {
-             struct name_list *list_tmp;
+             if (wildcardp (list_tmp->name))
+               skip = fnmatch (list_tmp->name, file->filename, 0) == 0;
+             else
+               skip = strcmp (list_tmp->name, file->filename) == 0;
 
-             /* Don't process sections from files which were
-                excluded.  */
-             for (list_tmp = sec->spec.exclude_name_list;
-                  list_tmp;
-                  list_tmp = list_tmp->next)
+             /* If this file is part of an archive, and the archive is
+                excluded, exclude this file.  */
+             if (! skip && file->the_bfd != NULL
+                 && file->the_bfd->my_archive != NULL
+                 && file->the_bfd->my_archive->filename != NULL)
                {
                  if (wildcardp (list_tmp->name))
-                   skip = fnmatch (list_tmp->name, file->filename, 0) == 0;
+                   skip = fnmatch (list_tmp->name,
+                                   file->the_bfd->my_archive->filename,
+                                   0) == 0;
                  else
-                   skip = strcmp (list_tmp->name, file->filename) == 0;
-
-                 if (skip)
-                   break;
+                   skip = strcmp (list_tmp->name,
+                                  file->the_bfd->my_archive->filename) == 0;
                }
 
-             if (!skip && sec->spec.name != NULL)
-               {
-                 const char *sname = bfd_get_section_name (file->the_bfd, s);
+             if (skip)
+               break;
+           }
 
-                 if (wildcardp (sec->spec.name))
-                   skip = fnmatch (sec->spec.name, sname, 0) != 0;
-                 else
-                   skip = strcmp (sec->spec.name, sname) != 0;
-               }
+         if (!skip && sec->spec.name != NULL)
+           {
+             const char *sname = bfd_get_section_name (file->the_bfd, s);
+
+             if (wildcardp (sec->spec.name))
+               skip = fnmatch (sec->spec.name, sname, 0) != 0;
+             else
+               skip = strcmp (sec->spec.name, sname) != 0;
            }
 
          if (!skip)
            (*callback) (ptr, sec, s, file, data);
 
-         if (sec != NULL)
-           sec = sec->next;
+         sec = sec->next;
        }
-      while (sec != NULL);
     }
 }
 
@@ -377,7 +388,7 @@ lang_for_each_statement_worker (func, s)
      void (*func) PARAMS ((lang_statement_union_type *));
      lang_statement_union_type *s;
 {
-  for (; s != (lang_statement_union_type *) NULL; s = s->next)
+  for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
     {
       func (s);
 
@@ -1012,13 +1023,10 @@ section_already_linked (abfd, sec, data)
              break;
            }
 
-         /* Set the output_section field so that wild_doit does not
-            create a lang_input_section structure for this section.
-            Since there might be a symbol in the section being
-            discarded, we must retain a pointer to the section which
-            we are really going to use.  */
+         /* Set the output_section field so that lang_add_section
+            does not create a lang_input_section structure for this
+            section.  */
          sec->output_section = bfd_abs_section_ptr;
-         sec->kept_section = l->sec;
 
          return;
        }
@@ -1076,7 +1084,7 @@ already_linked_table_free ()
 /* 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.
+   be enough to cause the pattern to be treated as a wildcard.
    That lets us handle DOS filenames more naturally.  */
 
 static boolean
@@ -1098,7 +1106,7 @@ wildcardp (pattern)
    input file which holds SECTION.  */
 
 void
-wild_doit (ptr, section, output, file)
+lang_add_section (ptr, section, output, file)
      lang_statement_list_type *ptr;
      asection *section;
      lang_output_section_statement_type *output;
@@ -1259,7 +1267,7 @@ wild_sort (wild, sec, file, section)
     return NULL;
 
   section_name = bfd_get_section_name (file->the_bfd, section);
-  for (l = wild->children.head; l != NULL; l = l->next)
+  for (l = wild->children.head; l != NULL; l = l->header.next)
     {
       lang_input_section_type *ls;
 
@@ -1372,31 +1380,31 @@ output_section_callback (ptr, sec, section, file, output)
      of the current list.  */
 
   if (before == NULL)
-    wild_doit (&ptr->children, section,
-              (lang_output_section_statement_type *) output,
-              file);
+    lang_add_section (&ptr->children, section,
+                     (lang_output_section_statement_type *) output,
+                     file);
   else
     {
       lang_statement_list_type list;
       lang_statement_union_type **pp;
 
       lang_list_init (&list);
-      wild_doit (&list, section,
-                (lang_output_section_statement_type *) output,
-                file);
+      lang_add_section (&list, section,
+                       (lang_output_section_statement_type *) output,
+                       file);
 
       /* If we are discarding the section, LIST.HEAD will
         be NULL.  */
       if (list.head != NULL)
        {
-         ASSERT (list.head->next == NULL);
+         ASSERT (list.head->header.next == NULL);
 
          for (pp = &ptr->children.head;
               *pp != before;
-              pp = &(*pp)->next)
+              pp = &(*pp)->header.next)
            ASSERT (*pp != NULL);
 
-         list.head->next = *pp;
+         list.head->header.next = *pp;
          *pp = list.head;
        }
     }
@@ -1618,12 +1626,7 @@ stricpy (dest, src)
   char c;
 
   while ((c = *src++) != 0)
-    {
-      if (isupper ((unsigned char) c))
-       c = tolower (c);
-
-      *dest++ = c;
-    }
+    *dest++ = TOLOWER (c);
 
   *dest = 0;
 }
@@ -1906,7 +1909,7 @@ open_input_bfds (s, force)
      lang_statement_union_type *s;
      boolean force;
 {
-  for (; s != (lang_statement_union_type *) NULL; s = s->next)
+  for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
     {
       switch (s->header.type)
        {
@@ -1967,8 +1970,8 @@ open_input_bfds (s, force)
 
              if (add.head != NULL)
                {
-                 *add.tail = s->next;
-                 s->next = add.head;
+                 *add.tail = s->header.next;
+                 s->header.next = add.head;
                }
            }
          break;
@@ -2062,12 +2065,13 @@ map_input_to_output_sections (s, target, output_section_statement)
      const char *target;
      lang_output_section_statement_type *output_section_statement;
 {
-  for (; s != (lang_statement_union_type *) NULL; s = s->next)
+  for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
     {
       switch (s->header.type)
        {
        case lang_wild_statement_enum:
          wild (&s->wild_statement, target, output_section_statement);
+         break;
        case lang_constructors_statement_enum:
          map_input_to_output_sections (constructor_list.head,
                                        target,
@@ -2513,7 +2517,7 @@ print_statement_list (s, os)
   while (s != NULL)
     {
       print_statement (s, os);
-      s = s->next;
+      s = s->header.next;
     }
 }
 
@@ -2619,94 +2623,97 @@ dprint_statement (s, n)
       while (s && --n >= 0)
        {
          print_statement (s, abs_output_section);
-         s = s->next;
+         s = s->header.next;
        }
     }
 
   config.map_file = map_save;
 }
 
-static bfd_vma
-insert_pad (this_ptr, fill, power, output_section_statement, dot)
-     lang_statement_union_type **this_ptr;
+static void
+insert_pad (ptr, fill, alignment_needed, output_section, dot)
+     lang_statement_union_type **ptr;
      fill_type fill;
-     unsigned int power;
-     asection *output_section_statement;
+     unsigned int alignment_needed;
+     asection *output_section;
      bfd_vma dot;
 {
-  /* Align this section first to the
-     input sections requirement, then
-     to the output section's requirement.
-     If this alignment is > than any seen before,
-     then record it too. Perform the alignment by
-     inserting a magic 'padding' statement.  */
-
-  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
-                                               ldfile_output_machine);
-  unsigned int alignment_needed = align_power (dot, power) - dot;
+  lang_statement_union_type *pad;
 
-  if (alignment_needed != 0)
+  pad = ((lang_statement_union_type *)
+        ((char *) ptr - offsetof (lang_statement_union_type, header.next)));
+  if (ptr != &statement_list.head
+      && pad->header.type == lang_padding_statement_enum
+      && pad->padding_statement.output_section == output_section)
     {
-      lang_statement_union_type *new =
-       ((lang_statement_union_type *)
-        stat_alloc (sizeof (lang_padding_statement_type)));
-
-      /* Link into existing chain.  */
-      new->header.next = *this_ptr;
-      *this_ptr = new;
-      new->header.type = lang_padding_statement_enum;
-      new->padding_statement.output_section = output_section_statement;
-      new->padding_statement.output_offset =
-       dot - output_section_statement->vma;
-      new->padding_statement.fill = fill;
-      new->padding_statement.size = alignment_needed * opb;
+      /* Use the existing pad statement.  The above test on output
+        section is probably redundant, but it doesn't hurt to check.  */
     }
-
-  /* Remember the most restrictive alignment.  */
-  if (power > output_section_statement->alignment_power)
+  else
     {
-      output_section_statement->alignment_power = power;
+      /* Make a new padding statement, linked into existing chain.  */
+      pad = ((lang_statement_union_type *)
+            stat_alloc (sizeof (lang_padding_statement_type)));
+      pad->header.next = *ptr;
+      *ptr = pad;
+      pad->header.type = lang_padding_statement_enum;
+      pad->padding_statement.output_section = output_section;
+      pad->padding_statement.fill = fill;
     }
-  output_section_statement->_raw_size += alignment_needed * opb;
-
-  return dot + alignment_needed;
+  pad->padding_statement.output_offset = dot - output_section->vma;
+  pad->padding_statement.size = alignment_needed;
+  output_section->_raw_size += alignment_needed;
 }
 
 /* Work out how much this section will move the dot point.  */
 
 static bfd_vma
-size_input_section (this_ptr, output_section_statement, fill, dot, relax)
+size_input_section (this_ptr, output_section_statement, fill, dot)
      lang_statement_union_type **this_ptr;
      lang_output_section_statement_type *output_section_statement;
      fill_type fill;
      bfd_vma dot;
-     boolean relax ATTRIBUTE_UNUSED;
 {
   lang_input_section_type *is = &((*this_ptr)->input_section);
   asection *i = is->section;
-  unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
-                                               ldfile_output_machine);
 
   if (is->ifile->just_syms_flag == false)
     {
+      unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
+                                                   ldfile_output_machine);
+      unsigned int alignment_needed;
+      asection *o;
+
+      /* Align this section first to the input sections requirement,
+        then to the output section's requirement.  If this alignment
+        is greater than any seen before, then record it too.  Perform
+        the alignment by inserting a magic 'padding' statement.  */
+
       if (output_section_statement->subsection_alignment != -1)
-       i->alignment_power =
-       output_section_statement->subsection_alignment;
+       i->alignment_power = output_section_statement->subsection_alignment;
+
+      o = output_section_statement->bfd_section;
+      if (o->alignment_power < i->alignment_power)
+       o->alignment_power = i->alignment_power;
+
+      alignment_needed = align_power (dot, i->alignment_power) - dot;
 
-      dot = insert_pad (this_ptr, fill, i->alignment_power,
-                       output_section_statement->bfd_section, dot);
+      if (alignment_needed != 0)
+       {
+         insert_pad (this_ptr, fill, alignment_needed * opb, o, dot);
+         dot += alignment_needed;
+       }
 
       /* Remember where in the output section this input section goes.  */
 
-      i->output_offset = dot - output_section_statement->bfd_section->vma;
+      i->output_offset = dot - o->vma;
 
       /* Mark how big the output section must be to contain this now.  */
       if (i->_cooked_size != 0)
        dot += i->_cooked_size / opb;
       else
        dot += i->_raw_size / opb;
-      output_section_statement->bfd_section->_raw_size =
-       (dot - output_section_statement->bfd_section->vma) * opb;
+      o->_raw_size = (dot - o->vma) * opb;
     }
   else
     {
@@ -2777,11 +2784,6 @@ _("%X%P: section %s [%V -> %V] overlaps section %s [%V -> %V]\n"),
     }
 }
 
-/* This variable indicates whether bfd_relax_section should be called
-   again.  */
-
-static boolean relax_again;
-
 /* Make sure the new address is within the region.  We explicitly permit the
    current address to be at the exact end of the region when the address is
    non-zero, in case the region is at the end of addressable memory and the
@@ -2828,13 +2830,13 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
      lang_statement_union_type **prev;
      fill_type fill;
      bfd_vma dot;
-     boolean relax;
+     boolean *relax;
 {
   unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
                                                ldfile_output_machine);
 
   /* Size up the sections from their constituent parts.  */
-  for (; s != (lang_statement_union_type *) NULL; s = s->next)
+  for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
     {
       switch (s->header.type)
        {
@@ -2857,7 +2859,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
                asection *input;
 
                if (os->children.head == NULL
-                   || os->children.head->next != NULL
+                   || os->children.head->header.next != NULL
                    || os->children.head->header.type != lang_input_section_enum)
                  einfo (_("%P%X: Internal error on COFF shared library section %s\n"),
                         os->name);
@@ -2947,9 +2949,8 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
                os->bfd_section->output_offset = 0;
              }
 
-           (void) lang_size_sections (os->children.head, os,
-                                      &os->children.head,
-                                      os->fill, dot, relax);
+           lang_size_sections (os->children.head, os, &os->children.head,
+                               os->fill, dot, relax);
 
            /* Put the section within the requested block size, or
               align at the block boundary.  */
@@ -3020,8 +3021,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
          dot = lang_size_sections (constructor_list.head,
                                    output_section_statement,
                                    &s->wild_statement.children.head,
-                                   fill,
-                                   dot, relax);
+                                   fill, dot, relax);
          break;
 
        case lang_data_statement_enum:
@@ -3113,12 +3113,10 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
                if (! bfd_relax_section (i->owner, i, &link_info, &again))
                  einfo (_("%P%F: can't relax section: %E\n"));
                if (again)
-                 relax_again = true;
+                 *relax = true;
              }
-           dot = size_input_section (prev,
-                                     output_section_statement,
-                                     output_section_statement->fill,
-                                     dot, relax);
+           dot = size_input_section (prev, output_section_statement,
+                                     output_section_statement->fill, dot);
          }
          break;
        case lang_input_statement_enum:
@@ -3141,31 +3139,22 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
 
            if (newdot != dot)
              {
-               /* The assignment changed dot.  Insert a pad.  */
                if (output_section_statement == abs_output_section)
                  {
                    /* If we don't have an output section, then just adjust
                       the default memory address.  */
                    lang_memory_region_lookup ("*default*")->current = newdot;
                  }
-               else if (!relax)
+               else
                  {
-                   lang_statement_union_type *new =
-                     ((lang_statement_union_type *)
-                      stat_alloc (sizeof (lang_padding_statement_type)));
-
-                   /* Link into existing chain.  */
-                   new->header.next = *prev;
-                   *prev = new;
-                   new->header.type = lang_padding_statement_enum;
-                   new->padding_statement.output_section =
-                     output_section_statement->bfd_section;
-                   new->padding_statement.output_offset =
-                     dot - output_section_statement->bfd_section->vma;
-                   new->padding_statement.fill = fill;
-                   new->padding_statement.size = (newdot - dot) * opb;
-                   output_section_statement->bfd_section->_raw_size +=
-                     new->padding_statement.size;
+                   /* Insert a pad after this statement.  We can't
+                      put the pad before when relaxing, in case the
+                      assignment references dot.  */
+                   insert_pad (&s->header.next, fill, (newdot - dot) * opb,
+                               output_section_statement->bfd_section, dot);
+
+                   /* Don't neuter the pad below when relaxing.  */
+                   s = s->header.next;
                  }
 
                dot = newdot;
@@ -3174,16 +3163,20 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
          break;
 
        case lang_padding_statement_enum:
-         /* If we are relaxing, and this is not the first pass, some
-            padding statements may have been inserted during previous
-            passes.  We may have to move the padding statement to a new
-            location if dot has a different value at this point in this
-            pass than it did at this point in the previous pass.  */
-         s->padding_statement.output_offset =
-           dot - output_section_statement->bfd_section->vma;
-         dot += s->padding_statement.size / opb;
-         output_section_statement->bfd_section->_raw_size +=
-           s->padding_statement.size;
+         /* If this is the first time lang_size_sections is called,
+            we won't have any padding statements.  If this is the
+            second or later passes when relaxing, we should allow
+            padding to shrink.  If padding is needed on this pass, it
+            will be added back in.  */
+         s->padding_statement.size = 0;
+
+         /* Make sure output_offset is valid.  If relaxation shrinks
+            the section and this pad isn't needed, it's possible to
+            have output_offset larger than the final size of the
+            section.  bfd_set_section_contents will complain even for
+            a pad size of zero.  */
+         s->padding_statement.output_offset
+           = dot - output_section_statement->bfd_section->vma;
          break;
 
        case lang_group_statement_enum:
@@ -3197,8 +3190,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
          FAIL ();
          break;
 
-         /* This can only get here when relaxing is turned on.  */
-
+         /* We can only get here when relaxing is turned on.  */
        case lang_address_statement_enum:
          break;
        }
@@ -3217,7 +3209,7 @@ lang_do_assignments (s, output_section_statement, fill, dot)
   unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
                                                ldfile_output_machine);
 
-  for (; s != (lang_statement_union_type *) NULL; s = s->next)
+  for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
     {
       switch (s->header.type)
        {
@@ -3579,6 +3571,8 @@ lang_check ()
 static void
 lang_common ()
 {
+  if (command_line.inhibit_common_definition)
+    return;
   if (link_info.relocateable
       && ! command_line.force_common_definition)
     return;
@@ -3739,18 +3733,18 @@ lang_place_orphans ()
                            lang_output_section_statement_lookup (".bss");
 
                        }
-                     wild_doit (&default_common_section->children, s,
-                                default_common_section, file);
+                     lang_add_section (&default_common_section->children, s,
+                                       default_common_section, file);
                    }
                }
              else if (ldemul_place_orphan (file, s))
                ;
              else
                {
-                 lang_output_section_statement_type *os =
-                 lang_output_section_statement_lookup (s->name);
+                 lang_output_section_statement_type *os;
 
-                 wild_doit (&os->children, s, os, file);
+                 os = lang_output_section_statement_lookup (s->name);
+                 lang_add_section (&os->children, s, os, file);
                }
            }
        }
@@ -3982,6 +3976,7 @@ static void
 reset_memory_regions ()
 {
   lang_memory_region_type *p = lang_memory_region_list;
+  asection *o;
 
   for (p = lang_memory_region_list;
        p != (lang_memory_region_type *) NULL;
@@ -3990,6 +3985,9 @@ reset_memory_regions ()
       p->old_length = (bfd_size_type) (p->current - p->origin);
       p->current = p->origin;
     }
+
+  for (o = output_bfd->sections; o != NULL; o = o->next)
+    o->_raw_size = 0;
 }
 
 /* If the wild pattern was marked KEEP, the member sections
@@ -4022,12 +4020,13 @@ static void
 lang_gc_sections_1 (s)
      lang_statement_union_type *s;
 {
-  for (; s != (lang_statement_union_type *) NULL; s = s->next)
+  for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
     {
       switch (s->header.type)
        {
        case lang_wild_statement_enum:
          lang_gc_wild (&s->wild_statement);
+         break;
        case lang_constructors_statement_enum:
          lang_gc_sections_1 (constructor_list.head);
          break;
@@ -4148,16 +4147,17 @@ lang_process ()
      section positions, since they will affect SIZEOF_HEADERS.  */
   lang_record_phdrs ();
 
+  /* Size up the sections.  */
+  lang_size_sections (statement_list.head,
+                     abs_output_section,
+                     &statement_list.head, 0, (bfd_vma) 0, NULL);
+
   /* Now run around and relax if we can.  */
   if (command_line.relax)
     {
-      /* First time round is a trial run to get the 'worst case'
-        addresses of the objects if there was no relaxing.  */
-      lang_size_sections (statement_list.head,
-                         abs_output_section,
-                         &(statement_list.head), 0, (bfd_vma) 0, false);
-
       /* Keep relaxing until bfd_relax_section gives up.  */
+      boolean relax_again;
+
       do
        {
          reset_memory_regions ();
@@ -4178,17 +4178,11 @@ lang_process ()
             globals are, so can make better guess.  */
          lang_size_sections (statement_list.head,
                              abs_output_section,
-                             &(statement_list.head), 0, (bfd_vma) 0, true);
+                             &(statement_list.head), 0, (bfd_vma) 0,
+                             &relax_again);
        }
       while (relax_again);
     }
-  else
-    {
-      /* Size up the sections.  */
-      lang_size_sections (statement_list.head,
-                         abs_output_section,
-                         &(statement_list.head), 0, (bfd_vma) 0, false);
-    }
 
   /* See if anything special should be done now we know how big
      everything is.  */
@@ -4807,7 +4801,7 @@ lang_leave_overlay_section (fill, phdrs)
   clean = xmalloc (strlen (name) + 1);
   s2 = clean;
   for (s1 = name; *s1 != '\0'; s1++)
-    if (isalnum ((unsigned char) *s1) || *s1 == '_')
+    if (ISALNUM (*s1) || *s1 == '_')
       *s2++ = *s1;
   *s2 = '\0';
 
@@ -5052,6 +5046,16 @@ lang_register_vers_node (name, version, deps)
   struct bfd_elf_version_tree *t, **pp;
   struct bfd_elf_version_expr *e1;
 
+  if (name == NULL)
+    name = "";
+
+  if ((name[0] == '\0' && lang_elf_version_info != NULL)
+      || (lang_elf_version_info && lang_elf_version_info->name[0] == '\0'))
+    {
+      einfo (_("%X%P: anonymous version tag cannot be combined with other version tags\n"));
+      return;
+    }
+
   /* 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)
@@ -5088,8 +5092,13 @@ lang_register_vers_node (name, version, deps)
 
   version->deps = deps;
   version->name = name;
-  ++version_index;
-  version->vernum = version_index;
+  if (name[0] != '\0')
+    {
+      ++version_index;
+      version->vernum = version_index;
+    }
+  else
+    version->vernum = 0;
 
   for (pp = &lang_elf_version_info; *pp != NULL; pp = &(*pp)->next)
     ;
This page took 0.033863 seconds and 4 git commands to generate.