Skip to content

Commit e5529b0

Browse files
committed
Address review comments
- Add comments clarifying invariants and getEnclosinSymbol rationale - Remove extraneous "-" from ld.lld.1 - Replace "-NOT: >>>" with "-EMPTY:" - Use split-file to simplify paths
1 parent 93c5866 commit e5529b0

File tree

4 files changed

+169
-155
lines changed

4 files changed

+169
-155
lines changed

lld/ELF/MarkLive.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,10 @@ template <class ELFT, bool TrackWhyLive> class MarkLive {
8787
// identifiers, so we just store a SmallVector instead of a multimap.
8888
DenseMap<StringRef, SmallVector<InputSectionBase *, 0>> cNamedSections;
8989

90-
// The most proximate reason that something is live.
90+
// The most proximate reason that something is live. This forms a DAG between
91+
// LiveItems. Acyclicality is maintained by only admitting the first
92+
// discovered reason for each LiveItem; this captures the acyclic region of
93+
// the liveness graph around the GC roots.
9194
DenseMap<LiveItem, LiveReason> whyLive;
9295
};
9396
} // namespace
@@ -145,6 +148,10 @@ void MarkLive<ELFT, TrackWhyLive>::resolveReloc(InputSectionBase &sec,
145148
relSec->nextInSectionGroup))) {
146149
Symbol *canonicalSym = d;
147150
if (TrackWhyLive && d->isSection()) {
151+
// This is expensive, so ideally this would be deferred until it's known
152+
// whether this reference contributes to a printed whyLive chain, but
153+
// that determination cannot be made without knowing the enclosing
154+
// symbol.
148155
if (Symbol *s = relSec->getEnclosingSymbol(offset))
149156
canonicalSym = s;
150157
else

lld/docs/ld.lld.1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,7 @@ Report unresolved symbols as warnings.
755755
Force load of all members in a static library.
756756
.It Fl -why-extract Ns = Ns Ar file
757757
Print to a file about why archive members are extracted.
758-
.It Fl --why-live Ns = Ns Ar glob
758+
.It Fl -why-live Ns = Ns Ar glob
759759
Report a chain of references preventing garbage collection for each symbol matching the glob.
760760
.It Fl -wrap Ns = Ns Ar symbol
761761
Redirect

lld/test/ELF/why-live.s

Lines changed: 0 additions & 153 deletions
This file was deleted.

lld/test/ELF/why-live.test

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# REQUIRES: x86
2+
3+
# RUN: rm -rf %t && split-file %s %t && cd %t
4+
# RUN: llvm-mc -n -filetype=obj -triple=x86_64 -o shared.o shared.s
5+
# RUN: ld.lld -shared shared.o -o a.so
6+
# RUN: llvm-mc -n -filetype=obj -triple=x86_64 -o a.o a.s
7+
8+
#--- shared.s
9+
.globl test_shared
10+
.section .test_shared,"ax",@progbits
11+
test_shared:
12+
jmp test_shared
13+
14+
#--- a.s
15+
## Simple live section
16+
.globl _start
17+
.section ._start,"ax",@progbits
18+
_start:
19+
jmp test_simple
20+
.quad .Lanonymous
21+
.quad .Lanonymous_within_symbol
22+
jmp test_shared
23+
.quad test_local
24+
.size _start, .-_start
25+
26+
.globl test_simple
27+
.section .test_simple,"ax",@progbits
28+
test_simple:
29+
jmp test_simple
30+
jmp test_from_unsized
31+
32+
# RUN: ld.lld a.o a.so --gc-sections --why-live=test_simple | FileCheck %s --check-prefix=SIMPLE
33+
34+
# SIMPLE: live symbol: a.o:(test_simple)
35+
# SIMPLE-NEXT: >>> referenced by: a.o:(_start) (entry point)
36+
# SIMPLE-EMPTY:
37+
38+
## Live only by being a member of .test_simple
39+
.globl test_incidental
40+
test_incidental:
41+
jmp test_incidental
42+
43+
# RUN: ld.lld a.o a.so --gc-sections --why-live=test_incidental | FileCheck %s --check-prefix=INCIDENTAL
44+
45+
# INCIDENTAL: live symbol: a.o:(test_incidental)
46+
# INCIDENTAL-NEXT: >>> in live section: a.o:(.test_simple)
47+
# INCIDENTAL-NEXT: >>> contained live symbol: a.o:(test_simple)
48+
# INCIDENTAL-NEXT: >>> referenced by: a.o:(_start) (entry point)
49+
# INCIDENTAL-EMPTY:
50+
51+
## Reached from a reference in section .test_simple directly, since test_simple is an unsized symbol.
52+
.globl test_from_unsized
53+
.section .test_from_unsized,"ax",@progbits
54+
test_from_unsized:
55+
jmp test_from_unsized
56+
57+
# RUN: ld.lld a.o a.so --gc-sections --why-live=test_from_unsized | FileCheck %s --check-prefix=FROM-UNSIZED
58+
59+
# FROM-UNSIZED: live symbol: a.o:(test_from_unsized)
60+
# FROM-UNSIZED-NEXT: >>> referenced by: a.o:(.test_simple)
61+
# FROM-UNSIZED-NEXT: >>> contained live symbol: a.o:(test_simple)
62+
# FROM-UNSIZED-NEXT: >>> referenced by: a.o:(_start) (entry point)
63+
# FROM-UNSIZED-EMPTY:
64+
65+
## Symbols in dead sections are dead and not reported.
66+
.globl test_dead
67+
.section .test_dead,"ax",@progbits
68+
test_dead:
69+
jmp test_dead
70+
71+
# RUN: ld.lld a.o a.so --gc-sections --why-live=test_dead | count 0
72+
73+
## Undefined symbols are considered live, since they are not in dead sections.
74+
75+
# RUN: ld.lld a.o a.so --gc-sections --why-live=test_undef -u test_undef | FileCheck %s --check-prefix=UNDEFINED
76+
77+
# UNDEFINED: live symbol: <internal>:(test_undef) (no section)
78+
# UNDEFINED-EMPTY:
79+
80+
## Defined symbols without input section parents are live.
81+
.globl test_absolute
82+
test_absolute = 1234
83+
84+
# RUN: ld.lld a.o a.so --gc-sections --why-live=test_absolute | FileCheck %s --check-prefix=ABSOLUTE
85+
86+
# ABSOLUTE: live symbol: a.o:(test_absolute) (no section)
87+
# ABSOLUTE-EMPTY:
88+
89+
## Retained sections are intrinsically live, and they make contained symbols live.
90+
.globl test_retained
91+
.section .test_retained,"axR",@progbits
92+
test_retained:
93+
jmp test_retained
94+
95+
# RUN: ld.lld a.o a.so --gc-sections --why-live=test_retained | FileCheck %s --check-prefix=RETAINED
96+
97+
# RETAINED: live symbol: a.o:(test_retained)
98+
# RETAINED-NEXT: >>> in live section: a.o:(.test_retained) (retained)
99+
# RETAINED-EMPTY:
100+
101+
## Relocs that reference offsets from sections (e.g., from anonymous symbols) are considered to point to the section if no enclosing symbol exists.
102+
103+
.globl test_section_offset
104+
.section .test_section_offset,"ax",@progbits
105+
test_section_offset:
106+
jmp test_section_offset
107+
.Lanonymous:
108+
jmp test_section_offset
109+
110+
# RUN: ld.lld a.o a.so --gc-sections --why-live=test_section_offset | FileCheck %s --check-prefix=SECTION-OFFSET
111+
112+
# SECTION-OFFSET: live symbol: a.o:(test_section_offset)
113+
# SECTION-OFFSET-NEXT: >>> in live section: a.o:(.test_section_offset)
114+
# SECTION-OFFSET-NEXT: >>> referenced by: a.o:(_start) (entry point)
115+
# SECTION-OFFSET-EMPTY:
116+
117+
## Relocs that reference offsets from sections (e.g., from anonymous symbols) are considered to point to the enclosing symbol if one exists.
118+
119+
.globl test_section_offset_within_symbol
120+
.section .test_section_offset_within_symbol,"ax",@progbits
121+
test_section_offset_within_symbol:
122+
jmp test_section_offset_within_symbol
123+
.Lanonymous_within_symbol:
124+
jmp test_section_offset_within_symbol
125+
.size test_section_offset_within_symbol, .-test_section_offset_within_symbol
126+
127+
# RUN: ld.lld a.o a.so --gc-sections --why-live=test_section_offset_within_symbol | FileCheck %s --check-prefix=SECTION-OFFSET-WITHIN-SYMBOL
128+
129+
# SECTION-OFFSET-WITHIN-SYMBOL: live symbol: a.o:(test_section_offset_within_symbol)
130+
# SECTION-OFFSET-WITHIN-SYMBOL-NEXT: >>> referenced by: a.o:(_start) (entry point)
131+
# SECTION-OFFSET-WITHIN-SYMBOL-EMPTY:
132+
133+
## Local symbols can be queried just like global symbols.
134+
135+
.section .test_local,"ax",@progbits
136+
test_local:
137+
jmp test_local
138+
.size test_local, .-test_local
139+
140+
# RUN: ld.lld a.o a.so --gc-sections --why-live=test_local | FileCheck %s --check-prefix=LOCAL
141+
142+
# LOCAL: live symbol: a.o:(test_local)
143+
# LOCAL-NEXT: >>> referenced by: a.o:(_start) (entry point)
144+
# LOCAL-EMPTY:
145+
146+
## Shared symbols
147+
148+
# RUN: ld.lld a.o a.so --gc-sections --why-live=test_shared | FileCheck %s --check-prefix=SHARED
149+
150+
# SHARED: live symbol: a.so:(test_shared)
151+
# SHARED-NEXT: >>> referenced by: a.o:(_start) (entry point)
152+
# SHARED-EMPTY:
153+
154+
## Globs match multiple cases. Multiple --why-live flags union.
155+
156+
# RUN: ld.lld a.o a.so --gc-sections --why-live=test_s* | FileCheck %s --check-prefix=MULTIPLE
157+
# RUN: ld.lld a.o a.so --gc-sections --why-live=test_simple --why-live=test_shared | FileCheck %s --check-prefix=MULTIPLE
158+
159+
# MULTIPLE-DAG: live symbol: a.o:(test_simple)
160+
# MULTIPLE-DAG: live symbol: a.so:(test_shared)

0 commit comments

Comments
 (0)