i386: Honour -mdirect-extern-access when calling __fentry__
commitbde21de1205c0456f6df68c950fb7ee631fcfa93
authorArd Biesheuvel <ardb@kernel.org>
Sun, 14 May 2023 16:18:38 +0000 (14 18:18 +0200)
committerUros Bizjak <ubizjak@gmail.com>
Sun, 14 May 2023 16:22:17 +0000 (14 18:22 +0200)
treefc826b487a12a9e0eeb678afd524ca2d9b5c39de
parent1871740c7803c2aea20f651f57b413bc425a051c
i386: Honour -mdirect-extern-access when calling __fentry__

The small and medium PIC code models generate profiling calls that
always load the address of __fentry__() via the GOT, even if
-mdirect-extern-access is in effect.

This deviates from the behavior with respect to other external
references, and results in a longer opcode that relies on linker
relaxation to eliminate the GOT load. In this particular case, the
transformation replaces an indirect 'CALL *__fentry__@GOTPCREL(%rip)'
with either 'CALL __fentry__; NOP' or 'NOP; CALL __fentry__', where the
NOP is a 1 byte NOP that preserves the 6 byte length of the sequence.

This is problematic for the Linux kernel, which generally relies on
-mdirect-extern-access and hidden visibility to eliminate GOT based
symbol references in code generated with -fpie/-fpic, without having to
depend on linker relaxation.

The Linux kernel relies on code patching to replace these opcodes with
NOPs at runtime, and this is complicated code that we'd prefer not to
complicate even more by adding support for patching both 5 and 6 byte
sequences as well as parsing the instruction stream to decide which
variant of CALL+NOP we are dealing with.

So let's honour -mdirect-extern-access, and only load the address of
__fentry__ via the GOT if direct references to external symbols are not
permitted.

Note that the GOT reference in question is in fact a data reference: we
explicitly load the address of __fentry__ from the GOT, which amounts to
eager binding, rather than emitting a PLT call that could bind eagerly,
lazily or directly at link time.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
gcc/ChangeLog:

* config/i386/i386.cc (x86_function_profiler): Take
ix86_direct_extern_access into account when generating calls
to __fentry__()
gcc/config/i386/i386.cc