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.
This commit is contained in:
parent
f882209d9a
commit
0f99513f2a
19
ld/ChangeLog
19
ld/ChangeLog
@ -1,3 +1,22 @@
|
||||
2017-11-12 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* 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 <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/22423
|
||||
|
44
ld/ldexp.c
44
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;
|
||||
|
44
ld/ldexp.h
44
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;
|
||||
|
24
ld/ldlang.c
24
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;
|
||||
|
Loading…
Reference in New Issue
Block a user