Coverage Report

Created: 2018-06-18 20:01

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