1fe6060f1SDimitry Andric //===- MarkLive.cpp -------------------------------------------------------===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric
9fe6060f1SDimitry Andric #include "MarkLive.h"
10fe6060f1SDimitry Andric #include "Config.h"
11fe6060f1SDimitry Andric #include "OutputSegment.h"
12fe6060f1SDimitry Andric #include "SymbolTable.h"
13fe6060f1SDimitry Andric #include "Symbols.h"
14fe6060f1SDimitry Andric #include "UnwindInfoSection.h"
15bdd1243dSDimitry Andric
16bdd1243dSDimitry Andric #include "lld/Common/ErrorHandler.h"
17fe6060f1SDimitry Andric #include "llvm/Support/TimeProfiler.h"
18fe6060f1SDimitry Andric
19bdd1243dSDimitry Andric #include "mach-o/compact_unwind_encoding.h"
20bdd1243dSDimitry Andric
21bdd1243dSDimitry Andric namespace lld::macho {
22fe6060f1SDimitry Andric
23fe6060f1SDimitry Andric using namespace llvm;
24fe6060f1SDimitry Andric using namespace llvm::MachO;
25fe6060f1SDimitry Andric
2681ad6265SDimitry Andric struct WhyLiveEntry {
2781ad6265SDimitry Andric InputSection *isec;
2881ad6265SDimitry Andric // Keep track of the entry that caused us to mark `isec` as live.
2981ad6265SDimitry Andric const WhyLiveEntry *prev;
30fe6060f1SDimitry Andric
WhyLiveEntrylld::macho::WhyLiveEntry3181ad6265SDimitry Andric WhyLiveEntry(InputSection *isec, const WhyLiveEntry *prev)
3281ad6265SDimitry Andric : isec(isec), prev(prev) {}
3381ad6265SDimitry Andric };
34fe6060f1SDimitry Andric
3581ad6265SDimitry Andric // Type-erased interface to MarkLiveImpl. Used for adding roots to the liveness
3681ad6265SDimitry Andric // graph.
3781ad6265SDimitry Andric class MarkLive {
3881ad6265SDimitry Andric public:
3981ad6265SDimitry Andric virtual void enqueue(InputSection *isec, uint64_t off) = 0;
4081ad6265SDimitry Andric virtual void addSym(Symbol *s) = 0;
4181ad6265SDimitry Andric virtual void markTransitively() = 0;
4281ad6265SDimitry Andric virtual ~MarkLive() = default;
4381ad6265SDimitry Andric };
4481ad6265SDimitry Andric
4581ad6265SDimitry Andric template <bool RecordWhyLive> class MarkLiveImpl : public MarkLive {
4681ad6265SDimitry Andric public:
4781ad6265SDimitry Andric // -why_live is a rarely used option, so we don't want support for that flag
4881ad6265SDimitry Andric // to slow down the main -dead_strip code path. As such, we employ templates
4981ad6265SDimitry Andric // to avoid the usage of WhyLiveEntry in the main code path. This saves us
5081ad6265SDimitry Andric // from needless allocations and pointer indirections.
5181ad6265SDimitry Andric using WorklistEntry =
5281ad6265SDimitry Andric std::conditional_t<RecordWhyLive, WhyLiveEntry, InputSection>;
5381ad6265SDimitry Andric
enqueue(InputSection * isec,uint64_t off)5481ad6265SDimitry Andric void enqueue(InputSection *isec, uint64_t off) override {
5581ad6265SDimitry Andric enqueue(isec, off, nullptr);
5681ad6265SDimitry Andric }
addSym(Symbol * s)5781ad6265SDimitry Andric void addSym(Symbol *s) override { addSym(s, nullptr); }
5881ad6265SDimitry Andric void markTransitively() override;
5981ad6265SDimitry Andric
6081ad6265SDimitry Andric private:
6181ad6265SDimitry Andric void enqueue(InputSection *isec, uint64_t off, const WorklistEntry *prev);
6281ad6265SDimitry Andric void addSym(Symbol *s, const WorklistEntry *prev);
6381ad6265SDimitry Andric const InputSection *getInputSection(const WorklistEntry *) const;
6481ad6265SDimitry Andric WorklistEntry *makeEntry(InputSection *, const WorklistEntry *prev) const;
6581ad6265SDimitry Andric
6681ad6265SDimitry Andric // We build up a worklist of sections which have been marked as live. We
6781ad6265SDimitry Andric // only push into the worklist when we discover an unmarked section, and we
6881ad6265SDimitry Andric // mark as we push, so sections never appear twice in the list. Literal
6981ad6265SDimitry Andric // sections cannot contain references to other sections, so we only store
7081ad6265SDimitry Andric // ConcatInputSections in our worklist.
7181ad6265SDimitry Andric SmallVector<WorklistEntry *, 256> worklist;
7281ad6265SDimitry Andric };
7381ad6265SDimitry Andric
7481ad6265SDimitry Andric template <bool RecordWhyLive>
enqueue(InputSection * isec,uint64_t off,const typename MarkLiveImpl<RecordWhyLive>::WorklistEntry * prev)7581ad6265SDimitry Andric void MarkLiveImpl<RecordWhyLive>::enqueue(
7681ad6265SDimitry Andric InputSection *isec, uint64_t off,
7781ad6265SDimitry Andric const typename MarkLiveImpl<RecordWhyLive>::WorklistEntry *prev) {
78fe6060f1SDimitry Andric if (isec->isLive(off))
79fe6060f1SDimitry Andric return;
80fe6060f1SDimitry Andric isec->markLive(off);
81fe6060f1SDimitry Andric if (auto s = dyn_cast<ConcatInputSection>(isec)) {
82fe6060f1SDimitry Andric assert(!s->isCoalescedWeak());
8381ad6265SDimitry Andric worklist.push_back(makeEntry(s, prev));
84fe6060f1SDimitry Andric }
8581ad6265SDimitry Andric }
86fe6060f1SDimitry Andric
printWhyLive(const Symbol * s,const WhyLiveEntry * prev)87bdd1243dSDimitry Andric static void printWhyLive(const Symbol *s, const WhyLiveEntry *prev) {
8881ad6265SDimitry Andric std::string out = toString(*s) + " from " + toString(s->getFile());
8981ad6265SDimitry Andric int indent = 2;
9081ad6265SDimitry Andric for (const WhyLiveEntry *entry = prev; entry;
9181ad6265SDimitry Andric entry = entry->prev, indent += 2) {
9281ad6265SDimitry Andric const TinyPtrVector<Defined *> &symbols = entry->isec->symbols;
9381ad6265SDimitry Andric // With .subsections_with_symbols set, most isecs will have exactly one
9481ad6265SDimitry Andric // entry in their symbols vector, so we just print the first one.
9581ad6265SDimitry Andric if (!symbols.empty())
9681ad6265SDimitry Andric out += "\n" + std::string(indent, ' ') + toString(*symbols.front()) +
9781ad6265SDimitry Andric " from " + toString(symbols.front()->getFile());
9881ad6265SDimitry Andric }
9981ad6265SDimitry Andric message(out);
10081ad6265SDimitry Andric }
10181ad6265SDimitry Andric
102bdd1243dSDimitry Andric template <bool RecordWhyLive>
addSym(Symbol * s,const typename MarkLiveImpl<RecordWhyLive>::WorklistEntry * prev)103bdd1243dSDimitry Andric void MarkLiveImpl<RecordWhyLive>::addSym(
104bdd1243dSDimitry Andric Symbol *s,
105bdd1243dSDimitry Andric const typename MarkLiveImpl<RecordWhyLive>::WorklistEntry *prev) {
106bdd1243dSDimitry Andric if (s->used)
107bdd1243dSDimitry Andric return;
108bdd1243dSDimitry Andric s->used = true;
109bdd1243dSDimitry Andric if constexpr (RecordWhyLive)
11081ad6265SDimitry Andric if (!config->whyLive.empty() && config->whyLive.match(s->getName()))
111bdd1243dSDimitry Andric printWhyLive(s, prev);
112bdd1243dSDimitry Andric if (auto *d = dyn_cast<Defined>(s)) {
113*0fca6ea1SDimitry Andric if (d->isec())
114*0fca6ea1SDimitry Andric enqueue(d->isec(), d->value, prev);
115*0fca6ea1SDimitry Andric if (d->unwindEntry())
116*0fca6ea1SDimitry Andric enqueue(d->unwindEntry(), 0, prev);
117bdd1243dSDimitry Andric }
11881ad6265SDimitry Andric }
11981ad6265SDimitry Andric
120bdd1243dSDimitry Andric template <bool RecordWhyLive>
getInputSection(const MarkLiveImpl<RecordWhyLive>::WorklistEntry * entry) const121bdd1243dSDimitry Andric const InputSection *MarkLiveImpl<RecordWhyLive>::getInputSection(
122bdd1243dSDimitry Andric const MarkLiveImpl<RecordWhyLive>::WorklistEntry *entry) const {
123bdd1243dSDimitry Andric if constexpr (RecordWhyLive)
12481ad6265SDimitry Andric return entry->isec;
125bdd1243dSDimitry Andric else
126bdd1243dSDimitry Andric return entry;
12781ad6265SDimitry Andric }
12881ad6265SDimitry Andric
129bdd1243dSDimitry Andric template <bool RecordWhyLive>
130bdd1243dSDimitry Andric typename MarkLiveImpl<RecordWhyLive>::WorklistEntry *
makeEntry(InputSection * isec,const MarkLiveImpl<RecordWhyLive>::WorklistEntry * prev) const131bdd1243dSDimitry Andric MarkLiveImpl<RecordWhyLive>::makeEntry(
132bdd1243dSDimitry Andric InputSection *isec,
133bdd1243dSDimitry Andric const MarkLiveImpl<RecordWhyLive>::WorklistEntry *prev) const {
134bdd1243dSDimitry Andric if constexpr (RecordWhyLive) {
13581ad6265SDimitry Andric if (!isec) {
13681ad6265SDimitry Andric assert(!prev);
13781ad6265SDimitry Andric return nullptr;
13881ad6265SDimitry Andric }
13981ad6265SDimitry Andric return make<WhyLiveEntry>(isec, prev);
140bdd1243dSDimitry Andric } else {
14181ad6265SDimitry Andric return isec;
14281ad6265SDimitry Andric }
143bdd1243dSDimitry Andric }
14481ad6265SDimitry Andric
14581ad6265SDimitry Andric template <bool RecordWhyLive>
markTransitively()14681ad6265SDimitry Andric void MarkLiveImpl<RecordWhyLive>::markTransitively() {
14781ad6265SDimitry Andric do {
14881ad6265SDimitry Andric // Mark things reachable from GC roots as live.
14981ad6265SDimitry Andric while (!worklist.empty()) {
15081ad6265SDimitry Andric WorklistEntry *entry = worklist.pop_back_val();
15181ad6265SDimitry Andric // Entries that get placed onto the worklist always contain
15281ad6265SDimitry Andric // ConcatInputSections. `WhyLiveEntry::prev` may point to entries that
15381ad6265SDimitry Andric // contain other types of InputSections (due to S_ATTR_LIVE_SUPPORT), but
15481ad6265SDimitry Andric // those entries should never be pushed onto the worklist.
15581ad6265SDimitry Andric auto *isec = cast<ConcatInputSection>(getInputSection(entry));
15681ad6265SDimitry Andric assert(isec->live && "We mark as live when pushing onto the worklist!");
15781ad6265SDimitry Andric
15881ad6265SDimitry Andric // Mark all symbols listed in the relocation table for this section.
15981ad6265SDimitry Andric for (const Reloc &r : isec->relocs) {
16081ad6265SDimitry Andric if (auto *s = r.referent.dyn_cast<Symbol *>())
16181ad6265SDimitry Andric addSym(s, entry);
16281ad6265SDimitry Andric else
16381ad6265SDimitry Andric enqueue(r.referent.get<InputSection *>(), r.addend, entry);
16481ad6265SDimitry Andric }
16581ad6265SDimitry Andric for (Defined *d : getInputSection(entry)->symbols)
16681ad6265SDimitry Andric addSym(d, entry);
16781ad6265SDimitry Andric }
16881ad6265SDimitry Andric
16981ad6265SDimitry Andric // S_ATTR_LIVE_SUPPORT sections are live if they point _to_ a live
17081ad6265SDimitry Andric // section. Process them in a second pass.
17181ad6265SDimitry Andric for (ConcatInputSection *isec : inputSections) {
17281ad6265SDimitry Andric // FIXME: Check if copying all S_ATTR_LIVE_SUPPORT sections into a
17381ad6265SDimitry Andric // separate vector and only walking that here is faster.
17481ad6265SDimitry Andric if (!(isec->getFlags() & S_ATTR_LIVE_SUPPORT) || isec->live)
17581ad6265SDimitry Andric continue;
17681ad6265SDimitry Andric
17781ad6265SDimitry Andric for (const Reloc &r : isec->relocs) {
17881ad6265SDimitry Andric if (auto *s = r.referent.dyn_cast<Symbol *>()) {
17981ad6265SDimitry Andric if (s->isLive()) {
18081ad6265SDimitry Andric InputSection *referentIsec = nullptr;
18181ad6265SDimitry Andric if (auto *d = dyn_cast<Defined>(s))
182*0fca6ea1SDimitry Andric referentIsec = d->isec();
18381ad6265SDimitry Andric enqueue(isec, 0, makeEntry(referentIsec, nullptr));
18481ad6265SDimitry Andric }
18581ad6265SDimitry Andric } else {
18681ad6265SDimitry Andric auto *referentIsec = r.referent.get<InputSection *>();
18781ad6265SDimitry Andric if (referentIsec->isLive(r.addend))
18881ad6265SDimitry Andric enqueue(isec, 0, makeEntry(referentIsec, nullptr));
18981ad6265SDimitry Andric }
19081ad6265SDimitry Andric }
19181ad6265SDimitry Andric }
19281ad6265SDimitry Andric
19381ad6265SDimitry Andric // S_ATTR_LIVE_SUPPORT could have marked additional sections live,
19481ad6265SDimitry Andric // which in turn could mark additional S_ATTR_LIVE_SUPPORT sections live.
19581ad6265SDimitry Andric // Iterate. In practice, the second iteration won't mark additional
19681ad6265SDimitry Andric // S_ATTR_LIVE_SUPPORT sections live.
19781ad6265SDimitry Andric } while (!worklist.empty());
19881ad6265SDimitry Andric }
19981ad6265SDimitry Andric
20081ad6265SDimitry Andric // Set live bit on for each reachable chunk. Unmarked (unreachable)
20181ad6265SDimitry Andric // InputSections will be ignored by Writer, so they will be excluded
20281ad6265SDimitry Andric // from the final output.
markLive()20381ad6265SDimitry Andric void markLive() {
20481ad6265SDimitry Andric TimeTraceScope timeScope("markLive");
20581ad6265SDimitry Andric MarkLive *marker;
20681ad6265SDimitry Andric if (config->whyLive.empty())
20781ad6265SDimitry Andric marker = make<MarkLiveImpl<false>>();
20881ad6265SDimitry Andric else
20981ad6265SDimitry Andric marker = make<MarkLiveImpl<true>>();
210fe6060f1SDimitry Andric // Add GC roots.
211fe6060f1SDimitry Andric if (config->entry)
21281ad6265SDimitry Andric marker->addSym(config->entry);
213fe6060f1SDimitry Andric for (Symbol *sym : symtab->getSymbols()) {
214fe6060f1SDimitry Andric if (auto *defined = dyn_cast<Defined>(sym)) {
215fe6060f1SDimitry Andric // -exported_symbol(s_list)
216fe6060f1SDimitry Andric if (!config->exportedSymbols.empty() &&
217fe6060f1SDimitry Andric config->exportedSymbols.match(defined->getName())) {
21881ad6265SDimitry Andric // NOTE: Even though exporting private externs is an ill-defined
21981ad6265SDimitry Andric // operation, we are purposely not checking for privateExtern in
22081ad6265SDimitry Andric // order to follow ld64's behavior of treating all exported private
22181ad6265SDimitry Andric // extern symbols as live, irrespective of whether they are autohide.
22281ad6265SDimitry Andric marker->addSym(defined);
223fe6060f1SDimitry Andric continue;
224fe6060f1SDimitry Andric }
225fe6060f1SDimitry Andric
226fe6060f1SDimitry Andric // public symbols explicitly marked .no_dead_strip
227fe6060f1SDimitry Andric if (defined->referencedDynamically || defined->noDeadStrip) {
22881ad6265SDimitry Andric marker->addSym(defined);
229fe6060f1SDimitry Andric continue;
230fe6060f1SDimitry Andric }
231fe6060f1SDimitry Andric
23281ad6265SDimitry Andric // FIXME: When we implement these flags, make symbols from them GC
23381ad6265SDimitry Andric // roots:
234fe6060f1SDimitry Andric // * -reexported_symbol(s_list)
235bdd1243dSDimitry Andric // * -alias_list
236fe6060f1SDimitry Andric // * -init
237fe6060f1SDimitry Andric
238fe6060f1SDimitry Andric // In dylibs and bundles and in executables with -export_dynamic,
239fe6060f1SDimitry Andric // all external functions are GC roots.
240fe6060f1SDimitry Andric bool externsAreRoots =
241fe6060f1SDimitry Andric config->outputType != MH_EXECUTE || config->exportDynamic;
242fe6060f1SDimitry Andric if (externsAreRoots && !defined->privateExtern) {
24381ad6265SDimitry Andric marker->addSym(defined);
244fe6060f1SDimitry Andric continue;
245fe6060f1SDimitry Andric }
246fe6060f1SDimitry Andric }
247fe6060f1SDimitry Andric }
248fe6060f1SDimitry Andric // -u symbols
249fe6060f1SDimitry Andric for (Symbol *sym : config->explicitUndefineds)
25081ad6265SDimitry Andric marker->addSym(sym);
251fe6060f1SDimitry Andric // local symbols explicitly marked .no_dead_strip
252fe6060f1SDimitry Andric for (const InputFile *file : inputFiles)
253fe6060f1SDimitry Andric if (auto *objFile = dyn_cast<ObjFile>(file))
254fe6060f1SDimitry Andric for (Symbol *sym : objFile->symbols)
255fe6060f1SDimitry Andric if (auto *defined = dyn_cast_or_null<Defined>(sym))
256fe6060f1SDimitry Andric if (!defined->isExternal() && defined->noDeadStrip)
25781ad6265SDimitry Andric marker->addSym(defined);
258fe6060f1SDimitry Andric if (auto *stubBinder =
259fe6060f1SDimitry Andric dyn_cast_or_null<DylibSymbol>(symtab->find("dyld_stub_binder")))
26081ad6265SDimitry Andric marker->addSym(stubBinder);
261fe6060f1SDimitry Andric for (ConcatInputSection *isec : inputSections) {
262fe6060f1SDimitry Andric // Sections marked no_dead_strip
263fe6060f1SDimitry Andric if (isec->getFlags() & S_ATTR_NO_DEAD_STRIP) {
26481ad6265SDimitry Andric marker->enqueue(isec, 0);
265fe6060f1SDimitry Andric continue;
266fe6060f1SDimitry Andric }
267fe6060f1SDimitry Andric
268fe6060f1SDimitry Andric // mod_init_funcs, mod_term_funcs sections
269fe6060f1SDimitry Andric if (sectionType(isec->getFlags()) == S_MOD_INIT_FUNC_POINTERS ||
270fe6060f1SDimitry Andric sectionType(isec->getFlags()) == S_MOD_TERM_FUNC_POINTERS) {
271bdd1243dSDimitry Andric assert(!config->emitInitOffsets ||
272bdd1243dSDimitry Andric sectionType(isec->getFlags()) != S_MOD_INIT_FUNC_POINTERS);
27381ad6265SDimitry Andric marker->enqueue(isec, 0);
274fe6060f1SDimitry Andric continue;
275fe6060f1SDimitry Andric }
276fe6060f1SDimitry Andric }
277fe6060f1SDimitry Andric
278bdd1243dSDimitry Andric for (ConcatInputSection *isec : in.initOffsets->inputs())
279bdd1243dSDimitry Andric marker->enqueue(isec, 0);
280bdd1243dSDimitry Andric
28181ad6265SDimitry Andric marker->markTransitively();
282fe6060f1SDimitry Andric }
283fe6060f1SDimitry Andric
284bdd1243dSDimitry Andric } // namespace lld::macho
285