diff options
author | Doug Kwan <dougkwan@google.com> | 2009-09-18 01:10:38 +0000 |
---|---|---|
committer | Doug Kwan <dougkwan@google.com> | 2009-09-18 01:10:38 +0000 |
commit | 20e6d0d602ee8907dd3b97bc1ffdeb9441a2314a (patch) | |
tree | 5bd14498c4fd271dc82884e007ec14fa04aaa582 /gold/script-sections.cc | |
parent | 5e445df679225ddbcd707c65ebb1c05af08536fc (diff) | |
download | binutils-gdb-20e6d0d602ee8907dd3b97bc1ffdeb9441a2314a.tar.gz |
2009-09-17 Doug Kwan <dougkwan@google.com>
* debug.h (DEBUG_RELAXATION): New constant.
(DEBUG_ALL): Add DEBUG_RELAXATION.
(debug_string_to_enum): Add relaxation debug option.
* layout.cc
(Layout::Relaxation_debug_check::check_output_data_for_reset_values,
Layout::Relaxation_debug_check::read_sections,
Layout::Relaxation_debug_check::read_sections): New method definitions.
(Layout::Layout): Initialize data members
record_output_section_data_from_scrips_,
script_output_section_data_list_ and relaxation_debug_check_.
(Layout::save_segments, Layout::restore_segments,
Layout::clean_up_after_relaxation, Layout::prepare_for_relaxation,
Layout::relaxation_loop_body): New method definitions.
(Layout::finalize): Support relaxation. Move section layout code to
Layout::relaxation_loop_body.
(Layout::set_asection_address_from_script): Move code for orphan
section placement out.
(Layout::place_orphan_sections_in_script): New method definition.
* layout.h (Output_segment_headers, Output_file_header):
New forward class declarations.
(Layout::~Layout): Define.
(Layout::new_output_section_data_from_script): New method definition.
(Layout::place_orphan_sections_in_script): New method declaration.
(Layout::Segment_states): New type declaration.
(Layout::save_segments, Layout::restore_segments,
Layout::clean_up_after_relaxation, Layout::prepare_for_relaxation,
Layout::relaxation_loop_body): New method declarations.
(Layout::Output_section_data_list): New type declaration.
(Layout::Relaxation_debug_check): New class definition.
(Layout::record_output_section_data_from_script_,
Layout::script_output_section_data_list_, Layout::segment_states_,
Layout::relaxation_debug_check_): New data members.
* output.cc: (Output_section_headers::do_size): New method definition.
(Output_section_headers::Output_section_headers): Move size
computation to Output_section_headers::do_size.
(Output_segment_headers::do_size): New method definition.
(Output_file_header::Output_file_header): Move size computation to
Output_file_header::do_size and call it.
(Output_file_header::do_size): New method definition.
(Output_data_group::Output_data_group): Adjust call to
Output_section_data.
(Output_data_dynamic::set_final_data_size): Add DT_NULL tag only once.
(Output_symtab_xindex::do_write): Add array bound check.
(Output_section::Input_section::print_to_mapfile): Handle
RELAXED_INPUT_SECTION_CODE.
(Output_section::Output_section): Initialize data member checkpoint_.
(Output_section::~Output_section): Delete checkpoint object pointed
by checkpoint_.
(Output_section::add_input_section): Always add an Input_section if
relaxing.
(Output_section::add_merge_input_section): Add assert.
(Output_section::relax_input_section): New method definition.
(Output_section::set_final_data_size): Set load address to zero for
an unallocated section.
(Output_section::do_address_and_file_offset_have_reset_values):
New method definition.
(Output_section::Input_section_sort_enty::Input_section_sort_enty):
Handle relaxed input section.
(Output_section::sort_attached_input_sections): Checkpoint input
section list lazily.
(Output_section::get_input_sections): Change type of input_sections to
list of Simple_input_section pointers. Checkpoint input section list
lazily. Also handle relaxed input sections.
(Output_section::add_input_section_for_script): Take a reference to
a Simple_input_section object instead of Relobj pointer and section
index as parameter. Handle relaxed input sections.
(Output_section::save_states, Output_section::restore_states): New
method definitions.
* output.h (Output_data::Output_data): Initialize is_data_size_fixed_.
(Output_data::is_data_size_fixed): New method definition.
(Output_data::reset_addresss_and_file_offset): Do not reset data size
if it is fixed.
(Output_data::address_and_file_offset_have_reset_values): New method
definition.
(Output_data::do_address_and_file_offset_have_reset_values): New method
definition.
(Output_data::set_data_size): Check that data size is not fixed.
(Output_data::fix_data_size): New method definition.
(Output_data::is_data_size_fixed_): New data member.
(Output_section_headers::set_final_data_size): New method definition.
(Output_section_headers::do_size): New method declaration.
(Output_segment_headers::set_final_data_size): New method definition.
(Output_segment_headers::do_size): New method declaration.
(Output_file_header::set_final_data_size)::New method definition.
(Output_file_header::do_size)::New method declaration.
(Output_section_data::Output_section_data): Add new parameter
is_data_size_fixed and use it to fix data size.
(Output_data_const::Output_data_const): Adjust call to base class
constructor and fix data size.
(Output_data_const_buffer::Output_data_const_buffer): Adjust call to
base class constructor and fix data size.
(Output_data_fixed_space::Output_data_fixed_space): Adjust call to
base class constructor and fix data size.
(Output_data_zero_fill::Output_data_zero_fill): Adjust call to base
class constructor and fix data size.
(Output_data_group::set_final_data_size): New method definition.
(Output_data_dynamic::Dynamic_entry::tag): New method definition.
(Output_symtab_xindex::Output_symtab_xindex): Adjust call to base
class constructor and fix data size.
(Output_relaxed_input_section): New class definition.
(Output_section::Simple_input_section): New class definition.
(Output_section::get_input_sections): Adjust parameter list.
(Output_section::add_input_section_for_script): Same.
(Output_section::save_states, Output_section::restore_states,
Output_section::do_address_and_file_offset_have_reset_values,
(Output_section::Input_section::Input_section): Handle
RELAXED_INPUT_SECTION_CODE. Add new overload for
Output_relaxed_input_section.
(Output_section::Input_section::is_input_section,
Output_section::Input_section::set_output_section): Handle relaxed
input section.
(Output_section::Input_section::is_relaxed_input_section,
Output_section::Input_section::output_section_data,
Output_section::Input_section::relaxed_input_section): New method
definitions.
(Output_section::Input_section::RELAXED_INPUT_SECTION_CODE): New enum
value.
(Output_section::Input_section::u1_): Update comments.
(Output_section::Input_section::u2_): Add new union member poris.
(Output_section::Checkpoint_output_section): New classs definition.
(Output_section::relax_input_section): New method declaration.
(Output_section::checkpoint_): New data member.
(Output_segment): Update comments.
(Output_segment::Output_segment): Un-privatize copy constructor.
(Output_segment::operator=): Un-privatize.
* script-sections.cc (Output_section_element::Input_section_list):
Change element type to Output_section::Simple_input_section.
(Output_section_element_dot_assignment::set_section_addresses):
Register output section data for relaxation clean up.
(Output_data_exression::Output_data_expression): Adjust call to base
constructor to fix data size.
(Output_section_element_data::set_section_addresses): Register
Output_data_expression object for relaxation clean up.
(struct Input_section_info): Replace Relobj pointer and section index
pair with Output_section::Simple_input_section and Convert struct to a
class.
(Input_section_sorter::operator()): Adjust access to
Input_section_info data member to use accessors.
(Output_section_element_input::set_section_addresses): Use layout
parameter. Adjust code to use Output_section::Simple_input_section
and Input_secction_info classes. Register filler for relaxation
clean up.
(Orphan_output_section::set_section_addresses): Replace Relobj pointer
and section index pair with Output_section::Simple_input_section
class. Adjust code accordingly.
(Phdrs_element::release_segment): New method definition.
(Script_sections::attach_sections_using_phdrs_clause): Do not modify
segment list.
(Script_sections::release_segments): New method definition.
* gold/script-sections.h (Script_sections::release_segments): New
method declaration.
* gold/target.h (Target::may_relax, Target::relax,
Target::do_may_relax, Target::do_relax): New method definitions.
Diffstat (limited to 'gold/script-sections.cc')
-rw-r--r-- | gold/script-sections.cc | 194 |
1 files changed, 139 insertions, 55 deletions
diff --git a/gold/script-sections.cc b/gold/script-sections.cc index 7396b3bf248..d6e2b7279e8 100644 --- a/gold/script-sections.cc +++ b/gold/script-sections.cc @@ -524,7 +524,7 @@ class Output_section_element { public: // A list of input sections. - typedef std::list<std::pair<Relobj*, unsigned int> > Input_section_list; + typedef std::list<Output_section::Simple_input_section> Input_section_list; Output_section_element() { } @@ -701,6 +701,7 @@ Output_section_element_dot_assignment::set_section_addresses( posd = new Output_data_const(this_fill, 0); } output_section->add_output_section_data(posd); + layout->new_output_section_data_from_script(posd); } *dot_value = next_dot; } @@ -736,7 +737,7 @@ class Output_data_expression : public Output_section_data Output_data_expression(int size, bool is_signed, Expression* val, const Symbol_table* symtab, const Layout* layout, uint64_t dot_value, Output_section* dot_section) - : Output_section_data(size, 0), + : Output_section_data(size, 0, true), is_signed_(is_signed), val_(val), symtab_(symtab), layout_(layout), dot_value_(dot_value), dot_section_(dot_section) { } @@ -877,13 +878,11 @@ Output_section_element_data::set_section_addresses( Input_section_list*) { gold_assert(os != NULL); - os->add_output_section_data(new Output_data_expression(this->size_, - this->is_signed_, - this->val_, - symtab, - layout, - *dot_value, - *dot_section)); + Output_data_expression* expression = + new Output_data_expression(this->size_, this->is_signed_, this->val_, + symtab, layout, *dot_value, *dot_section); + os->add_output_section_data(expression); + layout->new_output_section_data_from_script(expression); *dot_value += this->size_; } @@ -1169,13 +1168,68 @@ Output_section_element_input::match_name(const char* file_name, // Information we use to sort the input sections. -struct Input_section_info +class Input_section_info { - Relobj* relobj; - unsigned int shndx; - std::string section_name; - uint64_t size; - uint64_t addralign; + public: + Input_section_info(const Output_section::Simple_input_section& input_section) + : input_section_(input_section), section_name_(), + size_(0), addralign_(1) + { } + + // Return the simple input section. + const Output_section::Simple_input_section& + input_section() const + { return this->input_section_; } + + // Return the object. + Relobj* + relobj() const + { return this->input_section_.relobj(); } + + // Return the section index. + unsigned int + shndx() + { return this->input_section_.shndx(); } + + // Return the section name. + const std::string& + section_name() const + { return this->section_name_; } + + // Set the section name. + void + set_section_name(const std::string name) + { this->section_name_ = name; } + + // Return the section size. + uint64_t + size() const + { return this->size_; } + + // Set the section size. + void + set_size(uint64_t size) + { this->size_ = size; } + + // Return the address alignment. + uint64_t + addralign() const + { return this->addralign_; } + + // Set the address alignment. + void + set_addralign(uint64_t addralign) + { this->addralign_ = addralign; } + + private: + // Input section, can be a relaxed section. + Output_section::Simple_input_section input_section_; + // Name of the section. + std::string section_name_; + // Section size. + uint64_t size_; + // Address alignment. + uint64_t addralign_; }; // A class to sort the input sections. @@ -1202,22 +1256,22 @@ Input_section_sorter::operator()(const Input_section_info& isi1, if (this->section_sort_ == SORT_WILDCARD_BY_NAME || this->section_sort_ == SORT_WILDCARD_BY_NAME_BY_ALIGNMENT || (this->section_sort_ == SORT_WILDCARD_BY_ALIGNMENT_BY_NAME - && isi1.addralign == isi2.addralign)) + && isi1.addralign() == isi2.addralign())) { - if (isi1.section_name != isi2.section_name) - return isi1.section_name < isi2.section_name; + if (isi1.section_name() != isi2.section_name()) + return isi1.section_name() < isi2.section_name(); } if (this->section_sort_ == SORT_WILDCARD_BY_ALIGNMENT || this->section_sort_ == SORT_WILDCARD_BY_NAME_BY_ALIGNMENT || this->section_sort_ == SORT_WILDCARD_BY_ALIGNMENT_BY_NAME) { - if (isi1.addralign != isi2.addralign) - return isi1.addralign < isi2.addralign; + if (isi1.addralign() != isi2.addralign()) + return isi1.addralign() < isi2.addralign(); } if (this->filename_sort_ == SORT_WILDCARD_BY_NAME) { - if (isi1.relobj->name() != isi2.relobj->name()) - return isi1.relobj->name() < isi2.relobj->name(); + if (isi1.relobj()->name() != isi2.relobj()->name()) + return (isi1.relobj()->name() < isi2.relobj()->name()); } // Otherwise we leave them in the same order. @@ -1231,7 +1285,7 @@ Input_section_sorter::operator()(const Input_section_info& isi1, void Output_section_element_input::set_section_addresses( Symbol_table*, - Layout*, + Layout* layout, Output_section* output_section, uint64_t subalign, uint64_t* dot_value, @@ -1255,25 +1309,29 @@ Output_section_element_input::set_section_addresses( Input_section_list::iterator p = input_sections->begin(); while (p != input_sections->end()) { + Relobj* relobj = p->relobj(); + unsigned int shndx = p->shndx(); + Input_section_info isi(*p); + // Calling section_name and section_addralign is not very // efficient. - Input_section_info isi; - isi.relobj = p->first; - isi.shndx = p->second; // Lock the object so that we can get information about the // section. This is OK since we know we are single-threaded // here. { const Task* task = reinterpret_cast<const Task*>(-1); - Task_lock_obj<Object> tl(task, p->first); - - isi.section_name = p->first->section_name(p->second); - isi.size = p->first->section_size(p->second); - isi.addralign = p->first->section_addralign(p->second); + Task_lock_obj<Object> tl(task, relobj); + + isi.set_section_name(relobj->section_name(shndx)); + if (p->is_relaxed_input_section()) + isi.set_size(p->relaxed_input_section()->data_size()); + else + isi.set_size(relobj->section_size(shndx)); + isi.set_addralign(relobj->section_addralign(shndx)); } - if (!this->match_file_name(isi.relobj->name().c_str())) + if (!this->match_file_name(relobj->name().c_str())) ++p; else if (this->input_section_patterns_.empty()) { @@ -1287,7 +1345,7 @@ Output_section_element_input::set_section_addresses( { const Input_section_pattern& isp(this->input_section_patterns_[i]); - if (match(isi.section_name.c_str(), isp.pattern.c_str(), + if (match(isi.section_name().c_str(), isp.pattern.c_str(), isp.pattern_is_wildcard)) break; } @@ -1327,7 +1385,7 @@ Output_section_element_input::set_section_addresses( p != matching_sections[i].end(); ++p) { - uint64_t this_subalign = p->addralign; + uint64_t this_subalign = p->addralign(); if (this_subalign < subalign) this_subalign = subalign; @@ -1340,14 +1398,14 @@ Output_section_element_input::set_section_addresses( std::string this_fill = this->get_fill_string(fill, length); Output_section_data* posd = new Output_data_const(this_fill, 0); output_section->add_output_section_data(posd); + layout->new_output_section_data_from_script(posd); } - output_section->add_input_section_for_script(p->relobj, - p->shndx, - p->size, + output_section->add_input_section_for_script(p->input_section(), + p->size(), this_subalign); - *dot_value = address + p->size; + *dot_value = address + p->size(); } } @@ -2202,7 +2260,7 @@ Orphan_output_section::set_section_addresses(Symbol_table*, Layout*, uint64_t* dot_value, uint64_t* load_address) { - typedef std::list<std::pair<Relobj*, unsigned int> > Input_section_list; + typedef std::list<Output_section::Simple_input_section> Input_section_list; bool have_load_address = *load_address != *dot_value; @@ -2231,14 +2289,16 @@ Orphan_output_section::set_section_addresses(Symbol_table*, Layout*, // object. { const Task* task = reinterpret_cast<const Task*>(-1); - Task_lock_obj<Object> tl(task, p->first); - addralign = p->first->section_addralign(p->second); - size = p->first->section_size(p->second); + Task_lock_obj<Object> tl(task, p->relobj()); + addralign = p->relobj()->section_addralign(p->shndx()); + if (p->is_relaxed_input_section()) + size = p->relaxed_input_section()->data_size(); + else + size = p->relobj()->section_size(p->shndx()); } address = align_address(address, addralign); - this->os_->add_input_section_for_script(p->first, p->second, size, - addralign); + this->os_->add_input_section_for_script(*p, size, addralign); address += size; } @@ -2333,6 +2393,11 @@ class Phdrs_element segment() { return this->segment_; } + // Release the segment. + void + release_segment() + { this->segment_ = NULL; } + // Set the segment flags if appropriate. void set_flags_if_valid() @@ -3165,12 +3230,15 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout) // Output sections in the script which do not list segments are // attached to the same set of segments as the immediately preceding // output section. + String_list* phdr_names = NULL; + bool load_segments_only = false; for (Sections_elements::const_iterator p = this->sections_elements_->begin(); p != this->sections_elements_->end(); ++p) { bool orphan; + String_list* old_phdr_names = phdr_names; Output_section* os = (*p)->allocate_to_segment(&phdr_names, &orphan); if (os == NULL) continue; @@ -3181,6 +3249,11 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout) continue; } + // We see a list of segments names. Disable PT_LOAD segment only + // filtering. + if (old_phdr_names != phdr_names) + load_segments_only = false; + // If this is an orphan section--one that was not explicitly // mentioned in the linker script--then it should not inherit // any segment type other than PT_LOAD. Otherwise, e.g., the @@ -3189,17 +3262,9 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout) // we trust the linker script. if (orphan) { - String_list::iterator q = phdr_names->begin(); - while (q != phdr_names->end()) - { - Name_to_segment::const_iterator r = name_to_segment.find(*q); - // We give errors about unknown segments below. - if (r == name_to_segment.end() - || r->second->type() == elfcpp::PT_LOAD) - ++q; - else - q = phdr_names->erase(q); - } + // Enable PT_LOAD segments only filtering until we see another + // list of segment names. + load_segments_only = true; } bool in_load_segment = false; @@ -3212,6 +3277,10 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout) gold_error(_("no segment %s"), q->c_str()); else { + if (load_segments_only + && r->second->type() != elfcpp::PT_LOAD) + continue; + elfcpp::Elf_Word seg_flags = Layout::section_flags_to_segment(os->flags()); r->second->add_output_section(os, seg_flags); @@ -3366,6 +3435,21 @@ Script_sections::get_output_section_info(const char* name, uint64_t* address, return false; } +// Release all Output_segments. This remove all pointers to all +// Output_segments. + +void +Script_sections::release_segments() +{ + if (this->saw_phdrs_clause()) + { + for (Phdrs_elements::const_iterator p = this->phdrs_elements_->begin(); + p != this->phdrs_elements_->end(); + ++p) + (*p)->release_segment(); + } +} + // Print the SECTIONS clause to F for debugging. void |