]> Git Repo - binutils.git/blobdiff - ld/ldlang.c
Add embedded PowerPC ELF support.
[binutils.git] / ld / ldlang.c
index a1a5de91940434887157ede7c8eea041cc7a5c67..3f3809c8075bf652acae6248ad9625c00da88633 100644 (file)
@@ -49,11 +49,6 @@ static struct obstack stat_obstack;
 #define obstack_chunk_free free
 static CONST char *startup_file;
 static lang_statement_list_type input_file_chain;
-
-/* Points to the last statement in the .data section, so we can add
-   stuff to the data section without pain */
-static lang_statement_list_type end_of_data_section_statement_list;
-
 static boolean placed_commons = false;
 static lang_output_section_statement_type *default_common_section;
 static boolean map_option_f;
@@ -77,28 +72,23 @@ static lang_input_statement_type *new_afile
           const char *target, boolean add_to_list));
 static void print_flags PARAMS ((int *ignore_flags));
 static void init_os PARAMS ((lang_output_section_statement_type *s));
-static void wild_doit PARAMS ((lang_statement_list_type *ptr,
-                              asection *section,
-                              lang_output_section_statement_type *output,
-                              lang_input_statement_type *file));
-static asection *our_bfd_get_section_by_name PARAMS ((bfd *abfd,
-                                                     const char *section));
 static void wild_section PARAMS ((lang_wild_statement_type *ptr,
                                  const char *section,
                                  lang_input_statement_type *file,
                                  lang_output_section_statement_type *output));
 static lang_input_statement_type *lookup_name PARAMS ((const char *name));
-static void load_symbols PARAMS ((lang_input_statement_type *entry));
+static void load_symbols PARAMS ((lang_input_statement_type *entry,
+                                 lang_statement_list_type *));
 static void wild PARAMS ((lang_wild_statement_type *s,
                          const char *section, const char *file,
                          const char *target,
                          lang_output_section_statement_type *output));
 static bfd *open_output PARAMS ((const char *name));
 static void ldlang_open_output PARAMS ((lang_statement_union_type *statement));
-static void open_input_bfds PARAMS ((lang_statement_union_type *statement));
+static void open_input_bfds
+  PARAMS ((lang_statement_union_type *statement, boolean));
 static void lang_reasonable_defaults PARAMS ((void));
 static void lang_place_undefineds PARAMS ((void));
-static void lang_create_output_section_statements PARAMS ((void));
 static void map_input_to_output_sections
   PARAMS ((lang_statement_union_type *s,
           const char *target,
@@ -117,6 +107,8 @@ static void print_padding_statement PARAMS ((lang_padding_statement_type *s));
 static void print_wild_statement
   PARAMS ((lang_wild_statement_type *w,
           lang_output_section_statement_type *os));
+static void print_group
+  PARAMS ((lang_group_statement_type *, lang_output_section_statement_type *));
 static void print_statement PARAMS ((lang_statement_union_type *s,
                                     lang_output_section_statement_type *os));
 static void print_statements PARAMS ((void));
@@ -128,11 +120,6 @@ static bfd_vma size_input_section
   PARAMS ((lang_statement_union_type **this_ptr,
           lang_output_section_statement_type *output_section_statement,
           fill_type fill, bfd_vma dot, boolean relax));
-static bfd_vma lang_do_assignments
-  PARAMS ((lang_statement_union_type * s,
-          lang_output_section_statement_type *output_section_statement,
-          fill_type fill,
-          bfd_vma dot));
 static void lang_finish PARAMS ((void));
 static void lang_check PARAMS ((void));
 static void lang_common PARAMS ((void));
@@ -144,9 +131,8 @@ static void reset_memory_regions PARAMS ((void));
 /* EXPORTS */
 lang_output_section_statement_type *abs_output_section;
 lang_statement_list_type *stat_ptr = &statement_list;
-lang_statement_list_type file_chain =
-{0};
-CONST char *entry_symbol = 0;
+lang_statement_list_type file_chain = { 0 };
+static const char *entry_symbol = 0;
 boolean lang_has_input_file = false;
 boolean had_output_filename = false;
 boolean lang_float_flag = false;
@@ -231,6 +217,10 @@ lang_for_each_statement_worker (func, s)
            (func,
             s->wild_statement.children.head);
          break;
+       case lang_group_statement_enum:
+         lang_for_each_statement_worker (func,
+                                         s->group_statement.children.head);
+         break;
        case lang_data_statement_enum:
        case lang_reloc_statement_enum:
        case lang_object_symbols_statement_enum:
@@ -375,7 +365,6 @@ new_afile (name, file_type, target, add_to_list)
     }
   p->the_bfd = (bfd *) NULL;
   p->asymbols = (asymbol **) NULL;
-  p->superfile = (lang_input_statement_type *) NULL;
   p->next_real_file = (lang_statement_union_type *) NULL;
   p->next = (lang_statement_union_type *) NULL;
   p->symbol_count = 0;
@@ -393,25 +382,7 @@ lang_add_input_file (name, file_type, target)
      lang_input_file_enum_type file_type;
      CONST char *target;
 {
-  /* Look it up or build a new one */
   lang_has_input_file = true;
-
-#if 0
-  lang_input_statement_type *p;
-
-  for (p = (lang_input_statement_type *) input_file_chain.head;
-       p != (lang_input_statement_type *) NULL;
-       p = (lang_input_statement_type *) (p->next_real_file))
-    {
-      /* Sometimes we have incomplete entries in here */
-      if (p->filename != (char *) NULL)
-       {
-         if (strcmp (name, p->filename) == 0)
-           return p;
-       }
-
-    }
-#endif
   return new_afile (name, file_type, target, true);
 }
 
@@ -433,7 +404,7 @@ lang_init ()
                                    (char *) NULL);
   abs_output_section = lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME);
 
-  abs_output_section->bfd_section = &bfd_abs_section;
+  abs_output_section->bfd_section = bfd_abs_section_ptr;
 
 }
 
@@ -654,7 +625,7 @@ init_os (s)
 
 */
 
-static void
+void
 wild_doit (ptr, section, output, file)
      lang_statement_list_type * ptr;
      asection * section;
@@ -662,18 +633,7 @@ wild_doit (ptr, section, output, file)
      lang_input_statement_type * file;
 {
   if (output->bfd_section == (asection *) NULL)
-  {
     init_os (output);
-    /* Initialize the vma and size to the existing section.  This will
-       be overriden in lang_size_sections unless SEC_NEVER_LOAD gets
-       set.  */
-    if (section != (asection *) NULL)
-    {
-      bfd_set_section_vma (0, output->bfd_section,
-                          bfd_section_vma (0, section));
-      output->bfd_section->_raw_size = section->_raw_size;
-    }
-  }
 
   if (section != (asection *) NULL
       && section->output_section == (asection *) NULL)
@@ -685,14 +645,14 @@ wild_doit (ptr, section, output, file)
     new->ifile = file;
     section->output_section = output->bfd_section;
 
-    /* Be selective about what the output section inherits from the
-       input section */
-
-    if ((section->flags & SEC_SHARED_LIBRARY) != 0)
-      section->output_section->flags |= section->flags;
-    else
-      section->output_section->flags |=
-       section->flags & (flagword) (~ SEC_NEVER_LOAD);
+    /* We don't copy the SEC_NEVER_LOAD flag from an input section to
+       an output section, because we want to be able to include a
+       SEC_NEVER_LOAD section in the middle of an otherwise loaded
+       section (I don't know why we want to do this, but we do).
+       build_link_order in ldwrite.c handles this case by turning the
+       embedded SEC_NEVER_LOAD section into a fill.  */
+    section->output_section->flags |=
+      section->flags & (flagword) (~ SEC_NEVER_LOAD);
 
     if (!output->loadable) 
     {
@@ -712,43 +672,31 @@ wild_doit (ptr, section, output, file)
   }
 }
 
-static asection *
-our_bfd_get_section_by_name (abfd, section)
-     bfd * abfd;
-     CONST char *section;
-{
-  return bfd_get_section_by_name (abfd, section);
-}
-
 static void
 wild_section (ptr, section, file, output)
-     lang_wild_statement_type * ptr;
-     CONST char *section;
-     lang_input_statement_type * file;
-     lang_output_section_statement_type * output;
+     lang_wild_statement_type *ptr;
+     const char *section;
+     lang_input_statement_type *file;
+     lang_output_section_statement_type *output;
 {
-  asection *s;
-
   if (file->just_syms_flag == false)
     {
-      if (section == (char *) NULL)
-       {
-         /* Do the creation to all sections in the file */
-         for (s = file->the_bfd->sections; s != (asection *) NULL; s = s->next)
-         {
-           /* except for bss */
-           if ((s->flags & SEC_IS_COMMON)  == 0)
-           {
-             wild_doit (&ptr->children, s, output, file);
-           }
-         }
-       }
-      else
+      register asection *s;
+
+      for (s = file->the_bfd->sections; s != NULL; s = s->next)
        {
-         /* Do the creation to the named section only */
-         wild_doit (&ptr->children,
-                    our_bfd_get_section_by_name (file->the_bfd, section),
-                    output, file);
+         /* Attach all sections named SECTION.  If SECTION is NULL,
+            then attach all sections.
+
+            Previously, if SECTION was NULL, this code did not call
+            wild_doit if the SEC_IS_COMMON flag was set for the
+            section.  I did not understand that, and I took it out.
+            [email protected].  */
+
+         if (section == NULL
+             || strcmp (bfd_get_section_name (file->the_bfd, s),
+                        section) == 0)
+           wild_doit (&ptr->children, s, output, file);
        }
     }
 }
@@ -759,8 +707,7 @@ wild_section (ptr, section, file, output)
 
    Archives are pecuilar here. We may open them once, but if they do
    not define anything we need at the time, they won't have all their
-   symbols read. If we need them later, we'll have to redo it.
-   */
+   symbols read. If we need them later, we'll have to redo it.  */
 static lang_input_statement_type *
 lookup_name (name)
      CONST char *name;
@@ -791,7 +738,7 @@ lookup_name (name)
       || search->filename == (const char *) NULL)
     return search;
 
-  load_symbols (search);
+  load_symbols (search, (lang_statement_list_type *) NULL);
 
   return search;
 }
@@ -799,30 +746,70 @@ lookup_name (name)
 /* Get the symbols for an input file.  */
 
 static void
-load_symbols (entry)
+load_symbols (entry, place)
      lang_input_statement_type *entry;
+     lang_statement_list_type *place;
 {
+  char **matching;
+
   if (entry->loaded)
     return;
 
   ldfile_open_file (entry);
 
-  if (bfd_check_format (entry->the_bfd, bfd_object))
+  if (! bfd_check_format (entry->the_bfd, bfd_archive)
+      && ! bfd_check_format_matches (entry->the_bfd, bfd_object, &matching))
+    {
+      bfd_error_type err;
+      lang_statement_list_type *hold;
+
+      err = bfd_get_error ();
+      if (err == bfd_error_file_ambiguously_recognized)
+       {
+         char **p;
+
+         einfo ("%B: file not recognized: %E\n", entry->the_bfd);
+         einfo ("%B: matching formats:", entry->the_bfd);
+         for (p = matching; *p != NULL; p++)
+           einfo (" %s", *p);
+         einfo ("%F\n");
+       }
+      else if (err != bfd_error_file_not_recognized
+              || place == NULL)
+       einfo ("%F%B: file not recognized: %E\n", entry->the_bfd);
+
+      /* Try to interpret the file as a linker script.  */
+
+      bfd_close (entry->the_bfd);
+      entry->the_bfd = NULL;
+
+      ldfile_open_command_file (entry->filename);
+
+      hold = stat_ptr;
+      stat_ptr = place;
+
+      ldfile_assumed_script = true;
+      parser_input = input_script;
+      yyparse ();
+      ldfile_assumed_script = false;
+
+      stat_ptr = hold;
+
+      return;
+    }
+
+  /* We don't call ldlang_add_file for an archive.  Instead, the
+     add_symbols entry point will call ldlang_add_file, via the
+     add_archive_element callback, for each element of the archive
+     which is used.  */
+  if (bfd_get_format (entry->the_bfd) == bfd_object)
     {
       ldlang_add_file (entry);
       if (trace_files || trace_file_tries)
        info_msg ("%I\n", entry);
     }
-  else if (bfd_check_format (entry->the_bfd, bfd_archive))
-    {
-      /* There is nothing to do here; the add_symbols routine will
-        call ldlang_add_file (via the add_archive_element callback)
-        for each element of the archive which is used.  */
-    }
-  else
-    einfo ("%F%B: file not recognized: %E\n", entry->the_bfd);
 
-  if (bfd_link_add_symbols (entry->the_bfd, &link_info) == false)
+  if (! bfd_link_add_symbols (entry->the_bfd, &link_info))
     einfo ("%F%B: could not read symbols: %E\n", entry->the_bfd);
 
   entry->loaded = true;
@@ -931,6 +918,10 @@ ldlang_open_output (statement)
        output_bfd->flags |= WP_TEXT;
       else
        output_bfd->flags &= ~WP_TEXT;
+      if (config.traditional_format)
+       output_bfd->flags |= BFD_TRADITIONAL_FORMAT;
+      else
+       output_bfd->flags &= ~BFD_TRADITIONAL_FORMAT;
       break;
 
     case lang_target_statement_enum:
@@ -941,31 +932,78 @@ ldlang_open_output (statement)
     }
 }
 
+/* Open all the input files.  */
+
 static void
-open_input_bfds (statement)
-     lang_statement_union_type * statement;
+open_input_bfds (s, force)
+     lang_statement_union_type *s;
+     boolean force;
 {
-  switch (statement->header.type)
+  for (; s != (lang_statement_union_type *) NULL; s = s->next)
     {
-      case lang_target_statement_enum:
-      current_target = statement->target_statement.target;
-      break;
-    case lang_wild_statement_enum:
-      /* Maybe we should load the file's symbols */
-      if (statement->wild_statement.filename)
-       {
-         (void) lookup_name (statement->wild_statement.filename);
-       }
-      break;
-    case lang_input_statement_enum:
-      if (statement->input_statement.real == true)
+      switch (s->header.type)
        {
-         statement->input_statement.target = current_target;
-         load_symbols (&statement->input_statement);
+       case lang_constructors_statement_enum:
+         open_input_bfds (constructor_list.head, force);
+         break;
+       case lang_output_section_statement_enum:
+         open_input_bfds (s->output_section_statement.children.head, force);
+         break;
+       case lang_wild_statement_enum:
+         /* Maybe we should load the file's symbols */
+         if (s->wild_statement.filename)
+           (void) lookup_name (s->wild_statement.filename);
+         open_input_bfds (s->wild_statement.children.head, force);
+         break;
+       case lang_group_statement_enum:
+         {
+           struct bfd_link_hash_entry *undefs;
+
+           /* We must continually search the entries in the group
+               until no new symbols are added to the list of undefined
+               symbols.  */
+
+           do
+             {
+               undefs = link_info.hash->undefs_tail;
+               open_input_bfds (s->group_statement.children.head, true);
+             }
+           while (undefs != link_info.hash->undefs_tail);
+         }
+         break;
+       case lang_target_statement_enum:
+         current_target = s->target_statement.target;
+         break;
+       case lang_input_statement_enum:
+         if (s->input_statement.real == true)
+           {
+             lang_statement_list_type add;
+
+             s->input_statement.target = current_target;
+
+             /* If we are being called from within a group, and this
+                 is an archive which has already been searched, then
+                 force it to be researched.  */
+             if (force
+                 && s->input_statement.loaded
+                 && bfd_check_format (s->input_statement.the_bfd,
+                                      bfd_archive))
+               s->input_statement.loaded = false;
+
+             lang_list_init (&add);
+
+             load_symbols (&s->input_statement, &add);
+
+             if (add.head != NULL)
+               {
+                 *add.tail = s->next;
+                 s->next = add.head;
+               }
+           }
+         break;
+       default:
+         break;
        }
-      break;
-    default:
-      break;
     }
 }
 
@@ -1049,27 +1087,6 @@ lang_place_undefineds ()
     }
 }
 
-/* Copy important data from out internal form to the bfd way. Also
-   create a section for the dummy file
- */
-
-static void
-lang_create_output_section_statements ()
-{
-  lang_statement_union_type *os;
-
-  for (os = lang_output_section_statement.head;
-       os != (lang_statement_union_type *) NULL;
-       os = os->output_section_statement.next)
-    {
-      lang_output_section_statement_type *s =
-      &os->output_section_statement;
-
-      init_os (s);
-    }
-
-}
-
 /* Open input files and attatch to output sections */
 static void
 map_input_to_output_sections (s, target, output_section_statement)
@@ -1104,6 +1121,11 @@ map_input_to_output_sections (s, target, output_section_statement)
        case lang_target_statement_enum:
          target = s->target_statement.target;
          break;
+       case lang_group_statement_enum:
+         map_input_to_output_sections (s->group_statement.children.head,
+                                       target,
+                                       output_section_statement);
+         break;
        case lang_fill_statement_enum:
        case lang_input_section_enum:
        case lang_object_symbols_statement_enum:
@@ -1111,6 +1133,10 @@ map_input_to_output_sections (s, target, output_section_statement)
        case lang_reloc_statement_enum:
        case lang_assignment_statement_enum:
        case lang_padding_statement_enum:
+       case lang_input_statement_enum:
+         if (output_section_statement != NULL
+             && output_section_statement->bfd_section == NULL)
+           init_os (output_section_statement);
          break;
        case lang_afile_asection_pair_statement_enum:
          FAIL ();
@@ -1119,20 +1145,14 @@ map_input_to_output_sections (s, target, output_section_statement)
          /* Mark the specified section with the supplied address */
          {
            lang_output_section_statement_type *os =
-           lang_output_section_statement_lookup
-           (s->address_statement.section_name);
+             lang_output_section_statement_lookup
+               (s->address_statement.section_name);
 
+           if (os->bfd_section == NULL)
+             init_os (os);
            os->addr_tree = s->address_statement.address;
-           if (os->bfd_section == (asection *) NULL)
-             {
-               einfo ("%P%F: cannot set the address of undefined section %s\n",
-                      s->address_statement.section_name);
-             }
          }
          break;
-       case lang_input_statement_enum:
-         /* A standard input statement, has no wildcards */
-         break;
        }
     }
 }
@@ -1156,7 +1176,7 @@ print_output_section_statement (output_section_statement)
     print_address (section->vma);
     print_space ();
     print_size (section->_raw_size);
-    print_space();
+    print_space ();
     print_size(section->_cooked_size);
     print_space ();
     print_alignment (section->alignment_power);
@@ -1177,26 +1197,26 @@ print_output_section_statement (output_section_statement)
   }
   else
   {
-    fprintf (config.map_file, "No attached output section");
+    fprintf (config.map_file, " (no attached output section)");
   }
   print_nl ();
   if (output_section_statement->load_base)
     {
-      int b = exp_get_value_int(output_section_statement->load_base,
+      int b = exp_get_abs_int(output_section_statement->load_base,
                                0, "output base", lang_final_phase_enum);
-      printf("Output address   %08x\n", b);
+      fprintf (config.map_file, "Output address   %08x\n", b);
     }
   if (output_section_statement->section_alignment >= 0
       || output_section_statement->section_alignment >= 0) 
   {
-    printf("\t\t\t\t\tforced alignment ");
-    if ( output_section_statement->section_alignment >= 0) 
+    fprintf (config.map_file, "\t\t\t\t\tforced alignment ");
+    if (output_section_statement->section_alignment >= 0) 
     {
-      printf("section 2**%d ",output_section_statement->section_alignment );
+      fprintf (config.map_file, "section 2**%d ",output_section_statement->section_alignment );
     }
     if ( output_section_statement->subsection_alignment >= 0) 
     {
-      printf("subsection 2**%d ",output_section_statement->subsection_alignment );
+      fprintf (config.map_file, "subsection 2**%d ",output_section_statement->subsection_alignment );
     }
   
     print_nl ();
@@ -1460,6 +1480,19 @@ print_wild_statement (w, os)
   print_statement (w->children.head, os);
 
 }
+
+/* Print a group statement.  */
+
+static void
+print_group (s, os)
+     lang_group_statement_type *s;
+     lang_output_section_statement_type *os;
+{
+  fprintf (config.map_file, "START GROUP\n");
+  print_statement (s->children.head, os);
+  fprintf (config.map_file, "END GROUP\n");
+}
+
 static void
 print_statement (s, os)
      lang_statement_union_type * s;
@@ -1519,6 +1552,9 @@ print_statement (s, os)
        case lang_input_statement_enum:
          print_input_statement (&s->input_statement);
          break;
+       case lang_group_statement_enum:
+         print_group (&s->group_statement, os);
+         break;
        case lang_afile_asection_pair_statement_enum:
          FAIL ();
          break;
@@ -1650,15 +1686,38 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
        bfd_vma after;
        lang_output_section_statement_type *os = &s->output_section_statement;
 
-       /* If this is a shared library section, don't change the size
-         and address.  */
-       if (os->bfd_section->flags & SEC_SHARED_LIBRARY)
-        break;
+       if (os->bfd_section == NULL)
+        {
+          /* This section was never actually created.  */
+          break;
+        }
+
+       /* If this is a COFF shared library section, use the size and
+         address from the input section.  FIXME: This is COFF
+         specific; it would be cleaner if there were some other way
+         to do this, but nothing simple comes to mind.  */
+       if ((os->bfd_section->flags & SEC_COFF_SHARED_LIBRARY) != 0)
+        {
+          asection *input;
 
-       if (os->bfd_section == &bfd_abs_section)
+          if (os->children.head == NULL
+              || os->children.head->next != NULL
+              || os->children.head->header.type != lang_input_section_enum)
+            einfo ("%P%X: Internal error on COFF shared library section %s",
+                   os->name);
+
+          input = os->children.head->input_section.section;
+          bfd_set_section_vma (os->bfd_section->owner,
+                               os->bfd_section,
+                               bfd_section_vma (input->owner, input));
+          os->bfd_section->_raw_size = input->_raw_size;
+          break;
+        }
+
+       if (bfd_is_abs_section (os->bfd_section))
        {
         /* No matter what happens, an abs section starts at zero */
-        bfd_set_section_vma (0, os->bfd_section, 0);
+        ASSERT (os->bfd_section->vma == 0);
        }
        else
        {
@@ -1698,15 +1757,9 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
 
         bfd_set_section_vma (0, os->bfd_section, dot);
         
-        if (os->load_base) {
-          os->bfd_section->lma 
-            = exp_get_value_int(os->load_base, 0,"load base", lang_final_phase_enum);
-        }
+        os->bfd_section->output_offset = 0;
        }
 
-
-       os->bfd_section->output_offset = 0;
-
        (void) lang_size_sections (os->children.head, os, &os->children.head,
                                  os->fill, dot, relax);
        /* Ignore the size of the input sections, use the vma and size to */
@@ -1717,13 +1770,15 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
                        /* The coercion here is important, see ld.h.  */
                        (bfd_vma) os->block_value);
 
-       os->bfd_section->_raw_size = after - os->bfd_section->vma;
+       if (bfd_is_abs_section (os->bfd_section))
+        ASSERT (after == os->bfd_section->vma);
+       else
+        os->bfd_section->_raw_size = after - os->bfd_section->vma;
        dot = os->bfd_section->vma + os->bfd_section->_raw_size;
        os->processed = true;
 
        /* Replace into region ? */
-       if (os->addr_tree == (etree_type *) NULL
-          && os->region != (lang_memory_region_type *) NULL)
+       if (os->region != (lang_memory_region_type *) NULL)
        {
         os->region->current = dot;
         /* Make sure this isn't silly */
@@ -1741,6 +1796,8 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
           }
 
        }
+
+
      }
 
       break;
@@ -1852,29 +1909,38 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
                      &newdot);
 
        if (newdot != dot && !relax)
-       /* We've been moved ! so insert a pad */
-       {
-        lang_statement_union_type *new =
-         (lang_statement_union_type *)
-          stat_alloc ((bfd_size_type) (sizeof (lang_padding_statement_type)));
-
-        /* Link into existing chain */
-        new->header.next = *prev;
-        *prev = new;
-        new->header.type = lang_padding_statement_enum;
-        new->padding_statement.output_section =
-         output_section_statement->bfd_section;
-        new->padding_statement.output_offset =
-         dot - output_section_statement->bfd_section->vma;
-        new->padding_statement.fill = fill;
-        new->padding_statement.size = newdot - dot;
-        output_section_statement->bfd_section->_raw_size +=
-         new->padding_statement.size;
-        dot = newdot;
-       }
+        {
+          /* The assignment changed dot.  Insert a pad.  */
+          if (output_section_statement == abs_output_section)
+            {
+              /* If we don't have an output section, then just adjust
+                 the default memory address.  */
+              lang_memory_region_lookup ("*default*")->current = newdot;
+            }
+          else
+            {
+              lang_statement_union_type *new =
+                ((lang_statement_union_type *)
+                 stat_alloc (sizeof (lang_padding_statement_type)));
+
+              /* Link into existing chain */
+              new->header.next = *prev;
+              *prev = new;
+              new->header.type = lang_padding_statement_enum;
+              new->padding_statement.output_section =
+                output_section_statement->bfd_section;
+              new->padding_statement.output_offset =
+                dot - output_section_statement->bfd_section->vma;
+              new->padding_statement.fill = fill;
+              new->padding_statement.size = newdot - dot;
+              output_section_statement->bfd_section->_raw_size +=
+                new->padding_statement.size;
+            }
+
+          dot = newdot;
+        }
      }
-
-      break;
+     break;
 
    case lang_padding_statement_enum:
      /* If we are relaxing, and this is not the first pass, some
@@ -1887,6 +1953,13 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
      dot += s->padding_statement.size;
      break;
 
+     case lang_group_statement_enum:
+       dot = lang_size_sections (s->group_statement.children.head,
+                                output_section_statement,
+                                &s->group_statement.children.head,
+                                fill, dot, relax);
+       break;
+
      default:
       FAIL ();
       break;
@@ -1901,7 +1974,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
   return dot;
 }
 
-static bfd_vma
+bfd_vma
 lang_do_assignments (s, output_section_statement, fill, dot)
      lang_statement_union_type * s;
      lang_output_section_statement_type * output_section_statement;
@@ -1922,11 +1995,25 @@ lang_do_assignments (s, output_section_statement, fill, dot)
        case lang_output_section_statement_enum:
          {
            lang_output_section_statement_type *os =
-           &(s->output_section_statement);
+             &(s->output_section_statement);
 
-           dot = os->bfd_section->vma;
-           (void) lang_do_assignments (os->children.head, os, os->fill, dot);
-           dot = os->bfd_section->vma + os->bfd_section->_raw_size;
+           if (os->bfd_section != NULL)
+             {
+               dot = os->bfd_section->vma;
+               (void) lang_do_assignments (os->children.head, os,
+                                           os->fill, dot);
+               dot = os->bfd_section->vma + os->bfd_section->_raw_size;
+             }
+           if (os->load_base) 
+             {
+               /* If nothing has been placed into the output section then
+                  it won't have a bfd_section. */
+               if (os->bfd_section) 
+                 {
+                   os->bfd_section->lma 
+                     = exp_get_abs_int(os->load_base, 0,"load base", lang_final_phase_enum);
+                 }
+             }
          }
          break;
        case lang_wild_statement_enum:
@@ -2015,6 +2102,14 @@ lang_do_assignments (s, output_section_statement, fill, dot)
        case lang_padding_statement_enum:
          dot += s->padding_statement.size;
          break;
+
+       case lang_group_statement_enum:
+         dot = lang_do_assignments (s->group_statement.children.head,
+                                    output_section_statement,
+                                    fill, dot);
+
+         break;
+
        default:
          FAIL ();
          break;
@@ -2030,7 +2125,12 @@ static void
 lang_finish ()
 {
   struct bfd_link_hash_entry *h;
-  boolean warn = link_info.relocateable ? false : true;
+  boolean warn;
+
+  if (link_info.relocateable || link_info.shared)
+    warn = false;
+  else
+    warn = true;
 
   if (entry_symbol == (char *) NULL)
     {
@@ -2078,15 +2178,14 @@ lang_finish ()
     }
 }
 
-/* By now we know the target architecture, and we may have an */
-/* ldfile_output_machine_name */
+/* Check that the architecture of all the input files is compatible
+   with the output file.  */
+
 static void
 lang_check ()
 {
   lang_statement_union_type *file;
   bfd *input_bfd;
-  unsigned long input_machine;
-  enum bfd_architecture input_architecture;
   CONST bfd_arch_info_type *compatible;
 
   for (file = file_chain.head;
@@ -2094,36 +2193,12 @@ lang_check ()
        file = file->input_statement.next)
     {
       input_bfd = file->input_statement.the_bfd;
-
-      input_machine = bfd_get_mach (input_bfd);
-      input_architecture = bfd_get_arch (input_bfd);
-
-
-      /* Inspect the architecture and ensure we're linking like with
-         like */
-
       compatible = bfd_arch_get_compatible (input_bfd,
                                            output_bfd);
-      if (compatible)
-       {
-         ldfile_output_machine = compatible->mach;
-         ldfile_output_architecture = compatible->arch;
-       }
-      else
-       {
-
-         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));
-
-         if (! bfd_set_arch_mach (output_bfd,
-                                  input_architecture,
-                                  input_machine))
-           einfo ("%P%F:%s: can't set architecture: %E\n",
-                  bfd_get_filename (output_bfd));
-       }
-
+      if (compatible == NULL)
+       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));
     }
 }
 
@@ -2144,7 +2219,7 @@ lang_common ()
     {
       unsigned int power;
 
-      for (power = 1; power <= 16; power <<= 1)
+      for (power = 1; power < 4; power++)
        bfd_link_hash_traverse (link_info.hash, lang_one_common,
                                (PTR) &power);
     }
@@ -2159,49 +2234,24 @@ lang_one_common (h, info)
 {
   unsigned int power_of_two;
   bfd_vma size;
-  size_t align;
   asection *section;
 
   if (h->type != bfd_link_hash_common)
     return true;
 
   size = h->u.c.size;
-  switch (size)
-    {
-    case 0:
-    case 1:
-      power_of_two = 0;
-      align = 1;
-      break;
-    case 2:
-      power_of_two = 1;
-      align = 2;
-      break;
-    case 3:
-    case 4:
-      power_of_two = 2;
-      align = 4;
-      break;
-    case 5:
-    case 6:
-    case 7:
-    case 8:
-      power_of_two = 3;
-      align = 8;
-      break;
-    default:
-      power_of_two = 4;
-      align = 16;
-      break;
-    }
-             
-  if (config.sort_common && align != *(unsigned int *) info)
+  power_of_two = h->u.c.alignment_power;
+
+  if (config.sort_common
+      && power_of_two < *(unsigned int *) info
+      && *(unsigned int *) info < 4)
     return true;
 
   section = h->u.c.section;
 
   /* Increase the size of the section.  */
-  section->_raw_size = ALIGN_N (section->_raw_size, align);
+  section->_raw_size = ALIGN_N (section->_raw_size,
+                               (bfd_size_type) (1 << power_of_two));
 
   /* Adjust the alignment if necessary.  */
   if (power_of_two > section->alignment_power)
@@ -2215,6 +2265,9 @@ lang_one_common (h, info)
   /* Increase the size of the section.  */
   section->_raw_size += size;
 
+  /* Make sure the section is allocated in memory.  */
+  section->flags |= SEC_ALLOC;
+
   if (config.map_file != NULL)
     fprintf (config.map_file, "Allocating common %s: %lx at %lx %s\n",
             h->root.string, (unsigned long) size,
@@ -2241,6 +2294,9 @@ lang_place_orphans ()
     {
       asection *s;
 
+      if (file->just_syms_flag)
+       continue;
+
       for (s = file->the_bfd->sections;
           s != (asection *) NULL;
           s = s->next)
@@ -2271,6 +2327,8 @@ lang_place_orphans ()
                                 default_common_section, file);
                    }
                }
+             else if (ldemul_place_orphan (file, s))
+               ;
              else
                {
                  lang_output_section_statement_type *os =
@@ -2324,7 +2382,24 @@ lang_set_flags (ptr, flags)
     }
 }
 
+/* Call a function on each input file.  This function will be called
+   on an archive, but not on the elements.  */
+
+void
+lang_for_each_input_file (func)
+     void (*func) PARAMS ((lang_input_statement_type *));
+{
+  lang_input_statement_type *f;
+
+  for (f = (lang_input_statement_type *) input_file_chain.head;
+       f != NULL;
+       f = (lang_input_statement_type *) f->next_real_file)
+    func (f);
+}
 
+/* Call a function on each file.  The function will be called on all
+   the elements of an archive which are included in the link, but will
+   not be called on the archive file itself.  */
 
 void
 lang_for_each_file (func)
@@ -2501,9 +2576,6 @@ lang_process ()
   current_target = default_target;
 
   lang_for_each_statement (ldlang_open_output);        /* Open the output file */
-  /* For each output section statement, create a section in the output
-     file */
-  lang_create_output_section_statements ();
 
   ldemul_create_output_section_statements ();
 
@@ -2512,7 +2584,9 @@ lang_process ()
 
   /* Create a bfd for each input file */
   current_target = default_target;
-  lang_for_each_statement (open_input_bfds);
+  open_input_bfds (statement_list.head, false);
+
+  ldemul_after_open ();
 
   /* Build all sets based on the information gathered from the input
      files.  */
@@ -2627,11 +2701,25 @@ lang_section_start (name, address)
   ad->address = address;
 }
 
+/* Set the start symbol to NAME.  CMDLINE is nonzero if this is called
+   because of a -e argument on the command line, or zero if this is
+   called by ENTRY in a linker script.  Command line arguments take
+   precedence.  */
+
 void
-lang_add_entry (name)
+lang_add_entry (name, cmdline)
      CONST char *name;
+     int cmdline;
 {
-  entry_symbol = name;
+  static int from_cmdline;
+
+  if (entry_symbol == NULL
+      || cmdline
+      || ! from_cmdline)
+    {
+      entry_symbol = name;
+      from_cmdline = cmdline;
+    }
 }
 
 void
@@ -2695,7 +2783,7 @@ lang_add_data (type, exp)
 void
 lang_add_reloc (reloc, howto, section, name, addend)
      bfd_reloc_code_real_type reloc;
-     const reloc_howto_type *howto;
+     reloc_howto_type *howto;
      asection *section;
      const char *name;
      union etree_union *addend;
@@ -2760,14 +2848,6 @@ lang_leave_output_section_statement (fill, memspec)
   current_section->fill = fill;
   current_section->region = lang_memory_region_lookup (memspec);
   stat_ptr = &statement_list;
-
-  /* We remember if we are closing a .data section, since we use it to
-     store constructors in */
-  if (strcmp (current_section->name, ".data") == 0)
-    {
-      end_of_data_section_statement_list = statement_list;
-
-    }
 }
 
 /*
@@ -2800,7 +2880,7 @@ lang_abs_symbol_at_beginning_of (secname, name)
       else
        h->u.def.value = bfd_get_section_vma (output_bfd, sec);
 
-      h->u.def.section = &bfd_abs_section;
+      h->u.def.section = bfd_abs_section_ptr;
     }
 }
 
@@ -2835,7 +2915,7 @@ lang_abs_symbol_at_end_of (secname, name)
        h->u.def.value = (bfd_get_section_vma (output_bfd, sec)
                          + bfd_section_size (output_bfd, sec));
 
-      h->u.def.section = &bfd_abs_section;
+      h->u.def.section = bfd_abs_section_ptr;
     }
 }
 
@@ -2850,11 +2930,47 @@ lang_statement_append (list, element, field)
 }
 
 /* Set the output format type.  -oformat overrides scripts.  */
+
 void
-lang_add_output_format (format, from_script)
-     CONST char *format;
+lang_add_output_format (format, big, little, from_script)
+     const char *format;
+     const char *big;
+     const char *little;
      int from_script;
 {
   if (output_target == NULL || !from_script)
-    output_target = format;
+    {
+      if (command_line.endian == ENDIAN_BIG
+         && big != NULL)
+       format = big;
+      else if (command_line.endian == ENDIAN_LITTLE
+              && little != NULL)
+       format = little;
+
+      output_target = format;
+    }
+}
+
+/* Enter a group.  This creates a new lang_group_statement, and sets
+   stat_ptr to build new statements within the group.  */
+
+void
+lang_enter_group ()
+{
+  lang_group_statement_type *g;
+
+  g = new_stat (lang_group_statement, stat_ptr);
+  lang_list_init (&g->children);
+  stat_ptr = &g->children;
+}
+
+/* Leave a group.  This just resets stat_ptr to start writing to the
+   regular list of statements again.  Note that this will not work if
+   groups can occur inside anything else which can adjust stat_ptr,
+   but currently they can't.  */
+
+void
+lang_leave_group ()
+{
+  stat_ptr = &statement_list;
 }
This page took 0.060448 seconds and 4 git commands to generate.