summaryrefslogtreecommitdiff
path: root/ld/ldexp.c
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2017-11-12 17:20:09 -0800
committerH.J. Lu <hjl.tools@gmail.com>2017-11-12 17:20:18 -0800
commitd7475e036f69ff7ac78252db74a65fe4d617c4ee (patch)
tree4237220550a51952121c7c342638e49ebe60310b /ld/ldexp.c
parent0f99513f2a52b7d73b94a1f77b8c6de9159b50d7 (diff)
downloadbinutils-gdb-d7475e036f69ff7ac78252db74a65fe4d617c4ee.tar.gz
ld: Add fold_segment_align/fold_segment_relro_end/fold_segment_end
Extract DATA_SEGMENT_END/DATA_SEGMENT_ALIGN/DATA_SEGMENT_RELRO_END cases for GNU_RELRO segment into separate functions so that they can also be used for text-only LOAD segment. * ldexp.c (fold_unary): Extract the DATA_SEGMENT_END case to ... (fold_segment_end): New function. (fold_binary): Extract the DATA_SEGMENT_ALIGN case to ... (fold_segment_align): New function. (fold_binary): Extract the DATA_SEGMENT_RELRO_END case to ... (fold_segment_relro_end): New function.
Diffstat (limited to 'ld/ldexp.c')
-rw-r--r--ld/ldexp.c194
1 files changed, 105 insertions, 89 deletions
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 5633e507148..83d9f8f2a7f 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -343,6 +343,30 @@ update_definedness (const char *name, struct bfd_link_hash_entry *h)
}
static void
+fold_segment_end (seg_align_type *seg)
+{
+ if (expld.phase == lang_first_phase_enum
+ || expld.section != bfd_abs_section_ptr)
+ {
+ expld.result.valid_p = FALSE;
+ }
+ else if (seg->phase == exp_seg_align_seen
+ || seg->phase == exp_seg_relro_seen)
+ {
+ seg->phase = exp_seg_end_seen;
+ seg->end = expld.result.value;
+ }
+ else if (seg->phase == exp_seg_done
+ || seg->phase == exp_seg_adjust
+ || seg->phase == exp_seg_relro_adjust)
+ {
+ /* OK. */
+ }
+ else
+ expld.result.valid_p = FALSE;
+}
+
+static void
fold_unary (etree_type *tree)
{
exp_fold_tree_1 (tree->unary.child);
@@ -389,25 +413,7 @@ fold_unary (etree_type *tree)
break;
case DATA_SEGMENT_END:
- if (expld.phase == lang_first_phase_enum
- || expld.section != bfd_abs_section_ptr)
- {
- expld.result.valid_p = FALSE;
- }
- else if (expld.dataseg.phase == exp_seg_align_seen
- || expld.dataseg.phase == exp_seg_relro_seen)
- {
- expld.dataseg.phase = exp_seg_end_seen;
- expld.dataseg.end = expld.result.value;
- }
- else if (expld.dataseg.phase == exp_seg_done
- || expld.dataseg.phase == exp_seg_adjust
- || expld.dataseg.phase == exp_seg_relro_adjust)
- {
- /* OK. */
- }
- else
- expld.result.valid_p = FALSE;
+ fold_segment_end (&expld.dataseg);
break;
default:
@@ -444,6 +450,84 @@ arith_result_section (const etree_value_type *lhs)
}
static void
+fold_segment_align (seg_align_type *seg, etree_value_type *lhs)
+{
+ seg->relro = exp_seg_relro_start;
+ if (expld.phase == lang_first_phase_enum
+ || expld.section != bfd_abs_section_ptr)
+ expld.result.valid_p = FALSE;
+ else
+ {
+ bfd_vma maxpage = lhs->value;
+ bfd_vma commonpage = expld.result.value;
+
+ expld.result.value = align_n (expld.dot, maxpage);
+ if (seg->phase == exp_seg_relro_adjust)
+ expld.result.value = seg->base;
+ else if (seg->phase == exp_seg_adjust)
+ {
+ if (commonpage < maxpage)
+ expld.result.value += ((expld.dot + commonpage - 1)
+ & (maxpage - commonpage));
+ }
+ else
+ {
+ expld.result.value += expld.dot & (maxpage - 1);
+ if (seg->phase == exp_seg_done)
+ {
+ /* OK. */
+ }
+ else if (seg->phase == exp_seg_none)
+ {
+ seg->phase = exp_seg_align_seen;
+ seg->base = expld.result.value;
+ seg->pagesize = commonpage;
+ seg->maxpagesize = maxpage;
+ seg->relro_end = 0;
+ }
+ else
+ expld.result.valid_p = FALSE;
+ }
+ }
+}
+
+static void
+fold_segment_relro_end (seg_align_type *seg, etree_value_type *lhs)
+{
+ /* Operands swapped! XXX_SEGMENT_RELRO_END(offset,exp) has offset
+ in expld.result and exp in lhs. */
+ seg->relro = exp_seg_relro_end;
+ seg->relro_offset = expld.result.value;
+ if (expld.phase == lang_first_phase_enum
+ || expld.section != bfd_abs_section_ptr)
+ expld.result.valid_p = FALSE;
+ else if (seg->phase == exp_seg_align_seen
+ || seg->phase == exp_seg_adjust
+ || seg->phase == exp_seg_relro_adjust
+ || seg->phase == exp_seg_done)
+ {
+ if (seg->phase == exp_seg_align_seen
+ || seg->phase == exp_seg_relro_adjust)
+ seg->relro_end = lhs->value + expld.result.value;
+
+ if (seg->phase == exp_seg_relro_adjust
+ && (seg->relro_end & (seg->pagesize - 1)))
+ {
+ seg->relro_end += seg->pagesize - 1;
+ seg->relro_end &= ~(seg->pagesize - 1);
+ expld.result.value = seg->relro_end - expld.result.value;
+ }
+ else
+ expld.result.value = lhs->value;
+
+ if (seg->phase == exp_seg_align_seen)
+ seg->phase = exp_seg_relro_seen;
+ }
+ else
+ expld.result.valid_p = FALSE;
+}
+
+static void
fold_binary (etree_type *tree)
{
etree_value_type lhs;
@@ -573,79 +657,11 @@ fold_binary (etree_type *tree)
break;
case DATA_SEGMENT_ALIGN:
- expld.dataseg.relro = exp_seg_relro_start;
- if (expld.phase == lang_first_phase_enum
- || expld.section != bfd_abs_section_ptr)
- expld.result.valid_p = FALSE;
- else
- {
- bfd_vma maxpage = lhs.value;
- bfd_vma commonpage = expld.result.value;
-
- expld.result.value = align_n (expld.dot, maxpage);
- if (expld.dataseg.phase == exp_seg_relro_adjust)
- expld.result.value = expld.dataseg.base;
- else if (expld.dataseg.phase == exp_seg_adjust)
- {
- if (commonpage < maxpage)
- expld.result.value += ((expld.dot + commonpage - 1)
- & (maxpage - commonpage));
- }
- else
- {
- expld.result.value += expld.dot & (maxpage - 1);
- if (expld.dataseg.phase == exp_seg_done)
- {
- /* OK. */
- }
- else if (expld.dataseg.phase == exp_seg_none)
- {
- expld.dataseg.phase = exp_seg_align_seen;
- expld.dataseg.base = expld.result.value;
- expld.dataseg.pagesize = commonpage;
- expld.dataseg.maxpagesize = maxpage;
- expld.dataseg.relro_end = 0;
- }
- else
- expld.result.valid_p = FALSE;
- }
- }
+ fold_segment_align (&expld.dataseg, &lhs);
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_seg_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;
- else if (expld.dataseg.phase == exp_seg_align_seen
- || expld.dataseg.phase == exp_seg_adjust
- || expld.dataseg.phase == exp_seg_relro_adjust
- || expld.dataseg.phase == exp_seg_done)
- {
- if (expld.dataseg.phase == exp_seg_align_seen
- || expld.dataseg.phase == exp_seg_relro_adjust)
- expld.dataseg.relro_end = lhs.value + expld.result.value;
-
- if (expld.dataseg.phase == exp_seg_relro_adjust
- && (expld.dataseg.relro_end
- & (expld.dataseg.pagesize - 1)))
- {
- expld.dataseg.relro_end += expld.dataseg.pagesize - 1;
- expld.dataseg.relro_end &= ~(expld.dataseg.pagesize - 1);
- expld.result.value = (expld.dataseg.relro_end
- - expld.result.value);
- }
- else
- expld.result.value = lhs.value;
-
- if (expld.dataseg.phase == exp_seg_align_seen)
- expld.dataseg.phase = exp_seg_relro_seen;
- }
- else
- expld.result.valid_p = FALSE;
+ fold_segment_relro_end (&expld.dataseg, &lhs);
break;
default: