From Craig Silverstein: rename some option functions in preparation
[external/binutils.git] / gold / layout.cc
index faae577..fd7f3af 100644 (file)
@@ -52,11 +52,14 @@ Layout_task_runner::run(Workqueue* workqueue, const Task* task)
 {
   off_t file_size = this->layout_->finalize(this->input_objects_,
                                            this->symtab_,
+                                            this->target_,
                                            task);
 
   // Now we know the final size of the output file and we know where
   // each piece of information goes.
-  Output_file* of = new Output_file(parameters->output_file_name());
+  Output_file* of = new Output_file(parameters->options().output_file_name());
+  if (this->options_.oformat_enum() != General_options::OBJECT_FORMAT_ELF)
+    of->set_is_temporary();
   of->open(file_size);
 
   // Queue up the final set of tasks.
@@ -153,12 +156,14 @@ Layout::include_section(Sized_relobj<size, big_endian>*, const char* name,
     case elfcpp::SHT_RELA:
     case elfcpp::SHT_REL:
     case elfcpp::SHT_GROUP:
-      // For a relocatable link these should be handled elsewhere.
-      gold_assert(!parameters->output_is_object());
+      // If we are emitting relocations these should be handled
+      // elsewhere.
+      gold_assert(!parameters->options().relocatable()
+                 && !parameters->options().emit_relocs());
       return false;
 
     case elfcpp::SHT_PROGBITS:
-      if (parameters->strip_debug()
+      if (parameters->options().strip_debug()
          && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
        {
          // Debugging sections can only be recognized by name.
@@ -168,7 +173,7 @@ Layout::include_section(Sized_relobj<size, big_endian>*, const char* name,
              || is_prefix_of(".stab", name))
            return false;
        }
-      if (parameters->strip_debug_gdb()
+      if (parameters->options().strip_debug_gdb()
          && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
        {
          // Debugging sections can only be recognized by name.
@@ -231,8 +236,21 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key,
   else
     {
       // This is the first time we've seen this name/type/flags
-      // combination.
-      Output_section* os = this->make_output_section(name, type, flags);
+      // combination.  If the section has contents but no flags, then
+      // see whether we have an existing section with the same name.
+      // This is a workaround for cases where assembler code forgets
+      // to set section flags, and the GNU linker would simply pick an
+      // existing section with the same name.  FIXME: Perhaps there
+      // should be an option to control this.
+      Output_section* os = NULL;
+      if (type == elfcpp::SHT_PROGBITS && flags == 0)
+       {
+         os = this->find_output_section(name);
+         if (os != NULL && os->type() != elfcpp::SHT_PROGBITS)
+           os = NULL;
+       }
+      if (os == NULL)
+       os = this->make_output_section(name, type, flags);
       ins.first->second = os;
       return os;
     }
@@ -301,7 +319,7 @@ Layout::choose_output_section(const Relobj* relobj, const char* name,
   // output section.
 
   size_t len = strlen(name);
-  if (adjust_name && !parameters->output_is_object())
+  if (adjust_name && !parameters->options().relocatable())
     name = Layout::output_section_name(name, &len);
 
   Stringpool::Key name_key;
@@ -335,7 +353,7 @@ Layout::layout(Sized_relobj<size, big_endian>* object, unsigned int shndx,
 
   // In a relocatable link a grouped section must not be combined with
   // any other sections.
-  if (parameters->output_is_object()
+  if (parameters->options().relocatable()
       && (shdr.get_sh_flags() & elfcpp::SHF_GROUP) != 0)
     {
       name = this->namepool_.add(name, true, NULL);
@@ -368,7 +386,8 @@ Layout::layout_reloc(Sized_relobj<size, big_endian>* object,
                     Output_section* data_section,
                     Relocatable_relocs* rr)
 {
-  gold_assert(parameters->output_is_object());
+  gold_assert(parameters->options().relocatable()
+             || parameters->options().emit_relocs());
 
   int sh_type = shdr.get_sh_type();
 
@@ -425,7 +444,7 @@ Layout::layout_group(Symbol_table* symtab,
                     const elfcpp::Shdr<size, big_endian>& shdr,
                     const elfcpp::Elf_Word* contents)
 {
-  gold_assert(parameters->output_is_object());
+  gold_assert(parameters->options().relocatable());
   gold_assert(shdr.get_sh_type() == elfcpp::SHT_GROUP);
   group_section_name = this->namepool_.add(group_section_name, true, NULL);
   Output_section* os = this->make_output_section(group_section_name,
@@ -489,7 +508,7 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
       this->eh_frame_data_ = new Eh_frame();
       os->add_output_section_data(this->eh_frame_data_);
 
-      if (this->options_.create_eh_frame_hdr())
+      if (this->options_.eh_frame_hdr())
        {
          Output_section* hdr_os =
            this->choose_output_section(NULL,
@@ -605,7 +624,7 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
     this->unattached_section_list_.push_back(os);
   else
     {
-      if (parameters->output_is_object())
+      if (parameters->options().relocatable())
        return os;
 
       // If we have a SECTIONS clause, we can't handle the attachment
@@ -619,11 +638,10 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
 
       elfcpp::Elf_Word seg_flags = Layout::section_flags_to_segment(flags);
 
-      // The only thing we really care about for PT_LOAD segments is
-      // whether or not they are writable, so that is how we search
-      // for them.  People who need segments sorted on some other
-      // basis will have to wait until we implement a mechanism for
-      // them to describe the segments they want.
+      // In general the only thing we really care about for PT_LOAD
+      // segments is whether or not they are writable, so that is how
+      // we search for them.  People who need segments sorted on some
+      // other basis will have to use a linker script.
 
       Segment_list::const_iterator p;
       for (p = this->segment_list_.begin();
@@ -633,6 +651,15 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
          if ((*p)->type() == elfcpp::PT_LOAD
              && ((*p)->flags() & elfcpp::PF_W) == (seg_flags & elfcpp::PF_W))
            {
+             // If -Tbss was specified, we need to separate the data
+             // and BSS segments.
+             if (this->options_.user_set_Tbss())
+               {
+                 if ((type == elfcpp::SHT_NOBITS)
+                     == (*p)->has_any_data_sections())
+                   continue;
+               }
+
              (*p)->add_output_section(os, seg_flags);
              break;
            }
@@ -685,6 +712,18 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
   return os;
 }
 
+// Make an output section for a script.
+
+Output_section*
+Layout::make_output_section_for_script(const char* name)
+{
+  name = this->namepool_.add(name, false, NULL);
+  Output_section* os = this->make_output_section(name, elfcpp::SHT_PROGBITS,
+                                                elfcpp::SHF_ALLOC);
+  os->set_found_in_sections_clause();
+  return os;
+}
+
 // Return the number of segments we expect to see.
 
 size_t
@@ -889,10 +928,8 @@ Layout::find_first_load_seg()
 
 off_t
 Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
-                const Task* task)
+                Target* target, const Task* task)
 {
-  Target* const target = parameters->target();
-
   target->finalize_sections(this);
 
   this->count_local_symbols(task, input_objects);
@@ -901,7 +938,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
   this->create_executable_stack_info(target);
 
   Output_segment* phdr_seg = NULL;
-  if (!parameters->output_is_object() && !parameters->doing_static_link())
+  if (!parameters->options().relocatable() && !parameters->doing_static_link())
     {
       // There was a dynamic object in the link.  We need to create
       // some information for the dynamic linker.
@@ -915,14 +952,15 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
       Output_section* dynstr;
       std::vector<Symbol*> dynamic_symbols;
       unsigned int local_dynamic_count;
-      Versions versions(this->options_, &this->dynpool_);
+      Versions versions(*this->script_options()->version_script_info(),
+                        &this->dynpool_);
       this->create_dynamic_symtab(input_objects, symtab, &dynstr,
                                  &local_dynamic_count, &dynamic_symbols,
                                  &versions);
 
       // Create the .interp section to hold the name of the
       // interpreter, and put it in a PT_INTERP segment.
-      if (!parameters->output_is_shared())
+      if (!parameters->options().shared())
         this->create_interp(target);
 
       // Finish the .dynamic section to hold the dynamic data, and put
@@ -942,18 +980,21 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
   // If there is a SECTIONS clause, put all the input sections into
   // the required order.
   Output_segment* load_seg;
-  if (parameters->output_is_object())
-    load_seg = NULL;
-  else if (this->script_options_->saw_sections_clause())
+  if (this->script_options_->saw_sections_clause())
     load_seg = this->set_section_addresses_from_script(symtab);
+  else if (parameters->options().relocatable())
+    load_seg = NULL;
   else
     load_seg = this->find_first_load_seg();
 
+  if (this->options_.oformat_enum() != General_options::OBJECT_FORMAT_ELF)
+    load_seg = NULL;
+
   gold_assert(phdr_seg == NULL || load_seg != NULL);
 
   // Lay out the segment headers.
   Output_segment_headers* segment_headers;
-  if (parameters->output_is_object())
+  if (parameters->options().relocatable())
     segment_headers = NULL;
   else
     {
@@ -967,7 +1008,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
   // Lay out the file header.
   Output_file_header* file_header;
   file_header = new Output_file_header(target, symtab, segment_headers,
-                                      this->script_options_->entry());
+                                      this->options_.entry());
   if (load_seg != NULL)
     load_seg->add_initial_output_data(file_header);
 
@@ -976,7 +1017,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
     this->special_output_list_.push_back(segment_headers);
 
   if (this->script_options_->saw_phdrs_clause()
-      && !parameters->output_is_object())
+      && !parameters->options().relocatable())
     {
       // Support use of FILEHDRS and PHDRS attachments in a PHDRS
       // clause in a linker script.
@@ -991,7 +1032,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
   // Set the file offsets of all the segments, and all the sections
   // they contain.
   off_t off;
-  if (!parameters->output_is_object())
+  if (!parameters->options().relocatable())
     off = this->set_segment_offsets(target, load_seg, &shndx);
   else
     off = this->set_relocatable_section_offsets(file_header, &shndx);
@@ -1047,7 +1088,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
 void
 Layout::create_gold_note()
 {
-  if (parameters->output_is_object())
+  if (parameters->options().relocatable())
     return;
 
   // Authorities all agree that the values in a .note field should
@@ -1062,7 +1103,7 @@ Layout::create_gold_note()
   // .note.ABI-tag (as of version 1.6), so that's the one we go with
   // here.
 #ifdef GABI_FORMAT_FOR_DOTNOTE_SECTION   // This is not defined by default.
-  const int size = parameters->get_size();
+  const int size = parameters->target().get_size();
 #else
   const int size = 32;
 #endif
@@ -1082,7 +1123,7 @@ Layout::create_gold_note()
   gold_assert(sizeof buffer >= notesz);
   memset(buffer, 0, notesz);
 
-  bool is_big_endian = parameters->is_big_endian();
+  bool is_big_endian = parameters->target().is_big_endian();
 
   if (size == 32)
     {
@@ -1159,7 +1200,7 @@ Layout::create_executable_stack_info(const Target* target)
        is_stack_executable = false;
     }
 
-  if (parameters->output_is_object())
+  if (parameters->options().relocatable())
     {
       const char* name = this->namepool_.add(".note.GNU-stack", false, NULL);
       elfcpp::Elf_Xword flags = 0;
@@ -1259,14 +1300,18 @@ Layout::segment_precedes(const Output_segment* seg1,
     return false;
 
   // We sort PT_LOAD segments based on the flags.  Readonly segments
-  // come before writable segments.  Then executable segments come
-  // before non-executable segments.  Then the unlikely case of a
-  // non-readable segment comes before the normal case of a readable
-  // segment.  If there are multiple segments with the same type and
-  // flags, we require that the address be set, and we sort by
-  // virtual address and then physical address.
+  // come before writable segments.  Then writable segments with data
+  // come before writable segments without data.  Then executable
+  // segments come before non-executable segments.  Then the unlikely
+  // case of a non-readable segment comes before the normal case of a
+  // readable segment.  If there are multiple segments with the same
+  // type and flags, we require that the address be set, and we sort
+  // by virtual address and then physical address.
   if ((flags1 & elfcpp::PF_W) != (flags2 & elfcpp::PF_W))
     return (flags1 & elfcpp::PF_W) == 0;
+  if ((flags1 & elfcpp::PF_W) != 0
+      && seg1->has_any_data_sections() != seg2->has_any_data_sections())
+    return seg1->has_any_data_sections();
   if ((flags1 & elfcpp::PF_X) != (flags2 & elfcpp::PF_X))
     return (flags1 & elfcpp::PF_X) != 0;
   if ((flags1 & elfcpp::PF_R) != (flags2 & elfcpp::PF_R))
@@ -1292,9 +1337,9 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
   // Find the PT_LOAD segments, and set their addresses and offsets
   // and their section's addresses and offsets.
   uint64_t addr;
-  if (this->options_.user_set_text_segment_address())
-    addr = options_.text_segment_address();
-  else if (parameters->output_is_shared())
+  if (this->options_.user_set_Ttext())
+    addr = this->options_.Ttext();
+  else if (parameters->options().shared())
     addr = 0;
   else
     addr = target->default_text_segment_address();
@@ -1326,6 +1371,29 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
            gold_unreachable();
          load_seg = NULL;
 
+         bool are_addresses_set = (*p)->are_addresses_set();
+         if (are_addresses_set)
+           {
+             // When it comes to setting file offsets, we care about
+             // the physical address.
+             addr = (*p)->paddr();
+           }
+         else if (this->options_.user_set_Tdata()
+                  && ((*p)->flags() & elfcpp::PF_W) != 0
+                  && (!this->options_.user_set_Tbss()
+                      || (*p)->has_any_data_sections()))
+           {
+             addr = this->options_.Tdata();
+             are_addresses_set = true;
+           }
+         else if (this->options_.user_set_Tbss()
+                  && ((*p)->flags() & elfcpp::PF_W) != 0
+                  && !(*p)->has_any_data_sections())
+           {
+             addr = this->options_.Tbss();
+             are_addresses_set = true;
+           }
+
          uint64_t orig_addr = addr;
          uint64_t orig_off = off;
 
@@ -1335,13 +1403,8 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
          // FIXME: This should depend on the -n and -N options.
          (*p)->set_minimum_p_align(target->common_pagesize());
 
-         bool are_addresses_set = (*p)->are_addresses_set();
          if (are_addresses_set)
            {
-             // When it comes to setting file offsets, we care about
-             // the physical address.
-             addr = (*p)->paddr();
-
              // Adjust the file offset to the same address modulo the
              // page size.
              uint64_t unsigned_off = off;
@@ -1522,7 +1585,7 @@ Layout::set_section_offsets(off_t off, Layout::Section_offset_pass pass)
 unsigned int
 Layout::set_section_indexes(unsigned int shndx)
 {
-  const bool output_is_object = parameters->output_is_object();
+  const bool output_is_object = parameters->options().relocatable();
   for (Section_list::iterator p = this->unattached_section_list_.begin();
        p != this->unattached_section_list_.end();
        ++p)
@@ -1608,12 +1671,12 @@ Layout::create_symtab_sections(const Input_objects* input_objects,
 {
   int symsize;
   unsigned int align;
-  if (parameters->get_size() == 32)
+  if (parameters->target().get_size() == 32)
     {
       symsize = elfcpp::Elf_sizes<32>::sym_size;
       align = 4;
     }
-  else if (parameters->get_size() == 64)
+  else if (parameters->target().get_size() == 64)
     {
       symsize = elfcpp::Elf_sizes<64>::sym_size;
       align = 8;
@@ -1680,7 +1743,7 @@ Layout::create_symtab_sections(const Input_objects* input_objects,
   off = symtab->finalize(off, dynoff, dyn_global_index, dyncount,
                         &this->sympool_, &local_symcount);
 
-  if (!parameters->strip_all())
+  if (!parameters->options().strip_all())
     {
       this->sympool_.set_string_offsets();
 
@@ -1806,7 +1869,7 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
 
   int symsize;
   unsigned int align;
-  const int size = parameters->get_size();
+  const int size = parameters->target().get_size();
   if (size == 32)
     {
       symsize = elfcpp::Elf_sizes<32>::sym_size;
@@ -1918,58 +1981,39 @@ Layout::create_version_sections(const Versions* versions,
   if (!versions->any_defs() && !versions->any_needs())
     return;
 
-  if (parameters->get_size() == 32)
+  switch (parameters->size_and_endianness())
     {
-      if (parameters->is_big_endian())
-        {
-#ifdef HAVE_TARGET_32_BIG
-          this->sized_create_version_sections
-              SELECT_SIZE_ENDIAN_NAME(32, true)(
-                 versions, symtab, local_symcount, dynamic_symbols, dynstr
-                  SELECT_SIZE_ENDIAN(32, true));
-#else
-          gold_unreachable();
-#endif
-        }
-      else
-        {
 #ifdef HAVE_TARGET_32_LITTLE
-          this->sized_create_version_sections
-              SELECT_SIZE_ENDIAN_NAME(32, false)(
-                 versions, symtab, local_symcount, dynamic_symbols, dynstr
-                  SELECT_SIZE_ENDIAN(32, false));
-#else
-          gold_unreachable();
+    case Parameters::TARGET_32_LITTLE:
+      this->sized_create_version_sections<32, false>(versions, symtab,
+                                                    local_symcount,
+                                                    dynamic_symbols, dynstr);
+      break;
 #endif
-        }
-    }
-  else if (parameters->get_size() == 64)
-    {
-      if (parameters->is_big_endian())
-        {
-#ifdef HAVE_TARGET_64_BIG
-          this->sized_create_version_sections
-              SELECT_SIZE_ENDIAN_NAME(64, true)(
-                  versions, symtab, local_symcount, dynamic_symbols, dynstr
-                  SELECT_SIZE_ENDIAN(64, true));
-#else
-          gold_unreachable();
+#ifdef HAVE_TARGET_32_BIG
+    case Parameters::TARGET_32_BIG:
+      this->sized_create_version_sections<32, true>(versions, symtab,
+                                                   local_symcount,
+                                                   dynamic_symbols, dynstr);
+      break;
 #endif
-        }
-      else
-        {
 #ifdef HAVE_TARGET_64_LITTLE
-          this->sized_create_version_sections
-              SELECT_SIZE_ENDIAN_NAME(64, false)(
-                  versions, symtab, local_symcount, dynamic_symbols, dynstr
-                  SELECT_SIZE_ENDIAN(64, false));
-#else
-          gold_unreachable();
+    case Parameters::TARGET_64_LITTLE:
+      this->sized_create_version_sections<64, false>(versions, symtab,
+                                                    local_symcount,
+                                                    dynamic_symbols, dynstr);
+      break;
 #endif
-        }
+#ifdef HAVE_TARGET_64_BIG
+    case Parameters::TARGET_64_BIG:
+      this->sized_create_version_sections<64, true>(versions, symtab,
+                                                   local_symcount,
+                                                   dynamic_symbols, dynstr);
+      break;
+#endif
+    default:
+      gold_unreachable();
     }
-  else
-    gold_unreachable();
 }
 
 // Create the version sections, sized version.
@@ -1981,8 +2025,7 @@ Layout::sized_create_version_sections(
     const Symbol_table* symtab,
     unsigned int local_symcount,
     const std::vector<Symbol*>& dynamic_symbols,
-    const Output_section* dynstr
-    ACCEPT_SIZE_ENDIAN)
+    const Output_section* dynstr)
 {
   Output_section* vsec = this->choose_output_section(NULL, ".gnu.version",
                                                     elfcpp::SHT_GNU_versym,
@@ -1991,9 +2034,10 @@ Layout::sized_create_version_sections(
 
   unsigned char* vbuf;
   unsigned int vsize;
-  versions->symbol_section_contents SELECT_SIZE_ENDIAN_NAME(size, big_endian)(
-      symtab, &this->dynpool_, local_symcount, dynamic_symbols, &vbuf, &vsize
-      SELECT_SIZE_ENDIAN(size, big_endian));
+  versions->symbol_section_contents<size, big_endian>(symtab, &this->dynpool_,
+                                                     local_symcount,
+                                                     dynamic_symbols,
+                                                     &vbuf, &vsize);
 
   Output_section_data* vdata = new Output_data_const_buffer(vbuf, vsize, 2);
 
@@ -2015,9 +2059,8 @@ Layout::sized_create_version_sections(
       unsigned char* vdbuf;
       unsigned int vdsize;
       unsigned int vdentries;
-      versions->def_section_contents SELECT_SIZE_ENDIAN_NAME(size, big_endian)(
-          &this->dynpool_, &vdbuf, &vdsize, &vdentries
-          SELECT_SIZE_ENDIAN(size, big_endian));
+      versions->def_section_contents<size, big_endian>(&this->dynpool_, &vdbuf,
+                                                      &vdsize, &vdentries);
 
       Output_section_data* vddata = new Output_data_const_buffer(vdbuf,
                                                                 vdsize,
@@ -2042,9 +2085,9 @@ Layout::sized_create_version_sections(
       unsigned char* vnbuf;
       unsigned int vnsize;
       unsigned int vnentries;
-      versions->need_section_contents SELECT_SIZE_ENDIAN_NAME(size, big_endian)
-        (&this->dynpool_, &vnbuf, &vnsize, &vnentries
-         SELECT_SIZE_ENDIAN(size, big_endian));
+      versions->need_section_contents<size, big_endian>(&this->dynpool_,
+                                                       &vnbuf, &vnsize,
+                                                       &vnentries);
 
       Output_section_data* vndata = new Output_data_const_buffer(vnbuf,
                                                                 vnsize,
@@ -2114,7 +2157,7 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
       odyn->add_string(elfcpp::DT_NEEDED, (*p)->soname());
     }
 
-  if (parameters->output_is_shared())
+  if (parameters->options().shared())
     {
       const char* soname = this->options_.soname();
       if (soname != NULL)
@@ -2163,16 +2206,38 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
 
   // Look for text segments that have dynamic relocations.
   bool have_textrel = false;
-  for (Segment_list::const_iterator p = this->segment_list_.begin();
-       p != this->segment_list_.end();
-       ++p)
+  if (!this->script_options_->saw_sections_clause())
     {
-      if (((*p)->flags() & elfcpp::PF_W) == 0
-         && (*p)->dynamic_reloc_count() > 0)
-       {
-         have_textrel = true;
-         break;
-       }
+      for (Segment_list::const_iterator p = this->segment_list_.begin();
+           p != this->segment_list_.end();
+           ++p)
+        {
+          if (((*p)->flags() & elfcpp::PF_W) == 0
+              && (*p)->dynamic_reloc_count() > 0)
+            {
+              have_textrel = true;
+              break;
+            }
+        }
+    }
+  else
+    {
+      // We don't know the section -> segment mapping, so we are
+      // conservative and just look for readonly sections with
+      // relocations.  If those sections wind up in writable segments,
+      // then we have created an unnecessary DT_TEXTREL entry.
+      for (Section_list::const_iterator p = this->section_list_.begin();
+           p != this->section_list_.end();
+           ++p)
+        {
+          if (((*p)->flags() & elfcpp::SHF_ALLOC) != 0
+              && ((*p)->flags() & elfcpp::SHF_WRITE) == 0
+              && ((*p)->dynamic_reloc_count() > 0))
+            {
+              have_textrel = true;
+              break;
+            }
+        }
     }
 
   // Add a DT_FLAGS entry. We add it even if no flags are set so that
@@ -2184,7 +2249,7 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
       odyn->add_constant(elfcpp::DT_TEXTREL, 0);
       flags |= elfcpp::DF_TEXTREL;
     }
-  if (parameters->output_is_shared() && this->has_static_tls())
+  if (parameters->options().shared() && this->has_static_tls())
     flags |= elfcpp::DF_STATIC_TLS;
   odyn->add_constant(elfcpp::DT_FLAGS, flags);
 }
@@ -2379,7 +2444,7 @@ Layout::get_allocated_sections(Section_list* section_list) const
 Output_segment*
 Layout::make_output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
 {
-  gold_assert(!parameters->output_is_object());
+  gold_assert(!parameters->options().relocatable());
   Output_segment* oseg = new Output_segment(type, flags);
   this->segment_list_.push_back(oseg);
   return oseg;
@@ -2406,7 +2471,7 @@ Layout::write_output_sections(Output_file* of) const
 void
 Layout::write_data(const Symbol_table* symtab, Output_file* of) const
 {
-  if (!parameters->strip_all())
+  if (!parameters->options().strip_all())
     {
       const Output_section* symtab_section = this->symtab_section_;
       for (Section_list::const_iterator p = this->section_list_.begin();
@@ -2486,6 +2551,55 @@ Layout::write_sections_after_input_sections(Output_file* of)
   this->section_headers_->write(of);
 }
 
+// Write out a binary file.  This is called after the link is
+// complete.  IN is the temporary output file we used to generate the
+// ELF code.  We simply walk through the segments, read them from
+// their file offset in IN, and write them to their load address in
+// the output file.  FIXME: with a bit more work, we could support
+// S-records and/or Intel hex format here.
+
+void
+Layout::write_binary(Output_file* in) const
+{
+  gold_assert(this->options_.oformat_enum()
+             == General_options::OBJECT_FORMAT_BINARY);
+
+  // Get the size of the binary file.
+  uint64_t max_load_address = 0;
+  for (Segment_list::const_iterator p = this->segment_list_.begin();
+       p != this->segment_list_.end();
+       ++p)
+    {
+      if ((*p)->type() == elfcpp::PT_LOAD && (*p)->filesz() > 0)
+       {
+         uint64_t max_paddr = (*p)->paddr() + (*p)->filesz();
+         if (max_paddr > max_load_address)
+           max_load_address = max_paddr;
+       }
+    }
+
+  Output_file out(parameters->options().output_file_name());
+  out.open(max_load_address);
+
+  for (Segment_list::const_iterator p = this->segment_list_.begin();
+       p != this->segment_list_.end();
+       ++p)
+    {
+      if ((*p)->type() == elfcpp::PT_LOAD && (*p)->filesz() > 0)
+       {
+         const unsigned char* vin = in->get_input_view((*p)->offset(),
+                                                       (*p)->filesz());
+         unsigned char* vout = out.get_output_view((*p)->paddr(),
+                                                   (*p)->filesz());
+         memcpy(vout, vin, (*p)->filesz());
+         out.write_output_view((*p)->paddr(), (*p)->filesz(), vout);
+         in->free_input_view((*p)->offset(), (*p)->filesz(), vin);
+       }
+    }
+
+  out.close();
+}
+
 // Print statistical information to stderr.  This is used for --stats.
 
 void
@@ -2617,6 +2731,10 @@ Write_after_input_sections_task::run(Workqueue*)
 void
 Close_task_runner::run(Workqueue*, const Task*)
 {
+  // If we've been asked to create a binary file, we do so here.
+  if (this->options_->oformat_enum() != General_options::OBJECT_FORMAT_ELF)
+    this->layout_->write_binary(this->of_);
+
   this->of_->close();
 }