*** empty log message ***
[deliverable/binutils-gdb.git] / gold / output.h
index e2c41c7d7da74cecfda02676ff72a330b97ea4be..6631aa1e8495f856a73b4e48aa462385fa2402a7 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* relobj, unsigned int shndx)
+    : relobj_(relobj), shndx_(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)
   {
-    gold_assert(!this->is_data_size_valid_);
+    gold_assert(!this->is_data_size_valid_
+               && !this->is_data_size_fixed_);
     this->data_size_ = data_size;
     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
@@ -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,9 +639,14 @@ 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_section_data(off_t data_size, uint64_t addralign,
+                     bool is_data_size_fixed)
     : Output_data(), output_section_(NULL), addralign_(addralign)
-  { this->set_data_size(data_size); }
+  {
+    this->set_data_size(data_size);
+    if (is_data_size_fixed)
+      this->fix_data_size();
+  }
 
   Output_section_data(uint64_t addralign)
     : Output_data(), output_section_(NULL), addralign_(addralign)
@@ -668,15 +796,15 @@ 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_section_data(data.size(), addralign, true), data_(data)
   { }
 
   Output_data_const(const char* p, off_t len, uint64_t addralign)
-    : Output_section_data(len, addralign), data_(p, len)
+    : Output_section_data(len, addralign, true), data_(p, len)
   { }
 
   Output_data_const(const unsigned char* p, off_t len, uint64_t addralign)
-    : Output_section_data(len, addralign),
+    : Output_section_data(len, addralign, true),
       data_(reinterpret_cast<const char*>(p), len)
   { }
 
@@ -707,7 +835,7 @@ 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),
+    : Output_section_data(len, addralign, true),
       p_(p), map_name_(map_name)
   { }
 
@@ -742,7 +870,7 @@ class Output_data_fixed_space : public Output_section_data
  public:
   Output_data_fixed_space(off_t data_size, uint64_t addralign,
                          const char* map_name)
-    : Output_section_data(data_size, addralign),
+    : Output_section_data(data_size, addralign, true),
       map_name_(map_name)
   { }
 
@@ -805,7 +933,7 @@ 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_section_data(data_size, addralign, 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()
@@ -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_;
@@ -1805,6 +1940,11 @@ class Output_data_dynamic : public Output_section_data
       : tag_(tag), 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* relobj, unsigned int shndx,
+                              uint64_t addralign)
+    : Output_section_data_build(addralign), relobj_(relobj), shndx_(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
@@ -2177,6 +2335,11 @@ class Output_section : public Output_data
   set_is_relro()
   { this->is_relro_ = true; }
 
+  // Record that this section does not hold relro data.
+  void
+  clear_is_relro()
+  { this->is_relro_ = false; }
+
   // True if this section holds relro local data--relro data for which
   // the dynamic relocations are all RELATIVE relocations.
   bool
@@ -2188,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
@@ -2253,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.
@@ -2280,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 *relobj, unsigned int shndx)
+      : shndx_(shndx)
+    {
+      gold_assert(shndx != invalid_shndx);
+      this->u_.relobj = relobj;
+    }
+    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
@@ -2288,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.
@@ -2307,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();
@@ -2344,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
@@ -2417,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
@@ -2446,7 +2745,8 @@ class Output_section : public Output_data
     {
       gold_assert(shndx != OUTPUT_SECTION_CODE
                  && shndx != MERGE_DATA_SECTION_CODE
-                 && shndx != MERGE_STRING_SECTION_CODE);
+                 && shndx != MERGE_STRING_SECTION_CODE
+                 && shndx != RELAXED_INPUT_SECTION_CODE);
       this->u1_.data_size = data_size;
       this->u2_.object = object;
     }
@@ -2470,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
@@ -2491,7 +2799,8 @@ 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
@@ -2507,20 +2816,57 @@ class Output_section : public Output_data
               && this->addralign() == addralign);
     }
 
+    // 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.
@@ -2528,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
@@ -2606,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
@@ -2620,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_;
@@ -2633,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 addralign, elfcpp::Elf_Xword flags,
+                             const Input_section_list& input_sections,
+                             off_t first_input_offset,
+                             bool attached_input_sections_are_sorted)
+      : addralign_(addralign), flags_(flags),
+       input_sections_(input_sections),
+       input_sections_size_(input_sections_.size()),
+       input_sections_copy_(), first_input_offset_(first_input_offset),
+       attached_input_sections_are_sorted_(attached_input_sections_are_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;
 
@@ -2681,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*);
@@ -2703,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.
@@ -2799,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
 {
@@ -2849,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.
@@ -2953,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.
@@ -2998,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.
@@ -3031,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.
@@ -3046,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.
 
@@ -3106,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.035725 seconds and 4 git commands to generate.