Add -Wshadow to the gcc command line options used when compiling the binutils.
[deliverable/binutils-gdb.git] / gold / output.h
index 1c95881739f3eab76805b8db7d20ec1b8728a94b..21d80fb6aa5be69f0382e97c47ecc20f0e5ec165 100644 (file)
@@ -1,6 +1,6 @@
 // output.h -- manage the output file for gold   -*- C++ -*-
 
-// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -38,6 +38,7 @@ class General_options;
 class Object;
 class Symbol;
 class Output_file;
+class Output_merge_base;
 class Output_section;
 class Relocatable_relocs;
 class Target;
@@ -46,6 +47,62 @@ class Sized_target;
 template<int size, bool big_endian>
 class Sized_relobj;
 
+// This class specifies an input section.  It is used as a key type
+// for maps.
+
+class Input_section_specifier
+{
+ public:
+  Input_section_specifier(const Relobj* robj, unsigned int sec_shndx)
+    : relobj_(robj), shndx_(sec_shndx)
+  { }
+   
+  // Return Relobj of this.
+  const Relobj*
+  relobj() const
+  { return this->relobj_; }
+
+  // Return section index of this.
+  unsigned int
+  shndx() const
+  { return this->shndx_; }
+
+  // Whether this equals to another specifier ISS.
+  bool
+  eq(const Input_section_specifier& iss) const
+  { return this->relobj_ == iss.relobj_ && this->shndx_ == iss.shndx_; }
+
+  // Compute a hash value of this.
+  size_t
+  hash_value() const
+  {
+     return (gold::string_hash<char>(this->relobj_->name().c_str())
+            ^ this->shndx_);
+   }
+
+  // Functors for containers.
+  struct equal_to
+  {
+    bool
+    operator()(const Input_section_specifier& iss1,
+              const Input_section_specifier& iss2) const
+    { return iss1.eq(iss2); }
+  };
+  struct hash
+  {
+    size_t
+    operator()(const Input_section_specifier& iss) const
+    { return iss.hash_value(); }
+  };
+
+ private:
+  // An object.
+  const Relobj* relobj_;
+  // A section index. 
+  unsigned int shndx_;
+};
+
 // An abtract class for data which has to go into the output file.
 
 class Output_data
@@ -54,7 +111,7 @@ class Output_data
   explicit Output_data()
     : address_(0), data_size_(0), offset_(-1),
       is_address_valid_(false), is_data_size_valid_(false),
-      is_offset_valid_(false),
+      is_offset_valid_(false), is_data_size_fixed_(false),
       dynamic_reloc_count_(0)
   { }
 
@@ -80,6 +137,11 @@ class Output_data
     return this->data_size_;
   }
 
+  // Return true if data size is fixed.
+  bool
+  is_data_size_fixed() const
+  { return this->is_data_size_fixed_; }
+  
   // Return the file offset.  This is only valid after
   // Layout::finalize is finished.  For some non-allocated sections,
   // it may not be valid until near the end of the link.
@@ -97,10 +159,17 @@ class Output_data
   {
     this->is_address_valid_ = false;
     this->is_offset_valid_ = false;
-    this->is_data_size_valid_ = false;
+    if (!this->is_data_size_fixed_)
+      this->is_data_size_valid_ = false;
     this->do_reset_address_and_file_offset();
   }
 
+  // Return true if address and file offset already have reset values. In
+  // other words, calling reset_address_and_file_offset will not change them.
+  bool
+  address_and_file_offset_have_reset_values() const
+  { return this->do_address_and_file_offset_have_reset_values(); }
+
   // Return the required alignment.
   uint64_t
   addralign() const
@@ -311,6 +380,14 @@ class Output_data
   do_reset_address_and_file_offset()
   { }
 
+  // Return true if address and file offset already have reset values. In
+  // other words, calling reset_address_and_file_offset will not change them.
+  // A child class overriding do_reset_address_and_file_offset may need to
+  // also override this.
+  virtual bool
+  do_address_and_file_offset_have_reset_values() const
+  { return !this->is_address_valid_ && !this->is_offset_valid_; }
+
   // Set the TLS offset.  Called only for SHT_TLS sections.
   virtual void
   do_set_tls_offset(uint64_t)
@@ -330,15 +407,32 @@ class Output_data
 
   // Functions that child classes may call.
 
+  // Reset the address.  The Output_section class needs this when an
+  // SHF_ALLOC input section is added to an output section which was
+  // formerly not SHF_ALLOC.
+  void
+  mark_address_invalid()
+  { this->is_address_valid_ = false; }
+
   // Set the size of the data.
   void
-  set_data_size(off_t data_size)
+  set_data_size(off_t datasize)
   {
-    gold_assert(!this->is_data_size_valid_);
-    this->data_size_ = data_size;
+    gold_assert(!this->is_data_size_valid_
+               && !this->is_data_size_fixed_);
+    this->data_size_ = datasize;
     this->is_data_size_valid_ = true;
   }
 
+  // Fix the data size.  Once it is fixed, it cannot be changed
+  // and the data size remains always valid. 
+  void
+  fix_data_size()
+  {
+    gold_assert(this->is_data_size_valid_);
+    this->is_data_size_fixed_ = true;
+  }
+
   // Get the current data size--this is for the convenience of
   // sections which build up their size over time.
   off_t
@@ -348,10 +442,10 @@ class Output_data
   // Set the current data size--this is for the convenience of
   // sections which build up their size over time.
   void
-  set_current_data_size_for_child(off_t data_size)
+  set_current_data_size_for_child(off_t datasize)
   {
     gold_assert(!this->is_data_size_valid_);
-    this->data_size_ = data_size;
+    this->data_size_ = datasize;
   }
 
   // Return default alignment for the target size.
@@ -383,6 +477,8 @@ class Output_data
   bool is_data_size_valid_;
   // Whether offset_ is valid.
   bool is_offset_valid_;
+  // Whether data size is fixed.
+  bool is_data_size_fixed_;
   // Count of dynamic relocations applied to this section.
   unsigned int dynamic_reloc_count_;
 };
@@ -414,12 +510,21 @@ class Output_section_headers : public Output_data
   do_print_to_mapfile(Mapfile* mapfile) const
   { mapfile->print_output_data(this, _("** section headers")); }
 
+  // Set final data size.
+  void
+  set_final_data_size()
+  { this->set_data_size(this->do_size()); }
+
  private:
   // Write the data to the file with the right size and endianness.
   template<int size, bool big_endian>
   void
   do_sized_write(Output_file*);
 
+  // Compute data size.
+  off_t
+  do_size() const;
+
   const Layout* layout_;
   const Layout::Segment_list* segment_list_;
   const Layout::Section_list* section_list_;
@@ -450,12 +555,21 @@ class Output_segment_headers : public Output_data
   do_print_to_mapfile(Mapfile* mapfile) const
   { mapfile->print_output_data(this, _("** segment headers")); }
 
+  // Set final data size.
+  void
+  set_final_data_size()
+  { this->set_data_size(this->do_size()); }
+
  private:
   // Write the data to the file with the right size and endianness.
   template<int size, bool big_endian>
   void
   do_sized_write(Output_file*);
 
+  // Compute the current size.
+  off_t
+  do_size() const;
+
   const Layout::Segment_list& segment_list_;
 };
 
@@ -489,6 +603,11 @@ class Output_file_header : public Output_data
   do_print_to_mapfile(Mapfile* mapfile) const
   { mapfile->print_output_data(this, _("** file header")); }
 
+  // Set final data size.
+  void
+  set_final_data_size(void)
+  { this->set_data_size(this->do_size()); }
+
  private:
   // Write the data to the file with the right size and endianness.
   template<int size, bool big_endian>
@@ -500,6 +619,10 @@ class Output_file_header : public Output_data
   typename elfcpp::Elf_types<size>::Elf_Addr
   entry();
 
+  // Compute the current data size.
+  off_t
+  do_size() const;
+
   const Target* target_;
   const Symbol_table* symtab_;
   const Output_segment_headers* segment_header_;
@@ -516,12 +639,17 @@ class Output_file_header : public Output_data
 class Output_section_data : public Output_data
 {
  public:
-  Output_section_data(off_t data_size, uint64_t addralign)
-    : Output_data(), output_section_(NULL), addralign_(addralign)
-  { this->set_data_size(data_size); }
+  Output_section_data(off_t datasize, uint64_t addr_align,
+                     bool is_datasize_fixed)
+    : Output_data(), output_section_(NULL), addralign_(addr_align)
+  {
+    this->set_data_size(datasize);
+    if (is_datasize_fixed)
+      this->fix_data_size();
+  }
 
-  Output_section_data(uint64_t addralign)
-    : Output_data(), output_section_(NULL), addralign_(addralign)
+  Output_section_data(uint64_t addr_align)
+    : Output_data(), output_section_(NULL), addralign_(addr_align)
   { }
 
   // Return the output section.
@@ -547,9 +675,9 @@ class Output_section_data : public Output_data
   // this input offset is being discarded.
   bool
   output_offset(const Relobj* object, unsigned int shndx,
-               section_offset_type offset,
+               section_offset_type sec_offset,
                section_offset_type *poutput) const
-  { return this->do_output_offset(object, shndx, offset, poutput); }
+  { return this->do_output_offset(object, shndx, sec_offset, poutput); }
 
   // Return whether this is the merge section for the input section
   // SHNDX in OBJECT.  This should return true when output_offset
@@ -640,8 +768,8 @@ class Output_section_data : public Output_data
 class Output_section_data_build : public Output_section_data
 {
  public:
-  Output_section_data_build(uint64_t addralign)
-    : Output_section_data(addralign)
+  Output_section_data_build(uint64_t addr_align)
+    : Output_section_data(addr_align)
   { }
 
   // Get the current data size.
@@ -651,8 +779,8 @@ class Output_section_data_build : public Output_section_data
 
   // Set the current data size.
   void
-  set_current_data_size(off_t data_size)
-  { this->set_current_data_size_for_child(data_size); }
+  set_current_data_size(off_t datasize)
+  { this->set_current_data_size_for_child(datasize); }
 
  protected:
   // Set the final data size.
@@ -667,16 +795,16 @@ class Output_section_data_build : public Output_section_data
 class Output_data_const : public Output_section_data
 {
  public:
-  Output_data_const(const std::string& data, uint64_t addralign)
-    : Output_section_data(data.size(), addralign), data_(data)
+  Output_data_const(const std::string& data, uint64_t addr_align)
+    : Output_section_data(data.size(), addr_align, true), data_(data)
   { }
 
-  Output_data_const(const char* p, off_t len, uint64_t addralign)
-    : Output_section_data(len, addralign), data_(p, len)
+  Output_data_const(const char* p, off_t len, uint64_t addr_align)
+    : Output_section_data(len, addr_align, true), data_(p, len)
   { }
 
-  Output_data_const(const unsigned char* p, off_t len, uint64_t addralign)
-    : Output_section_data(len, addralign),
+  Output_data_const(const unsigned char* p, off_t len, uint64_t addr_align)
+    : Output_section_data(len, addr_align, true),
       data_(reinterpret_cast<const char*>(p), len)
   { }
 
@@ -706,8 +834,8 @@ class Output_data_const_buffer : public Output_section_data
 {
  public:
   Output_data_const_buffer(const unsigned char* p, off_t len,
-                          uint64_t addralign, const char* map_name)
-    : Output_section_data(len, addralign),
+                          uint64_t addr_align, const char* map_name)
+    : Output_section_data(len, addr_align, true),
       p_(p), map_name_(map_name)
   { }
 
@@ -740,9 +868,9 @@ class Output_data_const_buffer : public Output_section_data
 class Output_data_fixed_space : public Output_section_data
 {
  public:
-  Output_data_fixed_space(off_t data_size, uint64_t addralign,
+  Output_data_fixed_space(off_t datasize, uint64_t addr_align,
                          const char* map_name)
-    : Output_section_data(data_size, addralign),
+    : Output_section_data(datasize, addr_align, true),
       map_name_(map_name)
   { }
 
@@ -770,8 +898,8 @@ class Output_data_fixed_space : public Output_section_data
 class Output_data_space : public Output_section_data_build
 {
  public:
-  explicit Output_data_space(uint64_t addralign, const char* map_name)
-    : Output_section_data_build(addralign),
+  explicit Output_data_space(uint64_t addr_align, const char* map_name)
+    : Output_section_data_build(addr_align),
       map_name_(map_name)
   { }
 
@@ -804,8 +932,8 @@ class Output_data_space : public Output_section_data_build
 class Output_data_zero_fill : public Output_section_data
 {
  public:
-  Output_data_zero_fill(off_t data_size, uint64_t addralign)
-    : Output_section_data(data_size, addralign)
+  Output_data_zero_fill(off_t datasize, uint64_t addr_align)
+    : Output_section_data(datasize, addr_align, true)
   { }
 
  protected:
@@ -874,6 +1002,8 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
   typedef typename elfcpp::Elf_types<size>::Elf_Addr Addend;
 
+  static const Address invalid_address = static_cast<Address>(0) - 1;
+
   // An uninitialized entry.  We need this because we want to put
   // instances of this class into an STL container.
   Output_reloc()
@@ -1051,33 +1181,33 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   // A reloc against a global symbol.
 
   Output_reloc(Symbol* gsym, unsigned int type, Output_data* od,
-              Address address, Addend addend, bool is_relative)
-    : rel_(gsym, type, od, address, is_relative), addend_(addend)
+              Address addr, Addend addend, bool is_relative)
+    : rel_(gsym, type, od, addr, is_relative), addend_(addend)
   { }
 
   Output_reloc(Symbol* gsym, unsigned int type,
                Sized_relobj<size, big_endian>* relobj,
-              unsigned int shndx, Address address, Addend addend,
+              unsigned int shndx, Address addr, Addend addend,
               bool is_relative)
-    : rel_(gsym, type, relobj, shndx, address, is_relative), addend_(addend)
+    : rel_(gsym, type, relobj, shndx, addr, is_relative), addend_(addend)
   { }
 
   // A reloc against a local symbol.
 
   Output_reloc(Sized_relobj<size, big_endian>* relobj,
               unsigned int local_sym_index, unsigned int type,
-              Output_data* od, Address address,
+              Output_data* od, Address addr,
               Addend addend, bool is_relative, bool is_section_symbol)
-    : rel_(relobj, local_sym_index, type, od, address, is_relative,
+    : rel_(relobj, local_sym_index, type, od, addr, is_relative,
            is_section_symbol),
       addend_(addend)
   { }
 
   Output_reloc(Sized_relobj<size, big_endian>* relobj,
               unsigned int local_sym_index, unsigned int type,
-              unsigned int shndx, Address address,
+              unsigned int shndx, Address addr,
               Addend addend, bool is_relative, bool is_section_symbol)
-    : rel_(relobj, local_sym_index, type, shndx, address, is_relative,
+    : rel_(relobj, local_sym_index, type, shndx, addr, is_relative,
            is_section_symbol),
       addend_(addend)
   { }
@@ -1085,14 +1215,14 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   // A reloc against the STT_SECTION symbol of an output section.
 
   Output_reloc(Output_section* os, unsigned int type, Output_data* od,
-              Address address, Addend addend)
-    : rel_(os, type, od, address), addend_(addend)
+              Address addr, Addend addend)
+    : rel_(os, type, od, addr), addend_(addend)
   { }
 
   Output_reloc(Output_section* os, unsigned int type,
                Sized_relobj<size, big_endian>* relobj,
-              unsigned int shndx, Address address, Addend addend)
-    : rel_(os, type, relobj, shndx, address), addend_(addend)
+              unsigned int shndx, Address addr, Addend addend)
+    : rel_(os, type, relobj, shndx, addr), addend_(addend)
   { }
 
   // Write the reloc entry to an output view.
@@ -1215,33 +1345,33 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   // Add a reloc against a global symbol.
 
   void
-  add_global(Symbol* gsym, unsigned int type, Output_data* od, Address address)
-  { this->add(od, Output_reloc_type(gsym, type, od, address, false)); }
+  add_global(Symbol* gsym, unsigned int type, Output_data* od, Address addr)
+  { this->add(od, Output_reloc_type(gsym, type, od, addr, false)); }
 
   void
   add_global(Symbol* gsym, unsigned int type, Output_data* od,
              Sized_relobj<size, big_endian>* relobj,
-            unsigned int shndx, Address address)
-  { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
+            unsigned int shndx, Address addr)
+  { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, addr,
                                     false)); }
 
   // These are to simplify the Copy_relocs class.
 
   void
-  add_global(Symbol* gsym, unsigned int type, Output_data* od, Address address,
+  add_global(Symbol* gsym, unsigned int type, Output_data* od, Address addr,
             Address addend)
   {
     gold_assert(addend == 0);
-    this->add_global(gsym, type, od, address);
+    this->add_global(gsym, type, od, addr);
   }
 
   void
   add_global(Symbol* gsym, unsigned int type, Output_data* od,
              Sized_relobj<size, big_endian>* relobj,
-            unsigned int shndx, Address address, Address addend)
+            unsigned int shndx, Address addr, Address addend)
   {
     gold_assert(addend == 0);
-    this->add_global(gsym, type, od, relobj, shndx, address);
+    this->add_global(gsym, type, od, relobj, shndx, addr);
   }
 
   // Add a RELATIVE reloc against a global symbol.  The final relocation
@@ -1249,15 +1379,15 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
 
   void
   add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
-                      Address address)
-  { this->add(od, Output_reloc_type(gsym, type, od, address, true)); }
+                      Address addr)
+  { this->add(od, Output_reloc_type(gsym, type, od, addr, true)); }
 
   void
   add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
                       Sized_relobj<size, big_endian>* relobj,
-                      unsigned int shndx, Address address)
+                      unsigned int shndx, Address addr)
   {
-    this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
+    this->add(od, Output_reloc_type(gsym, type, relobj, shndx, addr,
                                     true));
   }
 
@@ -1266,19 +1396,19 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   void
   add_local(Sized_relobj<size, big_endian>* relobj,
            unsigned int local_sym_index, unsigned int type,
-           Output_data* od, Address address)
+           Output_data* od, Address addr)
   {
     this->add(od, Output_reloc_type(relobj, local_sym_index, type, od,
-                                    address, false, false));
+                                    addr, false, false));
   }
 
   void
   add_local(Sized_relobj<size, big_endian>* relobj,
            unsigned int local_sym_index, unsigned int type,
-           Output_data* od, unsigned int shndx, Address address)
+           Output_data* od, unsigned int shndx, Address addr)
   {
     this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
-                                   address, false, false));
+                                   addr, false, false));
   }
 
   // Add a RELATIVE reloc against a local symbol.
@@ -1286,19 +1416,19 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   void
   add_local_relative(Sized_relobj<size, big_endian>* relobj,
                     unsigned int local_sym_index, unsigned int type,
-                    Output_data* od, Address address)
+                    Output_data* od, Address addr)
   {
     this->add(od, Output_reloc_type(relobj, local_sym_index, type, od,
-                                    address, true, false));
+                                    addr, true, false));
   }
 
   void
   add_local_relative(Sized_relobj<size, big_endian>* relobj,
                     unsigned int local_sym_index, unsigned int type,
-                    Output_data* od, unsigned int shndx, Address address)
+                    Output_data* od, unsigned int shndx, Address addr)
   {
     this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
-                                   address, true, false));
+                                   addr, true, false));
   }
 
   // Add a reloc against a local section symbol.  This will be
@@ -1308,19 +1438,19 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   void
   add_local_section(Sized_relobj<size, big_endian>* relobj,
                     unsigned int input_shndx, unsigned int type,
-                    Output_data* od, Address address)
+                    Output_data* od, Address addr)
   {
     this->add(od, Output_reloc_type(relobj, input_shndx, type, od,
-                                    address, false, true));
+                                    addr, false, true));
   }
 
   void
   add_local_section(Sized_relobj<size, big_endian>* relobj,
                     unsigned int input_shndx, unsigned int type,
-                    Output_data* od, unsigned int shndx, Address address)
+                    Output_data* od, unsigned int shndx, Address addr)
   {
     this->add(od, Output_reloc_type(relobj, input_shndx, type, shndx,
-                                    address, false, true));
+                                    addr, false, true));
   }
 
   // A reloc against the STT_SECTION symbol of an output section.
@@ -1329,14 +1459,14 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
 
   void
   add_output_section(Output_section* os, unsigned int type,
-                    Output_data* od, Address address)
-  { this->add(od, Output_reloc_type(os, type, od, address)); }
+                    Output_data* od, Address addr)
+  { this->add(od, Output_reloc_type(os, type, od, addr)); }
 
   void
   add_output_section(Output_section* os, unsigned int type, Output_data* od,
                     Sized_relobj<size, big_endian>* relobj,
-                     unsigned int shndx, Address address)
-  { this->add(od, Output_reloc_type(os, type, relobj, shndx, address)); }
+                     unsigned int shndx, Address addr)
+  { this->add(od, Output_reloc_type(os, type, relobj, shndx, addr)); }
 };
 
 // The SHT_RELA version of Output_data_reloc.
@@ -1362,16 +1492,16 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
 
   void
   add_global(Symbol* gsym, unsigned int type, Output_data* od,
-            Address address, Addend addend)
-  { this->add(od, Output_reloc_type(gsym, type, od, address, addend,
+            Address addr, Addend addend)
+  { this->add(od, Output_reloc_type(gsym, type, od, addr, addend,
                                     false)); }
 
   void
   add_global(Symbol* gsym, unsigned int type, Output_data* od,
              Sized_relobj<size, big_endian>* relobj,
-            unsigned int shndx, Address address,
+            unsigned int shndx, Address addr,
             Addend addend)
-  { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
+  { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, addr,
                                     addend, false)); }
 
   // Add a RELATIVE reloc against a global symbol.  The final output
@@ -1381,14 +1511,14 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
 
   void
   add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
-                     Address address, Addend addend)
-  { this->add(od, Output_reloc_type(gsym, type, od, address, addend, true)); }
+                     Address addr, Addend addend)
+  { this->add(od, Output_reloc_type(gsym, type, od, addr, addend, true)); }
 
   void
   add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
                       Sized_relobj<size, big_endian>* relobj,
-                      unsigned int shndx, Address address, Addend addend)
-  { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
+                      unsigned int shndx, Address addr, Addend addend)
+  { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, addr,
                                     addend, true)); }
 
   // Add a reloc against a local symbol.
@@ -1396,20 +1526,20 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   void
   add_local(Sized_relobj<size, big_endian>* relobj,
            unsigned int local_sym_index, unsigned int type,
-           Output_data* od, Address address, Addend addend)
+           Output_data* od, Address addr, Addend addend)
   {
-    this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, address,
+    this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, addr,
                                    addend, false, false));
   }
 
   void
   add_local(Sized_relobj<size, big_endian>* relobj,
            unsigned int local_sym_index, unsigned int type,
-           Output_data* od, unsigned int shndx, Address address,
+           Output_data* od, unsigned int shndx, Address addr,
            Addend addend)
   {
     this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
-                                    address, addend, false, false));
+                                    addr, addend, false, false));
   }
 
   // Add a RELATIVE reloc against a local symbol.
@@ -1417,20 +1547,20 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   void
   add_local_relative(Sized_relobj<size, big_endian>* relobj,
                     unsigned int local_sym_index, unsigned int type,
-                    Output_data* od, Address address, Addend addend)
+                    Output_data* od, Address addr, Addend addend)
   {
-    this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, address,
+    this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, addr,
                                    addend, true, false));
   }
 
   void
   add_local_relative(Sized_relobj<size, big_endian>* relobj,
                     unsigned int local_sym_index, unsigned int type,
-                    Output_data* od, unsigned int shndx, Address address,
+                    Output_data* od, unsigned int shndx, Address addr,
                     Addend addend)
   {
     this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
-                                    address, addend, true, false));
+                                    addr, addend, true, false));
   }
 
   // Add a reloc against a local section symbol.  This will be
@@ -1440,34 +1570,34 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   void
   add_local_section(Sized_relobj<size, big_endian>* relobj,
                     unsigned int input_shndx, unsigned int type,
-                    Output_data* od, Address address, Addend addend)
+                    Output_data* od, Address addr, Addend addend)
   {
-    this->add(od, Output_reloc_type(relobj, input_shndx, type, od, address,
+    this->add(od, Output_reloc_type(relobj, input_shndx, type, od, addr,
                                    addend, false, true));
   }
 
   void
   add_local_section(Sized_relobj<size, big_endian>* relobj,
                     unsigned int input_shndx, unsigned int type,
-                    Output_data* od, unsigned int shndx, Address address,
+                    Output_data* od, unsigned int shndx, Address addr,
                     Addend addend)
   {
     this->add(od, Output_reloc_type(relobj, input_shndx, type, shndx,
-                                    address, addend, false, true));
+                                    addr, addend, false, true));
   }
 
   // A reloc against the STT_SECTION symbol of an output section.
 
   void
   add_output_section(Output_section* os, unsigned int type, Output_data* od,
-                    Address address, Addend addend)
-  { this->add(os, Output_reloc_type(os, type, od, address, addend)); }
+                    Address addr, Addend addend)
+  { this->add(os, Output_reloc_type(os, type, od, addr, addend)); }
 
   void
   add_output_section(Output_section* os, unsigned int type,
                      Sized_relobj<size, big_endian>* relobj,
-                    unsigned int shndx, Address address, Addend addend)
-  { this->add(os, Output_reloc_type(os, type, relobj, shndx, address,
+                    unsigned int shndx, Address addr, Addend addend)
+  { this->add(os, Output_reloc_type(os, type, relobj, shndx, addr,
                                     addend)); }
 };
 
@@ -1522,6 +1652,11 @@ class Output_data_group : public Output_section_data
   do_print_to_mapfile(Mapfile* mapfile) const
   { mapfile->print_output_data(this, _("** group")); }
 
+  // Set final data size.
+  void
+  set_final_data_size()
+  { this->set_data_size((this->input_shndxes_.size() + 1) * 4); }
+
  private:
   // The input object.
   Sized_relobj<size, big_endian>* relobj_;
@@ -1731,8 +1866,8 @@ class Output_data_dynamic : public Output_section_data
   // plus a constant offset.
   void
   add_section_plus_offset(elfcpp::DT tag, const Output_data* od,
-                          unsigned int offset)
-  { this->add_entry(Dynamic_entry(tag, od, offset)); }
+                          unsigned int sec_offset)
+  { this->add_entry(Dynamic_entry(tag, od, sec_offset)); }
 
   // Add a new dynamic entry with the size of output data.
   void
@@ -1777,34 +1912,39 @@ class Output_data_dynamic : public Output_section_data
   {
    public:
     // Create an entry with a fixed numeric value.
-    Dynamic_entry(elfcpp::DT tag, unsigned int val)
-      : tag_(tag), offset_(DYNAMIC_NUMBER)
+    Dynamic_entry(elfcpp::DT etag, unsigned int val)
+      : tag_(etag), offset_(DYNAMIC_NUMBER)
     { this->u_.val = val; }
 
     // Create an entry with the size or address of a section.
-    Dynamic_entry(elfcpp::DT tag, const Output_data* od, bool section_size)
-      : tag_(tag),
+    Dynamic_entry(elfcpp::DT etag, const Output_data* od, bool section_size)
+      : tag_(etag),
        offset_(section_size
                ? DYNAMIC_SECTION_SIZE
                : DYNAMIC_SECTION_ADDRESS)
     { this->u_.od = od; }
 
     // Create an entry with the address of a section plus a constant offset.
-    Dynamic_entry(elfcpp::DT tag, const Output_data* od, unsigned int offset)
-      : tag_(tag),
+    Dynamic_entry(elfcpp::DT etag, const Output_data* od, unsigned int offset)
+      : tag_(etag),
        offset_(offset)
     { this->u_.od = od; }
 
     // Create an entry with the address of a symbol.
-    Dynamic_entry(elfcpp::DT tag, const Symbol* sym)
-      : tag_(tag), offset_(DYNAMIC_SYMBOL)
+    Dynamic_entry(elfcpp::DT etag, const Symbol* sym)
+      : tag_(etag), offset_(DYNAMIC_SYMBOL)
     { this->u_.sym = sym; }
 
     // Create an entry with a string.
-    Dynamic_entry(elfcpp::DT tag, const char* str)
-      : tag_(tag), offset_(DYNAMIC_STRING)
+    Dynamic_entry(elfcpp::DT etag, const char* str)
+      : tag_(etag), offset_(DYNAMIC_STRING)
     { this->u_.str = str; }
 
+    // Return the tag of this entry.
+    elfcpp::DT
+    tag() const
+    { return this->tag_; }
+
     // Write the dynamic entry to an output view.
     template<int size, bool big_endian>
     void
@@ -1871,7 +2011,7 @@ class Output_symtab_xindex : public Output_section_data
 {
  public:
   Output_symtab_xindex(size_t symcount)
-    : Output_section_data(symcount * 4, 4),
+    : Output_section_data(symcount * 4, 4, true),
       entries_()
   { }
 
@@ -1903,6 +2043,33 @@ class Output_symtab_xindex : public Output_section_data
   Xindex_entries entries_;
 };
 
+// A relaxed input section.
+class Output_relaxed_input_section : public Output_section_data_build
+{
+ public:
+  // We would like to call relobj->section_addralign(shndx) to get the
+  // alignment but we do not want the constructor to fail.  So callers
+  // are repsonsible for ensuring that.
+  Output_relaxed_input_section(Relobj* rel_obj, unsigned int sec_shndx,
+                              uint64_t addr_align)
+    : Output_section_data_build(addr_align), relobj_(rel_obj), shndx_(sec_shndx)
+  { }
+  // Return the Relobj of this relaxed input section.
+  Relobj*
+  relobj() const
+  { return this->relobj_; }
+  // Return the section index of this relaxed input section.
+  unsigned int
+  shndx() const
+  { return this->shndx_; }
+
+ private:
+  Relobj* relobj_;
+  unsigned int shndx_;
+};
+
 // An output section.  We don't expect to have too many output
 // sections, so we don't bother to do a template on the size.
 
@@ -1915,7 +2082,7 @@ class Output_section : public Output_data
 
   // Add a new input section SHNDX, named NAME, with header SHDR, from
   // object OBJECT.  RELOC_SHNDX is the index of a relocation section
-  // which applies to this section, or 0 if none, or -1U if more than
+  // which applies to this section, or 0 if none, or -1 if more than
   // one.  HAVE_SECTIONS_SCRIPT is true if we have a SECTIONS clause
   // in a linker script; in that case we need to keep track of input
   // sections associated with an output section.  Return the offset
@@ -1931,6 +2098,10 @@ class Output_section : public Output_data
   void
   add_output_section_data(Output_section_data* posd);
 
+  // Add a relaxed input section PORIS to this output section.
+  void
+  add_relaxed_input_section(Output_relaxed_input_section* poris);
+
   // Return the section name.
   const char*
   name() const
@@ -1946,22 +2117,9 @@ class Output_section : public Output_data
   flags() const
   { return this->flags_; }
 
-  // Set the section flags.  This may only be used with the Layout
-  // code when it is prepared to move the section to a different
-  // segment.
-  void
-  set_flags(elfcpp::Elf_Xword flags)
-  { this->flags_ = flags; }
-
   // Update the output section flags based on input section flags.
   void
-  update_flags_for_input_section(elfcpp::Elf_Xword flags)
-  {
-    this->flags_ |= (flags
-                    & (elfcpp::SHF_WRITE
-                       | elfcpp::SHF_ALLOC
-                       | elfcpp::SHF_EXECINSTR));
-  }
+  update_flags_for_input_section(elfcpp::Elf_Xword flags);
 
   // Return the entsize field.
   uint64_t
@@ -1974,9 +2132,9 @@ class Output_section : public Output_data
 
   // Set the load address.
   void
-  set_load_address(uint64_t load_address)
+  set_load_address(uint64_t load_addr)
   {
-    this->load_address_ = load_address;
+    this->load_address_ = load_addr;
     this->has_load_address_ = true;
   }
 
@@ -2193,6 +2351,54 @@ class Output_section : public Output_data
   set_is_relro_local()
   { this->is_relro_local_ = true; }
 
+  // True if this is a small section: a section which holds small
+  // variables.
+  bool
+  is_small_section() const
+  { return this->is_small_section_; }
+
+  // Record that this is a small section.
+  void
+  set_is_small_section()
+  { this->is_small_section_ = true; }
+
+  // True if this is a large section: a section which holds large
+  // variables.
+  bool
+  is_large_section() const
+  { return this->is_large_section_; }
+
+  // Record that this is a large section.
+  void
+  set_is_large_section()
+  { this->is_large_section_ = true; }
+
+  // True if this is a large data (not BSS) section.
+  bool
+  is_large_data_section()
+  { return this->is_large_section_ && this->type_ != elfcpp::SHT_NOBITS; }
+
+  // True if this is the .interp section which goes into the PT_INTERP
+  // segment.
+  bool
+  is_interp() const
+  { return this->is_interp_; }
+
+  // Record that this is the interp section.
+  void
+  set_is_interp()
+  { this->is_interp_ = true; }
+
+  // True if this is a section used by the dynamic linker.
+  bool
+  is_dynamic_linker_section() const
+  { return this->is_dynamic_linker_section_; }
+
+  // Record that this is a section used by the dynamic linker.
+  void
+  set_is_dynamic_linker_section()
+  { this->is_dynamic_linker_section_ = true; }
+
   // Return whether this section should be written after all the input
   // sections are complete.
   bool
@@ -2258,12 +2464,14 @@ class Output_section : public Output_data
   output_address(const Relobj* object, unsigned int shndx,
                 off_t offset) const;
 
-  // Return the output address of the start of the merged section for
-  // input section SHNDX in object OBJECT.  This is not necessarily
-  // the offset corresponding to input offset 0 in the section, since
-  // the section may be mapped arbitrarily.
-  uint64_t
-  starting_output_address(const Relobj* object, unsigned int shndx) const;
+  // Look for the merged section for input section SHNDX in object
+  // OBJECT.  If found, return true, and set *ADDR to the address of
+  // the start of the merged section.  This is not necessary the
+  // output offset corresponding to input offset 0 in the section,
+  // since the section may be mapped arbitrarily.
+  bool
+  find_starting_output_address(const Relobj* object, unsigned int shndx,
+                              uint64_t* addr) const;
 
   // Record that this output section was found in the SECTIONS clause
   // of a linker script.
@@ -2285,6 +2493,69 @@ class Output_section : public Output_data
 
   // The next few calls are for linker script support.
 
+  // We need to export the input sections to linker scripts.  Previously
+  // we export a pair of Relobj pointer and section index.  We now need to
+  // handle relaxed input sections as well.  So we use this class.
+  class Simple_input_section
+  {
+   private:
+    static const unsigned int invalid_shndx = static_cast<unsigned int>(-1);
+
+   public:
+    Simple_input_section(Relobj *rel_obj, unsigned int sec_shndx)
+      : shndx_(sec_shndx)
+    {
+      gold_assert(sec_shndx != invalid_shndx);
+      this->u_.relobj = rel_obj;
+    }
+    Simple_input_section(Output_relaxed_input_section* section)
+      : shndx_(invalid_shndx)
+    { this->u_.relaxed_input_section = section; }
+
+    // Whether this is a relaxed section.
+    bool
+    is_relaxed_input_section() const
+    { return this->shndx_ == invalid_shndx; }
+
+    // Return object of an input section.
+    Relobj*
+    relobj() const
+    {
+      return ((this->shndx_ != invalid_shndx)
+             ? this->u_.relobj
+             : this->u_.relaxed_input_section->relobj());
+    }
+
+    // Return index of an input section.
+    unsigned int
+    shndx() const
+    {
+      return ((this->shndx_ != invalid_shndx)
+             ? this->shndx_
+             : this->u_.relaxed_input_section->shndx());
+    }
+
+    // Return the Output_relaxed_input_section object of a relaxed section.
+    Output_relaxed_input_section*
+    relaxed_input_section() const
+    {
+      gold_assert(this->shndx_ == invalid_shndx);
+      return this->u_.relaxed_input_section;
+    }
+
+   private:
+    // Pointer to either an Relobj or an Output_relaxed_input_section.
+    union
+    {
+      Relobj* relobj;
+      Output_relaxed_input_section* relaxed_input_section;
+    } u_;
+    // Section index for an non-relaxed section or invalid_shndx for
+    // a relaxed section.
+    unsigned int shndx_;
+  };
   // Store the list of input sections for this Output_section into the
   // list passed in.  This removes the input sections, leaving only
   // any Output_section_data elements.  This returns the size of those
@@ -2293,11 +2564,11 @@ class Output_section : public Output_data
   // any spaces between the remaining Output_section_data elements.
   uint64_t
   get_input_sections(uint64_t address, const std::string& fill,
-                    std::list<std::pair<Relobj*, unsigned int > >*);
+                    std::list<Simple_input_section>*);
 
   // Add an input section from a script.
   void
-  add_input_section_for_script(Relobj* object, unsigned int shndx,
+  add_input_section_for_script(const Simple_input_section& input_section,
                               off_t data_size, uint64_t addralign);
 
   // Set the current size of the output section.
@@ -2312,6 +2583,25 @@ class Output_section : public Output_data
 
   // End of linker script support.
 
+  // Save states before doing section layout.
+  // This is used for relaxation.
+  void
+  save_states();
+
+  // Restore states prior to section layout.
+  void
+  restore_states();
+
+  // Convert existing input sections to relaxed input sections.
+  void
+  convert_input_sections_to_relaxed_sections(
+      const std::vector<Output_relaxed_input_section*>& sections);
+
+  // Find a relaxed input section to an input section in OBJECT
+  // with index SHNDX.  Return NULL if none is found.
+  const Output_section_data*
+  find_relaxed_input_section(const Relobj* object, unsigned int shndx) const;
+  
   // Print merge statistics to stderr.
   void
   print_merge_stats();
@@ -2349,6 +2639,11 @@ class Output_section : public Output_data
   void
   do_reset_address_and_file_offset();
 
+  // Return true if address and file offset already have reset values. In
+  // other words, calling reset_address_and_file_offset will not change them.
+  bool
+  do_address_and_file_offset_have_reset_values() const;
+
   // Write the data to the file.  For a typical Output_section, this
   // does nothing: the data is written out by calling Object::Relocate
   // on each input object.  But if there are any Output_section_data
@@ -2381,8 +2676,8 @@ class Output_section : public Output_data
 
   // Return whether this is a section of the specified type.
   bool
-  do_is_section_type(elfcpp::Elf_Word type) const
-  { return this->type_ == type; }
+  do_is_section_type(elfcpp::Elf_Word sec_type) const
+  { return this->type_ == sec_type; }
 
   // Return whether the specified section flag is set.
   bool
@@ -2422,7 +2717,6 @@ class Output_section : public Output_data
   void
   write_to_postprocessing_buffer();
 
- private:
   // In some cases we need to keep a list of the input sections
   // associated with this output section.  We only need the list if we
   // might have to change the offsets of the input section within the
@@ -2444,15 +2738,16 @@ class Output_section : public Output_data
     }
 
     // For an ordinary input section.
-    Input_section(Relobj* object, unsigned int shndx, off_t data_size,
-                 uint64_t addralign)
-      : shndx_(shndx),
-       p2align_(ffsll(static_cast<long long>(addralign)))
+    Input_section(Relobj* object, unsigned int sec_shndx, off_t datasize,
+                 uint64_t addr_align)
+      : shndx_(sec_shndx),
+       p2align_(ffsll(static_cast<long long>(addr_align)))
     {
-      gold_assert(shndx != OUTPUT_SECTION_CODE
-                 && shndx != MERGE_DATA_SECTION_CODE
-                 && shndx != MERGE_STRING_SECTION_CODE);
-      this->u1_.data_size = data_size;
+      gold_assert(sec_shndx != OUTPUT_SECTION_CODE
+                 && sec_shndx != MERGE_DATA_SECTION_CODE
+                 && sec_shndx != MERGE_STRING_SECTION_CODE
+                 && sec_shndx != RELAXED_INPUT_SECTION_CODE);
+      this->u1_.data_size = datasize;
       this->u2_.object = object;
     }
 
@@ -2475,6 +2770,14 @@ class Output_section : public Output_data
       this->u2_.posd = posd;
     }
 
+    // For a relaxed input section.
+    Input_section(Output_relaxed_input_section *psection)
+      : shndx_(RELAXED_INPUT_SECTION_CODE), p2align_(0)
+    {
+      this->u1_.data_size = 0;
+      this->u2_.poris = psection;
+    }
+
     // The required alignment.
     uint64_t
     addralign() const
@@ -2496,36 +2799,74 @@ class Output_section : public Output_data
     {
       return (this->shndx_ != OUTPUT_SECTION_CODE
              && this->shndx_ != MERGE_DATA_SECTION_CODE
-             && this->shndx_ != MERGE_STRING_SECTION_CODE);
+             && this->shndx_ != MERGE_STRING_SECTION_CODE
+             && this->shndx_ != RELAXED_INPUT_SECTION_CODE);
     }
 
     // Return whether this is a merge section which matches the
     // parameters.
     bool
     is_merge_section(bool is_string, uint64_t entsize,
-                     uint64_t addralign) const
+                     uint64_t addr_align) const
     {
       return (this->shndx_ == (is_string
                               ? MERGE_STRING_SECTION_CODE
                               : MERGE_DATA_SECTION_CODE)
              && this->u1_.entsize == entsize
-              && this->addralign() == addralign);
+              && this->addralign() == addr_align);
+    }
+
+    // Return whether this is a relaxed input section.
+    bool
+    is_relaxed_input_section() const
+    { return this->shndx_ == RELAXED_INPUT_SECTION_CODE; }
+
+    // Return whether this is a generic Output_section_data.
+    bool
+    is_output_section_data() const
+    {
+      return this->shndx_ == OUTPUT_SECTION_CODE;
     }
 
     // Return the object for an input section.
     Relobj*
     relobj() const
     {
-      gold_assert(this->is_input_section());
-      return this->u2_.object;
+      if (this->is_input_section())
+        return this->u2_.object;
+      else if (this->is_relaxed_input_section())
+       return this->u2_.poris->relobj();
+      else
+       gold_unreachable();
     }
 
     // Return the input section index for an input section.
     unsigned int
     shndx() const
     {
-      gold_assert(this->is_input_section());
-      return this->shndx_;
+      if (this->is_input_section())
+        return this->shndx_;
+      else if (this->is_relaxed_input_section())
+       return this->u2_.poris->shndx();
+      else
+       gold_unreachable();
+    }
+
+    // For non-input-sections, return the associated Output_section_data
+    // object.
+    Output_section_data*
+    output_section_data() const
+    {
+      gold_assert(!this->is_input_section());
+      return this->u2_.posd;
+    }
+    // Return the Output_relaxed_input_section object.
+    Output_relaxed_input_section*
+    relaxed_input_section() const
+    {
+      gold_assert(this->is_relaxed_input_section());
+      return this->u2_.poris;
     }
 
     // Set the output section.
@@ -2533,7 +2874,9 @@ class Output_section : public Output_data
     set_output_section(Output_section* os)
     {
       gold_assert(!this->is_input_section());
-      this->u2_.posd->set_output_section(os);
+      Output_section_data *posd = 
+        this->is_relaxed_input_section() ? this->u2_.poris : this->u2_.posd;
+      posd->set_output_section(os);
     }
 
     // Set the address and file offset.  This is called during
@@ -2553,11 +2896,11 @@ class Output_section : public Output_data
 
     // Add an input section, for SHF_MERGE sections.
     bool
-    add_input_section(Relobj* object, unsigned int shndx)
+    add_input_section(Relobj* object, unsigned int sec_shndx)
     {
       gold_assert(this->shndx_ == MERGE_DATA_SECTION_CODE
                  || this->shndx_ == MERGE_STRING_SECTION_CODE);
-      return this->u2_.posd->add_input_section(object, shndx);
+      return this->u2_.posd->add_input_section(object, sec_shndx);
     }
 
     // Given an input OBJECT, an input section index SHNDX within that
@@ -2611,7 +2954,9 @@ class Output_section : public Output_data
       MERGE_DATA_SECTION_CODE = -2U,
       // An Output_section_data for an SHF_MERGE section with
       // SHF_STRINGS set.
-      MERGE_STRING_SECTION_CODE = -3U
+      MERGE_STRING_SECTION_CODE = -3U,
+      // An Output_section_data for a relaxed input section.
+      RELAXED_INPUT_SECTION_CODE = -4U
     };
 
     // For an ordinary input section, this is the section index in the
@@ -2625,8 +2970,8 @@ class Output_section : public Output_data
     {
       // For an ordinary input section, the section size.
       off_t data_size;
-      // For OUTPUT_SECTION_CODE, this is not used.  For
-      // MERGE_DATA_SECTION_CODE or MERGE_STRING_SECTION_CODE, the
+      // For OUTPUT_SECTION_CODE or RELAXED_INPUT_SECTION_CODE, this is not
+      // used.  For MERGE_DATA_SECTION_CODE or MERGE_STRING_SECTION_CODE, the
       // entity size.
       uint64_t entsize;
     } u1_;
@@ -2638,11 +2983,102 @@ class Output_section : public Output_data
       // For OUTPUT_SECTION_CODE or MERGE_DATA_SECTION_CODE or
       // MERGE_STRING_SECTION_CODE, the data.
       Output_section_data* posd;
+      // For RELAXED_INPUT_SECTION_CODE, the data.
+      Output_relaxed_input_section* poris;
     } u2_;
   };
 
   typedef std::vector<Input_section> Input_section_list;
 
+  // Allow a child class to access the input sections.
+  const Input_section_list&
+  input_sections() const
+  { return this->input_sections_; }
+
+ private:
+  // We only save enough information to undo the effects of section layout.
+  class Checkpoint_output_section
+  {
+   public:
+    Checkpoint_output_section(uint64_t addr_align, elfcpp::Elf_Xword sflags,
+                             const Input_section_list& sinput_sections,
+                             off_t first_input_off,
+                             bool attached_input_sections_sorted)
+      : addralign_(addr_align), flags_(sflags),
+       input_sections_(sinput_sections),
+       input_sections_size_(input_sections_.size()),
+       input_sections_copy_(), first_input_offset_(first_input_off),
+       attached_input_sections_are_sorted_(attached_input_sections_sorted)
+    { }
+
+    virtual
+    ~Checkpoint_output_section()
+    { }
+
+    // Return the address alignment.
+    uint64_t
+    addralign() const
+    { return this->addralign_; }
+
+    // Return the section flags.
+    elfcpp::Elf_Xword
+    flags() const
+    { return this->flags_; }
+
+    // Return a reference to the input section list copy.
+    Input_section_list*
+    input_sections()
+    { return &this->input_sections_copy_; }
+
+    // Return the size of input_sections at the time when checkpoint is
+    // taken.
+    size_t
+    input_sections_size() const
+    { return this->input_sections_size_; }
+
+    // Whether input sections are copied.
+    bool
+    input_sections_saved() const
+    { return this->input_sections_copy_.size() == this->input_sections_size_; }
+
+    off_t
+    first_input_offset() const
+    { return this->first_input_offset_; }
+
+    bool
+    attached_input_sections_are_sorted() const
+    { return this->attached_input_sections_are_sorted_; }
+
+    // Save input sections.
+    void
+    save_input_sections()
+    {
+      this->input_sections_copy_.reserve(this->input_sections_size_);
+      this->input_sections_copy_.clear();
+      Input_section_list::const_iterator p = this->input_sections_.begin();
+      gold_assert(this->input_sections_size_ >= this->input_sections_.size());
+      for(size_t i = 0; i < this->input_sections_size_ ; i++, ++p)
+       this->input_sections_copy_.push_back(*p);
+    }
+
+   private:
+    // The section alignment.
+    uint64_t addralign_;
+    // The section flags.
+    elfcpp::Elf_Xword flags_;
+    // Reference to the input sections to be checkpointed.
+    const Input_section_list& input_sections_;
+    // Size of the checkpointed portion of input_sections_;
+    size_t input_sections_size_;
+    // Copy of input sections.
+    Input_section_list input_sections_copy_;
+    // The offset of the first entry in input_sections_.
+    off_t first_input_offset_;
+    // True if the input sections attached to this output section have
+    // already been sorted.
+    bool attached_input_sections_are_sorted_;
+  };
+
   // This class is used to sort the input sections.
   class Input_section_sort_entry;
 
@@ -2662,9 +3098,9 @@ class Output_section : public Output_data
   class Fill
   {
    public:
-    Fill(off_t section_offset, off_t length)
-      : section_offset_(section_offset),
-       length_(convert_to_section_size_type(length))
+    Fill(off_t section_off, off_t len)
+      : section_offset_(section_off),
+       length_(convert_to_section_size_type(len))
     { }
 
     // Return section offset.
@@ -2686,6 +3122,82 @@ class Output_section : public Output_data
 
   typedef std::vector<Fill> Fill_list;
 
+  // This class describes properties of merge data sections.  It is used
+  // as a key type for maps.
+  class Merge_section_properties
+  {
+   public:
+    Merge_section_properties(bool is_string, uint64_t entsize,
+                            uint64_t addralign)
+      : is_string_(is_string), entsize_(entsize), addralign_(addralign)
+    { }
+
+    // Whether this equals to another Merge_section_properties MSP.
+    bool
+    eq(const Merge_section_properties& msp) const
+    {
+      return ((this->is_string_ == msp.is_string_)
+             && (this->entsize_ == msp.entsize_)
+             && (this->addralign_ == msp.addralign_));
+    }
+
+    // Compute a hash value for this using 64-bit FNV-1a hash.
+    size_t
+    hash_value() const
+    {
+      uint64_t h = 14695981039346656037ULL;    // FNV offset basis.
+      uint64_t prime = 1099511628211ULL;
+      h = (h ^ static_cast<uint64_t>(this->is_string_)) * prime;
+      h = (h ^ static_cast<uint64_t>(this->entsize_)) * prime;
+      h = (h ^ static_cast<uint64_t>(this->addralign_)) * prime;
+      return h;
+    }
+    
+    // Functors for associative containers.
+    struct equal_to
+    {
+      bool
+      operator()(const Merge_section_properties& msp1,
+                const Merge_section_properties& msp2) const
+      { return msp1.eq(msp2); }
+    };
+
+    struct hash
+    {
+      size_t
+      operator()(const Merge_section_properties& msp) const
+      { return msp.hash_value(); }
+    };
+
+   private:
+    // Whether this merge data section is for strings.
+    bool is_string_;
+    // Entsize of this merge data section.
+    uint64_t entsize_;
+    // Address alignment.
+    uint64_t addralign_;
+  };
+
+  // Map that link Merge_section_properties to Output_merge_base.
+  typedef Unordered_map<Merge_section_properties, Output_merge_base*,
+                       Merge_section_properties::hash,
+                       Merge_section_properties::equal_to>
+    Merge_section_by_properties_map;
+
+  // Map that link Input_section_specifier to Output_section_data.
+  typedef Unordered_map<Input_section_specifier, Output_section_data*,
+                       Input_section_specifier::hash,
+                       Input_section_specifier::equal_to>
+    Output_section_data_by_input_section_map;
+
+  // Map used during relaxation of existing sections.  This map
+  // an input section specifier to an input section list index.
+  // We assume that Input_section_list is a vector.
+  typedef Unordered_map<Input_section_specifier, size_t,
+                       Input_section_specifier::hash,
+                       Input_section_specifier::equal_to>
+    Relaxation_map;
+
   // Add a new output section by Input_section.
   void
   add_output_section_data(Input_section*);
@@ -2708,6 +3220,25 @@ class Output_section : public Output_data
   void
   sort_attached_input_sections();
 
+  // 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*
+  find_merge_section(const Relobj* object, unsigned int shndx) const;
+
+  // Build a relaxation map.
+  void
+  build_relaxation_map(
+      const Input_section_list& input_sections,
+      size_t limit,
+      Relaxation_map* map) const;
+
+  // Convert input sections in an input section list into relaxed sections.
+  void
+  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);
+
   // Most of these fields are only valid after layout.
 
   // The name of the section.  This will point into a Stringpool.
@@ -2804,14 +3335,43 @@ class Output_section : public Output_data
   bool is_relro_ : 1;
   // True if this section holds relro local data.
   bool is_relro_local_ : 1;
+  // True if this is a small section.
+  bool is_small_section_ : 1;
+  // True if this is a large section.
+  bool is_large_section_ : 1;
+  // True if this is the .interp section going into the PT_INTERP
+  // segment.
+  bool is_interp_ : 1;
+  // True if this is section is read by the dynamic linker.
+  bool is_dynamic_linker_section_ : 1;
+  // Whether code-fills are generated at write.
+  bool generate_code_fills_at_write_ : 1;
   // For SHT_TLS sections, the offset of this section relative to the base
   // of the TLS segment.
   uint64_t tls_offset_;
+  // Saved checkpoint.
+  Checkpoint_output_section* checkpoint_;
+  // Map from input sections to merge sections.
+  Output_section_data_by_input_section_map merge_section_map_;
+  // Map from merge section properties to merge_sections;
+  Merge_section_by_properties_map merge_section_by_properties_map_;
+  // Map from input sections to relaxed input sections.  This is mutable
+  // because it is updated lazily.  We may need to update it in a
+  // const qualified method.
+  mutable Output_section_data_by_input_section_map relaxed_input_section_map_;
+  // Whether relaxed_input_section_map_ is valid.
+  mutable bool is_relaxed_input_section_map_valid_;
 };
 
 // An output segment.  PT_LOAD segments are built from collections of
 // output sections.  Other segments typically point within PT_LOAD
 // segments, and are built directly as needed.
+//
+// NOTE: We want to use the copy constructor for this class.  During
+// relaxation, we may try built the segments multiple times.  We do
+// that by copying the original segment list before lay-out, doing
+// a trial lay-out and roll-back to the saved copied if we need to
+// to the lay-out again.
 
 class Output_segment
 {
@@ -2854,13 +3414,27 @@ class Output_segment
   offset() const
   { return this->offset_; }
 
+  // Whether this is a segment created to hold large data sections.
+  bool
+  is_large_data_segment() const
+  { return this->is_large_data_segment_; }
+
+  // Record that this is a segment created to hold large data
+  // sections.
+  void
+  set_is_large_data_segment()
+  { this->is_large_data_segment_ = true; }
+
   // Return the maximum alignment of the Output_data.
   uint64_t
   maximum_alignment();
 
-  // Add an Output_section to this segment.
+  // Add the Output_section OS to this segment.  SEG_FLAGS is the
+  // segment flags to use.  DO_SORT is true if we should sort the
+  // placement of the input section for more efficient generated code.
   void
-  add_output_section(Output_section* os, elfcpp::Elf_Word seg_flags);
+  add_output_section(Output_section* os, elfcpp::Elf_Word seg_flags,
+                    bool do_sort);
 
   // Remove an Output_section from this segment.  It is an error if it
   // is not present.
@@ -2893,18 +3467,18 @@ class Output_segment
 
   // Set the addresses.
   void
-  set_addresses(uint64_t vaddr, uint64_t paddr)
+  set_addresses(uint64_t v_addr, uint64_t p_addr)
   {
-    this->vaddr_ = vaddr;
-    this->paddr_ = paddr;
+    this->vaddr_ = v_addr;
+    this->paddr_ = p_addr;
     this->are_addresses_set_ = true;
   }
 
   // Set the segment flags.  This is only used if we have a PHDRS
   // clause which explicitly specifies the flags.
   void
-  set_flags(elfcpp::Elf_Word flags)
-  { this->flags_ = flags; }
+  set_flags(elfcpp::Elf_Word seg_flags)
+  { this->flags_ = seg_flags; }
 
   // Set the address of the segment to ADDR and the offset to *POFF
   // and set the addresses and offsets of all contained output
@@ -2958,9 +3532,6 @@ class Output_segment
   print_sections_to_mapfile(Mapfile*) const;
 
  private:
-  Output_segment(const Output_segment&);
-  Output_segment& operator=(const Output_segment&);
-
   typedef std::list<Output_data*> Output_data_list;
 
   // Find the maximum alignment in an Output_data_list.
@@ -3003,6 +3574,9 @@ class Output_segment
   void
   print_section_list_to_mapfile(Mapfile*, const Output_data_list*) const;
 
+  // NOTE: We want to use the copy constructor.  Currently, shallow copy
+  // works for us so we do not need to write our own copy constructor.
+  
   // The list of output data with contents attached to this segment.
   Output_data_list output_data_;
   // The list of output data without contents attached to this segment.
@@ -3036,6 +3610,8 @@ class Output_segment
   bool is_max_align_known_ : 1;
   // Whether vaddr and paddr were set by a linker script.
   bool are_addresses_set_ : 1;
+  // Whether this segment holds large data sections.
+  bool is_large_data_segment_ : 1;
 };
 
 // This class represents the output file.
@@ -3051,19 +3627,37 @@ class Output_file
   set_is_temporary()
   { this->is_temporary_ = true; }
 
+  // Try to open an existing file. Returns false if the file doesn't
+  // exist, has a size of 0 or can't be mmaped.  This method is
+  // thread-unsafe.
+  bool
+  open_for_modification();
+
   // Open the output file.  FILE_SIZE is the final size of the file.
+  // If the file already exists, it is deleted/truncated.  This method
+  // is thread-unsafe.
   void
   open(off_t file_size);
 
-  // Resize the output file.
+  // Resize the output file.  This method is thread-unsafe.
   void
   resize(off_t file_size);
 
   // Close the output file (flushing all buffered data) and make sure
-  // there are no errors.
+  // there are no errors.  This method is thread-unsafe.
   void
   close();
 
+  // Return the size of this file.
+  off_t
+  filesize()
+  { return this->file_size_; }
+
+  // Return the name of this file.
+  const char*
+  filename()
+  { return this->name_; }
+
   // We currently always use mmap which makes the view handling quite
   // simple.  In the future we may support other approaches.
 
@@ -3111,10 +3705,19 @@ class Output_file
   { }
 
  private:
-  // Map the file into memory and return a pointer to the map.
+  // Map the file into memory or, if that fails, allocate anonymous
+  // memory.
   void
   map();
 
+  // Allocate anonymous memory for the file.
+  bool
+  map_anonymous();
+
+  // Map the file into memory.
+  bool
+  map_no_anonymous();
+
   // Unmap the file from memory (and flush to disk buffers).
   void
   unmap();
This page took 0.0467919999999999 seconds and 4 git commands to generate.