diff options
-rw-r--r-- | ld/emulparams/elf64ppc.sh | 22 | ||||
-rw-r--r-- | ld/ldlang.c | 1 |
2 files changed, 21 insertions, 2 deletions
diff --git a/ld/emulparams/elf64ppc.sh b/ld/emulparams/elf64ppc.sh index 59132fa06fa..668606e7c18 100644 --- a/ld/emulparams/elf64ppc.sh +++ b/ld/emulparams/elf64ppc.sh @@ -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 diff --git a/ld/ldlang.c b/ld/ldlang.c index e640380e901..f12c09633a7 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -2458,7 +2458,6 @@ exp_init_os (etree_type *exp) { case ADDR: case LOADADDR: - case SIZEOF: { lang_output_section_statement_type *os; |