edk2 icon indicating copy to clipboard operation
edk2 copied to clipboard

BaseTools/GenFw X64: Drop GOT handling

Open ardbiesheuvel opened this issue 4 months ago • 3 comments

Modern x86_64 ELF toolchains rarely emit GOT entries when generating fully linked binaries such as the ones used by GenFw for ELF-to-PECOFF conversion. This is not only due to LTO, where the linker can see all symbols in the program and decide that GOT indirections are unnecessary; even when not using LTO, the compiler and linker can rely on relaxable GOTPCRELX relocations to obtain the same result. These relocations are described in the ELF psABI for x86_64, and can be relaxed to direct symbol references by the linker if they can be satisfied by symbol defined in the same executable (as opposed to ones defined in shared libraries).

GenFw currently implements support for GOT based relocations on x86_64, but this is tricky code* that has to work around the fact that no static relocations are emitted for the GOT by the linker, only dynamic ones. This is due to the fact that the --emit-relocs linker switch it relies on emits the relocations generated by the compiler, whereas the GOT is constructed by the linker itself.

It also assumes that linker relaxations are reflected in the output of --emit-relocs. For instance, when relaxing

movq foo@GOTPCREL(%rip), %rax

to

leaq foo(%rip), %rax

(which loads the address of 'foo' into RAX), the resulting GOTPCRELX relocation must either be suppressed or converted into a R_X86_64_PC32 relocation, or the reference will be misidentified. When this happens, GenFw will emit a PE/COFF relocation that refers to 'foo' directly rather than the GOT slot carrying its absolute address, resulting in corruption of the code at the symbol's address when the PE/COFF loader applies the relocation to what it assumes is an absolute address that needs to be relocated.

ld.bfd and LLD behave differently in this regard, and given that --emit-relocs is a crutch to begin with, it is not obvious what should be emitted for the case above.

If GOT support is really needed in GenFw, it would be much better to implement this based on dynamic relocations which are emitted when linking Position Independent Executables (PIE). PIE binaries are built to tolerate placement anywhere in the 64-bit address space, and its relocation section only describes absolute quantities that require handling by GenFw.

However, it appears we don't actually need to handle GOTs at all. So remove support for X64 GOT handling from GenFw:

  • remove the .got input sections from the linker scripts
  • remove GOTPCREL handling, so that non-relaxable GOTPCREL relocations are rejected by GenFw;
  • ignore GOTPCRELX relocations, which will be relaxed by the linker, and not cause an entry to be emitted into the .got section.

*case in point: it needs a 'safety net'

ardbiesheuvel avatar Oct 20 '24 16:10 ardbiesheuvel