[ELF] Make the rule to create relative relocations in a writable section…


[ELF] Make the rule to create relative relocations in a writable section stricter

The current rule is loose: !Sym.IsPreemptible || Expr == R_GOT.

When the symbol is non-preemptable, this allows absolute relocation
types with smaller numbers of bits, e.g. R_X86_64_{8,16,32}. They are
disallowed by ld.bfd and gold, e.g.

ld.bfd: a.o: relocation R_X86_64_8 against `.text' can not be used when making a shared object; recompile with -fPIC

This patch:

a) Add TargetInfo::SymbolicRel to represent relocation types that resolve to a
symbol value (e.g. R_AARCH_ABS64, R_386_32, R_X86_64_64).

As a side benefit, we currently (ab)use GotRel (R_*_GLOB_DAT) to resolve
GOT slots that are link-time constants. Since we now use Target->SymbolRel
to do the job, we can remove R_*_GLOB_DAT from relocateOne() for all targets.
R_*_GLOB_DAT cannot be used as static relocation types.

b) Change the condition to !Sym.IsPreemptible && Type != Target->SymbolicRel || Expr == R_GOT.

Some tests are caught by the improved error checking (ld.bfd/gold also
issue errors on them). Many misuse .long where .quad should be used

Reviewed By: ruiu

Differential Revision: https://reviews.llvm.org/D63121


Event Timeline

arichardson added inline comments.

I believe this broke -z notext for some of our MIPS64 PIE executables.

We have some pie binaries that use:

.option pic0
dla $a0, __symbol

This expands to a sequence of R_MIPS_LO16,R_MIPS_HI16,R_MIPS_HIGHER,R_MIPS_HIGHEST relocations and we use -z notext to fill them in at runtime.

For now I can just add != EM_MIPS to the condition to work around this.
I would prefer to not have that text relocation but I can't see how I could avoid it because in the case where we are using it we do not have a valid GOT pointer so we need to rely on absolute addresses. If I could somehow generate a relocation that gives me the offset relative to the load address, that would also work.