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" 140b57cec5SDimitry Andric #include <vector> 150b57cec5SDimitry Andric 16*bdd1243dSDimitry Andric namespace lld::coff { 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric // Set live bit on for each reachable chunk. Unmarked (unreachable) 190b57cec5SDimitry Andric // COMDAT chunks will be ignored by Writer, so they will be excluded 200b57cec5SDimitry Andric // from the final output. 21349cc55cSDimitry Andric void markLive(COFFLinkerContext &ctx) { 22349cc55cSDimitry Andric ScopedTimer t(ctx.gcTimer); 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric // We build up a worklist of sections which have been marked as live. We only 250b57cec5SDimitry Andric // push into the worklist when we discover an unmarked section, and we mark 260b57cec5SDimitry Andric // as we push, so sections never appear twice in the list. 270b57cec5SDimitry Andric SmallVector<SectionChunk *, 256> worklist; 280b57cec5SDimitry Andric 29d65cd7a5SDimitry Andric // COMDAT section chunks are dead by default. Add non-COMDAT chunks. Do not 30d65cd7a5SDimitry Andric // traverse DWARF sections. They are live, but they should not keep other 31d65cd7a5SDimitry Andric // sections alive. 32349cc55cSDimitry Andric for (Chunk *c : ctx.symtab.getChunks()) 330b57cec5SDimitry Andric if (auto *sc = dyn_cast<SectionChunk>(c)) 34d65cd7a5SDimitry Andric if (sc->live && !sc->isDWARF()) 350b57cec5SDimitry Andric worklist.push_back(sc); 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric auto enqueue = [&](SectionChunk *c) { 380b57cec5SDimitry Andric if (c->live) 390b57cec5SDimitry Andric return; 400b57cec5SDimitry Andric c->live = true; 410b57cec5SDimitry Andric worklist.push_back(c); 420b57cec5SDimitry Andric }; 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric auto addSym = [&](Symbol *b) { 450b57cec5SDimitry Andric if (auto *sym = dyn_cast<DefinedRegular>(b)) 460b57cec5SDimitry Andric enqueue(sym->getChunk()); 470b57cec5SDimitry Andric else if (auto *sym = dyn_cast<DefinedImportData>(b)) 480b57cec5SDimitry Andric sym->file->live = true; 490b57cec5SDimitry Andric else if (auto *sym = dyn_cast<DefinedImportThunk>(b)) 500b57cec5SDimitry Andric sym->wrappedSym->file->live = sym->wrappedSym->file->thunkLive = true; 510b57cec5SDimitry Andric }; 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric // Add GC root chunks. 54*bdd1243dSDimitry Andric for (Symbol *b : ctx.config.gcroot) 550b57cec5SDimitry Andric addSym(b); 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric while (!worklist.empty()) { 580b57cec5SDimitry Andric SectionChunk *sc = worklist.pop_back_val(); 590b57cec5SDimitry Andric assert(sc->live && "We mark as live when pushing onto the worklist!"); 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric // Mark all symbols listed in the relocation table for this section. 620b57cec5SDimitry Andric for (Symbol *b : sc->symbols()) 630b57cec5SDimitry Andric if (b) 640b57cec5SDimitry Andric addSym(b); 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric // Mark associative sections if any. 670b57cec5SDimitry Andric for (SectionChunk &c : sc->children()) 680b57cec5SDimitry Andric enqueue(&c); 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric } 72