* script-sections.cc (class Orphan_section_placement): Define
[binutils-gdb.git] / gold / output.cc
index e3b11714e8fb64ddfe87ca4a50201042e9cdbed0..0627cbe698fa64c87bd61fe2b4afb83275689398 100644 (file)
@@ -213,7 +213,9 @@ Output_section_headers::do_sized_write(Output_file* of)
     else
       oshdr.put_sh_link(shstrndx);
 
-    oshdr.put_sh_info(0);
+    size_t segment_count = this->segment_list_->size();
+    oshdr.put_sh_info(segment_count >= elfcpp::PN_XNUM ? segment_count : 0);
+
     oshdr.put_sh_addralign(0);
     oshdr.put_sh_entsize(0);
   }
@@ -442,7 +444,7 @@ Output_file_header::do_sized_write(Output_file* of)
   elfcpp::ET e_type;
   if (parameters->options().relocatable())
     e_type = elfcpp::ET_REL;
-  else if (parameters->options().shared())
+  else if (parameters->options().output_is_position_independent())
     e_type = elfcpp::ET_DYN;
   else
     e_type = elfcpp::ET_EXEC;
@@ -459,10 +461,7 @@ Output_file_header::do_sized_write(Output_file* of)
     oehdr.put_e_phoff(this->segment_header_->offset());
 
   oehdr.put_e_shoff(this->section_header_->offset());
-
-  // FIXME: The target needs to set the flags.
-  oehdr.put_e_flags(0);
-
+  oehdr.put_e_flags(this->target_->processor_specific_flags());
   oehdr.put_e_ehsize(elfcpp::Elf_sizes<size>::ehdr_size);
 
   if (this->segment_header_ == NULL)
@@ -473,8 +472,11 @@ Output_file_header::do_sized_write(Output_file* of)
   else
     {
       oehdr.put_e_phentsize(elfcpp::Elf_sizes<size>::phdr_size);
-      oehdr.put_e_phnum(this->segment_header_->data_size()
-                       / elfcpp::Elf_sizes<size>::phdr_size);
+      size_t phnum = (this->segment_header_->data_size()
+                     / elfcpp::Elf_sizes<size>::phdr_size);
+      if (phnum > elfcpp::PN_XNUM)
+       phnum = elfcpp::PN_XNUM;
+      oehdr.put_e_phnum(phnum);
     }
 
   oehdr.put_e_shentsize(elfcpp::Elf_sizes<size>::shdr_size);
@@ -636,9 +638,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     unsigned int type,
     Output_data* od,
     Address address,
-    bool is_relative)
+    bool is_relative,
+    bool is_symbolless)
   : address_(address), local_sym_index_(GSYM_CODE), type_(type),
-    is_relative_(is_relative), is_section_symbol_(false), shndx_(INVALID_CODE)
+    is_relative_(is_relative), is_symbolless_(is_symbolless),
+    is_section_symbol_(false), shndx_(INVALID_CODE)
 {
   // this->type_ is a bitfield; make sure TYPE fits.
   gold_assert(this->type_ == type);
@@ -655,9 +659,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Sized_relobj<size, big_endian>* relobj,
     unsigned int shndx,
     Address address,
-    bool is_relative)
+    bool is_relative,
+    bool is_symbolless)
   : address_(address), local_sym_index_(GSYM_CODE), type_(type),
-    is_relative_(is_relative), is_section_symbol_(false), shndx_(shndx)
+    is_relative_(is_relative), is_symbolless_(is_symbolless),
+    is_section_symbol_(false), shndx_(shndx)
 {
   gold_assert(shndx != INVALID_CODE);
   // this->type_ is a bitfield; make sure TYPE fits.
@@ -678,10 +684,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Output_data* od,
     Address address,
     bool is_relative,
+    bool is_symbolless,
     bool is_section_symbol)
   : address_(address), local_sym_index_(local_sym_index), type_(type),
-    is_relative_(is_relative), is_section_symbol_(is_section_symbol),
-    shndx_(INVALID_CODE)
+    is_relative_(is_relative), is_symbolless_(is_symbolless),
+    is_section_symbol_(is_section_symbol), shndx_(INVALID_CODE)
 {
   gold_assert(local_sym_index != GSYM_CODE
               && local_sym_index != INVALID_CODE);
@@ -701,10 +708,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     unsigned int shndx,
     Address address,
     bool is_relative,
+    bool is_symbolless,
     bool is_section_symbol)
   : address_(address), local_sym_index_(local_sym_index), type_(type),
-    is_relative_(is_relative), is_section_symbol_(is_section_symbol),
-    shndx_(shndx)
+    is_relative_(is_relative), is_symbolless_(is_symbolless),
+    is_section_symbol_(is_section_symbol), shndx_(shndx)
 {
   gold_assert(local_sym_index != GSYM_CODE
               && local_sym_index != INVALID_CODE);
@@ -726,7 +734,8 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Output_data* od,
     Address address)
   : address_(address), local_sym_index_(SECTION_CODE), type_(type),
-    is_relative_(false), is_section_symbol_(true), shndx_(INVALID_CODE)
+    is_relative_(false), is_symbolless_(false),
+    is_section_symbol_(true), shndx_(INVALID_CODE)
 {
   // this->type_ is a bitfield; make sure TYPE fits.
   gold_assert(this->type_ == type);
@@ -746,7 +755,8 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     unsigned int shndx,
     Address address)
   : address_(address), local_sym_index_(SECTION_CODE), type_(type),
-    is_relative_(false), is_section_symbol_(true), shndx_(shndx)
+    is_relative_(false), is_symbolless_(false),
+    is_section_symbol_(true), shndx_(shndx)
 {
   gold_assert(shndx != INVALID_CODE);
   // this->type_ is a bitfield; make sure TYPE fits.
@@ -759,6 +769,76 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     os->set_needs_symtab_index();
 }
 
+// An absolute relocation.
+
+template<bool dynamic, int size, bool big_endian>
+Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
+    unsigned int type,
+    Output_data* od,
+    Address address)
+  : address_(address), local_sym_index_(0), type_(type),
+    is_relative_(false), is_symbolless_(false),
+    is_section_symbol_(false), shndx_(INVALID_CODE)
+{
+  // this->type_ is a bitfield; make sure TYPE fits.
+  gold_assert(this->type_ == type);
+  this->u1_.relobj = NULL;
+  this->u2_.od = od;
+}
+
+template<bool dynamic, int size, bool big_endian>
+Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
+    unsigned int type,
+    Sized_relobj<size, big_endian>* relobj,
+    unsigned int shndx,
+    Address address)
+  : address_(address), local_sym_index_(0), type_(type),
+    is_relative_(false), is_symbolless_(false),
+    is_section_symbol_(false), shndx_(shndx)
+{
+  gold_assert(shndx != INVALID_CODE);
+  // this->type_ is a bitfield; make sure TYPE fits.
+  gold_assert(this->type_ == type);
+  this->u1_.relobj = NULL;
+  this->u2_.relobj = relobj;
+}
+
+// A target specific relocation.
+
+template<bool dynamic, int size, bool big_endian>
+Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
+    unsigned int type,
+    void* arg,
+    Output_data* od,
+    Address address)
+  : address_(address), local_sym_index_(TARGET_CODE), type_(type),
+    is_relative_(false), is_symbolless_(false),
+    is_section_symbol_(false), shndx_(INVALID_CODE)
+{
+  // this->type_ is a bitfield; make sure TYPE fits.
+  gold_assert(this->type_ == type);
+  this->u1_.arg = arg;
+  this->u2_.od = od;
+}
+
+template<bool dynamic, int size, bool big_endian>
+Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
+    unsigned int type,
+    void* arg,
+    Sized_relobj<size, big_endian>* relobj,
+    unsigned int shndx,
+    Address address)
+  : address_(address), local_sym_index_(TARGET_CODE), type_(type),
+    is_relative_(false), is_symbolless_(false),
+    is_section_symbol_(false), shndx_(shndx)
+{
+  gold_assert(shndx != INVALID_CODE);
+  // this->type_ is a bitfield; make sure TYPE fits.
+  gold_assert(this->type_ == type);
+  this->u1_.arg = arg;
+  this->u2_.relobj = relobj;
+}
+
 // Record that we need a dynamic symbol index for this relocation.
 
 template<bool dynamic, int size, bool big_endian>
@@ -766,7 +846,7 @@ void
 Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::
 set_needs_dynsym_index()
 {
-  if (this->is_relative_)
+  if (this->is_symbolless_)
     return;
   switch (this->local_sym_index_)
     {
@@ -781,6 +861,10 @@ set_needs_dynsym_index()
       this->u1_.os->set_needs_dynsym_index();
       break;
 
+    case TARGET_CODE:
+      // The target must take care of this if necessary.
+      break;
+
     case 0:
       break;
 
@@ -804,6 +888,8 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::get_symbol_index()
   const
 {
   unsigned int index;
+  if (this->is_symbolless_)
+    return 0;
   switch (this->local_sym_index_)
     {
     case INVALID_CODE:
@@ -825,6 +911,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::get_symbol_index()
        index = this->u1_.os->symtab_index();
       break;
 
+    case TARGET_CODE:
+      index = parameters->target().reloc_symbol_index(this->u1_.arg,
+                                                     this->type_);
+      break;
+
     case 0:
       // Relocations without symbols use a symbol index of 0.
       index = 0;
@@ -866,7 +957,9 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::
 {
   gold_assert(this->local_sym_index_ != GSYM_CODE
               && this->local_sym_index_ != SECTION_CODE
+             && this->local_sym_index_ != TARGET_CODE
               && this->local_sym_index_ != INVALID_CODE
+             && this->local_sym_index_ != 0
               && this->is_section_symbol_);
   const unsigned int lsi = this->local_sym_index_;
   Output_section* os = this->u1_.relobj->output_section(lsi);
@@ -916,7 +1009,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::write_rel(
     Write_rel* wr) const
 {
   wr->put_r_offset(this->get_address());
-  unsigned int sym_index = this->is_relative_ ? 0 : this->get_symbol_index();
+  unsigned int sym_index = this->get_symbol_index();
   wr->put_r_info(elfcpp::elf_r_info<size>(sym_index, this->type_));
 }
 
@@ -945,7 +1038,9 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::symbol_value(
       return sym->value() + addend;
     }
   gold_assert(this->local_sym_index_ != SECTION_CODE
+             && this->local_sym_index_ != TARGET_CODE
               && this->local_sym_index_ != INVALID_CODE
+             && this->local_sym_index_ != 0
               && !this->is_section_symbol_);
   const unsigned int lsi = this->local_sym_index_;
   const Symbol_value<size>* symval = this->u1_.relobj->local_symbol(lsi);
@@ -1013,7 +1108,10 @@ Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>::write(
   elfcpp::Rela_write<size, big_endian> orel(pov);
   this->rel_.write_rel(&orel);
   Addend addend = this->addend_;
-  if (this->rel_.is_relative())
+  if (this->rel_.is_target_specific())
+    addend = parameters->target().reloc_addend(this->rel_.target_arg(),
+                                              this->rel_.type(), addend);
+  else if (this->rel_.is_symbolless())
     addend = this->rel_.symbol_value(addend);
   else if (this->rel_.is_local_section_symbol())
     addend = this->rel_.local_section_offset(addend);
@@ -1052,7 +1150,7 @@ Output_data_reloc_base<sh_type, dynamic, size, big_endian>::do_write(
   const off_t oview_size = this->data_size();
   unsigned char* const oview = of->get_output_view(off, oview_size);
 
-  if (this->sort_relocs_)
+  if (this->sort_relocs())
     {
       gold_assert(dynamic);
       std::sort(this->relocs_.begin(), this->relocs_.end(),
@@ -1476,6 +1574,8 @@ Output_data_dynamic::Dynamic_entry::write(
 
     case DYNAMIC_SECTION_SIZE:
       val = this->u_.od->data_size();
+      if (this->od2 != NULL)
+       val += this->od2->data_size();
       break;
 
     case DYNAMIC_SYMBOL:
@@ -1522,9 +1622,13 @@ Output_data_dynamic::set_final_data_size()
 {
   // Add the terminating entry if it hasn't been added.
   // Because of relaxation, we can run this multiple times.
-  if (this->entries_.empty()
-      || this->entries_.rbegin()->tag() != elfcpp::DT_NULL)
-    this->add_constant(elfcpp::DT_NULL, 0);
+  if (this->entries_.empty() || this->entries_.back().tag() != elfcpp::DT_NULL)
+    {
+      int extra = parameters->options().spare_dynamic_tags();
+      for (int i = 0; i < extra; ++i)
+       this->add_constant(elfcpp::DT_NULL, 0);
+      this->add_constant(elfcpp::DT_NULL, 0);
+    }
 
   int dyn_size;
   if (parameters->target().get_size() == 32)
@@ -1798,10 +1902,21 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
     attached_input_sections_are_sorted_(false),
     is_relro_(false),
     is_relro_local_(false),
+    is_last_relro_(false),
+    is_first_non_relro_(false),
     is_small_section_(false),
     is_large_section_(false),
+    is_interp_(false),
+    is_dynamic_linker_section_(false),
+    generate_code_fills_at_write_(false),
+    is_entsize_zero_(false),
+    section_offsets_need_adjustment_(false),
     tls_offset_(0),
-    checkpoint_(NULL)
+    checkpoint_(NULL),
+    merge_section_map_(),
+    merge_section_by_properties_map_(),
+    relaxed_input_section_map_(),
+    is_relaxed_input_section_map_valid_(true)
 {
   // An unallocated section has no address.  Forcing this means that
   // we don't need special treatment for symbols defined in debug
@@ -1820,10 +1935,15 @@ Output_section::~Output_section()
 void
 Output_section::set_entsize(uint64_t v)
 {
-  if (this->entsize_ == 0)
+  if (this->is_entsize_zero_)
+    ;
+  else if (this->entsize_ == 0)
     this->entsize_ = v;
-  else
-    gold_assert(this->entsize_ == v);
+  else if (this->entsize_ != v)
+    {
+      this->entsize_ = 0;
+      this->is_entsize_zero_ = 1;
+    }
 }
 
 // Add the input section SHNDX, with header SHDR, named SECNAME, in
@@ -1859,8 +1979,6 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object,
     this->addralign_ = addralign;
 
   typename elfcpp::Elf_types<size>::Elf_WXword sh_flags = shdr.get_sh_flags();
-  this->update_flags_for_input_section(sh_flags);
-
   uint64_t entsize = shdr.get_sh_entsize();
 
   // .debug_str is a mergeable string section, but is not always so
@@ -1871,6 +1989,9 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object,
       entsize = 1;
     }
 
+  this->update_flags_for_input_section(sh_flags);
+  this->set_entsize(entsize);
+
   // If this is a SHF_MERGE section, we pass all the input sections to
   // a Output_data_merge.  We don't try to handle relocations for such
   // a section.  We don't try to handle empty merge sections--they
@@ -1892,7 +2013,21 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object,
   off_t aligned_offset_in_section = align_address(offset_in_section,
                                                   addralign);
 
+  // Determine if we want to delay code-fill generation until the output
+  // section is written.  When the target is relaxing, we want to delay fill
+  // generating to avoid adjusting them during relaxation.
+  if (!this->generate_code_fills_at_write_
+      && !have_sections_script
+      && (sh_flags & elfcpp::SHF_EXECINSTR) != 0
+      && parameters->target().has_code_fill()
+      && parameters->target().may_relax())
+    {
+      gold_assert(this->fills_.empty());
+      this->generate_code_fills_at_write_ = true;
+    }
+
   if (aligned_offset_in_section > offset_in_section
+      && !this->generate_code_fills_at_write_
       && !have_sections_script
       && (sh_flags & elfcpp::SHF_EXECINSTR) != 0
       && parameters->target().has_code_fill())
@@ -1905,8 +2040,6 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object,
         this->fills_.push_back(Fill(offset_in_section, fill_len));
       else
         {
-          // FIXME: When relaxing, the size needs to adjust to
-          // maintain a constant alignment.
           std::string fill_data(parameters->target().code_fill(fill_len));
           Output_data_const* odc = new Output_data_const(fill_data, 1);
           this->input_sections_.push_back(Input_section(odc));
@@ -1951,6 +2084,31 @@ Output_section::add_output_section_data(Output_section_data* posd)
     }
 }
 
+// Add a relaxed input section.
+
+void
+Output_section::add_relaxed_input_section(Output_relaxed_input_section* poris)
+{
+  Input_section inp(poris);
+  this->add_output_section_data(&inp);
+  if (this->is_relaxed_input_section_map_valid_)
+    {
+      Const_section_id csid(poris->relobj(), poris->shndx());
+      this->relaxed_input_section_map_[csid] = poris;
+    }
+
+  // For a relaxed section, we use the current data size.  Linker scripts
+  // get all the input sections, including relaxed one from an output
+  // section and add them back to them same output section to compute the
+  // output section size.  If we do not account for sizes of relaxed input
+  // sections,  an output section would be incorrectly sized.
+  off_t offset_in_section = this->current_data_size_for_child();
+  off_t aligned_offset_in_section = align_address(offset_in_section,
+                                                 poris->addralign());
+  this->set_current_data_size_for_child(aligned_offset_in_section
+                                       + poris->current_data_size());
+}
+
 // Add arbitrary data to an output section by Input_section.
 
 void
@@ -1995,73 +2153,160 @@ Output_section::add_merge_input_section(Relobj* object, unsigned int shndx,
   // We cannot restore merged input section states.
   gold_assert(this->checkpoint_ == NULL);
 
-  Input_section_list::iterator p;
-  for (p = this->input_sections_.begin();
-       p != this->input_sections_.end();
-       ++p)
-    if (p->is_merge_section(is_string, entsize, addralign))
-      {
-        p->add_input_section(object, shndx);
-        return true;
-      }
+  // Look up merge sections by required properties.
+  Merge_section_properties msp(is_string, entsize, addralign);
+  Merge_section_by_properties_map::const_iterator p =
+    this->merge_section_by_properties_map_.find(msp);
+  if (p != this->merge_section_by_properties_map_.end())
+    {
+      Output_merge_base* merge_section = p->second;
+      merge_section->add_input_section(object, shndx);
+      gold_assert(merge_section->is_string() == is_string
+                 && merge_section->entsize() == entsize
+                 && merge_section->addralign() == addralign);
+
+      // Link input section to found merge section.
+      Const_section_id csid(object, shndx);
+      this->merge_section_map_[csid] = merge_section;
+      return true;
+    }
 
   // We handle the actual constant merging in Output_merge_data or
   // Output_merge_string_data.
-  Output_section_data* posd;
+  Output_merge_base* pomb;
   if (!is_string)
-    posd = new Output_merge_data(entsize, addralign);
+    pomb = new Output_merge_data(entsize, addralign);
   else
     {
       switch (entsize)
        {
         case 1:
-         posd = new Output_merge_string<char>(addralign);
+         pomb = new Output_merge_string<char>(addralign);
          break;
         case 2:
-         posd = new Output_merge_string<uint16_t>(addralign);
+         pomb = new Output_merge_string<uint16_t>(addralign);
          break;
         case 4:
-         posd = new Output_merge_string<uint32_t>(addralign);
+         pomb = new Output_merge_string<uint32_t>(addralign);
          break;
         default:
          return false;
        }
     }
 
-  this->add_output_merge_section(posd, is_string, entsize);
-  posd->add_input_section(object, shndx);
+  // Add new merge section to this output section and link merge section
+  // properties to new merge section in map.
+  this->add_output_merge_section(pomb, is_string, entsize);
+  this->merge_section_by_properties_map_[msp] = pomb;
+
+  // Add input section to new merge section and link input section to new
+  // merge section in map.
+  pomb->add_input_section(object, shndx);
+  Const_section_id csid(object, shndx);
+  this->merge_section_map_[csid] = pomb;
 
   return true;
 }
 
-// Relax an existing input section.
+// Build a relaxation map to speed up relaxation of existing input sections.
+// Look up to the first LIMIT elements in INPUT_SECTIONS.
+
 void
-Output_section::relax_input_section(Output_relaxed_input_section *psection)
+Output_section::build_relaxation_map(
+  const Input_section_list& input_sections,
+  size_t limit,
+  Relaxation_map* relaxation_map) const
 {
-  Relobj* relobj = psection->relobj();
-  unsigned int shndx = psection->shndx();
+  for (size_t i = 0; i < limit; ++i)
+    {
+      const Input_section& is(input_sections[i]);
+      if (is.is_input_section() || is.is_relaxed_input_section())
+       {
+         Section_id sid(is.relobj(), is.shndx());
+         (*relaxation_map)[sid] = i;
+       }
+    }
+}
+
+// Convert regular input sections in INPUT_SECTIONS into relaxed input
+// sections in RELAXED_SECTIONS.  MAP is a prebuilt map from section id
+// indices of INPUT_SECTIONS.
 
+void
+Output_section::convert_input_sections_in_list_to_relaxed_sections(
+  const std::vector<Output_relaxed_input_section*>& relaxed_sections,
+  const Relaxation_map& map,
+  Input_section_list* input_sections)
+{
+  for (size_t i = 0; i < relaxed_sections.size(); ++i)
+    {
+      Output_relaxed_input_section* poris = relaxed_sections[i];
+      Section_id sid(poris->relobj(), poris->shndx());
+      Relaxation_map::const_iterator p = map.find(sid);
+      gold_assert(p != map.end());
+      gold_assert((*input_sections)[p->second].is_input_section());
+      (*input_sections)[p->second] = Input_section(poris);
+    }
+}
+  
+// Convert regular input sections into relaxed input sections. RELAXED_SECTIONS
+// is a vector of pointers to Output_relaxed_input_section or its derived
+// classes.  The relaxed sections must correspond to existing input sections.
+
+void
+Output_section::convert_input_sections_to_relaxed_sections(
+  const std::vector<Output_relaxed_input_section*>& relaxed_sections)
+{
   gold_assert(parameters->target().may_relax());
 
-  // This is not very efficient if we a going to relax a number of sections
-  // in an Output_section with lot of Input_sections.
-  for (Input_section_list::iterator p = this->input_sections_.begin();
-       p != this->input_sections_.end();
-       ++p)
+  // We want to make sure that restore_states does not undo the effect of
+  // this.  If there is no checkpoint active, just search the current
+  // input section list and replace the sections there.  If there is
+  // a checkpoint, also replace the sections there.
+  
+  // By default, we look at the whole list.
+  size_t limit = this->input_sections_.size();
+
+  if (this->checkpoint_ != NULL)
     {
-      if (p->is_input_section())
+      // Replace input sections with relaxed input section in the saved
+      // copy of the input section list.
+      if (this->checkpoint_->input_sections_saved())
        {
-         if (p->relobj() == relobj && p->shndx() == shndx)
-           {
-             gold_assert(p->addralign() == psection->addralign());
-             *p = Input_section(psection);
-             return;
-           }
+         Relaxation_map map;
+         this->build_relaxation_map(
+                   *(this->checkpoint_->input_sections()),
+                   this->checkpoint_->input_sections()->size(),
+                   &map);
+         this->convert_input_sections_in_list_to_relaxed_sections(
+                   relaxed_sections,
+                   map,
+                   this->checkpoint_->input_sections());
+       }
+      else
+       {
+         // We have not copied the input section list yet.  Instead, just
+         // look at the portion that would be saved.
+         limit = this->checkpoint_->input_sections_size();
        }
-      else if (p->is_relaxed_input_section())
-       gold_assert(p->relobj() != relobj || p->shndx() != shndx);
-
     }
+
+  // Convert input sections in input_section_list.
+  Relaxation_map map;
+  this->build_relaxation_map(this->input_sections_, limit, &map);
+  this->convert_input_sections_in_list_to_relaxed_sections(
+           relaxed_sections,
+           map,
+           &this->input_sections_);
+
+  // Update fast look-up map.
+  if (this->is_relaxed_input_section_map_valid_)
+    for (size_t i = 0; i < relaxed_sections.size(); ++i)
+      {
+       Output_relaxed_input_section* poris = relaxed_sections[i];
+       Const_section_id csid(poris->relobj(), poris->shndx());
+       this->relaxed_input_section_map_[csid] = poris;
+      }
 }
 
 // Update the output section flags based on input section flags.
@@ -2080,6 +2325,76 @@ Output_section::update_flags_for_input_section(elfcpp::Elf_Xword flags)
                   & (elfcpp::SHF_WRITE
                      | elfcpp::SHF_ALLOC
                      | elfcpp::SHF_EXECINSTR));
+
+  if ((flags & elfcpp::SHF_MERGE) == 0)
+    this->flags_ &=~ elfcpp::SHF_MERGE;
+  else
+    {
+      if (this->current_data_size_for_child() == 0)
+       this->flags_ |= elfcpp::SHF_MERGE;
+    }
+
+  if ((flags & elfcpp::SHF_STRINGS) == 0)
+    this->flags_ &=~ elfcpp::SHF_STRINGS;
+  else
+    {
+      if (this->current_data_size_for_child() == 0)
+       this->flags_ |= elfcpp::SHF_STRINGS;
+    }
+}
+
+// Find the merge section into which an input section with index SHNDX in
+// OBJECT has been added.  Return NULL if none found.
+
+Output_section_data*
+Output_section::find_merge_section(const Relobj* object,
+                                  unsigned int shndx) const
+{
+  Const_section_id csid(object, shndx);
+  Output_section_data_by_input_section_map::const_iterator p =
+    this->merge_section_map_.find(csid);
+  if (p != this->merge_section_map_.end())
+    {
+      Output_section_data* posd = p->second;
+      gold_assert(posd->is_merge_section_for(object, shndx));
+      return posd;
+    }
+  else
+    return NULL;
+}
+
+// Find an relaxed input section corresponding to an input section
+// in OBJECT with index SHNDX.
+
+const Output_relaxed_input_section*
+Output_section::find_relaxed_input_section(const Relobj* object,
+                                          unsigned int shndx) const
+{
+  // Be careful that the map may not be valid due to input section export
+  // to scripts or a check-point restore.
+  if (!this->is_relaxed_input_section_map_valid_)
+    {
+      // Rebuild the map as needed.
+      this->relaxed_input_section_map_.clear();
+      for (Input_section_list::const_iterator p = this->input_sections_.begin();
+          p != this->input_sections_.end();
+          ++p)
+       if (p->is_relaxed_input_section())
+         {
+           Const_section_id csid(p->relobj(), p->shndx());
+           this->relaxed_input_section_map_[csid] =
+             p->relaxed_input_section();
+         }
+      this->is_relaxed_input_section_map_valid_ = true;
+    }
+
+  Const_section_id csid(object, shndx);
+  Output_relaxed_input_section_by_input_section_map::const_iterator p =
+    this->relaxed_input_section_map_.find(csid);
+  if (p != this->relaxed_input_section_map_.end())
+    return p->second;
+  else
+    return NULL;
 }
 
 // Given an address OFFSET relative to the start of input section
@@ -2092,6 +2407,20 @@ Output_section::is_input_address_mapped(const Relobj* object,
                                        unsigned int shndx,
                                        off_t offset) const
 {
+  // Look at the Output_section_data_maps first.
+  const Output_section_data* posd = this->find_merge_section(object, shndx);
+  if (posd == NULL)
+    posd = this->find_relaxed_input_section(object, shndx);
+
+  if (posd != NULL)
+    {
+      section_offset_type output_offset;
+      bool found = posd->output_offset(object, shndx, offset, &output_offset);
+      gold_assert(found);   
+      return output_offset != -1;
+    }
+
+  // Fall back to the slow look-up.
   for (Input_section_list::const_iterator p = this->input_sections_.begin();
        p != this->input_sections_.end();
        ++p)
@@ -2116,9 +2445,23 @@ section_offset_type
 Output_section::output_offset(const Relobj* object, unsigned int shndx,
                              section_offset_type offset) const
 {
-  // This can only be called meaningfully when layout is complete.
-  gold_assert(Output_data::is_layout_complete());
+  // This can only be called meaningfully when we know the data size
+  // of this.
+  gold_assert(this->is_data_size_valid());
 
+  // Look at the Output_section_data_maps first.
+  const Output_section_data* posd = this->find_merge_section(object, shndx);
+  if (posd == NULL) 
+    posd = this->find_relaxed_input_section(object, shndx);
+  if (posd != NULL)
+    {
+      section_offset_type output_offset;
+      bool found = posd->output_offset(object, shndx, offset, &output_offset);
+      gold_assert(found);   
+      return output_offset;
+    }
+
+  // Fall back to the slow look-up.
   for (Input_section_list::const_iterator p = this->input_sections_.begin();
        p != this->input_sections_.end();
        ++p)
@@ -2138,6 +2481,20 @@ Output_section::output_address(const Relobj* object, unsigned int shndx,
                               off_t offset) const
 {
   uint64_t addr = this->address() + this->first_input_offset_;
+
+  // Look at the Output_section_data_maps first.
+  const Output_section_data* posd = this->find_merge_section(object, shndx);
+  if (posd == NULL) 
+    posd = this->find_relaxed_input_section(object, shndx);
+  if (posd != NULL && posd->is_address_valid())
+    {
+      section_offset_type output_offset;
+      bool found = posd->output_offset(object, shndx, offset, &output_offset);
+      gold_assert(found);
+      return posd->address() + output_offset;
+    }
+
+  // Fall back to the slow look-up.
   for (Input_section_list::const_iterator p = this->input_sections_.begin();
        p != this->input_sections_.end();
        ++p)
@@ -2169,6 +2526,9 @@ Output_section::find_starting_output_address(const Relobj* object,
                                             unsigned int shndx,
                                             uint64_t* paddr) const
 {
+  // FIXME: This becomes a bottle-neck if we have many relaxed sections.
+  // Looking up the merge section map does not always work as we sometimes
+  // find a merge section without its address set.
   uint64_t addr = this->address() + this->first_input_offset_;
   for (Input_section_list::const_iterator p = this->input_sections_.begin();
        p != this->input_sections_.end();
@@ -2339,7 +2699,7 @@ class Output_section::Input_section_sort_entry
   has_priority() const
   {
     gold_assert(this->section_has_name_);
-    return this->section_name_.find('.', 1);
+    return this->section_name_.find('.', 1) != std::string::npos;
   }
 
   // Return true if this an input file whose base name matches
@@ -2417,8 +2777,6 @@ Output_section::Input_section_sort_compare::operator()(
     }
 
   // A section with a priority follows a section without a priority.
-  // The GNU linker does this for all but .init_array sections; until
-  // further notice we'll assume that that is an mistake.
   bool s1_has_priority = s1.has_priority();
   bool s2_has_priority = s2.has_priority();
   if (s1_has_priority && !s2_has_priority)
@@ -2435,6 +2793,42 @@ Output_section::Input_section_sort_compare::operator()(
   return s1.index() < s2.index();
 }
 
+// Return true if S1 should come before S2 in an .init_array or .fini_array
+// output section.
+
+bool
+Output_section::Input_section_sort_init_fini_compare::operator()(
+    const Output_section::Input_section_sort_entry& s1,
+    const Output_section::Input_section_sort_entry& s2) const
+{
+  // We sort all the sections with no names to the end.
+  if (!s1.section_has_name() || !s2.section_has_name())
+    {
+      if (s1.section_has_name())
+       return true;
+      if (s2.section_has_name())
+       return false;
+      return s1.index() < s2.index();
+    }
+
+  // A section without a priority follows a section with a priority.
+  // This is the reverse of .ctors and .dtors sections.
+  bool s1_has_priority = s1.has_priority();
+  bool s2_has_priority = s2.has_priority();
+  if (s1_has_priority && !s2_has_priority)
+    return true;
+  if (!s1_has_priority && s2_has_priority)
+    return false;
+
+  // Otherwise we sort by name.
+  int compare = s1.section_name().compare(s2.section_name());
+  if (compare != 0)
+    return compare < 0;
+
+  // Otherwise we keep the input order.
+  return s1.index() < s2.index();
+}
+
 // Sort the input sections attached to an output section.
 
 void
@@ -2463,7 +2857,14 @@ Output_section::sort_attached_input_sections()
     sort_list.push_back(Input_section_sort_entry(*p, i));
 
   // Sort the input sections.
-  std::sort(sort_list.begin(), sort_list.end(), Input_section_sort_compare());
+  if (this->type() == elfcpp::SHT_PREINIT_ARRAY
+      || this->type() == elfcpp::SHT_INIT_ARRAY
+      || this->type() == elfcpp::SHT_FINI_ARRAY)
+    std::sort(sort_list.begin(), sort_list.end(),
+             Input_section_sort_init_fini_compare());
+  else
+    std::sort(sort_list.begin(), sort_list.end(),
+             Input_section_sort_compare());
 
   // Copy the sorted input sections back to our list.
   this->input_sections_.clear();
@@ -2532,6 +2933,9 @@ Output_section::do_write(Output_file* of)
 {
   gold_assert(!this->requires_postprocessing());
 
+  // If the target performs relaxation, we delay filler generation until now.
+  gold_assert(!this->generate_code_fills_at_write_ || this->fills_.empty());
+
   off_t output_section_file_offset = this->offset();
   for (Fill_list::iterator p = this->fills_.begin();
        p != this->fills_.end();
@@ -2542,10 +2946,22 @@ Output_section::do_write(Output_file* of)
                fill_data.data(), fill_data.size());
     }
 
+  off_t off = this->offset() + this->first_input_offset_;
   for (Input_section_list::iterator p = this->input_sections_.begin();
        p != this->input_sections_.end();
        ++p)
-    p->write(of);
+    {
+      off_t aligned_off = align_address(off, p->addralign());
+      if (this->generate_code_fills_at_write_ && (off != aligned_off))
+       {
+         size_t fill_len = aligned_off - off;
+         std::string fill_data(parameters->target().code_fill(fill_len));
+         of->write(off, fill_data.data(), fill_data.size());
+       }
+
+      p->write(of);
+      off = aligned_off + p->data_size();
+    }
 }
 
 // If a section requires postprocessing, create the buffer to use.
@@ -2586,6 +3002,9 @@ Output_section::write_to_postprocessing_buffer()
 {
   gold_assert(this->requires_postprocessing());
 
+  // If the target performs relaxation, we delay filler generation until now.
+  gold_assert(!this->generate_code_fills_at_write_ || this->fills_.empty());
+
   unsigned char* buffer = this->postprocessing_buffer();
   for (Fill_list::iterator p = this->fills_.begin();
        p != this->fills_.end();
@@ -2601,9 +3020,16 @@ Output_section::write_to_postprocessing_buffer()
        p != this->input_sections_.end();
        ++p)
     {
-      off = align_address(off, p->addralign());
-      p->write_to_buffer(buffer + off);
-      off += p->data_size();
+      off_t aligned_off = align_address(off, p->addralign());
+      if (this->generate_code_fills_at_write_ && (off != aligned_off))
+       {
+         size_t fill_len = aligned_off - off;
+         std::string fill_data(parameters->target().code_fill(fill_len));
+         memcpy(buffer + off, fill_data.data(), fill_data.size());
+       }
+
+      p->write_to_buffer(buffer + aligned_off);
+      off = aligned_off + p->data_size();
     }
 }
 
@@ -2627,6 +3053,9 @@ Output_section::get_input_sections(
       && !this->checkpoint_->input_sections_saved())
     this->checkpoint_->save_input_sections();
 
+  // Invalidate the relaxed input section map.
+  this->is_relaxed_input_section_map_valid_ = false;
+
   uint64_t orig_address = address;
 
   address = align_address(address, this->addralign());
@@ -2676,12 +3105,12 @@ Output_section::get_input_sections(
   return data_size;
 }
 
-// Add an input section from a script.
+// Add an simple input section.
 
 void
-Output_section::add_input_section_for_script(const Simple_input_section& sis,
-                                            off_t data_size,
-                                            uint64_t addralign)
+Output_section::add_simple_input_section(const Simple_input_section& sis,
+                                        off_t data_size,
+                                        uint64_t addralign)
 {
   if (addralign > this->addralign_)
     this->addralign_ = addralign;
@@ -2700,7 +3129,7 @@ Output_section::add_input_section_for_script(const Simple_input_section& sis,
   this->input_sections_.push_back(is);
 }
 
-//
+// Save states for relaxation.
 
 void
 Output_section::save_states()
@@ -2715,6 +3144,19 @@ Output_section::save_states()
   gold_assert(this->fills_.empty());
 }
 
+void
+Output_section::discard_states()
+{
+  gold_assert(this->checkpoint_ != NULL);
+  delete this->checkpoint_;
+  this->checkpoint_ = NULL;
+  gold_assert(this->fills_.empty());
+
+  // Simply invalidate the relaxed input section map since we do not keep
+  // track of it.
+  this->is_relaxed_input_section_map_valid_ = false;
+}
+
 void
 Output_section::restore_states()
 {
@@ -2738,11 +3180,38 @@ Output_section::restore_states()
       // extremely large output with hundreads of thousands of input
       // objects.  We may need to re-think how we should pass sections
       // to scripts.
-      this->input_sections_ = checkpoint->input_sections();
+      this->input_sections_ = *checkpoint->input_sections();
     }
 
   this->attached_input_sections_are_sorted_ =
     checkpoint->attached_input_sections_are_sorted();
+
+  // Simply invalidate the relaxed input section map since we do not keep
+  // track of it.
+  this->is_relaxed_input_section_map_valid_ = false;
+}
+
+// Update the section offsets of input sections in this.  This is required if
+// relaxation causes some input sections to change sizes.
+
+void
+Output_section::adjust_section_offsets()
+{
+  if (!this->section_offsets_need_adjustment_)
+    return;
+
+  off_t off = 0;
+  for (Input_section_list::iterator p = this->input_sections_.begin();
+       p != this->input_sections_.end();
+       ++p)
+    {
+      off = align_address(off, p->addralign());
+      if (p->is_input_section())
+       p->relobj()->set_section_offset(p->shndx(), off);
+      off += p->data_size();
+    }
+
+  this->section_offsets_need_adjustment_ = false;
 }
 
 // Print to the map file.
@@ -2788,20 +3257,25 @@ Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
     are_addresses_set_(false),
     is_large_data_segment_(false)
 {
+  // The ELF ABI specifies that a PT_TLS segment always has PF_R as
+  // the flags.
+  if (type == elfcpp::PT_TLS)
+    this->flags_ = elfcpp::PF_R;
 }
 
 // Add an Output_section to an Output_segment.
 
 void
 Output_segment::add_output_section(Output_section* os,
-                                  elfcpp::Elf_Word seg_flags)
+                                  elfcpp::Elf_Word seg_flags,
+                                  bool do_sort)
 {
   gold_assert((os->flags() & elfcpp::SHF_ALLOC) != 0);
   gold_assert(!this->is_max_align_known_);
   gold_assert(os->is_large_data_section() == this->is_large_data_segment());
+  gold_assert(this->type() == elfcpp::PT_LOAD || !do_sort);
 
-  // Update the segment flags.
-  this->flags_ |= seg_flags;
+  this->update_flags_for_output_section(seg_flags);
 
   Output_segment::Output_data_list* pdl;
   if (os->type() == elfcpp::SHT_NOBITS)
@@ -2809,19 +3283,12 @@ Output_segment::add_output_section(Output_section* os,
   else
     pdl = &this->output_data_;
 
-  // So that PT_NOTE segments will work correctly, we need to ensure
-  // that all SHT_NOTE sections are adjacent.  This will normally
-  // happen automatically, because all the SHT_NOTE input sections
-  // will wind up in the same output section.  However, it is possible
-  // for multiple SHT_NOTE input sections to have different section
-  // flags, and thus be in different output sections, but for the
-  // different section flags to map into the same segment flags and
-  // thus the same output segment.
-
   // Note that while there may be many input sections in an output
   // section, there are normally only a few output sections in an
-  // output segment.  This loop is expected to be fast.
+  // output segment.  The loops below are expected to be fast.
 
+  // So that PT_NOTE segments will work correctly, we need to ensure
+  // that all SHT_NOTE sections are adjacent.
   if (os->type() == elfcpp::SHT_NOTE && !pdl->empty())
     {
       Output_segment::Output_data_list::iterator p = pdl->end();
@@ -2843,67 +3310,98 @@ Output_segment::add_output_section(Output_section* os,
   // case: we group the SHF_TLS/SHT_NOBITS sections right after the
   // SHF_TLS/SHT_PROGBITS sections.  This lets us set up PT_TLS
   // correctly.  SHF_TLS sections get added to both a PT_LOAD segment
-  // and the PT_TLS segment -- we do this grouping only for the
-  // PT_LOAD segment.
+  // and the PT_TLS segment; we do this grouping only for the PT_LOAD
+  // segment.
   if (this->type_ != elfcpp::PT_TLS
       && (os->flags() & elfcpp::SHF_TLS) != 0)
     {
       pdl = &this->output_data_;
-      bool nobits = os->type() == elfcpp::SHT_NOBITS;
-      bool sawtls = false;
-      Output_segment::Output_data_list::iterator p = pdl->end();
-      do
+      if (!pdl->empty())
        {
-         --p;
-         bool insert;
-         if ((*p)->is_section_flag_set(elfcpp::SHF_TLS))
+         bool nobits = os->type() == elfcpp::SHT_NOBITS;
+         bool sawtls = false;
+         Output_segment::Output_data_list::iterator p = pdl->end();
+         gold_assert(p != pdl->begin());
+         do
            {
-             sawtls = true;
-             // Put a NOBITS section after the first TLS section.
-             // Put a PROGBITS section after the first TLS/PROGBITS
-             // section.
-             insert = nobits || !(*p)->is_section_type(elfcpp::SHT_NOBITS);
-           }
-         else
-           {
-             // If we've gone past the TLS sections, but we've seen a
-             // TLS section, then we need to insert this section now.
-             insert = sawtls;
-           }
+             --p;
+             bool insert;
+             if ((*p)->is_section_flag_set(elfcpp::SHF_TLS))
+               {
+                 sawtls = true;
+                 // Put a NOBITS section after the first TLS section.
+                 // Put a PROGBITS section after the first
+                 // TLS/PROGBITS section.
+                 insert = nobits || !(*p)->is_section_type(elfcpp::SHT_NOBITS);
+               }
+             else
+               {
+                 // If we've gone past the TLS sections, but we've
+                 // seen a TLS section, then we need to insert this
+                 // section now.
+                 insert = sawtls;
+               }
 
-         if (insert)
-           {
-             ++p;
-             pdl->insert(p, os);
-             return;
+             if (insert)
+               {
+                 ++p;
+                 pdl->insert(p, os);
+                 return;
+               }
            }
+         while (p != pdl->begin());
        }
-      while (p != pdl->begin());
 
       // There are no TLS sections yet; put this one at the requested
       // location in the section list.
     }
 
-  // For the PT_GNU_RELRO segment, we need to group relro sections,
-  // and we need to put them before any non-relro sections.  Also,
-  // relro local sections go before relro non-local sections.
-  if (parameters->options().relro() && os->is_relro())
+  if (do_sort)
     {
-      gold_assert(pdl == &this->output_data_);
-      Output_segment::Output_data_list::iterator p;
-      for (p = pdl->begin(); p != pdl->end(); ++p)
+      // For the PT_GNU_RELRO segment, we need to group relro
+      // sections, and we need to put them before any non-relro
+      // sections.  Any relro local sections go before relro non-local
+      // sections.  One section may be marked as the last relro
+      // section.
+      if (os->is_relro())
        {
-         if (!(*p)->is_section())
-           break;
+         gold_assert(pdl == &this->output_data_);
+         Output_segment::Output_data_list::iterator p;
+         for (p = pdl->begin(); p != pdl->end(); ++p)
+           {
+             if (!(*p)->is_section())
+               break;
+
+             Output_section* pos = (*p)->output_section();
+             if (!pos->is_relro()
+                 || (os->is_relro_local() && !pos->is_relro_local())
+                 || (!os->is_last_relro() && pos->is_last_relro()))
+               break;
+           }
 
-         Output_section* pos = (*p)->output_section();
-         if (!pos->is_relro()
-             || (os->is_relro_local() && !pos->is_relro_local()))
-           break;
+         pdl->insert(p, os);
+         return;
        }
 
-      pdl->insert(p, os);
-      return;
+      // One section may be marked as the first section which follows
+      // the relro sections.
+      if (os->is_first_non_relro())
+       {
+         gold_assert(pdl == &this->output_data_);
+         Output_segment::Output_data_list::iterator p;
+         for (p = pdl->begin(); p != pdl->end(); ++p)
+           {
+             if (!(*p)->is_section())
+               break;
+
+             Output_section* pos = (*p)->output_section();
+             if (!pos->is_relro())
+               break;
+           }
+
+         pdl->insert(p, os);
+         return;
+       }
     }
 
   // Small data sections go at the end of the list of data sections.
@@ -2969,6 +3467,68 @@ Output_segment::add_output_section(Output_section* os,
       gold_unreachable();
     }
 
+  // We do some further output section sorting in order to make the
+  // generated program run more efficiently.  We should only do this
+  // when not using a linker script, so it is controled by the DO_SORT
+  // parameter.
+  if (do_sort)
+    {
+      // FreeBSD requires the .interp section to be in the first page
+      // of the executable.  That is a more efficient location anyhow
+      // for any OS, since it means that the kernel will have the data
+      // handy after it reads the program headers.
+      if (os->is_interp() && !pdl->empty())
+       {
+         pdl->insert(pdl->begin(), os);
+         return;
+       }
+
+      // Put loadable non-writable notes immediately after the .interp
+      // sections, so that the PT_NOTE segment is on the first page of
+      // the executable.
+      if (os->type() == elfcpp::SHT_NOTE
+         && (os->flags() & elfcpp::SHF_WRITE) == 0
+         && !pdl->empty())
+       {
+         Output_segment::Output_data_list::iterator p = pdl->begin();
+         if ((*p)->is_section() && (*p)->output_section()->is_interp())
+           ++p;
+         pdl->insert(p, os);
+         return;
+       }
+
+      // If this section is used by the dynamic linker, and it is not
+      // writable, then put it first, after the .interp section and
+      // any loadable notes.  This makes it more likely that the
+      // dynamic linker will have to read less data from the disk.
+      if (os->is_dynamic_linker_section()
+         && !pdl->empty()
+         && (os->flags() & elfcpp::SHF_WRITE) == 0)
+       {
+         bool is_reloc = (os->type() == elfcpp::SHT_REL
+                          || os->type() == elfcpp::SHT_RELA);
+         Output_segment::Output_data_list::iterator p = pdl->begin();
+         while (p != pdl->end()
+                && (*p)->is_section()
+                && ((*p)->output_section()->is_dynamic_linker_section()
+                    || (*p)->output_section()->type() == elfcpp::SHT_NOTE))
+           {
+             // Put reloc sections after the other ones.  Putting the
+             // dynamic reloc sections first confuses BFD, notably
+             // objcopy and strip.
+             if (!is_reloc
+                 && ((*p)->output_section()->type() == elfcpp::SHT_REL
+                     || (*p)->output_section()->type() == elfcpp::SHT_RELA))
+               break;
+             ++p;
+           }
+         pdl->insert(p, os);
+         return;
+       }
+    }
+
+  // If there were no constraints on the output section, just add it
+  // to the end of the list.
   pdl->push_back(os);
 }
 
@@ -2993,8 +3553,8 @@ Output_segment::remove_output_section(Output_section* os)
   gold_unreachable();
 }
 
-// Add an Output_data (which is not an Output_section) to the start of
-// a segment.
+// Add an Output_data (which need not be an Output_section) to the
+// start of a segment.
 
 void
 Output_segment::add_initial_output_data(Output_data* od)
@@ -3030,19 +3590,6 @@ Output_segment::maximum_alignment()
       if (addralign > this->max_align_)
        this->max_align_ = addralign;
 
-      // If -z relro is in effect, and the first section in this
-      // segment is a relro section, then the segment must be aligned
-      // to at least the common page size.  This ensures that the
-      // PT_GNU_RELRO segment will start at a page boundary.
-      if (this->type_ == elfcpp::PT_LOAD
-         && parameters->options().relro()
-         && this->is_first_section_relro())
-       {
-         addralign = parameters->target().common_pagesize();
-         if (addralign > this->max_align_)
-           this->max_align_ = addralign;
-       }
-
       this->is_max_align_known_ = true;
     }
 
@@ -3096,11 +3643,57 @@ Output_segment::dynamic_reloc_count_list(const Output_data_list* pdl) const
 
 uint64_t
 Output_segment::set_section_addresses(const Layout* layout, bool reset,
-                                      uint64_t addr, off_t* poff,
+                                      uint64_t addr,
+                                     unsigned int increase_relro,
+                                     off_t* poff,
                                      unsigned int* pshndx)
 {
   gold_assert(this->type_ == elfcpp::PT_LOAD);
 
+  off_t orig_off = *poff;
+
+  // If we have relro sections, we need to pad forward now so that the
+  // relro sections plus INCREASE_RELRO end on a common page boundary.
+  if (parameters->options().relro()
+      && this->is_first_section_relro()
+      && (!this->are_addresses_set_ || reset))
+    {
+      uint64_t relro_size = 0;
+      off_t off = *poff;
+      for (Output_data_list::iterator p = this->output_data_.begin();
+          p != this->output_data_.end();
+          ++p)
+       {
+         if (!(*p)->is_section())
+           break;
+         Output_section* pos = (*p)->output_section();
+         if (!pos->is_relro())
+           break;
+         gold_assert(!(*p)->is_section_flag_set(elfcpp::SHF_TLS));
+         if ((*p)->is_address_valid())
+           relro_size += (*p)->data_size();
+         else
+           {
+             // FIXME: This could be faster.
+             (*p)->set_address_and_file_offset(addr + relro_size,
+                                               off + relro_size);
+             relro_size += (*p)->data_size();
+             (*p)->reset_address_and_file_offset();
+           }
+       }
+      relro_size += increase_relro;
+
+      uint64_t page_align = parameters->target().common_pagesize();
+
+      // Align to offset N such that (N + RELRO_SIZE) % PAGE_ALIGN == 0.
+      uint64_t desired_align = page_align - (relro_size % page_align);
+      if (desired_align < *poff % page_align)
+       *poff += page_align - *poff % page_align;
+      *poff += desired_align - *poff % page_align;
+      addr += *poff - orig_off;
+      orig_off = *poff;
+    }
+
   if (!reset && this->are_addresses_set_)
     {
       gold_assert(this->paddr_ == addr);
@@ -3115,15 +3708,10 @@ Output_segment::set_section_addresses(const Layout* layout, bool reset,
 
   bool in_tls = false;
 
-  bool in_relro = (parameters->options().relro()
-                  && this->is_first_section_relro());
-
-  off_t orig_off = *poff;
   this->offset_ = orig_off;
 
   addr = this->set_section_list_addresses(layout, reset, &this->output_data_,
-                                         addr, poff, pshndx, &in_tls,
-                                         &in_relro);
+                                         addr, poff, pshndx, &in_tls);
   this->filesz_ = *poff - orig_off;
 
   off_t off = *poff;
@@ -3131,7 +3719,7 @@ Output_segment::set_section_addresses(const Layout* layout, bool reset,
   uint64_t ret = this->set_section_list_addresses(layout, reset,
                                                   &this->output_bss_,
                                                  addr, poff, pshndx,
-                                                  &in_tls, &in_relro);
+                                                  &in_tls);
 
   // If the last section was a TLS section, align upward to the
   // alignment of the TLS segment, so that the overall size of the TLS
@@ -3142,14 +3730,6 @@ Output_segment::set_section_addresses(const Layout* layout, bool reset,
       *poff = align_address(*poff, segment_align);
     }
 
-  // If all the sections were relro sections, align upward to the
-  // common page size.
-  if (in_relro)
-    {
-      uint64_t page_align = parameters->target().common_pagesize();
-      *poff = align_address(*poff, page_align);
-    }
-
   this->memsz_ = *poff - orig_off;
 
   // Ignore the file offset adjustments made by the BSS Output_data
@@ -3167,7 +3747,7 @@ Output_segment::set_section_list_addresses(const Layout* layout, bool reset,
                                            Output_data_list* pdl,
                                           uint64_t addr, off_t* poff,
                                           unsigned int* pshndx,
-                                           bool* in_tls, bool* in_relro)
+                                           bool* in_tls)
 {
   off_t startoff = *poff;
 
@@ -3218,19 +3798,6 @@ Output_segment::set_section_list_addresses(const Layout* layout, bool reset,
                 }
             }
 
-         // If this is a non-relro section after a relro section,
-         // align it to a common page boundary so that the dynamic
-         // linker has a page to mark as read-only.
-         if (*in_relro
-             && (!(*p)->is_section()
-                 || !(*p)->output_section()->is_relro()))
-           {
-             uint64_t page_align = parameters->target().common_pagesize();
-             if (page_align > align)
-               align = page_align;
-             *in_relro = false;
-           }
-
          off = align_address(off, align);
          (*p)->set_address_and_file_offset(addr + (off - startoff), off);
        }
@@ -3238,8 +3805,31 @@ Output_segment::set_section_list_addresses(const Layout* layout, bool reset,
        {
          // The script may have inserted a skip forward, but it
          // better not have moved backward.
-         gold_assert((*p)->address() >= addr + (off - startoff));
-         off += (*p)->address() - (addr + (off - startoff));
+         if ((*p)->address() >= addr + (off - startoff))
+           off += (*p)->address() - (addr + (off - startoff));
+         else
+           {
+             if (!layout->script_options()->saw_sections_clause())
+               gold_unreachable();
+             else
+               {
+                 Output_section* os = (*p)->output_section();
+
+                 // Cast to unsigned long long to avoid format warnings.
+                 unsigned long long previous_dot =
+                   static_cast<unsigned long long>(addr + (off - startoff));
+                 unsigned long long dot =
+                   static_cast<unsigned long long>((*p)->address());
+
+                 if (os == NULL)
+                   gold_error(_("dot moves backward in linker script "
+                                "from 0x%llx to 0x%llx"), previous_dot, dot);
+                 else
+                   gold_error(_("address of section '%s' moves backward "
+                                "from 0x%llx to 0x%llx"),
+                              os->name(), previous_dot, dot);
+               }
+           }
          (*p)->set_file_offset(off);
          (*p)->finalize_data_size();
        }
@@ -3263,10 +3853,10 @@ Output_segment::set_section_list_addresses(const Layout* layout, bool reset,
 }
 
 // For a non-PT_LOAD segment, set the offset from the sections, if
-// any.
+// any.  Add INCREASE to the file size and the memory size.
 
 void
-Output_segment::set_offset()
+Output_segment::set_offset(unsigned int increase)
 {
   gold_assert(this->type_ != elfcpp::PT_LOAD);
 
@@ -3274,6 +3864,7 @@ Output_segment::set_offset()
 
   if (this->output_data_.empty() && this->output_bss_.empty())
     {
+      gold_assert(increase == 0);
       this->vaddr_ = 0;
       this->paddr_ = 0;
       this->are_addresses_set_ = true;
@@ -3315,6 +3906,9 @@ Output_segment::set_offset()
                  + last->data_size()
                  - this->vaddr_);
 
+  this->filesz_ += increase;
+  this->memsz_ += increase;
+
   // If this is a TLS segment, align the memory size.  The code in
   // set_section_list ensures that the section after the TLS segment
   // is aligned to give us room.
@@ -3324,16 +3918,6 @@ Output_segment::set_offset()
       gold_assert(this->vaddr_ == align_address(this->vaddr_, segment_align));
       this->memsz_ = align_address(this->memsz_, segment_align);
     }
-
-  // If this is a RELRO segment, align the memory size.  The code in
-  // set_section_list ensures that the section after the RELRO segment
-  // is aligned to give us room.
-  if (this->type_ == elfcpp::PT_GNU_RELRO)
-    {
-      uint64_t page_align = parameters->target().common_pagesize();
-      gold_assert(this->vaddr_ == align_address(this->vaddr_, page_align));
-      this->memsz_ = align_address(this->memsz_, page_align);
-    }
 }
 
 // Set the TLS offsets of the sections in the PT_TLS segment.