summaryrefslogtreecommitdiff
path: root/ld/ldlang.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2022-02-05 20:01:40 +1030
committerAlan Modra <amodra@gmail.com>2022-02-07 13:42:41 +1030
commit5197c88e2a8a17f7a67ce683df068b5bdf619427 (patch)
tree22693af32bea270137d3979ce22a55e23dcaba11 /ld/ldlang.c
parent2b1026f391d55070ae1e724c0770302d1c429611 (diff)
downloadbinutils-gdb-5197c88e2a8a17f7a67ce683df068b5bdf619427.tar.gz
Revert "ld: Rewrite lang_size_relro_segment_1"
This reverts commit c804c6f98d342c3d46f73d7a7ec6229d5ab1c9f3. PR ld/28743 PR ld/28819 * ldlang.c (lang_size_relro_segment_1): Revert 2022-01-14 change. * testsuite/ld-x86-64/pr28743-1.d: Likewise. * testsuite/ld-x86-64/pr28743-1.s: Likewise. * testsuite/ld-x86-64/x86-64.exp: Likewise.
Diffstat (limited to 'ld/ldlang.c')
-rw-r--r--ld/ldlang.c95
1 files changed, 44 insertions, 51 deletions
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 5dd3df12a0f..cf13932a9b1 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -6370,101 +6370,94 @@ lang_size_segment (seg_align_type *seg)
static bfd_vma
lang_size_relro_segment_1 (seg_align_type *seg)
{
- bfd_vma relro_end, desired_relro_base;
- asection *sec, *relro_sec = NULL;
+ bfd_vma relro_end, desired_end;
+ asection *sec, *prev_sec = NULL;
+ bool remove_page_gap = false;
unsigned int max_alignment_power = 0;
- bool seen_reloc_section = false;
- bool desired_relro_base_reduced = false;
/* Compute the expected PT_GNU_RELRO/PT_LOAD segment end. */
relro_end = ((seg->relro_end + seg->pagesize - 1)
& ~(seg->pagesize - 1));
/* Adjust by the offset arg of XXX_SEGMENT_RELRO_END. */
- desired_relro_base = relro_end - seg->relro_offset;
+ desired_end = relro_end - seg->relro_offset;
- /* For sections in the relro segment. */
+ /* For sections in the relro segment.. */
for (sec = link_info.output_bfd->section_last; sec; sec = sec->prev)
if ((sec->flags & SEC_ALLOC) != 0)
{
- /* Record the maximum alignment for all sections starting from
- the relro segment. */
if (sec->alignment_power > max_alignment_power)
max_alignment_power = sec->alignment_power;
if (sec->vma >= seg->base
&& sec->vma < seg->relro_end - seg->relro_offset)
{
- /* Where do we want to put the relro section so that the
- relro segment ends on the page bounary? */
+ /* Where do we want to put this section so that it ends as
+ desired? */
bfd_vma start, end, bump;
end = start = sec->vma;
if (!IS_TBSS (sec))
end += TO_ADDR (sec->size);
- bump = desired_relro_base - end;
+ bump = desired_end - end;
/* We'd like to increase START by BUMP, but we must heed
alignment so the increase might be less than optimum. */
start += bump;
start &= ~(((bfd_vma) 1 << sec->alignment_power) - 1);
/* This is now the desired end for the previous section. */
- desired_relro_base = start;
- relro_sec = sec;
- seen_reloc_section = true;
+ desired_end = start;
+ prev_sec = sec->prev;
}
- else if (seen_reloc_section)
+ }
+
+ seg->phase = exp_seg_relro_adjust;
+ ASSERT (desired_end >= seg->base);
+
+ for (; prev_sec; prev_sec = prev_sec->prev)
+ if ((prev_sec->flags & SEC_ALLOC) != 0)
+ {
+ if (prev_sec->alignment_power > max_alignment_power)
+ max_alignment_power = prev_sec->alignment_power;
+
+ if (prev_sec->size != 0)
{
- /* Stop searching if we see a non-relro section after seeing
- relro sections. */
+ /* The 1-page gap before the RELRO segment may be removed. */
+ remove_page_gap = ((prev_sec->vma + prev_sec->size
+ + seg->maxpagesize) < desired_end);
+
break;
}
}
- if (relro_sec != NULL
- && seg->maxpagesize >= (1U << max_alignment_power))
+ if (remove_page_gap)
{
- asection *prev_sec;
- bfd_vma prev_sec_end_plus_1_page;
-
- /* Find the first preceding load section. */
- for (prev_sec = relro_sec->prev;
- prev_sec != NULL;
- prev_sec = prev_sec->prev)
- if ((prev_sec->flags & SEC_ALLOC) != 0)
- break;
+ /* Find the maximum section alignment. */
+ for (sec = prev_sec; sec; sec = sec->prev)
+ if ((sec->flags & SEC_ALLOC) != 0
+ && sec->alignment_power > max_alignment_power)
+ max_alignment_power = sec->alignment_power;
- prev_sec_end_plus_1_page = (prev_sec->vma + prev_sec->size
- + seg->maxpagesize);
- if (prev_sec_end_plus_1_page < desired_relro_base)
+ /* Remove the 1-page gap before the RELRO segment only if the
+ maximum page size >= the maximum section alignment. */
+ if (seg->maxpagesize >= (1U << max_alignment_power))
{
- bfd_vma aligned_relro_base;
-
- desired_relro_base_reduced = true;
-
- /* Don't add the 1-page gap before the relro segment. Align
- the relro segment first. */
- aligned_relro_base = (desired_relro_base
- & ~(seg->maxpagesize - 1));
- if (prev_sec_end_plus_1_page < aligned_relro_base)
+ /* If the preceding section size is greater than the maximum
+ page size, subtract the maximum page size. Otherwise,
+ align the RELRO segment to the maximum page size. */
+ if (prev_sec->size > seg->maxpagesize)
{
- /* Subtract the maximum page size if therer is still a
- 1-page gap. */
- desired_relro_base -= seg->maxpagesize;
+ desired_end -= seg->maxpagesize;
relro_end -= seg->maxpagesize;
}
else
{
- /* Align the relro segment. */
- desired_relro_base = aligned_relro_base;
+ desired_end &= ~(seg->maxpagesize - 1);
relro_end &= ~(seg->maxpagesize - 1);
}
- }
- }
+ }
+ }
- seg->phase = exp_seg_relro_adjust;
- ASSERT (desired_relro_base_reduced
- || desired_relro_base >= seg->base);
- seg->base = desired_relro_base;
+ seg->base = desired_end;
return relro_end;
}