record-btrace: add record goto target methods
[deliverable/binutils-gdb.git] / ld / ldlang.c
index 750711ceb3cdcd7926dbeafb3d63ee9925d0e6ec..2a6c4c5e2ab550bd2aa48f46add1bcfeac396cc3 100644 (file)
@@ -1,7 +1,5 @@
 /* Linker command language support.
-   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
-   Free Software Foundation, Inc.
+   Copyright 1991-2013 Free Software Foundation, Inc.
 
    This file is part of the GNU Binutils.
 
@@ -72,7 +70,6 @@ static struct unique_sections *unique_section_list;
 
 /* Forward declarations.  */
 static void exp_init_os (etree_type *);
-static void init_map_userdata (bfd *, asection *, void *);
 static lang_input_statement_type *lookup_name (const char *);
 static struct bfd_hash_entry *lang_definedness_newfunc
  (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
@@ -387,7 +384,7 @@ get_init_priority (const char *name)
        decimal numerical value of the init_priority attribute.
        The order of execution in .init_array is forward and
        .fini_array is backward.
-     2: .ctors.NNNN/.ctors.NNNN: Where NNNN is 65535 minus the
+     2: .ctors.NNNN/.dtors.NNNN: Where NNNN is 65535 minus the
        decimal numerical value of the init_priority attribute.
        The order of execution in .ctors is backward and .dtors
        is forward.
@@ -1240,6 +1237,8 @@ lang_init (void)
 void
 lang_finish (void)
 {
+  bfd_link_hash_table_free (link_info.output_bfd, link_info.hash);
+  bfd_hash_table_free (&lang_definedness_table);
   output_section_statement_table_free ();
 }
 
@@ -1777,7 +1776,7 @@ lang_insert_orphan (asection *s,
   os_tail = ((lang_output_section_statement_type **)
             lang_output_section_statement.tail);
   os = lang_enter_output_section_statement (secname, address, normal_section,
-                                           NULL, NULL, NULL, constraint);
+                                           NULL, NULL, NULL, constraint, 0);
 
   ps = NULL;
   if (config.build_constructors && *os_tail == os)
@@ -1974,7 +1973,6 @@ lang_map (void)
 {
   lang_memory_region_type *m;
   bfd_boolean dis_header_printed = FALSE;
-  bfd *p;
 
   LANG_FOR_EACH_INPUT_STATEMENT (file)
     {
@@ -2046,50 +2044,34 @@ lang_map (void)
   if (! link_info.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);
     }
   lang_statement_iteration ++;
   print_statements ();
 }
 
-static void
-init_map_userdata (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;
-  new_data->map_symbol_def_count = 0;
-}
-
 static bfd_boolean
 sort_def_symbol (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)
+  if ((hash_entry->type == bfd_link_hash_defined
+       || hash_entry->type == bfd_link_hash_defweak)
+      && hash_entry->u.def.section->owner != link_info.output_bfd
+      && hash_entry->u.def.section->owner != NULL)
     {
-      struct fat_user_section_struct *ud;
+      input_section_userdata_type *ud;
       struct map_symbol_def *def;
 
-      ud = (struct fat_user_section_struct *)
-         get_userdata (hash_entry->u.def.section);
-      if  (! ud)
+      ud = ((input_section_userdata_type *)
+           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 = (struct fat_user_section_struct *)
-             get_userdata (hash_entry->u.def.section);
+         ud = (input_section_userdata_type *) stat_alloc (sizeof (*ud));
+         get_userdata (hash_entry->u.def.section) = ud;
+         ud->map_symbol_def_tail = &ud->map_symbol_def_head;
+         ud->map_symbol_def_count = 0;
        }
-      else if  (!ud->map_symbol_def_tail)
+      else if (!ud->map_symbol_def_tail)
        ud->map_symbol_def_tail = &ud->map_symbol_def_head;
 
       def = (struct map_symbol_def *) obstack_alloc (&map_obstack, sizeof *def);
@@ -2122,14 +2104,6 @@ init_os (lang_output_section_statement_type *s, flagword flags)
   s->bfd_section->output_section = s->bfd_section;
   s->bfd_section->output_offset = 0;
 
-  if (!link_info.reduce_memory_overheads)
-    {
-      fat_section_userdata_type *new_userdata = (fat_section_userdata_type *)
-       stat_alloc (sizeof (fat_section_userdata_type));
-      memset (new_userdata, 0, sizeof (fat_section_userdata_type));
-      get_userdata (s->bfd_section) = new_userdata;
-    }
-
   /* If there is a base address, make sure that any sections it might
      mention are initialized.  */
   if (s->addr_tree != NULL)
@@ -2779,7 +2753,7 @@ load_symbols (lang_input_statement_type *entry,
                 substitute BFD for us.  */
              if (!bfd_link_add_symbols (subsbfd, &link_info))
                {
-                 einfo (_("%F%B: could not read symbols: %E\n"), member);
+                 einfo (_("%F%B: error adding symbols: %E\n"), member);
                  loaded = FALSE;
                }
            }
@@ -2793,7 +2767,7 @@ load_symbols (lang_input_statement_type *entry,
   if (bfd_link_add_symbols (entry->the_bfd, &link_info))
     entry->flags.loaded = TRUE;
   else
-    einfo (_("%F%B: could not read symbols: %E\n"), entry->the_bfd);
+    einfo (_("%F%B: error adding symbols: %E\n"), entry->the_bfd);
 
   return entry->flags.loaded;
 }
@@ -3951,63 +3925,12 @@ print_output_section_statement
                        output_section_statement);
 }
 
-/* Scan for the use of the destination in the right hand side
-   of an expression.  In such cases we will not compute the
-   correct expression, since the value of DST that is used on
-   the right hand side will be its final value, not its value
-   just before this expression is evaluated.  */
-
-static bfd_boolean
-scan_for_self_assignment (const char * dst, etree_type * rhs)
-{
-  if (rhs == NULL || dst == NULL)
-    return FALSE;
-
-  switch (rhs->type.node_class)
-    {
-    case etree_binary:
-      return (scan_for_self_assignment (dst, rhs->binary.lhs)
-             || scan_for_self_assignment (dst, rhs->binary.rhs));
-
-    case etree_trinary:
-      return (scan_for_self_assignment (dst, rhs->trinary.lhs)
-             || scan_for_self_assignment (dst, rhs->trinary.rhs));
-
-    case etree_assign:
-    case etree_provided:
-    case etree_provide:
-      if (strcmp (dst, rhs->assign.dst) == 0)
-       return TRUE;
-      return scan_for_self_assignment (dst, rhs->assign.src);
-
-    case etree_unary:
-      return scan_for_self_assignment (dst, rhs->unary.child);
-
-    case etree_value:
-      if (rhs->value.str)
-       return strcmp (dst, rhs->value.str) == 0;
-      return FALSE;
-
-    case etree_name:
-      if (rhs->name.name)
-       return strcmp (dst, rhs->name.name) == 0;
-      return FALSE;
-
-    default:
-      break;
-    }
-
-  return FALSE;
-}
-
-
 static void
 print_assignment (lang_assignment_statement_type *assignment,
                  lang_output_section_statement_type *output_section)
 {
   unsigned int i;
   bfd_boolean is_dot;
-  bfd_boolean computation_is_valid = TRUE;
   etree_type *tree;
   asection *osec;
 
@@ -4018,15 +3941,14 @@ print_assignment (lang_assignment_statement_type *assignment,
     {
       is_dot = FALSE;
       tree = assignment->exp->assert_s.child;
-      computation_is_valid = TRUE;
     }
   else
     {
       const char *dst = assignment->exp->assign.dst;
 
       is_dot = (dst[0] == '.' && dst[1] == 0);
+      expld.assign_name = dst;
       tree = assignment->exp->assign.src;
-      computation_is_valid = is_dot || !scan_for_self_assignment (dst, tree);
     }
 
   osec = output_section->bfd_section;
@@ -4037,7 +3959,9 @@ print_assignment (lang_assignment_statement_type *assignment,
     {
       bfd_vma value;
 
-      if (computation_is_valid)
+      if (assignment->exp->type.node_class == etree_assert
+         || is_dot
+         || expld.assign_name != NULL)
        {
          value = expld.result.value;
 
@@ -4073,6 +3997,7 @@ print_assignment (lang_assignment_statement_type *assignment,
       minfo ("        ");
 #endif
     }
+  expld.assign_name = NULL;
 
   minfo ("                ");
   exp_print_tree (assignment->exp);
@@ -4132,8 +4057,8 @@ hash_entry_addr_cmp (const void *a, const void *b)
 static void
 print_all_symbols (asection *sec)
 {
-  struct fat_user_section_struct *ud =
-      (struct fat_user_section_struct *) get_userdata (sec);
+  input_section_userdata_type *ud
+    = (input_section_userdata_type *) get_userdata (sec);
   struct map_symbol_def *def;
   struct bfd_link_hash_entry **entries;
   unsigned int i;
@@ -5010,6 +4935,13 @@ lang_size_sections_1
              {
                bfd_vma lma = os->lma_region->current;
 
+               /* When LMA_REGION is the same as REGION, align the LMA
+                  as we did for the VMA, possibly including alignment
+                  from the bfd section.  If a different region, then
+                  only align according to the value in the output
+                  statement unless specified otherwise.  */
+               if (os->lma_region != os->region && !os->align_lma_with_input)
+                 section_alignment = os->section_alignment;
                if (section_alignment > 0)
                  lma = align_power (lma, section_alignment);
                os->bfd_section->lma = lma;
@@ -5404,18 +5336,14 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions)
       && link_info.relro && expld.dataseg.relro_end)
     {
       /* If DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END pair was seen, try
-        to put expld.dataseg.relro on a (common) page boundary.  */
-      bfd_vma min_base, old_base, relro_end, maxpage;
+        to put expld.dataseg.relro_end on a (common) page boundary.  */
+      bfd_vma min_base, relro_end, maxpage;
 
       expld.dataseg.phase = exp_dataseg_relro_adjust;
       maxpage = expld.dataseg.maxpagesize;
       /* 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);
-      /* OLD_BASE is the address for a feasible minimum address which will
-        still not cause a data overlap inside MAXPAGE causing file offset skip
-        by MAXPAGE.  */
-      old_base = expld.dataseg.base;
       expld.dataseg.base += (-expld.dataseg.relro_end
                             & (expld.dataseg.pagesize - 1));
       /* Compute the expected PT_GNU_RELRO segment end.  */
@@ -5431,9 +5359,9 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions)
       if (expld.dataseg.relro_end > relro_end)
        {
          /* The alignment of sections between DATA_SEGMENT_ALIGN
-            and DATA_SEGMENT_RELRO_END caused huge padding to be
-            inserted at DATA_SEGMENT_RELRO_END.  Try to start a bit lower so
-            that the section alignments will fit in.  */
+            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;
 
@@ -5447,9 +5375,11 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions)
 
          if (((bfd_vma) 1 << max_alignment_power) < expld.dataseg.pagesize)
            {
-             if (expld.dataseg.base - (1 << max_alignment_power) < old_base)
-               expld.dataseg.base += expld.dataseg.pagesize;
-             expld.dataseg.base -= (1 << max_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 &= ~((1 << max_alignment_power) - 1);
              lang_reset_memory_regions ();
              one_lang_size_sections_pass (relax, check_regions);
            }
@@ -5866,9 +5796,6 @@ lang_end (void)
            }
        }
     }
-
-  /* Don't bfd_hash_table_free (&lang_definedness_table);
-     map file output may result in a call of lang_track_definedness.  */
 }
 
 /* This is a small function used when we want to ignore errors from
@@ -6278,7 +6205,8 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
                                     etree_type *align,
                                     etree_type *subalign,
                                     etree_type *ebase,
-                                    int constraint)
+                                    int constraint,
+                                    int align_with_input)
 {
   lang_output_section_statement_type *os;
 
@@ -6300,6 +6228,10 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
   /* Make next things chain into subchain of this.  */
   push_stat_ptr (&os->children);
 
+  os->align_lma_with_input = align_with_input == ALIGN_WITH_INPUT;
+  if (os->align_lma_with_input && align != NULL)
+    einfo (_("%F%P:%S: error: align with input and explicit align specified\n"), NULL);
+
   os->subsection_alignment =
     topower (exp_get_value_int (subalign, -1, "subsection alignment"));
   os->section_alignment =
@@ -7350,7 +7282,7 @@ lang_enter_overlay_section (const char *name)
   etree_type *size;
 
   lang_enter_output_section_statement (name, overlay_vma, overlay_section,
-                                      0, overlay_subalign, 0, 0);
+                                      0, overlay_subalign, 0, 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
This page took 0.027343 seconds and 4 git commands to generate.