The DT_PLTRELSZ dynamic tag is calculated using the size of the OutputSection containing the In.RelaPlt InputSection. This will work for the default no linker script case and the majority of linker scripts. Unfortunately it doesn't work for some 'almost' sensible linker scripts. It is permitted by ELF to have a single OutputSection containing both In.RelaDyn, In.RelaPlt and In.RelaIPlt. It is also permissible for the range of memory [DT_RELA, DT_RELA + DT_RELASZ) and the range [DT_JMPREL, DT_JMPREL + DT_JMPRELSZ) to overlap as long as the the latter range is at the end (see comment in glibc dynamic loader) https://code.woboq.org/userspace/glibc/elf/dynamic-link.h.html#108).
To support a linker script containing something like: .rela.dyn : { *(.rela.dyn) *(.rela.plt) } use the InputSections to determine DT_JMPRELSZ rather than the OutputSection size. I've left the calculation of the .rela.dyn to be the size of the OutputSection as that is the most literal reading of ELF and the smallest change. This affects all targets, I've added tests for AArch64, x86 (cited in PR) and ARM (as the irelative relocations do not go in the .rel.plt).
There will be no change to any project using the default linker script or the more modern
.rela.dyn : { *(.rela.dyn) } .rela.plt : { *(.rela.plt) *(.rela.iplt) }
fixes pr39678 (https://bugs.llvm.org/show_bug.cgi?id=39678)
I considered giving an error message rather than trying to support this case but the logic of working out when there is an error is no simpler. It also risked faulting existing programs.
DT_JMPTREL -> DT_JMPREL