[Bug 970] #pragma visibility hidden in MdePkg/Include/X64/ProcessorBind.h is misconceived #pragma


bugzilla-daemon at bugzilla.tianocore.org...
 

https://bugzilla.tianocore.org/show_bug.cgi?id=970

--- Comment #2 from zenith432(a)users.sourceforge.net ---
... but here, I have to disagree. binutils only gained support for these
relocations in version 2.26 [0], and older versions of GCC do indeed emit a
different type of access depending on the visibility, even if this access lacks
any kind of ELF annotation (and I don't know why it should, but since you
brought it up ...)
You're conflating two separate things.
Earlier versions of GCC would generate GOT loads with R_X86_64_GOTPCREL
relocations for references to extern data, and that's what ld would handle by
transformating to lea instructions.

Notice with H.J. Liu says...

I am proposing to add 2 new relocations, R_X86_64_GOTPCRELX and
R_X86_64_REX_GOTPCRELX, to x86-64 psABI. Instead of generating
R_X86_64_GOTPCREL relocation agasint foo for foo(a)GOTPCREL(%rip),
we generate R_X86_64_GOTPCRELX or R_X86_64_REX_GOTPCRELX if there
is a REX prefix. Linker can treat them the same as R_X86_64_GOTPCREL
or it can perform the transformations listed above.
What he suggested (and was indeed done) was that for x86_64 instructions with a
REX prefix, instead of generating GOT load with R_X86_64_GOTPCREL relocation,
GCC generates GOT load with R_X86_64_REX_GOTPCRELX relocation, and ld was
extended to recognize that. Except for the formal distinction and the presence
of the REX prefix byte, the transformation is exactly the same. Check the
opcodes in the Intel processor manual if you don't believe me. The REX prefix
is needed for many instructions with a 64-bit data width. Prior to this change
it was simply making the same transformation ignoring the REX prefix byte.

MACHO faces the exact same issues and does not make a REX distriction to this
day. Here's recent defs used in kernel of macOS 10.13.3
https://opensource.apple.com/source/xnu/xnu-4570.41.2/EXTERNAL_HEADERS/mach-o/x86_64/reloc.h.auto.html

What the documentation in MdePkg/Include/X64/ProcessorBind.h claims

// Mark all symbol declarations and references as hidden, meaning they will
// not be subject to symbol preemption. This allows the compiler to refer to
// symbols directly using relative references rather than via the GOT, which
// contains absolute symbol addresses that are subject to runtime relocation.

is something no version of GCC or clang has ever done. If you think I'm wrong,
please name a version of GCC that did this, I'll build it and check.

The SYSV x86_64 ABI spec, section 3.5.4 says "Position-independent code cannot
contain absolute address. To access a global symbol the address of the symbol
*has* to be loaded from the Global Offset Table. The address of the entry in
the GOT can be obtained with a %rip-relative instruction in the small model."
While I can't find any formal definition what they mean by "global symbol",
section 3.2 states "The standard calling sequence requirements apply only to
global functions. Local functions that are not reachable from other
compilation units may use different conventions." So extrapolating what they
mean by "global function" to "global data" - any data not reachable from other
compilation units (= C source file in ISO C parlance) is local - the rest is
global.
So the SYSV ABI spec appears to explicitly forbid the kind of optimisation that
the documentation in MdePkg/Include/X64/ProcessorBind.h says the compiler
makes.

... which is precisely why we needed the 'hidden' visibility override, to
prevent [older versions of] GCC from emitting such relocations.
But GCC emits such relocations to this day! It's the linker that transforms
them. GenFw's success depends on the linker transforming them, not on GCC
abstaining from emitting them. It never abstains.

Maybe the problem was that updating to a recent version of GCC caused it to
emit R_X86_64_REX_GOTPCRELX, which an older verion of ld would then not
recognize, since it only recognized R_X86_64_GOTPCREL. But the solution to
that is to use a version of binutils compatible with the version of GCC being
used - as there can be many other such incompatibilities. For example, there
were version compatilibity problems with LTO plugin provided by GCC and
binutils that has to use it. At any rate, if this was added to address an
incompatibility between version of GCC and version of binutils used - it should
be phased out after this incompatibility gets old.

--
You are receiving this mail because:
You are on the CC list for the bug.