diff --git a/gold/layout.cc b/gold/layout.cc index 5edba48..0ab0977 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -1166,10 +1166,11 @@ Layout::attach_allocated_section_to_segment(Output_section* os) bool is_address_set = parameters->options().section_start(os->name(), &addr); // In general the only thing we really care about for PT_LOAD - // segments is whether or not they are writable, so that is how we - // search for them. Large data sections also go into their own - // PT_LOAD segment. People who need segments sorted on some other - // basis will have to use a linker script. + // segments is whether or not they are writable or executable, + // so that is how we search for them. + // Large data sections also go into their own PT_LOAD segment. + // People who need segments sorted on some other basis will + // have to use a linker script. Segment_list::const_iterator p; for (p = this->segment_list_.begin(); @@ -1181,6 +1182,8 @@ 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 (((*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()) @@ -1449,6 +1452,7 @@ Layout::define_group_signatures(Symbol_table* symtab) Output_segment* Layout::find_first_load_seg() { + Output_segment* best = NULL; for (Segment_list::const_iterator p = this->segment_list_.begin(); p != this->segment_list_.end(); ++p) @@ -1457,8 +1461,13 @@ Layout::find_first_load_seg() && ((*p)->flags() & elfcpp::PF_R) != 0 && (parameters->options().omagic() || ((*p)->flags() & elfcpp::PF_W) == 0)) - return *p; + { + if (best == NULL || this->segment_precedes(*p, best)) + best = *p; + } } + if (best != NULL) + return best; gold_assert(!this->script_options_->saw_phdrs_clause()); @@ -2616,13 +2625,22 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, // page in the file, but the loader will put them on // different pages in memory. + // If both the last segment and this one are readonly, + // align so that the dynamic linker will not overlap + // them in memory. + addr = align_address(addr, (*p)->maximum_alignment()); aligned_addr = addr; - if (was_readonly && ((*p)->flags() & elfcpp::PF_W) != 0) + if (was_readonly) { - if ((addr & (abi_pagesize - 1)) != 0) - addr = addr + abi_pagesize; + if (((*p)->flags() & elfcpp::PF_W) != 0) + { + if ((addr & (abi_pagesize - 1)) != 0) + addr = addr + abi_pagesize; + } + else + addr = align_address(addr, abi_pagesize); } off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));