aboutsummaryrefslogtreecommitdiff
path: root/gold/layout.cc
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2012-05-02 21:37:24 +0000
committerRoland McGrath <roland@gnu.org>2012-05-02 21:37:24 +0000
commit2e702c99c59f581594820852c607394c25bc9bd2 (patch)
treec3470ee3efb4025a07ff95b5135a5ec80febb849 /gold/layout.cc
parent1ef7171746433c3161d7d4b3c50a93f67d52c4a2 (diff)
downloadgdb-2e702c99c59f581594820852c607394c25bc9bd2.zip
gdb-2e702c99c59f581594820852c607394c25bc9bd2.tar.gz
gdb-2e702c99c59f581594820852c607394c25bc9bd2.tar.bz2
* configure.ac (ENABLE_GOLD): Consider *-*-nacl* targets ELF.
* configure: Regenerate. gold/ * nacl.cc: New file. * nacl.h: New file. * Makefile.am (CCFILES, HFILES): Add them. * Makefile.in: Regenerate. * i386.cc (Output_data_plt_i386_nacl): New class. (Output_data_plt_i386_nacl_exec): New class. (Output_data_plt_i386_nacl_dyn): New class. (Target_i386_nacl): New class. (Target_selector_i386_nacl): New class. (target_selector_i386): Use it instead of Target_selector_i386. * x86_64.cc (Output_data_plt_x86_64_nacl): New class. (Target_x86_64_nacl): New class. (Target_selector_x86_64_nacl): New class. (target_selector_x86_64, target_selector_x32): Use it instead of Target_selector_x86_64. * arm.cc (Output_data_plt_arm_nacl): New class. (Target_arm_nacl): New class. (Target_selector_arm_nacl): New class. (target_selector_arm, target_selector_armbe): Use it instead of Target_selector_arm. * target-select.cc (select_target): Take new Input_file* and off_t arguments, pass them on to recognize method of selector. * object.cc (make_elf_sized_object): Update caller. * parameters.cc (parameters_force_valid_target): Likewise. * incremental.cc (make_sized_incremental_binary): Likewise. * target-select.h: Update decl. (Target_selector::recognize): Take new Input_file* argument, pass it on to do_recognize. (Target_selector::do_recognize): Take new Input_file* argument. * freebsd.h (Target_selector_freebsd::do_recognize): Likewise. * powerpc.cc (Target_selector_powerpc::do_recognize): Likewise. * sparc.cc (Target_selector_sparc::do_recognize): Likewise. * testsuite/testfile.cc (Target_selector::do_recognize): Likewise. * target.h (Target::Target_info): New members isolate_execinstr and rosegment_gap. (Target::isolate_execinstr, Target::rosegment_gap): New methods. * arm.cc (Target_arm::arm_info): Update initializer. * i386.cc (Target_i386::i386_info): Likewise. * powerpc.cc (Target_powerpc::powerpc_info): Likewise. * sparc.cc (Target_sparc::sparc_info): Likewise. * x86_64.cc (Target_x86_64::x86_64_info): Likewise. * testsuite/testfile.cc (Target_test::test_target_info): Likewise. * layout.cc (Layout::attach_allocated_section_to_segment): Take new const Target* argument. If target->isolate_execinstr(), act like --rosegment. (Layout::find_first_load_seg): Take new const Target* argument; if target->isolate_execinstr(), reject PF_X segments. (Layout::relaxation_loop_body): Update caller. (Layout::set_segment_offsets): If target->isolate_execinstr(), reset file offset to zero when we hit LOAD_SEG, and then do a second loop over the segments before LOAD_SEG to reassign offsets after addresses have been determined. Handle target->rosegment_gap(). (Layout::attach_section_to_segment): Take new const Target* argument; pass it to attach_allocated_section_to_segment. (Layout::make_output_section): Update caller. (Layout::attach_sections_to_segments): Take new const Target* argument; pass it to attach_section_to_segment. * gold.cc (queue_middle_tasks): Update caller. * layout.h (Layout): Update method decls with new arguments. * arm.cc (Target_arm::Target_arm): Take optional argument for the Target_info pointer to use. (Target_arm::do_make_data_plt): New virtual method. (Target_arm::make_data_plt): New method that calls it. (Target_arm::make_plt_entry): Use it. (Output_data_plt_arm::Output_data_plt_arm): Take additional argument for the section alignment. (Output_data_plt_arm::do_first_plt_entry_offset): New abstract virtual method. (Output_data_plt_arm::first_plt_entry_offset): Call it. (Output_data_plt_arm::do_get_plt_entry_size): New abstract virtual method. (Output_data_plt_arm::get_plt_entry_size): Call it. (Output_data_plt_arm::do_fill_plt_entry): New abstract virtual method. (Output_data_plt_arm::fill_plt_entry): New method that calls it. (Output_data_plt_arm::do_fill_first_plt_entry): New abstract virtual method. (Output_data_plt_arm::fill_first_plt_entry): New method that calls it. (Output_data_plt_arm::set_final_data_size): Use get_plt_entry_size method instead of sizeof(plt_entry). (Output_data_plt_arm::add_entry): Likewise. Use first_plt_entry_offset method instead of sizeof(first_plt_entry). (Target_arm::first_plt_entry_offset): Call method on this->plt_ rather than static method. (Target_arm::plt_entry_size): Likewise. (Output_data_plt_arm::first_plt_entry, Output_data_plt_arm::plt_entry): Move to ... (Output_data_plt_arm_standard): ... here, new class. (Output_data_plt_arm::do_write): Move guts of PLT filling to... (Output_data_plt_arm_standard::do_fill_first_plt_entry): ... here ... (Output_data_plt_arm_standard::do_fill_plt_entry): ... and here. * x86_64.cc (Output_data_plt_x86_64::Output_data_plt_x86_64): Take additional argument for the PLT entry size. (Output_data_plt_x86_64::get_tlsdesc_plt_offset): Use get_plt_entry_size method rather than plt_entry_size variable. (Output_data_plt_x86_64::reserve_slot): Likewise. (Output_data_plt_x86_64::do_adjust_output_section): Likewise. (Output_data_plt_x86_64::add_entry): Likewise. (Output_data_plt_x86_64::add_local_ifunc_entry): Likewise. (Output_data_plt_x86_64::address_for_global): Likewise. (Output_data_plt_x86_64::address_for_local): Likewise. (Output_data_plt_x86_64::set_final_data_size): Likewise. (Output_data_plt_x86_64::first_plt_entry_offset): Likewise. Make method non-static. (Output_data_plt_x86_64::do_get_plt_entry_size): New abstract virtual method. (Output_data_plt_x86_64::get_plt_entry_size): Just call that. (Output_data_plt_x86_64::do_add_eh_frame): New abstract virtual method. (Output_data_plt_x86_64::add_eh_frame): New method to call it. (Output_data_plt_x86_64::do_fill_first_plt_entry): New abstract virtual method. (Output_data_plt_x86_64::fill_first_plt_entry): New method to call it. (Output_data_plt_x86_64::do_fill_plt_entry): New abstract virtual method. (Output_data_plt_x86_64::fill_plt_entry): New method to call it. (Output_data_plt_x86_64::do_fill_tlsdesc_entry): New abstract virtual method. (Output_data_plt_x86_64::fill_tlsdesc_entry): New method to call it. (Output_data_plt_x86_64::plt_entry_size) (Output_data_plt_x86_64::first_plt_entry) (Output_data_plt_x86_64::plt_entry) (Output_data_plt_x86_64::tlsdesc_plt_entry) (Output_data_plt_x86_64::plt_eh_frame_fde_size) (Output_data_plt_x86_64::plt_eh_frame_fde): Move to ... (Output_data_plt_x86_64_standard): ... here, new class. (Target_x86_64::Target_x86_64): Take optional argument for the Target_info pointer to use. (Target_x86_64::do_make_data_plt): New virtual method. (Target_x86_64::make_data_plt): New method to call it. (Target_x86_64::init_got_plt_for_update): Use that. Call this->plt_->add_eh_frame method here. (Output_data_plt_x86_64::init): Don't do add_eh_frame_for_plt here. (Target_x86_64::first_plt_entry_offset): Call method on this->plt_ rather than static method. (Target_x86_64::plt_entry_size): Likewise. (Output_data_plt_x86_64::do_write): Use get_plt_entry_size method rather than plt_entry_size variable. Move guts of PLT filling to... (Output_data_plt_x86_64_standard::do_fill_first_plt_entry): ... here ... (Output_data_plt_x86_64_standard::do_fill_plt_entry): ... and here ... (Output_data_plt_x86_64_standard::do_fill_tlsdesc_entry): ... and here. * i386.cc (Output_data_plt_i386::Output_data_plt_i386): Take additional argument for the section alignment. Don't do add_eh_frame_for_plt here. (Output_data_plt_i386::first_plt_entry_offset): Make the method non-static. Use get_plt_entry_size method rather than plt_entry_size variable. (Output_data_plt_i386::do_get_plt_entry_size): New abstract virtual method. (Output_data_plt_i386::get_plt_entry_size): Call it. (Output_data_plt_i386::do_add_eh_frame): New abstract virtual method. (Output_data_plt_i386::add_eh_frame): New method to call it. (Output_data_plt_i386::do_fill_first_plt_entry): New abstract virtual method. (Output_data_plt_i386::fill_first_plt_entry): New method to call it. (Output_data_plt_i386::do_fill_plt_entry): New abstract virtual method. (Output_data_plt_i386::fill_plt_entry): New method to call it. (Output_data_plt_i386::set_final_data_size): Use get_plt_entry_size method instead of plt_entry_size. (Output_data_plt_i386::plt_entry_size) (Output_data_plt_i386::plt_eh_frame_fde_size) (Output_data_plt_i386::plt_eh_frame_fde): Move to ... (Output_data_plt_i386_standard): ... here, new class. (Output_data_plt_i386_exec): New class. (Output_data_plt_i386::exec_first_plt_entry): Move to ... (Output_data_plt_i386_exec::first_plt_entry): ... here. (Output_data_plt_i386::exec_plt_entry): Move to ... (Output_data_plt_i386_exec::plt_entry): ... here. (Output_data_plt_i386_dyn): New class. (Output_data_plt_i386::first_plt_entry): Move to ... (Output_data_plt_i386_dyn::first_plt_entry): ... here. (Output_data_plt_i386::dyn_plt_entry): Move to ... (Output_data_plt_i386_dyn::plt_entry): ... here. (Target_i386::Target_i386): Take optional argument for the Target_info pointer to use. (Target_i386::do_make_data_plt): New virtual method. (Target_i386::make_data_plt): New method to call it. (Target_i386::make_plt_section): Use that. Call this->plt_->add_eh_frame method here. (Output_data_plt_i386::add_entry): Use get_plt_entry_size method rather than plt_entry_size variable. (Output_data_plt_i386::add_local_ifunc_entry): Likewise. (Output_data_plt_i386::address_for_local): Likewise. (Output_data_plt_i386::do_write): Likewise. Move guts of PLT filling to... (Output_data_plt_i386_exec::do_fill_first_plt_entry): ... here ... (Output_data_plt_i386_exec::do_fill_plt_entry): ... and here ... (Output_data_plt_i386_dyn::do_fill_first_plt_entry): ... and here ... (Output_data_plt_i386_dyn::do_fill_plt_entry): ... and here. Change-Id: Id24b95600489835ff5e860a39c147203d4380c2b
Diffstat (limited to 'gold/layout.cc')
-rw-r--r--gold/layout.cc463
1 files changed, 273 insertions, 190 deletions
diff --git a/gold/layout.cc b/gold/layout.cc
index 65d1432..7155f22 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -1,6 +1,7 @@
// layout.cc -- lay out output file sections for gold
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -155,9 +156,9 @@ off_t
Free_list::allocate(off_t len, uint64_t align, off_t minoff)
{
gold_debug(DEBUG_INCREMENTAL,
- "Free_list::allocate(%08lx, %d, %08lx)",
- static_cast<long>(len), static_cast<int>(align),
- static_cast<long>(minoff));
+ "Free_list::allocate(%08lx, %d, %08lx)",
+ static_cast<long>(len), static_cast<int>(align),
+ static_cast<long>(minoff));
if (len == 0)
return align_address(minoff, align);
@@ -222,17 +223,17 @@ void
Free_list::print_stats()
{
fprintf(stderr, _("%s: total free lists: %u\n"),
- program_name, Free_list::num_lists);
+ program_name, Free_list::num_lists);
fprintf(stderr, _("%s: total free list nodes: %u\n"),
- program_name, Free_list::num_nodes);
+ program_name, Free_list::num_nodes);
fprintf(stderr, _("%s: calls to Free_list::remove: %u\n"),
- program_name, Free_list::num_removes);
+ program_name, Free_list::num_removes);
fprintf(stderr, _("%s: nodes visited: %u\n"),
- program_name, Free_list::num_remove_visits);
+ program_name, Free_list::num_remove_visits);
fprintf(stderr, _("%s: calls to Free_list::allocate: %u\n"),
- program_name, Free_list::num_allocates);
+ program_name, Free_list::num_allocates);
fprintf(stderr, _("%s: nodes visited: %u\n"),
- program_name, Free_list::num_allocate_visits);
+ program_name, Free_list::num_allocate_visits);
}
// Layout::Relaxation_debug_check methods.
@@ -256,7 +257,7 @@ Layout::Relaxation_debug_check::check_output_data_for_reset_values(
++p)
gold_assert((*p)->address_and_file_offset_have_reset_values());
}
-
+
// Save information of SECTIONS for checking later.
void
@@ -319,7 +320,7 @@ Layout_task_runner::run(Workqueue* workqueue, const Task* task)
Layout* layout = this->layout_;
off_t file_size = layout->finalize(this->input_objects_,
this->symtab_,
- this->target_,
+ this->target_,
task);
// Now we know the final size of the output file and we know where
@@ -349,8 +350,8 @@ Layout_task_runner::run(Workqueue* workqueue, const Task* task)
// incremental information from the file before (possibly)
// overwriting it.
if (parameters->incremental_update())
- layout->incremental_base()->apply_incremental_relocs(this->symtab_,
- this->layout_,
+ layout->incremental_base()->apply_incremental_relocs(this->symtab_,
+ this->layout_,
of);
of->resize(file_size);
@@ -579,7 +580,7 @@ Layout::include_section(Sized_relobj_file<size, big_endian>*, const char* name,
{
// Debugging sections can only be recognized by name.
if (is_prefix_of(".debug", name)
- && !is_lines_only_debug_section(name))
+ && !is_lines_only_debug_section(name))
return false;
}
if (parameters->options().strip_debug_gdb()
@@ -587,17 +588,17 @@ Layout::include_section(Sized_relobj_file<size, big_endian>*, const char* name,
{
// Debugging sections can only be recognized by name.
if (is_prefix_of(".debug", name)
- && !is_gdb_debug_section(name))
+ && !is_gdb_debug_section(name))
return false;
}
if (parameters->options().strip_lto_sections()
- && !parameters->options().relocatable()
- && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
- {
- // Ignore LTO sections containing intermediate code.
- if (is_prefix_of(".gnu.lto_", name))
- return false;
- }
+ && !parameters->options().relocatable()
+ && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
+ {
+ // Ignore LTO sections containing intermediate code.
+ if (is_prefix_of(".gnu.lto_", name))
+ return false;
+ }
// The GNU linker strips .gnu_debuglink sections, so we do too.
// This is a feature used to keep debugging information in
// separate files.
@@ -713,27 +714,27 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key,
if (lookup_type == elfcpp::SHT_PROGBITS)
{
- if (flags == 0)
- {
- Output_section* same_name = this->find_output_section(name);
- if (same_name != NULL
- && (same_name->type() == elfcpp::SHT_PROGBITS
+ if (flags == 0)
+ {
+ Output_section* same_name = this->find_output_section(name);
+ if (same_name != NULL
+ && (same_name->type() == elfcpp::SHT_PROGBITS
|| same_name->type() == elfcpp::SHT_INIT_ARRAY
|| same_name->type() == elfcpp::SHT_FINI_ARRAY
|| same_name->type() == elfcpp::SHT_PREINIT_ARRAY)
- && (same_name->flags() & elfcpp::SHF_TLS) == 0)
- os = same_name;
- }
- else if ((flags & elfcpp::SHF_TLS) == 0)
- {
- elfcpp::Elf_Xword zero_flags = 0;
- const Key zero_key(name_key, std::make_pair(lookup_type,
+ && (same_name->flags() & elfcpp::SHF_TLS) == 0)
+ os = same_name;
+ }
+ else if ((flags & elfcpp::SHF_TLS) == 0)
+ {
+ elfcpp::Elf_Xword zero_flags = 0;
+ const Key zero_key(name_key, std::make_pair(lookup_type,
zero_flags));
- Section_name_map::iterator p =
- this->section_name_map_.find(zero_key);
- if (p != this->section_name_map_.end())
+ Section_name_map::iterator p =
+ this->section_name_map_.find(zero_key);
+ if (p != this->section_name_map_.end())
os = p->second;
- }
+ }
}
if (os == NULL)
@@ -925,7 +926,7 @@ Layout::init_fixed_output_section(const char* name,
Stringpool::Key name_key;
name = this->namepool_.add(name, true, &name_key);
Output_section* os = this->get_output_section(name, name_key, sh_type,
- sh_flags, ORDER_INVALID, false);
+ sh_flags, ORDER_INVALID, false);
os->set_fixed_layout(sh_addr, sh_offset, sh_size, sh_addralign);
if (sh_type != elfcpp::SHT_NOBITS)
this->free_list_.remove(sh_offset, sh_offset + sh_size);
@@ -1321,7 +1322,7 @@ Layout::add_to_gdb_index(bool is_type_unit,
false, ORDER_INVALID,
false);
if (os == NULL)
- return;
+ return;
this->gdb_index_data_ = new Gdb_index(os);
os->add_output_section_data(this->gdb_index_data_);
@@ -1379,22 +1380,22 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
os = new Output_compressed_section(&parameters->options(), name, type,
flags);
else if ((flags & elfcpp::SHF_ALLOC) == 0
- && parameters->options().strip_debug_non_line()
- && strcmp(".debug_abbrev", name) == 0)
+ && parameters->options().strip_debug_non_line()
+ && strcmp(".debug_abbrev", name) == 0)
{
os = this->debug_abbrev_ = new Output_reduced_debug_abbrev_section(
- name, type, flags);
+ name, type, flags);
if (this->debug_info_)
- this->debug_info_->set_abbreviations(this->debug_abbrev_);
+ this->debug_info_->set_abbreviations(this->debug_abbrev_);
}
else if ((flags & elfcpp::SHF_ALLOC) == 0
- && parameters->options().strip_debug_non_line()
- && strcmp(".debug_info", name) == 0)
+ && parameters->options().strip_debug_non_line()
+ && strcmp(".debug_info", name) == 0)
{
os = this->debug_info_ = new Output_reduced_debug_info_section(
- name, type, flags);
+ name, type, flags);
if (this->debug_abbrev_)
- this->debug_info_->set_abbreviations(this->debug_abbrev_);
+ this->debug_info_->set_abbreviations(this->debug_abbrev_);
}
else
{
@@ -1497,18 +1498,18 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
// a minimum size, so we must prevent allocations from the
// free list that leave a hole smaller than the minimum.
if (strcmp(name, ".debug_info") == 0)
- os->set_free_space_fill(new Output_fill_debug_info(false));
+ os->set_free_space_fill(new Output_fill_debug_info(false));
else if (strcmp(name, ".debug_types") == 0)
- os->set_free_space_fill(new Output_fill_debug_info(true));
+ os->set_free_space_fill(new Output_fill_debug_info(true));
else if (strcmp(name, ".debug_line") == 0)
- os->set_free_space_fill(new Output_fill_debug_line());
+ os->set_free_space_fill(new Output_fill_debug_line());
}
// If we have already attached the sections to segments, then we
// need to attach this one now. This happens for sections created
// directly by the linker.
if (this->sections_are_attached_)
- this->attach_section_to_segment(os);
+ this->attach_section_to_segment(&parameters->target(), os);
return os;
}
@@ -1585,12 +1586,12 @@ Layout::default_section_order(Output_section* os, bool is_relro_local)
// seen all the input sections.
void
-Layout::attach_sections_to_segments()
+Layout::attach_sections_to_segments(const Target* target)
{
for (Section_list::iterator p = this->section_list_.begin();
p != this->section_list_.end();
++p)
- this->attach_section_to_segment(*p);
+ this->attach_section_to_segment(target, *p);
this->sections_are_attached_ = true;
}
@@ -1598,18 +1599,19 @@ Layout::attach_sections_to_segments()
// Attach an output section to a segment.
void
-Layout::attach_section_to_segment(Output_section* os)
+Layout::attach_section_to_segment(const Target* target, Output_section* os)
{
if ((os->flags() & elfcpp::SHF_ALLOC) == 0)
this->unattached_section_list_.push_back(os);
else
- this->attach_allocated_section_to_segment(os);
+ this->attach_allocated_section_to_segment(target, os);
}
// Attach an allocated output section to a segment.
void
-Layout::attach_allocated_section_to_segment(Output_section* os)
+Layout::attach_allocated_section_to_segment(const Target* target,
+ Output_section* os)
{
elfcpp::Elf_Xword flags = os->flags();
gold_assert((flags & elfcpp::SHF_ALLOC) != 0);
@@ -1649,9 +1651,9 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
if (!parameters->options().omagic()
&& ((*p)->flags() & elfcpp::PF_W) != (seg_flags & elfcpp::PF_W))
continue;
- if (parameters->options().rosegment()
- && ((*p)->flags() & elfcpp::PF_X) != (seg_flags & elfcpp::PF_X))
- continue;
+ if ((target->isolate_execinstr() || parameters->options().rosegment())
+ && ((*p)->flags() & elfcpp::PF_X) != (seg_flags & elfcpp::PF_X))
+ continue;
// If -Tbss was specified, we need to separate the data and BSS
// segments.
if (parameters->options().user_set_Tbss())
@@ -1681,7 +1683,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
if (p == this->segment_list_.end())
{
Output_segment* oseg = this->make_output_segment(elfcpp::PT_LOAD,
- seg_flags);
+ seg_flags);
if (os->is_large_data_section())
oseg->set_is_large_data_segment();
oseg->add_output_section_to_load(this, os, seg_flags);
@@ -1695,24 +1697,24 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
{
// See if we already have an equivalent PT_NOTE segment.
for (p = this->segment_list_.begin();
- p != segment_list_.end();
- ++p)
- {
- if ((*p)->type() == elfcpp::PT_NOTE
- && (((*p)->flags() & elfcpp::PF_W)
- == (seg_flags & elfcpp::PF_W)))
- {
- (*p)->add_output_section_to_nonload(os, seg_flags);
- break;
- }
- }
+ p != segment_list_.end();
+ ++p)
+ {
+ if ((*p)->type() == elfcpp::PT_NOTE
+ && (((*p)->flags() & elfcpp::PF_W)
+ == (seg_flags & elfcpp::PF_W)))
+ {
+ (*p)->add_output_section_to_nonload(os, seg_flags);
+ break;
+ }
+ }
if (p == this->segment_list_.end())
- {
- Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE,
- seg_flags);
- oseg->add_output_section_to_nonload(os, seg_flags);
- }
+ {
+ Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE,
+ seg_flags);
+ oseg->add_output_section_to_nonload(os, seg_flags);
+ }
}
// If we see a loadable SHF_TLS section, we create a PT_TLS
@@ -1883,9 +1885,9 @@ Layout::define_section_symbols(Symbol_table* symtab)
{
const std::string name_string(name);
const std::string start_name(cident_section_start_prefix
- + name_string);
+ + name_string);
const std::string stop_name(cident_section_stop_prefix
- + name_string);
+ + name_string);
symtab->define_in_output_data(start_name.c_str(),
NULL, // version
@@ -1951,7 +1953,7 @@ Layout::define_group_signatures(Symbol_table* symtab)
// necessary.
Output_segment*
-Layout::find_first_load_seg()
+Layout::find_first_load_seg(const Target* target)
{
Output_segment* best = NULL;
for (Segment_list::const_iterator p = this->segment_list_.begin();
@@ -1961,11 +1963,13 @@ Layout::find_first_load_seg()
if ((*p)->type() == elfcpp::PT_LOAD
&& ((*p)->flags() & elfcpp::PF_R) != 0
&& (parameters->options().omagic()
- || ((*p)->flags() & elfcpp::PF_W) == 0))
- {
- if (best == NULL || this->segment_precedes(*p, best))
- best = *p;
- }
+ || ((*p)->flags() & elfcpp::PF_W) == 0)
+ && (!target->isolate_execinstr()
+ || ((*p)->flags() & elfcpp::PF_X) == 0))
+ {
+ if (best == NULL || this->segment_precedes(*p, best))
+ best = *p;
+ }
}
if (best != NULL)
return best;
@@ -2023,10 +2027,10 @@ Layout::restore_segments(const Segment_states* segment_states)
this->relro_segment_ = segment;
++list_iter;
- }
+ }
else
{
- list_iter = this->segment_list_.erase(list_iter);
+ list_iter = this->segment_list_.erase(list_iter);
// This is a segment created during section layout. It should be
// safe to remove it since we should have removed all pointers to it.
delete segment;
@@ -2059,7 +2063,7 @@ Layout::clean_up_after_relaxation()
(*p)->reset_address_and_file_offset();
}
-
+
// Reset special output object address and file offsets.
for (Data_list::iterator p = this->special_output_list_.begin();
p != this->special_output_list_.end();
@@ -2073,7 +2077,7 @@ Layout::clean_up_after_relaxation()
p != this->script_output_section_data_list_.end();
++p)
delete *p;
- this->script_output_section_data_list_.clear();
+ this->script_output_section_data_list_.clear();
}
// Prepare for relaxation.
@@ -2096,7 +2100,7 @@ Layout::prepare_for_relaxation()
if (is_debugging_enabled(DEBUG_RELAXATION))
this->relaxation_debug_check_->check_output_data_for_reset_values(
- this->section_list_, this->special_output_list_);
+ this->section_list_, this->special_output_list_);
// Also enable recording of output section data from scripts.
this->record_output_section_data_from_script_ = true;
@@ -2105,7 +2109,7 @@ Layout::prepare_for_relaxation()
// Relaxation loop body: If target has no relaxation, this runs only once
// Otherwise, the target relaxation hook is called at the end of
// each iteration. If the hook returns true, it means re-layout of
-// section is required.
+// section is required.
//
// The number of segments created by a linking script without a PHDRS
// clause may be affected by section sizes and alignments. There is
@@ -2115,8 +2119,8 @@ Layout::prepare_for_relaxation()
// layout. In order to be able to restart the section layout, we keep
// a copy of the segment list right before the relaxation loop and use
// that to restore the segments.
-//
-// PASS is the current relaxation pass number.
+//
+// PASS is the current relaxation pass number.
// SYMTAB is a symbol table.
// PLOAD_SEG is the address of a pointer for the load segment.
// PHDR_SEG is a pointer to the PHDR segment.
@@ -2148,7 +2152,7 @@ Layout::relaxation_loop_body(
else if (parameters->options().relocatable())
load_seg = NULL;
else
- load_seg = this->find_first_load_seg();
+ load_seg = this->find_first_load_seg(target);
if (parameters->options().oformat_enum()
!= General_options::OBJECT_FORMAT_ELF)
@@ -2205,9 +2209,9 @@ Layout::relaxation_loop_body(
load_seg->add_initial_output_data(z);
}
if (load_seg != NULL)
- load_seg->add_initial_output_data(segment_headers);
+ load_seg->add_initial_output_data(segment_headers);
if (phdr_seg != NULL)
- phdr_seg->add_initial_output_data(segment_headers);
+ phdr_seg->add_initial_output_data(segment_headers);
}
// Lay out the file header.
@@ -2268,11 +2272,11 @@ Layout::find_section_order_index(const std::string& section_name)
++it)
{
if (fnmatch((*it).c_str(), section_name.c_str(), FNM_NOESCAPE) == 0)
- {
- map_it = this->input_section_position_.find(*it);
- gold_assert(map_it != this->input_section_position_.end());
- return map_it->second;
- }
+ {
+ map_it = this->input_section_position_.find(*it);
+ gold_assert(map_it != this->input_section_position_.end());
+ return map_it->second;
+ }
}
return 0;
}
@@ -2290,7 +2294,7 @@ Layout::read_layout_from_file()
in.open(filename);
if (!in)
gold_fatal(_("unable to open --section-ordering-file file %s: %s"),
- filename, strerror(errno));
+ filename, strerror(errno));
std::getline(in, line); // this chops off the trailing \n, if any
unsigned int position = 1;
@@ -2299,17 +2303,17 @@ Layout::read_layout_from_file()
while (in)
{
if (!line.empty() && line[line.length() - 1] == '\r') // Windows
- line.resize(line.length() - 1);
+ line.resize(line.length() - 1);
// Ignore comments, beginning with '#'
if (line[0] == '#')
- {
- std::getline(in, line);
- continue;
- }
+ {
+ std::getline(in, line);
+ continue;
+ }
this->input_section_position_[line] = position;
// Store all glob patterns in a vector.
if (is_wildcard_string(line.c_str()))
- this->input_section_glob_.push_back(line);
+ this->input_section_glob_.push_back(line);
position++;
std::getline(in, line);
}
@@ -2373,7 +2377,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
std::vector<Symbol*> dynamic_symbols;
unsigned int local_dynamic_count;
Versions versions(*this->script_options()->version_script_info(),
- &this->dynpool_);
+ &this->dynpool_);
this->create_dynamic_symtab(input_objects, symtab, &dynstr,
&local_dynamic_count, &dynamic_symbols,
&versions);
@@ -2384,7 +2388,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
if ((!parameters->options().shared()
|| parameters->options().dynamic_linker() != NULL)
&& this->interp_segment_ == NULL)
- this->create_interp(target);
+ this->create_interp(target);
// Finish the .dynamic section to hold the dynamic data, and put
// it in a PT_DYNAMIC segment.
@@ -2403,7 +2407,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
// after we call create_version_sections.
this->set_dynamic_symbol_size(symtab);
}
-
+
// Create segment headers.
Output_segment_headers* segment_headers =
(parameters->options().relocatable()
@@ -2422,7 +2426,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
// a linker script.
if (this->script_options_->saw_sections_clause())
this->place_orphan_sections_in_script();
-
+
Output_segment* load_seg;
off_t off;
unsigned int shndx;
@@ -2431,7 +2435,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
// Take a snapshot of the section layout as needed.
if (target->may_relax())
this->prepare_for_relaxation();
-
+
// Run the relaxation loop to lay out sections.
do
{
@@ -2873,8 +2877,8 @@ Layout::create_incremental_info_sections(Symbol_table* symtab)
const char* incremental_strtab_name =
this->namepool_.add(".gnu_incremental_strtab", false, NULL);
Output_section* incremental_strtab_os = this->make_output_section(incremental_strtab_name,
- elfcpp::SHT_STRTAB, 0,
- ORDER_INVALID, false);
+ elfcpp::SHT_STRTAB, 0,
+ ORDER_INVALID, false);
Output_data_strtab* strtab_data =
new Output_data_strtab(incr->get_stringpool());
incremental_strtab_os->add_output_section_data(strtab_data);
@@ -3054,13 +3058,15 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
// Find the PT_LOAD segments, and set their addresses and offsets
// and their section's addresses and offsets.
- uint64_t addr;
+ uint64_t start_addr;
if (parameters->options().user_set_Ttext())
- addr = parameters->options().Ttext();
+ start_addr = parameters->options().Ttext();
else if (parameters->options().output_is_position_independent())
- addr = 0;
+ start_addr = 0;
else
- addr = target->default_text_segment_address();
+ start_addr = target->default_text_segment_address();
+
+ uint64_t addr = start_addr;
off_t off = 0;
// If LOAD_SEG is NULL, then the file header and segment headers
@@ -3085,15 +3091,39 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
const bool check_sections = parameters->options().check_sections();
Output_segment* last_load_segment = NULL;
+ unsigned int shndx_begin = *pshndx;
+ unsigned int shndx_load_seg = *pshndx;
+
for (Segment_list::iterator p = this->segment_list_.begin();
p != this->segment_list_.end();
++p)
{
if ((*p)->type() == elfcpp::PT_LOAD)
{
- if (load_seg != NULL && load_seg != *p)
- gold_unreachable();
- load_seg = NULL;
+ if (target->isolate_execinstr())
+ {
+ // When we hit the segment that should contain the
+ // file headers, reset the file offset so we place
+ // it and subsequent segments appropriately.
+ // We'll fix up the preceding segments below.
+ if (load_seg == *p)
+ {
+ if (off == 0)
+ load_seg = NULL;
+ else
+ {
+ off = 0;
+ shndx_load_seg = *pshndx;
+ }
+ }
+ }
+ else
+ {
+ // Verify that the file headers fall into the first segment.
+ if (load_seg != NULL && load_seg != *p)
+ gold_unreachable();
+ load_seg = NULL;
+ }
bool are_addresses_set = (*p)->are_addresses_set();
if (are_addresses_set)
@@ -3145,16 +3175,37 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
addr = align_address(addr, (*p)->maximum_alignment());
aligned_addr = addr;
- if ((addr & (abi_pagesize - 1)) != 0)
- addr = addr + abi_pagesize;
+ if (load_seg == *p)
+ {
+ // This is the segment that will contain the file
+ // headers, so its offset will have to be exactly zero.
+ gold_assert(orig_off == 0);
+
+ // If the target wants a fixed minimum distance from the
+ // text segment to the read-only segment, move up now.
+ uint64_t min_addr = start_addr + target->rosegment_gap();
+ if (addr < min_addr)
+ addr = min_addr;
+
+ // But this is not the first segment! To make its
+ // address congruent with its offset, that address better
+ // be aligned to the ABI-mandated page size.
+ addr = align_address(addr, abi_pagesize);
+ aligned_addr = addr;
+ }
+ else
+ {
+ if ((addr & (abi_pagesize - 1)) != 0)
+ addr = addr + abi_pagesize;
- off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
+ off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
+ }
}
if (!parameters->options().nmagic()
&& !parameters->options().omagic())
off = align_file_offset(off, addr, abi_pagesize);
- else if (load_seg == NULL)
+ else
{
// This is -N or -n with a section script which prevents
// us from using a load segment. We need to ensure that
@@ -3173,7 +3224,7 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
uint64_t new_addr = (*p)->set_section_addresses(this, false, addr,
&increase_relro,
&has_relro,
- &off, pshndx);
+ &off, pshndx);
// Now that we know the size of this segment, we may be able
// to save a page in memory, at the cost of wasting some
@@ -3212,7 +3263,7 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
new_addr = (*p)->set_section_addresses(this, true, addr,
&increase_relro,
&has_relro,
- &off, pshndx);
+ &off, pshndx);
}
}
@@ -3239,6 +3290,38 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
}
}
+ if (load_seg != NULL && target->isolate_execinstr())
+ {
+ // Process the early segments again, setting their file offsets
+ // so they land after the segments starting at LOAD_SEG.
+ off = align_file_offset(off, 0, target->abi_pagesize());
+
+ for (Segment_list::iterator p = this->segment_list_.begin();
+ *p != load_seg;
+ ++p)
+ {
+ if ((*p)->type() == elfcpp::PT_LOAD)
+ {
+ // We repeat the whole job of assigning addresses and
+ // offsets, but we really only want to change the offsets and
+ // must ensure that the addresses all come out the same as
+ // they did the first time through.
+ bool has_relro = false;
+ const uint64_t old_addr = (*p)->vaddr();
+ const uint64_t old_end = old_addr + (*p)->memsz();
+ uint64_t new_addr = (*p)->set_section_addresses(this, true,
+ old_addr,
+ &increase_relro,
+ &has_relro,
+ &off,
+ &shndx_begin);
+ gold_assert(new_addr == old_end);
+ }
+ }
+
+ gold_assert(shndx_begin == shndx_load_seg);
+ }
+
// Handle the non-PT_LOAD segments, setting their offsets from their
// section's offsets.
for (Segment_list::iterator p = this->segment_list_.begin();
@@ -3326,16 +3409,16 @@ Layout::set_section_offsets(off_t off, Layout::Section_offset_pass pass)
}
if (pass == BEFORE_INPUT_SECTIONS_PASS
- && (*p)->after_input_sections())
- continue;
+ && (*p)->after_input_sections())
+ continue;
else if (pass == POSTPROCESSING_SECTIONS_PASS
- && (!(*p)->after_input_sections()
- || (*p)->type() == elfcpp::SHT_STRTAB))
- continue;
+ && (!(*p)->after_input_sections()
+ || (*p)->type() == elfcpp::SHT_STRTAB))
+ continue;
else if (pass == STRTAB_AFTER_POSTPROCESSING_SECTIONS_PASS
- && (!(*p)->after_input_sections()
- || (*p)->type() != elfcpp::SHT_STRTAB))
- continue;
+ && (!(*p)->after_input_sections()
+ || (*p)->type() != elfcpp::SHT_STRTAB))
+ continue;
if (!parameters->incremental_update())
{
@@ -3352,7 +3435,7 @@ Layout::set_section_offsets(off_t off, Layout::Section_offset_pass pass)
if (off == -1)
{
if (is_debugging_enabled(DEBUG_INCREMENTAL))
- this->free_list_.dump();
+ this->free_list_.dump();
gold_assert((*p)->output_section() != NULL);
gold_fallback(_("out of patch space for section %s; "
"relink with --incremental-full"),
@@ -3377,7 +3460,7 @@ Layout::set_section_offsets(off_t off, Layout::Section_offset_pass pass)
off += (*p)->data_size();
if (off > maxoff)
- maxoff = off;
+ maxoff = off;
// At this point the name must be set.
if (pass != STRTAB_AFTER_POSTPROCESSING_SECTIONS_PASS)
@@ -3525,7 +3608,7 @@ Layout::create_symtab_sections(const Input_objects* input_objects,
++p)
{
unsigned int index = (*p)->finalize_local_symbols(local_symbol_index,
- off, symtab);
+ off, symtab);
off += (index - local_symbol_index) * symsize;
local_symbol_index = index;
}
@@ -3619,7 +3702,7 @@ Layout::create_symtab_sections(const Input_objects* input_objects,
else
{
symtab_off = this->allocate(off, align, *poff);
- if (off == -1)
+ if (off == -1)
gold_fallback(_("out of patch space for symbol table; "
"relink with --incremental-full"));
gold_debug(DEBUG_INCREMENTAL,
@@ -3722,7 +3805,7 @@ Layout::allocated_output_section_count() const
void
Layout::create_dynamic_symtab(const Input_objects* input_objects,
- Symbol_table* symtab,
+ Symbol_table* symtab,
Output_section** pdynstr,
unsigned int* plocal_dynamic_count,
std::vector<Symbol*>* pdynamic_symbols,
@@ -4301,45 +4384,45 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
{
case elfcpp::SHT_FINI_ARRAY:
odyn->add_section_address(elfcpp::DT_FINI_ARRAY, *p);
- odyn->add_section_size(elfcpp::DT_FINI_ARRAYSZ, *p);
+ odyn->add_section_size(elfcpp::DT_FINI_ARRAYSZ, *p);
break;
case elfcpp::SHT_INIT_ARRAY:
odyn->add_section_address(elfcpp::DT_INIT_ARRAY, *p);
- odyn->add_section_size(elfcpp::DT_INIT_ARRAYSZ, *p);
+ odyn->add_section_size(elfcpp::DT_INIT_ARRAYSZ, *p);
break;
case elfcpp::SHT_PREINIT_ARRAY:
odyn->add_section_address(elfcpp::DT_PREINIT_ARRAY, *p);
- odyn->add_section_size(elfcpp::DT_PREINIT_ARRAYSZ, *p);
+ odyn->add_section_size(elfcpp::DT_PREINIT_ARRAYSZ, *p);
break;
default:
break;
}
-
+
// Add a DT_RPATH entry if needed.
const General_options::Dir_list& rpath(parameters->options().rpath());
if (!rpath.empty())
{
std::string rpath_val;
for (General_options::Dir_list::const_iterator p = rpath.begin();
- p != rpath.end();
- ++p)
- {
- if (rpath_val.empty())
- rpath_val = p->name();
- else
- {
- // Eliminate duplicates.
- General_options::Dir_list::const_iterator q;
- for (q = rpath.begin(); q != p; ++q)
+ p != rpath.end();
+ ++p)
+ {
+ if (rpath_val.empty())
+ rpath_val = p->name();
+ else
+ {
+ // Eliminate duplicates.
+ General_options::Dir_list::const_iterator q;
+ for (q = rpath.begin(); q != p; ++q)
if (q->name() == p->name())
- break;
- if (q == p)
- {
- rpath_val += ':';
- rpath_val += p->name();
- }
- }
- }
+ break;
+ if (q == p)
+ {
+ rpath_val += ':';
+ rpath_val += p->name();
+ }
+ }
+ }
odyn->add_string(elfcpp::DT_RPATH, rpath_val);
if (parameters->options().enable_new_dtags())
@@ -4351,17 +4434,17 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
if (!this->script_options_->saw_sections_clause())
{
for (Segment_list::const_iterator p = this->segment_list_.begin();
- p != this->segment_list_.end();
- ++p)
- {
- if ((*p)->type() == elfcpp::PT_LOAD
+ p != this->segment_list_.end();
+ ++p)
+ {
+ if ((*p)->type() == elfcpp::PT_LOAD
&& ((*p)->flags() & elfcpp::PF_W) == 0
- && (*p)->has_dynamic_reloc())
- {
- have_textrel = true;
- break;
- }
- }
+ && (*p)->has_dynamic_reloc())
+ {
+ have_textrel = true;
+ break;
+ }
+ }
}
else
{
@@ -4370,17 +4453,17 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
// relocations. If those sections wind up in writable segments,
// then we have created an unnecessary DT_TEXTREL entry.
for (Section_list::const_iterator p = this->section_list_.begin();
- p != this->section_list_.end();
- ++p)
- {
- if (((*p)->flags() & elfcpp::SHF_ALLOC) != 0
- && ((*p)->flags() & elfcpp::SHF_WRITE) == 0
- && (*p)->has_dynamic_reloc())
- {
- have_textrel = true;
- break;
- }
- }
+ p != this->section_list_.end();
+ ++p)
+ {
+ if (((*p)->flags() & elfcpp::SHF_ALLOC) != 0
+ && ((*p)->flags() & elfcpp::SHF_WRITE) == 0
+ && (*p)->has_dynamic_reloc())
+ {
+ have_textrel = true;
+ break;
+ }
+ }
}
if (parameters->options().filter() != NULL)
@@ -4652,7 +4735,7 @@ Layout::find_or_add_kept_section(const std::string& name,
unsigned int shndx,
bool is_comdat,
bool is_group_name,
- Kept_section** kept_section)
+ Kept_section** kept_section)
{
// It's normal to see a couple of entries here, for the x86 thunk
// sections. If we see more than a few, we're linking a C++
@@ -4691,12 +4774,12 @@ Layout::find_or_add_kept_section(const std::string& name,
// If the kept group is from a plugin object, and we're in the
// replacement phase, accept the new one as a replacement.
if (ins.first->second.object() == NULL
- && parameters->options().plugins()->in_replacement_phase())
- {
+ && parameters->options().plugins()->in_replacement_phase())
+ {
ins.first->second.set_object(object);
ins.first->second.set_shndx(shndx);
- return true;
- }
+ return true;
+ }
return false;
}
else if (is_group_name)