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 <vector>
15 
16 namespace lld {
17 namespace 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.
22 void markLive(COFFLinkerContext &ctx) {
23   ScopedTimer t(ctx.gcTimer);
24 
25   // We build up a worklist of sections which have been marked as live. We only
26   // push into the worklist when we discover an unmarked section, and we mark
27   // as we push, so sections never appear twice in the list.
28   SmallVector<SectionChunk *, 256> worklist;
29 
30   // COMDAT section chunks are dead by default. Add non-COMDAT chunks. Do not
31   // traverse DWARF sections. They are live, but they should not keep other
32   // sections alive.
33   for (Chunk *c : ctx.symtab.getChunks())
34     if (auto *sc = dyn_cast<SectionChunk>(c))
35       if (sc->live && !sc->isDWARF())
36         worklist.push_back(sc);
37 
38   auto enqueue = [&](SectionChunk *c) {
39     if (c->live)
40       return;
41     c->live = true;
42     worklist.push_back(c);
43   };
44 
45   auto addSym = [&](Symbol *b) {
46     if (auto *sym = dyn_cast<DefinedRegular>(b))
47       enqueue(sym->getChunk());
48     else if (auto *sym = dyn_cast<DefinedImportData>(b))
49       sym->file->live = true;
50     else if (auto *sym = dyn_cast<DefinedImportThunk>(b))
51       sym->wrappedSym->file->live = sym->wrappedSym->file->thunkLive = true;
52   };
53 
54   // Add GC root chunks.
55   for (Symbol *b : config->gcroot)
56     addSym(b);
57 
58   while (!worklist.empty()) {
59     SectionChunk *sc = worklist.pop_back_val();
60     assert(sc->live && "We mark as live when pushing onto the worklist!");
61 
62     // Mark all symbols listed in the relocation table for this section.
63     for (Symbol *b : sc->symbols())
64       if (b)
65         addSym(b);
66 
67     // Mark associative sections if any.
68     for (SectionChunk &c : sc->children())
69       enqueue(&c);
70   }
71 }
72 }
73 }
74