aboutsummaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
authorDoug Kwan <dougkwan@google.com>2010-01-23 01:07:59 +0000
committerDoug Kwan <dougkwan@google.com>2010-01-23 01:07:59 +0000
commit8923b24c4bde41e6a15026aa1d20493fd383066c (patch)
treedfe04658736dd194c41401949bafb2afdf47dafb /gold
parent767acc28c194ace624485f0a907e07d1e95d4ce1 (diff)
downloadgdb-8923b24c4bde41e6a15026aa1d20493fd383066c.zip
gdb-8923b24c4bde41e6a15026aa1d20493fd383066c.tar.gz
gdb-8923b24c4bde41e6a15026aa1d20493fd383066c.tar.bz2
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.
Diffstat (limited to 'gold')
-rw-r--r--gold/ChangeLog26
-rw-r--r--gold/arm.cc26
-rw-r--r--gold/layout.cc9
-rw-r--r--gold/output.cc47
-rw-r--r--gold/output.h27
-rw-r--r--gold/script-sections.cc8
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 <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
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<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.
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<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_;
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;
}