@@ -48,18 +48,18 @@ namespace {
48
48
// Something that can be the most proximate reason that something else is alive.
49
49
typedef std::variant<InputSectionBase *, Symbol *> LiveReason;
50
50
51
- template <class ELFT > class MarkLive {
51
+ template <class ELFT , bool TrackWhyLive > class MarkLive {
52
52
public:
53
53
MarkLive (Ctx &ctx, unsigned partition) : ctx(ctx), partition(partition) {}
54
54
55
55
void run ();
56
56
void moveToMain ();
57
+ void printWhyLive (Symbol *s) const ;
57
58
58
59
private:
59
60
void enqueue (InputSectionBase *sec, uint64_t offset = 0 ,
60
61
Symbol *sym = nullptr ,
61
62
std::optional<LiveReason> reason = std::nullopt);
62
- void printWhyLive (Symbol *s) const ;
63
63
void markSymbol (Symbol *sym);
64
64
void mark ();
65
65
@@ -108,16 +108,16 @@ static uint64_t getAddend(Ctx &, InputSectionBase &sec,
108
108
return rel.r_addend ;
109
109
}
110
110
111
- template <class ELFT >
111
+ template <class ELFT , bool TrackWhyLive >
112
112
template <class RelTy >
113
- void MarkLive<ELFT>::resolveReloc(InputSectionBase &sec, RelTy &rel ,
114
- bool fromFDE) {
113
+ void MarkLive<ELFT, TrackWhyLive >::resolveReloc(InputSectionBase &sec,
114
+ RelTy &rel, bool fromFDE) {
115
115
// If a symbol is referenced in a live section, it is used.
116
116
Symbol &sym = sec.file ->getRelocTargetSym (rel);
117
117
sym.used = true ;
118
118
119
- LiveReason reason;
120
- if (!ctx. arg . whyLive . empty () ) {
119
+ std::optional< LiveReason> reason;
120
+ if (TrackWhyLive ) {
121
121
Defined *reasonSym = sec.getEnclosingSymbol (rel.r_offset );
122
122
reason = reasonSym ? LiveReason (reasonSym) : LiveReason (&sec);
123
123
}
@@ -142,7 +142,7 @@ void MarkLive<ELFT>::resolveReloc(InputSectionBase &sec, RelTy &rel,
142
142
if (!(fromFDE && ((relSec->flags & (SHF_EXECINSTR | SHF_LINK_ORDER)) ||
143
143
relSec->nextInSectionGroup ))) {
144
144
Symbol *canonicalSym = d;
145
- if (!ctx. arg . whyLive . empty () && d->isSection ()) {
145
+ if (TrackWhyLive && d->isSection ()) {
146
146
if (Symbol *s = relSec->getEnclosingSymbol (offset))
147
147
canonicalSym = s;
148
148
else
@@ -156,8 +156,8 @@ void MarkLive<ELFT>::resolveReloc(InputSectionBase &sec, RelTy &rel,
156
156
if (auto *ss = dyn_cast<SharedSymbol>(&sym)) {
157
157
if (!ss->isWeak ()) {
158
158
cast<SharedFile>(ss->file )->isNeeded = true ;
159
- if (!ctx. arg . whyLive . empty () )
160
- whyLive.try_emplace (&sym, reason);
159
+ if (TrackWhyLive )
160
+ whyLive.try_emplace (&sym, * reason);
161
161
}
162
162
}
163
163
@@ -179,10 +179,10 @@ void MarkLive<ELFT>::resolveReloc(InputSectionBase &sec, RelTy &rel,
179
179
// A possible improvement would be to fully process .eh_frame in the middle of
180
180
// the gc pass. With that we would be able to also gc some sections holding
181
181
// LSDAs and personality functions if we found that they were unused.
182
- template <class ELFT >
182
+ template <class ELFT , bool TrackWhyLive >
183
183
template <class RelTy >
184
- void MarkLive<ELFT>::scanEhFrameSection(EhInputSection &eh,
185
- ArrayRef<RelTy> rels) {
184
+ void MarkLive<ELFT, TrackWhyLive >::scanEhFrameSection(EhInputSection &eh,
185
+ ArrayRef<RelTy> rels) {
186
186
for (const EhSectionPiece &cie : eh.cies )
187
187
if (cie.firstRelocation != unsigned (-1 ))
188
188
resolveReloc (eh, rels[cie.firstRelocation ], false );
@@ -219,9 +219,10 @@ static bool isReserved(InputSectionBase *sec) {
219
219
}
220
220
}
221
221
222
- template <class ELFT >
223
- void MarkLive<ELFT>::enqueue(InputSectionBase *sec, uint64_t offset,
224
- Symbol *sym, std::optional<LiveReason> reason) {
222
+ template <class ELFT , bool TrackWhyLive>
223
+ void MarkLive<ELFT, TrackWhyLive>::enqueue(InputSectionBase *sec,
224
+ uint64_t offset, Symbol *sym,
225
+ std::optional<LiveReason> reason) {
225
226
// Usually, a whole section is marked as live or dead, but in mergeable
226
227
// (splittable) sections, each piece of data has independent liveness bit.
227
228
// So we explicitly tell it which offset is in use.
@@ -235,7 +236,7 @@ void MarkLive<ELFT>::enqueue(InputSectionBase *sec, uint64_t offset,
235
236
return ;
236
237
sec->partition = sec->partition ? 1 : partition;
237
238
238
- if (!ctx. arg . whyLive . empty () && reason) {
239
+ if (TrackWhyLive && reason) {
239
240
if (sym) {
240
241
// If a specific symbol is referenced, that makes it alive. It may in turn
241
242
// make its section alive.
@@ -253,7 +254,8 @@ void MarkLive<ELFT>::enqueue(InputSectionBase *sec, uint64_t offset,
253
254
}
254
255
255
256
// Print the stack of reasons that the given symbol is live.
256
- template <class ELFT > void MarkLive<ELFT>::printWhyLive(Symbol *s) const {
257
+ template <class ELFT , bool TrackWhyLive>
258
+ void MarkLive<ELFT, TrackWhyLive>::printWhyLive(Symbol *s) const {
257
259
// Skip dead symbols. A symbol is dead if it belongs to a dead section.
258
260
if (auto *d = dyn_cast<Defined>(s)) {
259
261
auto *reason = dyn_cast_or_null<InputSectionBase>(d->section );
@@ -296,7 +298,8 @@ template <class ELFT> void MarkLive<ELFT>::printWhyLive(Symbol *s) const {
296
298
}
297
299
}
298
300
299
- template <class ELFT > void MarkLive<ELFT>::markSymbol(Symbol *sym) {
301
+ template <class ELFT , bool TrackWhyLive>
302
+ void MarkLive<ELFT, TrackWhyLive>::markSymbol(Symbol *sym) {
300
303
if (auto *d = dyn_cast_or_null<Defined>(sym))
301
304
if (auto *isec = dyn_cast_or_null<InputSectionBase>(d->section ))
302
305
enqueue (isec, d->value , sym);
@@ -305,7 +308,8 @@ template <class ELFT> void MarkLive<ELFT>::markSymbol(Symbol *sym) {
305
308
// This is the main function of the garbage collector.
306
309
// Starting from GC-root sections, this function visits all reachable
307
310
// sections to set their "Live" bits.
308
- template <class ELFT > void MarkLive<ELFT>::run() {
311
+ template <class ELFT , bool TrackWhyLive>
312
+ void MarkLive<ELFT, TrackWhyLive>::run() {
309
313
// Add GC root symbols.
310
314
311
315
// Preserve externally-visible symbols if the symbols defined by this
@@ -346,7 +350,7 @@ template <class ELFT> void MarkLive<ELFT>::run() {
346
350
}
347
351
for (InputSectionBase *sec : ctx.inputSections ) {
348
352
if (sec->flags & SHF_GNU_RETAIN) {
349
- enqueue (sec, 0 , nullptr , std::nullopt );
353
+ enqueue (sec);
350
354
continue ;
351
355
}
352
356
if (sec->flags & SHF_LINK_ORDER)
@@ -397,9 +401,19 @@ template <class ELFT> void MarkLive<ELFT>::run() {
397
401
}
398
402
399
403
mark ();
404
+
405
+ if (TrackWhyLive) {
406
+ for (Symbol *sym : ctx.symtab ->getSymbols ()) {
407
+ if (llvm::any_of (ctx.arg .whyLive , [sym](const llvm::GlobPattern &pat) {
408
+ return pat.match (sym->getName ());
409
+ }))
410
+ printWhyLive (sym);
411
+ }
412
+ }
400
413
}
401
414
402
- template <class ELFT > void MarkLive<ELFT>::mark() {
415
+ template <class ELFT , bool TrackWhyLive>
416
+ void MarkLive<ELFT, TrackWhyLive>::mark() {
403
417
// Mark all reachable sections.
404
418
while (!queue.empty ()) {
405
419
InputSectionBase &sec = *queue.pop_back_val ();
@@ -419,15 +433,6 @@ template <class ELFT> void MarkLive<ELFT>::mark() {
419
433
if (sec.nextInSectionGroup )
420
434
enqueue (sec.nextInSectionGroup , 0 , nullptr , &sec);
421
435
}
422
-
423
- if (!ctx.arg .whyLive .empty ()) {
424
- for (Symbol *sym : ctx.symtab ->getSymbols ()) {
425
- if (llvm::any_of (ctx.arg .whyLive , [sym](const llvm::GlobPattern &pat) {
426
- return pat.match (sym->getName ());
427
- }))
428
- printWhyLive (sym);
429
- }
430
- }
431
436
}
432
437
433
438
// Move the sections for some symbols to the main partition, specifically ifuncs
@@ -439,7 +444,8 @@ template <class ELFT> void MarkLive<ELFT>::mark() {
439
444
// We also need to move sections whose names are C identifiers that are referred
440
445
// to from __start_/__stop_ symbols because there will only be one set of
441
446
// symbols for the whole program.
442
- template <class ELFT > void MarkLive<ELFT>::moveToMain() {
447
+ template <class ELFT , bool TrackWhyLive>
448
+ void MarkLive<ELFT, TrackWhyLive>::moveToMain() {
443
449
for (ELFFileBase *file : ctx.objectFiles )
444
450
for (Symbol *s : file->getSymbols ())
445
451
if (auto *d = dyn_cast<Defined>(s))
@@ -478,13 +484,16 @@ template <class ELFT> void elf::markLive(Ctx &ctx) {
478
484
479
485
// Follow the graph to mark all live sections.
480
486
for (unsigned i = 1 , e = ctx.partitions .size (); i <= e; ++i)
481
- MarkLive<ELFT>(ctx, i).run ();
487
+ if (ctx.arg .whyLive .empty ())
488
+ MarkLive<ELFT, false >(ctx, i).run ();
489
+ else
490
+ MarkLive<ELFT, true >(ctx, i).run ();
482
491
483
492
// If we have multiple partitions, some sections need to live in the main
484
493
// partition even if they were allocated to a loadable partition. Move them
485
494
// there now.
486
495
if (ctx.partitions .size () != 1 )
487
- MarkLive<ELFT>(ctx, 1 ).moveToMain ();
496
+ MarkLive<ELFT, false >(ctx, 1 ).moveToMain ();
488
497
489
498
// Report garbage-collected sections.
490
499
if (ctx.arg .printGcSections )
0 commit comments