Coverage Report

Created: 2018-01-17 21:32

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp --------------===//
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
///
11
/// \file Converts from in-memory normalized mach-o to in-memory Atoms.
12
///
13
///                  +------------+
14
///                  | normalized |
15
///                  +------------+
16
///                        |
17
///                        |
18
///                        v
19
///                    +-------+
20
///                    | Atoms |
21
///                    +-------+
22
23
#include "ArchHandler.h"
24
#include "Atoms.h"
25
#include "File.h"
26
#include "MachONormalizedFile.h"
27
#include "MachONormalizedFileBinaryUtils.h"
28
#include "lld/Common/LLVM.h"
29
#include "lld/Core/Error.h"
30
#include "llvm/BinaryFormat/Dwarf.h"
31
#include "llvm/BinaryFormat/MachO.h"
32
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
33
#include "llvm/Support/DataExtractor.h"
34
#include "llvm/Support/Debug.h"
35
#include "llvm/Support/Error.h"
36
#include "llvm/Support/Format.h"
37
#include "llvm/Support/LEB128.h"
38
#include "llvm/Support/raw_ostream.h"
39
40
using namespace llvm::MachO;
41
using namespace lld::mach_o::normalized;
42
43
#define DEBUG_TYPE "normalized-file-to-atoms"
44
45
namespace lld {
46
namespace mach_o {
47
48
49
namespace { // anonymous
50
51
52
#define ENTRY(seg, sect, type, atomType) \
53
  {seg, sect, type, DefinedAtom::atomType }
54
55
struct MachORelocatableSectionToAtomType {
56
  StringRef                 segmentName;
57
  StringRef                 sectionName;
58
  SectionType               sectionType;
59
  DefinedAtom::ContentType  atomType;
60
};
61
62
const MachORelocatableSectionToAtomType sectsToAtomType[] = {
63
  ENTRY("__TEXT", "__text",           S_REGULAR,          typeCode),
64
  ENTRY("__TEXT", "__text",           S_REGULAR,          typeResolver),
65
  ENTRY("__TEXT", "__cstring",        S_CSTRING_LITERALS, typeCString),
66
  ENTRY("",       "",                 S_CSTRING_LITERALS, typeCString),
67
  ENTRY("__TEXT", "__ustring",        S_REGULAR,          typeUTF16String),
68
  ENTRY("__TEXT", "__const",          S_REGULAR,          typeConstant),
69
  ENTRY("__TEXT", "__const_coal",     S_COALESCED,        typeConstant),
70
  ENTRY("__TEXT", "__eh_frame",       S_COALESCED,        typeCFI),
71
  ENTRY("__TEXT", "__eh_frame",       S_REGULAR,          typeCFI),
72
  ENTRY("__TEXT", "__literal4",       S_4BYTE_LITERALS,   typeLiteral4),
73
  ENTRY("__TEXT", "__literal8",       S_8BYTE_LITERALS,   typeLiteral8),
74
  ENTRY("__TEXT", "__literal16",      S_16BYTE_LITERALS,  typeLiteral16),
75
  ENTRY("__TEXT", "__gcc_except_tab", S_REGULAR,          typeLSDA),
76
  ENTRY("__DATA", "__data",           S_REGULAR,          typeData),
77
  ENTRY("__DATA", "__datacoal_nt",    S_COALESCED,        typeData),
78
  ENTRY("__DATA", "__const",          S_REGULAR,          typeConstData),
79
  ENTRY("__DATA", "__cfstring",       S_REGULAR,          typeCFString),
80
  ENTRY("__DATA", "__mod_init_func",  S_MOD_INIT_FUNC_POINTERS,
81
                                                          typeInitializerPtr),
82
  ENTRY("__DATA", "__mod_term_func",  S_MOD_TERM_FUNC_POINTERS,
83
                                                          typeTerminatorPtr),
84
  ENTRY("__DATA", "__got",            S_NON_LAZY_SYMBOL_POINTERS,
85
                                                          typeGOT),
86
  ENTRY("__DATA", "__bss",            S_ZEROFILL,         typeZeroFill),
87
  ENTRY("",       "",                 S_NON_LAZY_SYMBOL_POINTERS,
88
                                                          typeGOT),
89
  ENTRY("__DATA", "__interposing",    S_INTERPOSING,      typeInterposingTuples),
90
  ENTRY("__DATA", "__thread_vars",    S_THREAD_LOCAL_VARIABLES,
91
                                                          typeThunkTLV),
92
  ENTRY("__DATA", "__thread_data", S_THREAD_LOCAL_REGULAR, typeTLVInitialData),
93
  ENTRY("__DATA", "__thread_bss",     S_THREAD_LOCAL_ZEROFILL,
94
                                                        typeTLVInitialZeroFill),
95
  ENTRY("__DATA", "__objc_imageinfo", S_REGULAR,          typeObjCImageInfo),
96
  ENTRY("__DATA", "__objc_catlist",   S_REGULAR,          typeObjC2CategoryList),
97
  ENTRY("",       "",                 S_INTERPOSING,      typeInterposingTuples),
98
  ENTRY("__LD",   "__compact_unwind", S_REGULAR,
99
                                                         typeCompactUnwindInfo),
100
  ENTRY("",       "",                 S_REGULAR,          typeUnknown)
101
};
102
#undef ENTRY
103
104
105
/// Figures out ContentType of a mach-o section.
106
DefinedAtom::ContentType atomTypeFromSection(const Section &section,
107
142
                                             bool &customSectionName) {
108
142
  // First look for match of name and type. Empty names in table are wildcards.
109
142
  customSectionName = false;
110
142
  for (const MachORelocatableSectionToAtomType *p = sectsToAtomType ;
111
1.21k
                                 p->atomType != DefinedAtom::typeUnknown; 
++p1.07k
) {
112
1.21k
    if (p->sectionType != section.type)
113
743
      continue;
114
470
    if (!p->segmentName.equals(section.segmentName) && 
!p->segmentName.empty()273
)
115
270
      continue;
116
200
    if (!p->sectionName.equals(section.sectionName) && 
!p->sectionName.empty()65
)
117
62
      continue;
118
138
    customSectionName = p->segmentName.empty() && 
p->sectionName.empty()3
;
119
138
    return p->atomType;
120
138
  }
121
142
  // Look for code denoted by section attributes
122
142
  
if (4
section.attributes & S_ATTR_PURE_INSTRUCTIONS4
)
123
0
    return DefinedAtom::typeCode;
124
4
125
4
  return DefinedAtom::typeUnknown;
126
4
}
127
128
enum AtomizeModel {
129
  atomizeAtSymbols,
130
  atomizeFixedSize,
131
  atomizePointerSize,
132
  atomizeUTF8,
133
  atomizeUTF16,
134
  atomizeCFI,
135
  atomizeCU,
136
  atomizeCFString
137
};
138
139
/// Returns info on how to atomize a section of the specified ContentType.
140
void sectionParseInfo(DefinedAtom::ContentType atomType,
141
                      unsigned int &sizeMultiple,
142
                      DefinedAtom::Scope &scope,
143
                      DefinedAtom::Merge &merge,
144
142
                      AtomizeModel &atomizeModel) {
145
142
  struct ParseInfo {
146
142
    DefinedAtom::ContentType  atomType;
147
142
    unsigned int              sizeMultiple;
148
142
    DefinedAtom::Scope        scope;
149
142
    DefinedAtom::Merge        merge;
150
142
    AtomizeModel              atomizeModel;
151
142
  };
152
142
153
142
  #define ENTRY(type, size, scope, merge, model) \
154
2.55k
    {DefinedAtom::type, size, DefinedAtom::scope, DefinedAtom::merge, model }
155
142
156
142
  static const ParseInfo parseInfo[] = {
157
142
    ENTRY(typeCode,              1, scopeGlobal,          mergeNo,
158
142
                                                            atomizeAtSymbols),
159
142
    ENTRY(typeData,              1, scopeGlobal,          mergeNo,
160
142
                                                            atomizeAtSymbols),
161
142
    ENTRY(typeConstData,         1, scopeGlobal,          mergeNo,
162
142
                                                            atomizeAtSymbols),
163
142
    ENTRY(typeZeroFill,          1, scopeGlobal,          mergeNo,
164
142
                                                            atomizeAtSymbols),
165
142
    ENTRY(typeConstant,          1, scopeGlobal,          mergeNo,
166
142
                                                            atomizeAtSymbols),
167
142
    ENTRY(typeCString,           1, scopeLinkageUnit,     mergeByContent,
168
142
                                                            atomizeUTF8),
169
142
    ENTRY(typeUTF16String,       1, scopeLinkageUnit,     mergeByContent,
170
142
                                                            atomizeUTF16),
171
142
    ENTRY(typeCFI,               4, scopeTranslationUnit, mergeNo,
172
142
                                                            atomizeCFI),
173
142
    ENTRY(typeLiteral4,          4, scopeLinkageUnit,     mergeByContent,
174
142
                                                            atomizeFixedSize),
175
142
    ENTRY(typeLiteral8,          8, scopeLinkageUnit,     mergeByContent,
176
142
                                                            atomizeFixedSize),
177
142
    ENTRY(typeLiteral16,        16, scopeLinkageUnit,     mergeByContent,
178
142
                                                            atomizeFixedSize),
179
142
    ENTRY(typeCFString,          4, scopeLinkageUnit,     mergeByContent,
180
142
                                                            atomizeCFString),
181
142
    ENTRY(typeInitializerPtr,    4, scopeTranslationUnit, mergeNo,
182
142
                                                            atomizePointerSize),
183
142
    ENTRY(typeTerminatorPtr,     4, scopeTranslationUnit, mergeNo,
184
142
                                                            atomizePointerSize),
185
142
    ENTRY(typeCompactUnwindInfo, 4, scopeTranslationUnit, mergeNo,
186
142
                                                            atomizeCU),
187
142
    ENTRY(typeGOT,               4, scopeLinkageUnit,     mergeByContent,
188
142
                                                            atomizePointerSize),
189
142
    ENTRY(typeObjC2CategoryList, 4, scopeTranslationUnit, mergeByContent,
190
142
                                                            atomizePointerSize),
191
142
    ENTRY(typeUnknown,           1, scopeGlobal,          mergeNo,
192
142
                                                            atomizeAtSymbols)
193
142
  };
194
142
  #undef ENTRY
195
142
  const int tableLen = sizeof(parseInfo) / sizeof(ParseInfo);
196
755
  for (int i=0; i < tableLen; 
++i613
) {
197
745
    if (parseInfo[i].atomType == atomType) {
198
132
      sizeMultiple = parseInfo[i].sizeMultiple;
199
132
      scope        = parseInfo[i].scope;
200
132
      merge        = parseInfo[i].merge;
201
132
      atomizeModel = parseInfo[i].atomizeModel;
202
132
      return;
203
132
    }
204
745
  }
205
142
206
142
  // Unknown type is atomized by symbols.
207
142
  sizeMultiple = 1;
208
10
  scope = DefinedAtom::scopeGlobal;
209
10
  merge = DefinedAtom::mergeNo;
210
10
  atomizeModel = atomizeAtSymbols;
211
10
}
212
213
214
156
Atom::Scope atomScope(uint8_t scope) {
215
156
  switch (scope) {
216
156
  case N_EXT:
217
102
    return Atom::scopeGlobal;
218
156
  case N_PEXT:
219
7
  case N_PEXT | N_EXT:
220
7
    return Atom::scopeLinkageUnit;
221
47
  case 0:
222
47
    return Atom::scopeTranslationUnit;
223
0
  }
224
0
  llvm_unreachable("unknown scope value!");
225
0
}
226
227
void appendSymbolsInSection(const std::vector<Symbol> &inSymbols,
228
                            uint32_t sectionIndex,
229
212
                            SmallVector<const Symbol *, 64> &outSyms) {
230
297
  for (const Symbol &sym : inSymbols) {
231
297
    // Only look at definition symbols.
232
297
    if ((sym.type & N_TYPE) != N_SECT)
233
0
      continue;
234
297
    if (sym.sect != sectionIndex)
235
145
      continue;
236
152
    outSyms.push_back(&sym);
237
152
  }
238
212
}
239
240
void atomFromSymbol(DefinedAtom::ContentType atomType, const Section &section,
241
                    MachOFile &file, uint64_t symbolAddr, StringRef symbolName,
242
                    uint16_t symbolDescFlags, Atom::Scope symbolScope,
243
155
                    uint64_t nextSymbolAddr, bool scatterable, bool copyRefs) {
244
155
  // Mach-O symbol table does have size in it. Instead the size is the
245
155
  // difference between this and the next symbol.
246
155
  uint64_t size = nextSymbolAddr - symbolAddr;
247
155
  uint64_t offset = symbolAddr - section.address;
248
155
  bool noDeadStrip = (symbolDescFlags & N_NO_DEAD_STRIP) || 
!scatterable148
;
249
155
  if (isZeroFillSection(section.type)) {
250
1
    file.addZeroFillDefinedAtom(symbolName, symbolScope, offset, size,
251
1
                                noDeadStrip, copyRefs, &section);
252
154
  } else {
253
154
    DefinedAtom::Merge merge = (symbolDescFlags & N_WEAK_DEF)
254
154
                              ? 
DefinedAtom::mergeAsWeak1
:
DefinedAtom::mergeNo153
;
255
154
    bool thumb = (symbolDescFlags & N_ARM_THUMB_DEF);
256
154
    if (atomType == DefinedAtom::typeUnknown) {
257
6
      // Mach-O needs a segment and section name.  Concatentate those two
258
6
      // with a / separator (e.g. "seg/sect") to fit into the lld model
259
6
      // of just a section name.
260
6
      std::string segSectName = section.segmentName.str()
261
6
                                + "/" + section.sectionName.str();
262
6
      file.addDefinedAtomInCustomSection(symbolName, symbolScope, atomType,
263
6
                                         merge, thumb, noDeadStrip, offset,
264
6
                                         size, segSectName, true, &section);
265
148
    } else {
266
148
      if ((atomType == lld::DefinedAtom::typeCode) &&
267
148
          
(symbolDescFlags & N_SYMBOL_RESOLVER)114
) {
268
0
        atomType = lld::DefinedAtom::typeResolver;
269
0
      }
270
148
      file.addDefinedAtom(symbolName, symbolScope, atomType, merge,
271
148
                          offset, size, thumb, noDeadStrip, copyRefs, &section);
272
148
    }
273
154
  }
274
155
}
275
276
llvm::Error processSymboledSection(DefinedAtom::ContentType atomType,
277
                                   const Section &section,
278
                                   const NormalizedFile &normalizedFile,
279
                                   MachOFile &file, bool scatterable,
280
106
                                   bool copyRefs) {
281
106
  // Find section's index.
282
106
  uint32_t sectIndex = 1;
283
149
  for (auto &sect : normalizedFile.sections) {
284
149
    if (&sect == &section)
285
106
      break;
286
43
    ++sectIndex;
287
43
  }
288
106
289
106
  // Find all symbols in this section.
290
106
  SmallVector<const Symbol *, 64> symbols;
291
106
  appendSymbolsInSection(normalizedFile.globalSymbols, sectIndex, symbols);
292
106
  appendSymbolsInSection(normalizedFile.localSymbols,  sectIndex, symbols);
293
106
294
106
  // Sort symbols.
295
106
  std::sort(symbols.begin(), symbols.end(),
296
106
            [](const Symbol *lhs, const Symbol *rhs) -> bool {
297
64
              if (lhs == rhs)
298
0
                return false;
299
64
              // First by address.
300
64
              uint64_t lhsAddr = lhs->value;
301
64
              uint64_t rhsAddr = rhs->value;
302
64
              if (lhsAddr != rhsAddr)
303
60
                return lhsAddr < rhsAddr;
304
4
               // If same address, one is an alias so sort by scope.
305
4
              Atom::Scope lScope = atomScope(lhs->scope);
306
4
              Atom::Scope rScope = atomScope(rhs->scope);
307
4
              if (lScope != rScope)
308
3
                return lScope < rScope;
309
1
              // If same address and scope, see if one might be better as
310
1
              // the alias.
311
1
              bool lPrivate = (lhs->name.front() == 'l');
312
1
              bool rPrivate = (rhs->name.front() == 'l');
313
1
              if (lPrivate != rPrivate)
314
1
                return lPrivate;
315
0
              // If same address and scope, sort by name.
316
0
              return lhs->name < rhs->name;
317
0
            });
318
106
319
106
  // Debug logging of symbols.
320
106
  //for (const Symbol *sym : symbols)
321
106
  //  llvm::errs() << "  sym: "
322
106
  //    << llvm::format("0x%08llx ", (uint64_t)sym->value)
323
106
  //    << ", " << sym->name << "\n";
324
106
325
106
  // If section has no symbols and no content, there are no atoms.
326
106
  if (symbols.empty() && 
section.content.empty()4
)
327
0
    return llvm::Error::success();
328
106
329
106
  if (symbols.empty()) {
330
4
    // Section has no symbols, put all content in one anoymous atom.
331
4
    atomFromSymbol(atomType, section, file, section.address, StringRef(),
332
4
                  0, Atom::scopeTranslationUnit,
333
4
                  section.address + section.content.size(),
334
4
                  scatterable, copyRefs);
335
4
  }
336
102
  else if (symbols.front()->value != section.address) {
337
3
    // Section has anonymous content before first symbol.
338
3
    atomFromSymbol(atomType, section, file, section.address, StringRef(),
339
3
                   0, Atom::scopeTranslationUnit, symbols.front()->value,
340
3
                   scatterable, copyRefs);
341
3
  }
342
106
343
106
  const Symbol *lastSym = nullptr;
344
152
  for (const Symbol *sym : symbols) {
345
152
    if (lastSym != nullptr) {
346
50
      // Ignore any assembler added "ltmpNNN" symbol at start of section
347
50
      // if there is another symbol at the start.
348
50
      if ((lastSym->value != sym->value)
349
50
          || 
lastSym->value != section.address4
350
50
          || 
!lastSym->name.startswith("ltmp")4
) {
351
46
        atomFromSymbol(atomType, section, file, lastSym->value, lastSym->name,
352
46
                       lastSym->desc, atomScope(lastSym->scope), sym->value,
353
46
                       scatterable, copyRefs);
354
46
      }
355
50
    }
356
152
    lastSym = sym;
357
152
  }
358
106
  if (lastSym != nullptr) {
359
102
    atomFromSymbol(atomType, section, file, lastSym->value, lastSym->name,
360
102
                   lastSym->desc, atomScope(lastSym->scope),
361
102
                   section.address + section.content.size(),
362
102
                   scatterable, copyRefs);
363
102
  }
364
106
365
106
  // If object built without .subsections_via_symbols, add reference chain.
366
106
  if (!scatterable) {
367
7
    MachODefinedAtom *prevAtom = nullptr;
368
7
    file.eachAtomInSection(section,
369
9
                           [&](MachODefinedAtom *atom, uint64_t offset)->void {
370
9
      if (prevAtom)
371
2
        prevAtom->addReference(Reference::KindNamespace::all,
372
2
                               Reference::KindArch::all,
373
2
                               Reference::kindLayoutAfter, 0, atom, 0);
374
9
      prevAtom = atom;
375
9
    });
376
7
  }
377
106
378
106
  return llvm::Error::success();
379
106
}
380
381
llvm::Error processSection(DefinedAtom::ContentType atomType,
382
                           const Section &section,
383
                           bool customSectionName,
384
                           const NormalizedFile &normalizedFile,
385
                           MachOFile &file, bool scatterable,
386
142
                           bool copyRefs) {
387
142
  const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
388
142
  const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
389
142
390
142
  // Get info on how to atomize section.
391
142
  unsigned int       sizeMultiple;
392
142
  DefinedAtom::Scope scope;
393
142
  DefinedAtom::Merge merge;
394
142
  AtomizeModel       atomizeModel;
395
142
  sectionParseInfo(atomType, sizeMultiple, scope, merge, atomizeModel);
396
142
397
142
  // Validate section size.
398
142
  if ((section.content.size() % sizeMultiple) != 0)
399
0
    return llvm::make_error<GenericError>(Twine("Section ")
400
0
                                          + section.segmentName
401
0
                                          + "/" + section.sectionName
402
0
                                          + " has size ("
403
0
                                          + Twine(section.content.size())
404
0
                                          + ") which is not a multiple of "
405
0
                                          + Twine(sizeMultiple));
406
142
407
142
  if (atomizeModel == atomizeAtSymbols) {
408
106
    // Break section up into atoms each with a fixed size.
409
106
    return processSymboledSection(atomType, section, normalizedFile, file,
410
106
                                  scatterable, copyRefs);
411
106
  } else {
412
36
    unsigned int size;
413
95
    for (unsigned int offset = 0, e = section.content.size(); offset != e;) {
414
59
      switch (atomizeModel) {
415
59
      case atomizeFixedSize:
416
0
        // Break section up into atoms each with a fixed size.
417
0
        size = sizeMultiple;
418
0
        break;
419
59
      case atomizePointerSize:
420
6
        // Break section up into atoms each the size of a pointer.
421
6
        size = is64 ? 
85
:
41
;
422
6
        break;
423
59
      case atomizeUTF8:
424
9
        // Break section up into zero terminated c-strings.
425
9
        size = 0;
426
71
        for (unsigned int i = offset; i < e; 
++i62
) {
427
71
          if (section.content[i] == 0) {
428
9
            size = i + 1 - offset;
429
9
            break;
430
9
          }
431
71
        }
432
9
        break;
433
59
      case atomizeUTF16:
434
0
        // Break section up into zero terminated UTF16 strings.
435
0
        size = 0;
436
0
        for (unsigned int i = offset; i < e; i += 2) {
437
0
          if ((section.content[i] == 0) && (section.content[i + 1] == 0)) {
438
0
            size = i + 2 - offset;
439
0
            break;
440
0
          }
441
0
        }
442
0
        break;
443
59
      case atomizeCFI:
444
28
        // Break section up into dwarf unwind CFIs (FDE or CIE).
445
28
        size = read32(&section.content[offset], isBig) + 4;
446
28
        if (offset+size > section.content.size()) {
447
0
          return llvm::make_error<GenericError>(Twine("Section ")
448
0
                                                + section.segmentName
449
0
                                                + "/" + section.sectionName
450
0
                                                + " is malformed.  Size of CFI "
451
0
                                                "starting at offset ("
452
0
                                                + Twine(offset)
453
0
                                                + ") is past end of section.");
454
0
        }
455
28
        break;
456
28
      case atomizeCU:
457
14
        // Break section up into compact unwind entries.
458
14
        size = is64 ? 32 : 
200
;
459
14
        break;
460
28
      case atomizeCFString:
461
2
        // Break section up into NS/CFString objects.
462
2
        size = is64 ? 32 : 
160
;
463
2
        break;
464
28
      case atomizeAtSymbols:
465
0
        break;
466
59
      }
467
59
      if (size == 0) {
468
0
        return llvm::make_error<GenericError>(Twine("Section ")
469
0
                                              + section.segmentName
470
0
                                              + "/" + section.sectionName
471
0
                                              + " is malformed.  The last atom "
472
0
                                              "is not zero terminated.");
473
0
      }
474
59
      if (customSectionName) {
475
1
        // Mach-O needs a segment and section name.  Concatentate those two
476
1
        // with a / separator (e.g. "seg/sect") to fit into the lld model
477
1
        // of just a section name.
478
1
        std::string segSectName = section.segmentName.str()
479
1
                                  + "/" + section.sectionName.str();
480
1
        file.addDefinedAtomInCustomSection(StringRef(), scope, atomType,
481
1
                                           merge, false, false, offset,
482
1
                                           size, segSectName, true, &section);
483
58
      } else {
484
58
        file.addDefinedAtom(StringRef(), scope, atomType, merge, offset, size,
485
58
                            false, false, copyRefs, &section);
486
58
      }
487
59
      offset += size;
488
59
    }
489
36
  }
490
142
  
return llvm::Error::success()36
;
491
142
}
492
493
const Section* findSectionCoveringAddress(const NormalizedFile &normalizedFile,
494
133
                                          uint64_t address) {
495
231
  for (const Section &s : normalizedFile.sections) {
496
231
    uint64_t sAddr = s.address;
497
231
    if ((sAddr <= address) && (address < sAddr+s.content.size())) {
498
133
      return &s;
499
133
    }
500
231
  }
501
133
  
return nullptr0
;
502
133
}
503
504
const MachODefinedAtom *
505
findAtomCoveringAddress(const NormalizedFile &normalizedFile, MachOFile &file,
506
30
                        uint64_t addr, Reference::Addend &addend) {
507
30
  const Section *sect = nullptr;
508
30
  sect = findSectionCoveringAddress(normalizedFile, addr);
509
30
  if (!sect)
510
0
    return nullptr;
511
30
512
30
  uint32_t offsetInTarget;
513
30
  uint64_t offsetInSect = addr - sect->address;
514
30
  auto atom =
515
30
      file.findAtomCoveringAddress(*sect, offsetInSect, &offsetInTarget);
516
30
  addend = offsetInTarget;
517
30
  return atom;
518
30
}
519
520
// Walks all relocations for a section in a normalized .o file and
521
// creates corresponding lld::Reference objects.
522
llvm::Error convertRelocs(const Section &section,
523
                          const NormalizedFile &normalizedFile,
524
                          bool scatterable,
525
                          MachOFile &file,
526
145
                          ArchHandler &handler) {
527
145
  // Utility function for ArchHandler to find atom by its address.
528
145
  auto atomByAddr = [&] (uint32_t sectIndex, uint64_t addr,
529
145
                         const lld::Atom **atom, Reference::Addend *addend)
530
157
                         -> llvm::Error {
531
157
    if (sectIndex > normalizedFile.sections.size())
532
0
      return llvm::make_error<GenericError>(Twine("out of range section "
533
0
                                     "index (") + Twine(sectIndex) + ")");
534
157
    const Section *sect = nullptr;
535
157
    if (sectIndex == 0) {
536
93
      sect = findSectionCoveringAddress(normalizedFile, addr);
537
93
      if (!sect)
538
0
        return llvm::make_error<GenericError>(Twine("address (" + Twine(addr)
539
0
                                       + ") is not in any section"));
540
64
    } else {
541
64
      sect = &normalizedFile.sections[sectIndex-1];
542
64
    }
543
157
    uint32_t offsetInTarget;
544
157
    uint64_t offsetInSect = addr - sect->address;
545
157
    *atom = file.findAtomCoveringAddress(*sect, offsetInSect, &offsetInTarget);
546
157
    *addend = offsetInTarget;
547
157
    return llvm::Error::success();
548
157
  };
549
145
550
145
  // Utility function for ArchHandler to find atom by its symbol index.
551
145
  auto atomBySymbol = [&] (uint32_t symbolIndex, const lld::Atom **result)
552
148
                           -> llvm::Error {
553
148
    // Find symbol from index.
554
148
    const Symbol *sym = nullptr;
555
148
    uint32_t numStabs  = normalizedFile.stabsSymbols.size();
556
148
    uint32_t numLocal  = normalizedFile.localSymbols.size();
557
148
    uint32_t numGlobal = normalizedFile.globalSymbols.size();
558
148
    uint32_t numUndef  = normalizedFile.undefinedSymbols.size();
559
148
    assert(symbolIndex >= numStabs && "Searched for stab via atomBySymbol?");
560
148
    if (symbolIndex < numStabs+numLocal) {
561
50
      sym = &normalizedFile.localSymbols[symbolIndex-numStabs];
562
98
    } else if (symbolIndex < numStabs+numLocal+numGlobal) {
563
14
      sym = &normalizedFile.globalSymbols[symbolIndex-numStabs-numLocal];
564
84
    } else if (symbolIndex < numStabs+numLocal+numGlobal+numUndef) {
565
84
      sym = &normalizedFile.undefinedSymbols[symbolIndex-numStabs-numLocal-
566
84
                                             numGlobal];
567
84
    } else {
568
0
      return llvm::make_error<GenericError>(Twine("symbol index (")
569
0
                                     + Twine(symbolIndex) + ") out of range");
570
0
    }
571
148
572
148
    // Find atom from symbol.
573
148
    if ((sym->type & N_TYPE) == N_SECT) {
574
64
      if (sym->sect > normalizedFile.sections.size())
575
0
        return llvm::make_error<GenericError>(Twine("symbol section index (")
576
0
                                        + Twine(sym->sect) + ") out of range ");
577
64
      const Section &symSection = normalizedFile.sections[sym->sect-1];
578
64
      uint64_t targetOffsetInSect = sym->value - symSection.address;
579
64
      MachODefinedAtom *target = file.findAtomCoveringAddress(symSection,
580
64
                                                            targetOffsetInSect);
581
64
      if (target) {
582
64
        *result = target;
583
64
        return llvm::Error::success();
584
64
      }
585
0
      return llvm::make_error<GenericError>("no atom found for defined symbol");
586
84
    } else if ((sym->type & N_TYPE) == N_UNDF) {
587
84
      const lld::Atom *target = file.findUndefAtom(sym->name);
588
84
      if (target) {
589
84
        *result = target;
590
84
        return llvm::Error::success();
591
84
      }
592
0
      return llvm::make_error<GenericError>("no undefined atom found for sym");
593
0
    } else {
594
0
      // Search undefs
595
0
      return llvm::make_error<GenericError>("no atom found for symbol");
596
0
    }
597
0
  };
598
145
599
145
  const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
600
145
  // Use old-school iterator so that paired relocations can be grouped.
601
145
  for (auto it=section.relocations.begin(), e=section.relocations.end();
602
392
                                                                it != e; 
++it247
) {
603
248
    const Relocation &reloc = *it;
604
248
    // Find atom this relocation is in.
605
248
    if (reloc.offset > section.content.size())
606
0
      return llvm::make_error<GenericError>(
607
0
                                    Twine("r_address (") + Twine(reloc.offset)
608
0
                                    + ") is larger than section size ("
609
0
                                    + Twine(section.content.size()) + ")");
610
248
    uint32_t offsetInAtom;
611
248
    MachODefinedAtom *inAtom = file.findAtomCoveringAddress(section,
612
248
                                                            reloc.offset,
613
248
                                                            &offsetInAtom);
614
248
    assert(inAtom && "r_address in range, should have found atom");
615
248
    uint64_t fixupAddress = section.address + reloc.offset;
616
248
617
248
    const lld::Atom *target = nullptr;
618
248
    Reference::Addend addend = 0;
619
248
    Reference::KindValue kind;
620
248
    if (handler.isPairedReloc(reloc)) {
621
93
      // Handle paired relocations together.
622
93
      const Relocation &reloc2 = *++it;
623
93
      auto relocErr = handler.getPairReferenceInfo(
624
93
          reloc, reloc2, inAtom, offsetInAtom, fixupAddress, isBig, scatterable,
625
93
          atomByAddr, atomBySymbol, &kind, &target, &addend);
626
93
      if (relocErr) {
627
1
        return handleErrors(std::move(relocErr),
628
1
                            [&](std::unique_ptr<GenericError> GE) {
629
1
          return llvm::make_error<GenericError>(
630
1
            Twine("bad relocation (") + GE->getMessage()
631
1
             + ") in section "
632
1
             + section.segmentName + "/" + section.sectionName
633
1
             + " (r1_address=" + Twine::utohexstr(reloc.offset)
634
1
             + ", r1_type=" + Twine(reloc.type)
635
1
             + ", r1_extern=" + Twine(reloc.isExtern)
636
1
             + ", r1_length=" + Twine((int)reloc.length)
637
1
             + ", r1_pcrel=" + Twine(reloc.pcRel)
638
1
             + (!reloc.scattered ? (Twine(", r1_symbolnum=")
639
1
                                    + Twine(reloc.symbol))
640
1
                                 : (Twine(", r1_scattered=1, r1_value=")
641
0
                                    + Twine(reloc.value)))
642
1
             + ")"
643
1
             + ", (r2_address=" + Twine::utohexstr(reloc2.offset)
644
1
             + ", r2_type=" + Twine(reloc2.type)
645
1
             + ", r2_extern=" + Twine(reloc2.isExtern)
646
1
             + ", r2_length=" + Twine((int)reloc2.length)
647
1
             + ", r2_pcrel=" + Twine(reloc2.pcRel)
648
1
             + (!reloc2.scattered ? (Twine(", r2_symbolnum=")
649
1
                                     + Twine(reloc2.symbol))
650
1
                                  : (Twine(", r2_scattered=1, r2_value=")
651
0
                                     + Twine(reloc2.value)))
652
1
             + ")" );
653
1
          });
654
1
      }
655
155
    }
656
155
    else {
657
155
      // Use ArchHandler to convert relocation record into information
658
155
      // needed to instantiate an lld::Reference object.
659
155
      auto relocErr = handler.getReferenceInfo(
660
155
          reloc, inAtom, offsetInAtom, fixupAddress, isBig, atomByAddr,
661
155
          atomBySymbol, &kind, &target, &addend);
662
155
      if (relocErr) {
663
0
        return handleErrors(std::move(relocErr),
664
0
                            [&](std::unique_ptr<GenericError> GE) {
665
0
          return llvm::make_error<GenericError>(
666
0
            Twine("bad relocation (") + GE->getMessage()
667
0
             + ") in section "
668
0
             + section.segmentName + "/" + section.sectionName
669
0
             + " (r_address=" + Twine::utohexstr(reloc.offset)
670
0
             + ", r_type=" + Twine(reloc.type)
671
0
             + ", r_extern=" + Twine(reloc.isExtern)
672
0
             + ", r_length=" + Twine((int)reloc.length)
673
0
             + ", r_pcrel=" + Twine(reloc.pcRel)
674
0
             + (!reloc.scattered ? (Twine(", r_symbolnum=") + Twine(reloc.symbol))
675
0
                                 : (Twine(", r_scattered=1, r_value=")
676
0
                                    + Twine(reloc.value)))
677
0
             + ")" );
678
0
          });
679
0
      }
680
247
    }
681
247
    // Instantiate an lld::Reference object and add to its atom.
682
247
    inAtom->addReference(Reference::KindNamespace::mach_o,
683
247
                         handler.kindArch(),
684
247
                         kind, offsetInAtom, target, addend);
685
247
  }
686
145
687
145
  
return llvm::Error::success()144
;
688
145
}
689
690
316
bool isDebugInfoSection(const Section &section) {
691
316
  if ((section.attributes & S_ATTR_DEBUG) == 0)
692
284
    return false;
693
32
  return section.segmentName.equals("__DWARF");
694
32
}
695
696
0
static const Atom* findDefinedAtomByName(MachOFile &file, Twine name) {
697
0
  std::string strName = name.str();
698
0
  for (auto *atom : file.defined())
699
0
    if (atom->name() == strName)
700
0
      return atom;
701
0
  return nullptr;
702
0
}
703
704
2
static StringRef copyDebugString(StringRef str, BumpPtrAllocator &alloc) {
705
2
  char *strCopy = alloc.Allocate<char>(str.size() + 1);
706
2
  memcpy(strCopy, str.data(), str.size());
707
2
  strCopy[str.size()] = '\0';
708
2
  return strCopy;
709
2
}
710
711
llvm::Error parseStabs(MachOFile &file,
712
                       const NormalizedFile &normalizedFile,
713
80
                       bool copyRefs) {
714
80
715
80
  if (normalizedFile.stabsSymbols.empty())
716
80
    return llvm::Error::success();
717
0
718
0
  // FIXME: Kill this off when we can move to sane yaml parsing.
719
0
  std::unique_ptr<BumpPtrAllocator> allocator;
720
0
  if (copyRefs)
721
0
    allocator = llvm::make_unique<BumpPtrAllocator>();
722
0
723
0
  enum { start, inBeginEnd } state = start;
724
0
725
0
  const Atom *currentAtom = nullptr;
726
0
  uint64_t currentAtomAddress = 0;
727
0
  StabsDebugInfo::StabsList stabsList;
728
0
  for (const auto &stabSym : normalizedFile.stabsSymbols) {
729
0
    Stab stab(nullptr, stabSym.type, stabSym.sect, stabSym.desc,
730
0
              stabSym.value, stabSym.name);
731
0
    switch (state) {
732
0
    case start:
733
0
      switch (static_cast<StabType>(stabSym.type)) {
734
0
      case N_BNSYM:
735
0
        state = inBeginEnd;
736
0
        currentAtomAddress = stabSym.value;
737
0
        Reference::Addend addend;
738
0
        currentAtom = findAtomCoveringAddress(normalizedFile, file,
739
0
                                              currentAtomAddress, addend);
740
0
        if (addend != 0)
741
0
          return llvm::make_error<GenericError>(
742
0
                   "Non-zero addend for BNSYM '" + stabSym.name + "' in " +
743
0
                   file.path());
744
0
        if (currentAtom)
745
0
          stab.atom = currentAtom;
746
0
        else {
747
0
          // FIXME: ld64 just issues a warning here - should we match that?
748
0
          return llvm::make_error<GenericError>(
749
0
                   "can't find atom for stabs BNSYM at " +
750
0
                   Twine::utohexstr(stabSym.value) + " in " + file.path());
751
0
        }
752
0
        break;
753
0
      case N_SO:
754
0
      case N_OSO:
755
0
        // Not associated with an atom, just copy.
756
0
        if (copyRefs)
757
0
          stab.str = copyDebugString(stabSym.name, *allocator);
758
0
        else
759
0
          stab.str = stabSym.name;
760
0
        break;
761
0
      case N_GSYM: {
762
0
        auto colonIdx = stabSym.name.find(':');
763
0
        if (colonIdx != StringRef::npos) {
764
0
          StringRef name = stabSym.name.substr(0, colonIdx);
765
0
          currentAtom = findDefinedAtomByName(file, "_" + name);
766
0
          stab.atom = currentAtom;
767
0
          if (copyRefs)
768
0
            stab.str = copyDebugString(stabSym.name, *allocator);
769
0
          else
770
0
            stab.str = stabSym.name;
771
0
        } else {
772
0
          currentAtom = findDefinedAtomByName(file, stabSym.name);
773
0
          stab.atom = currentAtom;
774
0
          if (copyRefs)
775
0
            stab.str = copyDebugString(stabSym.name, *allocator);
776
0
          else
777
0
            stab.str = stabSym.name;
778
0
        }
779
0
        if (stab.atom == nullptr)
780
0
          return llvm::make_error<GenericError>(
781
0
                   "can't find atom for N_GSYM stabs" + stabSym.name +
782
0
                   " in " + file.path());
783
0
        break;
784
0
      }
785
0
      case N_FUN:
786
0
        return llvm::make_error<GenericError>(
787
0
                 "old-style N_FUN stab '" + stabSym.name + "' unsupported");
788
0
      default:
789
0
        return llvm::make_error<GenericError>(
790
0
                 "unrecognized stab symbol '" + stabSym.name + "'");
791
0
      }
792
0
      break;
793
0
    case inBeginEnd:
794
0
      stab.atom = currentAtom;
795
0
      switch (static_cast<StabType>(stabSym.type)) {
796
0
      case N_ENSYM:
797
0
        state = start;
798
0
        currentAtom = nullptr;
799
0
        break;
800
0
      case N_FUN:
801
0
        // Just copy the string.
802
0
        if (copyRefs)
803
0
          stab.str = copyDebugString(stabSym.name, *allocator);
804
0
        else
805
0
          stab.str = stabSym.name;
806
0
        break;
807
0
      default:
808
0
        return llvm::make_error<GenericError>(
809
0
                 "unrecognized stab symbol '" + stabSym.name + "'");
810
0
      }
811
0
    }
812
0
    llvm::dbgs() << "Adding to stabsList: " << stab << "\n";
813
0
    stabsList.push_back(stab);
814
0
  }
815
0
816
0
  file.setDebugInfo(llvm::make_unique<StabsDebugInfo>(std::move(stabsList)));
817
0
818
0
  // FIXME: Kill this off when we fix YAML memory ownership.
819
0
  file.debugInfo()->setAllocator(std::move(allocator));
820
0
821
0
  return llvm::Error::success();
822
0
}
823
824
static llvm::DataExtractor
825
dataExtractorFromSection(const NormalizedFile &normalizedFile,
826
4
                         const Section &S) {
827
4
  const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
828
4
  const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
829
4
  StringRef SecData(reinterpret_cast<const char*>(S.content.data()),
830
4
                    S.content.size());
831
4
  return llvm::DataExtractor(SecData, !isBig, is64 ? 8 : 
40
);
832
4
}
833
834
// FIXME: Cribbed from llvm-dwp -- should share "lightweight CU DIE
835
//        inspection" code if possible.
836
static uint32_t getCUAbbrevOffset(llvm::DataExtractor abbrevData,
837
1
                                  uint64_t abbrCode) {
838
1
  uint64_t curCode;
839
1
  uint32_t offset = 0;
840
1
  while ((curCode = abbrevData.getULEB128(&offset)) != abbrCode) {
841
0
    // Tag
842
0
    abbrevData.getULEB128(&offset);
843
0
    // DW_CHILDREN
844
0
    abbrevData.getU8(&offset);
845
0
    // Attributes
846
0
    while (abbrevData.getULEB128(&offset) | abbrevData.getULEB128(&offset))
847
0
      ;
848
0
  }
849
1
  return offset;
850
1
}
851
852
// FIXME: Cribbed from llvm-dwp -- should share "lightweight CU DIE
853
//        inspection" code if possible.
854
static Expected<const char *>
855
getIndexedString(const NormalizedFile &normalizedFile,
856
                 llvm::dwarf::Form form, llvm::DataExtractor infoData,
857
2
                 uint32_t &infoOffset, const Section &stringsSection) {
858
2
  if (form == llvm::dwarf::DW_FORM_string)
859
0
   return infoData.getCStr(&infoOffset);
860
2
  if (form != llvm::dwarf::DW_FORM_strp)
861
0
    return llvm::make_error<GenericError>(
862
0
        "string field encoded without DW_FORM_strp");
863
2
  uint32_t stringOffset = infoData.getU32(&infoOffset);
864
2
  llvm::DataExtractor stringsData =
865
2
    dataExtractorFromSection(normalizedFile, stringsSection);
866
2
  return stringsData.getCStr(&stringOffset);
867
2
}
868
869
// FIXME: Cribbed from llvm-dwp -- should share "lightweight CU DIE
870
//        inspection" code if possible.
871
static llvm::Expected<TranslationUnitSource>
872
readCompUnit(const NormalizedFile &normalizedFile,
873
             const Section &info,
874
             const Section &abbrev,
875
             const Section &strings,
876
1
             StringRef path) {
877
1
  // FIXME: Cribbed from llvm-dwp -- should share "lightweight CU DIE
878
1
  //        inspection" code if possible.
879
1
  uint32_t offset = 0;
880
1
  llvm::dwarf::DwarfFormat Format = llvm::dwarf::DwarfFormat::DWARF32;
881
1
  auto infoData = dataExtractorFromSection(normalizedFile, info);
882
1
  uint32_t length = infoData.getU32(&offset);
883
1
  if (length == 0xffffffff) {
884
0
    Format = llvm::dwarf::DwarfFormat::DWARF64;
885
0
    infoData.getU64(&offset);
886
0
  }
887
1
  else if (length > 0xffffff00)
888
0
    return llvm::make_error<GenericError>("Malformed DWARF in " + path);
889
1
890
1
  uint16_t version = infoData.getU16(&offset);
891
1
892
1
  if (version < 2 || version > 4)
893
0
    return llvm::make_error<GenericError>("Unsupported DWARF version in " +
894
0
                                          path);
895
1
896
1
  infoData.getU32(&offset); // Abbrev offset (should be zero)
897
1
  uint8_t addrSize = infoData.getU8(&offset);
898
1
899
1
  uint32_t abbrCode = infoData.getULEB128(&offset);
900
1
  auto abbrevData = dataExtractorFromSection(normalizedFile, abbrev);
901
1
  uint32_t abbrevOffset = getCUAbbrevOffset(abbrevData, abbrCode);
902
1
  uint64_t tag = abbrevData.getULEB128(&abbrevOffset);
903
1
  if (tag != llvm::dwarf::DW_TAG_compile_unit)
904
0
    return llvm::make_error<GenericError>("top level DIE is not a compile unit");
905
1
  // DW_CHILDREN
906
1
  abbrevData.getU8(&abbrevOffset);
907
1
  uint32_t name;
908
1
  llvm::dwarf::Form form;
909
1
  llvm::DWARFFormParams formParams = {version, addrSize, Format};
910
1
  TranslationUnitSource tu;
911
8
  while ((name = abbrevData.getULEB128(&abbrevOffset)) |
912
8
         (form = static_cast<llvm::dwarf::Form>(
913
8
             abbrevData.getULEB128(&abbrevOffset))) &&
914
8
         
(7
name != 07
||
form != 00
)) {
915
7
    switch (name) {
916
7
    case llvm::dwarf::DW_AT_name: {
917
1
      if (auto eName = getIndexedString(normalizedFile, form, infoData, offset,
918
1
                                        strings))
919
1
          tu.name = *eName;
920
0
      else
921
0
        return eName.takeError();
922
1
      break;
923
1
    }
924
1
    case llvm::dwarf::DW_AT_comp_dir: {
925
1
      if (auto eName = getIndexedString(normalizedFile, form, infoData, offset,
926
1
                                        strings))
927
1
        tu.path = *eName;
928
0
      else
929
0
        return eName.takeError();
930
1
      break;
931
1
    }
932
5
    default:
933
5
      llvm::DWARFFormValue::skipValue(form, infoData, &offset, formParams);
934
7
    }
935
7
  }
936
1
  return tu;
937
1
}
938
939
llvm::Error parseDebugInfo(MachOFile &file,
940
81
                           const NormalizedFile &normalizedFile, bool copyRefs) {
941
81
942
81
  // Find the interesting debug info sections.
943
81
  const Section *debugInfo = nullptr;
944
81
  const Section *debugAbbrev = nullptr;
945
81
  const Section *debugStrings = nullptr;
946
81
947
155
  for (auto &s : normalizedFile.sections) {
948
155
    if (s.segmentName == "__DWARF") {
949
12
      if (s.sectionName == "__debug_info")
950
1
        debugInfo = &s;
951
11
      else if (s.sectionName == "__debug_abbrev")
952
1
        debugAbbrev = &s;
953
10
      else if (s.sectionName == "__debug_str")
954
1
        debugStrings = &s;
955
12
    }
956
155
  }
957
81
958
81
  if (!debugInfo)
959
80
    return parseStabs(file, normalizedFile, copyRefs);
960
1
961
1
  if (debugInfo->content.size() == 0)
962
0
    return llvm::Error::success();
963
1
964
1
  if (debugInfo->content.size() < 12)
965
0
    return llvm::make_error<GenericError>("Malformed __debug_info section in " +
966
0
                                          file.path() + ": too small");
967
1
968
1
  if (!debugAbbrev)
969
0
    return llvm::make_error<GenericError>("Missing __dwarf_abbrev section in " +
970
0
                                          file.path());
971
1
972
1
  if (auto tuOrErr = readCompUnit(normalizedFile, *debugInfo, *debugAbbrev,
973
1
                                  *debugStrings, file.path())) {
974
1
    // FIXME: Kill of allocator and code under 'copyRefs' when we fix YAML
975
1
    //        memory ownership.
976
1
    std::unique_ptr<BumpPtrAllocator> allocator;
977
1
    if (copyRefs) {
978
1
      allocator = llvm::make_unique<BumpPtrAllocator>();
979
1
      tuOrErr->name = copyDebugString(tuOrErr->name, *allocator);
980
1
      tuOrErr->path = copyDebugString(tuOrErr->path, *allocator);
981
1
    }
982
1
    file.setDebugInfo(llvm::make_unique<DwarfDebugInfo>(std::move(*tuOrErr)));
983
1
    if (copyRefs)
984
1
      file.debugInfo()->setAllocator(std::move(allocator));
985
1
  } else
986
0
    return tuOrErr.takeError();
987
1
988
1
  return llvm::Error::success();
989
1
}
990
991
21
static int64_t readSPtr(bool is64, bool isBig, const uint8_t *addr) {
992
21
  if (is64)
993
19
    return read64(addr, isBig);
994
2
995
2
  int32_t res = read32(addr, isBig);
996
2
  return res;
997
2
}
998
999
/// --- Augmentation String Processing ---
1000
1001
struct CIEInfo {
1002
  bool _augmentationDataPresent = false;
1003
  bool _mayHaveEH = false;
1004
  uint32_t _offsetOfLSDA = ~0U;
1005
  uint32_t _offsetOfPersonality = ~0U;
1006
  uint32_t _offsetOfFDEPointerEncoding = ~0U;
1007
  uint32_t _augmentationDataLength = ~0U;
1008
};
1009
1010
typedef llvm::DenseMap<const MachODefinedAtom*, CIEInfo> CIEInfoMap;
1011
1012
static llvm::Error processAugmentationString(const uint8_t *augStr,
1013
                                             CIEInfo &cieInfo,
1014
13
                                             unsigned &len) {
1015
13
1016
13
  if (augStr[0] == '\0') {
1017
0
    len = 1;
1018
0
    return llvm::Error::success();
1019
0
  }
1020
13
1021
13
  if (augStr[0] != 'z')
1022
0
    return llvm::make_error<GenericError>("expected 'z' at start of "
1023
0
                                          "augmentation string");
1024
13
1025
13
  cieInfo._augmentationDataPresent = true;
1026
13
  uint64_t idx = 1;
1027
13
1028
13
  uint32_t offsetInAugmentationData = 0;
1029
36
  while (augStr[idx] != '\0') {
1030
23
    if (augStr[idx] == 'L') {
1031
5
      cieInfo._offsetOfLSDA = offsetInAugmentationData;
1032
5
      // This adds a single byte to the augmentation data.
1033
5
      ++offsetInAugmentationData;
1034
5
      ++idx;
1035
5
      continue;
1036
5
    }
1037
18
    if (augStr[idx] == 'P') {
1038
5
      cieInfo._offsetOfPersonality = offsetInAugmentationData;
1039
5
      // This adds a single byte to the augmentation data for the encoding,
1040
5
      // then a number of bytes for the pointer data.
1041
5
      // FIXME: We are assuming 4 is correct here for the pointer size as we
1042
5
      // always currently use delta32ToGOT.
1043
5
      offsetInAugmentationData += 5;
1044
5
      ++idx;
1045
5
      continue;
1046
5
    }
1047
13
    if (augStr[idx] == 'R') {
1048
13
      cieInfo._offsetOfFDEPointerEncoding = offsetInAugmentationData;
1049
13
      // This adds a single byte to the augmentation data.
1050
13
      ++offsetInAugmentationData;
1051
13
      ++idx;
1052
13
      continue;
1053
13
    }
1054
0
    if (augStr[idx] == 'e') {
1055
0
      if (augStr[idx + 1] != 'h')
1056
0
        return llvm::make_error<GenericError>("expected 'eh' in "
1057
0
                                              "augmentation string");
1058
0
      cieInfo._mayHaveEH = true;
1059
0
      idx += 2;
1060
0
      continue;
1061
0
    }
1062
0
    ++idx;
1063
0
  }
1064
13
1065
13
  cieInfo._augmentationDataLength = offsetInAugmentationData;
1066
13
1067
13
  len = idx + 1;
1068
13
  return llvm::Error::success();
1069
13
}
1070
1071
static llvm::Error processCIE(const NormalizedFile &normalizedFile,
1072
                              MachOFile &file,
1073
                              mach_o::ArchHandler &handler,
1074
                              const Section *ehFrameSection,
1075
                              MachODefinedAtom *atom,
1076
                              uint64_t offset,
1077
13
                              CIEInfoMap &cieInfos) {
1078
13
  const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
1079
13
  const uint8_t *frameData = atom->rawContent().data();
1080
13
1081
13
  CIEInfo cieInfo;
1082
13
1083
13
  uint32_t size = read32(frameData, isBig);
1084
13
  uint64_t cieIDField = size == 0xffffffffU
1085
13
                          ? 
sizeof(uint32_t) + sizeof(uint64_t)0
1086
13
                          : sizeof(uint32_t);
1087
13
  uint64_t versionField = cieIDField + sizeof(uint32_t);
1088
13
  uint64_t augmentationStringField = versionField + sizeof(uint8_t);
1089
13
1090
13
  unsigned augmentationStringLength = 0;
1091
13
  if (auto err = processAugmentationString(frameData + augmentationStringField,
1092
0
                                           cieInfo, augmentationStringLength))
1093
0
    return err;
1094
13
1095
13
  if (cieInfo._offsetOfPersonality != ~0U) {
1096
5
    // If we have augmentation data for the personality function, then we may
1097
5
    // need to implicitly generate its relocation.
1098
5
1099
5
    // Parse the EH Data field which is pointer sized.
1100
5
    uint64_t EHDataField = augmentationStringField + augmentationStringLength;
1101
5
    const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
1102
5
    unsigned EHDataFieldSize = (cieInfo._mayHaveEH ? 
(is64 0
?
80
:
40
) : 0);
1103
5
1104
5
    // Parse Code Align Factor which is a ULEB128.
1105
5
    uint64_t CodeAlignField = EHDataField + EHDataFieldSize;
1106
5
    unsigned lengthFieldSize = 0;
1107
5
    llvm::decodeULEB128(frameData + CodeAlignField, &lengthFieldSize);
1108
5
1109
5
    // Parse Data Align Factor which is a SLEB128.
1110
5
    uint64_t DataAlignField = CodeAlignField + lengthFieldSize;
1111
5
    llvm::decodeSLEB128(frameData + DataAlignField, &lengthFieldSize);
1112
5
1113
5
    // Parse Return Address Register which is a byte.
1114
5
    uint64_t ReturnAddressField = DataAlignField + lengthFieldSize;
1115
5
1116
5
    // Parse the augmentation length which is a ULEB128.
1117
5
    uint64_t AugmentationLengthField = ReturnAddressField + 1;
1118
5
    uint64_t AugmentationLength =
1119
5
      llvm::decodeULEB128(frameData + AugmentationLengthField,
1120
5
                          &lengthFieldSize);
1121
5
1122
5
    if (AugmentationLength != cieInfo._augmentationDataLength)
1123
0
      return llvm::make_error<GenericError>("CIE augmentation data length "
1124
0
                                            "mismatch");
1125
5
1126
5
    // Get the start address of the augmentation data.
1127
5
    uint64_t AugmentationDataField = AugmentationLengthField + lengthFieldSize;
1128
5
1129
5
    // Parse the personality function from the augmentation data.
1130
5
    uint64_t PersonalityField =
1131
5
      AugmentationDataField + cieInfo._offsetOfPersonality;
1132
5
1133
5
    // Parse the personality encoding.
1134
5
    // FIXME: Verify that this is a 32-bit pcrel offset.
1135
5
    uint64_t PersonalityFunctionField = PersonalityField + 1;
1136
5
1137
5
    if (atom->begin() != atom->end()) {
1138
3
      // If we have an explicit relocation, then make sure it matches this
1139
3
      // offset as this is where we'd expect it to be applied to.
1140
3
      DefinedAtom::reference_iterator CurrentRef = atom->begin();
1141
3
      if (CurrentRef->offsetInAtom() != PersonalityFunctionField)
1142
0
        return llvm::make_error<GenericError>("CIE personality reloc at "
1143
0
                                              "wrong offset");
1144
3
1145
3
      if (++CurrentRef != atom->end())
1146
0
        return llvm::make_error<GenericError>("CIE contains too many relocs");
1147
2
    } else {
1148
2
      // Implicitly generate the personality function reloc.  It's assumed to
1149
2
      // be a delta32 offset to a GOT entry.
1150
2
      // FIXME: Parse the encoding and check this.
1151
2
      int32_t funcDelta = read32(frameData + PersonalityFunctionField, isBig);
1152
2
      uint64_t funcAddress = ehFrameSection->address + offset +
1153
2
                             PersonalityFunctionField;
1154
2
      funcAddress += funcDelta;
1155
2
1156
2
      const MachODefinedAtom *func = nullptr;
1157
2
      Reference::Addend addend;
1158
2
      func = findAtomCoveringAddress(normalizedFile, file, funcAddress,
1159
2
                                     addend);
1160
2
      atom->addReference(Reference::KindNamespace::mach_o, handler.kindArch(),
1161
2
                         handler.unwindRefToPersonalityFunctionKind(),
1162
2
                         PersonalityFunctionField, func, addend);
1163
2
    }
1164
8
  } else if (atom->begin() != atom->end()) {
1165
0
    // Otherwise, we expect there to be no relocations in this atom as the only
1166
0
    // relocation would have been to the personality function.
1167
0
    return llvm::make_error<GenericError>("unexpected relocation in CIE");
1168
0
  }
1169
13
1170
13
1171
13
  cieInfos[atom] = std::move(cieInfo);
1172
13
1173
13
  return llvm::Error::success();
1174
13
}
1175
1176
static llvm::Error processFDE(const NormalizedFile &normalizedFile,
1177
                              MachOFile &file,
1178
                              mach_o::ArchHandler &handler,
1179
                              const Section *ehFrameSection,
1180
                              MachODefinedAtom *atom,
1181
                              uint64_t offset,
1182
15
                              const CIEInfoMap &cieInfos) {
1183
15
1184
15
  const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
1185
15
  const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
1186
15
1187
15
  // Compiler wasn't lazy and actually told us what it meant.
1188
15
  // Unfortunately, the compiler may not have generated references for all of
1189
15
  // [cie, func, lsda] and so we still need to parse the FDE and add references
1190
15
  // for any the compiler didn't generate.
1191
15
  if (atom->begin() != atom->end())
1192
4
    atom->sortReferences();
1193
15
1194
15
  DefinedAtom::reference_iterator CurrentRef = atom->begin();
1195
15
1196
15
  // This helper returns the reference (if one exists) at the offset we are
1197
15
  // currently processing.  It automatically increments the ref iterator if we
1198
15
  // do return a ref, and throws an error if we pass over a ref without
1199
15
  // comsuming it.
1200
15
  auto currentRefGetter = [&CurrentRef,
1201
36
                           &atom](uint64_t Offset)->const Reference* {
1202
36
    // If there are no more refs found, then we are done.
1203
36
    if (CurrentRef == atom->end())
1204
26
      return nullptr;
1205
10
1206
10
    const Reference *Ref = *CurrentRef;
1207
10
1208
10
    // If we haven't reached the offset for this reference, then return that
1209
10
    // we don't yet have a reference to process.
1210
10
    if (Offset < Ref->offsetInAtom())
1211
2
      return nullptr;
1212
8
1213
8
    // If the offset is equal, then we want to process this ref.
1214
8
    if (Offset == Ref->offsetInAtom()) {
1215
8
      ++CurrentRef;
1216
8
      return Ref;
1217
8
    }
1218
0
1219
0
    // The current ref is at an offset which is earlier than the current
1220
0
    // offset, then we failed to consume it when we should have.  In this case
1221
0
    // throw an error.
1222
0
    llvm::report_fatal_error("Skipped reference when processing FDE");
1223
0
  };
1224
15
1225
15
  // Helper to either get the reference at this current location, and verify
1226
15
  // that it is of the expected type, or add a reference of that type.
1227
15
  // Returns the reference target.
1228
15
  auto verifyOrAddReference = [&](uint64_t targetAddress,
1229
15
                                  Reference::KindValue refKind,
1230
15
                                  uint64_t refAddress,
1231
36
                                  bool allowsAddend)->const Atom* {
1232
36
    if (auto *ref = currentRefGetter(refAddress)) {
1233
8
      // The compiler already emitted a relocation for the CIE ref.  This should
1234
8
      // have been converted to the correct type of reference in
1235
8
      // get[Pair]ReferenceInfo().
1236
8
      assert(ref->kindValue() == refKind &&
1237
8
             "Incorrect EHFrame reference kind");
1238
8
      return ref->target();
1239
8
    }
1240
28
    Reference::Addend addend;
1241
28
    auto *target = findAtomCoveringAddress(normalizedFile, file,
1242
28
                                           targetAddress, addend);
1243
28
    atom->addReference(Reference::KindNamespace::mach_o, handler.kindArch(),
1244
28
                       refKind, refAddress, target, addend);
1245
28
1246
28
    if (!allowsAddend)
1247
28
      assert(!addend && "EHFrame reference cannot have addend");
1248
28
    return target;
1249
28
  };
1250
15
1251
15
  const uint8_t *startFrameData = atom->rawContent().data();
1252
15
  const uint8_t *frameData = startFrameData;
1253
15
1254
15
  uint32_t size = read32(frameData, isBig);
1255
15
  uint64_t cieFieldInFDE = size == 0xffffffffU
1256
15
    ? 
sizeof(uint32_t) + sizeof(uint64_t)0
1257
15
    : sizeof(uint32_t);
1258
15
1259
15
  // Linker needs to fixup a reference from the FDE to its parent CIE (a
1260
15
  // 32-bit byte offset backwards in the __eh_frame section).
1261
15
  uint32_t cieDelta = read32(frameData + cieFieldInFDE, isBig);
1262
15
  uint64_t cieAddress = ehFrameSection->address + offset + cieFieldInFDE;
1263
15
  cieAddress -= cieDelta;
1264
15
1265
15
  auto *cieRefTarget = verifyOrAddReference(cieAddress,
1266
15
                                            handler.unwindRefToCIEKind(),
1267
15
                                            cieFieldInFDE, false);
1268
15
  const MachODefinedAtom *cie = dyn_cast<MachODefinedAtom>(cieRefTarget);
1269
15
  assert(cie && cie->contentType() == DefinedAtom::typeCFI &&
1270
15
         "FDE's CIE field does not point at the start of a CIE.");
1271
15
1272
15
  const CIEInfo &cieInfo = cieInfos.find(cie)->second;
1273
15
1274
15
  // Linker needs to fixup reference from the FDE to the function it's
1275
15
  // describing. FIXME: there are actually different ways to do this, and the
1276
15
  // particular method used is specified in the CIE's augmentation fields
1277
15
  // (hopefully)
1278
15
  uint64_t rangeFieldInFDE = cieFieldInFDE + sizeof(uint32_t);
1279
15
1280
15
  int64_t functionFromFDE = readSPtr(is64, isBig,
1281
15
                                     frameData + rangeFieldInFDE);
1282
15
  uint64_t rangeStart = ehFrameSection->address + offset + rangeFieldInFDE;
1283
15
  rangeStart += functionFromFDE;
1284
15
1285
15
  verifyOrAddReference(rangeStart,
1286
15
                       handler.unwindRefToFunctionKind(),
1287
15
                       rangeFieldInFDE, true);
1288
15
1289
15
  // Handle the augmentation data if there is any.
1290
15
  if (cieInfo._augmentationDataPresent) {
1291
15
    // First process the augmentation data length field.
1292
15
    uint64_t augmentationDataLengthFieldInFDE =
1293
15
      rangeFieldInFDE + 2 * (is64 ? 
sizeof(uint64_t)13
:
sizeof(uint32_t)2
);
1294
15
    unsigned lengthFieldSize = 0;
1295
15
    uint64_t augmentationDataLength =
1296
15
      llvm::decodeULEB128(frameData + augmentationDataLengthFieldInFDE,
1297
15
                          &lengthFieldSize);
1298
15
1299
15
    if (cieInfo._offsetOfLSDA != ~0U && 
augmentationDataLength > 06
) {
1300
6
1301
6
      // Look at the augmentation data field.
1302
6
      uint64_t augmentationDataFieldInFDE =
1303
6
        augmentationDataLengthFieldInFDE + lengthFieldSize;
1304
6
1305
6
      int64_t lsdaFromFDE = readSPtr(is64, isBig,
1306
6
                                     frameData + augmentationDataFieldInFDE);
1307
6
      uint64_t lsdaStart =
1308
6
        ehFrameSection->address + offset + augmentationDataFieldInFDE +
1309
6
        lsdaFromFDE;
1310
6
1311
6
      verifyOrAddReference(lsdaStart,
1312
6
                           handler.unwindRefToFunctionKind(),
1313
6
                           augmentationDataFieldInFDE, true);
1314
6
    }
1315
15
  }
1316
15
1317
15
  return llvm::Error::success();
1318
15
}
1319
1320
llvm::Error addEHFrameReferences(const NormalizedFile &normalizedFile,
1321
                                 MachOFile &file,
1322
81
                                 mach_o::ArchHandler &handler) {
1323
81
1324
81
  const Section *ehFrameSection = nullptr;
1325
81
  for (auto &section : normalizedFile.sections)
1326
152
    if (section.segmentName == "__TEXT" &&
1327
152
        
section.sectionName == "__eh_frame"96
) {
1328
11
      ehFrameSection = &section;
1329
11
      break;
1330
11
    }
1331
81
1332
81
  // No __eh_frame so nothing to do.
1333
81
  if (!ehFrameSection)
1334
70
    return llvm::Error::success();
1335
11
1336
11
  llvm::Error ehFrameErr = llvm::Error::success();
1337
11
  CIEInfoMap cieInfos;
1338
11
1339
11
  file.eachAtomInSection(*ehFrameSection,
1340
28
                         [&](MachODefinedAtom *atom, uint64_t offset) -> void {
1341
28
    assert(atom->contentType() == DefinedAtom::typeCFI);
1342
28
1343
28
    // Bail out if we've encountered an error.
1344
28
    if (ehFrameErr)
1345
0
      return;
1346
28
1347
28
    const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
1348
28
    if (ArchHandler::isDwarfCIE(isBig, atom))
1349
13
      ehFrameErr = processCIE(normalizedFile, file, handler, ehFrameSection,
1350
13
                              atom, offset, cieInfos);
1351
15
    else
1352
15
      ehFrameErr = processFDE(normalizedFile, file, handler, ehFrameSection,
1353
15
                              atom, offset, cieInfos);
1354
28
  });
1355
11
1356
11
  return ehFrameErr;
1357
11
}
1358
1359
llvm::Error parseObjCImageInfo(const Section &sect,
1360
                               const NormalizedFile &normalizedFile,
1361
5
                               MachOFile &file) {
1362
5
1363
5
  //  struct objc_image_info  {
1364
5
  //    uint32_t  version;  // initially 0
1365
5
  //    uint32_t  flags;
1366
5
  //  };
1367
5
1368
5
  ArrayRef<uint8_t> content = sect.content;
1369
5
  if (content.size() != 8)
1370
0
    return llvm::make_error<GenericError>(sect.segmentName + "/" +
1371
0
                                          sect.sectionName +
1372
0
                                          " in file " + file.path() +
1373
0
                                          " should be 8 bytes in size");
1374
5
1375
5
  const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
1376
5
  uint32_t version = read32(content.data(), isBig);
1377
5
  if (version)
1378
1
    return llvm::make_error<GenericError>(sect.segmentName + "/" +
1379
1
                                          sect.sectionName +
1380
1
                                          " in file " + file.path() +
1381
1
                                          " should have version=0");
1382
4
1383
4
  uint32_t flags = read32(content.data() + 4, isBig);
1384
4
  if (flags & (MachOLinkingContext::objc_supports_gc |
1385
4
               MachOLinkingContext::objc_gc_only))
1386
1
    return llvm::make_error<GenericError>(sect.segmentName + "/" +
1387
1
                                          sect.sectionName +
1388
1
                                          " in file " + file.path() +
1389
1
                                          " uses GC.  This is not supported");
1390
3
1391
3
  if (flags & MachOLinkingContext::objc_retainReleaseForSimulator)
1392
2
    file.setObjcConstraint(MachOLinkingContext::objc_retainReleaseForSimulator);
1393
1
  else
1394
1
    file.setObjcConstraint(MachOLinkingContext::objc_retainRelease);
1395
3
1396
3
  file.setSwiftVersion((flags >> 8) & 0xFF);
1397
3
1398
3
  return llvm::Error::success();
1399
3
}
1400
1401
/// Converts normalized mach-o file into an lld::File and lld::Atoms.
1402
llvm::Expected<std::unique_ptr<lld::File>>
1403
objectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
1404
76
              bool copyRefs) {
1405
76
  std::unique_ptr<MachOFile> file(new MachOFile(path));
1406
76
  if (auto ec = normalizedObjectToAtoms(file.get(), normalizedFile, copyRefs))
1407
3
    return std::move(ec);
1408
73
  return std::unique_ptr<File>(std::move(file));
1409
73
}
1410
1411
llvm::Expected<std::unique_ptr<lld::File>>
1412
dylibToAtoms(const NormalizedFile &normalizedFile, StringRef path,
1413
57
             bool copyRefs) {
1414
57
  // Instantiate SharedLibraryFile object.
1415
57
  std::unique_ptr<MachODylibFile> file(new MachODylibFile(path));
1416
57
  if (auto ec = normalizedDylibToAtoms(file.get(), normalizedFile, copyRefs))
1417
0
    return std::move(ec);
1418
57
  return std::unique_ptr<File>(std::move(file));
1419
57
}
1420
1421
} // anonymous namespace
1422
1423
namespace normalized {
1424
1425
147
static bool isObjCImageInfo(const Section &sect) {
1426
147
  return (sect.segmentName == "__OBJC" && 
sect.sectionName == "__image_info"0
) ||
1427
147
    (sect.segmentName == "__DATA" && 
sect.sectionName == "__objc_imageinfo"37
);
1428
147
}
1429
1430
llvm::Error
1431
normalizedObjectToAtoms(MachOFile *file,
1432
                        const NormalizedFile &normalizedFile,
1433
84
                        bool copyRefs) {
1434
84
  DEBUG(llvm::dbgs() << "******** Normalizing file to atoms: "
1435
84
                    << file->path() << "\n");
1436
84
  bool scatterable = ((normalizedFile.flags & MH_SUBSECTIONS_VIA_SYMBOLS) != 0);
1437
84
1438
84
  // Create atoms from each section.
1439
159
  for (auto &sect : normalizedFile.sections) {
1440
159
1441
159
    // If this is a debug-info section parse it specially.
1442
159
    if (isDebugInfoSection(sect))
1443
12
      continue;
1444
147
1445
147
    // If the file contains an objc_image_info struct, then we should parse the
1446
147
    // ObjC flags and Swift version.
1447
147
    if (isObjCImageInfo(sect)) {
1448
5
      if (auto ec = parseObjCImageInfo(sect, normalizedFile, *file))
1449
2
        return ec;
1450
3
      // We then skip adding atoms for this section as we use the ObjCPass to
1451
3
      // re-emit this data after it has been aggregated for all files.
1452
3
      continue;
1453
3
    }
1454
142
1455
142
    bool customSectionName;
1456
142
    DefinedAtom::ContentType atomType = atomTypeFromSection(sect,
1457
142
                                                            customSectionName);
1458
142
    if (auto ec =  processSection(atomType, sect, customSectionName,
1459
0
                                  normalizedFile, *file, scatterable, copyRefs))
1460
0
      return ec;
1461
142
  }
1462
84
  // Create atoms from undefined symbols.
1463
84
  
for (auto &sym : normalizedFile.undefinedSymbols)82
{
1464
52
    // Undefinded symbols with n_value != 0 are actually tentative definitions.
1465
52
    if (sym.value == Hex64(0)) {
1466
52
      file->addUndefinedAtom(sym.name, copyRefs);
1467
52
    } else {
1468
0
      file->addTentativeDefAtom(sym.name, atomScope(sym.scope), sym.value,
1469
0
                                DefinedAtom::Alignment(1 << (sym.desc >> 8)),
1470
0
                                copyRefs);
1471
0
    }
1472
52
  }
1473
82
1474
82
  // Convert mach-o relocations to References
1475
82
  std::unique_ptr<mach_o::ArchHandler> handler
1476
82
                                     = ArchHandler::create(normalizedFile.arch);
1477
157
  for (auto &sect : normalizedFile.sections) {
1478
157
    if (isDebugInfoSection(sect))
1479
12
      continue;
1480
145
    if (llvm::Error ec = convertRelocs(sect, normalizedFile, scatterable,
1481
1
                                       *file, *handler))
1482
1
      return ec;
1483
145
  }
1484
82
1485
82
  // Add additional arch-specific References
1486
210
  
file->eachDefinedAtom([&](MachODefinedAtom* atom) -> void 81
{
1487
210
    handler->addAdditionalReferences(*atom);
1488
210
  });
1489
81
1490
81
  // Each __eh_frame section needs references to both __text (the function we're
1491
81
  // providing unwind info for) and itself (FDE -> CIE). These aren't
1492
81
  // represented in the relocations on some architectures, so we have to add
1493
81
  // them back in manually there.
1494
81
  if (auto ec = addEHFrameReferences(normalizedFile, *file, *handler))
1495
0
    return ec;
1496
81
1497
81
  // Process mach-o data-in-code regions array. That information is encoded in
1498
81
  // atoms as References at each transition point.
1499
81
  unsigned nextIndex = 0;
1500
81
  for (const DataInCode &entry : normalizedFile.dataInCode) {
1501
10
    ++nextIndex;
1502
10
    const Section* s = findSectionCoveringAddress(normalizedFile, entry.offset);
1503
10
    if (!s) {
1504
0
      return llvm::make_error<GenericError>(Twine("LC_DATA_IN_CODE address ("
1505
0
                                                  + Twine(entry.offset)
1506
0
                                                  + ") is not in any section"));
1507
0
    }
1508
10
    uint64_t offsetInSect = entry.offset - s->address;
1509
10
    uint32_t offsetInAtom;
1510
10
    MachODefinedAtom *atom = file->findAtomCoveringAddress(*s, offsetInSect,
1511
10
                                                           &offsetInAtom);
1512
10
    if (offsetInAtom + entry.length > atom->size()) {
1513
0
      return llvm::make_error<GenericError>(Twine("LC_DATA_IN_CODE entry "
1514
0
                                                  "(offset="
1515
0
                                                  + Twine(entry.offset)
1516
0
                                                  + ", length="
1517
0
                                                  + Twine(entry.length)
1518
0
                                                  + ") crosses atom boundary."));
1519
0
    }
1520
10
    // Add reference that marks start of data-in-code.
1521
10
    atom->addReference(Reference::KindNamespace::mach_o, handler->kindArch(),
1522
10
                       handler->dataInCodeTransitionStart(*atom),
1523
10
                       offsetInAtom, atom, entry.kind);
1524
10
1525
10
    // Peek at next entry, if it starts where this one ends, skip ending ref.
1526
10
    if (nextIndex < normalizedFile.dataInCode.size()) {
1527
8
      const DataInCode &nextEntry = normalizedFile.dataInCode[nextIndex];
1528
8
      if (nextEntry.offset == (entry.offset + entry.length))
1529
6
        continue;
1530
4
    }
1531
4
1532
4
    // If data goes to end of function, skip ending ref.
1533
4
    if ((offsetInAtom + entry.length) == atom->size())
1534
1
      continue;
1535
3
1536
3
    // Add reference that marks end of data-in-code.
1537
3
    atom->addReference(Reference::KindNamespace::mach_o, handler->kindArch(),
1538
3
                       handler->dataInCodeTransitionEnd(*atom),
1539
3
                       offsetInAtom+entry.length, atom, 0);
1540
3
  }
1541
81
1542
81
  // Cache some attributes on the file for use later.
1543
81
  file->setFlags(normalizedFile.flags);
1544
81
  file->setArch(normalizedFile.arch);
1545
81
  file->setOS(normalizedFile.os);
1546
81
  file->setMinVersion(normalizedFile.minOSverson);
1547
81
  file->setMinVersionLoadCommandKind(normalizedFile.minOSVersionKind);
1548
81
1549
81
  // Sort references in each atom to their canonical order.
1550
210
  for (const DefinedAtom* defAtom : file->defined()) {
1551
210
    reinterpret_cast<const SimpleDefinedAtom*>(defAtom)->sortReferences();
1552
210
  }
1553
81
1554
81
  if (auto err = parseDebugInfo(*file, normalizedFile, copyRefs))
1555
0
    return err;
1556
81
1557
81
  return llvm::Error::success();
1558
81
}
1559
1560
llvm::Error
1561
normalizedDylibToAtoms(MachODylibFile *file,
1562
                       const NormalizedFile &normalizedFile,
1563
59
                       bool copyRefs) {
1564
59
  file->setInstallName(normalizedFile.installName);
1565
59
  file->setCompatVersion(normalizedFile.compatVersion);
1566
59
  file->setCurrentVersion(normalizedFile.currentVersion);
1567
59
1568
59
  // Tell MachODylibFile object about all symbols it exports.
1569
59
  if (!normalizedFile.exportInfo.empty()) {
1570
58
    // If exports trie exists, use it instead of traditional symbol table.
1571
70
    for (const Export &exp : normalizedFile.exportInfo) {
1572
70
      bool weakDef = (exp.flags & EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
1573
70
      // StringRefs from export iterator are ephemeral, so force copy.
1574
70
      file->addExportedSymbol(exp.name, weakDef, true);
1575
70
    }
1576
58
  } else {
1577
1
    for (auto &sym : normalizedFile.globalSymbols) {
1578
1
      assert((sym.scope & N_EXT) && "only expect external symbols here");
1579
1
      bool weakDef = (sym.desc & N_WEAK_DEF);
1580
1
      file->addExportedSymbol(sym.name, weakDef, copyRefs);
1581
1
    }
1582
1
  }
1583
59
  // Tell MachODylibFile object about all dylibs it re-exports.
1584
59
  for (const DependentDylib &dep : normalizedFile.dependentDylibs) {
1585
2
    if (dep.kind == llvm::MachO::LC_REEXPORT_DYLIB)
1586
0
      file->addReExportedDylib(dep.path);
1587
2
  }
1588
59
  return llvm::Error::success();
1589
59
}
1590
1591
void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
1592
                                          StringRef &segmentName,
1593
                                          StringRef &sectionName,
1594
                                          SectionType &sectionType,
1595
                                          SectionAttr &sectionAttrs,
1596
62
                                          bool &relocsToDefinedCanBeImplicit) {
1597
62
1598
62
  for (const MachORelocatableSectionToAtomType *p = sectsToAtomType ;
1599
625
                                 p->atomType != DefinedAtom::typeUnknown; 
++p563
) {
1600
625
    if (p->atomType != atomType)
1601
563
      continue;
1602
62
    // Wild carded entries are ignored for reverse lookups.
1603
62
    if (p->segmentName.empty() || p->sectionName.empty())
1604
0
      continue;
1605
62
    segmentName = p->segmentName;
1606
62
    sectionName = p->sectionName;
1607
62
    sectionType = p->sectionType;
1608
62
    sectionAttrs = 0;
1609
62
    relocsToDefinedCanBeImplicit = false;
1610
62
    if (atomType == DefinedAtom::typeCode)
1611
26
      sectionAttrs = S_ATTR_PURE_INSTRUCTIONS;
1612
62
    if (atomType == DefinedAtom::typeCFI)
1613
5
      relocsToDefinedCanBeImplicit = true;
1614
62
    return;
1615
62
  }
1616
62
  
llvm_unreachable0
("content type not yet supported");
1617
0
}
1618
1619
llvm::Expected<std::unique_ptr<lld::File>>
1620
normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path,
1621
133
                  bool copyRefs) {
1622
133
  switch (normalizedFile.fileType) {
1623
133
  case MH_DYLIB:
1624
57
  case MH_DYLIB_STUB:
1625
57
    return dylibToAtoms(normalizedFile, path, copyRefs);
1626
76
  case MH_OBJECT:
1627
76
    return objectToAtoms(normalizedFile, path, copyRefs);
1628
57
  default:
1629
0
    llvm_unreachable("unhandled MachO file type!");
1630
0
  }
1631
0
}
1632
1633
} // namespace normalized
1634
} // namespace mach_o
1635
} // namespace lld