xref: /openbsd/gnu/llvm/lld/MachO/MarkLive.cpp (revision dfe94b16)
11cf9926bSpatrick //===- MarkLive.cpp -------------------------------------------------------===//
21cf9926bSpatrick //
31cf9926bSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41cf9926bSpatrick // See https://llvm.org/LICENSE.txt for license information.
51cf9926bSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61cf9926bSpatrick //
71cf9926bSpatrick //===----------------------------------------------------------------------===//
81cf9926bSpatrick 
91cf9926bSpatrick #include "MarkLive.h"
101cf9926bSpatrick #include "Config.h"
111cf9926bSpatrick #include "OutputSegment.h"
121cf9926bSpatrick #include "SymbolTable.h"
131cf9926bSpatrick #include "Symbols.h"
141cf9926bSpatrick #include "UnwindInfoSection.h"
15*dfe94b16Srobert 
16*dfe94b16Srobert #include "lld/Common/ErrorHandler.h"
171cf9926bSpatrick #include "llvm/Support/TimeProfiler.h"
181cf9926bSpatrick 
19*dfe94b16Srobert #include "mach-o/compact_unwind_encoding.h"
20*dfe94b16Srobert 
21*dfe94b16Srobert namespace lld::macho {
221cf9926bSpatrick 
231cf9926bSpatrick using namespace llvm;
241cf9926bSpatrick using namespace llvm::MachO;
251cf9926bSpatrick 
26*dfe94b16Srobert struct WhyLiveEntry {
27*dfe94b16Srobert   InputSection *isec;
28*dfe94b16Srobert   // Keep track of the entry that caused us to mark `isec` as live.
29*dfe94b16Srobert   const WhyLiveEntry *prev;
301cf9926bSpatrick 
WhyLiveEntrylld::macho::WhyLiveEntry31*dfe94b16Srobert   WhyLiveEntry(InputSection *isec, const WhyLiveEntry *prev)
32*dfe94b16Srobert       : isec(isec), prev(prev) {}
33*dfe94b16Srobert };
341cf9926bSpatrick 
35*dfe94b16Srobert // Type-erased interface to MarkLiveImpl. Used for adding roots to the liveness
36*dfe94b16Srobert // graph.
37*dfe94b16Srobert class MarkLive {
38*dfe94b16Srobert public:
39*dfe94b16Srobert   virtual void enqueue(InputSection *isec, uint64_t off) = 0;
40*dfe94b16Srobert   virtual void addSym(Symbol *s) = 0;
41*dfe94b16Srobert   virtual void markTransitively() = 0;
42*dfe94b16Srobert   virtual ~MarkLive() = default;
43*dfe94b16Srobert };
44*dfe94b16Srobert 
45*dfe94b16Srobert template <bool RecordWhyLive> class MarkLiveImpl : public MarkLive {
46*dfe94b16Srobert public:
47*dfe94b16Srobert   // -why_live is a rarely used option, so we don't want support for that flag
48*dfe94b16Srobert   // to slow down the main -dead_strip code path. As such, we employ templates
49*dfe94b16Srobert   // to avoid the usage of WhyLiveEntry in the main code path. This saves us
50*dfe94b16Srobert   // from needless allocations and pointer indirections.
51*dfe94b16Srobert   using WorklistEntry =
52*dfe94b16Srobert       std::conditional_t<RecordWhyLive, WhyLiveEntry, InputSection>;
53*dfe94b16Srobert 
enqueue(InputSection * isec,uint64_t off)54*dfe94b16Srobert   void enqueue(InputSection *isec, uint64_t off) override {
55*dfe94b16Srobert     enqueue(isec, off, nullptr);
56*dfe94b16Srobert   }
addSym(Symbol * s)57*dfe94b16Srobert   void addSym(Symbol *s) override { addSym(s, nullptr); }
58*dfe94b16Srobert   void markTransitively() override;
59*dfe94b16Srobert 
60*dfe94b16Srobert private:
61*dfe94b16Srobert   void enqueue(InputSection *isec, uint64_t off, const WorklistEntry *prev);
62*dfe94b16Srobert   void addSym(Symbol *s, const WorklistEntry *prev);
63*dfe94b16Srobert   const InputSection *getInputSection(const WorklistEntry *) const;
64*dfe94b16Srobert   WorklistEntry *makeEntry(InputSection *, const WorklistEntry *prev) const;
65*dfe94b16Srobert 
66*dfe94b16Srobert   // We build up a worklist of sections which have been marked as live. We
67*dfe94b16Srobert   // only push into the worklist when we discover an unmarked section, and we
68*dfe94b16Srobert   // mark as we push, so sections never appear twice in the list. Literal
69*dfe94b16Srobert   // sections cannot contain references to other sections, so we only store
70*dfe94b16Srobert   // ConcatInputSections in our worklist.
71*dfe94b16Srobert   SmallVector<WorklistEntry *, 256> worklist;
72*dfe94b16Srobert };
73*dfe94b16Srobert 
74*dfe94b16Srobert template <bool RecordWhyLive>
enqueue(InputSection * isec,uint64_t off,const typename MarkLiveImpl<RecordWhyLive>::WorklistEntry * prev)75*dfe94b16Srobert void MarkLiveImpl<RecordWhyLive>::enqueue(
76*dfe94b16Srobert     InputSection *isec, uint64_t off,
77*dfe94b16Srobert     const typename MarkLiveImpl<RecordWhyLive>::WorklistEntry *prev) {
781cf9926bSpatrick   if (isec->isLive(off))
791cf9926bSpatrick     return;
801cf9926bSpatrick   isec->markLive(off);
811cf9926bSpatrick   if (auto s = dyn_cast<ConcatInputSection>(isec)) {
821cf9926bSpatrick     assert(!s->isCoalescedWeak());
83*dfe94b16Srobert     worklist.push_back(makeEntry(s, prev));
841cf9926bSpatrick   }
85*dfe94b16Srobert }
861cf9926bSpatrick 
printWhyLive(const Symbol * s,const WhyLiveEntry * prev)87*dfe94b16Srobert static void printWhyLive(const Symbol *s, const WhyLiveEntry *prev) {
88*dfe94b16Srobert   std::string out = toString(*s) + " from " + toString(s->getFile());
89*dfe94b16Srobert   int indent = 2;
90*dfe94b16Srobert   for (const WhyLiveEntry *entry = prev; entry;
91*dfe94b16Srobert        entry = entry->prev, indent += 2) {
92*dfe94b16Srobert     const TinyPtrVector<Defined *> &symbols = entry->isec->symbols;
93*dfe94b16Srobert     // With .subsections_with_symbols set, most isecs will have exactly one
94*dfe94b16Srobert     // entry in their symbols vector, so we just print the first one.
95*dfe94b16Srobert     if (!symbols.empty())
96*dfe94b16Srobert       out += "\n" + std::string(indent, ' ') + toString(*symbols.front()) +
97*dfe94b16Srobert              " from " + toString(symbols.front()->getFile());
98*dfe94b16Srobert   }
99*dfe94b16Srobert   message(out);
100*dfe94b16Srobert }
101*dfe94b16Srobert 
102*dfe94b16Srobert template <bool RecordWhyLive>
addSym(Symbol * s,const typename MarkLiveImpl<RecordWhyLive>::WorklistEntry * prev)103*dfe94b16Srobert void MarkLiveImpl<RecordWhyLive>::addSym(
104*dfe94b16Srobert     Symbol *s,
105*dfe94b16Srobert     const typename MarkLiveImpl<RecordWhyLive>::WorklistEntry *prev) {
106*dfe94b16Srobert   if (s->used)
107*dfe94b16Srobert     return;
1081cf9926bSpatrick   s->used = true;
109*dfe94b16Srobert   if constexpr (RecordWhyLive)
110*dfe94b16Srobert     if (!config->whyLive.empty() && config->whyLive.match(s->getName()))
111*dfe94b16Srobert       printWhyLive(s, prev);
112*dfe94b16Srobert   if (auto *d = dyn_cast<Defined>(s)) {
1131cf9926bSpatrick     if (d->isec)
114*dfe94b16Srobert       enqueue(d->isec, d->value, prev);
115*dfe94b16Srobert     if (d->unwindEntry)
116*dfe94b16Srobert       enqueue(d->unwindEntry, 0, prev);
1171cf9926bSpatrick   }
1181cf9926bSpatrick }
1191cf9926bSpatrick 
120*dfe94b16Srobert template <bool RecordWhyLive>
getInputSection(const MarkLiveImpl<RecordWhyLive>::WorklistEntry * entry) const121*dfe94b16Srobert const InputSection *MarkLiveImpl<RecordWhyLive>::getInputSection(
122*dfe94b16Srobert     const MarkLiveImpl<RecordWhyLive>::WorklistEntry *entry) const {
123*dfe94b16Srobert   if constexpr (RecordWhyLive)
124*dfe94b16Srobert     return entry->isec;
1251cf9926bSpatrick   else
126*dfe94b16Srobert     return entry;
127*dfe94b16Srobert }
128*dfe94b16Srobert 
129*dfe94b16Srobert template <bool RecordWhyLive>
130*dfe94b16Srobert typename MarkLiveImpl<RecordWhyLive>::WorklistEntry *
makeEntry(InputSection * isec,const MarkLiveImpl<RecordWhyLive>::WorklistEntry * prev) const131*dfe94b16Srobert MarkLiveImpl<RecordWhyLive>::makeEntry(
132*dfe94b16Srobert     InputSection *isec,
133*dfe94b16Srobert     const MarkLiveImpl<RecordWhyLive>::WorklistEntry *prev) const {
134*dfe94b16Srobert   if constexpr (RecordWhyLive) {
135*dfe94b16Srobert     if (!isec) {
136*dfe94b16Srobert       assert(!prev);
137*dfe94b16Srobert       return nullptr;
138*dfe94b16Srobert     }
139*dfe94b16Srobert     return make<WhyLiveEntry>(isec, prev);
140*dfe94b16Srobert   } else {
141*dfe94b16Srobert     return isec;
1421cf9926bSpatrick   }
1431cf9926bSpatrick }
1441cf9926bSpatrick 
145*dfe94b16Srobert template <bool RecordWhyLive>
markTransitively()146*dfe94b16Srobert void MarkLiveImpl<RecordWhyLive>::markTransitively() {
1471cf9926bSpatrick   do {
1481cf9926bSpatrick     // Mark things reachable from GC roots as live.
1491cf9926bSpatrick     while (!worklist.empty()) {
150*dfe94b16Srobert       WorklistEntry *entry = worklist.pop_back_val();
151*dfe94b16Srobert       // Entries that get placed onto the worklist always contain
152*dfe94b16Srobert       // ConcatInputSections. `WhyLiveEntry::prev` may point to entries that
153*dfe94b16Srobert       // contain other types of InputSections (due to S_ATTR_LIVE_SUPPORT), but
154*dfe94b16Srobert       // those entries should never be pushed onto the worklist.
155*dfe94b16Srobert       auto *isec = cast<ConcatInputSection>(getInputSection(entry));
156*dfe94b16Srobert       assert(isec->live && "We mark as live when pushing onto the worklist!");
1571cf9926bSpatrick 
1581cf9926bSpatrick       // Mark all symbols listed in the relocation table for this section.
159*dfe94b16Srobert       for (const Reloc &r : isec->relocs) {
1601cf9926bSpatrick         if (auto *s = r.referent.dyn_cast<Symbol *>())
161*dfe94b16Srobert           addSym(s, entry);
1621cf9926bSpatrick         else
163*dfe94b16Srobert           enqueue(r.referent.get<InputSection *>(), r.addend, entry);
1641cf9926bSpatrick       }
165*dfe94b16Srobert       for (Defined *d : getInputSection(entry)->symbols)
166*dfe94b16Srobert         addSym(d, entry);
1671cf9926bSpatrick     }
1681cf9926bSpatrick 
169*dfe94b16Srobert     // S_ATTR_LIVE_SUPPORT sections are live if they point _to_ a live
170*dfe94b16Srobert     // section. Process them in a second pass.
1711cf9926bSpatrick     for (ConcatInputSection *isec : inputSections) {
1721cf9926bSpatrick       // FIXME: Check if copying all S_ATTR_LIVE_SUPPORT sections into a
1731cf9926bSpatrick       // separate vector and only walking that here is faster.
1741cf9926bSpatrick       if (!(isec->getFlags() & S_ATTR_LIVE_SUPPORT) || isec->live)
1751cf9926bSpatrick         continue;
1761cf9926bSpatrick 
1771cf9926bSpatrick       for (const Reloc &r : isec->relocs) {
178*dfe94b16Srobert         if (auto *s = r.referent.dyn_cast<Symbol *>()) {
179*dfe94b16Srobert           if (s->isLive()) {
180*dfe94b16Srobert             InputSection *referentIsec = nullptr;
181*dfe94b16Srobert             if (auto *d = dyn_cast<Defined>(s))
182*dfe94b16Srobert               referentIsec = d->isec;
183*dfe94b16Srobert             enqueue(isec, 0, makeEntry(referentIsec, nullptr));
184*dfe94b16Srobert           }
185*dfe94b16Srobert         } else {
186*dfe94b16Srobert           auto *referentIsec = r.referent.get<InputSection *>();
187*dfe94b16Srobert           if (referentIsec->isLive(r.addend))
188*dfe94b16Srobert             enqueue(isec, 0, makeEntry(referentIsec, nullptr));
189*dfe94b16Srobert         }
1901cf9926bSpatrick       }
1911cf9926bSpatrick     }
1921cf9926bSpatrick 
1931cf9926bSpatrick     // S_ATTR_LIVE_SUPPORT could have marked additional sections live,
1941cf9926bSpatrick     // which in turn could mark additional S_ATTR_LIVE_SUPPORT sections live.
1951cf9926bSpatrick     // Iterate. In practice, the second iteration won't mark additional
1961cf9926bSpatrick     // S_ATTR_LIVE_SUPPORT sections live.
1971cf9926bSpatrick   } while (!worklist.empty());
1981cf9926bSpatrick }
1991cf9926bSpatrick 
200*dfe94b16Srobert // Set live bit on for each reachable chunk. Unmarked (unreachable)
201*dfe94b16Srobert // InputSections will be ignored by Writer, so they will be excluded
202*dfe94b16Srobert // from the final output.
markLive()203*dfe94b16Srobert void markLive() {
204*dfe94b16Srobert   TimeTraceScope timeScope("markLive");
205*dfe94b16Srobert   MarkLive *marker;
206*dfe94b16Srobert   if (config->whyLive.empty())
207*dfe94b16Srobert     marker = make<MarkLiveImpl<false>>();
208*dfe94b16Srobert   else
209*dfe94b16Srobert     marker = make<MarkLiveImpl<true>>();
210*dfe94b16Srobert   // Add GC roots.
211*dfe94b16Srobert   if (config->entry)
212*dfe94b16Srobert     marker->addSym(config->entry);
213*dfe94b16Srobert   for (Symbol *sym : symtab->getSymbols()) {
214*dfe94b16Srobert     if (auto *defined = dyn_cast<Defined>(sym)) {
215*dfe94b16Srobert       // -exported_symbol(s_list)
216*dfe94b16Srobert       if (!config->exportedSymbols.empty() &&
217*dfe94b16Srobert           config->exportedSymbols.match(defined->getName())) {
218*dfe94b16Srobert         // NOTE: Even though exporting private externs is an ill-defined
219*dfe94b16Srobert         // operation, we are purposely not checking for privateExtern in
220*dfe94b16Srobert         // order to follow ld64's behavior of treating all exported private
221*dfe94b16Srobert         // extern symbols as live, irrespective of whether they are autohide.
222*dfe94b16Srobert         marker->addSym(defined);
223*dfe94b16Srobert         continue;
224*dfe94b16Srobert       }
225*dfe94b16Srobert 
226*dfe94b16Srobert       // public symbols explicitly marked .no_dead_strip
227*dfe94b16Srobert       if (defined->referencedDynamically || defined->noDeadStrip) {
228*dfe94b16Srobert         marker->addSym(defined);
229*dfe94b16Srobert         continue;
230*dfe94b16Srobert       }
231*dfe94b16Srobert 
232*dfe94b16Srobert       // FIXME: When we implement these flags, make symbols from them GC
233*dfe94b16Srobert       // roots:
234*dfe94b16Srobert       // * -reexported_symbol(s_list)
235*dfe94b16Srobert       // * -alias_list
236*dfe94b16Srobert       // * -init
237*dfe94b16Srobert 
238*dfe94b16Srobert       // In dylibs and bundles and in executables with -export_dynamic,
239*dfe94b16Srobert       // all external functions are GC roots.
240*dfe94b16Srobert       bool externsAreRoots =
241*dfe94b16Srobert           config->outputType != MH_EXECUTE || config->exportDynamic;
242*dfe94b16Srobert       if (externsAreRoots && !defined->privateExtern) {
243*dfe94b16Srobert         marker->addSym(defined);
244*dfe94b16Srobert         continue;
245*dfe94b16Srobert       }
246*dfe94b16Srobert     }
247*dfe94b16Srobert   }
248*dfe94b16Srobert   // -u symbols
249*dfe94b16Srobert   for (Symbol *sym : config->explicitUndefineds)
250*dfe94b16Srobert     marker->addSym(sym);
251*dfe94b16Srobert   // local symbols explicitly marked .no_dead_strip
252*dfe94b16Srobert   for (const InputFile *file : inputFiles)
253*dfe94b16Srobert     if (auto *objFile = dyn_cast<ObjFile>(file))
254*dfe94b16Srobert       for (Symbol *sym : objFile->symbols)
255*dfe94b16Srobert         if (auto *defined = dyn_cast_or_null<Defined>(sym))
256*dfe94b16Srobert           if (!defined->isExternal() && defined->noDeadStrip)
257*dfe94b16Srobert             marker->addSym(defined);
258*dfe94b16Srobert   if (auto *stubBinder =
259*dfe94b16Srobert           dyn_cast_or_null<DylibSymbol>(symtab->find("dyld_stub_binder")))
260*dfe94b16Srobert     marker->addSym(stubBinder);
261*dfe94b16Srobert   for (ConcatInputSection *isec : inputSections) {
262*dfe94b16Srobert     // Sections marked no_dead_strip
263*dfe94b16Srobert     if (isec->getFlags() & S_ATTR_NO_DEAD_STRIP) {
264*dfe94b16Srobert       marker->enqueue(isec, 0);
265*dfe94b16Srobert       continue;
266*dfe94b16Srobert     }
267*dfe94b16Srobert 
268*dfe94b16Srobert     // mod_init_funcs, mod_term_funcs sections
269*dfe94b16Srobert     if (sectionType(isec->getFlags()) == S_MOD_INIT_FUNC_POINTERS ||
270*dfe94b16Srobert         sectionType(isec->getFlags()) == S_MOD_TERM_FUNC_POINTERS) {
271*dfe94b16Srobert       assert(!config->emitInitOffsets ||
272*dfe94b16Srobert              sectionType(isec->getFlags()) != S_MOD_INIT_FUNC_POINTERS);
273*dfe94b16Srobert       marker->enqueue(isec, 0);
274*dfe94b16Srobert       continue;
275*dfe94b16Srobert     }
276*dfe94b16Srobert   }
277*dfe94b16Srobert 
278*dfe94b16Srobert   for (ConcatInputSection *isec : in.initOffsets->inputs())
279*dfe94b16Srobert     marker->enqueue(isec, 0);
280*dfe94b16Srobert 
281*dfe94b16Srobert   marker->markTransitively();
282*dfe94b16Srobert }
283*dfe94b16Srobert 
284*dfe94b16Srobert } // namespace lld::macho
285