* ldgram.y (DATA_SEGMENT_RELRO_END): Add one argument.
* scripttempl/elf.sc (DATA_SEGMENT_RELRO_END): Add 0 as first argument. (DATA_SEGMENT_RELRO_GOTPLT_END): Pass $SEPARATE_GOTPLT as first and . as second argument. (GOTPLT): Move $DATA_SEGMENT_RELRO_GOTPLT_END before the section. * ldexp.c (fold_unary): Remove DATA_SEGMENT_RELRO_END handling here. (fold_binary): Add it here. Insert padding to make relro_end COMMONPAGESIZE bytes aligned. For DATA_SEGMENT_ALIGN in exp_dataseg_relro_adjust phase just use previously computed exp_data_seg.base. * ldlang.c (lang_size_sections): Set exp_data_seg.base for relro_adjust here. Call lang_size_sections_1 once more if there was too big padding at DATA_SEGMENT_RELRO_END. * ld.texinfo (DATA_SEGMENT_RELRO_END): Add documentation.
This commit is contained in:
parent
daab19f765
commit
a4f5ad884e
6 changed files with 100 additions and 31 deletions
18
ld/ChangeLog
18
ld/ChangeLog
|
@ -1,3 +1,21 @@
|
||||||
|
2004-10-04 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
|
* ldgram.y (DATA_SEGMENT_RELRO_END): Add one argument.
|
||||||
|
* scripttempl/elf.sc (DATA_SEGMENT_RELRO_END): Add 0 as first
|
||||||
|
argument.
|
||||||
|
(DATA_SEGMENT_RELRO_GOTPLT_END): Pass $SEPARATE_GOTPLT as first
|
||||||
|
and . as second argument.
|
||||||
|
(GOTPLT): Move $DATA_SEGMENT_RELRO_GOTPLT_END before the section.
|
||||||
|
* ldexp.c (fold_unary): Remove DATA_SEGMENT_RELRO_END handling here.
|
||||||
|
(fold_binary): Add it here. Insert padding to make relro_end
|
||||||
|
COMMONPAGESIZE bytes aligned. For DATA_SEGMENT_ALIGN in
|
||||||
|
exp_dataseg_relro_adjust phase just use previously computed
|
||||||
|
exp_data_seg.base.
|
||||||
|
* ldlang.c (lang_size_sections): Set exp_data_seg.base for
|
||||||
|
relro_adjust here. Call lang_size_sections_1 once more if there
|
||||||
|
was too big padding at DATA_SEGMENT_RELRO_END.
|
||||||
|
* ld.texinfo (DATA_SEGMENT_RELRO_END): Add documentation.
|
||||||
|
|
||||||
2004-10-01 Paul Brook <paul@codesourcery.com>
|
2004-10-01 Paul Brook <paul@codesourcery.com>
|
||||||
|
|
||||||
* emulparams/armelf.sh: Add unwinding table sections.
|
* emulparams/armelf.sh: Add unwinding table sections.
|
||||||
|
|
|
@ -4545,6 +4545,21 @@ evaluation purposes.
|
||||||
. = DATA_SEGMENT_END(.);
|
. = DATA_SEGMENT_END(.);
|
||||||
@end smallexample
|
@end smallexample
|
||||||
|
|
||||||
|
@item DATA_SEGMENT_RELRO_END(@var{offset}, @var{exp})
|
||||||
|
@kindex DATA_SEGMENT_RELRO_END(@var{offset}, @var{exp})
|
||||||
|
This defines the end of the @code{PT_GNU_RELRO} segment when
|
||||||
|
@samp{-z relro} option is used. Second argument is returned.
|
||||||
|
When @samp{-z relro} option is not present, @code{DATA_SEGMENT_RELRO_END}
|
||||||
|
does nothing, otherwise @code{DATA_SEGMENT_ALIGN} is padded so that
|
||||||
|
@var{exp} + @var{offset} is aligned to the most commonly used page
|
||||||
|
boundary for particular target. If present in the linker script,
|
||||||
|
it must always come in between @code{DATA_SEGMENT_ALIGN} and
|
||||||
|
@code{DATA_SEGMENT_END}.
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
. = DATA_SEGMENT_RELRO_END(24, .);
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
@item DEFINED(@var{symbol})
|
@item DEFINED(@var{symbol})
|
||||||
@kindex DEFINED(@var{symbol})
|
@kindex DEFINED(@var{symbol})
|
||||||
@cindex symbol defaults
|
@cindex symbol defaults
|
||||||
|
|
53
ld/ldexp.c
53
ld/ldexp.c
|
@ -265,25 +265,6 @@ fold_unary (etree_type *tree,
|
||||||
result.valid_p = FALSE;
|
result.valid_p = FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATA_SEGMENT_RELRO_END:
|
|
||||||
if (allocation_done != lang_first_phase_enum
|
|
||||||
&& (exp_data_seg.phase == exp_dataseg_align_seen
|
|
||||||
|| exp_data_seg.phase == exp_dataseg_adjust
|
|
||||||
|| exp_data_seg.phase == exp_dataseg_relro_adjust
|
|
||||||
|| allocation_done != lang_allocating_phase_enum))
|
|
||||||
{
|
|
||||||
if (exp_data_seg.phase == exp_dataseg_align_seen
|
|
||||||
|| exp_data_seg.phase == exp_dataseg_relro_adjust)
|
|
||||||
exp_data_seg.relro_end
|
|
||||||
= result.value + current_section->bfd_section->vma;
|
|
||||||
if (exp_data_seg.phase == exp_dataseg_align_seen)
|
|
||||||
exp_data_seg.phase = exp_dataseg_relro_seen;
|
|
||||||
result.value = dot - current_section->bfd_section->vma;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
result.valid_p = FALSE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DATA_SEGMENT_END:
|
case DATA_SEGMENT_END:
|
||||||
if (allocation_done != lang_first_phase_enum
|
if (allocation_done != lang_first_phase_enum
|
||||||
&& current_section == abs_output_section
|
&& current_section == abs_output_section
|
||||||
|
@ -422,13 +403,7 @@ fold_binary (etree_type *tree,
|
||||||
|
|
||||||
result.value = align_n (dot, maxpage);
|
result.value = align_n (dot, maxpage);
|
||||||
if (exp_data_seg.phase == exp_dataseg_relro_adjust)
|
if (exp_data_seg.phase == exp_dataseg_relro_adjust)
|
||||||
{
|
result.value = exp_data_seg.base;
|
||||||
/* Attempt to align DATA_SEGMENT_RELRO_END at
|
|
||||||
a common page boundary. */
|
|
||||||
exp_data_seg.base += (-exp_data_seg.relro_end
|
|
||||||
& (other.value - 1));
|
|
||||||
result.value = exp_data_seg.base;
|
|
||||||
}
|
|
||||||
else if (exp_data_seg.phase != exp_dataseg_adjust)
|
else if (exp_data_seg.phase != exp_dataseg_adjust)
|
||||||
{
|
{
|
||||||
result.value += dot & (maxpage - 1);
|
result.value += dot & (maxpage - 1);
|
||||||
|
@ -448,6 +423,32 @@ fold_binary (etree_type *tree,
|
||||||
result.valid_p = FALSE;
|
result.valid_p = FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DATA_SEGMENT_RELRO_END:
|
||||||
|
if (allocation_done != lang_first_phase_enum
|
||||||
|
&& (exp_data_seg.phase == exp_dataseg_align_seen
|
||||||
|
|| exp_data_seg.phase == exp_dataseg_adjust
|
||||||
|
|| exp_data_seg.phase == exp_dataseg_relro_adjust
|
||||||
|
|| allocation_done != lang_allocating_phase_enum))
|
||||||
|
{
|
||||||
|
if (exp_data_seg.phase == exp_dataseg_align_seen
|
||||||
|
|| exp_data_seg.phase == exp_dataseg_relro_adjust)
|
||||||
|
exp_data_seg.relro_end
|
||||||
|
= result.value + other.value;
|
||||||
|
if (exp_data_seg.phase == exp_dataseg_relro_adjust
|
||||||
|
&& (exp_data_seg.relro_end
|
||||||
|
& (exp_data_seg.pagesize - 1)))
|
||||||
|
{
|
||||||
|
exp_data_seg.relro_end += exp_data_seg.pagesize - 1;
|
||||||
|
exp_data_seg.relro_end &= ~(exp_data_seg.pagesize - 1);
|
||||||
|
result.value = exp_data_seg.relro_end - other.value;
|
||||||
|
}
|
||||||
|
if (exp_data_seg.phase == exp_dataseg_align_seen)
|
||||||
|
exp_data_seg.phase = exp_dataseg_relro_seen;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result.valid_p = FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
FAIL ();
|
FAIL ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -808,8 +808,8 @@ exp :
|
||||||
{ $$ = exp_binop(ALIGN_K,$3,$5); }
|
{ $$ = exp_binop(ALIGN_K,$3,$5); }
|
||||||
| DATA_SEGMENT_ALIGN '(' exp ',' exp ')'
|
| DATA_SEGMENT_ALIGN '(' exp ',' exp ')'
|
||||||
{ $$ = exp_binop (DATA_SEGMENT_ALIGN, $3, $5); }
|
{ $$ = exp_binop (DATA_SEGMENT_ALIGN, $3, $5); }
|
||||||
| DATA_SEGMENT_RELRO_END '(' exp ')'
|
| DATA_SEGMENT_RELRO_END '(' exp ',' exp ')'
|
||||||
{ $$ = exp_unop(DATA_SEGMENT_RELRO_END, $3); }
|
{ $$ = exp_binop (DATA_SEGMENT_RELRO_END, $5, $3); }
|
||||||
| DATA_SEGMENT_END '(' exp ')'
|
| DATA_SEGMENT_END '(' exp ')'
|
||||||
{ $$ = exp_unop(DATA_SEGMENT_END, $3); }
|
{ $$ = exp_unop(DATA_SEGMENT_END, $3); }
|
||||||
| BLOCK '(' exp ')'
|
| BLOCK '(' exp ')'
|
||||||
|
|
34
ld/ldlang.c
34
ld/ldlang.c
|
@ -3286,10 +3286,44 @@ lang_size_sections
|
||||||
{
|
{
|
||||||
/* If DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END pair was seen, try
|
/* If DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END pair was seen, try
|
||||||
to put exp_data_seg.relro on a (common) page boundary. */
|
to put exp_data_seg.relro on a (common) page boundary. */
|
||||||
|
bfd_vma old_base, relro_end;
|
||||||
|
|
||||||
exp_data_seg.phase = exp_dataseg_relro_adjust;
|
exp_data_seg.phase = exp_dataseg_relro_adjust;
|
||||||
|
old_base = exp_data_seg.base;
|
||||||
|
exp_data_seg.base += (-exp_data_seg.relro_end
|
||||||
|
& (exp_data_seg.pagesize - 1));
|
||||||
|
/* Compute the expected PT_GNU_RELRO segment end. */
|
||||||
|
relro_end = (exp_data_seg.relro_end + exp_data_seg.pagesize - 1)
|
||||||
|
& (exp_data_seg.pagesize - 1);
|
||||||
result = lang_size_sections_1 (s, output_section_statement, prev, fill,
|
result = lang_size_sections_1 (s, output_section_statement, prev, fill,
|
||||||
dot, relax, check_regions);
|
dot, relax, check_regions);
|
||||||
|
if (exp_data_seg.relro_end > relro_end)
|
||||||
|
{
|
||||||
|
/* The alignment of sections between DATA_SEGMENT_ALIGN
|
||||||
|
and DATA_SEGMENT_RELRO_END caused huge padding to be
|
||||||
|
inserted at DATA_SEGMENT_RELRO_END. Try some other base. */
|
||||||
|
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 = output_bfd->sections; sec; sec = sec->next)
|
||||||
|
if (sec->vma >= exp_data_seg.base
|
||||||
|
&& sec->vma < exp_data_seg.relro_end
|
||||||
|
&& sec->alignment_power > max_alignment_power)
|
||||||
|
max_alignment_power = sec->alignment_power;
|
||||||
|
|
||||||
|
if (((bfd_vma) 1 << max_alignment_power) < exp_data_seg.pagesize)
|
||||||
|
{
|
||||||
|
if (exp_data_seg.base - (1 << max_alignment_power)
|
||||||
|
< old_base)
|
||||||
|
exp_data_seg.base += exp_data_seg.pagesize;
|
||||||
|
exp_data_seg.base -= (1 << max_alignment_power);
|
||||||
|
result = lang_size_sections_1 (s, output_section_statement,
|
||||||
|
prev, fill, dot, relax,
|
||||||
|
check_regions);
|
||||||
|
}
|
||||||
|
}
|
||||||
link_info.relro_start = exp_data_seg.base;
|
link_info.relro_start = exp_data_seg.base;
|
||||||
link_info.relro_end = exp_data_seg.relro_end;
|
link_info.relro_end = exp_data_seg.relro_end;
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,9 +90,9 @@ if test -n "${COMMONPAGESIZE}"; then
|
||||||
DATA_SEGMENT_ALIGN="ALIGN (${SEGMENT_SIZE}) - ((${MAXPAGESIZE} - .) & (${MAXPAGESIZE} - 1)); . = DATA_SEGMENT_ALIGN (${MAXPAGESIZE}, ${COMMONPAGESIZE})"
|
DATA_SEGMENT_ALIGN="ALIGN (${SEGMENT_SIZE}) - ((${MAXPAGESIZE} - .) & (${MAXPAGESIZE} - 1)); . = DATA_SEGMENT_ALIGN (${MAXPAGESIZE}, ${COMMONPAGESIZE})"
|
||||||
DATA_SEGMENT_END=". = DATA_SEGMENT_END (.);"
|
DATA_SEGMENT_END=". = DATA_SEGMENT_END (.);"
|
||||||
if test -n "${SEPARATE_GOTPLT}"; then
|
if test -n "${SEPARATE_GOTPLT}"; then
|
||||||
DATA_SEGMENT_RELRO_GOTPLT_END=". = DATA_SEGMENT_RELRO_END (. + ${SEPARATE_GOTPLT});"
|
DATA_SEGMENT_RELRO_GOTPLT_END=". = DATA_SEGMENT_RELRO_END (${SEPARATE_GOTPLT}, .);"
|
||||||
else
|
else
|
||||||
DATA_SEGMENT_RELRO_END=". = DATA_SEGMENT_RELRO_END (.);"
|
DATA_SEGMENT_RELRO_END=". = DATA_SEGMENT_RELRO_END (0, .);"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
INTERP=".interp ${RELOCATING-0} : { *(.interp) }"
|
INTERP=".interp ${RELOCATING-0} : { *(.interp) }"
|
||||||
|
@ -102,7 +102,8 @@ if test -z "$GOT"; then
|
||||||
GOT=".got ${RELOCATING-0} : { *(.got.plt) *(.got) }"
|
GOT=".got ${RELOCATING-0} : { *(.got.plt) *(.got) }"
|
||||||
else
|
else
|
||||||
GOT=".got ${RELOCATING-0} : { *(.got) }"
|
GOT=".got ${RELOCATING-0} : { *(.got) }"
|
||||||
GOTPLT=".got.plt ${RELOCATING-0} : { ${RELOCATING+${DATA_SEGMENT_RELRO_GOTPLT_END}} *(.got.plt) }"
|
GOTPLT="${RELOCATING+${DATA_SEGMENT_RELRO_GOTPLT_END}}
|
||||||
|
.got.plt ${RELOCATING-0} : { *(.got.plt) }"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
DYNAMIC=".dynamic ${RELOCATING-0} : { *(.dynamic) }"
|
DYNAMIC=".dynamic ${RELOCATING-0} : { *(.dynamic) }"
|
||||||
|
|
Loading…
Reference in a new issue