diff options
Diffstat (limited to 'binutils-2.19/gold/output.h')
-rw-r--r-- | binutils-2.19/gold/output.h | 789 |
1 files changed, 425 insertions, 364 deletions
diff --git a/binutils-2.19/gold/output.h b/binutils-2.19/gold/output.h index 8088565..da321b6 100644 --- a/binutils-2.19/gold/output.h +++ b/binutils-2.19/gold/output.h @@ -2314,6 +2314,188 @@ class Output_relaxed_input_section : public Output_section_data_build unsigned int shndx_; }; +// This class describes properties of merge data sections. It is used +// as a key type for maps. +class Merge_section_properties +{ + public: + Merge_section_properties(bool is_string, uint64_t entsize, + uint64_t addralign) + : is_string_(is_string), entsize_(entsize), addralign_(addralign) + { } + + // Whether this equals to another Merge_section_properties MSP. + bool + eq(const Merge_section_properties& msp) const + { + return ((this->is_string_ == msp.is_string_) + && (this->entsize_ == msp.entsize_) + && (this->addralign_ == msp.addralign_)); + } + + // Compute a hash value for this using 64-bit FNV-1a hash. + size_t + hash_value() const + { + uint64_t h = 14695981039346656037ULL; // FNV offset basis. + uint64_t prime = 1099511628211ULL; + h = (h ^ static_cast<uint64_t>(this->is_string_)) * prime; + h = (h ^ static_cast<uint64_t>(this->entsize_)) * prime; + h = (h ^ static_cast<uint64_t>(this->addralign_)) * prime; + return h; + } + + // Functors for associative containers. + struct equal_to + { + bool + operator()(const Merge_section_properties& msp1, + const Merge_section_properties& msp2) const + { return msp1.eq(msp2); } + }; + + struct hash + { + size_t + operator()(const Merge_section_properties& msp) const + { return msp.hash_value(); } + }; + + private: + // Whether this merge data section is for strings. + bool is_string_; + // Entsize of this merge data section. + uint64_t entsize_; + // Address alignment. + uint64_t addralign_; +}; + +// This class is used to speed up look up of special input sections in an +// Output_section. + +class Output_section_lookup_maps +{ + public: + Output_section_lookup_maps() + : is_valid_(true), merge_sections_by_properties_(), + merge_sections_by_id_(), relaxed_input_sections_by_id_() + { } + + // Whether the maps are valid. + bool + is_valid() const + { return this->is_valid_; } + + // Invalidate the maps. + void + invalidate() + { this->is_valid_ = false; } + + // Clear the maps. + void + clear() + { + this->merge_sections_by_properties_.clear(); + this->merge_sections_by_id_.clear(); + this->relaxed_input_sections_by_id_.clear(); + // A cleared map is valid. + this->is_valid_ = true; + } + + // Find a merge section by merge section properties. Return NULL if none + // is found. + Output_merge_base* + find_merge_section(const Merge_section_properties& msp) const + { + gold_assert(this->is_valid_); + Merge_sections_by_properties::const_iterator p = + this->merge_sections_by_properties_.find(msp); + return p != this->merge_sections_by_properties_.end() ? p->second : NULL; + } + + // Find a merge section by section ID of a merge input section. Return NULL + // if none is found. + Output_merge_base* + find_merge_section(const Object* object, unsigned int shndx) const + { + gold_assert(this->is_valid_); + Merge_sections_by_id::const_iterator p = + this->merge_sections_by_id_.find(Const_section_id(object, shndx)); + return p != this->merge_sections_by_id_.end() ? p->second : NULL; + } + + // Add a merge section pointed by POMB with properties MSP. + void + add_merge_section(const Merge_section_properties& msp, + Output_merge_base* pomb) + { + std::pair<Merge_section_properties, Output_merge_base*> value(msp, pomb); + std::pair<Merge_sections_by_properties::iterator, bool> result = + this->merge_sections_by_properties_.insert(value); + gold_assert(value.second); + } + + // Add a mapping from a merged input section in OBJECT with index SHNDX + // to a merge output section pointed by POMB. + void + add_merge_input_section(const Object* object, unsigned int shndx, + Output_merge_base* pomb) + { + Const_section_id csid(object, shndx); + std::pair<Const_section_id, Output_merge_base*> value(csid, pomb); + std::pair<Merge_sections_by_id::iterator, bool> result = + this->merge_sections_by_id_.insert(value); + gold_assert(value.second); + } + + // Find a relaxed input section of OBJECT with index SHNDX. + Output_relaxed_input_section* + find_relaxed_input_section(const Object* object, unsigned int shndx) const + { + gold_assert(this->is_valid_); + Relaxed_input_sections_by_id::const_iterator p = + this->relaxed_input_sections_by_id_.find(Const_section_id(object, shndx)); + return p != this->relaxed_input_sections_by_id_.end() ? p->second : NULL; + } + + // Add a relaxed input section pointed by POMB and whose original input + // section is in OBJECT with index SHNDX. + void + add_relaxed_input_section(const Relobj* relobj, unsigned int shndx, + Output_relaxed_input_section* poris) + { + Const_section_id csid(relobj, shndx); + std::pair<Const_section_id, Output_relaxed_input_section*> + value(csid, poris); + std::pair<Relaxed_input_sections_by_id::iterator, bool> result = + this->relaxed_input_sections_by_id_.insert(value); + gold_assert(value.second); + } + + private: + typedef Unordered_map<Const_section_id, Output_merge_base*, + Const_section_id_hash> + Merge_sections_by_id; + + typedef Unordered_map<Merge_section_properties, Output_merge_base*, + Merge_section_properties::hash, + Merge_section_properties::equal_to> + Merge_sections_by_properties; + + typedef Unordered_map<Const_section_id, Output_relaxed_input_section*, + Const_section_id_hash> + Relaxed_input_sections_by_id; + + // Whether this is valid + bool is_valid_; + // Merge sections by merge section properties. + Merge_sections_by_properties merge_sections_by_properties_; + // Merge sections by section IDs. + Merge_sections_by_id merge_sections_by_id_; + // Relaxed sections by section IDs. + Relaxed_input_sections_by_id relaxed_input_sections_by_id_; +}; + // An output section. We don't expect to have too many output // sections, so we don't bother to do a template on the size. @@ -2766,263 +2948,6 @@ class Output_section : public Output_data // The next few calls are for linker script support. - // We need to export the input sections to linker scripts. Previously - // we export a pair of Relobj pointer and section index. We now need to - // handle relaxed input sections as well. So we use this class. - class Simple_input_section - { - private: - static const unsigned int invalid_shndx = static_cast<unsigned int>(-1); - - public: - Simple_input_section(Relobj *relobj, unsigned int shndx) - : shndx_(shndx) - { - gold_assert(shndx != invalid_shndx); - this->u_.relobj = relobj; - } - - Simple_input_section(Output_relaxed_input_section* section) - : shndx_(invalid_shndx) - { this->u_.relaxed_input_section = section; } - - // Whether this is a relaxed section. - bool - is_relaxed_input_section() const - { return this->shndx_ == invalid_shndx; } - - // Return object of an input section. - Relobj* - relobj() const - { - return ((this->shndx_ != invalid_shndx) - ? this->u_.relobj - : this->u_.relaxed_input_section->relobj()); - } - - // Return index of an input section. - unsigned int - shndx() const - { - return ((this->shndx_ != invalid_shndx) - ? this->shndx_ - : this->u_.relaxed_input_section->shndx()); - } - - // Return the Output_relaxed_input_section object of a relaxed section. - Output_relaxed_input_section* - relaxed_input_section() const - { - gold_assert(this->shndx_ == invalid_shndx); - return this->u_.relaxed_input_section; - } - - private: - // Pointer to either an Relobj or an Output_relaxed_input_section. - union - { - Relobj* relobj; - Output_relaxed_input_section* relaxed_input_section; - } u_; - // Section index for an non-relaxed section or invalid_shndx for - // a relaxed section. - unsigned int shndx_; - }; - - // Store the list of input sections for this Output_section into the - // list passed in. This removes the input sections, leaving only - // any Output_section_data elements. This returns the size of those - // Output_section_data elements. ADDRESS is the address of this - // output section. FILL is the fill value to use, in case there are - // any spaces between the remaining Output_section_data elements. - uint64_t - get_input_sections(uint64_t address, const std::string& fill, - std::list<Simple_input_section>*); - - // Add a simple input section. - void - 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 - set_current_data_size(off_t size) - { this->set_current_data_size_for_child(size); } - - // Get the current size of the output section. - off_t - current_data_size() const - { return this->current_data_size_for_child(); } - - // End of linker script support. - - // Save states before doing section layout. - // This is used for relaxation. - void - save_states(); - - // Restore states prior to section layout. - void - restore_states(); - - // Discard states. - void - discard_states(); - - // Convert existing input sections to relaxed input sections. - void - convert_input_sections_to_relaxed_sections( - const std::vector<Output_relaxed_input_section*>& sections); - - // Find a relaxed input section to an input section in OBJECT - // with index SHNDX. Return NULL if none is found. - 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(); - - // Whether this is a NOLOAD section. - bool - is_noload() const - { return this->is_noload_; } - - // Set NOLOAD flag. - void - set_is_noload() - { this->is_noload_ = true; } - - // Print merge statistics to stderr. - void - print_merge_stats(); - - protected: - // Return the output section--i.e., the object itself. - Output_section* - do_output_section() - { return this; } - - const Output_section* - do_output_section() const - { return this; } - - // Return the section index in the output file. - unsigned int - do_out_shndx() const - { - gold_assert(this->out_shndx_ != -1U); - return this->out_shndx_; - } - - // Set the output section index. - void - do_set_out_shndx(unsigned int shndx) - { - gold_assert(this->out_shndx_ == -1U || this->out_shndx_ == shndx); - this->out_shndx_ = shndx; - } - - // Set the final data size of the Output_section. For a typical - // Output_section, there is nothing to do, but if there are any - // Output_section_data objects we need to set their final addresses - // here. - virtual void - set_final_data_size(); - - // Reset the address and file offset. - void - do_reset_address_and_file_offset(); - - // Return true if address and file offset already have reset values. In - // other words, calling reset_address_and_file_offset will not change them. - bool - do_address_and_file_offset_have_reset_values() const; - - // Write the data to the file. For a typical Output_section, this - // does nothing: the data is written out by calling Object::Relocate - // on each input object. But if there are any Output_section_data - // objects we do need to write them out here. - virtual void - do_write(Output_file*); - - // Return the address alignment--function required by parent class. - uint64_t - do_addralign() const - { return this->addralign_; } - - // Return whether there is a load address. - bool - do_has_load_address() const - { return this->has_load_address_; } - - // Return the load address. - uint64_t - do_load_address() const - { - gold_assert(this->has_load_address_); - return this->load_address_; - } - - // Return whether this is an Output_section. - bool - do_is_section() const - { return true; } - - // Return whether this is a section of the specified type. - bool - do_is_section_type(elfcpp::Elf_Word type) const - { return this->type_ == type; } - - // Return whether the specified section flag is set. - bool - do_is_section_flag_set(elfcpp::Elf_Xword flag) const - { return (this->flags_ & flag) != 0; } - - // Set the TLS offset. Called only for SHT_TLS sections. - void - do_set_tls_offset(uint64_t tls_base); - - // Return the TLS offset, relative to the base of the TLS segment. - // Valid only for SHT_TLS sections. - uint64_t - do_tls_offset() const - { return this->tls_offset_; } - - // This may be implemented by a child class. - virtual void - do_finalize_name(Layout*) - { } - - // Print to the map file. - virtual void - do_print_to_mapfile(Mapfile*) const; - - // Record that this section requires postprocessing after all - // relocations have been applied. This is called by a child class. - void - set_requires_postprocessing() - { - this->requires_postprocessing_ = true; - this->after_input_sections_ = true; - } - - // Write all the data of an Output_section into the postprocessing - // buffer. - void - write_to_postprocessing_buffer(); - // In some cases we need to keep a list of the input sections // associated with this output section. We only need the list if we // might have to change the offsets of the input section within the @@ -3088,13 +3013,29 @@ class Output_section : public Output_data uint64_t addralign() const { - if (!this->is_input_section()) + if (this->p2align_ != 0) + return static_cast<uint64_t>(1) << (this->p2align_ - 1); + else if (!this->is_input_section()) return this->u2_.posd->addralign(); - return (this->p2align_ == 0 - ? 0 - : static_cast<uint64_t>(1) << (this->p2align_ - 1)); + else + return 0; } + // Set the required alignment, which must be either 0 or a power of 2. + // For input sections that are sub-classes of Output_section_data, a + // alignment of zero means asking the underlying object for alignment. + void + set_addralign(uint64_t addralign) + { + if (addralign == 0) + this->p2align_ = 0; + else + { + gold_assert((addralign & (addralign - 1)) == 0); + this->p2align_ = ffsll(static_cast<long long>(addralign)); + } + } + // Return the required size. off_t data_size() const; @@ -3122,6 +3063,14 @@ class Output_section : public Output_data && this->addralign() == addralign); } + // Return whether this is a merge section for some input section. + bool + is_merge_section() const + { + return (this->shndx_ == MERGE_DATA_SECTION_CODE + || this->shndx_ == MERGE_STRING_SECTION_CODE); + } + // Return whether this is a relaxed input section. bool is_relaxed_input_section() const @@ -3136,27 +3085,11 @@ class Output_section : public Output_data // Return the object for an input section. Relobj* - relobj() const - { - if (this->is_input_section()) - return this->u2_.object; - else if (this->is_relaxed_input_section()) - return this->u2_.poris->relobj(); - else - gold_unreachable(); - } + relobj() const; // Return the input section index for an input section. unsigned int - shndx() const - { - if (this->is_input_section()) - return this->shndx_; - else if (this->is_relaxed_input_section()) - return this->u2_.poris->shndx(); - else - gold_unreachable(); - } + shndx() const; // For non-input-sections, return the associated Output_section_data // object. @@ -3167,6 +3100,14 @@ class Output_section : public Output_data return this->u2_.posd; } + // For a merge section, return the Output_merge_base pointer. + Output_merge_base* + output_merge_base() const + { + gold_assert(this->is_merge_section()); + return this->u2_.pomb; + } + // Return the Output_relaxed_input_section object. Output_relaxed_input_section* relaxed_input_section() const @@ -3289,11 +3230,206 @@ class Output_section : public Output_data // For OUTPUT_SECTION_CODE or MERGE_DATA_SECTION_CODE or // MERGE_STRING_SECTION_CODE, the data. Output_section_data* posd; + Output_merge_base* pomb; // For RELAXED_INPUT_SECTION_CODE, the data. Output_relaxed_input_section* poris; } u2_; }; + // Store the list of input sections for this Output_section into the + // list passed in. This removes the input sections, leaving only + // any Output_section_data elements. This returns the size of those + // Output_section_data elements. ADDRESS is the address of this + // output section. FILL is the fill value to use, in case there are + // any spaces between the remaining Output_section_data elements. + uint64_t + get_input_sections(uint64_t address, const std::string& fill, + std::list<Input_section>*); + + // Add a script input section. A script input section can either be + // a plain input section or a sub-class of Output_section_data. + void + add_script_input_section(const Input_section& input_section); + + // Set the current size of the output section. + void + set_current_data_size(off_t size) + { this->set_current_data_size_for_child(size); } + + // Get the current size of the output section. + off_t + current_data_size() const + { return this->current_data_size_for_child(); } + + // End of linker script support. + + // Save states before doing section layout. + // This is used for relaxation. + void + save_states(); + + // Restore states prior to section layout. + void + restore_states(); + + // Discard states. + void + discard_states(); + + // Convert existing input sections to relaxed input sections. + void + convert_input_sections_to_relaxed_sections( + const std::vector<Output_relaxed_input_section*>& sections); + + // Find a relaxed input section to an input section in OBJECT + // with index SHNDX. Return NULL if none is found. + 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(); + + // Whether this is a NOLOAD section. + bool + is_noload() const + { return this->is_noload_; } + + // Set NOLOAD flag. + void + set_is_noload() + { this->is_noload_ = true; } + + // Print merge statistics to stderr. + void + print_merge_stats(); + + protected: + // Return the output section--i.e., the object itself. + Output_section* + do_output_section() + { return this; } + + const Output_section* + do_output_section() const + { return this; } + + // Return the section index in the output file. + unsigned int + do_out_shndx() const + { + gold_assert(this->out_shndx_ != -1U); + return this->out_shndx_; + } + + // Set the output section index. + void + do_set_out_shndx(unsigned int shndx) + { + gold_assert(this->out_shndx_ == -1U || this->out_shndx_ == shndx); + this->out_shndx_ = shndx; + } + + // Set the final data size of the Output_section. For a typical + // Output_section, there is nothing to do, but if there are any + // Output_section_data objects we need to set their final addresses + // here. + virtual void + set_final_data_size(); + + // Reset the address and file offset. + void + do_reset_address_and_file_offset(); + + // Return true if address and file offset already have reset values. In + // other words, calling reset_address_and_file_offset will not change them. + bool + do_address_and_file_offset_have_reset_values() const; + + // Write the data to the file. For a typical Output_section, this + // does nothing: the data is written out by calling Object::Relocate + // on each input object. But if there are any Output_section_data + // objects we do need to write them out here. + virtual void + do_write(Output_file*); + + // Return the address alignment--function required by parent class. + uint64_t + do_addralign() const + { return this->addralign_; } + + // Return whether there is a load address. + bool + do_has_load_address() const + { return this->has_load_address_; } + + // Return the load address. + uint64_t + do_load_address() const + { + gold_assert(this->has_load_address_); + return this->load_address_; + } + + // Return whether this is an Output_section. + bool + do_is_section() const + { return true; } + + // Return whether this is a section of the specified type. + bool + do_is_section_type(elfcpp::Elf_Word type) const + { return this->type_ == type; } + + // Return whether the specified section flag is set. + bool + do_is_section_flag_set(elfcpp::Elf_Xword flag) const + { return (this->flags_ & flag) != 0; } + + // Set the TLS offset. Called only for SHT_TLS sections. + void + do_set_tls_offset(uint64_t tls_base); + + // Return the TLS offset, relative to the base of the TLS segment. + // Valid only for SHT_TLS sections. + uint64_t + do_tls_offset() const + { return this->tls_offset_; } + + // This may be implemented by a child class. + virtual void + do_finalize_name(Layout*) + { } + + // Print to the map file. + virtual void + do_print_to_mapfile(Mapfile*) const; + + // Record that this section requires postprocessing after all + // relocations have been applied. This is called by a child class. + void + set_requires_postprocessing() + { + this->requires_postprocessing_ = true; + this->after_input_sections_ = true; + } + + // Write all the data of an Output_section into the postprocessing + // buffer. + void + write_to_postprocessing_buffer(); + typedef std::vector<Input_section> Input_section_list; // Allow a child class to access the input sections. @@ -3436,78 +3572,6 @@ class Output_section : public Output_data typedef std::vector<Fill> Fill_list; - // This class describes properties of merge data sections. It is used - // as a key type for maps. - class Merge_section_properties - { - public: - Merge_section_properties(bool is_string, uint64_t entsize, - uint64_t addralign) - : is_string_(is_string), entsize_(entsize), addralign_(addralign) - { } - - // Whether this equals to another Merge_section_properties MSP. - bool - eq(const Merge_section_properties& msp) const - { - return ((this->is_string_ == msp.is_string_) - && (this->entsize_ == msp.entsize_) - && (this->addralign_ == msp.addralign_)); - } - - // Compute a hash value for this using 64-bit FNV-1a hash. - size_t - hash_value() const - { - uint64_t h = 14695981039346656037ULL; // FNV offset basis. - uint64_t prime = 1099511628211ULL; - h = (h ^ static_cast<uint64_t>(this->is_string_)) * prime; - h = (h ^ static_cast<uint64_t>(this->entsize_)) * prime; - h = (h ^ static_cast<uint64_t>(this->addralign_)) * prime; - return h; - } - - // Functors for associative containers. - struct equal_to - { - bool - operator()(const Merge_section_properties& msp1, - const Merge_section_properties& msp2) const - { return msp1.eq(msp2); } - }; - - struct hash - { - size_t - operator()(const Merge_section_properties& msp) const - { return msp.hash_value(); } - }; - - private: - // Whether this merge data section is for strings. - bool is_string_; - // Entsize of this merge data section. - uint64_t entsize_; - // Address alignment. - uint64_t addralign_; - }; - - // Map that link Merge_section_properties to Output_merge_base. - typedef Unordered_map<Merge_section_properties, Output_merge_base*, - Merge_section_properties::hash, - Merge_section_properties::equal_to> - Merge_section_by_properties_map; - - // Map that link Const_section_id to Output_section_data. - typedef Unordered_map<Const_section_id, Output_section_data*, - Const_section_id_hash> - Output_section_data_by_input_section_map; - - // Map that link Const_section_id to Output_relaxed_input_section. - typedef Unordered_map<Const_section_id, Output_relaxed_input_section*, - Const_section_id_hash> - Output_relaxed_input_section_by_input_section_map; - // Map used during relaxation of existing sections. This map // a section id an input section list index. We assume that // Input_section_list is a vector. @@ -3518,10 +3582,12 @@ class Output_section : public Output_data add_output_section_data(Input_section*); // Add an SHF_MERGE input section. Returns true if the section was - // handled. + // handled. If KEEPS_INPUT_SECTIONS is true, the output merge section + // stores information about the merged input sections. bool add_merge_input_section(Relobj* object, unsigned int shndx, uint64_t flags, - uint64_t entsize, uint64_t addralign); + uint64_t entsize, uint64_t addralign, + bool keeps_input_sections); // Add an output SHF_MERGE section POSD to this output section. // IS_STRING indicates whether it is a SHF_STRINGS section, and @@ -3554,6 +3620,10 @@ class Output_section : public Output_data const Relaxation_map& map, Input_section_list* input_sections); + // Build the lookup maps for merge and relaxed input sections. + void + build_lookup_maps() const; + // Most of these fields are only valid after layout. // The name of the section. This will point into a Stringpool. @@ -3676,17 +3746,8 @@ class Output_section : public Output_data uint64_t tls_offset_; // Saved checkpoint. Checkpoint_output_section* checkpoint_; - // Map from input sections to merge sections. - Output_section_data_by_input_section_map merge_section_map_; - // Map from merge section properties to merge_sections; - Merge_section_by_properties_map merge_section_by_properties_map_; - // Map from input sections to relaxed input sections. This is mutable - // because it is updated lazily. We may need to update it in a - // const qualified method. - mutable Output_relaxed_input_section_by_input_section_map - relaxed_input_section_map_; - // Whether relaxed_input_section_map_ is valid. - mutable bool is_relaxed_input_section_map_valid_; + // Fast lookup maps for merged and relaxed input sections. + Output_section_lookup_maps* lookup_maps_; }; // An output segment. PT_LOAD segments are built from collections of |