[GOLD][PATCH] Remove Output_section::Simple_input_section class.

Doug Kwan (關振德) dougkwan@google.com
Fri May 14 15:14:00 GMT 2010


Hi,

    This patch removes Output_section::Simple_input_section class and
replaces uses of it with equivalent code using
Output_section::Input_section.  As we discussed previously, I need to
export merge sections in Output_section using the get_input_sections
method.  Instead of extending Simple_input_section to handle merge
sections, it is simpler just use Input_section in the
get_input_sections interface.  We can also avoid conversion between
Simple_input_section and Input_section.  This affects some code
scripts processing and the relaxation code in the ARM back-end.  The
patch adjusts affected code accordingly.

   The patch has been tested with the full gold test suite on x86_64
on hardware and ARM on qemu.

-Doug

2010-05-14  Doug Kwan  <dougkwan@google.com>

        * arm.cc (Arm_input_section::original_size): New method.
        (Arm_input_section::do_output_offset): Remove static cast.
        (Arm_input_section::original_size_): Change type to off_t.
        (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.
-------------- next part --------------
Index: gold/arm.cc
===================================================================
RCS file: /cvs/src/src/gold/arm.cc,v
retrieving revision 1.102
diff -u -u -p -r1.102 arm.cc
--- gold/arm.cc	13 May 2010 02:41:15 -0000	1.102
+++ gold/arm.cc	14 May 2010 07:29:08 -0000
@@ -1164,6 +1164,11 @@ class Arm_input_section : public Output_
   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.
+  off_t
+  original_size() const
+  { return this->original_size_; }
+
  protected:
   // Write data to output file.
   void
@@ -1197,8 +1202,7 @@ class Arm_input_section : public Output_
     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;
@@ -1215,7 +1219,7 @@ class Arm_input_section : public Output_
   // Address alignment of the original input section.
   uint64_t original_addralign_;
   // Section size of the original input section.
-  uint64_t original_size_;
+  off_t original_size_;
   // Stub table.
   Stub_table<big_endian>* stub_table_;
 };
@@ -4949,10 +4953,8 @@ Arm_input_section<big_endian>::set_final
 
   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 +5578,8 @@ Arm_output_section<big_endian>::fix_exid
 
   // 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 +5588,23 @@ Arm_output_section<big_endian>::fix_exid
   
   // 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 +5629,8 @@ Arm_output_section<big_endian>::fix_exid
       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 +5685,9 @@ Arm_output_section<big_endian>::fix_exid
 	{
 	  // 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 +5697,7 @@ Arm_output_section<big_endian>::fix_exid
   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 +10450,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 +10499,28 @@ 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 as this point, set them here.
+      for (Stub_table_iterator sp = this->stub_tables_.begin();
+	   sp != this->stub_tables_.end();
+	   ++sp)
+	{
+	  // Update address and file offset of stub table.
+	  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: gold/output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.124
diff -u -u -p -r1.124 output.cc
--- gold/output.cc	9 Apr 2010 17:32:58 -0000	1.124
+++ gold/output.cc	14 May 2010 07:29:08 -0000
@@ -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 plian input section or a special input section like
+// a relaxed input section.  For special input section, it's 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
   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: gold/output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.104
diff -u -u -p -r1.104 output.h
--- gold/output.h	23 Apr 2010 04:47:32 -0000	1.104
+++ gold/output.h	14 May 2010 07:29:09 -0000
@@ -2766,263 +2766,6 @@ class Output_section : public Output_dat
 
   // 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_dat
     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_dat
     } 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: gold/script-sections.cc
===================================================================
RCS file: /cvs/src/src/gold/script-sections.cc,v
retrieving revision 1.33
diff -u -u -p -r1.33 script-sections.cc
--- gold/script-sections.cc	23 Apr 2010 04:47:33 -0000	1.33
+++ gold/script-sections.cc	14 May 2010 07:29:09 -0000
@@ -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
 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_sectio
 	   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_sectio
 	      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_addre
 					     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_addre
        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;
     }
 


More information about the Binutils mailing list