Add variable length tests for emit_ref in trace-condition.exp
[deliverable/binutils-gdb.git] / ld / ldlang.c
index b0741691042a5220e27fc2375f0c335cc3cd9597..1cbba39e988b61ad1cb6d793f20e7af2a656b343 100644 (file)
@@ -1,5 +1,5 @@
 /* Linker command language support.
-   Copyright (C) 1991-2015 Free Software Foundation, Inc.
+   Copyright (C) 1991-2016 Free Software Foundation, Inc.
 
    This file is part of the GNU Binutils.
 
 #define offsetof(TYPE, MEMBER) ((size_t) & (((TYPE*) 0)->MEMBER))
 #endif
 
-/* Locals variables.  */
+/* Convert between addresses in bytes and sizes in octets.
+   For currently supported targets, octets_per_byte is always a power
+   of two, so we can use shifts.  */
+#define TO_ADDR(X) ((X) >> opb_shift)
+#define TO_SIZE(X) ((X) << opb_shift)
+
+/* Local variables.  */
 static struct obstack stat_obstack;
 static struct obstack map_obstack;
 
@@ -68,6 +74,7 @@ static lang_statement_list_type *stat_save[10];
 static lang_statement_list_type **stat_save_ptr = &stat_save[0];
 static struct unique_sections *unique_section_list;
 static struct asneeded_minfo *asneeded_list_head;
+static unsigned int opb_shift = 0;
 
 /* Forward declarations.  */
 static void exp_init_os (etree_type *);
@@ -201,7 +208,7 @@ unique_section_p (const asection *sec,
   struct unique_sections *unam;
   const char *secnam;
 
-  if (link_info.relocatable
+  if (bfd_link_relocatable (&link_info)
       && sec->owner != NULL
       && bfd_is_group_section (sec->owner, sec))
     return !(os != NULL
@@ -1499,11 +1506,12 @@ next_matching_output_section_statement (lang_output_section_statement_type *os,
 
 lang_output_section_statement_type *
 lang_output_section_find_by_flags (const asection *sec,
+                                  flagword sec_flags,
                                   lang_output_section_statement_type **exact,
                                   lang_match_sec_type_func match_type)
 {
   lang_output_section_statement_type *first, *look, *found;
-  flagword look_flags, sec_flags, differ;
+  flagword look_flags, differ;
 
   /* We know the first statement on this list is *ABS*.  May as well
      skip it.  */
@@ -1511,7 +1519,6 @@ lang_output_section_find_by_flags (const asection *sec,
   first = first->next;
 
   /* First try for an exact match.  */
-  sec_flags = sec->flags;
   found = NULL;
   for (look = first; look; look = look->next)
     {
@@ -1695,7 +1702,7 @@ lang_output_section_find_by_flags (const asection *sec,
   if (found || !match_type)
     return found;
 
-  return lang_output_section_find_by_flags (sec, NULL, NULL);
+  return lang_output_section_find_by_flags (sec, sec_flags, NULL, NULL);
 }
 
 /* Find the last output section before given output statement.
@@ -1805,6 +1812,7 @@ lang_insert_orphan (asection *s,
 {
   lang_statement_list_type add;
   const char *ps;
+  lang_assignment_statement_type *start_assign;
   lang_output_section_statement_type *os;
   lang_output_section_statement_type **os_tail;
 
@@ -1817,7 +1825,8 @@ lang_insert_orphan (asection *s,
       push_stat_ptr (&add);
     }
 
-  if (link_info.relocatable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
+  if (bfd_link_relocatable (&link_info)
+      || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
     address = exp_intop (0);
 
   os_tail = ((lang_output_section_statement_type **)
@@ -1826,6 +1835,7 @@ lang_insert_orphan (asection *s,
                                            NULL, NULL, NULL, constraint, 0);
 
   ps = NULL;
+  start_assign = NULL;
   if (config.build_constructors && *os_tail == os)
     {
       /* If the name of the section is representable in C, then create
@@ -1840,9 +1850,10 @@ lang_insert_orphan (asection *s,
          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);
-         lang_add_assignment (exp_provide (symname,
-                                           exp_nameop (NAME, "."),
-                                           FALSE));
+         start_assign
+           = lang_add_assignment (exp_provide (symname,
+                                               exp_nameop (NAME, "."),
+                                               FALSE));
        }
     }
 
@@ -1865,16 +1876,25 @@ lang_insert_orphan (asection *s,
     lang_leave_output_section_statement (NULL, DEFAULT_MEMORY_REGION, NULL,
                                         NULL);
 
-  if (ps != NULL && *ps == '\0')
+  if (start_assign != NULL)
     {
       char *symname;
+      lang_assignment_statement_type *stop_assign;
+      bfd_vma dot;
 
       symname = (char *) xmalloc (ps - secname + sizeof "__stop_" + 1);
       symname[0] = bfd_get_symbol_leading_char (link_info.output_bfd);
       sprintf (symname + (symname[0] != 0), "__stop_%s", secname);
-      lang_add_assignment (exp_provide (symname,
-                                       exp_nameop (NAME, "."),
-                                       FALSE));
+      stop_assign
+       = lang_add_assignment (exp_provide (symname,
+                                           exp_nameop (NAME, "."),
+                                           FALSE));
+      /* Evaluate the expression to define the symbol if referenced,
+        before sizing dynamic sections.  */
+      dot = os->bfd_section->vma;
+      exp_fold_tree (start_assign->exp, os->bfd_section, &dot);
+      dot += TO_ADDR (s->size);
+      exp_fold_tree (stop_assign->exp, os->bfd_section, &dot);
     }
 
   /* Restore the global list pointer.  */
@@ -2184,7 +2204,7 @@ init_os (lang_output_section_statement_type *s, flagword flags)
                                                         s->name, flags);
   if (s->bfd_section == NULL)
     {
-      einfo (_("%P%F: output format %s cannot represent section called %s\n"),
+      einfo (_("%P%F: output format %s cannot represent section called %s: %E\n"),
             link_info.output_bfd->xvec->name, s->name);
     }
   s->bfd_section->output_section = s->bfd_section;
@@ -2347,7 +2367,7 @@ lang_add_section (lang_statement_list_type *ptr,
      format targets, .text$foo sections go into .text and it's odd
      to see .text with SEC_LINK_ONCE set.  */
 
-  if (!link_info.relocatable)
+  if (!bfd_link_relocatable (&link_info))
     flags &= ~(SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_RELOC);
 
   switch (output->sectype)
@@ -3172,7 +3192,8 @@ ldlang_open_output (lang_statement_union_type *statement)
       ASSERT (link_info.output_bfd == NULL);
       open_output (statement->output_statement.name);
       ldemul_set_output_arch ();
-      if (config.magic_demand_paged && !link_info.relocatable)
+      if (config.magic_demand_paged
+         && !bfd_link_relocatable (&link_info))
        link_info.output_bfd->flags |= D_PAGED;
       else
        link_info.output_bfd->flags &= ~D_PAGED;
@@ -3194,15 +3215,6 @@ ldlang_open_output (lang_statement_union_type *statement)
     }
 }
 
-/* Convert between addresses in bytes and sizes in octets.
-   For currently supported targets, octets_per_byte is always a power
-   of two, so we can use shifts.  */
-#define TO_ADDR(X) ((X) >> opb_shift)
-#define TO_SIZE(X) ((X) << opb_shift)
-
-/* Support the above.  */
-static unsigned int opb_shift = 0;
-
 static void
 init_opb (void)
 {
@@ -3413,6 +3425,55 @@ lang_place_undefineds (void)
     insert_undefined (ptr->name);
 }
 
+/* Structure used to build the list of symbols that the user has required
+   be defined.  */
+
+struct require_defined_symbol
+{
+  const char *name;
+  struct require_defined_symbol *next;
+};
+
+/* The list of symbols that the user has required be defined.  */
+
+static struct require_defined_symbol *require_defined_symbol_list;
+
+/* Add a new symbol NAME to the list of symbols that are required to be
+   defined.  */
+
+void
+ldlang_add_require_defined (const char * const name)
+{
+  struct require_defined_symbol *ptr;
+
+  ldlang_add_undef (name, TRUE);
+  ptr = (struct require_defined_symbol *) stat_alloc (sizeof (*ptr));
+  ptr->next = require_defined_symbol_list;
+  ptr->name = strdup (name);
+  require_defined_symbol_list = ptr;
+}
+
+/* Check that all symbols the user required to be defined, are defined,
+   raise an error if we find a symbol that is not defined.  */
+
+static void
+ldlang_check_require_defined_symbols (void)
+{
+  struct require_defined_symbol *ptr;
+
+  for (ptr = require_defined_symbol_list; ptr != NULL; ptr = ptr->next)
+    {
+      struct bfd_link_hash_entry *h;
+
+      h = bfd_link_hash_lookup (link_info.hash, ptr->name,
+                                FALSE, FALSE, TRUE);
+      if (h == NULL
+          || (h->type != bfd_link_hash_defined
+              && h->type != bfd_link_hash_defweak))
+        einfo(_("%P%X: required symbol `%s' not defined\n"), ptr->name);
+    }
+}
+
 /* Check for all readonly or some readwrite sections.  */
 
 static void
@@ -3939,7 +4000,7 @@ print_output_section_statement
              ++len;
            }
 
-         minfo ("0x%V %W", section->vma, section->size);
+         minfo ("0x%V %W", section->vma, TO_ADDR (section->size));
 
          if (section->vma != section->lma)
            minfo (_(" load address 0x%V"), section->lma);
@@ -4161,7 +4222,7 @@ print_input_section (asection *i, bfd_boolean is_discarded)
        size = 0;
     }
 
-  minfo ("0x%V %W %B\n", addr, TO_ADDR (size), i->owner);
+  minfo ("0x%V %W %B\n", addr, size, i->owner);
 
   if (size != i->rawsize && i->rawsize != 0)
     {
@@ -4249,7 +4310,9 @@ print_data_statement (lang_data_statement_type *data)
       break;
     }
 
-  minfo ("0x%V %W %s 0x%v", addr, size, name, data->value);
+  if (size < TO_SIZE ((unsigned) 1))
+    size = TO_SIZE ((unsigned) 1);
+  minfo ("0x%V %W %s 0x%v", addr, TO_ADDR (size), name, data->value);
 
   if (data->exp->type.node_class != etree_value)
     {
@@ -4292,7 +4355,7 @@ print_reloc_statement (lang_reloc_statement_type *reloc)
 
   size = bfd_get_reloc_size (reloc->howto);
 
-  minfo ("0x%V %W RELOC %s ", addr, size, reloc->howto->name);
+  minfo ("0x%V %W RELOC %s ", addr, TO_ADDR (size), reloc->howto->name);
 
   if (reloc->name != NULL)
     minfo ("%s+", reloc->name);
@@ -4325,7 +4388,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, (bfd_vma) s->size);
+  minfo ("0x%V %W ", addr, TO_ADDR (s->size));
 
   if (s->fill->size != 0)
     {
@@ -4614,17 +4677,21 @@ size_input_section
   return dot;
 }
 
+struct check_sec
+{
+  asection *sec;
+  bfd_boolean warned;
+};
+
 static int
 sort_sections_by_lma (const void *arg1, const void *arg2)
 {
-  const asection *sec1 = *(const asection **) arg1;
-  const asection *sec2 = *(const asection **) arg2;
+  const asection *sec1 = ((const struct check_sec *) arg1)->sec;
+  const asection *sec2 = ((const struct check_sec *) arg2)->sec;
 
-  if (bfd_section_lma (sec1->owner, sec1)
-      < bfd_section_lma (sec2->owner, sec2))
+  if (sec1->lma < sec2->lma)
     return -1;
-  else if (bfd_section_lma (sec1->owner, sec1)
-          > bfd_section_lma (sec2->owner, sec2))
+  else if (sec1->lma > sec2->lma)
     return 1;
   else if (sec1->id < sec2->id)
     return -1;
@@ -4634,10 +4701,29 @@ sort_sections_by_lma (const void *arg1, const void *arg2)
   return 0;
 }
 
+static int
+sort_sections_by_vma (const void *arg1, const void *arg2)
+{
+  const asection *sec1 = ((const struct check_sec *) arg1)->sec;
+  const asection *sec2 = ((const struct check_sec *) arg2)->sec;
+
+  if (sec1->vma < sec2->vma)
+    return -1;
+  else if (sec1->vma > sec2->vma)
+    return 1;
+  else if (sec1->id < sec2->id)
+    return -1;
+  else if (sec1->id > sec2->id)
+    return 1;
+
+  return 0;
+}
+
+#define IS_TBSS(s) \
+  ((s->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == SEC_THREAD_LOCAL)
+
 #define IGNORE_SECTION(s) \
-  ((s->flags & SEC_ALLOC) == 0                         \
-   || ((s->flags & SEC_THREAD_LOCAL) != 0              \
-       && (s->flags & SEC_LOAD) == 0))
+  ((s->flags & SEC_ALLOC) == 0 || IS_TBSS (s))
 
 /* Check to see if any allocated sections overlap with other allocated
    sections.  This can happen if a linker script specifies the output
@@ -4648,66 +4734,111 @@ static void
 lang_check_section_addresses (void)
 {
   asection *s, *p;
-  asection **sections, **spp;
-  unsigned int count;
+  struct check_sec *sections;
+  size_t i, count;
   bfd_vma s_start;
   bfd_vma s_end;
-  bfd_vma p_start;
-  bfd_vma p_end;
-  bfd_size_type amt;
+  bfd_vma p_start = 0;
+  bfd_vma p_end = 0;
   lang_memory_region_type *m;
+  bfd_boolean overlays;
 
   if (bfd_count_sections (link_info.output_bfd) <= 1)
     return;
 
-  amt = bfd_count_sections (link_info.output_bfd) * sizeof (asection *);
-  sections = (asection **) xmalloc (amt);
+  count = bfd_count_sections (link_info.output_bfd);
+  sections = XNEWVEC (struct check_sec, count);
 
   /* Scan all sections in the output list.  */
   count = 0;
   for (s = link_info.output_bfd->sections; s != NULL; s = s->next)
     {
-      /* Only consider loadable sections with real contents.  */
-      if (!(s->flags & SEC_LOAD)
-         || !(s->flags & SEC_ALLOC)
+      if (IGNORE_SECTION (s)
          || s->size == 0)
        continue;
 
-      sections[count] = s;
+      sections[count].sec = s;
+      sections[count].warned = FALSE;
       count++;
     }
 
   if (count <= 1)
-    return;
+    {
+      free (sections);
+      return;
+    }
+
+  qsort (sections, count, sizeof (*sections), sort_sections_by_lma);
 
-  qsort (sections, (size_t) count, sizeof (asection *),
-        sort_sections_by_lma);
+  /* First check section LMAs.  There should be no overlap of LMAs on
+     loadable sections, even with overlays.  */
+  for (p = NULL, i = 0; i < count; i++)
+    {
+      s = sections[i].sec;
+      if ((s->flags & SEC_LOAD) != 0)
+       {
+         s_start = s->lma;
+         s_end = s_start + TO_ADDR (s->size) - 1;
+
+         /* Look for an overlap.  We have sorted sections by lma, so
+            we know that s_start >= p_start.  Besides the obvious
+            case of overlap when the current section starts before
+            the previous one ends, we also must have overlap if the
+            previous section wraps around the address space.  */
+         if (p != NULL
+             && (s_start <= p_end
+                 || p_end < p_start))
+           {
+             einfo (_("%X%P: section %s LMA [%V,%V]"
+                      " overlaps section %s LMA [%V,%V]\n"),
+                    s->name, s_start, s_end, p->name, p_start, p_end);
+             sections[i].warned = TRUE;
+           }
+         p = s;
+         p_start = s_start;
+         p_end = s_end;
+       }
+    }
 
-  spp = sections;
-  s = *spp++;
-  s_start = s->lma;
-  s_end = s_start + TO_ADDR (s->size) - 1;
-  for (count--; count; count--)
+  /* If any non-zero size allocated section (excluding tbss) starts at
+     exactly the same VMA as another such section, then we have
+     overlays.  Overlays generated by the OVERLAY keyword will have
+     this property.  It is possible to intentionally generate overlays
+     that fail this test, but it would be unusual.  */
+  qsort (sections, count, sizeof (*sections), sort_sections_by_vma);
+  overlays = FALSE;
+  p_start = sections[0].sec->vma;
+  for (i = 1; i < count; i++)
     {
-      /* We must check the sections' LMA addresses not their VMA
-        addresses because overlay sections can have overlapping VMAs
-        but they must have distinct LMAs.  */
-      p = s;
+      s_start = sections[i].sec->vma;
+      if (p_start == s_start)
+       {
+         overlays = TRUE;
+         break;
+       }
       p_start = s_start;
-      p_end = s_end;
-      s = *spp++;
-      s_start = s->lma;
-      s_end = s_start + TO_ADDR (s->size) - 1;
-
-      /* Look for an overlap.  We have sorted sections by lma, so we
-        know that s_start >= p_start.  Besides the obvious case of
-        overlap when the current section starts before the previous
-        one ends, we also must have overlap if the previous section
-        wraps around the address space.  */
-      if (s_start <= p_end
-         || p_end < p_start)
-       einfo (_("%X%P: section %s loaded at [%V,%V] overlaps section %s loaded at [%V,%V]\n"),
-              s->name, s_start, s_end, p->name, p_start, p_end);
+    }
+
+  /* Now check section VMAs if no overlays were detected.  */
+  if (!overlays)
+    {
+      for (p = NULL, i = 0; i < count; i++)
+       {
+         s = sections[i].sec;
+         s_start = s->vma;
+         s_end = s_start + TO_ADDR (s->size) - 1;
+
+         if (p != NULL
+             && !sections[i].warned
+             && (s_start <= p_end
+                 || p_end < p_start))
+           einfo (_("%X%P: section %s VMA [%V,%V]"
+                    " overlaps section %s VMA [%V,%V]\n"),
+                  s->name, s_start, s_end, p->name, p_start, p_end);
+         p = s;
+         p_start = s_start;
+         p_end = s_end;
+       }
     }
 
   free (sections);
@@ -4724,7 +4855,6 @@ lang_check_section_addresses (void)
     if (m->had_full_message)
       einfo (_("%X%P: region `%s' overflowed by %ld bytes\n"),
             m->name_list.name, (long)(m->current - (m->origin + m->length)));
-
 }
 
 /* Make sure the new address is within the region.  We explicitly permit the
@@ -4797,7 +4927,7 @@ lang_size_sections_1
               here, in lang_insert_orphan, or in the default linker scripts.
               This is covering for coff backend linker bugs.  See PR6945.  */
            if (os->addr_tree == NULL
-               && link_info.relocatable
+               && bfd_link_relocatable (&link_info)
                && (bfd_get_flavour (link_info.output_bfd)
                    == bfd_target_coff_flavour))
              os->addr_tree = exp_intop (0);
@@ -4876,7 +5006,7 @@ lang_size_sections_1
                       defined, issue an error message.  */
                    if (!os->ignored
                        && !IGNORE_SECTION (os->bfd_section)
-                       && ! link_info.relocatable
+                       && !bfd_link_relocatable (&link_info)
                        && check_regions
                        && strcmp (os->region->name_list.name,
                                   DEFAULT_MEMORY_REGION) == 0
@@ -5004,7 +5134,7 @@ lang_size_sections_1
                   create overlapping LMAs.  */
                if (dot < last->vma
                    && os->bfd_section->size != 0
-                   && dot + os->bfd_section->size <= last->vma)
+                   && dot + TO_ADDR (os->bfd_section->size) <= last->vma)
                  {
                    /* If dot moved backwards then leave lma equal to
                       vma.  This is the old default lma, which might
@@ -5021,7 +5151,7 @@ lang_size_sections_1
                    /* If this is an overlay, set the current lma to that
                       at the end of the previous section.  */
                    if (os->sectype == overlay_section)
-                     lma = last->lma + last->size;
+                     lma = last->lma + TO_ADDR (last->size);
 
                    /* Otherwise, keep the same lma to vma relationship
                       as the previous section.  */
@@ -5046,9 +5176,7 @@ lang_size_sections_1
               To avoid warnings about dot moving backwards when using
               -Ttext, don't start tracking sections until we find one
               of non-zero size or with lma set differently to vma.  */
-           if (((os->bfd_section->flags & SEC_HAS_CONTENTS) != 0
-                || (os->bfd_section->flags & SEC_THREAD_LOCAL) == 0)
-               && (os->bfd_section->flags & SEC_ALLOC) != 0
+           if (!IGNORE_SECTION (os->bfd_section)
                && (os->bfd_section->size != 0
                    || (r->last_os == NULL
                        && os->bfd_section->vma != os->bfd_section->lma)
@@ -5056,13 +5184,12 @@ lang_size_sections_1
                        && dot >= (r->last_os->output_section_statement
                                   .bfd_section->vma)))
                && os->lma_region == NULL
-               && !link_info.relocatable)
+               && !bfd_link_relocatable (&link_info))
              r->last_os = s;
 
            /* .tbss sections effectively have zero size.  */
-           if ((os->bfd_section->flags & SEC_HAS_CONTENTS) != 0
-               || (os->bfd_section->flags & SEC_THREAD_LOCAL) == 0
-               || link_info.relocatable)
+           if (!IS_TBSS (os->bfd_section)
+               || bfd_link_relocatable (&link_info))
              dotdelta = TO_ADDR (os->bfd_section->size);
            else
              dotdelta = 0;
@@ -5382,56 +5509,55 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions)
   if (expld.dataseg.phase == exp_dataseg_end_seen
       && link_info.relro && expld.dataseg.relro_end)
     {
-      bfd_vma initial_base, min_base, relro_end, maxpage;
+      bfd_vma initial_base, relro_end, desired_end;
+      asection *sec;
 
-      expld.dataseg.phase = exp_dataseg_relro_adjust;
-      maxpage = expld.dataseg.maxpagesize;
-      initial_base = expld.dataseg.base;
-      /* Try to put expld.dataseg.relro_end on a (common) page boundary.  */
-      expld.dataseg.base += (-expld.dataseg.relro_end
-                            & (expld.dataseg.pagesize - 1));
       /* Compute the expected PT_GNU_RELRO segment end.  */
       relro_end = ((expld.dataseg.relro_end + expld.dataseg.pagesize - 1)
                   & ~(expld.dataseg.pagesize - 1));
-      /* MIN_BASE is the absolute minimum address we are allowed to start the
-        read-write segment (byte before will be mapped read-only).  */
-      min_base = (expld.dataseg.min_base + maxpage - 1) & ~(maxpage - 1);
-      if (min_base + maxpage < expld.dataseg.base)
-       {
-         expld.dataseg.base -= maxpage;
-         relro_end -= maxpage;
-       }
+
+      /* Adjust by the offset arg of DATA_SEGMENT_RELRO_END.  */
+      desired_end = relro_end - expld.dataseg.relro_offset;
+
+      /* For sections in the relro segment..  */
+      for (sec = link_info.output_bfd->section_last; sec; sec = sec->prev)
+       if ((sec->flags & SEC_ALLOC) != 0
+           && sec->vma >= expld.dataseg.base
+           && sec->vma < expld.dataseg.relro_end - expld.dataseg.relro_offset)
+         {
+           /* Where do we want to put this section so that it ends as
+              desired?  */
+           bfd_vma start, end, bump;
+
+           end = start = sec->vma;
+           if (!IS_TBSS (sec))
+             end += TO_ADDR (sec->size);
+           bump = desired_end - end;
+           /* We'd like to increase START by BUMP, but we must heed
+              alignment so the increase might be less than optimum.  */
+           start += bump;
+           start &= ~(((bfd_vma) 1 << sec->alignment_power) - 1);
+           /* This is now the desired end for the previous section.  */
+           desired_end = start;
+         }
+
+      expld.dataseg.phase = exp_dataseg_relro_adjust;
+      ASSERT (desired_end >= expld.dataseg.base);
+      initial_base = expld.dataseg.base;
+      expld.dataseg.base = desired_end;
       lang_reset_memory_regions ();
       one_lang_size_sections_pass (relax, check_regions);
+
       if (expld.dataseg.relro_end > relro_end)
        {
-         /* The alignment of sections between DATA_SEGMENT_ALIGN
-            and DATA_SEGMENT_RELRO_END can cause excessive padding to
-            be inserted at DATA_SEGMENT_RELRO_END.  Try to start a
-            bit lower so that the section alignments will fit in.  */
-         asection *sec;
-         unsigned int max_alignment_power = 0;
-
-         /* Find maximum alignment power of sections between
-            DATA_SEGMENT_ALIGN and DATA_SEGMENT_RELRO_END.  */
-         for (sec = link_info.output_bfd->sections; sec; sec = sec->next)
-           if (sec->vma >= expld.dataseg.base
-               && sec->vma < expld.dataseg.relro_end
-               && sec->alignment_power > max_alignment_power)
-             max_alignment_power = sec->alignment_power;
-
-         /* Aligning the adjusted base guarantees the padding
-            between sections won't change.  This is better than
-            simply subtracting 1 << max_alignment_power which is
-            what we used to do here.  */
-         expld.dataseg.base &= ~(((bfd_vma) 1 << max_alignment_power) - 1);
-         /* It doesn't make much sense to go lower than the initial
-            base.  That can only increase padding.  */
-         if (expld.dataseg.base < initial_base)
-           expld.dataseg.base = initial_base;
+         /* Assignments to dot, or to output section address in a
+            user script have increased padding over the original.
+            Revert.  */
+         expld.dataseg.base = initial_base;
          lang_reset_memory_regions ();
          one_lang_size_sections_pass (relax, check_regions);
        }
+
       link_info.relro_start = expld.dataseg.base;
       link_info.relro_end = expld.dataseg.relro_end;
     }
@@ -5500,9 +5626,8 @@ lang_do_assignments_1 (lang_statement_union_type *s,
                                       os, os->fill, dot, found_end);
 
                /* .tbss sections effectively have zero size.  */
-               if ((os->bfd_section->flags & SEC_HAS_CONTENTS) != 0
-                   || (os->bfd_section->flags & SEC_THREAD_LOCAL) == 0
-                   || link_info.relocatable)
+               if (!IS_TBSS (os->bfd_section)
+                   || bfd_link_relocatable (&link_info))
                  dot += TO_ADDR (os->bfd_section->size);
 
                if (os->update_dot_tree != NULL)
@@ -5726,7 +5851,7 @@ lang_set_startof (void)
 {
   asection *s;
 
-  if (link_info.relocatable)
+  if (bfd_link_relocatable (&link_info))
     return;
 
   for (s = link_info.output_bfd->sections; s != NULL; s = s->next)
@@ -5766,15 +5891,15 @@ lang_end (void)
   struct bfd_link_hash_entry *h;
   bfd_boolean warn;
 
-  if ((link_info.relocatable && !link_info.gc_sections)
-      || (link_info.shared && !link_info.executable))
+  if ((bfd_link_relocatable (&link_info) && !link_info.gc_sections)
+      || bfd_link_dll (&link_info))
     warn = entry_from_cmdline;
   else
     warn = TRUE;
 
   /* Force the user to specify a root when generating a relocatable with
      --gc-sections.  */
-  if (link_info.gc_sections && link_info.relocatable
+  if (link_info.gc_sections && bfd_link_relocatable (&link_info)
       && !(entry_from_cmdline || undef_from_cmdline))
     einfo (_("%P%F: gc-sections requires either an entry or "
             "an undefined symbol\n"));
@@ -5884,7 +6009,8 @@ lang_check (void)
         input format may not have equivalent representations in
         the output format (and besides BFD does not translate
         relocs for other link purposes than a final link).  */
-      if ((link_info.relocatable || link_info.emitrelocations)
+      if ((bfd_link_relocatable (&link_info)
+          || link_info.emitrelocations)
          && (compatible == NULL
              || (bfd_get_flavour (input_bfd)
                  != bfd_get_flavour (link_info.output_bfd)))
@@ -5940,7 +6066,7 @@ lang_common (void)
 {
   if (command_line.inhibit_common_definition)
     return;
-  if (link_info.relocatable
+  if (bfd_link_relocatable (&link_info)
       && ! command_line.force_common_definition)
     return;
 
@@ -6055,6 +6181,55 @@ lang_one_common (struct bfd_link_hash_entry *h, void *info)
   return TRUE;
 }
 
+/* Handle a single orphan section S, placing the orphan into an appropriate
+   output section.  The effects of the --orphan-handling command line
+   option are handled here.  */
+
+static void
+ldlang_place_orphan (asection *s)
+{
+  if (config.orphan_handling == orphan_handling_discard)
+    {
+      lang_output_section_statement_type *os;
+      os = lang_output_section_statement_lookup (DISCARD_SECTION_NAME, 0,
+                                                TRUE);
+      if (os->addr_tree == NULL
+         && (bfd_link_relocatable (&link_info)
+             || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0))
+       os->addr_tree = exp_intop (0);
+      lang_add_section (&os->children, s, NULL, os);
+    }
+  else
+    {
+      lang_output_section_statement_type *os;
+      const char *name = s->name;
+      int constraint = 0;
+
+      if (config.orphan_handling == orphan_handling_error)
+       einfo ("%X%P: error: unplaced orphan section `%A' from `%B'.\n",
+              s, s->owner);
+
+      if (config.unique_orphan_sections || unique_section_p (s, NULL))
+       constraint = SPECIAL;
+
+      os = ldemul_place_orphan (s, name, constraint);
+      if (os == NULL)
+       {
+         os = lang_output_section_statement_lookup (name, constraint, TRUE);
+         if (os->addr_tree == NULL
+             && (bfd_link_relocatable (&link_info)
+                 || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0))
+           os->addr_tree = exp_intop (0);
+         lang_add_section (&os->children, s, NULL, os);
+       }
+
+      if (config.orphan_handling == orphan_handling_warn)
+       einfo ("%P: warning: orphan section `%A' from `%B' being "
+              "placed in section `%s'.\n",
+              s, s->owner, os->name);
+    }
+}
+
 /* Run through the input files and ensure that every input section has
    somewhere to go.  If one is found without a destination then create
    an input request and place it into the statement tree.  */
@@ -6082,7 +6257,7 @@ lang_place_orphans (void)
                  /* This is a lonely common section which must have
                     come from an archive.  We attach to the section
                     with the wildcard.  */
-                 if (! link_info.relocatable
+                 if (!bfd_link_relocatable (&link_info)
                      || command_line.force_common_definition)
                    {
                      if (default_common_section == NULL)
@@ -6094,27 +6269,7 @@ lang_place_orphans (void)
                    }
                }
              else
-               {
-                 const char *name = s->name;
-                 int constraint = 0;
-
-                 if (config.unique_orphan_sections
-                     || unique_section_p (s, NULL))
-                   constraint = SPECIAL;
-
-                 if (!ldemul_place_orphan (s, name, constraint))
-                   {
-                     lang_output_section_statement_type *os;
-                     os = lang_output_section_statement_lookup (name,
-                                                                constraint,
-                                                                TRUE);
-                     if (os->addr_tree == NULL
-                         && (link_info.relocatable
-                             || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0))
-                       os->addr_tree = exp_intop (0);
-                     lang_add_section (&os->children, s, NULL, os);
-                   }
-               }
+               ldlang_place_orphan (s);
            }
        }
     }
@@ -6384,13 +6539,12 @@ static void
 lang_gc_sections (void)
 {
   /* Keep all sections so marked in the link script.  */
-
   lang_gc_sections_1 (statement_list.head);
 
   /* 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)
+  if (bfd_link_relocatable (&link_info))
     {
       LANG_FOR_EACH_INPUT_STATEMENT (f)
        {
@@ -6607,6 +6761,45 @@ lang_list_remove_tail (lang_statement_list_type *destlist,
 }
 #endif /* ENABLE_PLUGINS */
 
+/* Add NAME to the list of garbage collection entry points.  */
+
+void
+lang_add_gc_name (const char * name)
+{
+  struct bfd_sym_chain *sym;
+
+  if (name == NULL)
+    return;
+
+  sym = (struct bfd_sym_chain *) stat_alloc (sizeof (*sym));
+
+  sym->next = link_info.gc_sym_list;
+  sym->name = name;
+  link_info.gc_sym_list = sym;
+}
+
+/* Check relocations.  */
+
+static void
+lang_check_relocs (void)
+{
+  if (link_info.check_relocs_after_open_input)
+    {
+      bfd *abfd;
+
+      for (abfd = link_info.input_bfds;
+          abfd != (bfd *) NULL; abfd = abfd->link.next)
+       if (!bfd_link_check_relocs (abfd, &link_info))
+         {
+           /* No object output, fail return.  */
+           config.make_executable = FALSE;
+           /* Note: we do not abort the loop, but rather
+              continue the scan in case there are other
+              bad relocations to report.  */
+         }
+    }
+}
+
 void
 lang_process (void)
 {
@@ -6689,26 +6882,29 @@ lang_process (void)
     }
 #endif /* ENABLE_PLUGINS */
 
+  /* Make sure that nobody has tried to add a symbol to this list before now.  */
+  ASSERT (link_info.gc_sym_list == NULL);
+
   link_info.gc_sym_list = &entry_symbol;
+
   if (entry_symbol.name == NULL)
-    link_info.gc_sym_list = ldlang_undef_chain_list_head;
-  if (link_info.init_function != NULL)
     {
-      struct bfd_sym_chain *sym
-       = (struct bfd_sym_chain *) stat_alloc (sizeof (*sym));
-      sym->next = link_info.gc_sym_list;
-      sym->name = link_info.init_function;
-      link_info.gc_sym_list = sym;
-    }
-  if (link_info.fini_function != NULL)
-    {
-      struct bfd_sym_chain *sym
-       = (struct bfd_sym_chain *) stat_alloc (sizeof (*sym));
-      sym->next = link_info.gc_sym_list;
-      sym->name = link_info.fini_function;
-      link_info.gc_sym_list = sym;
+      link_info.gc_sym_list = ldlang_undef_chain_list_head;
+
+      /* entry_symbol is normally initialied by a ENTRY definition in the
+        linker script or the -e command line option.  But if neither of
+        these have been used, the target specific backend may still have
+        provided an entry symbol via a call to lang_default_entry().
+        Unfortunately this value will not be processed until lang_end()
+        is called, long after this function has finished.  So detect this
+        case here and add the target's entry symbol to the list of starting
+        points for garbage collection resolution.  */
+      lang_add_gc_name (entry_symbol_default);
     }
 
+  lang_add_gc_name (link_info.init_function);
+  lang_add_gc_name (link_info.fini_function);
+
   ldemul_after_open ();
   if (config.map_file != NULL)
     lang_print_asneeded ();
@@ -6743,6 +6939,9 @@ lang_process (void)
   /* Remove unreferenced sections if asked to.  */
   lang_gc_sections ();
 
+  /* Check relocations.  */
+  lang_check_relocs ();
+
   /* Update wild statements.  */
   update_wild_statements (statement_list.head);
 
@@ -6756,7 +6955,7 @@ lang_process (void)
   /* Find any sections not attached explicitly and handle them.  */
   lang_place_orphans ();
 
-  if (! link_info.relocatable)
+  if (!bfd_link_relocatable (&link_info))
     {
       asection *found;
 
@@ -6787,7 +6986,7 @@ lang_process (void)
   lang_record_phdrs ();
 
   /* Check relro sections.  */
-  if (link_info.relro && ! link_info.relocatable)
+  if (link_info.relro && !bfd_link_relocatable (&link_info))
     lang_find_relro_sections ();
 
   /* Size up the sections.  */
@@ -6806,10 +7005,16 @@ lang_process (void)
 
   ldemul_finish ();
 
+  /* Convert absolute symbols to section relative.  */
+  ldexp_finalize_syms ();
+
   /* Make sure that the section addresses make sense.  */
   if (command_line.check_section_addresses)
     lang_check_section_addresses ();
 
+  /* Check any required symbols are known.  */
+  ldlang_check_require_defined_symbols ();
+
   lang_end ();
 }
 
@@ -7306,11 +7511,21 @@ lang_add_nocrossref (lang_nocrossref_type *l)
   n = (struct lang_nocrossrefs *) xmalloc (sizeof *n);
   n->next = nocrossref_list;
   n->list = l;
+  n->onlyfirst = FALSE;
   nocrossref_list = n;
 
   /* Set notice_all so that we get informed about all symbols.  */
   link_info.notice_all = TRUE;
 }
+
+/* Record a section that cannot be referenced from a list of sections.  */
+
+void
+lang_add_nocrossref_to (lang_nocrossref_type *l)
+{
+  lang_add_nocrossref (l);
+  nocrossref_list->onlyfirst = TRUE;
+}
 \f
 /* Overlay handling.  We handle overlays with some static variables.  */
 
@@ -8138,3 +8353,41 @@ lang_ld_feature (char *str)
       p = q;
     }
 }
+
+/* Pretty print memory amount.  */
+
+static void
+lang_print_memory_size (bfd_vma sz)
+{
+  if ((sz & 0x3fffffff) == 0)
+    printf ("%10" BFD_VMA_FMT "u GB", sz >> 30);
+  else if ((sz & 0xfffff) == 0)
+    printf ("%10" BFD_VMA_FMT "u MB", sz >> 20);
+  else if ((sz & 0x3ff) == 0)
+    printf ("%10" BFD_VMA_FMT "u KB", sz >> 10);
+  else
+    printf (" %10" BFD_VMA_FMT "u B", sz);
+}
+
+/* Implement --print-memory-usage: disply per region memory usage.  */
+
+void
+lang_print_memory_usage (void)
+{
+  lang_memory_region_type *r;
+
+  printf ("Memory region         Used Size  Region Size  %%age Used\n");
+  for (r = lang_memory_region_list; r->next != NULL; r = r->next)
+    {
+      bfd_vma used_length = r->current - r->origin;
+      double percent;
+
+      printf ("%16s: ",r->name_list.name);
+      lang_print_memory_size (used_length);
+      lang_print_memory_size ((bfd_vma) r->length);
+
+      percent = used_length * 100.0 / r->length;
+
+      printf ("    %6.2f%%\n", percent);
+    }
+}
This page took 0.036134 seconds and 4 git commands to generate.