1//===- MarkLive.cpp -------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "COFFLinkerContext.h"
10#include "Chunks.h"
11#include "Symbols.h"
12#include "lld/Common/Timer.h"
13#include "llvm/ADT/STLExtras.h"
14#include "llvm/Support/TimeProfiler.h"
15#include <vector>
16
17namespace lld::coff {
18
19// Set live bit on for each reachable chunk. Unmarked (unreachable)
20// COMDAT chunks will be ignored by Writer, so they will be excluded
21// from the final output.
22void markLive(COFFLinkerContext &ctx) {
23 llvm::TimeTraceScope timeScope("Mark live");
24 ScopedTimer t(ctx.gcTimer);
25
26 // We build up a worklist of sections which have been marked as live. We only
27 // push into the worklist when we discover an unmarked section, and we mark
28 // as we push, so sections never appear twice in the list.
29 SmallVector<SectionChunk *, 256> worklist;
30
31 // COMDAT section chunks are dead by default. Add non-COMDAT chunks. Do not
32 // traverse DWARF sections. They are live, but they should not keep other
33 // sections alive.
34 for (Chunk *c : ctx.symtab.getChunks())
35 if (auto *sc = dyn_cast<SectionChunk>(Val: c))
36 if (sc->live && !sc->isDWARF())
37 worklist.push_back(Elt: sc);
38
39 auto enqueue = [&](SectionChunk *c) {
40 if (c->live)
41 return;
42 c->live = true;
43 worklist.push_back(Elt: c);
44 };
45
46 auto addSym = [&](Symbol *b) {
47 if (auto *sym = dyn_cast<DefinedRegular>(Val: b))
48 enqueue(sym->getChunk());
49 else if (auto *sym = dyn_cast<DefinedImportData>(Val: b))
50 sym->file->live = true;
51 else if (auto *sym = dyn_cast<DefinedImportThunk>(Val: b))
52 sym->wrappedSym->file->live = sym->wrappedSym->file->thunkLive = true;
53 };
54
55 // Add GC root chunks.
56 for (Symbol *b : ctx.config.gcroot)
57 addSym(b);
58
59 while (!worklist.empty()) {
60 SectionChunk *sc = worklist.pop_back_val();
61 assert(sc->live && "We mark as live when pushing onto the worklist!");
62
63 // Mark all symbols listed in the relocation table for this section.
64 for (Symbol *b : sc->symbols())
65 if (b)
66 addSym(b);
67
68 // Mark associative sections if any.
69 for (SectionChunk &c : sc->children())
70 enqueue(&c);
71
72 // Mark EC entry thunks.
73 if (Defined *entryThunk = sc->getEntryThunk())
74 addSym(entryThunk);
75 }
76}
77}
78