* ld-scripts/crossref.exp: Compile test source with -mtiny=0 in order to
[deliverable/binutils-gdb.git] / ld / ldlang.c
index 92cb77df1172a0bfe5d198ff00431993f134f00b..b06cabd40b63f7965e2da2e88259fa4997362ca0 100644 (file)
@@ -3,22 +3,22 @@
    2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
 
-   This file is part of GLD, the Gnu Linker.
+   This file is part of the GNU Binutils.
 
-   GLD is free software; you can redistribute it and/or modify
+   This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
 
-   GLD is distributed in the hope that it will be useful,
+   This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with GLD; see the file COPYING.  If not, write to the Free
-   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
-   02110-1301, USA.  */
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
 #include "sysdep.h"
 #include "bfd.h"
@@ -1654,13 +1654,14 @@ lang_insert_orphan (asection *s,
                    case lang_output_section_statement_enum:
                      if (assign != NULL)
                        where = assign;
+                     break;
                    case lang_input_statement_enum:
                    case lang_address_statement_enum:
                    case lang_target_statement_enum:
                    case lang_output_statement_enum:
                    case lang_group_statement_enum:
                    case lang_afile_asection_pair_statement_enum:
-                     break;
+                     continue;
                    }
                  break;
                }
@@ -1810,6 +1811,7 @@ lang_map (void)
        bfd_map_over_sections (p, init_map_userdata, 0);
       bfd_link_hash_traverse (link_info.hash, sort_def_symbol, 0);
     }
+  lang_statement_iteration ++;
   print_statements ();
 }
 
@@ -3380,7 +3382,8 @@ 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)
+         if (!os->section_relative_symbol
+             && !os->update_dot_tree)
            os->ignored = TRUE;
          output_section->flags |= SEC_EXCLUDE;
          bfd_section_list_remove (output_bfd, output_section);
@@ -3537,7 +3540,7 @@ print_assignment (lang_assignment_statement_type *assignment,
              value = h->u.def.value;
 
              if (expld.result.section)
-             value += expld.result.section->vma;
+               value += expld.result.section->vma;
 
              minfo ("[0x%V]", value);
            }
@@ -4101,6 +4104,10 @@ sort_sections_by_lma (const void *arg1, const void *arg2)
   else if (bfd_section_lma (sec1->owner, sec1)
           > bfd_section_lma (sec2->owner, sec2))
     return 1;
+  else if (sec1->id < sec2->id)
+    return -1;
+  else if (sec1->id > sec2->id)
+    return 1;
 
   return 0;
 }
@@ -4242,13 +4249,12 @@ lang_size_sections_1
                os->processed_vma = FALSE;
                exp_fold_tree (os->addr_tree, bfd_abs_section_ptr, &dot);
 
-               if (!expld.result.valid_p
-                   && expld.phase != lang_mark_phase_enum)
+               if (expld.result.valid_p)
+                 dot = expld.result.value + expld.result.section->vma;
+               else if (expld.phase != lang_mark_phase_enum)
                  einfo (_("%F%S: non constant or forward reference"
                           " address expression for section %s\n"),
                         os->name);
-
-               dot = expld.result.value + expld.result.section->vma;
              }
 
            if (os->bfd_section == NULL)
@@ -4630,10 +4636,32 @@ lang_size_sections_1
            bfd_vma newdot = dot;
            etree_type *tree = s->assignment_statement.exp;
 
+           expld.dataseg.relro = exp_dataseg_relro_none;
+
            exp_fold_tree (tree,
                           output_section_statement->bfd_section,
                           &newdot);
 
+           if (expld.dataseg.relro == exp_dataseg_relro_start)
+             {
+               if (!expld.dataseg.relro_start_stat)
+                 expld.dataseg.relro_start_stat = s;
+               else
+                 {
+                   ASSERT (expld.dataseg.relro_start_stat == s);
+                 }
+             }
+           else if (expld.dataseg.relro == exp_dataseg_relro_end)
+             {
+               if (!expld.dataseg.relro_end_stat)
+                 expld.dataseg.relro_end_stat = s;
+               else
+                 {
+                   ASSERT (expld.dataseg.relro_end_stat == s);
+                 }
+             }
+           expld.dataseg.relro = exp_dataseg_relro_none;
+
            /* This symbol is relative to this section.  */
            if ((tree->type.node_class == etree_provided
                 || tree->type.node_class == etree_assign)
@@ -5156,7 +5184,7 @@ lang_check (void)
       if (compatible == NULL)
        {
          if (command_line.warn_mismatch)
-           einfo (_("%P: warning: %s architecture of input file `%B'"
+           einfo (_("%P%X: %s architecture of input file `%B'"
                     " is incompatible with %s output\n"),
                   bfd_printable_name (input_bfd), input_bfd,
                   bfd_printable_name (output_bfd));
@@ -5269,9 +5297,17 @@ lang_one_common (struct bfd_link_hash_entry *h, void *info)
 
       name = bfd_demangle (output_bfd, h->root.string,
                           DMGL_ANSI | DMGL_PARAMS);
-      minfo ("%s", name);
-      len = strlen (name);
-      free (name);
+      if (name == NULL)
+       {
+         minfo ("%s", h->root.string);
+         len = strlen (h->root.string);
+       }
+      else
+       {
+         minfo ("%s", name);
+         len = strlen (name);
+         free (name);
+       }
 
       if (len >= 19)
        {
@@ -5427,8 +5463,6 @@ lang_for_each_file (void (*func) (lang_input_statement_type *))
 void
 ldlang_add_file (lang_input_statement_type *entry)
 {
-  bfd **pp;
-
   lang_statement_append (&file_chain,
                         (lang_statement_union_type *) entry,
                         &entry->next);
@@ -5437,9 +5471,9 @@ ldlang_add_file (lang_input_statement_type *entry)
      a link.  */
   ASSERT (entry->the_bfd->link_next == NULL);
   ASSERT (entry->the_bfd != output_bfd);
-  for (pp = &link_info.input_bfds; *pp != NULL; pp = &(*pp)->link_next)
-    ;
-  *pp = entry->the_bfd;
+
+  *link_info.input_bfds_tail = entry->the_bfd;
+  link_info.input_bfds_tail = &entry->the_bfd->link_next;
   entry->the_bfd->usrdata = entry;
   bfd_set_gp_size (entry->the_bfd, g_switch_value);
 
@@ -5653,6 +5687,81 @@ lang_gc_sections (void)
     bfd_gc_sections (output_bfd, &link_info);
 }
 
+/* Worker for lang_find_relro_sections_1.  */
+
+static void
+find_relro_section_callback (lang_wild_statement_type *ptr ATTRIBUTE_UNUSED,
+                            struct wildcard_list *sec ATTRIBUTE_UNUSED,
+                            asection *section,
+                            lang_input_statement_type *file ATTRIBUTE_UNUSED,
+                            void *data)
+{
+  /* Discarded, excluded and ignored sections effectively have zero
+     size.  */
+  if (section->output_section != NULL
+      && section->output_section->owner == output_bfd
+      && (section->output_section->flags & SEC_EXCLUDE) == 0
+      && !IGNORE_SECTION (section)
+      && section->size != 0)
+    {
+      bfd_boolean *has_relro_section = (bfd_boolean *) data;
+      *has_relro_section = TRUE;
+    }
+}
+
+/* Iterate over sections for relro sections.  */
+
+static void
+lang_find_relro_sections_1 (lang_statement_union_type *s,
+                           bfd_boolean *has_relro_section)
+{
+  if (*has_relro_section)
+    return;
+
+  for (; s != NULL; s = s->header.next)
+    {
+      if (s == expld.dataseg.relro_end_stat)
+       break;
+
+      switch (s->header.type)
+       {
+       case lang_wild_statement_enum:
+         walk_wild (&s->wild_statement,
+                    find_relro_section_callback,
+                    has_relro_section);
+         break;
+       case lang_constructors_statement_enum:
+         lang_find_relro_sections_1 (constructor_list.head,
+                                     has_relro_section);
+         break;
+       case lang_output_section_statement_enum:
+         lang_find_relro_sections_1 (s->output_section_statement.children.head,
+                                     has_relro_section);
+         break;
+       case lang_group_statement_enum:
+         lang_find_relro_sections_1 (s->group_statement.children.head,
+                                     has_relro_section);
+         break;
+       default:
+         break;
+       }
+    }
+}
+
+static void
+lang_find_relro_sections (void)
+{
+  bfd_boolean has_relro_section = FALSE;
+
+  /* Check all sections in the link script.  */
+
+  lang_find_relro_sections_1 (expld.dataseg.relro_start_stat,
+                             &has_relro_section);
+
+  if (!has_relro_section)
+    link_info.relro = FALSE;
+}
+
 /* Relax all sections until bfd_relax_section gives up.  */
 
 static void
@@ -5780,6 +5889,10 @@ lang_process (void)
      section positions, since they will affect SIZEOF_HEADERS.  */
   lang_record_phdrs ();
 
+  /* Check relro sections.  */
+  if (link_info.relro && ! link_info.relocatable)
+    lang_find_relro_sections ();
+
   /* Size up the sections.  */
   lang_size_sections (NULL, !command_line.relax);
 
@@ -6252,9 +6365,7 @@ lang_record_phdrs (void)
                  || (os->bfd_section->flags & SEC_ALLOC) == 0)
                continue;
 
-             if (last)
-               pl = last;
-             else
+             if (last == NULL)
                {
                  lang_output_section_statement_type * tmp_os;
 
@@ -6268,9 +6379,14 @@ lang_record_phdrs (void)
                     http://sourceware.org/ml/binutils/2007-02/msg00291.html  */
                  for (tmp_os = os; tmp_os; tmp_os = tmp_os->next)
                    if (tmp_os->phdrs)
-                     break;
-                 pl = tmp_os->phdrs;
+                     {
+                       last = tmp_os->phdrs;
+                       break;
+                     }
+                 if (last == NULL)
+                   einfo (_("%F%P: no sections assigned to phdrs\n"));
                }
+             pl = last;
            }
 
          if (os->bfd_section == NULL)
This page took 0.027283 seconds and 4 git commands to generate.