10b57cec5SDimitry Andric //===- MarkLive.cpp -------------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 9349cc55cSDimitry Andric #include "COFFLinkerContext.h" 100b57cec5SDimitry Andric #include "Chunks.h" 110b57cec5SDimitry Andric #include "Symbols.h" 120b57cec5SDimitry Andric #include "lld/Common/Timer.h" 130b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 145f757f3fSDimitry Andric #include "llvm/Support/TimeProfiler.h" 150b57cec5SDimitry Andric #include <vector> 160b57cec5SDimitry Andric 17bdd1243dSDimitry Andric namespace lld::coff { 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric // Set live bit on for each reachable chunk. Unmarked (unreachable) 200b57cec5SDimitry Andric // COMDAT chunks will be ignored by Writer, so they will be excluded 210b57cec5SDimitry Andric // from the final output. markLive(COFFLinkerContext & ctx)22349cc55cSDimitry Andricvoid markLive(COFFLinkerContext &ctx) { 235f757f3fSDimitry Andric llvm::TimeTraceScope timeScope("Mark live"); 24349cc55cSDimitry Andric ScopedTimer t(ctx.gcTimer); 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric // We build up a worklist of sections which have been marked as live. We only 270b57cec5SDimitry Andric // push into the worklist when we discover an unmarked section, and we mark 280b57cec5SDimitry Andric // as we push, so sections never appear twice in the list. 290b57cec5SDimitry Andric SmallVector<SectionChunk *, 256> worklist; 300b57cec5SDimitry Andric 31d65cd7a5SDimitry Andric // COMDAT section chunks are dead by default. Add non-COMDAT chunks. Do not 32d65cd7a5SDimitry Andric // traverse DWARF sections. They are live, but they should not keep other 33d65cd7a5SDimitry Andric // sections alive. 34349cc55cSDimitry Andric for (Chunk *c : ctx.symtab.getChunks()) 350b57cec5SDimitry Andric if (auto *sc = dyn_cast<SectionChunk>(c)) 36d65cd7a5SDimitry Andric if (sc->live && !sc->isDWARF()) 370b57cec5SDimitry Andric worklist.push_back(sc); 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric auto enqueue = [&](SectionChunk *c) { 400b57cec5SDimitry Andric if (c->live) 410b57cec5SDimitry Andric return; 420b57cec5SDimitry Andric c->live = true; 430b57cec5SDimitry Andric worklist.push_back(c); 440b57cec5SDimitry Andric }; 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric auto addSym = [&](Symbol *b) { 470b57cec5SDimitry Andric if (auto *sym = dyn_cast<DefinedRegular>(b)) 480b57cec5SDimitry Andric enqueue(sym->getChunk()); 490b57cec5SDimitry Andric else if (auto *sym = dyn_cast<DefinedImportData>(b)) 500b57cec5SDimitry Andric sym->file->live = true; 510b57cec5SDimitry Andric else if (auto *sym = dyn_cast<DefinedImportThunk>(b)) 520b57cec5SDimitry Andric sym->wrappedSym->file->live = sym->wrappedSym->file->thunkLive = true; 530b57cec5SDimitry Andric }; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric // Add GC root chunks. 56bdd1243dSDimitry Andric for (Symbol *b : ctx.config.gcroot) 570b57cec5SDimitry Andric addSym(b); 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric while (!worklist.empty()) { 600b57cec5SDimitry Andric SectionChunk *sc = worklist.pop_back_val(); 610b57cec5SDimitry Andric assert(sc->live && "We mark as live when pushing onto the worklist!"); 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric // Mark all symbols listed in the relocation table for this section. 640b57cec5SDimitry Andric for (Symbol *b : sc->symbols()) 650b57cec5SDimitry Andric if (b) 660b57cec5SDimitry Andric addSym(b); 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric // Mark associative sections if any. 690b57cec5SDimitry Andric for (SectionChunk &c : sc->children()) 700b57cec5SDimitry Andric enqueue(&c); 71*0fca6ea1SDimitry Andric 72*0fca6ea1SDimitry Andric // Mark EC entry thunks. 73*0fca6ea1SDimitry Andric if (Defined *entryThunk = sc->getEntryThunk()) 74*0fca6ea1SDimitry Andric addSym(entryThunk); 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric } 78