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.
This commit is contained in:
parent
51b5d4a8c5
commit
6625d24e23
|
@ -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
|
||||
|
|
65
gold/arm.cc
65
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.
|
||||
|
|
|
@ -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.
|
||||
|
|
475
gold/output.h
475
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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue