* amd64obsd-tdep.c (amd64obsd_sigtramp_p): Adjust for new
[deliverable/binutils-gdb.git] / ld / ldlang.c
index d2b5fed74a690beb36843c3f0b5eeb4b0983a909..7ff8be0dcb888641507070fc815251bfa9a3dd2c 100644 (file)
@@ -47,6 +47,7 @@
 
 /* Locals variables.  */
 static struct obstack stat_obstack;
+static struct obstack map_obstack;
 
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
@@ -65,6 +66,7 @@ static struct bfd_hash_table lang_definedness_table;
 
 /* Forward declarations.  */
 static void exp_init_os (etree_type *);
+static void init_map_userdata (bfd *, asection *, void *);
 static bfd_boolean wildcardp (const char *);
 static lang_input_statement_type *lookup_name (const char *);
 static bfd_boolean load_symbols (lang_input_statement_type *,
@@ -72,6 +74,8 @@ static bfd_boolean load_symbols (lang_input_statement_type *,
 static struct bfd_hash_entry *lang_definedness_newfunc
  (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
 static void insert_undefined (const char *);
+static void print_all_symbols (asection *);
+static bfd_boolean sort_def_symbol (struct bfd_link_hash_entry *, void *);
 static void print_statement (lang_statement_union_type *,
                             lang_output_section_statement_type *);
 static void print_statement_list (lang_statement_union_type *,
@@ -302,13 +306,11 @@ lang_for_each_statement_worker (void (*func) (lang_statement_union_type *),
          break;
        case lang_output_section_statement_enum:
          lang_for_each_statement_worker
-           (func,
-            s->output_section_statement.children.head);
+           (func, s->output_section_statement.children.head);
          break;
        case lang_wild_statement_enum:
-         lang_for_each_statement_worker
-           (func,
-            s->wild_statement.children.head);
+         lang_for_each_statement_worker (func,
+                                         s->wild_statement.children.head);
          break;
        case lang_group_statement_enum:
          lang_for_each_statement_worker (func,
@@ -522,7 +524,8 @@ lang_init (void)
   and so we issue a warning.  */
 
 static lang_memory_region_type *lang_memory_region_list;
-static lang_memory_region_type **lang_memory_region_list_tail = &lang_memory_region_list;
+static lang_memory_region_type **lang_memory_region_list_tail
+  = &lang_memory_region_list;
 
 lang_memory_region_type *
 lang_memory_region_lookup (const char *const name, bfd_boolean create)
@@ -538,7 +541,8 @@ lang_memory_region_lookup (const char *const name, bfd_boolean create)
     if (strcmp (p->name, name) == 0)
       {
        if (create)
-         einfo (_("%P:%S: warning: redeclaration of memory region '%s'\n"), name);
+         einfo (_("%P:%S: warning: redeclaration of memory region '%s'\n"),
+                name);
        return p;
       }
 
@@ -598,8 +602,8 @@ lang_memory_default (asection *section)
   return lang_memory_region_lookup (DEFAULT_MEMORY_REGION, FALSE);
 }
 
-lang_output_section_statement_type *
-lang_output_section_find (const char *const name)
+static lang_output_section_statement_type *
+lang_output_section_find_1 (const char *const name, int constraint)
 {
   lang_statement_union_type *u;
   lang_output_section_statement_type *lookup;
@@ -607,18 +611,26 @@ lang_output_section_find (const char *const name)
   for (u = lang_output_section_statement.head; u != NULL; u = lookup->next)
     {
       lookup = &u->output_section_statement;
-      if (strcmp (name, lookup->name) == 0)
+      if (strcmp (name, lookup->name) == 0
+         && lookup->constraint != -1
+         && (constraint == 0 || constraint == lookup->constraint))
        return lookup;
     }
   return NULL;
 }
 
 lang_output_section_statement_type *
-lang_output_section_statement_lookup (const char *const name)
+lang_output_section_find (const char *const name)
+{
+  return lang_output_section_find_1 (name, 0);
+}
+
+static lang_output_section_statement_type *
+lang_output_section_statement_lookup_1 (const char *const name, int constraint)
 {
   lang_output_section_statement_type *lookup;
 
-  lookup = lang_output_section_find (name);
+  lookup = lang_output_section_find_1 (name, constraint);
   if (lookup == NULL)
     {
       lookup = new_stat (lang_output_section_statement, stat_ptr);
@@ -631,6 +643,7 @@ lang_output_section_statement_lookup (const char *const name)
       lookup->next = NULL;
       lookup->bfd_section = NULL;
       lookup->processed = 0;
+      lookup->constraint = constraint;
       lookup->sectype = normal_section;
       lookup->addr_tree = NULL;
       lang_list_init (&lookup->children);
@@ -650,6 +663,12 @@ lang_output_section_statement_lookup (const char *const name)
   return lookup;
 }
 
+lang_output_section_statement_type *
+lang_output_section_statement_lookup (const char *const name)
+{
+  return lang_output_section_statement_lookup_1 (name, 0);
+}
+
 static void
 lang_map_flags (flagword flag)
 {
@@ -673,6 +692,7 @@ void
 lang_map (void)
 {
   lang_memory_region_type *m;
+  bfd *p;
 
   minfo (_("\nMemory Configuration\n\n"));
   fprintf (config.map_file, "%-16s %-18s %-18s %s\n",
@@ -718,15 +738,66 @@ lang_map (void)
 
   fprintf (config.map_file, _("\nLinker script and memory map\n\n"));
 
+  if (! command_line.reduce_memory_overheads)
+    {
+      obstack_begin (&map_obstack, 1000);
+      for (p = link_info.input_bfds; p != (bfd *) NULL; p = p->link_next)
+       bfd_map_over_sections (p, init_map_userdata, 0);
+      bfd_link_hash_traverse (link_info.hash, sort_def_symbol, 0);
+    }
   print_statements ();
 }
 
+static void
+init_map_userdata (abfd, sec, data)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asection *sec;
+     void *data ATTRIBUTE_UNUSED;
+{
+  fat_section_userdata_type *new_data
+    = ((fat_section_userdata_type *) (stat_alloc
+                                     (sizeof (fat_section_userdata_type))));
+
+  ASSERT (get_userdata (sec) == NULL);
+  get_userdata (sec) = new_data;
+  new_data->map_symbol_def_tail = &new_data->map_symbol_def_head;
+}
+
+static bfd_boolean
+sort_def_symbol (hash_entry, info)
+     struct bfd_link_hash_entry *hash_entry;
+     void *info ATTRIBUTE_UNUSED;
+{
+  if (hash_entry->type == bfd_link_hash_defined
+      || hash_entry->type == bfd_link_hash_defweak)
+    {
+      struct fat_user_section_struct *ud;
+      struct map_symbol_def *def;
+
+      ud = get_userdata (hash_entry->u.def.section);
+      if  (! ud)
+       {
+         /* ??? What do we have to do to initialize this beforehand?  */
+         /* The first time we get here is bfd_abs_section...  */
+         init_map_userdata (0, hash_entry->u.def.section, 0);
+         ud = get_userdata (hash_entry->u.def.section);
+       }
+      else if  (!ud->map_symbol_def_tail)
+       ud->map_symbol_def_tail = &ud->map_symbol_def_head;
+      def = obstack_alloc (&map_obstack, sizeof *def);
+      def->entry = hash_entry;
+      *ud->map_symbol_def_tail = def;
+      ud->map_symbol_def_tail = &def->next;
+    }
+  return TRUE;
+}
+
 /* Initialize an output section.  */
 
 static void
 init_os (lang_output_section_statement_type *s)
 {
-  section_userdata_type *new;
+  lean_section_userdata_type *new;
 
   if (s->bfd_section != NULL)
     return;
@@ -734,7 +805,7 @@ init_os (lang_output_section_statement_type *s)
   if (strcmp (s->name, DISCARD_SECTION_NAME) == 0)
     einfo (_("%P%F: Illegal use of `%s' section\n"), DISCARD_SECTION_NAME);
 
-  new = stat_alloc (sizeof (section_userdata_type));
+  new = stat_alloc (SECTION_USERDATA_SIZE);
 
   s->bfd_section = bfd_get_section_by_name (output_bfd, s->name);
   if (s->bfd_section == NULL)
@@ -859,8 +930,7 @@ section_already_linked (bfd *abfd, asection *sec, void *data)
       return;
     }
 
-  flags = bfd_get_section_flags (abfd, sec);
-
+  flags = sec->flags;
   if ((flags & SEC_LINK_ONCE) == 0)
     return;
 
@@ -908,7 +978,8 @@ section_already_linked (bfd *abfd, asection *sec, void *data)
                einfo (_("%P: %B: warning: ignoring duplicate section `%s'\n"),
                       abfd, name);
              else
-               einfo (_("%P: %B: warning: ignoring duplicate `%s' section symbol `%s'\n"),
+               einfo (_("%P: %B: warning: ignoring duplicate `%s'"
+                        " section symbol `%s'\n"),
                       abfd, name, sec->comdat->name);
              break;
 
@@ -922,7 +993,8 @@ section_already_linked (bfd *abfd, asection *sec, void *data)
            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\n"),
+               einfo (_("%P: %B: warning: duplicate section `%s'"
+                        " has different size\n"),
                       abfd, name);
              break;
            }
@@ -1018,19 +1090,11 @@ lang_add_section (lang_statement_list_type *ptr,
                  lang_output_section_statement_type *output,
                  lang_input_statement_type *file)
 {
-  flagword flags;
+  flagword flags = section->flags;
   bfd_boolean discard;
 
-  flags = bfd_get_section_flags (section->owner, section);
-
-  discard = FALSE;
-
-  /* Discard sections marked with SEC_EXCLUDE if we are doing a final
-     link.  Discard debugging sections marked with SEC_EXCLUDE on a
-     relocatable link too.  */
-  if ((flags & SEC_EXCLUDE) != 0
-      && ((flags & SEC_DEBUGGING) != 0 || !link_info.relocatable))
-    discard = TRUE;
+  /* Discard sections marked with SEC_EXCLUDE.  */
+  discard = (flags & SEC_EXCLUDE) != 0;
 
   /* Discard input sections which are assigned to a section named
      DISCARD_SECTION_NAME.  */
@@ -1272,11 +1336,6 @@ output_section_callback (lang_wild_statement_type *ptr,
   if (unique_section_p (section))
     return;
 
-  /* If the wild pattern was marked KEEP, the member sections
-     should be as well.  */
-  if (ptr->keep_sections)
-    section->flags |= SEC_KEEP;
-
   before = wild_sort (ptr, sec, file, section);
 
   /* Here BEFORE points to the lang_input_section which
@@ -1315,6 +1374,24 @@ output_section_callback (lang_wild_statement_type *ptr,
     }
 }
 
+/* Check if all sections in a wild statement for a particular FILE
+   are readonly.  */
+
+static void
+check_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)
+{
+  /* Exclude sections that match UNIQUE_SECTION_LIST.  */
+  if (unique_section_p (section))
+    return;
+
+  if (section->output_section == NULL && (section->flags & SEC_READONLY) == 0)
+    ((lang_output_section_statement_type *) data)->all_input_readonly = FALSE;
+}
+
 /* This is passed a file name which must have been seen already and
    added to the statement tree.  We will see if it has been opened
    already and had its symbols read.  If not then we'll read it.  */
@@ -1342,8 +1419,8 @@ lookup_name (const char *name)
     }
 
   if (search == NULL)
-    search = new_afile (name, lang_input_file_is_search_file_enum, default_target,
-                       FALSE);
+    search = new_afile (name, lang_input_file_is_search_file_enum,
+                       default_target, FALSE);
 
   /* If we have already added this file, or this file is not real
      (FIXME: can that ever actually happen?) or the name is NULL
@@ -1737,7 +1814,8 @@ open_output (const char *name)
                  /* Oh dear - we could not find any targets that
                     satisfy our requirements.  */
                  if (winner == NULL)
-                   einfo (_("%P: warning: could not find any targets that match endianness requirement\n"));
+                   einfo (_("%P: warning: could not find any targets"
+                            " that match endianness requirement\n"));
                  else
                    output_target = winner->name;
                }
@@ -2068,6 +2146,41 @@ lang_place_undefineds (void)
     insert_undefined (ptr->name);
 }
 
+/* Check for all readonly or some readwrite sections.  */
+
+static void
+check_input_sections
+  (lang_statement_union_type *s,
+   lang_output_section_statement_type *output_section_statement)
+{
+  for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
+    {
+      switch (s->header.type)
+      {
+      case lang_wild_statement_enum:
+       walk_wild (&s->wild_statement, check_section_callback,
+                  output_section_statement);
+       if (! output_section_statement->all_input_readonly)
+         return;
+       break;
+      case lang_constructors_statement_enum:
+       check_input_sections (constructor_list.head,
+                             output_section_statement);
+       if (! output_section_statement->all_input_readonly)
+         return;
+       break;
+      case lang_group_statement_enum:
+       check_input_sections (s->group_statement.children.head,
+                             output_section_statement);
+       if (! output_section_statement->all_input_readonly)
+         return;
+       break;
+      default:
+       break;
+      }
+    }
+}
+
 /* Open input files and attach to output sections.  */
 
 static void
@@ -2088,6 +2201,23 @@ map_input_to_output_sections
                                        output_section_statement);
          break;
        case lang_output_section_statement_enum:
+         if (s->output_section_statement.constraint)
+           {
+             if (s->output_section_statement.constraint == -1)
+               break;
+             s->output_section_statement.all_input_readonly = TRUE;
+             check_input_sections (s->output_section_statement.children.head,
+                                   &s->output_section_statement);
+             if ((s->output_section_statement.all_input_readonly
+                  && s->output_section_statement.constraint == ONLY_IF_RW)
+                 || (!s->output_section_statement.all_input_readonly
+                     && s->output_section_statement.constraint == ONLY_IF_RO))
+               {
+                 s->output_section_statement.constraint = -1;
+                 break;
+               }
+           }
+
          map_input_to_output_sections (s->output_section_statement.children.head,
                                        target,
                                        &s->output_section_statement);
@@ -2162,6 +2292,8 @@ strip_excluded_output_sections (void)
       asection *s;
 
       os = &u->output_section_statement;
+      if (os->constraint == -1)
+       continue;
       s = os->bfd_section;
       if (s != NULL && (s->flags & SEC_EXCLUDE) != 0)
        {
@@ -2275,7 +2407,7 @@ print_input_statement (lang_input_statement_type *statm)
 }
 
 /* Print all symbols defined in a particular section.  This is called
-   via bfd_link_hash_traverse.  */
+   via bfd_link_hash_traverse, or by print_all_symbols.  */
 
 static bfd_boolean
 print_one_symbol (struct bfd_link_hash_entry *hash_entry, void *ptr)
@@ -2301,6 +2433,18 @@ print_one_symbol (struct bfd_link_hash_entry *hash_entry, void *ptr)
   return TRUE;
 }
 
+static void
+print_all_symbols (sec)
+     asection *sec;
+{
+  struct fat_user_section_struct *ud = get_userdata (sec);
+  struct map_symbol_def *def;
+
+  *ud->map_symbol_def_tail = 0;
+  for (def = ud->map_symbol_def_head; def; def = def->next)
+    print_one_symbol (def->entry, sec);
+}
+
 /* Print information about an input section to the map file.  */
 
 static void
@@ -2312,51 +2456,59 @@ print_input_section (lang_input_section_type *in)
   init_opb ();
   if (size != 0)
     {
-      print_space ();
+      int len;
+      bfd_vma addr;
 
+      print_space ();
       minfo ("%s", i->name);
 
-      if (i->output_section != NULL)
+      len = 1 + strlen (i->name);
+      if (len >= SECTION_NAME_MAP_LENGTH - 1)
+       {
+         print_nl ();
+         len = 0;
+       }
+      while (len < SECTION_NAME_MAP_LENGTH)
        {
-         int len;
+         print_space ();
+         ++len;
+       }
 
-         len = 1 + strlen (i->name);
-         if (len >= SECTION_NAME_MAP_LENGTH - 1)
-           {
-             print_nl ();
-             len = 0;
-           }
-         while (len < SECTION_NAME_MAP_LENGTH)
-           {
-             print_space ();
-             ++len;
-           }
+      if (i->output_section != NULL && (i->flags & SEC_EXCLUDE) == 0)
+       addr = i->output_section->vma + i->output_offset;
+      else
+       {
+         addr = print_dot;
+         size = 0;
+       }
 
-         minfo ("0x%V %W %B\n",
-                i->output_section->vma + i->output_offset, TO_ADDR (size),
-                i->owner);
+      minfo ("0x%V %W %B\n", addr, TO_ADDR (size), i->owner);
 
-         if (i->_cooked_size != 0 && i->_cooked_size != i->_raw_size)
-           {
-             len = SECTION_NAME_MAP_LENGTH + 3;
+      if (size != i->_raw_size)
+       {
+         len = SECTION_NAME_MAP_LENGTH + 3;
 #ifdef BFD64
-             len += 16;
+         len += 16;
 #else
-             len += 8;
+         len += 8;
 #endif
-             while (len > 0)
-               {
-                 print_space ();
-                 --len;
-               }
-
-             minfo (_("%W (size before relaxing)\n"), i->_raw_size);
+         while (len > 0)
+           {
+             print_space ();
+             --len;
            }
 
-         bfd_link_hash_traverse (link_info.hash, print_one_symbol, i);
+         minfo (_("%W (size before relaxing)\n"), i->_raw_size);
+       }
 
-         print_dot = (i->output_section->vma + i->output_offset
-                      + TO_ADDR (size));
+      if (i->output_section != NULL && (i->flags & SEC_EXCLUDE) == 0)
+       {
+         if (command_line.reduce_memory_overheads)
+           bfd_link_hash_traverse (link_info.hash, print_one_symbol, i);
+         else
+           print_all_symbols (i);
+
+         print_dot = addr + TO_ADDR (size);
        }
     }
 }
@@ -2490,7 +2642,7 @@ print_padding_statement (lang_padding_statement_type *s)
   addr = s->output_offset;
   if (s->output_section != NULL)
     addr += s->output_section->vma;
-  minfo ("0x%V %W ", addr, s->size);
+  minfo ("0x%V %W ", addr, (bfd_vma) s->size);
 
   if (s->fill->size != 0)
     {
@@ -2721,15 +2873,16 @@ insert_pad (lang_statement_union_type **ptr,
 /* Work out how much this section will move the dot point.  */
 
 static bfd_vma
-size_input_section (lang_statement_union_type **this_ptr,
-                   lang_output_section_statement_type *output_section_statement,
-                   fill_type *fill,
-                   bfd_vma dot)
+size_input_section
+  (lang_statement_union_type **this_ptr,
+   lang_output_section_statement_type *output_section_statement,
+   fill_type *fill,
+   bfd_vma dot)
 {
   lang_input_section_type *is = &((*this_ptr)->input_section);
   asection *i = is->section;
 
-  if (!is->ifile->just_syms_flag)
+  if (!is->ifile->just_syms_flag && (i->flags & SEC_EXCLUDE) == 0)
     {
       unsigned int alignment_needed;
       asection *o;
@@ -2774,11 +2927,9 @@ size_input_section (lang_statement_union_type **this_ptr,
 }
 
 #define IGNORE_SECTION(bfd, s) \
-  (((bfd_get_section_flags (bfd, s) & SEC_THREAD_LOCAL)                        \
-    ? ((bfd_get_section_flags (bfd, s) & (SEC_LOAD | SEC_NEVER_LOAD))  \
-       != SEC_LOAD)                                                    \
-    :  ((bfd_get_section_flags (bfd, s) & (SEC_ALLOC | SEC_NEVER_LOAD)) \
-       != SEC_ALLOC))                                                  \
+  (((s->flags & SEC_THREAD_LOCAL) != 0                         \
+    ? (s->flags & (SEC_LOAD | SEC_NEVER_LOAD)) != SEC_LOAD     \
+    : (s->flags & (SEC_ALLOC | SEC_NEVER_LOAD)) != SEC_ALLOC)  \
    || bfd_section_size (bfd, s) == 0)
 
 /* Check to see if any allocated sections overlap with other allocated
@@ -2854,7 +3005,8 @@ os_region_check (lang_output_section_statement_type *os,
     {
       if (tree != NULL)
        {
-         einfo (_("%X%P: address 0x%v of %B section %s is not within region %s\n"),
+         einfo (_("%X%P: address 0x%v of %B section %s"
+                  " is not within region %s\n"),
                 region->current,
                 os->bfd_section->owner,
                 os->bfd_section->name,
@@ -2909,9 +3061,10 @@ lang_size_sections_1
 
                if (os->children.head == 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);
+                   || (os->children.head->header.type
+                       != lang_input_section_enum))
+                 einfo (_("%P%X: Internal error on COFF shared library"
+                          " section %s\n"), os->name);
 
                input = os->children.head->input_section.section;
                bfd_set_section_vma (os->bfd_section->owner,
@@ -2933,10 +3086,10 @@ lang_size_sections_1
                    /* No address specified for this section, get one
                       from the region specification.  */
                    if (os->region == NULL
-                       || (((bfd_get_section_flags (output_bfd, os->bfd_section)
-                             & (SEC_ALLOC | SEC_LOAD)) != 0)
+                       || ((os->bfd_section->flags & (SEC_ALLOC | SEC_LOAD))
                            && os->region->name[0] == '*'
-                           && strcmp (os->region->name, DEFAULT_MEMORY_REGION) == 0))
+                           && strcmp (os->region->name,
+                                      DEFAULT_MEMORY_REGION) == 0))
                      {
                        os->region = lang_memory_default (os->bfd_section);
                      }
@@ -2947,7 +3100,8 @@ lang_size_sections_1
                    if (!IGNORE_SECTION (output_bfd, os->bfd_section)
                        && ! link_info.relocatable
                        && check_regions
-                       && strcmp (os->region->name, DEFAULT_MEMORY_REGION) == 0
+                       && strcmp (os->region->name,
+                                  DEFAULT_MEMORY_REGION) == 0
                        && lang_memory_region_list != NULL
                        && (strcmp (lang_memory_region_list->name,
                                    DEFAULT_MEMORY_REGION) != 0
@@ -2958,16 +3112,18 @@ lang_size_sections_1
                           default memory region we can end up creating an
                           excessively large binary, or even seg faulting when
                           attempting to perform a negative seek.  See
-                            http://sources.redhat.com/ml/binutils/2003-04/msg00423.html
+                          sources.redhat.com/ml/binutils/2003-04/msg00423.html
                           for an example of this.  This behaviour can be
                           overridden by the using the --no-check-sections
                           switch.  */
                        if (command_line.check_section_addresses)
-                         einfo (_("%P%F: error: no memory region specified for loadable section `%s'\n"),
+                         einfo (_("%P%F: error: no memory region specified"
+                                  " for loadable section `%s'\n"),
                                 bfd_get_section_name (output_bfd,
                                                       os->bfd_section));
                        else
-                         einfo (_("%P: warning: no memory region specified for loadable section `%s'\n"),
+                         einfo (_("%P: warning: no memory region specified"
+                                  " for loadable section `%s'\n"),
                                 bfd_get_section_name (output_bfd,
                                                       os->bfd_section));
                      }
@@ -2983,7 +3139,8 @@ lang_size_sections_1
                                           os->bfd_section->alignment_power);
 
                        if (dot != olddot && config.warn_section_align)
-                         einfo (_("%P: warning: changing start of section %s by %u bytes\n"),
+                         einfo (_("%P: warning: changing start of section"
+                                  " %s by %u bytes\n"),
                                 os->name, (unsigned int) (dot - olddot));
                      }
                  }
@@ -2999,7 +3156,8 @@ lang_size_sections_1
                    os->processed = 0;
                    
                    if (!r.valid_p)
-                     einfo (_("%F%S: non constant or forward reference address expression for section %s\n"),
+                     einfo (_("%F%S: non constant or forward reference"
+                              " address expression for section %s\n"),
                             os->name);
 
                    dot = r.value + r.section->bfd_section->vma;
@@ -3054,10 +3212,8 @@ lang_size_sections_1
               addresses of sections after it. We have to update
               dot.  */
            if (os->region != NULL
-               && ((bfd_get_section_flags (output_bfd, os->bfd_section)
-                    & SEC_NEVER_LOAD) == 0
-                   || (bfd_get_section_flags (output_bfd, os->bfd_section)
-                       & (SEC_ALLOC | SEC_LOAD))))
+               && ((os->bfd_section->flags & SEC_NEVER_LOAD) == 0
+                   || (os->bfd_section->flags & (SEC_ALLOC | SEC_LOAD))))
              {
                os->region->current = dot;
 
@@ -3216,7 +3372,8 @@ lang_size_sections_1
                  {
                    /* If we don't have an output section, then just adjust
                       the default memory address.  */
-                   lang_memory_region_lookup (DEFAULT_MEMORY_REGION, FALSE)->current = newdot;
+                   lang_memory_region_lookup (DEFAULT_MEMORY_REGION,
+                                              FALSE)->current = newdot;
                  }
                else
                  {
@@ -3233,7 +3390,8 @@ lang_size_sections_1
                /* If dot is advanced, this implies that the section should
                   have space allocated to it, unless the user has explicitly
                   stated that the section should never be loaded.  */
-               if (!(output_section_statement->flags & (SEC_NEVER_LOAD | SEC_ALLOC)))
+               if (!(output_section_statement->flags
+                     & (SEC_NEVER_LOAD | SEC_ALLOC)))
                  output_section_statement->bfd_section->flags |= SEC_ALLOC;
 
                dot = newdot;
@@ -3297,7 +3455,19 @@ lang_size_sections
   exp_data_seg.phase = exp_dataseg_none;
   result = lang_size_sections_1 (s, output_section_statement, prev, fill,
                                 dot, relax, check_regions);
-  if (exp_data_seg.phase == exp_dataseg_end_seen)
+  if (exp_data_seg.phase == exp_dataseg_end_seen
+      && link_info.relro && exp_data_seg.relro_end)
+    {
+      /* If DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END pair was seen, try
+        to put exp_data_seg.relro on a (common) page boundary.  */
+
+      exp_data_seg.phase = exp_dataseg_relro_adjust;
+      result = lang_size_sections_1 (s, output_section_statement, prev, fill,
+                                    dot, relax, check_regions);
+      link_info.relro_start = exp_data_seg.base;
+      link_info.relro_end = exp_data_seg.relro_end;
+    }
+  else if (exp_data_seg.phase == exp_dataseg_end_seen)
     {
       /* If DATA_SEGMENT_ALIGN DATA_SEGMENT_END pair was seen, check whether
         a page could be saved in the data segment.  */
@@ -3447,10 +3617,13 @@ lang_do_assignments_1
          {
            asection *in = s->input_section.section;
 
-           if (in->_cooked_size != 0)
-             dot += TO_ADDR (in->_cooked_size);
-           else
-             dot += TO_ADDR (in->_raw_size);
+           if ((in->flags & SEC_EXCLUDE) == 0)
+             {
+               if (in->_cooked_size != 0)
+                 dot += TO_ADDR (in->_cooked_size);
+               else
+                 dot += TO_ADDR (in->_raw_size);
+             }
          }
          break;
 
@@ -3492,10 +3665,11 @@ lang_do_assignments_1
 }
 
 void
-lang_do_assignments (lang_statement_union_type *s,
-                    lang_output_section_statement_type *output_section_statement,
-                    fill_type *fill,
-                    bfd_vma dot)
+lang_do_assignments
+  (lang_statement_union_type *s,
+   lang_output_section_statement_type *output_section_statement,
+   fill_type *fill,
+   bfd_vma dot)
 {
   /* Callers of exp_fold_tree need to increment this.  */
   lang_statement_iteration++;
@@ -3609,7 +3783,8 @@ lang_finish (void)
          if (ts != NULL)
            {
              if (warn)
-               einfo (_("%P: warning: cannot find entry symbol %s; defaulting to %V\n"),
+               einfo (_("%P: warning: cannot find entry symbol %s;"
+                        " defaulting to %V\n"),
                       entry_symbol.name,
                       bfd_get_section_vma (output_bfd, ts));
              if (! bfd_set_start_address (output_bfd,
@@ -3620,7 +3795,8 @@ lang_finish (void)
          else
            {
              if (warn)
-               einfo (_("%P: warning: cannot find entry symbol %s; not setting start address\n"),
+               einfo (_("%P: warning: cannot find entry symbol %s;"
+                        " not setting start address\n"),
                       entry_symbol.name);
            }
        }
@@ -3652,8 +3828,9 @@ lang_check (void)
   for (file = file_chain.head; file != NULL; file = file->input_statement.next)
     {
       input_bfd = file->input_statement.the_bfd;
-      compatible = bfd_arch_get_compatible (input_bfd, output_bfd,
-                                           command_line.accept_unknown_input_arch);
+      compatible
+       = bfd_arch_get_compatible (input_bfd, output_bfd,
+                                  command_line.accept_unknown_input_arch);
 
       /* In general it is not possible to perform a relocatable
         link between differing object formats when the input
@@ -3666,7 +3843,8 @@ lang_check (void)
              || bfd_get_flavour (input_bfd) != bfd_get_flavour (output_bfd))
          && (bfd_get_file_flags (input_bfd) & HAS_RELOC) != 0)
        {
-         einfo (_("%P%F: Relocatable linking with relocations from format %s (%B) to format %s (%B) is not supported\n"),
+         einfo (_("%P%F: Relocatable linking with relocations from"
+                  " format %s (%B) to format %s (%B) is not supported\n"),
                 bfd_get_target (input_bfd), input_bfd,
                 bfd_get_target (output_bfd), output_bfd);
          /* einfo with %F exits.  */
@@ -3675,7 +3853,8 @@ lang_check (void)
       if (compatible == NULL)
        {
          if (command_line.warn_mismatch)
-           einfo (_("%P: warning: %s architecture of input file `%B' is incompatible with %s output\n"),
+           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));
        }
@@ -3696,8 +3875,8 @@ lang_check (void)
          if (! bfd_merge_private_bfd_data (input_bfd, output_bfd))
            {
              if (command_line.warn_mismatch)
-               einfo (_("%P%X: failed to merge target specific data of file %B\n"),
-                      input_bfd);
+               einfo (_("%P%X: failed to merge target specific data"
+                        " of file %B\n"), input_bfd);
            }
          if (! command_line.warn_mismatch)
            bfd_set_error_handler (pfn);
@@ -3840,9 +4019,10 @@ lang_place_orphans (void)
                 around for a sensible place for it to go.  */
 
              if (file->just_syms_flag)
-               {
-                 abort ();
-               }
+               abort ();
+
+             if ((s->flags & SEC_EXCLUDE) != 0)
+               s->output_section = bfd_abs_section_ptr;
              else if (strcmp (s->name, "COMMON") == 0)
                {
                  /* This is a lonely common section which must have
@@ -3857,7 +4037,8 @@ lang_place_orphans (void)
                          /* 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"));
+                         info_msg (_("%P: no [COMMON] command,"
+                                     " defaulting to .bss\n"));
 #endif
                          default_common_section =
                            lang_output_section_statement_lookup (".bss");
@@ -4017,13 +4198,15 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
                                     enum section_type sectype,
                                     etree_type *align,
                                     etree_type *subalign,
-                                    etree_type *ebase)
+                                    etree_type *ebase,
+                                    int constraint)
 {
   lang_output_section_statement_type *os;
 
   current_section =
    os =
-    lang_output_section_statement_lookup (output_section_statement_name);
+    lang_output_section_statement_lookup_1 (output_section_statement_name,
+                                           constraint);
 
   /* Add this statement to tree.  */
 #if 0
@@ -4080,8 +4263,7 @@ lang_reset_memory_regions (void)
     o->_raw_size = 0;
 }
 
-/* If the wild pattern was marked KEEP, the member sections
-   should be as well.  */
+/* Worker for lang_gc_sections_1.  */
 
 static void
 gc_section_callback (lang_wild_statement_type *ptr,
@@ -4090,18 +4272,12 @@ gc_section_callback (lang_wild_statement_type *ptr,
                     lang_input_statement_type *file ATTRIBUTE_UNUSED,
                     void *data ATTRIBUTE_UNUSED)
 {
+  /* If the wild pattern was marked KEEP, the member sections
+     should be as well.  */
   if (ptr->keep_sections)
     section->flags |= SEC_KEEP;
 }
 
-/* Handle a wild statement, marking it against GC.  */
-
-static void
-lang_gc_wild (lang_wild_statement_type *s)
-{
-  walk_wild (s, gc_section_callback, NULL);
-}
-
 /* Iterate over sections marking them against GC.  */
 
 static void
@@ -4112,7 +4288,7 @@ lang_gc_sections_1 (lang_statement_union_type *s)
       switch (s->header.type)
        {
        case lang_wild_statement_enum:
-         lang_gc_wild (&s->wild_statement);
+         walk_wild (&s->wild_statement, gc_section_callback, NULL);
          break;
        case lang_constructors_statement_enum:
          lang_gc_sections_1 (constructor_list.head);
@@ -4156,7 +4332,22 @@ lang_gc_sections (void)
        }
     }
 
-  bfd_gc_sections (output_bfd, &link_info);
+  /* SEC_EXCLUDE is ignored when doing a relocatable link, except in
+     the special case of debug info.  (See bfd/stabs.c)
+     Twiddle the flag here, to simplify later linker code.  */
+  if (link_info.relocatable)
+    {
+      LANG_FOR_EACH_INPUT_STATEMENT (f)
+       {
+         asection *sec;
+         for (sec = f->the_bfd->sections; sec != NULL; sec = sec->next)
+           if ((sec->flags & SEC_DEBUGGING) == 0)
+             sec->flags &= ~SEC_EXCLUDE;
+       }
+    }
+
+  if (command_line.gc_sections)
+    bfd_gc_sections (output_bfd, &link_info);
 }
 
 void
@@ -4204,14 +4395,7 @@ lang_process (void)
   ldctor_build_sets ();
 
   /* Remove unreferenced sections if asked to.  */
-  if (command_line.gc_sections)
-    lang_gc_sections ();
-
-  /* If there were any SEC_MERGE sections, finish their merging, so that
-     section sizes can be computed.  This has to be done after GC of sections,
-     so that GCed sections are not merged, but before assigning output
-     sections, since removing whole input sections is hard then.  */
-  bfd_merge_sections (output_bfd, &link_info);
+  lang_gc_sections ();
 
   /* Size up the common data.  */
   lang_common ();
@@ -4225,8 +4409,16 @@ lang_process (void)
 
   if (! link_info.relocatable)
     {
+      asection *found;
+
+      /* Merge SEC_MERGE sections.  This has to be done after GC of
+        sections, so that GCed sections are not merged, but before
+        assigning dynamic symbols, since removing whole input sections
+        is hard then.  */
+      bfd_merge_sections (output_bfd, &link_info);
+
       /* Look for a text section and set the readonly attribute in it.  */
-      asection *found = bfd_get_section_by_name (output_bfd, ".text");
+      found = bfd_get_section_by_name (output_bfd, ".text");
 
       if (found != NULL)
        {
@@ -4522,8 +4714,9 @@ lang_get_regions (lang_memory_region_type **region,
 {
   *lma_region = lang_memory_region_lookup (lma_memspec, FALSE);
 
-  /* If no runtime region or VMA has been specified, but the load region has
-     been specified, then use the load region for the runtime region as well.  */
+  /* If no runtime region or VMA has been specified, but the load region
+     has been specified, then use the load region for the runtime region
+     as well.  */
   if (lma_memspec != NULL
       && ! have_vma
       && strcmp (memspec, DEFAULT_MEMORY_REGION) == 0)
@@ -4725,6 +4918,8 @@ lang_record_phdrs (void)
          lang_output_section_phdr_list *pl;
 
          os = &u->output_section_statement;
+         if (os->constraint == -1)
+           continue;
 
          pl = os->phdrs;
          if (pl != NULL)
@@ -4784,7 +4979,8 @@ lang_record_phdrs (void)
     {
       lang_output_section_phdr_list *pl;
 
-      if (u->output_section_statement.bfd_section == NULL)
+      if (u->output_section_statement.constraint == -1
+         || u->output_section_statement.bfd_section == NULL)
        continue;
 
       for (pl = u->output_section_statement.phdrs;
@@ -4856,7 +5052,7 @@ lang_enter_overlay_section (const char *name)
   etree_type *size;
 
   lang_enter_output_section_statement (name, overlay_vma, normal_section,
-                                      0, overlay_subalign, 0);
+                                      0, overlay_subalign, 0, 0);
 
   /* If this is the first section, then base the VMA of future
      sections on this one.  This will work correctly even if `.' is
@@ -5319,7 +5515,8 @@ lang_register_vers_node (const char *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"));
+      einfo (_("%X%P: anonymous version tag cannot be combined"
+              " with other version tags\n"));
       free (version);
       return;
     }
@@ -5347,16 +5544,17 @@ lang_register_vers_node (const char *name,
              while (e2 && strcmp (e1->symbol, e2->symbol) == 0)
                {
                  if (e1->mask == e2->mask)
-                   einfo (_("%X%P: duplicate expression `%s' in version information\n"),
-                          e1->symbol);
+                   einfo (_("%X%P: duplicate expression `%s'"
+                            " in version information\n"), e1->symbol);
                  e2 = e2->next;
                }
            }
          else if (!e1->symbol)
            for (e2 = t->locals.remaining; e2 != NULL; e2 = e2->next)
-             if (strcmp (e1->pattern, e2->pattern) == 0 && e1->mask == e2->mask)
-               einfo (_("%X%P: duplicate expression `%s' in version information\n"),
-                      e1->pattern);
+             if (strcmp (e1->pattern, e2->pattern) == 0
+                 && e1->mask == e2->mask)
+               einfo (_("%X%P: duplicate expression `%s'"
+                        " in version information\n"), e1->pattern);
        }
     }
 
@@ -5372,16 +5570,18 @@ lang_register_vers_node (const char *name,
              while (e2 && strcmp (e1->symbol, e2->symbol) == 0)
                {
                  if (e1->mask == e2->mask)
-                   einfo (_("%X%P: duplicate expression `%s' in version information\n"),
+                   einfo (_("%X%P: duplicate expression `%s'"
+                            " in version information\n"),
                           e1->symbol);
                  e2 = e2->next;
                }
            }
          else if (!e1->symbol)
            for (e2 = t->globals.remaining; e2 != NULL; e2 = e2->next)
-             if (strcmp (e1->pattern, e2->pattern) == 0 && e1->mask == e2->mask)
-               einfo (_("%X%P: duplicate expression `%s' in version information\n"),
-                      e1->pattern);
+             if (strcmp (e1->pattern, e2->pattern) == 0
+                 && e1->mask == e2->mask)
+               einfo (_("%X%P: duplicate expression `%s'"
+                        " in version information\n"), e1->pattern);
        }
     }
 
@@ -5454,8 +5654,7 @@ lang_do_version_exports_section (void)
       /* Do not free the contents, as we used them creating the regex.  */
 
       /* Do not include this section in the link.  */
-      bfd_set_section_flags (is->the_bfd, sec,
-       bfd_get_section_flags (is->the_bfd, sec) | SEC_EXCLUDE);
+      sec->flags |= SEC_EXCLUDE;
     }
 
   lreg = lang_new_vers_pattern (NULL, "*", NULL);
This page took 0.035994 seconds and 4 git commands to generate.