diff options
author | Doug Kwan <dougkwan@google.com> | 2010-05-19 07:09:36 +0000 |
---|---|---|
committer | Doug Kwan <dougkwan@google.com> | 2010-05-19 07:09:36 +0000 |
commit | 6625d24e236a525781fda9482af925ade7f60c97 (patch) | |
tree | 486f3bcb594dee1205afa0342019f0733ebd31a0 | |
parent | 51b5d4a8c5e50baae29270983b16cfdd49ed7646 (diff) | |
download | gdb-6625d24e236a525781fda9482af925ade7f60c97.zip gdb-6625d24e236a525781fda9482af925ade7f60c97.tar.gz gdb-6625d24e236a525781fda9482af925ade7f60c97.tar.bz2 |
2010-05-14 Doug Kwan <dougkwan@google.com>
* arm.cc (Arm_input_section::original_size): New method.
(Arm_input_section::do_addralign): Add a cast.
(Arm_input_section::do_output_offset): Remove static cast.
(Arm_input_section::original_addralign,
Arm_input_section::original_size_): Change type to uint32_t.
(Arm_input_section::init): Add safe casts for section alignment
and size.
(Arm_input_section::set_final_data_size): Do not set address and
offset of stub table.
(Arm_output_section::fix_exidx_coverage): Change use of of
Output_section::Simple_input_section to that of
Output_section::Input_section.
(Target_arm::do_relax): Set addresses and file offsets of Stub_tables
except for the first pass.
* output.cc (Output_section::get_input_sections): Change type of
input_sections to std::list<Input_section>.
(Output_section::add_script_input_section): Rename from
Output_section::add_simple_input_section. Change type of SIS
parameter from Simple_input_section to Input_section.
* output.h (Output_section::Simple_input_section): Remove class.
(Output_section::Input_section): Change class visibility to public.
(Output_section::Input_section::addralign): Use stored alignments
for special input sections if set.
(Output_section::Input_section::set_addralign): New method.
(Output_section::get_input_sections): Change parameter type from
list of Simple_input_section to list of Input_section.
(Output_section::add_script_input_section): Rename from
Output_section::add_simple_input_section. Change first parameter's
type from Simple_input_section to Input_section and remove the
second and third parameters.
* script-sections.cc (Input_section::Input_section_list): Change
type to list of Output_section::Input_section/
(Input_section_info::Input_section_info): Change parameter type of
INPUT_SECTION to Output_section::Input_section.
(Input_section_info::input_section): Change return type.
(Input_section_info::input_section_): Change type to
Output_section::Input_section.
(Output_section_element_input::set_section_addresses): Adjust code
to use Output_section::Input_section instead of
Output_section::Simple_input_section. Adjust code for renaming
of Output_section::add_simple_input_section.
(Orphan_output_section::set_section_addresses): Ditto.
-rw-r--r-- | gold/ChangeLog | 45 | ||||
-rw-r--r-- | gold/arm.cc | 65 | ||||
-rw-r--r-- | gold/output.cc | 27 | ||||
-rw-r--r-- | gold/output.h | 475 | ||||
-rw-r--r-- | gold/script-sections.cc | 55 |
5 files changed, 339 insertions, 328 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index b78195e..1ff2a48 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,48 @@ +2010-05-19 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_input_section::original_size): New method. + (Arm_input_section::do_addralign): Add a cast. + (Arm_input_section::do_output_offset): Remove static cast. + (Arm_input_section::original_addralign, + Arm_input_section::original_size_): Change type to uint32_t. + (Arm_input_section::init): Add safe casts for section alignment + and size. + (Arm_input_section::set_final_data_size): Do not set address and + offset of stub table. + (Arm_output_section::fix_exidx_coverage): Change use of of + Output_section::Simple_input_section to that of + Output_section::Input_section. + (Target_arm::do_relax): Set addresses and file offsets of Stub_tables + except for the first pass. + * output.cc (Output_section::get_input_sections): Change type of + input_sections to std::list<Input_section>. + (Output_section::add_script_input_section): Rename from + Output_section::add_simple_input_section. Change type of SIS + parameter from Simple_input_section to Input_section. + * output.h (Output_section::Simple_input_section): Remove class. + (Output_section::Input_section): Change class visibility to public. + (Output_section::Input_section::addralign): Use stored alignments + for special input sections if set. + (Output_section::Input_section::set_addralign): New method. + (Output_section::get_input_sections): Change parameter type from + list of Simple_input_section to list of Input_section. + (Output_section::add_script_input_section): Rename from + Output_section::add_simple_input_section. Change first parameter's + type from Simple_input_section to Input_section and remove the + second and third parameters. + * script-sections.cc (Input_section::Input_section_list): Change + type to list of Output_section::Input_section/ + (Input_section_info::Input_section_info): Change parameter type of + INPUT_SECTION to Output_section::Input_section. + (Input_section_info::input_section): Change return type. + (Input_section_info::input_section_): Change type to + Output_section::Input_section. + (Output_section_element_input::set_section_addresses): Adjust code + to use Output_section::Input_section instead of + Output_section::Simple_input_section. Adjust code for renaming + of Output_section::add_simple_input_section. + (Orphan_output_section::set_section_addresses): Ditto. + 2010-05-18 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> * gold.h (Unordered_multimap, Unordered_map): Fix defines for diff --git a/gold/arm.cc b/gold/arm.cc index c304d2a..3dc2f22 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -1164,6 +1164,11 @@ class Arm_input_section : public Output_relaxed_input_section as_arm_input_section(Output_relaxed_input_section* poris) { return static_cast<Arm_input_section<big_endian>*>(poris); } + // Return the original size of the section. + uint32_t + original_size() const + { return this->original_size_; } + protected: // Write data to output file. void @@ -1175,7 +1180,7 @@ class Arm_input_section : public Output_relaxed_input_section { if (this->is_stub_table_owner()) return std::max(this->stub_table_->addralign(), - this->original_addralign_); + static_cast<uint64_t>(this->original_addralign_)); else return this->original_addralign_; } @@ -1197,8 +1202,7 @@ class Arm_input_section : public Output_relaxed_input_section if ((object == this->relobj()) && (shndx == this->shndx()) && (offset >= 0) - && (convert_types<uint64_t, section_offset_type>(offset) - <= this->original_size_)) + && (offset <= this->original_size_)) { *poutput = offset; return true; @@ -1213,9 +1217,9 @@ class Arm_input_section : public Output_relaxed_input_section Arm_input_section& operator=(const Arm_input_section&); // Address alignment of the original input section. - uint64_t original_addralign_; + uint32_t original_addralign_; // Section size of the original input section. - uint64_t original_size_; + uint32_t original_size_; // Stub table. Stub_table<big_endian>* stub_table_; }; @@ -4909,8 +4913,10 @@ Arm_input_section<big_endian>::init() // Cache these to speed up size and alignment queries. It is too slow // to call section_addraglin and section_size every time. - this->original_addralign_ = relobj->section_addralign(shndx); - this->original_size_ = relobj->section_size(shndx); + this->original_addralign_ = + convert_types<uint32_t, uint64_t>(relobj->section_addralign(shndx)); + this->original_size_ = + convert_types<uint32_t, uint64_t>(relobj->section_size(shndx)); // We want to make this look like the original input section after // output sections are finalized. @@ -4949,10 +4955,8 @@ Arm_input_section<big_endian>::set_final_data_size() if (this->is_stub_table_owner()) { - // The stub table comes after the original section contents. + this->stub_table_->finalize_data_size(); off = align_address(off, this->stub_table_->addralign()); - this->stub_table_->set_address_and_file_offset(this->address() + off, - this->offset() + off); off += this->stub_table_->data_size(); } this->set_data_size(off); @@ -5576,8 +5580,8 @@ Arm_output_section<big_endian>::fix_exidx_coverage( // Remove all input sections. uint64_t address = this->address(); - typedef std::list<Simple_input_section> Simple_input_section_list; - Simple_input_section_list input_sections; + typedef std::list<Output_section::Input_section> Input_section_list; + Input_section_list input_sections; this->reset_address_and_file_offset(); this->get_input_sections(address, std::string(""), &input_sections); @@ -5586,20 +5590,23 @@ Arm_output_section<big_endian>::fix_exidx_coverage( // Go through all the known input sections and record them. typedef Unordered_set<Section_id, Section_id_hash> Section_id_set; - Section_id_set known_input_sections; - for (Simple_input_section_list::const_iterator p = input_sections.begin(); + typedef Unordered_map<Section_id, const Output_section::Input_section*, + Section_id_hash> Text_to_exidx_map; + Text_to_exidx_map text_to_exidx_map; + for (Input_section_list::const_iterator p = input_sections.begin(); p != input_sections.end(); ++p) { // This should never happen. At this point, we should only see // plain EXIDX input sections. gold_assert(!p->is_relaxed_input_section()); - known_input_sections.insert(Section_id(p->relobj(), p->shndx())); + text_to_exidx_map[Section_id(p->relobj(), p->shndx())] = &(*p); } Arm_exidx_fixup exidx_fixup(this, merge_exidx_entries); // Go over the sorted text sections. + typedef Unordered_set<Section_id, Section_id_hash> Section_id_set; Section_id_set processed_input_sections; for (Text_section_list::const_iterator p = sorted_text_sections.begin(); p != sorted_text_sections.end(); @@ -5624,7 +5631,8 @@ Arm_output_section<big_endian>::fix_exidx_coverage( Relobj* exidx_relobj = exidx_input_section->relobj(); unsigned int exidx_shndx = exidx_input_section->shndx(); Section_id sid(exidx_relobj, exidx_shndx); - if (known_input_sections.find(sid) == known_input_sections.end()) + Text_to_exidx_map::const_iterator iter = text_to_exidx_map.find(sid); + if (iter == text_to_exidx_map.end()) { // This is odd. We have not seen this EXIDX input section before. // We cannot do fix-up. If we saw a SECTIONS clause in a script, @@ -5679,9 +5687,9 @@ Arm_output_section<big_endian>::fix_exidx_coverage( { // Just add back the EXIDX input section. gold_assert(section_offset_map == NULL); - Output_section::Simple_input_section sis(exidx_relobj, exidx_shndx); - this->add_simple_input_section(sis, exidx_input_section->size(), - exidx_input_section->addralign()); + const Output_section::Input_section* pis = iter->second; + gold_assert(pis->is_input_section()); + this->add_script_input_section(*pis); } processed_input_sections.insert(Section_id(exidx_relobj, exidx_shndx)); @@ -5691,7 +5699,7 @@ Arm_output_section<big_endian>::fix_exidx_coverage( exidx_fixup.add_exidx_cantunwind_as_needed(); // Remove any known EXIDX input sections that are not processed. - for (Simple_input_section_list::const_iterator p = input_sections.begin(); + for (Input_section_list::const_iterator p = input_sections.begin(); p != input_sections.end(); ++p) { @@ -10444,6 +10452,7 @@ Target_arm<big_endian>::do_relax( // If this is the first pass, we need to group input sections into // stub groups. bool done_exidx_fixup = false; + typedef typename Stub_table_list::iterator Stub_table_iterator; if (pass == 1) { // Determine the stub group size. The group size is the absolute @@ -10492,13 +10501,27 @@ Target_arm<big_endian>::do_relax( done_exidx_fixup = true; } } + else + { + // If this is not the first pass, addresses and file offsets have + // been reset at this point, set them here. + for (Stub_table_iterator sp = this->stub_tables_.begin(); + sp != this->stub_tables_.end(); + ++sp) + { + Arm_input_section<big_endian>* owner = (*sp)->owner(); + off_t off = align_address(owner->original_size(), + (*sp)->addralign()); + (*sp)->set_address_and_file_offset(owner->address() + off, + owner->offset() + off); + } + } // The Cortex-A8 stubs are sensitive to layout of code sections. At the // beginning of each relaxation pass, just blow away all the stubs. // Alternatively, we could selectively remove only the stubs and reloc // information for code sections that have moved since the last pass. // That would require more book-keeping. - typedef typename Stub_table_list::iterator Stub_table_iterator; if (this->fix_cortex_a8_) { // Clear all Cortex-A8 reloc information. diff --git a/gold/output.cc b/gold/output.cc index 6878034..4c9776d 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -3046,7 +3046,7 @@ uint64_t Output_section::get_input_sections( uint64_t address, const std::string& fill, - std::list<Simple_input_section>* input_sections) + std::list<Input_section>* input_sections) { if (this->checkpoint_ != NULL && !this->checkpoint_->input_sections_saved()) @@ -3064,12 +3064,8 @@ Output_section::get_input_sections( p != this->input_sections_.end(); ++p) { - if (p->is_input_section()) - input_sections->push_back(Simple_input_section(p->relobj(), - p->shndx())); - else if (p->is_relaxed_input_section()) - input_sections->push_back( - Simple_input_section(p->relaxed_input_section())); + if (p->is_input_section() || p->is_relaxed_input_section()) + input_sections->push_back(*p); else { uint64_t aligned_address = align_address(address, p->addralign()); @@ -3104,13 +3100,16 @@ Output_section::get_input_sections( return data_size; } -// Add an simple input section. +// Add a script input section. SIS is an Output_section::Input_section, +// which can be either a plain input section or a special input section like +// a relaxed input section. For a special input section, its size must be +// finalized. void -Output_section::add_simple_input_section(const Simple_input_section& sis, - off_t data_size, - uint64_t addralign) +Output_section::add_script_input_section(const Input_section& sis) { + uint64_t data_size = sis.data_size(); + uint64_t addralign = sis.addralign(); if (addralign > this->addralign_) this->addralign_ = addralign; @@ -3121,11 +3120,7 @@ Output_section::add_simple_input_section(const Simple_input_section& sis, this->set_current_data_size_for_child(aligned_offset_in_section + data_size); - Input_section is = - (sis.is_relaxed_input_section() - ? Input_section(sis.relaxed_input_section()) - : Input_section(sis.relobj(), sis.shndx(), data_size, addralign)); - this->input_sections_.push_back(is); + this->input_sections_.push_back(sis); } // Save states for relaxation. diff --git a/gold/output.h b/gold/output.h index 410ec2c..a15fe27 100644 --- a/gold/output.h +++ b/gold/output.h @@ -2766,263 +2766,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 +2831,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; @@ -3294,6 +3053,200 @@ class Output_section : public Output_data } 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. diff --git a/gold/script-sections.cc b/gold/script-sections.cc index b4cbb40..e778279 100644 --- a/gold/script-sections.cc +++ b/gold/script-sections.cc @@ -546,7 +546,7 @@ class Output_section_element { public: // A list of input sections. - typedef std::list<Output_section::Simple_input_section> Input_section_list; + typedef std::list<Output_section::Input_section> Input_section_list; Output_section_element() { } @@ -1195,13 +1195,13 @@ Output_section_element_input::match_name(const char* file_name, class Input_section_info { public: - Input_section_info(const Output_section::Simple_input_section& input_section) + Input_section_info(const Output_section::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& + const Output_section::Input_section& input_section() const { return this->input_section_; } @@ -1247,7 +1247,7 @@ class Input_section_info private: // Input section, can be a relaxed section. - Output_section::Simple_input_section input_section_; + Output_section::Input_section input_section_; // Name of the section. std::string section_name_; // Section size. @@ -1418,9 +1418,20 @@ Output_section_element_input::set_section_addresses( p != matching_sections[i].end(); ++p) { - uint64_t this_subalign = p->addralign(); + // Override the original address alignment if SUBALIGN is specified + // and is greater than the original alignment. We need to make a + // copy of the input section to modify the alignment. + Output_section::Input_section sis(p->input_section()); + + uint64_t this_subalign = sis.addralign(); + if (!sis.is_input_section()) + sis.output_section_data()->finalize_data_size(); + uint64_t data_size = sis.data_size(); if (this_subalign < subalign) - this_subalign = subalign; + { + this_subalign = subalign; + sis.set_addralign(subalign); + } uint64_t address = align_address(dot, this_subalign); @@ -1434,11 +1445,8 @@ Output_section_element_input::set_section_addresses( layout->new_output_section_data_from_script(posd); } - output_section->add_simple_input_section(p->input_section(), - p->size(), - this_subalign); - - dot = address + p->size(); + output_section->add_script_input_section(sis); + dot = address + data_size; } } @@ -2381,7 +2389,7 @@ Orphan_output_section::set_section_addresses(Symbol_table*, Layout*, uint64_t*, uint64_t* load_address) { - typedef std::list<Output_section::Simple_input_section> Input_section_list; + typedef std::list<Output_section::Input_section> Input_section_list; bool have_load_address = *load_address != *dot_value; @@ -2403,25 +2411,12 @@ Orphan_output_section::set_section_addresses(Symbol_table*, Layout*, p != input_sections.end(); ++p) { - uint64_t addralign; - uint64_t size; - - // We know we are single-threaded, so it is OK to lock the - // object. - { - const Task* task = reinterpret_cast<const Task*>(-1); - Task_lock_obj<Object> tl(task, p->relobj()); - addralign = p->relobj()->section_addralign(p->shndx()); - if (p->is_relaxed_input_section()) - // We use current data size because relxed section sizes may not - // have finalized yet. - size = p->relaxed_input_section()->current_data_size(); - else - size = p->relobj()->section_size(p->shndx()); - } - + uint64_t addralign = p->addralign(); + if (!p->is_input_section()) + p->output_section_data()->finalize_data_size(); + uint64_t size = p->data_size(); address = align_address(address, addralign); - this->os_->add_simple_input_section(*p, size, addralign); + this->os_->add_script_input_section(*p); address += size; } |