mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-23 11:39:26 +08:00
2009-09-17 Doug Kwan <dougkwan@google.com>
* debug.h (DEBUG_RELAXATION): New constant. (DEBUG_ALL): Add DEBUG_RELAXATION. (debug_string_to_enum): Add relaxation debug option. * layout.cc (Layout::Relaxation_debug_check::check_output_data_for_reset_values, Layout::Relaxation_debug_check::read_sections, Layout::Relaxation_debug_check::read_sections): New method definitions. (Layout::Layout): Initialize data members record_output_section_data_from_scrips_, script_output_section_data_list_ and relaxation_debug_check_. (Layout::save_segments, Layout::restore_segments, Layout::clean_up_after_relaxation, Layout::prepare_for_relaxation, Layout::relaxation_loop_body): New method definitions. (Layout::finalize): Support relaxation. Move section layout code to Layout::relaxation_loop_body. (Layout::set_asection_address_from_script): Move code for orphan section placement out. (Layout::place_orphan_sections_in_script): New method definition. * layout.h (Output_segment_headers, Output_file_header): New forward class declarations. (Layout::~Layout): Define. (Layout::new_output_section_data_from_script): New method definition. (Layout::place_orphan_sections_in_script): New method declaration. (Layout::Segment_states): New type declaration. (Layout::save_segments, Layout::restore_segments, Layout::clean_up_after_relaxation, Layout::prepare_for_relaxation, Layout::relaxation_loop_body): New method declarations. (Layout::Output_section_data_list): New type declaration. (Layout::Relaxation_debug_check): New class definition. (Layout::record_output_section_data_from_script_, Layout::script_output_section_data_list_, Layout::segment_states_, Layout::relaxation_debug_check_): New data members. * output.cc: (Output_section_headers::do_size): New method definition. (Output_section_headers::Output_section_headers): Move size computation to Output_section_headers::do_size. (Output_segment_headers::do_size): New method definition. (Output_file_header::Output_file_header): Move size computation to Output_file_header::do_size and call it. (Output_file_header::do_size): New method definition. (Output_data_group::Output_data_group): Adjust call to Output_section_data. (Output_data_dynamic::set_final_data_size): Add DT_NULL tag only once. (Output_symtab_xindex::do_write): Add array bound check. (Output_section::Input_section::print_to_mapfile): Handle RELAXED_INPUT_SECTION_CODE. (Output_section::Output_section): Initialize data member checkpoint_. (Output_section::~Output_section): Delete checkpoint object pointed by checkpoint_. (Output_section::add_input_section): Always add an Input_section if relaxing. (Output_section::add_merge_input_section): Add assert. (Output_section::relax_input_section): New method definition. (Output_section::set_final_data_size): Set load address to zero for an unallocated section. (Output_section::do_address_and_file_offset_have_reset_values): New method definition. (Output_section::Input_section_sort_enty::Input_section_sort_enty): Handle relaxed input section. (Output_section::sort_attached_input_sections): Checkpoint input section list lazily. (Output_section::get_input_sections): Change type of input_sections to list of Simple_input_section pointers. Checkpoint input section list lazily. Also handle relaxed input sections. (Output_section::add_input_section_for_script): Take a reference to a Simple_input_section object instead of Relobj pointer and section index as parameter. Handle relaxed input sections. (Output_section::save_states, Output_section::restore_states): New method definitions. * output.h (Output_data::Output_data): Initialize is_data_size_fixed_. (Output_data::is_data_size_fixed): New method definition. (Output_data::reset_addresss_and_file_offset): Do not reset data size if it is fixed. (Output_data::address_and_file_offset_have_reset_values): New method definition. (Output_data::do_address_and_file_offset_have_reset_values): New method definition. (Output_data::set_data_size): Check that data size is not fixed. (Output_data::fix_data_size): New method definition. (Output_data::is_data_size_fixed_): New data member. (Output_section_headers::set_final_data_size): New method definition. (Output_section_headers::do_size): New method declaration. (Output_segment_headers::set_final_data_size): New method definition. (Output_segment_headers::do_size): New method declaration. (Output_file_header::set_final_data_size)::New method definition. (Output_file_header::do_size)::New method declaration. (Output_section_data::Output_section_data): Add new parameter is_data_size_fixed and use it to fix data size. (Output_data_const::Output_data_const): Adjust call to base class constructor and fix data size. (Output_data_const_buffer::Output_data_const_buffer): Adjust call to base class constructor and fix data size. (Output_data_fixed_space::Output_data_fixed_space): Adjust call to base class constructor and fix data size. (Output_data_zero_fill::Output_data_zero_fill): Adjust call to base class constructor and fix data size. (Output_data_group::set_final_data_size): New method definition. (Output_data_dynamic::Dynamic_entry::tag): New method definition. (Output_symtab_xindex::Output_symtab_xindex): Adjust call to base class constructor and fix data size. (Output_relaxed_input_section): New class definition. (Output_section::Simple_input_section): New class definition. (Output_section::get_input_sections): Adjust parameter list. (Output_section::add_input_section_for_script): Same. (Output_section::save_states, Output_section::restore_states, Output_section::do_address_and_file_offset_have_reset_values, (Output_section::Input_section::Input_section): Handle RELAXED_INPUT_SECTION_CODE. Add new overload for Output_relaxed_input_section. (Output_section::Input_section::is_input_section, Output_section::Input_section::set_output_section): Handle relaxed input section. (Output_section::Input_section::is_relaxed_input_section, Output_section::Input_section::output_section_data, Output_section::Input_section::relaxed_input_section): New method definitions. (Output_section::Input_section::RELAXED_INPUT_SECTION_CODE): New enum value. (Output_section::Input_section::u1_): Update comments. (Output_section::Input_section::u2_): Add new union member poris. (Output_section::Checkpoint_output_section): New classs definition. (Output_section::relax_input_section): New method declaration. (Output_section::checkpoint_): New data member. (Output_segment): Update comments. (Output_segment::Output_segment): Un-privatize copy constructor. (Output_segment::operator=): Un-privatize. * script-sections.cc (Output_section_element::Input_section_list): Change element type to Output_section::Simple_input_section. (Output_section_element_dot_assignment::set_section_addresses): Register output section data for relaxation clean up. (Output_data_exression::Output_data_expression): Adjust call to base constructor to fix data size. (Output_section_element_data::set_section_addresses): Register Output_data_expression object for relaxation clean up. (struct Input_section_info): Replace Relobj pointer and section index pair with Output_section::Simple_input_section and Convert struct to a class. (Input_section_sorter::operator()): Adjust access to Input_section_info data member to use accessors. (Output_section_element_input::set_section_addresses): Use layout parameter. Adjust code to use Output_section::Simple_input_section and Input_secction_info classes. Register filler for relaxation clean up. (Orphan_output_section::set_section_addresses): Replace Relobj pointer and section index pair with Output_section::Simple_input_section class. Adjust code accordingly. (Phdrs_element::release_segment): New method definition. (Script_sections::attach_sections_using_phdrs_clause): Do not modify segment list. (Script_sections::release_segments): New method definition. * gold/script-sections.h (Script_sections::release_segments): New method declaration. * gold/target.h (Target::may_relax, Target::relax, Target::do_may_relax, Target::do_relax): New method definitions.
This commit is contained in:
@ -524,7 +524,7 @@ class Output_section_element
|
||||
{
|
||||
public:
|
||||
// A list of input sections.
|
||||
typedef std::list<std::pair<Relobj*, unsigned int> > Input_section_list;
|
||||
typedef std::list<Output_section::Simple_input_section> Input_section_list;
|
||||
|
||||
Output_section_element()
|
||||
{ }
|
||||
@ -701,6 +701,7 @@ Output_section_element_dot_assignment::set_section_addresses(
|
||||
posd = new Output_data_const(this_fill, 0);
|
||||
}
|
||||
output_section->add_output_section_data(posd);
|
||||
layout->new_output_section_data_from_script(posd);
|
||||
}
|
||||
*dot_value = next_dot;
|
||||
}
|
||||
@ -736,7 +737,7 @@ class Output_data_expression : public Output_section_data
|
||||
Output_data_expression(int size, bool is_signed, Expression* val,
|
||||
const Symbol_table* symtab, const Layout* layout,
|
||||
uint64_t dot_value, Output_section* dot_section)
|
||||
: Output_section_data(size, 0),
|
||||
: Output_section_data(size, 0, true),
|
||||
is_signed_(is_signed), val_(val), symtab_(symtab),
|
||||
layout_(layout), dot_value_(dot_value), dot_section_(dot_section)
|
||||
{ }
|
||||
@ -877,13 +878,11 @@ Output_section_element_data::set_section_addresses(
|
||||
Input_section_list*)
|
||||
{
|
||||
gold_assert(os != NULL);
|
||||
os->add_output_section_data(new Output_data_expression(this->size_,
|
||||
this->is_signed_,
|
||||
this->val_,
|
||||
symtab,
|
||||
layout,
|
||||
*dot_value,
|
||||
*dot_section));
|
||||
Output_data_expression* expression =
|
||||
new Output_data_expression(this->size_, this->is_signed_, this->val_,
|
||||
symtab, layout, *dot_value, *dot_section);
|
||||
os->add_output_section_data(expression);
|
||||
layout->new_output_section_data_from_script(expression);
|
||||
*dot_value += this->size_;
|
||||
}
|
||||
|
||||
@ -1169,13 +1168,68 @@ Output_section_element_input::match_name(const char* file_name,
|
||||
|
||||
// Information we use to sort the input sections.
|
||||
|
||||
struct Input_section_info
|
||||
class Input_section_info
|
||||
{
|
||||
Relobj* relobj;
|
||||
unsigned int shndx;
|
||||
std::string section_name;
|
||||
uint64_t size;
|
||||
uint64_t addralign;
|
||||
public:
|
||||
Input_section_info(const Output_section::Simple_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&
|
||||
input_section() const
|
||||
{ return this->input_section_; }
|
||||
|
||||
// Return the object.
|
||||
Relobj*
|
||||
relobj() const
|
||||
{ return this->input_section_.relobj(); }
|
||||
|
||||
// Return the section index.
|
||||
unsigned int
|
||||
shndx()
|
||||
{ return this->input_section_.shndx(); }
|
||||
|
||||
// Return the section name.
|
||||
const std::string&
|
||||
section_name() const
|
||||
{ return this->section_name_; }
|
||||
|
||||
// Set the section name.
|
||||
void
|
||||
set_section_name(const std::string name)
|
||||
{ this->section_name_ = name; }
|
||||
|
||||
// Return the section size.
|
||||
uint64_t
|
||||
size() const
|
||||
{ return this->size_; }
|
||||
|
||||
// Set the section size.
|
||||
void
|
||||
set_size(uint64_t size)
|
||||
{ this->size_ = size; }
|
||||
|
||||
// Return the address alignment.
|
||||
uint64_t
|
||||
addralign() const
|
||||
{ return this->addralign_; }
|
||||
|
||||
// Set the address alignment.
|
||||
void
|
||||
set_addralign(uint64_t addralign)
|
||||
{ this->addralign_ = addralign; }
|
||||
|
||||
private:
|
||||
// Input section, can be a relaxed section.
|
||||
Output_section::Simple_input_section input_section_;
|
||||
// Name of the section.
|
||||
std::string section_name_;
|
||||
// Section size.
|
||||
uint64_t size_;
|
||||
// Address alignment.
|
||||
uint64_t addralign_;
|
||||
};
|
||||
|
||||
// A class to sort the input sections.
|
||||
@ -1202,22 +1256,22 @@ Input_section_sorter::operator()(const Input_section_info& isi1,
|
||||
if (this->section_sort_ == SORT_WILDCARD_BY_NAME
|
||||
|| this->section_sort_ == SORT_WILDCARD_BY_NAME_BY_ALIGNMENT
|
||||
|| (this->section_sort_ == SORT_WILDCARD_BY_ALIGNMENT_BY_NAME
|
||||
&& isi1.addralign == isi2.addralign))
|
||||
&& isi1.addralign() == isi2.addralign()))
|
||||
{
|
||||
if (isi1.section_name != isi2.section_name)
|
||||
return isi1.section_name < isi2.section_name;
|
||||
if (isi1.section_name() != isi2.section_name())
|
||||
return isi1.section_name() < isi2.section_name();
|
||||
}
|
||||
if (this->section_sort_ == SORT_WILDCARD_BY_ALIGNMENT
|
||||
|| this->section_sort_ == SORT_WILDCARD_BY_NAME_BY_ALIGNMENT
|
||||
|| this->section_sort_ == SORT_WILDCARD_BY_ALIGNMENT_BY_NAME)
|
||||
{
|
||||
if (isi1.addralign != isi2.addralign)
|
||||
return isi1.addralign < isi2.addralign;
|
||||
if (isi1.addralign() != isi2.addralign())
|
||||
return isi1.addralign() < isi2.addralign();
|
||||
}
|
||||
if (this->filename_sort_ == SORT_WILDCARD_BY_NAME)
|
||||
{
|
||||
if (isi1.relobj->name() != isi2.relobj->name())
|
||||
return isi1.relobj->name() < isi2.relobj->name();
|
||||
if (isi1.relobj()->name() != isi2.relobj()->name())
|
||||
return (isi1.relobj()->name() < isi2.relobj()->name());
|
||||
}
|
||||
|
||||
// Otherwise we leave them in the same order.
|
||||
@ -1231,7 +1285,7 @@ Input_section_sorter::operator()(const Input_section_info& isi1,
|
||||
void
|
||||
Output_section_element_input::set_section_addresses(
|
||||
Symbol_table*,
|
||||
Layout*,
|
||||
Layout* layout,
|
||||
Output_section* output_section,
|
||||
uint64_t subalign,
|
||||
uint64_t* dot_value,
|
||||
@ -1255,25 +1309,29 @@ Output_section_element_input::set_section_addresses(
|
||||
Input_section_list::iterator p = input_sections->begin();
|
||||
while (p != input_sections->end())
|
||||
{
|
||||
Relobj* relobj = p->relobj();
|
||||
unsigned int shndx = p->shndx();
|
||||
Input_section_info isi(*p);
|
||||
|
||||
// Calling section_name and section_addralign is not very
|
||||
// efficient.
|
||||
Input_section_info isi;
|
||||
isi.relobj = p->first;
|
||||
isi.shndx = p->second;
|
||||
|
||||
// Lock the object so that we can get information about the
|
||||
// section. This is OK since we know we are single-threaded
|
||||
// here.
|
||||
{
|
||||
const Task* task = reinterpret_cast<const Task*>(-1);
|
||||
Task_lock_obj<Object> tl(task, p->first);
|
||||
Task_lock_obj<Object> tl(task, relobj);
|
||||
|
||||
isi.section_name = p->first->section_name(p->second);
|
||||
isi.size = p->first->section_size(p->second);
|
||||
isi.addralign = p->first->section_addralign(p->second);
|
||||
isi.set_section_name(relobj->section_name(shndx));
|
||||
if (p->is_relaxed_input_section())
|
||||
isi.set_size(p->relaxed_input_section()->data_size());
|
||||
else
|
||||
isi.set_size(relobj->section_size(shndx));
|
||||
isi.set_addralign(relobj->section_addralign(shndx));
|
||||
}
|
||||
|
||||
if (!this->match_file_name(isi.relobj->name().c_str()))
|
||||
if (!this->match_file_name(relobj->name().c_str()))
|
||||
++p;
|
||||
else if (this->input_section_patterns_.empty())
|
||||
{
|
||||
@ -1287,7 +1345,7 @@ Output_section_element_input::set_section_addresses(
|
||||
{
|
||||
const Input_section_pattern&
|
||||
isp(this->input_section_patterns_[i]);
|
||||
if (match(isi.section_name.c_str(), isp.pattern.c_str(),
|
||||
if (match(isi.section_name().c_str(), isp.pattern.c_str(),
|
||||
isp.pattern_is_wildcard))
|
||||
break;
|
||||
}
|
||||
@ -1327,7 +1385,7 @@ Output_section_element_input::set_section_addresses(
|
||||
p != matching_sections[i].end();
|
||||
++p)
|
||||
{
|
||||
uint64_t this_subalign = p->addralign;
|
||||
uint64_t this_subalign = p->addralign();
|
||||
if (this_subalign < subalign)
|
||||
this_subalign = subalign;
|
||||
|
||||
@ -1340,14 +1398,14 @@ Output_section_element_input::set_section_addresses(
|
||||
std::string this_fill = this->get_fill_string(fill, length);
|
||||
Output_section_data* posd = new Output_data_const(this_fill, 0);
|
||||
output_section->add_output_section_data(posd);
|
||||
layout->new_output_section_data_from_script(posd);
|
||||
}
|
||||
|
||||
output_section->add_input_section_for_script(p->relobj,
|
||||
p->shndx,
|
||||
p->size,
|
||||
output_section->add_input_section_for_script(p->input_section(),
|
||||
p->size(),
|
||||
this_subalign);
|
||||
|
||||
*dot_value = address + p->size;
|
||||
*dot_value = address + p->size();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2202,7 +2260,7 @@ Orphan_output_section::set_section_addresses(Symbol_table*, Layout*,
|
||||
uint64_t* dot_value,
|
||||
uint64_t* load_address)
|
||||
{
|
||||
typedef std::list<std::pair<Relobj*, unsigned int> > Input_section_list;
|
||||
typedef std::list<Output_section::Simple_input_section> Input_section_list;
|
||||
|
||||
bool have_load_address = *load_address != *dot_value;
|
||||
|
||||
@ -2231,14 +2289,16 @@ Orphan_output_section::set_section_addresses(Symbol_table*, Layout*,
|
||||
// object.
|
||||
{
|
||||
const Task* task = reinterpret_cast<const Task*>(-1);
|
||||
Task_lock_obj<Object> tl(task, p->first);
|
||||
addralign = p->first->section_addralign(p->second);
|
||||
size = p->first->section_size(p->second);
|
||||
Task_lock_obj<Object> tl(task, p->relobj());
|
||||
addralign = p->relobj()->section_addralign(p->shndx());
|
||||
if (p->is_relaxed_input_section())
|
||||
size = p->relaxed_input_section()->data_size();
|
||||
else
|
||||
size = p->relobj()->section_size(p->shndx());
|
||||
}
|
||||
|
||||
address = align_address(address, addralign);
|
||||
this->os_->add_input_section_for_script(p->first, p->second, size,
|
||||
addralign);
|
||||
this->os_->add_input_section_for_script(*p, size, addralign);
|
||||
address += size;
|
||||
}
|
||||
|
||||
@ -2333,6 +2393,11 @@ class Phdrs_element
|
||||
segment()
|
||||
{ return this->segment_; }
|
||||
|
||||
// Release the segment.
|
||||
void
|
||||
release_segment()
|
||||
{ this->segment_ = NULL; }
|
||||
|
||||
// Set the segment flags if appropriate.
|
||||
void
|
||||
set_flags_if_valid()
|
||||
@ -3165,12 +3230,15 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout)
|
||||
// Output sections in the script which do not list segments are
|
||||
// attached to the same set of segments as the immediately preceding
|
||||
// output section.
|
||||
|
||||
String_list* phdr_names = NULL;
|
||||
bool load_segments_only = false;
|
||||
for (Sections_elements::const_iterator p = this->sections_elements_->begin();
|
||||
p != this->sections_elements_->end();
|
||||
++p)
|
||||
{
|
||||
bool orphan;
|
||||
String_list* old_phdr_names = phdr_names;
|
||||
Output_section* os = (*p)->allocate_to_segment(&phdr_names, &orphan);
|
||||
if (os == NULL)
|
||||
continue;
|
||||
@ -3181,6 +3249,11 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout)
|
||||
continue;
|
||||
}
|
||||
|
||||
// We see a list of segments names. Disable PT_LOAD segment only
|
||||
// filtering.
|
||||
if (old_phdr_names != phdr_names)
|
||||
load_segments_only = false;
|
||||
|
||||
// If this is an orphan section--one that was not explicitly
|
||||
// mentioned in the linker script--then it should not inherit
|
||||
// any segment type other than PT_LOAD. Otherwise, e.g., the
|
||||
@ -3189,17 +3262,9 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout)
|
||||
// we trust the linker script.
|
||||
if (orphan)
|
||||
{
|
||||
String_list::iterator q = phdr_names->begin();
|
||||
while (q != phdr_names->end())
|
||||
{
|
||||
Name_to_segment::const_iterator r = name_to_segment.find(*q);
|
||||
// We give errors about unknown segments below.
|
||||
if (r == name_to_segment.end()
|
||||
|| r->second->type() == elfcpp::PT_LOAD)
|
||||
++q;
|
||||
else
|
||||
q = phdr_names->erase(q);
|
||||
}
|
||||
// Enable PT_LOAD segments only filtering until we see another
|
||||
// list of segment names.
|
||||
load_segments_only = true;
|
||||
}
|
||||
|
||||
bool in_load_segment = false;
|
||||
@ -3212,6 +3277,10 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout)
|
||||
gold_error(_("no segment %s"), q->c_str());
|
||||
else
|
||||
{
|
||||
if (load_segments_only
|
||||
&& r->second->type() != elfcpp::PT_LOAD)
|
||||
continue;
|
||||
|
||||
elfcpp::Elf_Word seg_flags =
|
||||
Layout::section_flags_to_segment(os->flags());
|
||||
r->second->add_output_section(os, seg_flags);
|
||||
@ -3366,6 +3435,21 @@ Script_sections::get_output_section_info(const char* name, uint64_t* address,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Release all Output_segments. This remove all pointers to all
|
||||
// Output_segments.
|
||||
|
||||
void
|
||||
Script_sections::release_segments()
|
||||
{
|
||||
if (this->saw_phdrs_clause())
|
||||
{
|
||||
for (Phdrs_elements::const_iterator p = this->phdrs_elements_->begin();
|
||||
p != this->phdrs_elements_->end();
|
||||
++p)
|
||||
(*p)->release_segment();
|
||||
}
|
||||
}
|
||||
|
||||
// Print the SECTIONS clause to F for debugging.
|
||||
|
||||
void
|
||||
|
Reference in New Issue
Block a user