aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/ChangeLog9
-rw-r--r--ld/ldexp.c2
-rw-r--r--ld/ldlang.c33
-rw-r--r--ld/scripttempl/elf.sc6
4 files changed, 33 insertions, 17 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 6b929aa..b8c506f 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,5 +1,14 @@
2015-04-01 Alan Modra <amodra@gmail.com>
+ * ldlang.c (lang_size_sections): When alignment of sections
+ results in relro base adjustment being too large, don't go lower
+ than the initial value.
+ * ldexp.c (fold_binary <DATA_SEGMENT_RELRO_END>): Comment.
+ * scripttempl/elf.sc (DATA_SEGMENT_ALIGN): Omit SEGMENT_SIZE
+ alignment when SEGMENT_SIZE is the same as MAXPAGESIZE.
+
+2015-04-01 Alan Modra <amodra@gmail.com>
+
* emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation): Don't
init ehdr_start_save.
diff --git a/ld/ldexp.c b/ld/ldexp.c
index ac66cc0..9cd9e29 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -588,6 +588,8 @@ fold_binary (etree_type *tree)
break;
case DATA_SEGMENT_RELRO_END:
+ /* Operands swapped! DATA_SEGMENT_RELRO_END(offset,exp)
+ has offset in expld.result and exp in lhs. */
expld.dataseg.relro = exp_dataseg_relro_end;
if (expld.phase == lang_first_phase_enum
|| expld.section != bfd_abs_section_ptr)
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 8880821..13e7b1a 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -5382,20 +5382,20 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions)
if (expld.dataseg.phase == exp_dataseg_end_seen
&& link_info.relro && expld.dataseg.relro_end)
{
- /* If DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END pair was seen, try
- to put expld.dataseg.relro_end on a (common) page boundary. */
- bfd_vma min_base, relro_end, maxpage;
+ bfd_vma initial_base, min_base, relro_end, maxpage;
expld.dataseg.phase = exp_dataseg_relro_adjust;
maxpage = expld.dataseg.maxpagesize;
- /* MIN_BASE is the absolute minimum address we are allowed to start the
- read-write segment (byte before will be mapped read-only). */
- min_base = (expld.dataseg.min_base + maxpage - 1) & ~(maxpage - 1);
+ initial_base = expld.dataseg.base;
+ /* Try to put expld.dataseg.relro_end on a (common) page boundary. */
expld.dataseg.base += (-expld.dataseg.relro_end
& (expld.dataseg.pagesize - 1));
/* Compute the expected PT_GNU_RELRO segment end. */
relro_end = ((expld.dataseg.relro_end + expld.dataseg.pagesize - 1)
& ~(expld.dataseg.pagesize - 1));
+ /* MIN_BASE is the absolute minimum address we are allowed to start the
+ read-write segment (byte before will be mapped read-only). */
+ min_base = (expld.dataseg.min_base + maxpage - 1) & ~(maxpage - 1);
if (min_base + maxpage < expld.dataseg.base)
{
expld.dataseg.base -= maxpage;
@@ -5420,16 +5420,17 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions)
&& sec->alignment_power > max_alignment_power)
max_alignment_power = sec->alignment_power;
- if (((bfd_vma) 1 << max_alignment_power) < expld.dataseg.pagesize)
- {
- /* Aligning the adjusted base guarantees the padding
- between sections won't change. This is better than
- simply subtracting 1 << max_alignment_power which is
- what we used to do here. */
- expld.dataseg.base &= ~((1 << max_alignment_power) - 1);
- lang_reset_memory_regions ();
- one_lang_size_sections_pass (relax, check_regions);
- }
+ /* Aligning the adjusted base guarantees the padding
+ between sections won't change. This is better than
+ simply subtracting 1 << max_alignment_power which is
+ what we used to do here. */
+ expld.dataseg.base &= ~((1 << max_alignment_power) - 1);
+ /* It doesn't make much sense to go lower than the initial
+ base. That can only increase padding. */
+ if (expld.dataseg.base < initial_base)
+ expld.dataseg.base = initial_base;
+ lang_reset_memory_regions ();
+ one_lang_size_sections_pass (relax, check_regions);
}
link_info.relro_start = expld.dataseg.base;
link_info.relro_end = expld.dataseg.relro_end;
diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc
index c9c80b0..b4f52eb 100644
--- a/ld/scripttempl/elf.sc
+++ b/ld/scripttempl/elf.sc
@@ -128,7 +128,11 @@ DATA_SEGMENT_ALIGN="ALIGN(${SEGMENT_SIZE}) + (. & (${MAXPAGESIZE} - 1))"
DATA_SEGMENT_RELRO_END=""
DATA_SEGMENT_END=""
if test -n "${COMMONPAGESIZE}"; then
- DATA_SEGMENT_ALIGN="ALIGN (${SEGMENT_SIZE}) - ((${MAXPAGESIZE} - .) & (${MAXPAGESIZE} - 1)); . = DATA_SEGMENT_ALIGN (${MAXPAGESIZE}, ${COMMONPAGESIZE})"
+ if test "${SEGMENT_SIZE}" != "${MAXPAGESIZE}"; then
+ DATA_SEGMENT_ALIGN="ALIGN (${SEGMENT_SIZE}) - ((${MAXPAGESIZE} - .) & (${MAXPAGESIZE} - 1)); . = DATA_SEGMENT_ALIGN (${MAXPAGESIZE}, ${COMMONPAGESIZE})"
+ else
+ DATA_SEGMENT_ALIGN="DATA_SEGMENT_ALIGN (${MAXPAGESIZE}, ${COMMONPAGESIZE})"
+ fi
DATA_SEGMENT_END=". = DATA_SEGMENT_END (.);"
DATA_SEGMENT_RELRO_END=". = DATA_SEGMENT_RELRO_END (${SEPARATE_GOTPLT-0}, .);"
fi