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