diff options
author | Jakub Jelinek <jakub@redhat.com> | 2004-10-04 13:41:15 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2004-10-04 13:41:15 +0000 |
commit | a4f5ad884ecd1b56c973e0d562d97720140d1ec8 (patch) | |
tree | 53f1cb3832ca29707b8bacd44f9ff14538fbbbce /ld/ldlang.c | |
parent | daab19f765f12cce4c9f73efaff8b8ba75a139b5 (diff) | |
download | gdb-a4f5ad884ecd1b56c973e0d562d97720140d1ec8.zip gdb-a4f5ad884ecd1b56c973e0d562d97720140d1ec8.tar.gz gdb-a4f5ad884ecd1b56c973e0d562d97720140d1ec8.tar.bz2 |
* 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.
Diffstat (limited to 'ld/ldlang.c')
-rw-r--r-- | ld/ldlang.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/ld/ldlang.c b/ld/ldlang.c index 5988635..55a42be 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -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; } |