Skip to content

Commit 724ed20

Browse files
committed
[ELF] Hint -z nostart-stop-gc for __start_ undefined references
Make users aware what to do with ld.lld 13.0.0 / GNU ld<2015-10 --gc-sections behavior. Differential Revision: https://reviews.llvm.org/D114830 (cherry picked from commit 353fe72)
1 parent f3394dc commit 724ed20

File tree

4 files changed

+94
-0
lines changed

4 files changed

+94
-0
lines changed

lld/ELF/Relocations.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -927,6 +927,12 @@ static void reportUndefinedSymbol(const UndefinedDiag &undef,
927927
msg +=
928928
"\n>>> the vtable symbol may be undefined because the class is missing "
929929
"its key function (see https://lld.llvm.org/missingkeyfunction)";
930+
if (config->gcSections && config->zStartStopGC &&
931+
sym.getName().startswith("__start_")) {
932+
msg += "\n>>> the encapsulation symbol needs to be retained under "
933+
"--gc-sections properly; consider -z nostart-stop-gc "
934+
"(see https://lld.llvm.org/ELF/start-stop-gc)";
935+
}
930936

931937
if (undef.isWarning)
932938
warn(msg);

lld/docs/ELF/start-stop-gc.rst

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
-z start-stop-gc
2+
================
3+
4+
If your ``-Wl,--gc-sections`` build fail with a linker error like this:
5+
6+
error: undefined symbol: __start_meta
7+
>>> referenced by {{.*}}
8+
>>> the encapsulation symbol needs to be retained under --gc-sections properly; consider -z nostart-stop-gc (see https://lld.llvm.org/ELF/start-stop-gc)
9+
10+
it is likely your C identifier name sections are not properly annotated to
11+
suffice under ``--gc-sections``.
12+
13+
``__start_meta`` and ``__stop_meta`` are sometimed called encapsulation
14+
symbols. In October 2015, GNU ld switched behavior and made a ``__start_meta``
15+
reference from a live section retain all ``meta`` input sections. This
16+
conservative behavior works for existing code which does not take GC into fair
17+
consideration, but unnecessarily increases sizes for modern metadata section
18+
usage which desires precise GC.
19+
20+
GNU ld 2.37 added ``-z start-stop-gc`` to restore the traditional behavior
21+
ld.lld 13.0.0 defaults to ``-z start-stop-gc`` and supports ``-z nostart-stop-gc``
22+
to switch to the conservative behavior.
23+
24+
The Apple ld64 linker has a similar ``section$start`` feature and always
25+
allowed GC (like ``-z start-stop-gc``).
26+
27+
Annotate C identifier name sections
28+
-----------------------------------
29+
30+
A C identifier name section (``meta``) sometimes depends on another section.
31+
Let that section reference ``meta`` via a relocation.
32+
33+
.. code-block:: c
34+
35+
asm(".pushsection .init_array,\"aw\",%init_array\n" \
36+
".reloc ., BFD_RELOC_NONE, meta\n" \
37+
".popsection\n")
38+
39+
If a relocation is inconvenient, consider using ``__attribute__((retain))``
40+
(GCC 11 with modern binutils, Clang 13).
41+
42+
.. code-block:: c
43+
44+
#pragma GCC diagnostic push
45+
#pragma GCC diagnostic ignored "-Wattributes"
46+
__attribute__((retain,used,section("meta")))
47+
static const char dummy[0];
48+
#pragma GCC diagnostic pop
49+
50+
GCC before 11 and Clang before 13 do not recognize ``__attribute__((retain))``,
51+
so ``-Wattributes`` may need to be ignored. On ELF targets,
52+
``__attribute__((used))`` prevents compiler discarding, but does not affect
53+
linker ``--gc-sections``.
54+
55+
In a macro, you may use:
56+
57+
.. code-block:: c
58+
59+
_Pragma("GCC diagnostic push")
60+
_Pragma("GCC diagnostic ignored \"-Wattributes\"")
61+
...
62+
_Pragma("GCC diagnostic pop")
63+
64+
If you use the ``SECTIONS`` command in a linker script, use
65+
`the ``KEEP`` keyword <https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html>`_, e.g.
66+
``meta : { KEEP(*(meta)) }``

lld/docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,4 +178,5 @@ document soon.
178178
Partitions
179179
ReleaseNotes
180180
ELF/linker_script
181+
ELF/start-stop-gc
181182
ELF/warn_backrefs
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# REQUIRES: x86
2+
## Some projects may not work with GNU ld<2015-10 (ld.lld 13.0.0) --gc-sections behavior.
3+
## Give a hint.
4+
5+
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
6+
# RUN: ld.lld %t.o -o /dev/null
7+
# RUN: ld.lld %t.o --gc-sections -z nostart-stop-gc -o /dev/null
8+
# RUN: not ld.lld %t.o --gc-sections -o /dev/null 2>&1 | FileCheck %s
9+
10+
# CHECK: error: undefined symbol: __start_meta
11+
# CHECK-NEXT: >>> referenced by {{.*}}
12+
# CHECK-NEXT: >>> the encapsulation symbol needs to be retained under --gc-sections properly; consider -z nostart-stop-gc (see https://lld.llvm.org/ELF/start-stop-gc)
13+
14+
.section .text,"ax",@progbits
15+
.global _start
16+
_start:
17+
.quad __start_meta - .
18+
.quad __stop_meta - .
19+
20+
.section meta,"aw",@progbits
21+
.quad 0

0 commit comments

Comments
 (0)