https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123439
Bug ID: 123439
Summary: Regression in being able to link compiler-generated
thunks with linker script in 32-bit x86 code
Product: gcc
Version: 15.2.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: taylor.hutt at broadcom dot com
Target Milestone: ---
Created attachment 63246
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=63246&action=edit
Source, compile commands, and artifacts
We feel we have found a regression in the gcc ecosystem between
version 9 and version 15. With version 15, the linking has changed in
a way that prevents thunks generated by the compiler from being
combined into .text section, and the rest of the tooling (eg: linker
scripts) is unable, to our knowledge, to represent the full complement
of attributes to ensure the thunk's sections are not dropped on the
floor.
Although all the artifacts and commands executed are present in the
attached tarball, if you want to reproduce the failure:
The 'compile' script should be executed in one of these four ways:
./compile 9 32
./compile 9 64
./compile 15 32
./compile 15 64
Export these variables from your calling environment to allow the
script to function:
GCC9="${GCC9:?Set GCC9 to full path of a gcc9 'gcc' executable.}";
LD9="${LD9:?Set LD9 to full path of a gcc9 'ld' executable.}";
OBJCOPY9="${OBJCOPY9:?Set OBJCOPY9 to full path of a gcc9-adjacent
'objcopy' executable.}";
GCC15="${GCC15:?Set GCC15 to full path of a gcc15 'gcc' executable.}";
LD15="${LD15:?Set LD15 to full path of a gcc15 'ld' executable.}";
OBJCOPY15="${OBJCOPY15:?Set OBJCOPY15 to full path of a gcc15-adjacent
'objcopy' executable.}";
NM="${NM:?Set NM to full path of an 'nm' executable.}";
GAWK="${GAWK:?Set GAWK to full path of a 'gawk' executable.}";
The script builds a minimal example of a system that tests secure
enclaves. The actual in-house test exercises the enclave in legacy,
compatability, and long modes.
Included here is minimal infrastructure that shows 32-bit fails (and
that 64-bit works, but that's mainly because of rip-relative
addressing).
The compile script builds the code that runs in an enclave into a
relocatable image that has specially named sections. This resultant
file relocatable file is then linked into another executable image
that serves as the loader for the enclave code.
The enclave code must be position independent.
With gcc9, this works for both 32- and 64-bit.
With gcc15, the 64-bit version works, but 32-bit version is unable to
link due to these errors:
`__x86.get_pc_thunk.bx' referenced in section `.le_code' of
./15/launch.demoted.o: defined in \
discarded section `.text.__x86.get_pc_thunk.bx[__x86.get_pc_thunk.bx]' of
./15/launch.demoted.o
`.text.__x86.get_pc_thunk.bx' referenced in section `.le_other' of
./15/launch.demoted.o: \
defined in discarded section
`.text.__x86.get_pc_thunk.bx[__x86.get_pc_thunk.bx]' of ./15/launch.demoted.o
These thunks are generated by the compiler and put into the text
section, but they section in which they reside does not have the same
attributes or alignment as the actual text section, so the new
gcc15-related linker will not combine them.
All attempts to have these thunks subsumed by a linker-script output
section have failed; as far as we can tell, it's not possible to
create an output section compatible with the thunk's section with
linker scripts. So the thunk sections end up being not covered, and
then are dropped by the linker because there is no place to put them
in the output -- and then the link fails.
This functionality used to work (gcc9), but with the gcc15-related
linker's new script heuristics, it no longer works.
If there is a way to do this with gcc15 we'd love to know how.
The attached tarball has all the source needed to reproduce the image failure.
It also contains the commands executed (see 00*), and the artifacts in
the gcc-{9,15}-codesize-{32,64} directories.