1//===- lib/ReaderWriter/MachO/CompactUnwindPass.cpp -------------*- C++ -*-===//
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/// \file A pass to convert MachO's __compact_unwind sections into the final
10/// __unwind_info format used during runtime. See
11/// mach-o/compact_unwind_encoding.h for more details on the formats involved.
12///
13//===----------------------------------------------------------------------===//
14
15#include "ArchHandler.h"
16#include "File.h"
17#include "MachONormalizedFileBinaryUtils.h"
18#include "MachOPasses.h"
19#include "lld/Common/LLVM.h"
20#include "lld/Core/DefinedAtom.h"
21#include "lld/Core/File.h"
22#include "lld/Core/Reference.h"
23#include "lld/Core/Simple.h"
24#include "llvm/ADT/DenseMap.h"
25#include "llvm/Support/Debug.h"
26#include "llvm/Support/Format.h"
27
28#define DEBUG_TYPE "macho-compact-unwind"
29
30namespace lld {
31namespace mach_o {
32
33namespace {
34struct CompactUnwindEntry {
35  const Atom *rangeStart;
36  const Atom *personalityFunction;
37  const Atom *lsdaLocation;
38  const Atom *ehFrame;
39
40  uint32_t rangeLength;
41
42  // There are 3 types of compact unwind entry, distinguished by the encoding
43  // value: 0 indicates a function with no unwind info;
44  // _archHandler.dwarfCompactUnwindType() indicates that the entry defers to
45  // __eh_frame, and that the ehFrame entry will be valid; any other value is a
46  // real compact unwind entry -- personalityFunction will be set and
47  // lsdaLocation may be.
48  uint32_t encoding;
49
50  CompactUnwindEntry(const DefinedAtom *function)
51      : rangeStart(function), personalityFunction(nullptr),
52        lsdaLocation(nullptr), ehFrame(nullptr), rangeLength(function->size()),
53        encoding(0) {}
54
55  CompactUnwindEntry()
56      : rangeStart(nullptr), personalityFunction(nullptr),
57        lsdaLocation(nullptr), ehFrame(nullptr), rangeLength(0), encoding(0) {}
58};
59
60struct UnwindInfoPage {
61  ArrayRef<CompactUnwindEntry> entries;
62};
63}
64
65class UnwindInfoAtom : public SimpleDefinedAtom {
66public:
67  UnwindInfoAtom(ArchHandler &archHandler, const File &file, bool isBig,
68                 std::vector<const Atom *> &personalities,
69                 std::vector<uint32_t> &commonEncodings,
70                 std::vector<UnwindInfoPage> &pages, uint32_t numLSDAs)
71      : SimpleDefinedAtom(file), _archHandler(archHandler),
72        _commonEncodingsOffset(7 * sizeof(uint32_t)),
73        _personalityArrayOffset(_commonEncodingsOffset +
74                                commonEncodings.size() * sizeof(uint32_t)),
75        _topLevelIndexOffset(_personalityArrayOffset +
76                             personalities.size() * sizeof(uint32_t)),
77        _lsdaIndexOffset(_topLevelIndexOffset +
78                         3 * (pages.size() + 1) * sizeof(uint32_t)),
79        _firstPageOffset(_lsdaIndexOffset + 2 * numLSDAs * sizeof(uint32_t)),
80        _isBig(isBig) {
81
82    addHeader(commonEncodings.size(), personalities.size(), pages.size());
83    addCommonEncodings(commonEncodings);
84    addPersonalityFunctions(personalities);
85    addTopLevelIndexes(pages);
86    addLSDAIndexes(pages, numLSDAs);
87    addSecondLevelPages(pages);
88  }
89
90  ~UnwindInfoAtom() override = default;
91
92  ContentType contentType() const override {
93    return DefinedAtom::typeProcessedUnwindInfo;
94  }
95
96  Alignment alignment() const override { return 4; }
97
98  uint64_t size() const override { return _contents.size(); }
99
100  ContentPermissions permissions() const override {
101    return DefinedAtom::permR__;
102  }
103
104  ArrayRef<uint8_t> rawContent() const override { return _contents; }
105
106  void addHeader(uint32_t numCommon, uint32_t numPersonalities,
107                 uint32_t numPages) {
108    using normalized::write32;
109
110    uint32_t headerSize = 7 * sizeof(uint32_t);
111    _contents.resize(headerSize);
112
113    uint8_t *headerEntries = _contents.data();
114    // version
115    write32(headerEntries, 1, _isBig);
116    // commonEncodingsArraySectionOffset
117    write32(headerEntries + sizeof(uint32_t), _commonEncodingsOffset, _isBig);
118    // commonEncodingsArrayCount
119    write32(headerEntries + 2 * sizeof(uint32_t), numCommon, _isBig);
120    // personalityArraySectionOffset
121    write32(headerEntries + 3 * sizeof(uint32_t), _personalityArrayOffset,
122            _isBig);
123    // personalityArrayCount
124    write32(headerEntries + 4 * sizeof(uint32_t), numPersonalities, _isBig);
125    // indexSectionOffset
126    write32(headerEntries + 5 * sizeof(uint32_t), _topLevelIndexOffset, _isBig);
127    // indexCount
128    write32(headerEntries + 6 * sizeof(uint32_t), numPages + 1, _isBig);
129  }
130
131  /// Add the list of common encodings to the section; this is simply an array
132  /// of uint32_t compact values. Size has already been specified in the header.
133  void addCommonEncodings(std::vector<uint32_t> &commonEncodings) {
134    using normalized::write32;
135
136    _contents.resize(_commonEncodingsOffset +
137                     commonEncodings.size() * sizeof(uint32_t));
138    uint8_t *commonEncodingsArea =
139        reinterpret_cast<uint8_t *>(_contents.data() + _commonEncodingsOffset);
140
141    for (uint32_t encoding : commonEncodings) {
142      write32(commonEncodingsArea, encoding, _isBig);
143      commonEncodingsArea += sizeof(uint32_t);
144    }
145  }
146
147  void addPersonalityFunctions(std::vector<const Atom *> personalities) {
148    _contents.resize(_personalityArrayOffset +
149                     personalities.size() * sizeof(uint32_t));
150
151    for (unsigned i = 0; i < personalities.size(); ++i)
152      addImageReferenceIndirect(_personalityArrayOffset + i * sizeof(uint32_t),
153                                personalities[i]);
154  }
155
156  void addTopLevelIndexes(std::vector<UnwindInfoPage> &pages) {
157    using normalized::write32;
158
159    uint32_t numIndexes = pages.size() + 1;
160    _contents.resize(_topLevelIndexOffset + numIndexes * 3 * sizeof(uint32_t));
161
162    uint32_t pageLoc = _firstPageOffset;
163
164    // The most difficult job here is calculating the LSDAs; everything else
165    // follows fairly naturally, but we can't state where the first
166    uint8_t *indexData = &_contents[_topLevelIndexOffset];
167    uint32_t numLSDAs = 0;
168    for (unsigned i = 0; i < pages.size(); ++i) {
169      // functionOffset
170      addImageReference(_topLevelIndexOffset + 3 * i * sizeof(uint32_t),
171                        pages[i].entries[0].rangeStart);
172      // secondLevelPagesSectionOffset
173      write32(indexData + (3 * i + 1) * sizeof(uint32_t), pageLoc, _isBig);
174      write32(indexData + (3 * i + 2) * sizeof(uint32_t),
175              _lsdaIndexOffset + numLSDAs * 2 * sizeof(uint32_t), _isBig);
176
177      for (auto &entry : pages[i].entries)
178        if (entry.lsdaLocation)
179          ++numLSDAs;
180    }
181
182    // Finally, write out the final sentinel index
183    auto &finalEntry = pages[pages.size() - 1].entries.back();
184    addImageReference(_topLevelIndexOffset +
185                          3 * pages.size() * sizeof(uint32_t),
186                      finalEntry.rangeStart, finalEntry.rangeLength);
187    // secondLevelPagesSectionOffset => 0
188    write32(indexData + (3 * pages.size() + 2) * sizeof(uint32_t),
189            _lsdaIndexOffset + numLSDAs * 2 * sizeof(uint32_t), _isBig);
190  }
191
192  void addLSDAIndexes(std::vector<UnwindInfoPage> &pages, uint32_t numLSDAs) {
193    _contents.resize(_lsdaIndexOffset + numLSDAs * 2 * sizeof(uint32_t));
194
195    uint32_t curOffset = _lsdaIndexOffset;
196    for (auto &page : pages) {
197      for (auto &entry : page.entries) {
198        if (!entry.lsdaLocation)
199          continue;
200
201        addImageReference(curOffset, entry.rangeStart);
202        addImageReference(curOffset + sizeof(uint32_t), entry.lsdaLocation);
203        curOffset += 2 * sizeof(uint32_t);
204      }
205    }
206  }
207
208  void addSecondLevelPages(std::vector<UnwindInfoPage> &pages) {
209    for (auto &page : pages) {
210      addRegularSecondLevelPage(page);
211    }
212  }
213
214  void addRegularSecondLevelPage(const UnwindInfoPage &page) {
215    uint32_t curPageOffset = _contents.size();
216    const int16_t headerSize = sizeof(uint32_t) + 2 * sizeof(uint16_t);
217    uint32_t curPageSize =
218        headerSize + 2 * page.entries.size() * sizeof(uint32_t);
219    _contents.resize(curPageOffset + curPageSize);
220
221    using normalized::write32;
222    using normalized::write16;
223    // 2 => regular page
224    write32(&_contents[curPageOffset], 2, _isBig);
225    // offset of 1st entry
226    write16(&_contents[curPageOffset + 4], headerSize, _isBig);
227    write16(&_contents[curPageOffset + 6], page.entries.size(), _isBig);
228
229    uint32_t pagePos = curPageOffset + headerSize;
230    for (auto &entry : page.entries) {
231      addImageReference(pagePos, entry.rangeStart);
232
233      write32(_contents.data() + pagePos + sizeof(uint32_t), entry.encoding,
234              _isBig);
235      if ((entry.encoding & 0x0f000000U) ==
236          _archHandler.dwarfCompactUnwindType())
237        addEhFrameReference(pagePos + sizeof(uint32_t), entry.ehFrame);
238
239      pagePos += 2 * sizeof(uint32_t);
240    }
241  }
242
243  void addEhFrameReference(uint32_t offset, const Atom *dest,
244                           Reference::Addend addend = 0) {
245    addReference(Reference::KindNamespace::mach_o, _archHandler.kindArch(),
246                 _archHandler.unwindRefToEhFrameKind(), offset, dest, addend);
247  }
248
249  void addImageReference(uint32_t offset, const Atom *dest,
250                         Reference::Addend addend = 0) {
251    addReference(Reference::KindNamespace::mach_o, _archHandler.kindArch(),
252                 _archHandler.imageOffsetKind(), offset, dest, addend);
253  }
254
255  void addImageReferenceIndirect(uint32_t offset, const Atom *dest) {
256    addReference(Reference::KindNamespace::mach_o, _archHandler.kindArch(),
257                 _archHandler.imageOffsetKindIndirect(), offset, dest, 0);
258  }
259
260private:
261  mach_o::ArchHandler &_archHandler;
262  std::vector<uint8_t> _contents;
263  uint32_t _commonEncodingsOffset;
264  uint32_t _personalityArrayOffset;
265  uint32_t _topLevelIndexOffset;
266  uint32_t _lsdaIndexOffset;
267  uint32_t _firstPageOffset;
268  bool _isBig;
269};
270
271/// Pass for instantiating and optimizing GOT slots.
272///
273class CompactUnwindPass : public Pass {
274public:
275  CompactUnwindPass(const MachOLinkingContext &context)
276      : _ctx(context), _archHandler(_ctx.archHandler()),
277        _file(*_ctx.make_file<MachOFile>("<mach-o Compact Unwind Pass>")),
278        _isBig(MachOLinkingContext::isBigEndian(_ctx.arch())) {
279    _file.setOrdinal(_ctx.getNextOrdinalAndIncrement());
280  }
281
282private:
283  llvm::Error perform(SimpleFile &mergedFile) override {
284    LLVM_DEBUG(llvm::dbgs() << "MachO Compact Unwind pass\n");
285
286    std::map<const Atom *, CompactUnwindEntry> unwindLocs;
287    std::map<const Atom *, const Atom *> dwarfFrames;
288    std::vector<const Atom *> personalities;
289    uint32_t numLSDAs = 0;
290
291    // First collect all __compact_unwind and __eh_frame entries, addressable by
292    // the function referred to.
293    collectCompactUnwindEntries(mergedFile, unwindLocs, personalities,
294                                numLSDAs);
295
296    collectDwarfFrameEntries(mergedFile, dwarfFrames);
297
298    // Skip rest of pass if no unwind info.
299    if (unwindLocs.empty() && dwarfFrames.empty())
300      return llvm::Error::success();
301
302    // FIXME: if there are more than 4 personality functions then we need to
303    // defer to DWARF info for the ones we don't put in the list. They should
304    // also probably be sorted by frequency.
305    assert(personalities.size() <= 4);
306
307    // TODO: Find common encodings for use by compressed pages.
308    std::vector<uint32_t> commonEncodings;
309
310    // Now sort the entries by final address and fixup the compact encoding to
311    // its final form (i.e. set personality function bits & create DWARF
312    // references where needed).
313    std::vector<CompactUnwindEntry> unwindInfos = createUnwindInfoEntries(
314        mergedFile, unwindLocs, personalities, dwarfFrames);
315
316    // Remove any unused eh-frame atoms.
317    pruneUnusedEHFrames(mergedFile, unwindInfos, unwindLocs, dwarfFrames);
318
319    // Finally, we can start creating pages based on these entries.
320
321    LLVM_DEBUG(llvm::dbgs() << "  Splitting entries into pages\n");
322    // FIXME: we split the entries into pages naively: lots of 4k pages followed
323    // by a small one. ld64 tried to minimize space and align them to real 4k
324    // boundaries. That might be worth doing, or perhaps we could perform some
325    // minor balancing for expected number of lookups.
326    std::vector<UnwindInfoPage> pages;
327    auto remainingInfos = llvm::makeArrayRef(unwindInfos);
328    do {
329      pages.push_back(UnwindInfoPage());
330
331      // FIXME: we only create regular pages at the moment. These can hold up to
332      // 1021 entries according to the documentation.
333      unsigned entriesInPage = std::min(1021U, (unsigned)remainingInfos.size());
334
335      pages.back().entries = remainingInfos.slice(0, entriesInPage);
336      remainingInfos = remainingInfos.slice(entriesInPage);
337
338      LLVM_DEBUG(llvm::dbgs()
339                 << "    Page from "
340                 << pages.back().entries[0].rangeStart->name() << " to "
341                 << pages.back().entries.back().rangeStart->name() << " + "
342                 << llvm::format("0x%x",
343                                 pages.back().entries.back().rangeLength)
344                 << " has " << entriesInPage << " entries\n");
345    } while (!remainingInfos.empty());
346
347    auto *unwind = new (_file.allocator())
348        UnwindInfoAtom(_archHandler, _file, _isBig, personalities,
349                       commonEncodings, pages, numLSDAs);
350    mergedFile.addAtom(*unwind);
351
352    // Finally, remove all __compact_unwind atoms now that we've processed them.
353    mergedFile.removeDefinedAtomsIf([](const DefinedAtom *atom) {
354      return atom->contentType() == DefinedAtom::typeCompactUnwindInfo;
355    });
356
357    return llvm::Error::success();
358  }
359
360  void collectCompactUnwindEntries(
361      const SimpleFile &mergedFile,
362      std::map<const Atom *, CompactUnwindEntry> &unwindLocs,
363      std::vector<const Atom *> &personalities, uint32_t &numLSDAs) {
364    LLVM_DEBUG(llvm::dbgs() << "  Collecting __compact_unwind entries\n");
365
366    for (const DefinedAtom *atom : mergedFile.defined()) {
367      if (atom->contentType() != DefinedAtom::typeCompactUnwindInfo)
368        continue;
369
370      auto unwindEntry = extractCompactUnwindEntry(atom);
371      unwindLocs.insert(std::make_pair(unwindEntry.rangeStart, unwindEntry));
372
373      LLVM_DEBUG(llvm::dbgs() << "    Entry for "
374                              << unwindEntry.rangeStart->name() << ", encoding="
375                              << llvm::format("0x%08x", unwindEntry.encoding));
376      if (unwindEntry.personalityFunction)
377        LLVM_DEBUG(llvm::dbgs()
378                   << ", personality="
379                   << unwindEntry.personalityFunction->name()
380                   << ", lsdaLoc=" << unwindEntry.lsdaLocation->name());
381      LLVM_DEBUG(llvm::dbgs() << '\n');
382
383      // Count number of LSDAs we see, since we need to know how big the index
384      // will be while laying out the section.
385      if (unwindEntry.lsdaLocation)
386        ++numLSDAs;
387
388      // Gather the personality functions now, so that they're in deterministic
389      // order (derived from the DefinedAtom order).
390      if (unwindEntry.personalityFunction &&
391          !llvm::count(personalities, unwindEntry.personalityFunction))
392        personalities.push_back(unwindEntry.personalityFunction);
393    }
394  }
395
396  CompactUnwindEntry extractCompactUnwindEntry(const DefinedAtom *atom) {
397    CompactUnwindEntry entry;
398
399    for (const Reference *ref : *atom) {
400      switch (ref->offsetInAtom()) {
401      case 0:
402        // FIXME: there could legitimately be functions with multiple encoding
403        // entries. However, nothing produces them at the moment.
404        assert(ref->addend() == 0 && "unexpected offset into function");
405        entry.rangeStart = ref->target();
406        break;
407      case 0x10:
408        assert(ref->addend() == 0 && "unexpected offset into personality fn");
409        entry.personalityFunction = ref->target();
410        break;
411      case 0x18:
412        assert(ref->addend() == 0 && "unexpected offset into LSDA atom");
413        entry.lsdaLocation = ref->target();
414        break;
415      }
416    }
417
418    if (atom->rawContent().size() < 4 * sizeof(uint32_t))
419      return entry;
420
421    using normalized::read32;
422    entry.rangeLength =
423        read32(atom->rawContent().data() + 2 * sizeof(uint32_t), _isBig);
424    entry.encoding =
425        read32(atom->rawContent().data() + 3 * sizeof(uint32_t), _isBig);
426    return entry;
427  }
428
429  void
430  collectDwarfFrameEntries(const SimpleFile &mergedFile,
431                           std::map<const Atom *, const Atom *> &dwarfFrames) {
432    for (const DefinedAtom *ehFrameAtom : mergedFile.defined()) {
433      if (ehFrameAtom->contentType() != DefinedAtom::typeCFI)
434        continue;
435      if (ArchHandler::isDwarfCIE(_isBig, ehFrameAtom))
436        continue;
437
438      if (const Atom *function = _archHandler.fdeTargetFunction(ehFrameAtom))
439        dwarfFrames[function] = ehFrameAtom;
440    }
441  }
442
443  /// Every atom defined in __TEXT,__text needs an entry in the final
444  /// __unwind_info section (in order). These comes from two sources:
445  ///   + Input __compact_unwind sections where possible (after adding the
446  ///      personality function offset which is only known now).
447  ///   + A synthesised reference to __eh_frame if there's no __compact_unwind
448  ///     or too many personality functions to be accommodated.
449  std::vector<CompactUnwindEntry> createUnwindInfoEntries(
450      const SimpleFile &mergedFile,
451      const std::map<const Atom *, CompactUnwindEntry> &unwindLocs,
452      const std::vector<const Atom *> &personalities,
453      const std::map<const Atom *, const Atom *> &dwarfFrames) {
454    std::vector<CompactUnwindEntry> unwindInfos;
455
456    LLVM_DEBUG(llvm::dbgs() << "  Creating __unwind_info entries\n");
457    // The final order in the __unwind_info section must be derived from the
458    // order of typeCode atoms, since that's how they'll be put into the object
459    // file eventually (yuck!).
460    for (const DefinedAtom *atom : mergedFile.defined()) {
461      if (atom->contentType() != DefinedAtom::typeCode)
462        continue;
463
464      unwindInfos.push_back(finalizeUnwindInfoEntryForAtom(
465          atom, unwindLocs, personalities, dwarfFrames));
466
467      LLVM_DEBUG(llvm::dbgs()
468                 << "    Entry for " << atom->name() << ", final encoding="
469                 << llvm::format("0x%08x", unwindInfos.back().encoding)
470                 << '\n');
471    }
472
473    return unwindInfos;
474  }
475
476  /// Remove unused EH frames.
477  ///
478  /// An EH frame is considered unused if there is a corresponding compact
479  /// unwind atom that doesn't require the EH frame.
480  void pruneUnusedEHFrames(
481                   SimpleFile &mergedFile,
482                   const std::vector<CompactUnwindEntry> &unwindInfos,
483                   const std::map<const Atom *, CompactUnwindEntry> &unwindLocs,
484                   const std::map<const Atom *, const Atom *> &dwarfFrames) {
485
486    // Worklist of all 'used' FDEs.
487    std::vector<const DefinedAtom *> usedDwarfWorklist;
488
489    // We have to check two conditions when building the worklist:
490    // (1) EH frames used by compact unwind entries.
491    for (auto &entry : unwindInfos)
492      if (entry.ehFrame)
493        usedDwarfWorklist.push_back(cast<DefinedAtom>(entry.ehFrame));
494
495    // (2) EH frames that reference functions with no corresponding compact
496    //     unwind info.
497    for (auto &entry : dwarfFrames)
498      if (!unwindLocs.count(entry.first))
499        usedDwarfWorklist.push_back(cast<DefinedAtom>(entry.second));
500
501    // Add all transitively referenced CFI atoms by processing the worklist.
502    std::set<const Atom *> usedDwarfFrames;
503    while (!usedDwarfWorklist.empty()) {
504      const DefinedAtom *cfiAtom = usedDwarfWorklist.back();
505      usedDwarfWorklist.pop_back();
506      usedDwarfFrames.insert(cfiAtom);
507      for (const auto *ref : *cfiAtom) {
508        const DefinedAtom *cfiTarget = dyn_cast<DefinedAtom>(ref->target());
509        if (cfiTarget->contentType() == DefinedAtom::typeCFI)
510          usedDwarfWorklist.push_back(cfiTarget);
511      }
512    }
513
514    // Finally, delete all unreferenced CFI atoms.
515    mergedFile.removeDefinedAtomsIf([&](const DefinedAtom *atom) {
516      if ((atom->contentType() == DefinedAtom::typeCFI) &&
517          !usedDwarfFrames.count(atom))
518        return true;
519      return false;
520    });
521  }
522
523  CompactUnwindEntry finalizeUnwindInfoEntryForAtom(
524      const DefinedAtom *function,
525      const std::map<const Atom *, CompactUnwindEntry> &unwindLocs,
526      const std::vector<const Atom *> &personalities,
527      const std::map<const Atom *, const Atom *> &dwarfFrames) {
528    auto unwindLoc = unwindLocs.find(function);
529
530    CompactUnwindEntry entry;
531    if (unwindLoc == unwindLocs.end()) {
532      // Default entry has correct encoding (0 => no unwind), but we need to
533      // synthesise the function.
534      entry.rangeStart = function;
535      entry.rangeLength = function->size();
536    } else
537      entry = unwindLoc->second;
538
539
540    // If there's no __compact_unwind entry, or it explicitly says to use
541    // __eh_frame, we need to try and fill in the correct DWARF atom.
542    if (entry.encoding == _archHandler.dwarfCompactUnwindType() ||
543        entry.encoding == 0) {
544      auto dwarfFrame = dwarfFrames.find(function);
545      if (dwarfFrame != dwarfFrames.end()) {
546        entry.encoding = _archHandler.dwarfCompactUnwindType();
547        entry.ehFrame = dwarfFrame->second;
548      }
549    }
550
551    auto personality = llvm::find(personalities, entry.personalityFunction);
552    uint32_t personalityIdx = personality == personalities.end()
553                                  ? 0
554                                  : personality - personalities.begin() + 1;
555
556    // FIXME: We should also use DWARF when there isn't enough room for the
557    // personality function in the compact encoding.
558    assert(personalityIdx < 4 && "too many personality functions");
559
560    entry.encoding |= personalityIdx << 28;
561
562    if (entry.lsdaLocation)
563      entry.encoding |= 1U << 30;
564
565    return entry;
566  }
567
568  const MachOLinkingContext &_ctx;
569  mach_o::ArchHandler &_archHandler;
570  MachOFile &_file;
571  bool _isBig;
572};
573
574void addCompactUnwindPass(PassManager &pm, const MachOLinkingContext &ctx) {
575  assert(ctx.needsCompactUnwindPass());
576  pm.add(std::make_unique<CompactUnwindPass>(ctx));
577}
578
579} // end namesapce mach_o
580} // end namesapce lld
581