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 17 namespace 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. 22 void 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.driver.getChunks()) 35 if (auto *sc = dyn_cast<SectionChunk>(c)) 36 if (sc->live && !sc->isDWARF()) 37 worklist.push_back(sc); 38 39 auto enqueue = [&](SectionChunk *c) { 40 if (c->live) 41 return; 42 c->live = true; 43 worklist.push_back(c); 44 }; 45 46 std::function<void(Symbol *)> addSym; 47 48 auto addImportFile = [&](ImportFile *file) { 49 file->live = true; 50 if (file->impchkThunk && file->impchkThunk->exitThunk) 51 addSym(file->impchkThunk->exitThunk); 52 }; 53 54 addSym = [&](Symbol *b) { 55 if (auto *sym = dyn_cast<DefinedRegular>(b)) { 56 enqueue(sym->getChunk()); 57 } else if (auto *sym = dyn_cast<DefinedImportData>(b)) { 58 addImportFile(sym->file); 59 } else if (auto *sym = dyn_cast<DefinedImportThunk>(b)) { 60 addImportFile(sym->wrappedSym->file); 61 sym->getChunk()->live = true; 62 } 63 }; 64 65 // Add GC root chunks. 66 for (Symbol *b : ctx.config.gcroot) 67 addSym(b); 68 69 while (!worklist.empty()) { 70 SectionChunk *sc = worklist.pop_back_val(); 71 assert(sc->live && "We mark as live when pushing onto the worklist!"); 72 73 // Mark all symbols listed in the relocation table for this section. 74 for (Symbol *b : sc->symbols()) 75 if (b) 76 addSym(b); 77 78 // Mark associative sections if any. 79 for (SectionChunk &c : sc->children()) 80 enqueue(&c); 81 82 // Mark EC entry thunks. 83 if (Defined *entryThunk = sc->getEntryThunk()) 84 addSym(entryThunk); 85 } 86 } 87 } 88