aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gold/ChangeLog45
-rw-r--r--gold/arm.cc65
-rw-r--r--gold/output.cc27
-rw-r--r--gold/output.h475
-rw-r--r--gold/script-sections.cc55
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;
}