aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/ChangeLog9
-rw-r--r--ld/ldexp.c2
-rw-r--r--ld/ldexp.h2
-rw-r--r--ld/ldlang.c73
-rw-r--r--ld/testsuite/ChangeLog4
-rw-r--r--ld/testsuite/ld-x86-64/pr18176.d2
6 files changed, 50 insertions, 42 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index b9b75fb..104963d 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,12 @@
+2015-04-22 Alan Modra <amodra@gmail.com>
+
+ * ldexp.h (struct ldexp_control): Delete dataseg.min_base. Add
+ data_seg.relro_offset.
+ * ldexp.c (fold_binary <DATA_SEGMENT_ALIGN>): Don't set min_base.
+ (fold_binary <DATA_SEGMENT_RELRO_END>): Do set relro_offset.
+ * ldlang.c (lang_size_sections): Rewrite code adjusting relro
+ segment base to line up last section on page boundary.
+
2015-04-15 H.J. Lu <hongjiu.lu@intel.com>
* NEWS: Mention
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 9cd9e29..a5192b1 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -575,7 +575,6 @@ fold_binary (etree_type *tree)
else if (expld.dataseg.phase == exp_dataseg_none)
{
expld.dataseg.phase = exp_dataseg_align_seen;
- expld.dataseg.min_base = expld.dot;
expld.dataseg.base = expld.result.value;
expld.dataseg.pagesize = commonpage;
expld.dataseg.maxpagesize = maxpage;
@@ -591,6 +590,7 @@ fold_binary (etree_type *tree)
/* Operands swapped! DATA_SEGMENT_RELRO_END(offset,exp)
has offset in expld.result and exp in lhs. */
expld.dataseg.relro = exp_dataseg_relro_end;
+ expld.dataseg.relro_offset = expld.result.value;
if (expld.phase == lang_first_phase_enum
|| expld.section != bfd_abs_section_ptr)
expld.result.valid_p = FALSE;
diff --git a/ld/ldexp.h b/ld/ldexp.h
index 10fcf3d..f61df6b 100644
--- a/ld/ldexp.h
+++ b/ld/ldexp.h
@@ -156,7 +156,7 @@ struct ldexp_control {
struct {
enum phase_enum phase;
- bfd_vma base, min_base, relro_end, end, pagesize, maxpagesize;
+ bfd_vma base, relro_offset, relro_end, end, pagesize, maxpagesize;
enum relro_enum relro;
diff --git a/ld/ldlang.c b/ld/ldlang.c
index b074169..c96c21f 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -5382,56 +5382,51 @@ 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)
{
- bfd_vma initial_base, min_base, relro_end, maxpage;
+ bfd_vma initial_base, relro_end, desired_end;
+ asection *sec;
- expld.dataseg.phase = exp_dataseg_relro_adjust;
- maxpage = expld.dataseg.maxpagesize;
- 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;
- relro_end -= maxpage;
- }
+
+ /* Adjust by the offset arg of DATA_SEGMENT_RELRO_END. */
+ desired_end = relro_end - expld.dataseg.relro_offset;
+
+ /* For sections in the relro segment.. */
+ for (sec = link_info.output_bfd->section_last; sec; sec = sec->prev)
+ if (!IGNORE_SECTION (sec)
+ && sec->vma >= expld.dataseg.base
+ && sec->vma < expld.dataseg.relro_end - expld.dataseg.relro_offset)
+ {
+ /* Where do we want to put this section so that it ends as
+ desired? */
+ bfd_vma start = sec->vma;
+ bfd_vma end = start + sec->size;
+ bfd_vma bump = desired_end - end;
+ /* We'd like to increase START by BUMP, but we must heed
+ alignment so the increase might be less than optimum. */
+ start += bump & ~(((bfd_vma) 1 << sec->alignment_power) - 1);
+ /* This is now the desired end for the previous section. */
+ desired_end = start;
+ }
+
+ expld.dataseg.phase = exp_dataseg_relro_adjust;
+ ASSERT (desired_end >= expld.dataseg.base);
+ initial_base = expld.dataseg.base;
+ expld.dataseg.base = desired_end;
lang_reset_memory_regions ();
one_lang_size_sections_pass (relax, check_regions);
+
if (expld.dataseg.relro_end > relro_end)
{
- /* The alignment of sections between DATA_SEGMENT_ALIGN
- and DATA_SEGMENT_RELRO_END can cause excessive padding to
- be inserted at DATA_SEGMENT_RELRO_END. Try to start a
- bit lower so that the section alignments will fit in. */
- asection *sec;
- unsigned int max_alignment_power = 0;
-
- /* Find maximum alignment power of sections between
- DATA_SEGMENT_ALIGN and DATA_SEGMENT_RELRO_END. */
- for (sec = link_info.output_bfd->sections; sec; sec = sec->next)
- if (sec->vma >= expld.dataseg.base
- && sec->vma < expld.dataseg.relro_end
- && sec->alignment_power > max_alignment_power)
- max_alignment_power = sec->alignment_power;
-
- /* 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 &= ~(((bfd_vma) 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;
+ /* Assignments to dot, or to output section address in a
+ user script have increased padding over the original.
+ Revert. */
+ 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/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index ea6a863..8c37da2 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2015-04-22 Alan Modra <amodra@gmail.com>
+
+ * ld-x86-64/pr18176.d: Update.
+
2015-04-22 H.J. Lu <hongjiu.lu@intel.com>
PR ld/18289
diff --git a/ld/testsuite/ld-x86-64/pr18176.d b/ld/testsuite/ld-x86-64/pr18176.d
index 3a08539..4e3ad9f 100644
--- a/ld/testsuite/ld-x86-64/pr18176.d
+++ b/ld/testsuite/ld-x86-64/pr18176.d
@@ -5,5 +5,5 @@
#target: x86_64-*-linux*
#...
- GNU_RELRO 0x04bd07 0x000000000024bd07 0x000000000024bd07 0x0022f9 0x0022f9 R 0x1
+ GNU_RELRO 0x04bd17 0x000000000024bd17 0x000000000024bd17 0x0022e9 0x0022e9 R 0x1
#pass