On 10/03/2021 14:48, Alan Modra wrote:
This patch future-proofs the kernel against linker changes that might
put the toc pointer at some location other than .got+0x8000, by
replacing __toc_start+0x8000 with .TOC. throughout. If the kernel's
idea of the toc pointer doesn't agree with the linker, bad things
happen.
Works great with gcc (v8, v10), ld (2.23), clang-11, lld-11.
prom_init.c code relocating its toc is also changed so that a symbolic
__prom_init_toc_start toc-pointer relative address is calculated
rather than assuming that it is always at toc-pointer - 0x8000. The
length calculations loading values from the toc are also avoided.
It's a little incestuous to do that with unreloc_toc picking up
adjusted values (which is fine in practice, they both adjust by the
same amount if all goes well).
I've also changed the way .got is aligned in vmlinux.lds and
zImage.lds, mostly so that dumping out section info by objdump or
readelf plainly shows the alignment is 256. This linker script
feature was added 2005-09-27, available in FSF binutils releases from
2.17 onwards. Should be safe to use in the kernel, I think.
Finally, put *(.got) before the prom_init.o entry which only needs
*(.toc), so that the GOT header goes in the correct place. I don't
believe this makes any difference for the kernel as it would for
dynamic objects being loaded by ld.so. That change is just to stop
lusers who blindly copy kernel scripts being led astray. Of course,
this change needs the prom_init.c changes.
Some notes on .toc and .got.
.toc is a compiler generated section of addresses. .got is a linker
generated section of addresses, generally built when the linker sees
R_*_*GOT* relocations. In the case of powerpc64 ld.bfd, there are
multiple generated .got sections, one per input object file. So you
can somewhat reasonably write in a linker script an input section
statement like *prom_init.o(.got .toc) to mean "the .got and .toc
section for files matching *prom_init.o".
For my own education, is .got for prom_init.o still generated by ld or gcc?
In other words, should "objdump -D -s -j .got" ever dump .got for any .o
file, like below?
===
objdump -D -s -j .got
~/pbuild/kernel-llvm-ld/arch/powerpc/kernel/prom_init.o
/home/aik/pbuild/kernel-llvm-ld/arch/powerpc/kernel/prom_init.o:
file format elf64-powerpcle
objdump: section '.got' mentioned in a -j option, but not found in any
input file
===
--
Alexey Kardashevskiy
IBM OzLabs, LTC Team
e-mail: a...@linux.ibm.com