![](/style/images/good.png)
![](/style/images/bad.png)
Linker notes on x86
source link: https://maskray.me/blog/2023-02-19-linker-notes-on-x86
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
This article describes target-specific things about x86 in ELF linkers. I will use "x86" to refer to both x86-32 and x86-64.
Global Offset Table
_GLOBAL_OFFSET_TABLE_
is defined at the start of the
section .got.plt
. .got.plt
has 3 reserved
entries.
_GLOBAL_OFFSET_TABLE_[0]
stores the link-time address of
_DYNAMIC
for a legacy reason. It's unused now. See All
about Global Offset Table.
_GLOBAL_OFFSET_TABLE_[1]
and
_GLOBAL_OFFSET_TABLE_[2]
are for lazy binding PLT.
GOT optimization
See All about Global Offset Table#GOT optimization.
Procedure Linkage Table
Retpoline and Indirect Branch Tracking
ld.lld supports -z retpolineplt
for Spectre v2
mitigation.
See .note.gnu.property
below for Indirect Branch
Tracking.
See All about Procedure Linkage Table#x86 for detail.
Thread Local Storage
x86 uses TLS Variant II: the static TLS blocks are placed below the thread pointer.
Beside the traditional general dynamic and local dynamic TLS models, there are TLSDESC ABIs for x86-32 and x86-64.
The linker performs TLS optimization.
See All about thread-local storage.
.note.gnu.property
The linker parses input .note.gnu.property
sections and
recognize -z force-ibt
and -z shstk
to compute
the output .note.gnu.property
(type is
SHT_NOTE
) section.
The following code (extracted from ld.lld) describes the behavior.
Basically, without extra options, the output has the
GNU_PROPERTY_X86_FEATURE_1_IBT
bit if all input
.note.gnu.property
sections have the bit (logical AND).
-z force-ibt
forces setting the bit with a warning.
The output has the GNU_PROPERTY_X86_FEATURE_1_SHSK
bit
if all input .note.gnu.property
sections have the bit
(logical AND). -z shstk
forces setting the bit without a
warning.
for (ELFFileBase *f : ctx.objectFiles) {
uint32_t features = f->andFeatures;
if (!(features & GNU_PROPERTY_X86_FEATURE_1_IBT)) {
if (config->zCetReport == "error")
error(toString(f) + ": -z cet-report: file does not have GNU_PROPERTY_X86_FEATURE_1_IBT property");
else if config->zCetReport == "warning")
warn(toString(f) + ": -z cet-report: file does not have GNU_PROPERTY_X86_FEATURE_1_IBT property");
}
if (!(features & GNU_PROPERTY_X86_FEATURE_1_SHSTK)) {
if (config->zCetReport == "error")
error(toString(f) + ": -z cet-report: file does not have GNU_PROPERTY_X86_FEATURE_1_SHSTK property");
else if config->zCetReport == "warning")
warn(toString(f) + ": -z cet-report: file does not have GNU_PROPERTY_X86_FEATURE_1_SHSTK property");
}
if (config->zForceIbt && !(features & GNU_PROPERTY_X86_FEATURE_1_IBT)) {
if (config->zCetReport == "none")
warn(toString(f) + ": -z force-ibt: file does not have "
"GNU_PROPERTY_X86_FEATURE_1_IBT property");
features |= GNU_PROPERTY_X86_FEATURE_1_IBT;
}
ret &= features;
}
// Force enable Shadow Stack.
if (config->zShstk)
ret |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
See Control flow integrity for an overview of Intel CET.
.eh_frame
Clang since rL252300 emits .eh_frame
sections of type
SHT_X86_64_UNWIND
. It is unfortunate that
.eh_frame
does not use a dedicated section type but
nowadays
.gnu.linkonce.t.__x86.get_pc_thunk.bx
The magic symbol prefix .gnu.linkonce
was used before
COMDAT was introduced into ELF. .gnu.linkonce
was very
obsoleted now, but unfortunately
.gnu.linkonce.t.__x86.get_pc_thunk.bx
remained relevant in
glibc x86-32 until glibc 2.32 (2020-08).
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK