From 8923b24c4bde41e6a15026aa1d20493fd383066c Mon Sep 17 00:00:00 2001 From: Doug Kwan Date: Sat, 23 Jan 2010 01:07:59 +0000 Subject: [PATCH] 2010-01-22 Doug Kwan * 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 | 26 ++++++++++++++++++++++++++ gold/arm.cc | 26 +++++++++++++++++++++++++- gold/layout.cc | 9 ++++++++- gold/output.cc | 47 ++++++++++++++++++++++++++++++++++++++++++----- gold/output.h | 27 ++++++++++++++++++++++++--- gold/script-sections.cc | 8 ++++---- 6 files changed, 129 insertions(+), 14 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index 0e94f26..94f2585 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,29 @@ +2010-01-22 Doug Kwan + + * 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 * gold/arm.cc (Target_arm): Updated fix_v4bx method and usage of diff --git a/gold/arm.cc b/gold/arm.cc index f655d59..03f59f6 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -8716,12 +8716,36 @@ Target_arm::do_relax( // or addresses alignments changed. These are the only things that // matter. bool any_stub_table_changed = false; + Unordered_set 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* 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. diff --git a/gold/layout.cc b/gold/layout.cc index dc339d6..52989a5 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -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. diff --git a/gold/output.cc b/gold/output.cc index 6374895..a8f03e7 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -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 diff --git a/gold/output.h b/gold/output.h index ec16ca3..60d57de 100644 --- a/gold/output.h +++ b/gold/output.h @@ -2718,10 +2718,10 @@ class Output_section : public Output_data get_input_sections(uint64_t address, const std::string& fill, std::list*); - // 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_; diff --git a/gold/script-sections.cc b/gold/script-sections.cc index e106435..3cbabf4 100644 --- a/gold/script-sections.cc +++ b/gold/script-sections.cc @@ -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; } -- 2.7.4