* ld-elf/comm-data.exp: Add XFAIL for arm*-*-* targets, referring
[deliverable/binutils-gdb.git] / ld / ldlang.c
index f4eb703b71da0e8cfb2b2e7c1823f2323e585deb..680221122ad46824a3491dd84f774588bfa247e1 100644 (file)
@@ -1790,17 +1790,12 @@ lang_insert_orphan (asection *s,
       if (*ps == '\0')
        {
          char *symname;
-         etree_type *e_align;
 
          symname = (char *) xmalloc (ps - secname + sizeof "__start_" + 1);
          symname[0] = bfd_get_symbol_leading_char (link_info.output_bfd);
          sprintf (symname + (symname[0] != 0), "__start_%s", secname);
-         e_align = exp_unop (ALIGN_K,
-                             exp_intop ((bfd_vma) 1 << s->alignment_power));
-         lang_add_assignment (exp_assign (".", e_align));
          lang_add_assignment (exp_provide (symname,
-                                           exp_unop (ABSOLUTE,
-                                                     exp_nameop (NAME, ".")),
+                                           exp_nameop (NAME, "."),
                                            FALSE));
        }
     }
@@ -2467,7 +2462,9 @@ wild_sort (lang_wild_statement_type *wild,
       /* Here either the files are not sorted by name, or we are
         looking at the sections for this file.  */
 
-      if (sec != NULL && sec->spec.sorted != none)
+      if (sec != NULL
+         && sec->spec.sorted != none
+         && sec->spec.sorted != by_none)
        if (compare_section (sec->spec.sorted, section, ls->section) < 0)
          break;
     }
@@ -2673,6 +2670,7 @@ load_symbols (lang_input_statement_type *entry,
     {
       bfd_error_type err;
       struct lang_input_statement_flags save_flags;
+      extern FILE *yyin;
 
       err = bfd_get_error ();
 
@@ -2720,6 +2718,9 @@ load_symbols (lang_input_statement_type *entry,
       save_flags.missing_file |= input_flags.missing_file;
       input_flags = save_flags;
       pop_stat_ptr ();
+      fclose (yyin);
+      yyin = NULL;
+      entry->flags.loaded = TRUE;
 
       return TRUE;
     }
@@ -2741,7 +2742,7 @@ load_symbols (lang_input_statement_type *entry,
       if (!entry->flags.reload)
 #endif
        ldlang_add_file (entry);
-      if (trace_files || trace_file_tries)
+      if (trace_files || verbose)
        info_msg ("%I\n", entry);
       break;
 
@@ -3229,6 +3230,7 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
 #endif
                  && !s->input_statement.flags.whole_archive
                  && s->input_statement.flags.loaded
+                 && s->input_statement.the_bfd != NULL
                  && bfd_check_format (s->input_statement.the_bfd,
                                       bfd_archive))
                s->input_statement.flags.loaded = FALSE;
@@ -3238,6 +3240,7 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
                       && plugin_insert == NULL
                       && s->input_statement.flags.loaded
                       && s->input_statement.flags.add_DT_NEEDED_for_regular
+                      && s->input_statement.the_bfd != NULL
                       && ((s->input_statement.the_bfd->flags) & DYNAMIC) != 0
                       && plugin_should_reload (s->input_statement.the_bfd))
                {
@@ -3283,7 +3286,7 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
 #endif
          break;
        case lang_assignment_statement_enum:
-         if (s->assignment_statement.exp->assign.hidden)
+         if (s->assignment_statement.exp->assign.defsym)
            /* This is from a --defsym on the command line.  */
            exp_fold_tree_no_dot (s->assignment_statement.exp);
          break;
@@ -3493,7 +3496,6 @@ update_wild_statements (lang_statement_union_type *s)
              break;
 
            case lang_wild_statement_enum:
-             sec = s->wild_statement.section_list;
              for (sec = s->wild_statement.section_list; sec != NULL;
                   sec = sec->next)
                {
@@ -3521,8 +3523,11 @@ update_wild_statements (lang_statement_union_type *s)
              break;
 
            case lang_output_section_statement_enum:
-             update_wild_statements
-               (s->output_section_statement.children.head);
+             /* Don't sort .init/.fini sections.  */
+             if (strcmp (s->output_section_statement.name, ".init") != 0
+                 && strcmp (s->output_section_statement.name, ".fini") != 0)
+               update_wild_statements
+                 (s->output_section_statement.children.head);
              break;
 
            case lang_group_statement_enum:
@@ -3889,8 +3894,7 @@ strip_excluded_output_sections (void)
        {
          /* We don't set bfd_section to NULL since bfd_section of the
             removed output section statement may still be used.  */
-         if (!os->section_relative_symbol
-             && !os->update_dot_tree)
+         if (!os->update_dot)
            os->ignored = TRUE;
          output_section->flags |= SEC_EXCLUDE;
          bfd_section_list_remove (link_info.output_bfd, output_section);
@@ -4590,7 +4594,8 @@ insert_pad (lang_statement_union_type **ptr,
     }
   pad->padding_statement.output_offset = dot - output_section->vma;
   pad->padding_statement.size = alignment_needed;
-  output_section->size += alignment_needed;
+  output_section->size = TO_SIZE (dot + TO_ADDR (alignment_needed)
+                                 - output_section->vma);
 }
 
 /* Work out how much this section will move the dot point.  */
@@ -5155,7 +5160,9 @@ lang_size_sections_1
            if (size < TO_SIZE ((unsigned) 1))
              size = TO_SIZE ((unsigned) 1);
            dot += TO_ADDR (size);
-           output_section_statement->bfd_section->size += size;
+           output_section_statement->bfd_section->size
+             = TO_SIZE (dot - output_section_statement->bfd_section->vma);
+
          }
          break;
 
@@ -5169,7 +5176,8 @@ lang_size_sections_1
              output_section_statement->bfd_section;
            size = bfd_get_reloc_size (s->reloc_statement.howto);
            dot += TO_ADDR (size);
-           output_section_statement->bfd_section->size += size;
+           output_section_statement->bfd_section->size
+             = TO_SIZE (dot - output_section_statement->bfd_section->vma);
          }
          break;
 
@@ -5248,12 +5256,12 @@ lang_size_sections_1
              }
            expld.dataseg.relro = exp_dataseg_relro_none;
 
-           /* This symbol is relative to this section.  */
+           /* This symbol may be relative to this section.  */
            if ((tree->type.node_class == etree_provided
                 || tree->type.node_class == etree_assign)
                && (tree->assign.dst [0] != '.'
                    || tree->assign.dst [1] != '\0'))
-             output_section_statement->section_relative_symbol = 1;
+             output_section_statement->update_dot = 1;
 
            if (!output_section_statement->ignored)
              {
@@ -5467,13 +5475,18 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions)
     expld.dataseg.phase = exp_dataseg_done;
 }
 
+static lang_output_section_statement_type *current_section;
+static lang_assignment_statement_type *current_assign;
+static bfd_boolean prefer_next_section;
+
 /* Worker function for lang_do_assignments.  Recursiveness goes here.  */
 
 static bfd_vma
 lang_do_assignments_1 (lang_statement_union_type *s,
                       lang_output_section_statement_type *current_os,
                       fill_type *fill,
-                      bfd_vma dot)
+                      bfd_vma dot,
+                      bfd_boolean *found_end)
 {
   for (; s != NULL; s = s->header.next)
     {
@@ -5481,7 +5494,7 @@ lang_do_assignments_1 (lang_statement_union_type *s,
        {
        case lang_constructors_statement_enum:
          dot = lang_do_assignments_1 (constructor_list.head,
-                                      current_os, fill, dot);
+                                      current_os, fill, dot, found_end);
          break;
 
        case lang_output_section_statement_enum:
@@ -5489,11 +5502,18 @@ lang_do_assignments_1 (lang_statement_union_type *s,
            lang_output_section_statement_type *os;
 
            os = &(s->output_section_statement);
+           os->after_end = *found_end;
            if (os->bfd_section != NULL && !os->ignored)
              {
+               if ((os->bfd_section->flags & SEC_ALLOC) != 0)
+                 {
+                   current_section = os;
+                   prefer_next_section = FALSE;
+                 }
                dot = os->bfd_section->vma;
 
-               lang_do_assignments_1 (os->children.head, os, os->fill, dot);
+               lang_do_assignments_1 (os->children.head,
+                                      os, os->fill, dot, found_end);
 
                /* .tbss sections effectively have zero size.  */
                if ((os->bfd_section->flags & SEC_HAS_CONTENTS) != 0
@@ -5510,7 +5530,7 @@ lang_do_assignments_1 (lang_statement_union_type *s,
        case lang_wild_statement_enum:
 
          dot = lang_do_assignments_1 (s->wild_statement.children.head,
-                                      current_os, fill, dot);
+                                      current_os, fill, dot, found_end);
          break;
 
        case lang_object_symbols_statement_enum:
@@ -5581,6 +5601,19 @@ lang_do_assignments_1 (lang_statement_union_type *s,
          break;
 
        case lang_assignment_statement_enum:
+         current_assign = &s->assignment_statement;
+         if (current_assign->exp->type.node_class != etree_assert)
+           {
+             const char *p = current_assign->exp->assign.dst;
+
+             if (current_os == abs_output_section && p[0] == '.' && p[1] == 0)
+               prefer_next_section = TRUE;
+
+             while (*p == '_')
+               ++p;
+             if (strcmp (p, "end") == 0)
+               *found_end = TRUE;
+           }
          exp_fold_tree (s->assignment_statement.exp,
                         current_os->bfd_section,
                         &dot);
@@ -5592,7 +5625,7 @@ lang_do_assignments_1 (lang_statement_union_type *s,
 
        case lang_group_statement_enum:
          dot = lang_do_assignments_1 (s->group_statement.children.head,
-                                      current_os, fill, dot);
+                                      current_os, fill, dot, found_end);
          break;
 
        case lang_insert_statement_enum:
@@ -5612,9 +5645,89 @@ lang_do_assignments_1 (lang_statement_union_type *s,
 void
 lang_do_assignments (lang_phase_type phase)
 {
+  bfd_boolean found_end = FALSE;
+
+  current_section = NULL;
+  prefer_next_section = FALSE;
   expld.phase = phase;
   lang_statement_iteration++;
-  lang_do_assignments_1 (statement_list.head, abs_output_section, NULL, 0);
+  lang_do_assignments_1 (statement_list.head,
+                        abs_output_section, NULL, 0, &found_end);
+}
+
+/* For an assignment statement outside of an output section statement,
+   choose the best of neighbouring output sections to use for values
+   of "dot".  */
+
+asection *
+section_for_dot (void)
+{
+  asection *s;
+
+  /* Assignments belong to the previous output section, unless there
+     has been an assignment to "dot", in which case following
+     assignments belong to the next output section.  (The assumption
+     is that an assignment to "dot" is setting up the address for the
+     next output section.)  Except that past the assignment to "_end"
+     we always associate with the previous section.  This exception is
+     for targets like SH that define an alloc .stack or other
+     weirdness after non-alloc sections.  */
+  if (current_section == NULL || prefer_next_section)
+    {
+      lang_statement_union_type *stmt;
+      lang_output_section_statement_type *os;
+
+      for (stmt = (lang_statement_union_type *) current_assign;
+          stmt != NULL;
+          stmt = stmt->header.next)
+       if (stmt->header.type == lang_output_section_statement_enum)
+         break;
+
+      os = &stmt->output_section_statement;
+      while (os != NULL
+            && !os->after_end
+            && (os->bfd_section == NULL
+                || (os->bfd_section->flags & SEC_EXCLUDE) != 0
+                || bfd_section_removed_from_list (link_info.output_bfd,
+                                                  os->bfd_section)))
+       os = os->next;
+
+      if (current_section == NULL || os == NULL || !os->after_end)
+       {
+         if (os != NULL)
+           s = os->bfd_section;
+         else
+           s = link_info.output_bfd->section_last;
+         while (s != NULL
+                && ((s->flags & SEC_ALLOC) == 0
+                    || (s->flags & SEC_THREAD_LOCAL) != 0))
+           s = s->prev;
+         if (s != NULL)
+           return s;
+
+         return bfd_abs_section_ptr;
+       }
+    }
+
+  s = current_section->bfd_section;
+
+  /* The section may have been stripped.  */
+  while (s != NULL
+        && ((s->flags & SEC_EXCLUDE) != 0
+            || (s->flags & SEC_ALLOC) == 0
+            || (s->flags & SEC_THREAD_LOCAL) != 0
+            || bfd_section_removed_from_list (link_info.output_bfd, s)))
+    s = s->prev;
+  if (s == NULL)
+    s = link_info.output_bfd->sections;
+  while (s != NULL
+        && ((s->flags & SEC_ALLOC) == 0
+            || (s->flags & SEC_THREAD_LOCAL) != 0))
+    s = s->next;
+  if (s != NULL)
+    return s;
+
+  return bfd_abs_section_ptr;
 }
 
 /* Fix any .startof. or .sizeof. symbols.  When the assemblers see the
@@ -5646,8 +5759,8 @@ lang_set_startof (void)
       if (h != NULL && h->type == bfd_link_hash_undefined)
        {
          h->type = bfd_link_hash_defined;
-         h->u.def.value = bfd_get_section_vma (link_info.output_bfd, s);
-         h->u.def.section = bfd_abs_section_ptr;
+         h->u.def.value = 0;
+         h->u.def.section = s;
        }
 
       sprintf (buf, ".sizeof.%s", secname);
@@ -6133,8 +6246,6 @@ lang_add_output (const char *name, int from_script)
     }
 }
 
-static lang_output_section_statement_type *current_section;
-
 static int
 topower (int x)
 {
@@ -6942,69 +7053,6 @@ lang_leave_output_section_statement (fill_type *fill, const char *memspec,
   pop_stat_ptr ();
 }
 
-/* Create an absolute symbol with the given name with the value of the
-   address of first byte of the section named.
-
-   If the symbol already exists, then do nothing.  */
-
-void
-lang_abs_symbol_at_beginning_of (const char *secname, const char *name)
-{
-  struct bfd_link_hash_entry *h;
-
-  h = bfd_link_hash_lookup (link_info.hash, name, TRUE, TRUE, TRUE);
-  if (h == NULL)
-    einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
-
-  if (h->type == bfd_link_hash_new
-      || h->type == bfd_link_hash_undefined)
-    {
-      asection *sec;
-
-      h->type = bfd_link_hash_defined;
-
-      sec = bfd_get_section_by_name (link_info.output_bfd, secname);
-      if (sec == NULL)
-       h->u.def.value = 0;
-      else
-       h->u.def.value = bfd_get_section_vma (link_info.output_bfd, sec);
-
-      h->u.def.section = bfd_abs_section_ptr;
-    }
-}
-
-/* Create an absolute symbol with the given name with the value of the
-   address of the first byte after the end of the section named.
-
-   If the symbol already exists, then do nothing.  */
-
-void
-lang_abs_symbol_at_end_of (const char *secname, const char *name)
-{
-  struct bfd_link_hash_entry *h;
-
-  h = bfd_link_hash_lookup (link_info.hash, name, TRUE, TRUE, TRUE);
-  if (h == NULL)
-    einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
-
-  if (h->type == bfd_link_hash_new
-      || h->type == bfd_link_hash_undefined)
-    {
-      asection *sec;
-
-      h->type = bfd_link_hash_defined;
-
-      sec = bfd_get_section_by_name (link_info.output_bfd, secname);
-      if (sec == NULL)
-       h->u.def.value = 0;
-      else
-       h->u.def.value = (bfd_get_section_vma (link_info.output_bfd, sec)
-                         + TO_ADDR (sec->size));
-
-      h->u.def.section = bfd_abs_section_ptr;
-    }
-}
-
 void
 lang_statement_append (lang_statement_list_type *list,
                       lang_statement_union_type *element,
@@ -7390,8 +7438,11 @@ lang_leave_overlay (etree_type *lma_expr,
   /* After setting the size of the last section, set '.' to end of the
      overlay region.  */
   if (overlay_list != NULL)
-    overlay_list->os->update_dot_tree
-      = exp_assign (".", exp_binop ('+', overlay_vma, overlay_max));
+    {
+      overlay_list->os->update_dot = 1;
+      overlay_list->os->update_dot_tree
+       = exp_assign (".", exp_binop ('+', overlay_vma, overlay_max), FALSE);
+    }
 
   l = overlay_list;
   while (l != NULL)
This page took 0.029558 seconds and 4 git commands to generate.