2010-05-14 Doug Kwan <dougkwan@google.com>
authorDoug Kwan <dougkwan@google.com>
Wed, 19 May 2010 07:09:36 +0000 (07:09 +0000)
committerDoug Kwan <dougkwan@google.com>
Wed, 19 May 2010 07:09:36 +0000 (07:09 +0000)
* arm.cc (Arm_input_section::original_size): New method.
(Arm_input_section::do_addralign): Add a cast.
(Arm_input_section::do_output_offset): Remove static cast.
(Arm_input_section::original_addralign,
 Arm_input_section::original_size_): Change type to uint32_t.
(Arm_input_section::init): Add safe casts for section alignment
and size.
(Arm_input_section::set_final_data_size): Do not set address and
offset of stub table.
(Arm_output_section::fix_exidx_coverage): Change use of of
Output_section::Simple_input_section to that of
Output_section::Input_section.
(Target_arm::do_relax): Set addresses and file offsets of Stub_tables
except for the first pass.
* output.cc (Output_section::get_input_sections): Change type of
input_sections to std::list<Input_section>.
(Output_section::add_script_input_section): Rename from
Output_section::add_simple_input_section.  Change type of SIS
parameter from Simple_input_section to Input_section.
* output.h (Output_section::Simple_input_section): Remove class.
(Output_section::Input_section): Change class visibility to public.
(Output_section::Input_section::addralign): Use stored alignments
for special input sections if set.
(Output_section::Input_section::set_addralign): New method.
(Output_section::get_input_sections): Change parameter type from
list of Simple_input_section to list of Input_section.
(Output_section::add_script_input_section): Rename from
Output_section::add_simple_input_section. Change first parameter's
type from Simple_input_section to Input_section and remove the
second and third parameters.
* script-sections.cc (Input_section::Input_section_list): Change
type to list of Output_section::Input_section/
(Input_section_info::Input_section_info): Change parameter type of
INPUT_SECTION to Output_section::Input_section.
(Input_section_info::input_section): Change return type.
(Input_section_info::input_section_): Change type to
Output_section::Input_section.
(Output_section_element_input::set_section_addresses): Adjust code
to use Output_section::Input_section instead of
Output_section::Simple_input_section.  Adjust code for renaming
of Output_section::add_simple_input_section.
(Orphan_output_section::set_section_addresses): Ditto.

gold/ChangeLog
gold/arm.cc
gold/output.cc
gold/output.h
gold/script-sections.cc

index b78195e943255e7b0bc348f950091afeb0baf05b..1ff2a48906c0a4be877971aa718bf8414a3e0961 100644 (file)
@@ -1,3 +1,48 @@
+2010-05-19  Doug Kwan  <dougkwan@google.com>
+
+       * arm.cc (Arm_input_section::original_size): New method.
+       (Arm_input_section::do_addralign): Add a cast.
+       (Arm_input_section::do_output_offset): Remove static cast.
+       (Arm_input_section::original_addralign,
+        Arm_input_section::original_size_): Change type to uint32_t.
+       (Arm_input_section::init): Add safe casts for section alignment
+       and size.
+       (Arm_input_section::set_final_data_size): Do not set address and
+       offset of stub table.
+       (Arm_output_section::fix_exidx_coverage): Change use of of
+       Output_section::Simple_input_section to that of
+       Output_section::Input_section.
+       (Target_arm::do_relax): Set addresses and file offsets of Stub_tables
+       except for the first pass.
+       * output.cc (Output_section::get_input_sections): Change type of
+       input_sections to std::list<Input_section>.
+       (Output_section::add_script_input_section): Rename from
+       Output_section::add_simple_input_section.  Change type of SIS
+       parameter from Simple_input_section to Input_section.
+       * output.h (Output_section::Simple_input_section): Remove class.
+       (Output_section::Input_section): Change class visibility to public.
+       (Output_section::Input_section::addralign): Use stored alignments
+       for special input sections if set.
+       (Output_section::Input_section::set_addralign): New method.
+       (Output_section::get_input_sections): Change parameter type from
+       list of Simple_input_section to list of Input_section.
+       (Output_section::add_script_input_section): Rename from
+       Output_section::add_simple_input_section. Change first parameter's
+       type from Simple_input_section to Input_section and remove the
+       second and third parameters.
+       * script-sections.cc (Input_section::Input_section_list): Change
+       type to list of Output_section::Input_section/
+       (Input_section_info::Input_section_info): Change parameter type of
+       INPUT_SECTION to Output_section::Input_section.
+       (Input_section_info::input_section): Change return type.
+       (Input_section_info::input_section_): Change type to
+       Output_section::Input_section.
+       (Output_section_element_input::set_section_addresses): Adjust code
+       to use Output_section::Input_section instead of
+       Output_section::Simple_input_section.  Adjust code for renaming
+       of Output_section::add_simple_input_section.
+       (Orphan_output_section::set_section_addresses): Ditto.
+
 2010-05-18  Ralf Wildenhues  <Ralf.Wildenhues@gmx.de>
 
        * gold.h (Unordered_multimap, Unordered_map): Fix defines for
index c304d2acfc92bb6448f92120c44ee5f00d2ce491..3dc2f22023e50c9dbcc67b5dab8de6d133ee5e53 100644 (file)
@@ -1164,6 +1164,11 @@ class Arm_input_section : public Output_relaxed_input_section
   as_arm_input_section(Output_relaxed_input_section* poris)
   { return static_cast<Arm_input_section<big_endian>*>(poris); }
 
+  // Return the original size of the section.
+  uint32_t
+  original_size() const
+  { return this->original_size_; }
+
  protected:
   // Write data to output file.
   void
@@ -1175,7 +1180,7 @@ class Arm_input_section : public Output_relaxed_input_section
   {
     if (this->is_stub_table_owner())
       return std::max(this->stub_table_->addralign(),
-                     this->original_addralign_);
+                     static_cast<uint64_t>(this->original_addralign_));
     else
       return this->original_addralign_;
   }
@@ -1197,8 +1202,7 @@ class Arm_input_section : public Output_relaxed_input_section
     if ((object == this->relobj())
        && (shndx == this->shndx())
        && (offset >= 0)
-       && (convert_types<uint64_t, section_offset_type>(offset)
-           <= this->original_size_))
+       && (offset <= this->original_size_))
       {
        *poutput = offset;
        return true;
@@ -1213,9 +1217,9 @@ class Arm_input_section : public Output_relaxed_input_section
   Arm_input_section& operator=(const Arm_input_section&);
 
   // Address alignment of the original input section.
-  uint64_t original_addralign_;
+  uint32_t original_addralign_;
   // Section size of the original input section.
-  uint64_t original_size_;
+  uint32_t original_size_;
   // Stub table.
   Stub_table<big_endian>* stub_table_;
 };
@@ -4909,8 +4913,10 @@ Arm_input_section<big_endian>::init()
 
   // Cache these to speed up size and alignment queries.  It is too slow
   // to call section_addraglin and section_size every time.
-  this->original_addralign_ = relobj->section_addralign(shndx);
-  this->original_size_ = relobj->section_size(shndx);
+  this->original_addralign_ =
+    convert_types<uint32_t, uint64_t>(relobj->section_addralign(shndx));
+  this->original_size_ =
+    convert_types<uint32_t, uint64_t>(relobj->section_size(shndx));
 
   // We want to make this look like the original input section after
   // output sections are finalized.
@@ -4949,10 +4955,8 @@ Arm_input_section<big_endian>::set_final_data_size()
 
   if (this->is_stub_table_owner())
     {
-      // The stub table comes after the original section contents.
+      this->stub_table_->finalize_data_size();
       off = align_address(off, this->stub_table_->addralign());
-      this->stub_table_->set_address_and_file_offset(this->address() + off,
-                                                    this->offset() + off);
       off += this->stub_table_->data_size();
     }
   this->set_data_size(off);
@@ -5576,8 +5580,8 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
 
   // Remove all input sections.
   uint64_t address = this->address();
-  typedef std::list<Simple_input_section> Simple_input_section_list;
-  Simple_input_section_list input_sections;
+  typedef std::list<Output_section::Input_section> Input_section_list;
+  Input_section_list input_sections;
   this->reset_address_and_file_offset();
   this->get_input_sections(address, std::string(""), &input_sections);
 
@@ -5586,20 +5590,23 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
   
   // Go through all the known input sections and record them.
   typedef Unordered_set<Section_id, Section_id_hash> Section_id_set;
-  Section_id_set known_input_sections;
-  for (Simple_input_section_list::const_iterator p = input_sections.begin();
+  typedef Unordered_map<Section_id, const Output_section::Input_section*,
+                       Section_id_hash> Text_to_exidx_map;
+  Text_to_exidx_map text_to_exidx_map;
+  for (Input_section_list::const_iterator p = input_sections.begin();
        p != input_sections.end();
        ++p)
     {
       // This should never happen.  At this point, we should only see
       // plain EXIDX input sections.
       gold_assert(!p->is_relaxed_input_section());
-      known_input_sections.insert(Section_id(p->relobj(), p->shndx()));
+      text_to_exidx_map[Section_id(p->relobj(), p->shndx())] = &(*p);
     }
 
   Arm_exidx_fixup exidx_fixup(this, merge_exidx_entries);
 
   // Go over the sorted text sections.
+  typedef Unordered_set<Section_id, Section_id_hash> Section_id_set;
   Section_id_set processed_input_sections;
   for (Text_section_list::const_iterator p = sorted_text_sections.begin();
        p != sorted_text_sections.end();
@@ -5624,7 +5631,8 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
       Relobj* exidx_relobj = exidx_input_section->relobj();
       unsigned int exidx_shndx = exidx_input_section->shndx();
       Section_id sid(exidx_relobj, exidx_shndx);
-      if (known_input_sections.find(sid) == known_input_sections.end())
+      Text_to_exidx_map::const_iterator iter = text_to_exidx_map.find(sid);
+      if (iter == text_to_exidx_map.end())
        {
          // This is odd.  We have not seen this EXIDX input section before.
          // We cannot do fix-up.  If we saw a SECTIONS clause in a script,
@@ -5679,9 +5687,9 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
        {
          // Just add back the EXIDX input section.
          gold_assert(section_offset_map == NULL);
-         Output_section::Simple_input_section sis(exidx_relobj, exidx_shndx);
-         this->add_simple_input_section(sis, exidx_input_section->size(),
-                                        exidx_input_section->addralign());
+         const Output_section::Input_section* pis = iter->second;
+         gold_assert(pis->is_input_section());
+         this->add_script_input_section(*pis);
        }
 
       processed_input_sections.insert(Section_id(exidx_relobj, exidx_shndx)); 
@@ -5691,7 +5699,7 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
   exidx_fixup.add_exidx_cantunwind_as_needed();
 
   // Remove any known EXIDX input sections that are not processed.
-  for (Simple_input_section_list::const_iterator p = input_sections.begin();
+  for (Input_section_list::const_iterator p = input_sections.begin();
        p != input_sections.end();
        ++p)
     {
@@ -10444,6 +10452,7 @@ Target_arm<big_endian>::do_relax(
   // If this is the first pass, we need to group input sections into
   // stub groups.
   bool done_exidx_fixup = false;
+  typedef typename Stub_table_list::iterator Stub_table_iterator;
   if (pass == 1)
     {
       // Determine the stub group size.  The group size is the absolute
@@ -10492,13 +10501,27 @@ Target_arm<big_endian>::do_relax(
          done_exidx_fixup = true;
        }
     }
+  else
+    {
+      // If this is not the first pass, addresses and file offsets have
+      // been reset at this point, set them here.
+      for (Stub_table_iterator sp = this->stub_tables_.begin();
+          sp != this->stub_tables_.end();
+          ++sp)
+       {
+         Arm_input_section<big_endian>* owner = (*sp)->owner();
+         off_t off = align_address(owner->original_size(),
+                                   (*sp)->addralign());
+         (*sp)->set_address_and_file_offset(owner->address() + off,
+                                            owner->offset() + off);
+       }
+    }
 
   // The Cortex-A8 stubs are sensitive to layout of code sections.  At the
   // beginning of each relaxation pass, just blow away all the stubs.
   // Alternatively, we could selectively remove only the stubs and reloc
   // information for code sections that have moved since the last pass.
   // That would require more book-keeping.
-  typedef typename Stub_table_list::iterator Stub_table_iterator;
   if (this->fix_cortex_a8_)
     {
       // Clear all Cortex-A8 reloc information.
index 687803479a020f9b102c67b298bd7b7f62bb8bb9..4c9776d6313742d749e207ae1b3b5ec70bcc81d6 100644 (file)
@@ -3046,7 +3046,7 @@ uint64_t
 Output_section::get_input_sections(
     uint64_t address,
     const std::string& fill,
-    std::list<Simple_input_section>* input_sections)
+    std::list<Input_section>* input_sections)
 {
   if (this->checkpoint_ != NULL
       && !this->checkpoint_->input_sections_saved())
@@ -3064,12 +3064,8 @@ Output_section::get_input_sections(
        p != this->input_sections_.end();
        ++p)
     {
-      if (p->is_input_section())
-       input_sections->push_back(Simple_input_section(p->relobj(),
-                                                      p->shndx()));
-      else if (p->is_relaxed_input_section())
-       input_sections->push_back(
-           Simple_input_section(p->relaxed_input_section()));
+      if (p->is_input_section() || p->is_relaxed_input_section())
+       input_sections->push_back(*p);
       else
        {
          uint64_t aligned_address = align_address(address, p->addralign());
@@ -3104,13 +3100,16 @@ Output_section::get_input_sections(
   return data_size;
 }
 
-// Add an simple input section.
+// Add a script input section.  SIS is an Output_section::Input_section,
+// which can be either a plain input section or a special input section like
+// a relaxed input section.  For a special input section, its size must be
+// finalized.
 
 void
-Output_section::add_simple_input_section(const Simple_input_section& sis,
-                                        off_t data_size,
-                                        uint64_t addralign)
+Output_section::add_script_input_section(const Input_section& sis)
 {
+  uint64_t data_size = sis.data_size();
+  uint64_t addralign = sis.addralign();
   if (addralign > this->addralign_)
     this->addralign_ = addralign;
 
@@ -3121,11 +3120,7 @@ Output_section::add_simple_input_section(const Simple_input_section& sis,
   this->set_current_data_size_for_child(aligned_offset_in_section
                                        + data_size);
 
-  Input_section is =
-    (sis.is_relaxed_input_section()
-     ? Input_section(sis.relaxed_input_section())
-     : Input_section(sis.relobj(), sis.shndx(), data_size, addralign));
-  this->input_sections_.push_back(is);
+  this->input_sections_.push_back(sis);
 }
 
 // Save states for relaxation.
index 410ec2c39e67f74e65bc82419dcad76fd77c5db5..a15fe2718f9e786e8b2bbb9893f52ce74a686059 100644 (file)
@@ -2766,263 +2766,6 @@ 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
-  // Output_section_data elements.  ADDRESS is the address of this
-  // output section.  FILL is the fill value to use, in case there are
-  // any spaces between the remaining Output_section_data elements.
-  uint64_t
-  get_input_sections(uint64_t address, const std::string& fill,
-                    std::list<Simple_input_section>*);
-
-  // Add a simple input section.
-  void
-  add_simple_input_section(const Simple_input_section& input_section,
-                          off_t data_size, uint64_t addralign);
-
-  // Set the current size of the output section.
-  void
-  set_current_data_size(off_t size)
-  { this->set_current_data_size_for_child(size); }
-
-  // Get the current size of the output section.
-  off_t
-  current_data_size() const
-  { return this->current_data_size_for_child(); }
-
-  // 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();
-
-  // Discard states.
-  void
-  discard_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_relaxed_input_section*
-  find_relaxed_input_section(const Relobj* object, unsigned int shndx) const;
-  
-  // Whether section offsets need adjustment due to relaxation.
-  bool
-  section_offsets_need_adjustment() const
-  { return this->section_offsets_need_adjustment_; }
-
-  // Set section_offsets_need_adjustment to be true.
-  void
-  set_section_offsets_need_adjustment()
-  { this->section_offsets_need_adjustment_ = true; }
-
-  // Adjust section offsets of input sections in this.  This is
-  // requires if relaxation caused some input sections to change sizes.
-  void
-  adjust_section_offsets();
-
-  // Whether this is a NOLOAD section.
-  bool
-  is_noload() const
-  { return this->is_noload_; }
-
-  // Set NOLOAD flag.
-  void
-  set_is_noload()
-  { this->is_noload_ = true; }
-
-  // Print merge statistics to stderr.
-  void
-  print_merge_stats();
-
- protected:
-  // Return the output section--i.e., the object itself.
-  Output_section*
-  do_output_section()
-  { return this; }
-
-  const Output_section*
-  do_output_section() const
-  { return this; }
-
-  // Return the section index in the output file.
-  unsigned int
-  do_out_shndx() const
-  {
-    gold_assert(this->out_shndx_ != -1U);
-    return this->out_shndx_;
-  }
-
-  // Set the output section index.
-  void
-  do_set_out_shndx(unsigned int shndx)
-  {
-    gold_assert(this->out_shndx_ == -1U || this->out_shndx_ == shndx);
-    this->out_shndx_ = shndx;
-  }
-
-  // Set the final data size of the Output_section.  For a typical
-  // Output_section, there is nothing to do, but if there are any
-  // Output_section_data objects we need to set their final addresses
-  // here.
-  virtual void
-  set_final_data_size();
-
-  // Reset the address and file offset.
-  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
-  // objects we do need to write them out here.
-  virtual void
-  do_write(Output_file*);
-
-  // Return the address alignment--function required by parent class.
-  uint64_t
-  do_addralign() const
-  { return this->addralign_; }
-
-  // Return whether there is a load address.
-  bool
-  do_has_load_address() const
-  { return this->has_load_address_; }
-
-  // Return the load address.
-  uint64_t
-  do_load_address() const
-  {
-    gold_assert(this->has_load_address_);
-    return this->load_address_;
-  }
-
-  // Return whether this is an Output_section.
-  bool
-  do_is_section() const
-  { return true; }
-
-  // Return whether this is a section of the specified type.
-  bool
-  do_is_section_type(elfcpp::Elf_Word type) const
-  { return this->type_ == type; }
-
-  // Return whether the specified section flag is set.
-  bool
-  do_is_section_flag_set(elfcpp::Elf_Xword flag) const
-  { return (this->flags_ & flag) != 0; }
-
-  // Set the TLS offset.  Called only for SHT_TLS sections.
-  void
-  do_set_tls_offset(uint64_t tls_base);
-
-  // Return the TLS offset, relative to the base of the TLS segment.
-  // Valid only for SHT_TLS sections.
-  uint64_t
-  do_tls_offset() const
-  { return this->tls_offset_; }
-
-  // This may be implemented by a child class.
-  virtual void
-  do_finalize_name(Layout*)
-  { }
-
-  // Print to the map file.
-  virtual void
-  do_print_to_mapfile(Mapfile*) const;
-
-  // Record that this section requires postprocessing after all
-  // relocations have been applied.  This is called by a child class.
-  void
-  set_requires_postprocessing()
-  {
-    this->requires_postprocessing_ = true;
-    this->after_input_sections_ = true;
-  }
-
-  // Write all the data of an Output_section into the postprocessing
-  // buffer.
-  void
-  write_to_postprocessing_buffer();
-
   // 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
@@ -3088,13 +2831,29 @@ class Output_section : public Output_data
     uint64_t
     addralign() const
     {
-      if (!this->is_input_section())
+      if (this->p2align_ != 0)
+       return static_cast<uint64_t>(1) << (this->p2align_ - 1);
+      else if (!this->is_input_section())
        return this->u2_.posd->addralign();
-      return (this->p2align_ == 0
-             ? 0
-             : static_cast<uint64_t>(1) << (this->p2align_ - 1));
+      else
+       return 0;
     }
 
+    // Set the required alignment, which must be either 0 or a power of 2.
+    // For input sections that are sub-classes of Output_section_data, a
+    // alignment of zero means asking the underlying object for alignment.
+    void
+    set_addralign(uint64_t addralign)
+    {
+      if (addralign == 0)
+       this->p2align_ = 0;
+      else
+       {
+         gold_assert((addralign & (addralign - 1)) == 0);
+         this->p2align_ = ffsll(static_cast<long long>(addralign));
+       }
+    }
     // Return the required size.
     off_t
     data_size() const;
@@ -3294,6 +3053,200 @@ class Output_section : public Output_data
     } u2_;
   };
 
+  // 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
+  // Output_section_data elements.  ADDRESS is the address of this
+  // output section.  FILL is the fill value to use, in case there are
+  // any spaces between the remaining Output_section_data elements.
+  uint64_t
+  get_input_sections(uint64_t address, const std::string& fill,
+                    std::list<Input_section>*);
+
+  // Add a script input section.  A script input section can either be
+  // a plain input section or a sub-class of Output_section_data.
+  void
+  add_script_input_section(const Input_section& input_section);
+
+  // Set the current size of the output section.
+  void
+  set_current_data_size(off_t size)
+  { this->set_current_data_size_for_child(size); }
+
+  // Get the current size of the output section.
+  off_t
+  current_data_size() const
+  { return this->current_data_size_for_child(); }
+
+  // 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();
+
+  // Discard states.
+  void
+  discard_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_relaxed_input_section*
+  find_relaxed_input_section(const Relobj* object, unsigned int shndx) const;
+  
+  // Whether section offsets need adjustment due to relaxation.
+  bool
+  section_offsets_need_adjustment() const
+  { return this->section_offsets_need_adjustment_; }
+
+  // Set section_offsets_need_adjustment to be true.
+  void
+  set_section_offsets_need_adjustment()
+  { this->section_offsets_need_adjustment_ = true; }
+
+  // Adjust section offsets of input sections in this.  This is
+  // requires if relaxation caused some input sections to change sizes.
+  void
+  adjust_section_offsets();
+
+  // Whether this is a NOLOAD section.
+  bool
+  is_noload() const
+  { return this->is_noload_; }
+
+  // Set NOLOAD flag.
+  void
+  set_is_noload()
+  { this->is_noload_ = true; }
+
+  // Print merge statistics to stderr.
+  void
+  print_merge_stats();
+
+ protected:
+  // Return the output section--i.e., the object itself.
+  Output_section*
+  do_output_section()
+  { return this; }
+
+  const Output_section*
+  do_output_section() const
+  { return this; }
+
+  // Return the section index in the output file.
+  unsigned int
+  do_out_shndx() const
+  {
+    gold_assert(this->out_shndx_ != -1U);
+    return this->out_shndx_;
+  }
+
+  // Set the output section index.
+  void
+  do_set_out_shndx(unsigned int shndx)
+  {
+    gold_assert(this->out_shndx_ == -1U || this->out_shndx_ == shndx);
+    this->out_shndx_ = shndx;
+  }
+
+  // Set the final data size of the Output_section.  For a typical
+  // Output_section, there is nothing to do, but if there are any
+  // Output_section_data objects we need to set their final addresses
+  // here.
+  virtual void
+  set_final_data_size();
+
+  // Reset the address and file offset.
+  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
+  // objects we do need to write them out here.
+  virtual void
+  do_write(Output_file*);
+
+  // Return the address alignment--function required by parent class.
+  uint64_t
+  do_addralign() const
+  { return this->addralign_; }
+
+  // Return whether there is a load address.
+  bool
+  do_has_load_address() const
+  { return this->has_load_address_; }
+
+  // Return the load address.
+  uint64_t
+  do_load_address() const
+  {
+    gold_assert(this->has_load_address_);
+    return this->load_address_;
+  }
+
+  // Return whether this is an Output_section.
+  bool
+  do_is_section() const
+  { return true; }
+
+  // Return whether this is a section of the specified type.
+  bool
+  do_is_section_type(elfcpp::Elf_Word type) const
+  { return this->type_ == type; }
+
+  // Return whether the specified section flag is set.
+  bool
+  do_is_section_flag_set(elfcpp::Elf_Xword flag) const
+  { return (this->flags_ & flag) != 0; }
+
+  // Set the TLS offset.  Called only for SHT_TLS sections.
+  void
+  do_set_tls_offset(uint64_t tls_base);
+
+  // Return the TLS offset, relative to the base of the TLS segment.
+  // Valid only for SHT_TLS sections.
+  uint64_t
+  do_tls_offset() const
+  { return this->tls_offset_; }
+
+  // This may be implemented by a child class.
+  virtual void
+  do_finalize_name(Layout*)
+  { }
+
+  // Print to the map file.
+  virtual void
+  do_print_to_mapfile(Mapfile*) const;
+
+  // Record that this section requires postprocessing after all
+  // relocations have been applied.  This is called by a child class.
+  void
+  set_requires_postprocessing()
+  {
+    this->requires_postprocessing_ = true;
+    this->after_input_sections_ = true;
+  }
+
+  // Write all the data of an Output_section into the postprocessing
+  // buffer.
+  void
+  write_to_postprocessing_buffer();
+
   typedef std::vector<Input_section> Input_section_list;
 
   // Allow a child class to access the input sections.
index b4cbb40114910131f2cf52efd13f8364d81b6911..e7782798a5f48f5416ab5f1a49263bfb2e08dd1b 100644 (file)
@@ -546,7 +546,7 @@ class Output_section_element
 {
  public:
   // A list of input sections.
-  typedef std::list<Output_section::Simple_input_section> Input_section_list;
+  typedef std::list<Output_section::Input_section> Input_section_list;
 
   Output_section_element()
   { }
@@ -1195,13 +1195,13 @@ Output_section_element_input::match_name(const char* file_name,
 class Input_section_info
 {
  public:
-  Input_section_info(const Output_section::Simple_input_section& input_section)
+  Input_section_info(const Output_section::Input_section& input_section)
     : input_section_(input_section), section_name_(),
       size_(0), addralign_(1)
   { }
 
   // Return the simple input section.
-  const Output_section::Simple_input_section&
+  const Output_section::Input_section&
   input_section() const
   { return this->input_section_; }
 
@@ -1247,7 +1247,7 @@ class Input_section_info
 
  private:
   // Input section, can be a relaxed section.
-  Output_section::Simple_input_section input_section_;
+  Output_section::Input_section input_section_;
   // Name of the section. 
   std::string section_name_;
   // Section size.
@@ -1418,9 +1418,20 @@ Output_section_element_input::set_section_addresses(
           p != matching_sections[i].end();
           ++p)
        {
-         uint64_t this_subalign = p->addralign();
+         // Override the original address alignment if SUBALIGN is specified
+         // and is greater than the original alignment.  We need to make a
+         // copy of the input section to modify the alignment.
+         Output_section::Input_section sis(p->input_section());
+
+         uint64_t this_subalign = sis.addralign();
+         if (!sis.is_input_section())
+           sis.output_section_data()->finalize_data_size();    
+         uint64_t data_size = sis.data_size();
          if (this_subalign < subalign)
-           this_subalign = subalign;
+           {
+             this_subalign = subalign;
+             sis.set_addralign(subalign);
+           }
 
          uint64_t address = align_address(dot, this_subalign);
 
@@ -1434,11 +1445,8 @@ Output_section_element_input::set_section_addresses(
              layout->new_output_section_data_from_script(posd);
            }
 
-         output_section->add_simple_input_section(p->input_section(),
-                                                  p->size(),
-                                                  this_subalign);
-
-         dot = address + p->size();
+         output_section->add_script_input_section(sis);
+         dot = address + data_size;
        }
     }
 
@@ -2381,7 +2389,7 @@ Orphan_output_section::set_section_addresses(Symbol_table*, Layout*,
                                             uint64_t*,
                                              uint64_t* load_address)
 {
-  typedef std::list<Output_section::Simple_input_section> Input_section_list;
+  typedef std::list<Output_section::Input_section> Input_section_list;
 
   bool have_load_address = *load_address != *dot_value;
 
@@ -2403,25 +2411,12 @@ Orphan_output_section::set_section_addresses(Symbol_table*, Layout*,
        p != input_sections.end();
        ++p)
     {
-      uint64_t addralign;
-      uint64_t size;
-
-      // We know we are single-threaded, so it is OK to lock the
-      // object.
-      {
-       const Task* task = reinterpret_cast<const Task*>(-1);
-       Task_lock_obj<Object> tl(task, p->relobj());
-       addralign = p->relobj()->section_addralign(p->shndx());
-       if (p->is_relaxed_input_section())
-         // We use current data size because relxed section sizes may not
-         // have finalized yet.
-         size = p->relaxed_input_section()->current_data_size();
-       else
-         size = p->relobj()->section_size(p->shndx());
-      }
-
+      uint64_t addralign = p->addralign();
+      if (!p->is_input_section())
+       p->output_section_data()->finalize_data_size(); 
+      uint64_t size = p->data_size();
       address = align_address(address, addralign);
-      this->os_->add_simple_input_section(*p, size, addralign);
+      this->os_->add_script_input_section(*p);
       address += size;
     }