+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
// 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.
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.
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_(),
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;
this->input_sections_.push_back(is);
}
-//
+// Save states for relaxation.
void
Output_section::save_states()
gold_assert(this->fills_.empty());
}
+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()
{
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
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
void
restore_states();
+ // Discard states.
+ void
+ discard_states();
+
// Convert existing input sections to relaxed input sections.
void
convert_input_sections_to_relaxed_sections(
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();
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_;
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();
}
}
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;
}