Re: PowerPC64 .branch_lt address

On seeing PR29369 my suspicion was naturally on a recent powerpc64
change, commit 0ab80031430e.  Without a reproducer, I spent time
wondering what could have gone wrong, and while I doubt this patch
would have fixed the PR, there are some improvements that can be made
to cater for user silliness.

I also noticed that when -z relro -z now sections are created out of
order, with .got before .plt in the section headers but .got is laid
out at a higher address.  That's due to the address expression for
.branch_lt referencing SIZEOF(.got) and so calling init_os (which
creates a bfd section) for .got before the .plt section is created.
Fix that by ignoring SIZEOF in exp_init_os.  Unlike ADDR and LOADADDR
which need to reference section vma and lma respectively, SIZEOF can
and does cope with a missing bfd section by returning zero for its
size, which of course is correct.

	PR 29369
	* ldlang.c (exp_init_os): Don't create a bfd section for SIZEOF.
	* emulparams/elf64ppc.sh (OTHER_RELRO_SECTIONS_2): Revise
	.branch_lt address to take into account possible user sections
	with alignment larger than 8 bytes.
This commit is contained in:
Alan Modra 2022-07-25 09:25:49 +09:30
parent 5d8af25542
commit 5d471bd907
2 changed files with 21 additions and 2 deletions

View file

@ -34,10 +34,30 @@ OTHER_GOT_RELOC_SECTIONS="
.rela.toc1 ${RELOCATING-0} : { *(.rela.toc1) }
.rela.tocbss ${RELOCATING-0} : { *(.rela.tocbss) }
.rela.branch_lt ${RELOCATING-0} : { *(.rela.branch_lt) }"
# The idea behind setting .branch_lt address as we do below is to put
# it up against .got which is 256 byte aligned, so that the offset
# from .TOC. to an entry in .branch_lt remains fixed after stub
# sizing. (.eh_frame is edited late.) When -z relro -z now, we have
# .branch_lt, .plt, .iplt, then .got, so in that case we move
# .branch_lt so that the end of .iplt is against .got. All of these
# sections are linker generated, with alignment eight and size a
# multiple of eight, but a user playing games with their own
# .branch_lt, .plt or .iplt sections can result in unexpected
# alignment or size. Cope with that anyway. Note that if user
# alignment of .branch_lt is 256 or more then nothing special need be
# done.
#
# To understand what is going on here consider that the end address
# of .iplt should be 0 mod 256, so the start of .iplt should be
# -sizeof(.iplt) mod 256. But the start is constrained by alignment,
# so goes down to (-alignof(.iplt) & -sizeof(.iplt)) mod 256. Repeat
# that calculation for .plt and .branch_lt to find the start of
# .branch_lt then subtract . mod 256 to find the padding. Of course
# just one mod 256 suffices, which is done by anding with 255.
OTHER_RELRO_SECTIONS_2="
.opd ${RELOCATING-0} :${RELOCATING+ ALIGN(8)} { KEEP (*(.opd)) }
.toc1 ${RELOCATING-0} :${RELOCATING+ ALIGN(8)} { *(.toc1) }
.branch_lt ${RELOCATING-0}${RELOCATING+(SIZEOF(.got) != 0 ? . + 255 - (255 & (. - 1 + ALIGN(SIZEOF(.branch_lt),8)${RELRO_NOW+ + ALIGN(SIZEOF(.plt),8) + ALIGN(SIZEOF(.iplt),8)})) : ALIGN(8))} : { *(.branch_lt) }"
.branch_lt ${RELOCATING-0}${RELOCATING+ALIGNOF(.branch_lt) < 256 && SIZEOF(.got) != 0 ? . + (((-MAX(ALIGNOF(.branch_lt),8) & (-SIZEOF(.branch_lt)${RELRO_NOW+ + (-MAX(ALIGNOF(.plt),8) & (-SIZEOF(.plt) + (-MAX(ALIGNOF(.iplt),8) & -SIZEOF(.iplt))))})) - .) & 255) : ALIGN(MAX(ALIGNOF(.branch_lt), SIZEOF(.got) != 0 ? 256 : 8))} : { *(.branch_lt) }"
INITIAL_READWRITE_SECTIONS="
.toc ${RELOCATING-0} :${RELOCATING+ ALIGN(8)} { *(.toc) }"
# Put .got before .data

View file

@ -2458,7 +2458,6 @@ exp_init_os (etree_type *exp)
{
case ADDR:
case LOADADDR:
case SIZEOF:
{
lang_output_section_statement_type *os;