2010-01-22 Doug Kwan <dougkwan@google.com>
authorDoug Kwan <dougkwan@google.com>
Sat, 23 Jan 2010 01:07:59 +0000 (01:07 +0000)
committerDoug Kwan <dougkwan@google.com>
Sat, 23 Jan 2010 01:07:59 +0000 (01:07 +0000)
* arm.cc (Target_arm::do_relax): Record an output section for section
offset adjustment it contains any stub table that has changed.
* layout.cc (Layout::clean_up_after_relaxation): Adjust section
offsets in an output section if necessary.
* output.cc (Output_section::Output_section): Initialize
section_offsets_need_adjustments_.
(Output_section::add_input_section_for_script): Renamed to
Output_section::add_simple_input_section.
(Output_section::save_states): Add a comment.
(Output_section::discard_states): New method defintion.
(Output_section::adjust_section_offsets): Same.
* output.h (Output_section::add_input_section_for_script): Renamed to
Output_section::add_simple_input_section.
(Output_section::discard_states): New method declaration.
(Output_section::adjust_section_offsets): Same.
(Output_section::section_offsets_need_adjustment,
Output_section::set_section_offsets_need_adjustment): New method
definitions.
(Output_section::section_offsets_need_adjustment_): New data member.
* script-sections.cc
(Output_section_element_input::set_section_address): Adjust code for
renaming of Output_section::add_input_section_for_script.
(Orphan_output_section::set_section_address): Same.

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

index 0e94f26..94f2585 100644 (file)
@@ -1,3 +1,29 @@
+2010-01-22  Doug Kwan  <dougkwan@google.com>
+
+       * arm.cc (Target_arm::do_relax): Record an output section for section
+       offset adjustment it contains any stub table that has changed.
+       * layout.cc (Layout::clean_up_after_relaxation): Adjust section
+       offsets in an output section if necessary.
+       * output.cc (Output_section::Output_section): Initialize
+       section_offsets_need_adjustments_.
+       (Output_section::add_input_section_for_script): Renamed to
+       Output_section::add_simple_input_section.
+       (Output_section::save_states): Add a comment.
+       (Output_section::discard_states): New method defintion.
+       (Output_section::adjust_section_offsets): Same.
+       * output.h (Output_section::add_input_section_for_script): Renamed to
+       Output_section::add_simple_input_section.
+       (Output_section::discard_states): New method declaration.
+       (Output_section::adjust_section_offsets): Same.
+       (Output_section::section_offsets_need_adjustment,
+       Output_section::set_section_offsets_need_adjustment): New method
+       definitions.
+       (Output_section::section_offsets_need_adjustment_): New data member.
+       * script-sections.cc
+       (Output_section_element_input::set_section_address): Adjust code for
+       renaming of Output_section::add_input_section_for_script.
+       (Orphan_output_section::set_section_address): Same.
+
 2010-01-22  Viktor Kutuzov  <vkutuzov@accesssoftek.com>
 
        * gold/arm.cc (Target_arm): Updated fix_v4bx method and usage of
index f655d59..03f59f6 100644 (file)
@@ -8716,12 +8716,36 @@ Target_arm<big_endian>::do_relax(
   // or addresses alignments changed.  These are the only things that
   // matter.
   bool any_stub_table_changed = false;
+  Unordered_set<const Output_section*> sections_needing_adjustment;
   for (Stub_table_iterator sp = this->stub_tables_.begin();
        (sp != this->stub_tables_.end()) && !any_stub_table_changed;
        ++sp)
     {
       if ((*sp)->update_data_size_and_addralign())
-       any_stub_table_changed = true;
+       {
+         // Update data size of stub table owner.
+         Arm_input_section<big_endian>* owner = (*sp)->owner();
+         uint64_t address = owner->address();
+         off_t offset = owner->offset();
+         owner->reset_address_and_file_offset();
+         owner->set_address_and_file_offset(address, offset);
+
+         sections_needing_adjustment.insert(owner->output_section());
+         any_stub_table_changed = true;
+       }
+    }
+
+  // Output_section_data::output_section() returns a const pointer but we
+  // need to update output sections, so we record all output sections needing
+  // update above and scan the sections here to find out what sections need
+  // to be updated.
+  for(Layout::Section_list::const_iterator p = layout->section_list().begin();
+      p != layout->section_list().end();
+      ++p)
+    {
+      if (sections_needing_adjustment.find(*p)
+         != sections_needing_adjustment.end())
+       (*p)->set_section_offsets_need_adjustment();
     }
 
   // Finalize the stubs in the last relaxation pass.
index dc339d6..52989a5 100644 (file)
@@ -1401,8 +1401,15 @@ Layout::clean_up_after_relaxation()
        p != this->section_list_.end();
        ++p)
     {
-      (*p)->reset_address_and_file_offset();
       (*p)->restore_states();
+
+      // If an input section changes size because of relaxation,
+      // we need to adjust the section offsets of all input sections.
+      // after such a section.
+      if ((*p)->section_offsets_need_adjustment())
+       (*p)->adjust_section_offsets();
+
+      (*p)->reset_address_and_file_offset();
     }
   
   // Reset special output object address and file offsets.
index 6374895..a8f03e7 100644 (file)
@@ -1890,6 +1890,7 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
     is_dynamic_linker_section_(false),
     generate_code_fills_at_write_(false),
     is_entsize_zero_(false),
+    section_offsets_need_adjustment_(false),
     tls_offset_(0),
     checkpoint_(NULL),
     merge_section_map_(),
@@ -3043,12 +3044,12 @@ Output_section::get_input_sections(
   return data_size;
 }
 
-// Add an input section from a script.
+// Add an simple input section.
 
 void
-Output_section::add_input_section_for_script(const Simple_input_section& sis,
-                                            off_t data_size,
-                                            uint64_t addralign)
+Output_section::add_simple_input_section(const Simple_input_section& sis,
+                                        off_t data_size,
+                                        uint64_t addralign)
 {
   if (addralign > this->addralign_)
     this->addralign_ = addralign;
@@ -3067,7 +3068,7 @@ Output_section::add_input_section_for_script(const Simple_input_section& sis,
   this->input_sections_.push_back(is);
 }
 
-//
+// Save states for relaxation.
 
 void
 Output_section::save_states()
@@ -3083,6 +3084,19 @@ Output_section::save_states()
 }
 
 void
+Output_section::discard_states()
+{
+  gold_assert(this->checkpoint_ != NULL);
+  delete this->checkpoint_;
+  this->checkpoint_ = NULL;
+  gold_assert(this->fills_.empty());
+
+  // Simply invalidate the relaxed input section map since we do not keep
+  // track of it.
+  this->is_relaxed_input_section_map_valid_ = false;
+}
+
+void
 Output_section::restore_states()
 {
   gold_assert(this->checkpoint_ != NULL);
@@ -3116,6 +3130,29 @@ Output_section::restore_states()
   this->is_relaxed_input_section_map_valid_ = false;
 }
 
+// Update the section offsets of input sections in this.  This is required if
+// relaxation causes some input sections to change sizes.
+
+void
+Output_section::adjust_section_offsets()
+{
+  if (!this->section_offsets_need_adjustment_)
+    return;
+
+  off_t off = 0;
+  for (Input_section_list::iterator p = this->input_sections_.begin();
+       p != this->input_sections_.end();
+       ++p)
+    {
+      off = align_address(off, p->addralign());
+      if (p->is_input_section())
+       p->relobj()->set_section_offset(p->shndx(), off);
+      off += p->data_size();
+    }
+
+  this->section_offsets_need_adjustment_ = false;
+}
+
 // Print to the map file.
 
 void
index ec16ca3..60d57de 100644 (file)
@@ -2718,10 +2718,10 @@ class Output_section : public Output_data
   get_input_sections(uint64_t address, const std::string& fill,
                     std::list<Simple_input_section>*);
 
-  // Add an input section from a script.
+  // Add a simple input section.
   void
-  add_input_section_for_script(const Simple_input_section& input_section,
-                              off_t data_size, uint64_t addralign);
+  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
@@ -2744,6 +2744,10 @@ class Output_section : public Output_data
   void
   restore_states();
 
+  // Discard states.
+  void
+  discard_states();
+
   // Convert existing input sections to relaxed input sections.
   void
   convert_input_sections_to_relaxed_sections(
@@ -2754,6 +2758,21 @@ class Output_section : public Output_data
   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();
+
   // Print merge statistics to stderr.
   void
   print_merge_stats();
@@ -3509,6 +3528,8 @@ class Output_section : public Output_data
   bool generate_code_fills_at_write_ : 1;
   // Whether the entry size field should be zero.
   bool is_entsize_zero_ : 1;
+  // Whether section offsets need adjustment due to relaxation.
+  bool section_offsets_need_adjustment_ : 1;
   // For SHT_TLS sections, the offset of this section relative to the base
   // of the TLS segment.
   uint64_t tls_offset_;
index e106435..3cbabf4 100644 (file)
@@ -1409,9 +1409,9 @@ Output_section_element_input::set_section_addresses(
              layout->new_output_section_data_from_script(posd);
            }
 
-         output_section->add_input_section_for_script(p->input_section(),
-                                                      p->size(),
-                                                      this_subalign);
+         output_section->add_simple_input_section(p->input_section(),
+                                                  p->size(),
+                                                  this_subalign);
 
          dot = address + p->size();
        }
@@ -2315,7 +2315,7 @@ Orphan_output_section::set_section_addresses(Symbol_table*, Layout*,
       }
 
       address = align_address(address, addralign);
-      this->os_->add_input_section_for_script(*p, size, addralign);
+      this->os_->add_simple_input_section(*p, size, addralign);
       address += size;
     }