This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [patch][gold] Don't put rodata and text in the same segment.
Attached is a new version of the rosegment patch that also generalizes
and documents the logic for deciding if we should move forward by a
page.
2010-09-08 Rafael Espindola <espindola@google.com>
* layout.cc (Layout::attach_allocated_section_to_segment): Add support
for --rosegment.
(Layout::find_first_load_seg): Search all segments to find the first
one.
(Layout::set_segment_offsets): Generalize the decision of when to
move forward by a page.
* options.h (rosegment): New.
Cheers,
--
Rafael Ãvila de EspÃndola
diff --git a/gold/layout.cc b/gold/layout.cc
index bfe6a5e..c2bab29 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -1171,10 +1171,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();
@@ -1186,6 +1187,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 -Tbss was specified, we need to separate the data and BSS
// segments.
if (parameters->options().user_set_Tbss())
@@ -1454,6 +1458,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)
@@ -1462,8 +1467,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());
@@ -2567,7 +2577,7 @@ 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;
- bool was_readonly = false;
+ elfcpp::Elf_Word old_flags = -1;
for (Segment_list::iterator p = this->segment_list_.begin();
p != this->segment_list_.end();
++p)
@@ -2614,21 +2624,26 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
if (!are_addresses_set)
{
- // If the last segment was readonly, and this one is
- // not, then skip the address forward one page,
- // maintaining the same position within the page. This
- // lets us store both segments overlapping on a single
- // page in the file, but the loader will put them on
- // different pages in memory.
+ // If the R, W or X flags changed, skip the address forward one
+ // page, maintaining the same position within the page.
+ // Advancing to the next page lets the loader set the flags
+ // correctly for each segment.
+ // Maintaining the same position within the page lets us store
+ // both segments overlapping on a single page in the file, but
+ // the loader will put them on different pages in memory.
+ // We will revisit this decision once we know the size of the
+ // segment.
addr = align_address(addr, (*p)->maximum_alignment());
aligned_addr = addr;
- if (was_readonly && ((*p)->flags() & elfcpp::PF_W) != 0)
- {
- if ((addr & (abi_pagesize - 1)) != 0)
- addr = addr + abi_pagesize;
- }
+ const elfcpp::Elf_Word cur_flags =
+ ((*p)->flags() & (elfcpp::PF_W | elfcpp::PF_R | elfcpp::PF_X));
+
+ if (old_flags != static_cast<elfcpp::Elf_Word>(-1)
+ && cur_flags != old_flags
+ && (addr & (abi_pagesize - 1)) != 0)
+ addr = addr + abi_pagesize;
off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
}
@@ -2686,8 +2701,8 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
addr = new_addr;
- if (((*p)->flags() & elfcpp::PF_W) == 0)
- was_readonly = true;
+ old_flags =
+ ((*p)->flags() & (elfcpp::PF_W | elfcpp::PF_R | elfcpp::PF_X));
// Implement --check-sections. We know that the segments
// are sorted by LMA.
diff --git a/gold/options.h b/gold/options.h
index c5e24cc..c990961 100644
--- a/gold/options.h
+++ b/gold/options.h
@@ -808,6 +808,10 @@ class General_options
N_(" Only search directories specified on the command line."),
NULL);
+ DEFINE_bool(rosegment, options::TWO_DASHES, '\0', false,
+ N_(" Put read-only non-executable sections in their own segment"),
+ NULL);
+
DEFINE_string(m, options::EXACTLY_ONE_DASH, 'm', "",
N_("Ignored for compatibility"), N_("EMULATION"));