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.
> I think it would be OK to have an option to put read-only data in a
> different segment.
I see. The attached patch moves the it behind an option.
2010-09-01 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): Align the address of a read only segment
that follows a read only one.
* Makefile.am: Add a --rosegment bootstrap test.
* Makefile.in: Regenerate.
* options.h (rosegment): New.
> Ian
>
Cheers,
--
Rafael Ãvila de EspÃndola
diff --git a/gold/Makefile.am b/gold/Makefile.am
index df5e66c..5f366b4 100644
--- a/gold/Makefile.am
+++ b/gold/Makefile.am
@@ -219,6 +219,7 @@ gcctestdir1/ld: ld-new
rm -f gcctestdir1/ld
(cd gcctestdir1 && $(LN_S) ../ld-new ld)
+# regular bootstrap
ld1_SOURCES = $(sources_var)
ld1_DEPENDENCIES = $(deps_var) gcctestdir1/ld
ld1_LDADD = $(ldadd_var)
@@ -240,6 +241,29 @@ bootstrap-test: ld2
echo "cmp ld1 ld2" > $@
chmod +x $@
+# --rosegment bootstrap
+ld1_ro_SOURCES = $(sources_var)
+ld1_ro_DEPENDENCIES = $(deps_var) gcctestdir1/ld
+ld1_ro_LDADD = $(ldadd_var)
+ld1_ro_LDFLAGS = -Bgcctestdir1/ -Wl,--rosegment
+
+gcctestdir2-ro/ld: ld1-ro
+ test -d gcctestdir2-ro || mkdir -p gcctestdir2-ro
+ rm -f gcctestdir2/ld-ro
+ (cd gcctestdir2-ro && $(LN_S) ../ld1-ro ld)
+
+ld2_ro_SOURCES = $(sources_var)
+ld2_ro_DEPENDENCIES = $(deps_var) gcctestdir2-ro/ld
+ld2_ro_LDADD = $(ldadd_var)
+ld2_ro_LDFLAGS = -Bgcctestdir2-ro/ -Wl,--rosegment
+
+bootstrap-test-ro: ld2-ro
+ rm -f $@
+ echo "#!/bin/sh" > $@
+ echo "cmp ld1-ro ld2-ro" > $@
+ chmod +x $@
+
+# -r bootstrap
libgold-1-r.o: gcctestdir1/ld libgold.a
gcctestdir1/ld -o $@ -r --whole-archive libgold.a
@@ -267,8 +291,8 @@ bootstrap-test-r: ld2-r
echo "cmp ld1-r ld2-r" > $@
chmod +x $@
-check_PROGRAMS = ld1 ld2 ld1-r ld2-r
-TESTS = bootstrap-test bootstrap-test-r
+check_PROGRAMS = ld1 ld2 ld1-r ld2-r ld1-ro ld2-ro
+TESTS = bootstrap-test bootstrap-test-r bootstrap-test-ro
endif
endif
diff --git a/gold/layout.cc b/gold/layout.cc
index 5edba48..81e15a4 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,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())
@@ -1449,6 +1453,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 +1462,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 +2626,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));
diff --git a/gold/options.h b/gold/options.h
index c5e24cc..4e4730b 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_(" Use a distinct segment for ro but not executable sections."),
+ NULL);
+
DEFINE_string(m, options::EXACTLY_ONE_DASH, 'm', "",
N_("Ignored for compatibility"), N_("EMULATION"));