[PATCH][GOLD] Adjust section offset in an output section during relaxation.
Doug Kwan (關振德)
dougkwan@google.com
Fri Jan 22 22:24:00 GMT 2010
Hi,
This mainly fixes a problem in which section offsets of input
sections in an output section are not updated during relaxation. If
one of the input sections is relaxed, all the input sections after
that need to have their section offsets updated. I took a simpler
approach of updating all the section offsets. This patch also
contains a few unrelated changes that are used by the EXIDX code. I
renamed Output_section::add_input_section_for_script() to
Output_section::add_simple_input_section() since it is also used by
the EXIDX fix-up and the method is not really for scripts only. I
also added Output_section::discard_states() method to discard the
currently saved states. The EXIDX fix-up needs to modify many saved
states. So it is easier to just discard the saved states and re-take
another snapshot after the fix-up.
-Doug
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.
-------------- next part --------------
Index: gold/arm.cc
===================================================================
RCS file: /cvs/src/src/gold/arm.cc,v
retrieving revision 1.63
diff -u -u -p -r1.63 arm.cc
--- gold/arm.cc 22 Jan 2010 19:43:00 -0000 1.63
+++ gold/arm.cc 22 Jan 2010 21:59:37 -0000
@@ -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: gold/layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.163
diff -u -u -p -r1.163 layout.cc
--- gold/layout.cc 8 Jan 2010 21:07:34 -0000 1.163
+++ gold/layout.cc 22 Jan 2010 21:59:37 -0000
@@ -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: gold/output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.117
diff -u -u -p -r1.117 output.cc
--- gold/output.cc 20 Jan 2010 17:29:52 -0000 1.117
+++ gold/output.cc 22 Jan 2010 21:59:37 -0000
@@ -1890,6 +1890,7 @@ Output_section::Output_section(const cha
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_sc
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: gold/output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.98
diff -u -u -p -r1.98 output.h
--- gold/output.h 20 Jan 2010 17:29:52 -0000 1.98
+++ gold/output.h 22 Jan 2010 21:59:37 -0000
@@ -2718,10 +2718,10 @@ class Output_section : public Output_dat
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_dat
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_dat
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_dat
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: gold/script-sections.cc
===================================================================
RCS file: /cvs/src/src/gold/script-sections.cc,v
retrieving revision 1.29
diff -u -u -p -r1.29 script-sections.cc
--- gold/script-sections.cc 29 Dec 2009 00:31:48 -0000 1.29
+++ gold/script-sections.cc 22 Jan 2010 21:59:37 -0000
@@ -1409,9 +1409,9 @@ Output_section_element_input::set_sectio
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_addre
}
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;
}
More information about the Binutils
mailing list