void
Layout::Relaxation_debug_check::check_output_data_for_reset_values(
const Layout::Section_list& sections,
- const Layout::Data_list& special_outputs)
+ const Layout::Data_list& special_outputs,
+ const Layout::Data_list& relax_outputs)
{
for(Layout::Section_list::const_iterator p = sections.begin();
p != sections.end();
p != special_outputs.end();
++p)
gold_assert((*p)->address_and_file_offset_have_reset_values());
+
+ gold_assert(relax_outputs.empty());
}
// Save information of SECTIONS for checking later.
section_list_(),
unattached_section_list_(),
special_output_list_(),
+ relax_output_list_(),
section_headers_(NULL),
tls_segment_(NULL),
relro_segment_(NULL),
++p)
delete *p;
this->script_output_section_data_list_.clear();
+
+ // Special-case fill output objects are recreated each time through
+ // the relaxation loop.
+ this->reset_relax_output();
+}
+
+void
+Layout::reset_relax_output()
+{
+ for (Data_list::const_iterator p = this->relax_output_list_.begin();
+ p != this->relax_output_list_.end();
+ ++p)
+ delete *p;
+ this->relax_output_list_.clear();
}
// 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_,
+ this->relax_output_list_);
// Also enable recording of output section data from scripts.
this->record_output_section_data_from_script_ = true;
}
+// If the user set the address of the text segment, that may not be
+// compatible with putting the segment headers and file headers into
+// that segment. For isolate_execinstr() targets, it's the rodata
+// segment rather than text where we might put the headers.
+static inline bool
+load_seg_unusable_for_headers(const Target* target)
+{
+ const General_options& options = parameters->options();
+ if (target->isolate_execinstr())
+ return (options.user_set_Trodata_segment()
+ && options.Trodata_segment() % target->abi_pagesize() != 0);
+ else
+ return (options.user_set_Ttext()
+ && options.Ttext() % target->abi_pagesize() != 0);
+}
+
// 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
!= General_options::OBJECT_FORMAT_ELF)
load_seg = NULL;
- // If the user set the address of the text segment, that may not be
- // compatible with putting the segment headers and file headers into
- // that segment.
- if (parameters->options().user_set_Ttext()
- && parameters->options().Ttext() % target->abi_pagesize() != 0)
+ if (load_seg_unusable_for_headers(target))
{
load_seg = NULL;
phdr_seg = NULL;
return aligned_off;
}
+// On targets where the text segment contains only executable code,
+// a non-executable segment is never the text segment.
+
+static inline bool
+is_text_segment(const Target* target, const Output_segment* seg)
+{
+ elfcpp::Elf_Xword flags = seg->flags();
+ if ((flags & elfcpp::PF_W) != 0)
+ return false;
+ if ((flags & elfcpp::PF_X) == 0)
+ return !target->isolate_execinstr();
+ return true;
+}
+
// Set the file offsets of all the segments, and all the sections they
// contain. They have all been created. LOAD_SEG must be be laid out
// first. Return the offset of the data to follow.
}
else if (parameters->options().user_set_Ttext()
&& (parameters->options().omagic()
- || ((*p)->flags() & elfcpp::PF_W) == 0))
+ || is_text_segment(target, *p)))
{
are_addresses_set = true;
}
+ else if (parameters->options().user_set_Trodata_segment()
+ && ((*p)->flags() & (elfcpp::PF_W | elfcpp::PF_X)) == 0)
+ {
+ addr = parameters->options().Trodata_segment();
+ are_addresses_set = true;
+ }
else if (parameters->options().user_set_Tdata()
&& ((*p)->flags() & elfcpp::PF_W) != 0
&& (!parameters->options().user_set_Tbss()
unsigned int shndx_hold = *pshndx;
bool has_relro = false;
- uint64_t new_addr = (*p)->set_section_addresses(this, false, addr,
+ uint64_t new_addr = (*p)->set_section_addresses(target, this,
+ false, addr,
&increase_relro,
&has_relro,
&off, pshndx);
increase_relro = 0;
has_relro = false;
- new_addr = (*p)->set_section_addresses(this, true, addr,
+ new_addr = (*p)->set_section_addresses(target, this,
+ true, addr,
&increase_relro,
&has_relro,
&off, pshndx);
// so they land after the segments starting at LOAD_SEG.
off = align_file_offset(off, 0, target->abi_pagesize());
+ this->reset_relax_output();
+
for (Segment_list::iterator p = this->segment_list_.begin();
*p != load_seg;
++p)
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,
+ uint64_t new_addr = (*p)->set_section_addresses(target, this,
+ true, old_addr,
&increase_relro,
&has_relro,
&off,
p != this->special_output_list_.end();
++p)
(*p)->write(of);
+
+ // Write out the Output_data which are not in an Output_section
+ // and are regenerated in each iteration of relaxation.
+ for (Data_list::const_iterator p = this->relax_output_list_.begin();
+ p != this->relax_output_list_.end();
+ ++p)
+ (*p)->write(of);
}
// Write out the Output_sections which can only be written after the