* 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:
Jakub Jelinek
2004-10-04 13:41:15 +00:00
parent daab19f765
commit a4f5ad884e
6 changed files with 100 additions and 31 deletions

View File

@@ -3286,10 +3286,44 @@ lang_size_sections
{
/* If DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END pair was seen, try
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;
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,
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_end = exp_data_seg.relro_end;
}