From 0f99513f2a52b7d73b94a1f77b8c6de9159b50d7 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Sun, 12 Nov 2017 17:17:47 -0800 Subject: [PATCH] ld: Update phase_enum/relro_enum and add seg_align_type Update GNU_RELRO date type so that they can also be used for text-only LOAD segment. * ldexp.h (phase_enum): Rename exp_dataseg_none, exp_dataseg_align_seen, exp_dataseg_relro_seen, exp_dataseg_end_seen, exp_dataseg_relro_adjust, exp_dataseg_adjust and exp_dataseg_done to exp_seg_none, exp_seg_align_seen, exp_seg_relro_seen, exp_seg_end_seen, exp_seg_relro_adjust, exp_seg_adjust and exp_seg_done. (relro_enum): Rename exp_dataseg_relro_none, exp_dataseg_relro_start and exp_dataseg_relro_end to exp_seg_relro_none, exp_seg_relro_start and exp_seg_relro_end. (seg_align_type): New struct type. (ldexp_control): Use seg_align_type. * ldexp.c (fold_unary): Updated. (fold_binary): Likewise. * ldlang.c (strip_excluded_output_sections): Likewise. (lang_size_sections_1): Likewise. (lang_size_sections): Likewise. --- ld/ChangeLog | 19 +++++++++++++++++++ ld/ldexp.c | 44 ++++++++++++++++++++++---------------------- ld/ldexp.h | 44 +++++++++++++++++++++++--------------------- ld/ldlang.c | 24 ++++++++++++------------ 4 files changed, 76 insertions(+), 55 deletions(-) diff --git a/ld/ChangeLog b/ld/ChangeLog index 5888e052196..0a39d744394 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,22 @@ +2017-11-12 H.J. Lu + + * ldexp.h (phase_enum): Rename exp_dataseg_none, + exp_dataseg_align_seen, exp_dataseg_relro_seen, + exp_dataseg_end_seen, exp_dataseg_relro_adjust, + exp_dataseg_adjust and exp_dataseg_done to exp_seg_none, + exp_seg_align_seen, exp_seg_relro_seen, exp_seg_end_seen, + exp_seg_relro_adjust, exp_seg_adjust and exp_seg_done. + (relro_enum): Rename exp_dataseg_relro_none, + exp_dataseg_relro_start and exp_dataseg_relro_end to + exp_seg_relro_none, exp_seg_relro_start and exp_seg_relro_end. + (seg_align_type): New struct type. + (ldexp_control): Use seg_align_type. + * ldexp.c (fold_unary): Updated. + (fold_binary): Likewise. + * ldlang.c (strip_excluded_output_sections): Likewise. + (lang_size_sections_1): Likewise. + (lang_size_sections): Likewise. + 2017-11-12 H.J. Lu PR ld/22423 diff --git a/ld/ldexp.c b/ld/ldexp.c index 792e21e130c..5633e507148 100644 --- a/ld/ldexp.c +++ b/ld/ldexp.c @@ -394,15 +394,15 @@ fold_unary (etree_type *tree) { expld.result.valid_p = FALSE; } - else if (expld.dataseg.phase == exp_dataseg_align_seen - || expld.dataseg.phase == exp_dataseg_relro_seen) + else if (expld.dataseg.phase == exp_seg_align_seen + || expld.dataseg.phase == exp_seg_relro_seen) { - expld.dataseg.phase = exp_dataseg_end_seen; + expld.dataseg.phase = exp_seg_end_seen; expld.dataseg.end = expld.result.value; } - else if (expld.dataseg.phase == exp_dataseg_done - || expld.dataseg.phase == exp_dataseg_adjust - || expld.dataseg.phase == exp_dataseg_relro_adjust) + else if (expld.dataseg.phase == exp_seg_done + || expld.dataseg.phase == exp_seg_adjust + || expld.dataseg.phase == exp_seg_relro_adjust) { /* OK. */ } @@ -573,7 +573,7 @@ fold_binary (etree_type *tree) break; case DATA_SEGMENT_ALIGN: - expld.dataseg.relro = exp_dataseg_relro_start; + 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; @@ -583,9 +583,9 @@ fold_binary (etree_type *tree) bfd_vma commonpage = expld.result.value; expld.result.value = align_n (expld.dot, maxpage); - if (expld.dataseg.phase == exp_dataseg_relro_adjust) + if (expld.dataseg.phase == exp_seg_relro_adjust) expld.result.value = expld.dataseg.base; - else if (expld.dataseg.phase == exp_dataseg_adjust) + else if (expld.dataseg.phase == exp_seg_adjust) { if (commonpage < maxpage) expld.result.value += ((expld.dot + commonpage - 1) @@ -594,13 +594,13 @@ fold_binary (etree_type *tree) else { expld.result.value += expld.dot & (maxpage - 1); - if (expld.dataseg.phase == exp_dataseg_done) + if (expld.dataseg.phase == exp_seg_done) { /* OK. */ } - else if (expld.dataseg.phase == exp_dataseg_none) + else if (expld.dataseg.phase == exp_seg_none) { - expld.dataseg.phase = exp_dataseg_align_seen; + expld.dataseg.phase = exp_seg_align_seen; expld.dataseg.base = expld.result.value; expld.dataseg.pagesize = commonpage; expld.dataseg.maxpagesize = maxpage; @@ -615,21 +615,21 @@ fold_binary (etree_type *tree) 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; + 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_dataseg_align_seen - || expld.dataseg.phase == exp_dataseg_adjust - || expld.dataseg.phase == exp_dataseg_relro_adjust - || expld.dataseg.phase == exp_dataseg_done) + 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_dataseg_align_seen - || expld.dataseg.phase == exp_dataseg_relro_adjust) + 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_dataseg_relro_adjust + if (expld.dataseg.phase == exp_seg_relro_adjust && (expld.dataseg.relro_end & (expld.dataseg.pagesize - 1))) { @@ -641,8 +641,8 @@ fold_binary (etree_type *tree) else expld.result.value = lhs.value; - if (expld.dataseg.phase == exp_dataseg_align_seen) - expld.dataseg.phase = exp_dataseg_relro_seen; + if (expld.dataseg.phase == exp_seg_align_seen) + expld.dataseg.phase = exp_seg_relro_seen; } else expld.result.valid_p = FALSE; diff --git a/ld/ldexp.h b/ld/ldexp.h index 265bb7bd655..5ff0fa0a1fc 100644 --- a/ld/ldexp.h +++ b/ld/ldexp.h @@ -115,23 +115,34 @@ union lang_statement_union; enum phase_enum { /* We step through the first four states here as we see the associated linker script tokens. */ - exp_dataseg_none, - exp_dataseg_align_seen, - exp_dataseg_relro_seen, - exp_dataseg_end_seen, + exp_seg_none, + exp_seg_align_seen, + exp_seg_relro_seen, + exp_seg_end_seen, /* The last three states are final, and affect the value returned - by DATA_SEGMENT_ALIGN. */ - exp_dataseg_relro_adjust, - exp_dataseg_adjust, - exp_dataseg_done + by XXX_SEGMENT_ALIGN. */ + exp_seg_relro_adjust, + exp_seg_adjust, + exp_seg_done }; enum relro_enum { - exp_dataseg_relro_none, - exp_dataseg_relro_start, - exp_dataseg_relro_end, + exp_seg_relro_none, + exp_seg_relro_start, + exp_seg_relro_end, }; +typedef struct { + enum phase_enum phase; + + bfd_vma base, relro_offset, relro_end, end, pagesize, maxpagesize; + + enum relro_enum relro; + + union lang_statement_union *relro_start_stat; + union lang_statement_union *relro_end_stat; +} seg_align_type; + struct ldexp_control { /* Modify expression evaluation depending on this. */ lang_phase_type phase; @@ -161,16 +172,7 @@ struct ldexp_control { asection *section; /* State machine and results for DATASEG. */ - struct { - enum phase_enum phase; - - bfd_vma base, relro_offset, relro_end, end, pagesize, maxpagesize; - - enum relro_enum relro; - - union lang_statement_union *relro_start_stat; - union lang_statement_union *relro_end_stat; - } dataseg; + seg_align_type dataseg; }; extern struct ldexp_control expld; diff --git a/ld/ldlang.c b/ld/ldlang.c index b89c4e6daad..2cb16476924 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -3890,7 +3890,7 @@ strip_excluded_output_sections (void) if (expld.phase != lang_mark_phase_enum) { expld.phase = lang_mark_phase_enum; - expld.dataseg.phase = exp_dataseg_none; + expld.dataseg.phase = exp_seg_none; one_lang_size_sections_pass (NULL, FALSE); lang_reset_memory_regions (); } @@ -5426,13 +5426,13 @@ lang_size_sections_1 bfd_vma newdot = dot; etree_type *tree = s->assignment_statement.exp; - expld.dataseg.relro = exp_dataseg_relro_none; + expld.dataseg.relro = exp_seg_relro_none; exp_fold_tree (tree, output_section_statement->bfd_section, &newdot); - if (expld.dataseg.relro == exp_dataseg_relro_start) + if (expld.dataseg.relro == exp_seg_relro_start) { if (!expld.dataseg.relro_start_stat) expld.dataseg.relro_start_stat = s; @@ -5441,7 +5441,7 @@ lang_size_sections_1 ASSERT (expld.dataseg.relro_start_stat == s); } } - else if (expld.dataseg.relro == exp_dataseg_relro_end) + else if (expld.dataseg.relro == exp_seg_relro_end) { if (!expld.dataseg.relro_end_stat) expld.dataseg.relro_end_stat = s; @@ -5450,7 +5450,7 @@ lang_size_sections_1 ASSERT (expld.dataseg.relro_end_stat == s); } } - expld.dataseg.relro = exp_dataseg_relro_none; + expld.dataseg.relro = exp_seg_relro_none; /* This symbol may be relative to this section. */ if ((tree->type.node_class == etree_provided @@ -5593,10 +5593,10 @@ void lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions) { expld.phase = lang_allocating_phase_enum; - expld.dataseg.phase = exp_dataseg_none; + expld.dataseg.phase = exp_seg_none; one_lang_size_sections_pass (relax, check_regions); - if (expld.dataseg.phase == exp_dataseg_end_seen + if (expld.dataseg.phase == exp_seg_end_seen && link_info.relro && expld.dataseg.relro_end) { bfd_vma initial_base, relro_end, desired_end; @@ -5631,7 +5631,7 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions) desired_end = start; } - expld.dataseg.phase = exp_dataseg_relro_adjust; + expld.dataseg.phase = exp_seg_relro_adjust; ASSERT (desired_end >= expld.dataseg.base); initial_base = expld.dataseg.base; expld.dataseg.base = desired_end; @@ -5651,7 +5651,7 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions) link_info.relro_start = expld.dataseg.base; link_info.relro_end = expld.dataseg.relro_end; } - else if (expld.dataseg.phase == exp_dataseg_end_seen) + else if (expld.dataseg.phase == exp_seg_end_seen) { /* If DATA_SEGMENT_ALIGN DATA_SEGMENT_END pair was seen, check whether a page could be saved in the data segment. */ @@ -5664,15 +5664,15 @@ lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions) != (expld.dataseg.end & ~(expld.dataseg.pagesize - 1))) && first + last <= expld.dataseg.pagesize) { - expld.dataseg.phase = exp_dataseg_adjust; + expld.dataseg.phase = exp_seg_adjust; lang_reset_memory_regions (); one_lang_size_sections_pass (relax, check_regions); } else - expld.dataseg.phase = exp_dataseg_done; + expld.dataseg.phase = exp_seg_done; } else - expld.dataseg.phase = exp_dataseg_done; + expld.dataseg.phase = exp_seg_done; } static lang_output_section_statement_type *current_section; -- 2.30.2