diff options
author | Doug Kwan <dougkwan@google.com> | 2010-05-23 07:43:39 +0000 |
---|---|---|
committer | Doug Kwan <dougkwan@google.com> | 2010-05-23 07:43:39 +0000 |
commit | 0439c7962a9133f00b9c836c8f211b1cc7b2211c (patch) | |
tree | af4aa52e69d35439bcc7451ec50d11935fca773d /gold/output.cc | |
parent | f434ba0309555deb86dc8b6da65ea67d588bda30 (diff) | |
download | gdb-0439c7962a9133f00b9c836c8f211b1cc7b2211c.zip gdb-0439c7962a9133f00b9c836c8f211b1cc7b2211c.tar.gz gdb-0439c7962a9133f00b9c836c8f211b1cc7b2211c.tar.bz2 |
2010-05-23 Doug Kwan <dougkwan@google.com>
* arm.cc (Arm_input_section::do_output_offset): Use convert_types
instead of a cast.
(Target_arm::apply_cortex_a8_workaround): Rewrite a conditional branch
with a direct branch, not a conditional branch, to a stub.
* merge.cc (Output_merge_base::record_input_section): New method
defintion.
(Output_merge_data::do_add_input_section): Record input section if
keeps-input-sections flag is set.
(Output_merge_string::do_add_input_section): Ditto.
* merge.h (Output_merge_base::Output_merge_base): Initialize new data
members KEEPS_INPUT_SECTIONS_, FIRST_RELOBJ_, FIRST_SHNDX_ and
INPUT_SECTIONS_.
(Output_merge_base::keeps_input_sections,
Output_merge_base::set_keeps_input_sections,
Output_merge_base::first_relobj, Output_merge_base::first_shndx): New
method definitions.
(Output_merge_base::Input_sections): New type declaration.
(Output_merge_base::input_sections_begin,
Output_merge_base::input_sections_end,
Output_merge_base::do_set_keeps_input_sections): New method definitions.
(Output_merge_base::bool keeps_input_sections_,
Output_merge_base::first_relobj_, Output_merge_base::first_shndx_,
Output_merge_base::input_sections_): New data members.
(Output_merge_data::do_set_keeps_input_sections): New method
defintion.
(Output_merge_string::do_set_keeps_input_sections): Ditto.
* output.cc (Output_section::Input_section::relobj): Move method
defintion from class declaration to here and handle merge sections.
(Output_section::Input_section::shndx): Ditto.
(Output_section::Output_section): Remove initializations of removed
data members and initialize new data member LOOKUP_MAPS_.
(Output_section::add_input_section): Set keeps-input-sections flag
for a newly created merge output section as appropriate. Adjust code
to use Output_section_lookup_maps class.
(Output_section::add_relaxed_input_section): Adjst code for lookup
maps code refactoring.
(Output_section::add_merge_input_section): Add a new parameter
KEEPS_INPUT_SECTION. Adjust code to use Output_section_lookup_maps
class. If adding input section to a newly created merge output
section fails, remove the new merge section.
(Output_section::convert_input_sections_in_list_to_relaxed_input_sections):
Adjust code for use of the Output_section_lookup_maps class.
(Output_section::find_merge_section): Ditto.
(Output_section::build_lookup_maps): New method defintion.
(Output_section::find_relaxed_input_section): Adjust code to use
Output_section_lookup_maps class.
(Output_section::get_input_sections): Export merge sections. Adjust
code to use Output_section_lookup_maps class.
(Output_section:::add_script_input_section): Adjust code to use
Output_section_lookup_maps class. Update lookup maps for merge
sections also.
(Output_section::discard_states): Use Output_section_lookup_maps.
(Output_section::restore_states): Same.
* output.h (Merge_section_properties): Move class defintion out of
Output_section.
(Output_section_lookup_maps): New class.
(Output_section::Input_section::is_merge_section): New method
defintion.
(Output_section::Input_section::relobj): Move defintion out of class
defintion. Declare method only.
(Output_section::Input_section::shndx): Ditto.
(Output_section::Input_section::output_merge_base): New method defintion.
(Output_section::Input_section::u2_.pomb): New union field.
(Output_section::Merge_section_by_properties_map,
Output_section::Output_section_data_by_input_section_map,
Output_section::Ouptut_relaxed_input_section_by_input_section_map):
Remove types.
(Output_section::add_merge_input_section): Add new parameter
KEEPS_INPUT_SECTIONS.
(Output_section::build_lookup_maps): New method declaration.
(Output_section::merge_section_map_,
Output_section::merge_section_by_properties_map_,
Output_section::relaxed_input_section_map_,
Output_section::is_relaxed_input_section_map_valid_): Remove data
members.
(Output_section::lookup_maps_): New data member.
Diffstat (limited to 'gold/output.cc')
-rw-r--r-- | gold/output.cc | 226 |
1 files changed, 156 insertions, 70 deletions
diff --git a/gold/output.cc b/gold/output.cc index 4c9776d..752a1d3 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -1749,6 +1749,42 @@ Output_section::Input_section::data_size() const return this->u2_.posd->data_size(); } +// Return the object for an input section. + +Relobj* +Output_section::Input_section::relobj() const +{ + if (this->is_input_section()) + return this->u2_.object; + else if (this->is_merge_section()) + { + gold_assert(this->u2_.pomb->first_relobj() != NULL); + return this->u2_.pomb->first_relobj(); + } + else if (this->is_relaxed_input_section()) + return this->u2_.poris->relobj(); + else + gold_unreachable(); +} + +// Return the input section index for an input section. + +unsigned int +Output_section::Input_section::shndx() const +{ + if (this->is_input_section()) + return this->shndx_; + else if (this->is_merge_section()) + { + gold_assert(this->u2_.pomb->first_relobj() != NULL); + return this->u2_.pomb->first_shndx(); + } + else if (this->is_relaxed_input_section()) + return this->u2_.poris->shndx(); + else + gold_unreachable(); +} + // Set the address and file offset. void @@ -1914,10 +1950,7 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type, is_noload_(false), tls_offset_(0), checkpoint_(NULL), - merge_section_map_(), - merge_section_by_properties_map_(), - relaxed_input_section_map_(), - is_relaxed_input_section_map_valid_(true) + lookup_maps_(new Output_section_lookup_maps) { // An unallocated section has no address. Forcing this means that // we don't need special treatment for symbols defined in debug @@ -2001,8 +2034,12 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object, && reloc_shndx == 0 && shdr.get_sh_size() > 0) { - if (this->add_merge_input_section(object, shndx, sh_flags, - entsize, addralign)) + // Keep information about merged input sections for rebuilding fast + // lookup maps if we have sections-script or we do relaxation. + bool keeps_input_sections = + have_sections_script || parameters->target().may_relax(); + if (this->add_merge_input_section(object, shndx, sh_flags, entsize, + addralign, keeps_input_sections)) { // Tell the relocation routines that they need to call the // output_offset method to determine the final address. @@ -2092,11 +2129,9 @@ Output_section::add_relaxed_input_section(Output_relaxed_input_section* poris) { Input_section inp(poris); this->add_output_section_data(&inp); - if (this->is_relaxed_input_section_map_valid_) - { - Const_section_id csid(poris->relobj(), poris->shndx()); - this->relaxed_input_section_map_[csid] = poris; - } + if (this->lookup_maps_->is_valid()) + this->lookup_maps_->add_relaxed_input_section(poris->relobj(), + poris->shndx(), poris); // For a relaxed section, we use the current data size. Linker scripts // get all the input sections, including relaxed one from an output @@ -2142,7 +2177,8 @@ Output_section::add_output_merge_section(Output_section_data* posd, bool Output_section::add_merge_input_section(Relobj* object, unsigned int shndx, uint64_t flags, uint64_t entsize, - uint64_t addralign) + uint64_t addralign, + bool keeps_input_sections) { bool is_string = (flags & elfcpp::SHF_STRINGS) != 0; @@ -2155,13 +2191,15 @@ Output_section::add_merge_input_section(Relobj* object, unsigned int shndx, gold_assert(this->checkpoint_ == NULL); // Look up merge sections by required properties. - Output_merge_base* pomb; + // Currently, we only invalidate the lookup maps in script processing + // and relaxation. We should not have done either when we reach here. + // So we assume that the lookup maps are valid to simply code. + gold_assert(this->lookup_maps_->is_valid()); Merge_section_properties msp(is_string, entsize, addralign); - Merge_section_by_properties_map::const_iterator p = - this->merge_section_by_properties_map_.find(msp); - if (p != this->merge_section_by_properties_map_.end()) + Output_merge_base* pomb = this->lookup_maps_->find_merge_section(msp); + bool is_new = false; + if (pomb != NULL) { - pomb = p->second; gold_assert(pomb->is_string() == is_string && pomb->entsize() == entsize && pomb->addralign() == addralign); @@ -2188,22 +2226,36 @@ Output_section::add_merge_input_section(Relobj* object, unsigned int shndx, return false; } } - // Add new merge section to this output section and link merge - // section properties to new merge section in map. - this->add_output_merge_section(pomb, is_string, entsize); - this->merge_section_by_properties_map_[msp] = pomb; + // If we need to do script processing or relaxation, we need to keep + // the original input sections to rebuild the fast lookup maps. + if (keeps_input_sections) + pomb->set_keeps_input_sections(); + is_new = true; } if (pomb->add_input_section(object, shndx)) { + // Add new merge section to this output section and link merge + // section properties to new merge section in map. + if (is_new) + { + this->add_output_merge_section(pomb, is_string, entsize); + this->lookup_maps_->add_merge_section(msp, pomb); + } + // Add input section to new merge section and link input section to new // merge section in map. - Const_section_id csid(object, shndx); - this->merge_section_map_[csid] = pomb; + this->lookup_maps_->add_merge_input_section(object, shndx, pomb); return true; } else - return false; + { + // If add_input_section failed, delete new merge section to avoid + // exporting empty merge sections in Output_section::get_input_section. + if (is_new) + delete pomb; + return false; + } } // Build a relaxation map to speed up relaxation of existing input sections. @@ -2298,12 +2350,12 @@ Output_section::convert_input_sections_to_relaxed_sections( &this->input_sections_); // Update fast look-up map. - if (this->is_relaxed_input_section_map_valid_) + if (this->lookup_maps_->is_valid()) for (size_t i = 0; i < relaxed_sections.size(); ++i) { Output_relaxed_input_section* poris = relaxed_sections[i]; - Const_section_id csid(poris->relobj(), poris->shndx()); - this->relaxed_input_section_map_[csid] = poris; + this->lookup_maps_->add_relaxed_input_section(poris->relobj(), + poris->shndx(), poris); } } @@ -2348,17 +2400,47 @@ Output_section_data* Output_section::find_merge_section(const Relobj* object, unsigned int shndx) const { - Const_section_id csid(object, shndx); - Output_section_data_by_input_section_map::const_iterator p = - this->merge_section_map_.find(csid); - if (p != this->merge_section_map_.end()) + if (!this->lookup_maps_->is_valid()) + this->build_lookup_maps(); + return this->lookup_maps_->find_merge_section(object, shndx); +} + +// Build the lookup maps for merge and relaxed sections. This is needs +// to be declared as a const methods so that it is callable with a const +// Output_section pointer. The method only updates states of the maps. + +void +Output_section::build_lookup_maps() const +{ + this->lookup_maps_->clear(); + for (Input_section_list::const_iterator p = this->input_sections_.begin(); + p != this->input_sections_.end(); + ++p) { - Output_section_data* posd = p->second; - gold_assert(posd->is_merge_section_for(object, shndx)); - return posd; + if (p->is_merge_section()) + { + Output_merge_base* pomb = p->output_merge_base(); + Merge_section_properties msp(pomb->is_string(), pomb->entsize(), + pomb->addralign()); + this->lookup_maps_->add_merge_section(msp, pomb); + for (Output_merge_base::Input_sections::const_iterator is = + pomb->input_sections_begin(); + is != pomb->input_sections_end(); + ++is) + { + const Const_section_id& csid = *is; + this->lookup_maps_->add_merge_input_section(csid.first, + csid.second, pomb); + } + + } + else if (p->is_relaxed_input_section()) + { + Output_relaxed_input_section* poris = p->relaxed_input_section(); + this->lookup_maps_->add_relaxed_input_section(poris->relobj(), + poris->shndx(), poris); + } } - else - return NULL; } // Find an relaxed input section corresponding to an input section @@ -2368,31 +2450,9 @@ const Output_relaxed_input_section* Output_section::find_relaxed_input_section(const Relobj* object, unsigned int shndx) const { - // Be careful that the map may not be valid due to input section export - // to scripts or a check-point restore. - if (!this->is_relaxed_input_section_map_valid_) - { - // Rebuild the map as needed. - this->relaxed_input_section_map_.clear(); - for (Input_section_list::const_iterator p = this->input_sections_.begin(); - p != this->input_sections_.end(); - ++p) - if (p->is_relaxed_input_section()) - { - Const_section_id csid(p->relobj(), p->shndx()); - this->relaxed_input_section_map_[csid] = - p->relaxed_input_section(); - } - this->is_relaxed_input_section_map_valid_ = true; - } - - Const_section_id csid(object, shndx); - Output_relaxed_input_section_by_input_section_map::const_iterator p = - this->relaxed_input_section_map_.find(csid); - if (p != this->relaxed_input_section_map_.end()) - return p->second; - else - return NULL; + if (!this->lookup_maps_->is_valid()) + this->build_lookup_maps(); + return this->lookup_maps_->find_relaxed_input_section(object, shndx); } // Given an address OFFSET relative to the start of input section @@ -3052,8 +3112,8 @@ Output_section::get_input_sections( && !this->checkpoint_->input_sections_saved()) this->checkpoint_->save_input_sections(); - // Invalidate the relaxed input section map. - this->is_relaxed_input_section_map_valid_ = false; + // Invalidate fast look-up maps. + this->lookup_maps_->invalidate(); uint64_t orig_address = address; @@ -3064,7 +3124,9 @@ Output_section::get_input_sections( p != this->input_sections_.end(); ++p) { - if (p->is_input_section() || p->is_relaxed_input_section()) + if (p->is_input_section() + || p->is_relaxed_input_section() + || p->is_merge_section()) input_sections->push_back(*p); else { @@ -3121,6 +3183,30 @@ Output_section::add_script_input_section(const Input_section& sis) + data_size); this->input_sections_.push_back(sis); + + // Update fast lookup maps if necessary. + if (this->lookup_maps_->is_valid()) + { + if (sis.is_merge_section()) + { + Output_merge_base* pomb = sis.output_merge_base(); + Merge_section_properties msp(pomb->is_string(), pomb->entsize(), + pomb->addralign()); + this->lookup_maps_->add_merge_section(msp, pomb); + for (Output_merge_base::Input_sections::const_iterator p = + pomb->input_sections_begin(); + p != pomb->input_sections_end(); + ++p) + this->lookup_maps_->add_merge_input_section(p->first, p->second, + pomb); + } + else if (sis.is_relaxed_input_section()) + { + Output_relaxed_input_section* poris = sis.relaxed_input_section(); + this->lookup_maps_->add_relaxed_input_section(poris->relobj(), + poris->shndx(), poris); + } + } } // Save states for relaxation. @@ -3146,9 +3232,9 @@ Output_section::discard_states() 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; + // Simply invalidate the fast lookup maps since we do not keep + // track of them. + this->lookup_maps_->invalidate(); } void @@ -3180,9 +3266,9 @@ Output_section::restore_states() this->attached_input_sections_are_sorted_ = checkpoint->attached_input_sections_are_sorted(); - // Simply invalidate the relaxed input section map since we do not keep - // track of it. - this->is_relaxed_input_section_map_valid_ = false; + // Simply invalidate the fast lookup maps since we do not keep + // track of them. + this->lookup_maps_->invalidate(); } // Update the section offsets of input sections in this. This is required if |