mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-30 09:09:16 +08:00
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:
@ -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>
|
2010-05-18 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
|
||||||
|
|
||||||
* gold.h (Unordered_multimap, Unordered_map): Fix defines for
|
* 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)
|
as_arm_input_section(Output_relaxed_input_section* poris)
|
||||||
{ return static_cast<Arm_input_section<big_endian>*>(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:
|
protected:
|
||||||
// Write data to output file.
|
// Write data to output file.
|
||||||
void
|
void
|
||||||
@ -1175,7 +1180,7 @@ class Arm_input_section : public Output_relaxed_input_section
|
|||||||
{
|
{
|
||||||
if (this->is_stub_table_owner())
|
if (this->is_stub_table_owner())
|
||||||
return std::max(this->stub_table_->addralign(),
|
return std::max(this->stub_table_->addralign(),
|
||||||
this->original_addralign_);
|
static_cast<uint64_t>(this->original_addralign_));
|
||||||
else
|
else
|
||||||
return this->original_addralign_;
|
return this->original_addralign_;
|
||||||
}
|
}
|
||||||
@ -1197,8 +1202,7 @@ class Arm_input_section : public Output_relaxed_input_section
|
|||||||
if ((object == this->relobj())
|
if ((object == this->relobj())
|
||||||
&& (shndx == this->shndx())
|
&& (shndx == this->shndx())
|
||||||
&& (offset >= 0)
|
&& (offset >= 0)
|
||||||
&& (convert_types<uint64_t, section_offset_type>(offset)
|
&& (offset <= this->original_size_))
|
||||||
<= this->original_size_))
|
|
||||||
{
|
{
|
||||||
*poutput = offset;
|
*poutput = offset;
|
||||||
return true;
|
return true;
|
||||||
@ -1213,9 +1217,9 @@ class Arm_input_section : public Output_relaxed_input_section
|
|||||||
Arm_input_section& operator=(const Arm_input_section&);
|
Arm_input_section& operator=(const Arm_input_section&);
|
||||||
|
|
||||||
// Address alignment of the original input section.
|
// Address alignment of the original input section.
|
||||||
uint64_t original_addralign_;
|
uint32_t original_addralign_;
|
||||||
// Section size of the original input section.
|
// Section size of the original input section.
|
||||||
uint64_t original_size_;
|
uint32_t original_size_;
|
||||||
// Stub table.
|
// Stub table.
|
||||||
Stub_table<big_endian>* 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
|
// Cache these to speed up size and alignment queries. It is too slow
|
||||||
// to call section_addraglin and section_size every time.
|
// to call section_addraglin and section_size every time.
|
||||||
this->original_addralign_ = relobj->section_addralign(shndx);
|
this->original_addralign_ =
|
||||||
this->original_size_ = relobj->section_size(shndx);
|
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
|
// We want to make this look like the original input section after
|
||||||
// output sections are finalized.
|
// output sections are finalized.
|
||||||
@ -4949,10 +4955,8 @@ Arm_input_section<big_endian>::set_final_data_size()
|
|||||||
|
|
||||||
if (this->is_stub_table_owner())
|
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());
|
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();
|
off += this->stub_table_->data_size();
|
||||||
}
|
}
|
||||||
this->set_data_size(off);
|
this->set_data_size(off);
|
||||||
@ -5576,8 +5580,8 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
|
|||||||
|
|
||||||
// Remove all input sections.
|
// Remove all input sections.
|
||||||
uint64_t address = this->address();
|
uint64_t address = this->address();
|
||||||
typedef std::list<Simple_input_section> Simple_input_section_list;
|
typedef std::list<Output_section::Input_section> Input_section_list;
|
||||||
Simple_input_section_list input_sections;
|
Input_section_list input_sections;
|
||||||
this->reset_address_and_file_offset();
|
this->reset_address_and_file_offset();
|
||||||
this->get_input_sections(address, std::string(""), &input_sections);
|
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.
|
// Go through all the known input sections and record them.
|
||||||
typedef Unordered_set<Section_id, Section_id_hash> Section_id_set;
|
typedef Unordered_set<Section_id, Section_id_hash> Section_id_set;
|
||||||
Section_id_set known_input_sections;
|
typedef Unordered_map<Section_id, const Output_section::Input_section*,
|
||||||
for (Simple_input_section_list::const_iterator p = input_sections.begin();
|
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 != input_sections.end();
|
||||||
++p)
|
++p)
|
||||||
{
|
{
|
||||||
// This should never happen. At this point, we should only see
|
// This should never happen. At this point, we should only see
|
||||||
// plain EXIDX input sections.
|
// plain EXIDX input sections.
|
||||||
gold_assert(!p->is_relaxed_input_section());
|
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);
|
Arm_exidx_fixup exidx_fixup(this, merge_exidx_entries);
|
||||||
|
|
||||||
// Go over the sorted text sections.
|
// Go over the sorted text sections.
|
||||||
|
typedef Unordered_set<Section_id, Section_id_hash> Section_id_set;
|
||||||
Section_id_set processed_input_sections;
|
Section_id_set processed_input_sections;
|
||||||
for (Text_section_list::const_iterator p = sorted_text_sections.begin();
|
for (Text_section_list::const_iterator p = sorted_text_sections.begin();
|
||||||
p != sorted_text_sections.end();
|
p != sorted_text_sections.end();
|
||||||
@ -5624,7 +5631,8 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
|
|||||||
Relobj* exidx_relobj = exidx_input_section->relobj();
|
Relobj* exidx_relobj = exidx_input_section->relobj();
|
||||||
unsigned int exidx_shndx = exidx_input_section->shndx();
|
unsigned int exidx_shndx = exidx_input_section->shndx();
|
||||||
Section_id sid(exidx_relobj, exidx_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.
|
// 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,
|
// 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.
|
// Just add back the EXIDX input section.
|
||||||
gold_assert(section_offset_map == NULL);
|
gold_assert(section_offset_map == NULL);
|
||||||
Output_section::Simple_input_section sis(exidx_relobj, exidx_shndx);
|
const Output_section::Input_section* pis = iter->second;
|
||||||
this->add_simple_input_section(sis, exidx_input_section->size(),
|
gold_assert(pis->is_input_section());
|
||||||
exidx_input_section->addralign());
|
this->add_script_input_section(*pis);
|
||||||
}
|
}
|
||||||
|
|
||||||
processed_input_sections.insert(Section_id(exidx_relobj, exidx_shndx));
|
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();
|
exidx_fixup.add_exidx_cantunwind_as_needed();
|
||||||
|
|
||||||
// Remove any known EXIDX input sections that are not processed.
|
// 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 != input_sections.end();
|
||||||
++p)
|
++p)
|
||||||
{
|
{
|
||||||
@ -10444,6 +10452,7 @@ Target_arm<big_endian>::do_relax(
|
|||||||
// If this is the first pass, we need to group input sections into
|
// If this is the first pass, we need to group input sections into
|
||||||
// stub groups.
|
// stub groups.
|
||||||
bool done_exidx_fixup = false;
|
bool done_exidx_fixup = false;
|
||||||
|
typedef typename Stub_table_list::iterator Stub_table_iterator;
|
||||||
if (pass == 1)
|
if (pass == 1)
|
||||||
{
|
{
|
||||||
// Determine the stub group size. The group size is the absolute
|
// 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;
|
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
|
// The Cortex-A8 stubs are sensitive to layout of code sections. At the
|
||||||
// beginning of each relaxation pass, just blow away all the stubs.
|
// beginning of each relaxation pass, just blow away all the stubs.
|
||||||
// Alternatively, we could selectively remove only the stubs and reloc
|
// Alternatively, we could selectively remove only the stubs and reloc
|
||||||
// information for code sections that have moved since the last pass.
|
// information for code sections that have moved since the last pass.
|
||||||
// That would require more book-keeping.
|
// That would require more book-keeping.
|
||||||
typedef typename Stub_table_list::iterator Stub_table_iterator;
|
|
||||||
if (this->fix_cortex_a8_)
|
if (this->fix_cortex_a8_)
|
||||||
{
|
{
|
||||||
// Clear all Cortex-A8 reloc information.
|
// Clear all Cortex-A8 reloc information.
|
||||||
|
@ -3046,7 +3046,7 @@ uint64_t
|
|||||||
Output_section::get_input_sections(
|
Output_section::get_input_sections(
|
||||||
uint64_t address,
|
uint64_t address,
|
||||||
const std::string& fill,
|
const std::string& fill,
|
||||||
std::list<Simple_input_section>* input_sections)
|
std::list<Input_section>* input_sections)
|
||||||
{
|
{
|
||||||
if (this->checkpoint_ != NULL
|
if (this->checkpoint_ != NULL
|
||||||
&& !this->checkpoint_->input_sections_saved())
|
&& !this->checkpoint_->input_sections_saved())
|
||||||
@ -3064,12 +3064,8 @@ Output_section::get_input_sections(
|
|||||||
p != this->input_sections_.end();
|
p != this->input_sections_.end();
|
||||||
++p)
|
++p)
|
||||||
{
|
{
|
||||||
if (p->is_input_section())
|
if (p->is_input_section() || p->is_relaxed_input_section())
|
||||||
input_sections->push_back(Simple_input_section(p->relobj(),
|
input_sections->push_back(*p);
|
||||||
p->shndx()));
|
|
||||||
else if (p->is_relaxed_input_section())
|
|
||||||
input_sections->push_back(
|
|
||||||
Simple_input_section(p->relaxed_input_section()));
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint64_t aligned_address = align_address(address, p->addralign());
|
uint64_t aligned_address = align_address(address, p->addralign());
|
||||||
@ -3104,13 +3100,16 @@ Output_section::get_input_sections(
|
|||||||
return data_size;
|
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
|
void
|
||||||
Output_section::add_simple_input_section(const Simple_input_section& sis,
|
Output_section::add_script_input_section(const Input_section& sis)
|
||||||
off_t data_size,
|
|
||||||
uint64_t addralign)
|
|
||||||
{
|
{
|
||||||
|
uint64_t data_size = sis.data_size();
|
||||||
|
uint64_t addralign = sis.addralign();
|
||||||
if (addralign > this->addralign_)
|
if (addralign > this->addralign_)
|
||||||
this->addralign_ = 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
|
this->set_current_data_size_for_child(aligned_offset_in_section
|
||||||
+ data_size);
|
+ data_size);
|
||||||
|
|
||||||
Input_section is =
|
this->input_sections_.push_back(sis);
|
||||||
(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save states for relaxation.
|
// 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.
|
// 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
|
// 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
|
// associated with this output section. We only need the list if we
|
||||||
// might have to change the offsets of the input section within the
|
// might have to change the offsets of the input section within the
|
||||||
@ -3088,11 +2831,27 @@ class Output_section : public Output_data
|
|||||||
uint64_t
|
uint64_t
|
||||||
addralign() const
|
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->u2_.posd->addralign();
|
||||||
return (this->p2align_ == 0
|
else
|
||||||
? 0
|
return 0;
|
||||||
: static_cast<uint64_t>(1) << (this->p2align_ - 1));
|
}
|
||||||
|
|
||||||
|
// 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.
|
// Return the required size.
|
||||||
@ -3294,6 +3053,200 @@ class Output_section : public Output_data
|
|||||||
} u2_;
|
} 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;
|
typedef std::vector<Input_section> Input_section_list;
|
||||||
|
|
||||||
// Allow a child class to access the input sections.
|
// Allow a child class to access the input sections.
|
||||||
|
@ -546,7 +546,7 @@ class Output_section_element
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// A list of input sections.
|
// 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()
|
Output_section_element()
|
||||||
{ }
|
{ }
|
||||||
@ -1195,13 +1195,13 @@ Output_section_element_input::match_name(const char* file_name,
|
|||||||
class Input_section_info
|
class Input_section_info
|
||||||
{
|
{
|
||||||
public:
|
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_(),
|
: input_section_(input_section), section_name_(),
|
||||||
size_(0), addralign_(1)
|
size_(0), addralign_(1)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
// Return the simple input section.
|
// Return the simple input section.
|
||||||
const Output_section::Simple_input_section&
|
const Output_section::Input_section&
|
||||||
input_section() const
|
input_section() const
|
||||||
{ return this->input_section_; }
|
{ return this->input_section_; }
|
||||||
|
|
||||||
@ -1247,7 +1247,7 @@ class Input_section_info
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// Input section, can be a relaxed section.
|
// Input section, can be a relaxed section.
|
||||||
Output_section::Simple_input_section input_section_;
|
Output_section::Input_section input_section_;
|
||||||
// Name of the section.
|
// Name of the section.
|
||||||
std::string section_name_;
|
std::string section_name_;
|
||||||
// Section size.
|
// Section size.
|
||||||
@ -1418,9 +1418,20 @@ Output_section_element_input::set_section_addresses(
|
|||||||
p != matching_sections[i].end();
|
p != matching_sections[i].end();
|
||||||
++p)
|
++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)
|
if (this_subalign < subalign)
|
||||||
|
{
|
||||||
this_subalign = subalign;
|
this_subalign = subalign;
|
||||||
|
sis.set_addralign(subalign);
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t address = align_address(dot, this_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);
|
layout->new_output_section_data_from_script(posd);
|
||||||
}
|
}
|
||||||
|
|
||||||
output_section->add_simple_input_section(p->input_section(),
|
output_section->add_script_input_section(sis);
|
||||||
p->size(),
|
dot = address + data_size;
|
||||||
this_subalign);
|
|
||||||
|
|
||||||
dot = address + p->size();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2381,7 +2389,7 @@ Orphan_output_section::set_section_addresses(Symbol_table*, Layout*,
|
|||||||
uint64_t*,
|
uint64_t*,
|
||||||
uint64_t* load_address)
|
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;
|
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 != input_sections.end();
|
||||||
++p)
|
++p)
|
||||||
{
|
{
|
||||||
uint64_t addralign;
|
uint64_t addralign = p->addralign();
|
||||||
uint64_t size;
|
if (!p->is_input_section())
|
||||||
|
p->output_section_data()->finalize_data_size();
|
||||||
// We know we are single-threaded, so it is OK to lock the
|
uint64_t size = p->data_size();
|
||||||
// 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());
|
|
||||||
}
|
|
||||||
|
|
||||||
address = align_address(address, addralign);
|
address = align_address(address, addralign);
|
||||||
this->os_->add_simple_input_section(*p, size, addralign);
|
this->os_->add_script_input_section(*p);
|
||||||
address += size;
|
address += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user