1//===- MachOObjectFile.cpp - Mach-O object file binding -------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the MachOObjectFile class, which binds the MachOObject
10// class to the generic ObjectFile wrapper.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/ADT/ArrayRef.h"
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/SmallVector.h"
17#include "llvm/ADT/StringRef.h"
18#include "llvm/ADT/StringSwitch.h"
19#include "llvm/ADT/Twine.h"
20#include "llvm/ADT/bit.h"
21#include "llvm/BinaryFormat/MachO.h"
22#include "llvm/BinaryFormat/Swift.h"
23#include "llvm/Object/Error.h"
24#include "llvm/Object/MachO.h"
25#include "llvm/Object/ObjectFile.h"
26#include "llvm/Object/SymbolicFile.h"
27#include "llvm/Support/DataExtractor.h"
28#include "llvm/Support/Debug.h"
29#include "llvm/Support/Errc.h"
30#include "llvm/Support/Error.h"
31#include "llvm/Support/ErrorHandling.h"
32#include "llvm/Support/FileSystem.h"
33#include "llvm/Support/Format.h"
34#include "llvm/Support/LEB128.h"
35#include "llvm/Support/MemoryBufferRef.h"
36#include "llvm/Support/Path.h"
37#include "llvm/Support/SwapByteOrder.h"
38#include "llvm/Support/raw_ostream.h"
39#include "llvm/TargetParser/Host.h"
40#include "llvm/TargetParser/Triple.h"
41#include <algorithm>
42#include <cassert>
43#include <cstddef>
44#include <cstdint>
45#include <cstring>
46#include <limits>
47#include <list>
48#include <memory>
49#include <system_error>
50
51using namespace llvm;
52using namespace object;
53
54namespace {
55
56  struct section_base {
57    char sectname[16];
58    char segname[16];
59  };
60
61} // end anonymous namespace
62
63static Error malformedError(const Twine &Msg) {
64  return make_error<GenericBinaryError>("truncated or malformed object (" +
65                                            Msg + ")",
66                                        object_error::parse_failed);
67}
68
69// FIXME: Replace all uses of this function with getStructOrErr.
70template <typename T>
71static T getStruct(const MachOObjectFile &O, const char *P) {
72  // Don't read before the beginning or past the end of the file
73  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
74    report_fatal_error("Malformed MachO file.");
75
76  T Cmd;
77  memcpy(&Cmd, P, sizeof(T));
78  if (O.isLittleEndian() != sys::IsLittleEndianHost)
79    MachO::swapStruct(Cmd);
80  return Cmd;
81}
82
83template <typename T>
84static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
85  // Don't read before the beginning or past the end of the file
86  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
87    return malformedError("Structure read out-of-range");
88
89  T Cmd;
90  memcpy(&Cmd, P, sizeof(T));
91  if (O.isLittleEndian() != sys::IsLittleEndianHost)
92    MachO::swapStruct(Cmd);
93  return Cmd;
94}
95
96static const char *
97getSectionPtr(const MachOObjectFile &O, MachOObjectFile::LoadCommandInfo L,
98              unsigned Sec) {
99  uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
100
101  bool Is64 = O.is64Bit();
102  unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) :
103                                    sizeof(MachO::segment_command);
104  unsigned SectionSize = Is64 ? sizeof(MachO::section_64) :
105                                sizeof(MachO::section);
106
107  uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
108  return reinterpret_cast<const char*>(SectionAddr);
109}
110
111static const char *getPtr(const MachOObjectFile &O, size_t Offset,
112                          size_t MachOFilesetEntryOffset = 0) {
113  assert(Offset <= O.getData().size() &&
114         MachOFilesetEntryOffset <= O.getData().size());
115  return O.getData().data() + Offset + MachOFilesetEntryOffset;
116}
117
118static MachO::nlist_base
119getSymbolTableEntryBase(const MachOObjectFile &O, DataRefImpl DRI) {
120  const char *P = reinterpret_cast<const char *>(DRI.p);
121  return getStruct<MachO::nlist_base>(O, P);
122}
123
124static StringRef parseSegmentOrSectionName(const char *P) {
125  if (P[15] == 0)
126    // Null terminated.
127    return P;
128  // Not null terminated, so this is a 16 char string.
129  return StringRef(P, 16);
130}
131
132static unsigned getCPUType(const MachOObjectFile &O) {
133  return O.getHeader().cputype;
134}
135
136static unsigned getCPUSubType(const MachOObjectFile &O) {
137  return O.getHeader().cpusubtype;
138}
139
140static uint32_t
141getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
142  return RE.r_word0;
143}
144
145static unsigned
146getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
147  return RE.r_word0 & 0xffffff;
148}
149
150static bool getPlainRelocationPCRel(const MachOObjectFile &O,
151                                    const MachO::any_relocation_info &RE) {
152  if (O.isLittleEndian())
153    return (RE.r_word1 >> 24) & 1;
154  return (RE.r_word1 >> 7) & 1;
155}
156
157static bool
158getScatteredRelocationPCRel(const MachO::any_relocation_info &RE) {
159  return (RE.r_word0 >> 30) & 1;
160}
161
162static unsigned getPlainRelocationLength(const MachOObjectFile &O,
163                                         const MachO::any_relocation_info &RE) {
164  if (O.isLittleEndian())
165    return (RE.r_word1 >> 25) & 3;
166  return (RE.r_word1 >> 5) & 3;
167}
168
169static unsigned
170getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
171  return (RE.r_word0 >> 28) & 3;
172}
173
174static unsigned getPlainRelocationType(const MachOObjectFile &O,
175                                       const MachO::any_relocation_info &RE) {
176  if (O.isLittleEndian())
177    return RE.r_word1 >> 28;
178  return RE.r_word1 & 0xf;
179}
180
181static uint32_t getSectionFlags(const MachOObjectFile &O,
182                                DataRefImpl Sec) {
183  if (O.is64Bit()) {
184    MachO::section_64 Sect = O.getSection64(Sec);
185    return Sect.flags;
186  }
187  MachO::section Sect = O.getSection(Sec);
188  return Sect.flags;
189}
190
191static Expected<MachOObjectFile::LoadCommandInfo>
192getLoadCommandInfo(const MachOObjectFile &Obj, const char *Ptr,
193                   uint32_t LoadCommandIndex) {
194  if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
195    if (CmdOrErr->cmdsize + Ptr > Obj.getData().end())
196      return malformedError("load command " + Twine(LoadCommandIndex) +
197                            " extends past end of file");
198    if (CmdOrErr->cmdsize < 8)
199      return malformedError("load command " + Twine(LoadCommandIndex) +
200                            " with size less than 8 bytes");
201    return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
202  } else
203    return CmdOrErr.takeError();
204}
205
206static Expected<MachOObjectFile::LoadCommandInfo>
207getFirstLoadCommandInfo(const MachOObjectFile &Obj) {
208  unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
209                                      : sizeof(MachO::mach_header);
210  if (sizeof(MachO::load_command) > Obj.getHeader().sizeofcmds)
211    return malformedError("load command 0 extends past the end all load "
212                          "commands in the file");
213  return getLoadCommandInfo(
214      Obj, getPtr(Obj, HeaderSize, Obj.getMachOFilesetEntryOffset()), 0);
215}
216
217static Expected<MachOObjectFile::LoadCommandInfo>
218getNextLoadCommandInfo(const MachOObjectFile &Obj, uint32_t LoadCommandIndex,
219                       const MachOObjectFile::LoadCommandInfo &L) {
220  unsigned HeaderSize = Obj.is64Bit() ? sizeof(MachO::mach_header_64)
221                                      : sizeof(MachO::mach_header);
222  if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >
223      Obj.getData().data() + Obj.getMachOFilesetEntryOffset() + HeaderSize +
224          Obj.getHeader().sizeofcmds)
225    return malformedError("load command " + Twine(LoadCommandIndex + 1) +
226                          " extends past the end all load commands in the file");
227  return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);
228}
229
230template <typename T>
231static void parseHeader(const MachOObjectFile &Obj, T &Header,
232                        Error &Err) {
233  if (sizeof(T) > Obj.getData().size()) {
234    Err = malformedError("the mach header extends past the end of the "
235                         "file");
236    return;
237  }
238  if (auto HeaderOrErr = getStructOrErr<T>(
239          Obj, getPtr(Obj, 0, Obj.getMachOFilesetEntryOffset())))
240    Header = *HeaderOrErr;
241  else
242    Err = HeaderOrErr.takeError();
243}
244
245// This is used to check for overlapping of Mach-O elements.
246struct MachOElement {
247  uint64_t Offset;
248  uint64_t Size;
249  const char *Name;
250};
251
252static Error checkOverlappingElement(std::list<MachOElement> &Elements,
253                                     uint64_t Offset, uint64_t Size,
254                                     const char *Name) {
255  if (Size == 0)
256    return Error::success();
257
258  for (auto it = Elements.begin(); it != Elements.end(); ++it) {
259    const auto &E = *it;
260    if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||
261        (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) ||
262        (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))
263      return malformedError(Twine(Name) + " at offset " + Twine(Offset) +
264                            " with a size of " + Twine(Size) + ", overlaps " +
265                            E.Name + " at offset " + Twine(E.Offset) + " with "
266                            "a size of " + Twine(E.Size));
267    auto nt = it;
268    nt++;
269    if (nt != Elements.end()) {
270      const auto &N = *nt;
271      if (Offset + Size <= N.Offset) {
272        Elements.insert(nt, {Offset, Size, Name});
273        return Error::success();
274      }
275    }
276  }
277  Elements.push_back({Offset, Size, Name});
278  return Error::success();
279}
280
281// Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
282// sections to \param Sections, and optionally sets
283// \param IsPageZeroSegment to true.
284template <typename Segment, typename Section>
285static Error parseSegmentLoadCommand(
286    const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load,
287    SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
288    uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders,
289    std::list<MachOElement> &Elements) {
290  const unsigned SegmentLoadSize = sizeof(Segment);
291  if (Load.C.cmdsize < SegmentLoadSize)
292    return malformedError("load command " + Twine(LoadCommandIndex) +
293                          " " + CmdName + " cmdsize too small");
294  if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
295    Segment S = SegOrErr.get();
296    const unsigned SectionSize = sizeof(Section);
297    uint64_t FileSize = Obj.getData().size();
298    if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
299        S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
300      return malformedError("load command " + Twine(LoadCommandIndex) +
301                            " inconsistent cmdsize in " + CmdName +
302                            " for the number of sections");
303    for (unsigned J = 0; J < S.nsects; ++J) {
304      const char *Sec = getSectionPtr(Obj, Load, J);
305      Sections.push_back(Sec);
306      auto SectionOrErr = getStructOrErr<Section>(Obj, Sec);
307      if (!SectionOrErr)
308        return SectionOrErr.takeError();
309      Section s = SectionOrErr.get();
310      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
311          Obj.getHeader().filetype != MachO::MH_DSYM &&
312          s.flags != MachO::S_ZEROFILL &&
313          s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
314          s.offset > FileSize)
315        return malformedError("offset field of section " + Twine(J) + " in " +
316                              CmdName + " command " + Twine(LoadCommandIndex) +
317                              " extends past the end of the file");
318      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
319          Obj.getHeader().filetype != MachO::MH_DSYM &&
320          s.flags != MachO::S_ZEROFILL &&
321          s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 &&
322          s.offset < SizeOfHeaders && s.size != 0)
323        return malformedError("offset field of section " + Twine(J) + " in " +
324                              CmdName + " command " + Twine(LoadCommandIndex) +
325                              " not past the headers of the file");
326      uint64_t BigSize = s.offset;
327      BigSize += s.size;
328      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
329          Obj.getHeader().filetype != MachO::MH_DSYM &&
330          s.flags != MachO::S_ZEROFILL &&
331          s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
332          BigSize > FileSize)
333        return malformedError("offset field plus size field of section " +
334                              Twine(J) + " in " + CmdName + " command " +
335                              Twine(LoadCommandIndex) +
336                              " extends past the end of the file");
337      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
338          Obj.getHeader().filetype != MachO::MH_DSYM &&
339          s.flags != MachO::S_ZEROFILL &&
340          s.flags != MachO::S_THREAD_LOCAL_ZEROFILL &&
341          s.size > S.filesize)
342        return malformedError("size field of section " +
343                              Twine(J) + " in " + CmdName + " command " +
344                              Twine(LoadCommandIndex) +
345                              " greater than the segment");
346      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
347          Obj.getHeader().filetype != MachO::MH_DSYM && s.size != 0 &&
348          s.addr < S.vmaddr)
349        return malformedError("addr field of section " + Twine(J) + " in " +
350                              CmdName + " command " + Twine(LoadCommandIndex) +
351                              " less than the segment's vmaddr");
352      BigSize = s.addr;
353      BigSize += s.size;
354      uint64_t BigEnd = S.vmaddr;
355      BigEnd += S.vmsize;
356      if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd)
357        return malformedError("addr field plus size of section " + Twine(J) +
358                              " in " + CmdName + " command " +
359                              Twine(LoadCommandIndex) +
360                              " greater than than "
361                              "the segment's vmaddr plus vmsize");
362      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
363          Obj.getHeader().filetype != MachO::MH_DSYM &&
364          s.flags != MachO::S_ZEROFILL &&
365          s.flags != MachO::S_THREAD_LOCAL_ZEROFILL)
366        if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,
367                                                "section contents"))
368          return Err;
369      if (s.reloff > FileSize)
370        return malformedError("reloff field of section " + Twine(J) + " in " +
371                              CmdName + " command " + Twine(LoadCommandIndex) +
372                              " extends past the end of the file");
373      BigSize = s.nreloc;
374      BigSize *= sizeof(struct MachO::relocation_info);
375      BigSize += s.reloff;
376      if (BigSize > FileSize)
377        return malformedError("reloff field plus nreloc field times sizeof("
378                              "struct relocation_info) of section " +
379                              Twine(J) + " in " + CmdName + " command " +
380                              Twine(LoadCommandIndex) +
381                              " extends past the end of the file");
382      if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *
383                                              sizeof(struct
384                                              MachO::relocation_info),
385                                              "section relocation entries"))
386        return Err;
387    }
388    if (S.fileoff > FileSize)
389      return malformedError("load command " + Twine(LoadCommandIndex) +
390                            " fileoff field in " + CmdName +
391                            " extends past the end of the file");
392    uint64_t BigSize = S.fileoff;
393    BigSize += S.filesize;
394    if (BigSize > FileSize)
395      return malformedError("load command " + Twine(LoadCommandIndex) +
396                            " fileoff field plus filesize field in " +
397                            CmdName + " extends past the end of the file");
398    if (S.vmsize != 0 && S.filesize > S.vmsize)
399      return malformedError("load command " + Twine(LoadCommandIndex) +
400                            " filesize field in " + CmdName +
401                            " greater than vmsize field");
402    IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
403  } else
404    return SegOrErr.takeError();
405
406  return Error::success();
407}
408
409static Error checkSymtabCommand(const MachOObjectFile &Obj,
410                                const MachOObjectFile::LoadCommandInfo &Load,
411                                uint32_t LoadCommandIndex,
412                                const char **SymtabLoadCmd,
413                                std::list<MachOElement> &Elements) {
414  if (Load.C.cmdsize < sizeof(MachO::symtab_command))
415    return malformedError("load command " + Twine(LoadCommandIndex) +
416                          " LC_SYMTAB cmdsize too small");
417  if (*SymtabLoadCmd != nullptr)
418    return malformedError("more than one LC_SYMTAB command");
419  auto SymtabOrErr = getStructOrErr<MachO::symtab_command>(Obj, Load.Ptr);
420  if (!SymtabOrErr)
421    return SymtabOrErr.takeError();
422  MachO::symtab_command Symtab = SymtabOrErr.get();
423  if (Symtab.cmdsize != sizeof(MachO::symtab_command))
424    return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +
425                          " has incorrect cmdsize");
426  uint64_t FileSize = Obj.getData().size();
427  if (Symtab.symoff > FileSize)
428    return malformedError("symoff field of LC_SYMTAB command " +
429                          Twine(LoadCommandIndex) + " extends past the end "
430                          "of the file");
431  uint64_t SymtabSize = Symtab.nsyms;
432  const char *struct_nlist_name;
433  if (Obj.is64Bit()) {
434    SymtabSize *= sizeof(MachO::nlist_64);
435    struct_nlist_name = "struct nlist_64";
436  } else {
437    SymtabSize *= sizeof(MachO::nlist);
438    struct_nlist_name = "struct nlist";
439  }
440  uint64_t BigSize = SymtabSize;
441  BigSize += Symtab.symoff;
442  if (BigSize > FileSize)
443    return malformedError("symoff field plus nsyms field times sizeof(" +
444                          Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
445                          Twine(LoadCommandIndex) + " extends past the end "
446                          "of the file");
447  if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,
448                                          "symbol table"))
449    return Err;
450  if (Symtab.stroff > FileSize)
451    return malformedError("stroff field of LC_SYMTAB command " +
452                          Twine(LoadCommandIndex) + " extends past the end "
453                          "of the file");
454  BigSize = Symtab.stroff;
455  BigSize += Symtab.strsize;
456  if (BigSize > FileSize)
457    return malformedError("stroff field plus strsize field of LC_SYMTAB "
458                          "command " + Twine(LoadCommandIndex) + " extends "
459                          "past the end of the file");
460  if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,
461                                          Symtab.strsize, "string table"))
462    return Err;
463  *SymtabLoadCmd = Load.Ptr;
464  return Error::success();
465}
466
467static Error checkDysymtabCommand(const MachOObjectFile &Obj,
468                                  const MachOObjectFile::LoadCommandInfo &Load,
469                                  uint32_t LoadCommandIndex,
470                                  const char **DysymtabLoadCmd,
471                                  std::list<MachOElement> &Elements) {
472  if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))
473    return malformedError("load command " + Twine(LoadCommandIndex) +
474                          " LC_DYSYMTAB cmdsize too small");
475  if (*DysymtabLoadCmd != nullptr)
476    return malformedError("more than one LC_DYSYMTAB command");
477  auto DysymtabOrErr =
478    getStructOrErr<MachO::dysymtab_command>(Obj, Load.Ptr);
479  if (!DysymtabOrErr)
480    return DysymtabOrErr.takeError();
481  MachO::dysymtab_command Dysymtab = DysymtabOrErr.get();
482  if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))
483    return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +
484                          " has incorrect cmdsize");
485  uint64_t FileSize = Obj.getData().size();
486  if (Dysymtab.tocoff > FileSize)
487    return malformedError("tocoff field of LC_DYSYMTAB command " +
488                          Twine(LoadCommandIndex) + " extends past the end of "
489                          "the file");
490  uint64_t BigSize = Dysymtab.ntoc;
491  BigSize *= sizeof(MachO::dylib_table_of_contents);
492  BigSize += Dysymtab.tocoff;
493  if (BigSize > FileSize)
494    return malformedError("tocoff field plus ntoc field times sizeof(struct "
495                          "dylib_table_of_contents) of LC_DYSYMTAB command " +
496                          Twine(LoadCommandIndex) + " extends past the end of "
497                          "the file");
498  if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff,
499                                          Dysymtab.ntoc * sizeof(struct
500                                          MachO::dylib_table_of_contents),
501                                          "table of contents"))
502    return Err;
503  if (Dysymtab.modtaboff > FileSize)
504    return malformedError("modtaboff field of LC_DYSYMTAB command " +
505                          Twine(LoadCommandIndex) + " extends past the end of "
506                          "the file");
507  BigSize = Dysymtab.nmodtab;
508  const char *struct_dylib_module_name;
509  uint64_t sizeof_modtab;
510  if (Obj.is64Bit()) {
511    sizeof_modtab = sizeof(MachO::dylib_module_64);
512    struct_dylib_module_name = "struct dylib_module_64";
513  } else {
514    sizeof_modtab = sizeof(MachO::dylib_module);
515    struct_dylib_module_name = "struct dylib_module";
516  }
517  BigSize *= sizeof_modtab;
518  BigSize += Dysymtab.modtaboff;
519  if (BigSize > FileSize)
520    return malformedError("modtaboff field plus nmodtab field times sizeof(" +
521                          Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "
522                          "command " + Twine(LoadCommandIndex) + " extends "
523                          "past the end of the file");
524  if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff,
525                                          Dysymtab.nmodtab * sizeof_modtab,
526                                          "module table"))
527    return Err;
528  if (Dysymtab.extrefsymoff > FileSize)
529    return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
530                          Twine(LoadCommandIndex) + " extends past the end of "
531                          "the file");
532  BigSize = Dysymtab.nextrefsyms;
533  BigSize *= sizeof(MachO::dylib_reference);
534  BigSize += Dysymtab.extrefsymoff;
535  if (BigSize > FileSize)
536    return malformedError("extrefsymoff field plus nextrefsyms field times "
537                          "sizeof(struct dylib_reference) of LC_DYSYMTAB "
538                          "command " + Twine(LoadCommandIndex) + " extends "
539                          "past the end of the file");
540  if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff,
541                                          Dysymtab.nextrefsyms *
542                                              sizeof(MachO::dylib_reference),
543                                          "reference table"))
544    return Err;
545  if (Dysymtab.indirectsymoff > FileSize)
546    return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
547                          Twine(LoadCommandIndex) + " extends past the end of "
548                          "the file");
549  BigSize = Dysymtab.nindirectsyms;
550  BigSize *= sizeof(uint32_t);
551  BigSize += Dysymtab.indirectsymoff;
552  if (BigSize > FileSize)
553    return malformedError("indirectsymoff field plus nindirectsyms field times "
554                          "sizeof(uint32_t) of LC_DYSYMTAB command " +
555                          Twine(LoadCommandIndex) + " extends past the end of "
556                          "the file");
557  if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff,
558                                          Dysymtab.nindirectsyms *
559                                          sizeof(uint32_t),
560                                          "indirect table"))
561    return Err;
562  if (Dysymtab.extreloff > FileSize)
563    return malformedError("extreloff field of LC_DYSYMTAB command " +
564                          Twine(LoadCommandIndex) + " extends past the end of "
565                          "the file");
566  BigSize = Dysymtab.nextrel;
567  BigSize *= sizeof(MachO::relocation_info);
568  BigSize += Dysymtab.extreloff;
569  if (BigSize > FileSize)
570    return malformedError("extreloff field plus nextrel field times sizeof"
571                          "(struct relocation_info) of LC_DYSYMTAB command " +
572                          Twine(LoadCommandIndex) + " extends past the end of "
573                          "the file");
574  if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff,
575                                          Dysymtab.nextrel *
576                                              sizeof(MachO::relocation_info),
577                                          "external relocation table"))
578    return Err;
579  if (Dysymtab.locreloff > FileSize)
580    return malformedError("locreloff field of LC_DYSYMTAB command " +
581                          Twine(LoadCommandIndex) + " extends past the end of "
582                          "the file");
583  BigSize = Dysymtab.nlocrel;
584  BigSize *= sizeof(MachO::relocation_info);
585  BigSize += Dysymtab.locreloff;
586  if (BigSize > FileSize)
587    return malformedError("locreloff field plus nlocrel field times sizeof"
588                          "(struct relocation_info) of LC_DYSYMTAB command " +
589                          Twine(LoadCommandIndex) + " extends past the end of "
590                          "the file");
591  if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff,
592                                          Dysymtab.nlocrel *
593                                              sizeof(MachO::relocation_info),
594                                          "local relocation table"))
595    return Err;
596  *DysymtabLoadCmd = Load.Ptr;
597  return Error::success();
598}
599
600static Error checkLinkeditDataCommand(const MachOObjectFile &Obj,
601                                 const MachOObjectFile::LoadCommandInfo &Load,
602                                 uint32_t LoadCommandIndex,
603                                 const char **LoadCmd, const char *CmdName,
604                                 std::list<MachOElement> &Elements,
605                                 const char *ElementName) {
606  if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
607    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
608                          CmdName + " cmdsize too small");
609  if (*LoadCmd != nullptr)
610    return malformedError("more than one " + Twine(CmdName) + " command");
611  auto LinkDataOrError =
612    getStructOrErr<MachO::linkedit_data_command>(Obj, Load.Ptr);
613  if (!LinkDataOrError)
614    return LinkDataOrError.takeError();
615  MachO::linkedit_data_command LinkData = LinkDataOrError.get();
616  if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
617    return malformedError(Twine(CmdName) + " command " +
618                          Twine(LoadCommandIndex) + " has incorrect cmdsize");
619  uint64_t FileSize = Obj.getData().size();
620  if (LinkData.dataoff > FileSize)
621    return malformedError("dataoff field of " + Twine(CmdName) + " command " +
622                          Twine(LoadCommandIndex) + " extends past the end of "
623                          "the file");
624  uint64_t BigSize = LinkData.dataoff;
625  BigSize += LinkData.datasize;
626  if (BigSize > FileSize)
627    return malformedError("dataoff field plus datasize field of " +
628                          Twine(CmdName) + " command " +
629                          Twine(LoadCommandIndex) + " extends past the end of "
630                          "the file");
631  if (Error Err = checkOverlappingElement(Elements, LinkData.dataoff,
632                                          LinkData.datasize, ElementName))
633    return Err;
634  *LoadCmd = Load.Ptr;
635  return Error::success();
636}
637
638static Error checkDyldInfoCommand(const MachOObjectFile &Obj,
639                                  const MachOObjectFile::LoadCommandInfo &Load,
640                                  uint32_t LoadCommandIndex,
641                                  const char **LoadCmd, const char *CmdName,
642                                  std::list<MachOElement> &Elements) {
643  if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))
644    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
645                          CmdName + " cmdsize too small");
646  if (*LoadCmd != nullptr)
647    return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
648                          "command");
649  auto DyldInfoOrErr =
650    getStructOrErr<MachO::dyld_info_command>(Obj, Load.Ptr);
651  if (!DyldInfoOrErr)
652    return DyldInfoOrErr.takeError();
653  MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
654  if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))
655    return malformedError(Twine(CmdName) + " command " +
656                          Twine(LoadCommandIndex) + " has incorrect cmdsize");
657  uint64_t FileSize = Obj.getData().size();
658  if (DyldInfo.rebase_off > FileSize)
659    return malformedError("rebase_off field of " + Twine(CmdName) +
660                          " command " + Twine(LoadCommandIndex) + " extends "
661                          "past the end of the file");
662  uint64_t BigSize = DyldInfo.rebase_off;
663  BigSize += DyldInfo.rebase_size;
664  if (BigSize > FileSize)
665    return malformedError("rebase_off field plus rebase_size field of " +
666                          Twine(CmdName) + " command " +
667                          Twine(LoadCommandIndex) + " extends past the end of "
668                          "the file");
669  if (Error Err = checkOverlappingElement(Elements, DyldInfo.rebase_off,
670                                          DyldInfo.rebase_size,
671                                          "dyld rebase info"))
672    return Err;
673  if (DyldInfo.bind_off > FileSize)
674    return malformedError("bind_off field of " + Twine(CmdName) +
675                          " command " + Twine(LoadCommandIndex) + " extends "
676                          "past the end of the file");
677  BigSize = DyldInfo.bind_off;
678  BigSize += DyldInfo.bind_size;
679  if (BigSize > FileSize)
680    return malformedError("bind_off field plus bind_size field of " +
681                          Twine(CmdName) + " command " +
682                          Twine(LoadCommandIndex) + " extends past the end of "
683                          "the file");
684  if (Error Err = checkOverlappingElement(Elements, DyldInfo.bind_off,
685                                          DyldInfo.bind_size,
686                                          "dyld bind info"))
687    return Err;
688  if (DyldInfo.weak_bind_off > FileSize)
689    return malformedError("weak_bind_off field of " + Twine(CmdName) +
690                          " command " + Twine(LoadCommandIndex) + " extends "
691                          "past the end of the file");
692  BigSize = DyldInfo.weak_bind_off;
693  BigSize += DyldInfo.weak_bind_size;
694  if (BigSize > FileSize)
695    return malformedError("weak_bind_off field plus weak_bind_size field of " +
696                          Twine(CmdName) + " command " +
697                          Twine(LoadCommandIndex) + " extends past the end of "
698                          "the file");
699  if (Error Err = checkOverlappingElement(Elements, DyldInfo.weak_bind_off,
700                                          DyldInfo.weak_bind_size,
701                                          "dyld weak bind info"))
702    return Err;
703  if (DyldInfo.lazy_bind_off > FileSize)
704    return malformedError("lazy_bind_off field of " + Twine(CmdName) +
705                          " command " + Twine(LoadCommandIndex) + " extends "
706                          "past the end of the file");
707  BigSize = DyldInfo.lazy_bind_off;
708  BigSize += DyldInfo.lazy_bind_size;
709  if (BigSize > FileSize)
710    return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
711                          Twine(CmdName) + " command " +
712                          Twine(LoadCommandIndex) + " extends past the end of "
713                          "the file");
714  if (Error Err = checkOverlappingElement(Elements, DyldInfo.lazy_bind_off,
715                                          DyldInfo.lazy_bind_size,
716                                          "dyld lazy bind info"))
717    return Err;
718  if (DyldInfo.export_off > FileSize)
719    return malformedError("export_off field of " + Twine(CmdName) +
720                          " command " + Twine(LoadCommandIndex) + " extends "
721                          "past the end of the file");
722  BigSize = DyldInfo.export_off;
723  BigSize += DyldInfo.export_size;
724  if (BigSize > FileSize)
725    return malformedError("export_off field plus export_size field of " +
726                          Twine(CmdName) + " command " +
727                          Twine(LoadCommandIndex) + " extends past the end of "
728                          "the file");
729  if (Error Err = checkOverlappingElement(Elements, DyldInfo.export_off,
730                                          DyldInfo.export_size,
731                                          "dyld export info"))
732    return Err;
733  *LoadCmd = Load.Ptr;
734  return Error::success();
735}
736
737static Error checkDylibCommand(const MachOObjectFile &Obj,
738                               const MachOObjectFile::LoadCommandInfo &Load,
739                               uint32_t LoadCommandIndex, const char *CmdName) {
740  if (Load.C.cmdsize < sizeof(MachO::dylib_command))
741    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
742                          CmdName + " cmdsize too small");
743  auto CommandOrErr = getStructOrErr<MachO::dylib_command>(Obj, Load.Ptr);
744  if (!CommandOrErr)
745    return CommandOrErr.takeError();
746  MachO::dylib_command D = CommandOrErr.get();
747  if (D.dylib.name < sizeof(MachO::dylib_command))
748    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
749                          CmdName + " name.offset field too small, not past "
750                          "the end of the dylib_command struct");
751  if (D.dylib.name >= D.cmdsize)
752    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
753                          CmdName + " name.offset field extends past the end "
754                          "of the load command");
755  // Make sure there is a null between the starting offset of the name and
756  // the end of the load command.
757  uint32_t i;
758  const char *P = (const char *)Load.Ptr;
759  for (i = D.dylib.name; i < D.cmdsize; i++)
760    if (P[i] == '\0')
761      break;
762  if (i >= D.cmdsize)
763    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
764                          CmdName + " library name extends past the end of the "
765                          "load command");
766  return Error::success();
767}
768
769static Error checkDylibIdCommand(const MachOObjectFile &Obj,
770                                 const MachOObjectFile::LoadCommandInfo &Load,
771                                 uint32_t LoadCommandIndex,
772                                 const char **LoadCmd) {
773  if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,
774                                     "LC_ID_DYLIB"))
775    return Err;
776  if (*LoadCmd != nullptr)
777    return malformedError("more than one LC_ID_DYLIB command");
778  if (Obj.getHeader().filetype != MachO::MH_DYLIB &&
779      Obj.getHeader().filetype != MachO::MH_DYLIB_STUB)
780    return malformedError("LC_ID_DYLIB load command in non-dynamic library "
781                          "file type");
782  *LoadCmd = Load.Ptr;
783  return Error::success();
784}
785
786static Error checkDyldCommand(const MachOObjectFile &Obj,
787                              const MachOObjectFile::LoadCommandInfo &Load,
788                              uint32_t LoadCommandIndex, const char *CmdName) {
789  if (Load.C.cmdsize < sizeof(MachO::dylinker_command))
790    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
791                          CmdName + " cmdsize too small");
792  auto CommandOrErr = getStructOrErr<MachO::dylinker_command>(Obj, Load.Ptr);
793  if (!CommandOrErr)
794    return CommandOrErr.takeError();
795  MachO::dylinker_command D = CommandOrErr.get();
796  if (D.name < sizeof(MachO::dylinker_command))
797    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
798                          CmdName + " name.offset field too small, not past "
799                          "the end of the dylinker_command struct");
800  if (D.name >= D.cmdsize)
801    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
802                          CmdName + " name.offset field extends past the end "
803                          "of the load command");
804  // Make sure there is a null between the starting offset of the name and
805  // the end of the load command.
806  uint32_t i;
807  const char *P = (const char *)Load.Ptr;
808  for (i = D.name; i < D.cmdsize; i++)
809    if (P[i] == '\0')
810      break;
811  if (i >= D.cmdsize)
812    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
813                          CmdName + " dyld name extends past the end of the "
814                          "load command");
815  return Error::success();
816}
817
818static Error checkVersCommand(const MachOObjectFile &Obj,
819                              const MachOObjectFile::LoadCommandInfo &Load,
820                              uint32_t LoadCommandIndex,
821                              const char **LoadCmd, const char *CmdName) {
822  if (Load.C.cmdsize != sizeof(MachO::version_min_command))
823    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
824                          CmdName + " has incorrect cmdsize");
825  if (*LoadCmd != nullptr)
826    return malformedError("more than one LC_VERSION_MIN_MACOSX, "
827                          "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
828                          "LC_VERSION_MIN_WATCHOS command");
829  *LoadCmd = Load.Ptr;
830  return Error::success();
831}
832
833static Error checkNoteCommand(const MachOObjectFile &Obj,
834                              const MachOObjectFile::LoadCommandInfo &Load,
835                              uint32_t LoadCommandIndex,
836                              std::list<MachOElement> &Elements) {
837  if (Load.C.cmdsize != sizeof(MachO::note_command))
838    return malformedError("load command " + Twine(LoadCommandIndex) +
839                          " LC_NOTE has incorrect cmdsize");
840  auto NoteCmdOrErr = getStructOrErr<MachO::note_command>(Obj, Load.Ptr);
841  if (!NoteCmdOrErr)
842    return NoteCmdOrErr.takeError();
843  MachO::note_command Nt = NoteCmdOrErr.get();
844  uint64_t FileSize = Obj.getData().size();
845  if (Nt.offset > FileSize)
846    return malformedError("offset field of LC_NOTE command " +
847                          Twine(LoadCommandIndex) + " extends "
848                          "past the end of the file");
849  uint64_t BigSize = Nt.offset;
850  BigSize += Nt.size;
851  if (BigSize > FileSize)
852    return malformedError("size field plus offset field of LC_NOTE command " +
853                          Twine(LoadCommandIndex) + " extends past the end of "
854                          "the file");
855  if (Error Err = checkOverlappingElement(Elements, Nt.offset, Nt.size,
856                                          "LC_NOTE data"))
857    return Err;
858  return Error::success();
859}
860
861static Error
862parseBuildVersionCommand(const MachOObjectFile &Obj,
863                         const MachOObjectFile::LoadCommandInfo &Load,
864                         SmallVectorImpl<const char*> &BuildTools,
865                         uint32_t LoadCommandIndex) {
866  auto BVCOrErr =
867    getStructOrErr<MachO::build_version_command>(Obj, Load.Ptr);
868  if (!BVCOrErr)
869    return BVCOrErr.takeError();
870  MachO::build_version_command BVC = BVCOrErr.get();
871  if (Load.C.cmdsize !=
872      sizeof(MachO::build_version_command) +
873          BVC.ntools * sizeof(MachO::build_tool_version))
874    return malformedError("load command " + Twine(LoadCommandIndex) +
875                          " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
876
877  auto Start = Load.Ptr + sizeof(MachO::build_version_command);
878  BuildTools.resize(BVC.ntools);
879  for (unsigned i = 0; i < BVC.ntools; ++i)
880    BuildTools[i] = Start + i * sizeof(MachO::build_tool_version);
881
882  return Error::success();
883}
884
885static Error checkRpathCommand(const MachOObjectFile &Obj,
886                               const MachOObjectFile::LoadCommandInfo &Load,
887                               uint32_t LoadCommandIndex) {
888  if (Load.C.cmdsize < sizeof(MachO::rpath_command))
889    return malformedError("load command " + Twine(LoadCommandIndex) +
890                          " LC_RPATH cmdsize too small");
891  auto ROrErr = getStructOrErr<MachO::rpath_command>(Obj, Load.Ptr);
892  if (!ROrErr)
893    return ROrErr.takeError();
894  MachO::rpath_command R = ROrErr.get();
895  if (R.path < sizeof(MachO::rpath_command))
896    return malformedError("load command " + Twine(LoadCommandIndex) +
897                          " LC_RPATH path.offset field too small, not past "
898                          "the end of the rpath_command struct");
899  if (R.path >= R.cmdsize)
900    return malformedError("load command " + Twine(LoadCommandIndex) +
901                          " LC_RPATH path.offset field extends past the end "
902                          "of the load command");
903  // Make sure there is a null between the starting offset of the path and
904  // the end of the load command.
905  uint32_t i;
906  const char *P = (const char *)Load.Ptr;
907  for (i = R.path; i < R.cmdsize; i++)
908    if (P[i] == '\0')
909      break;
910  if (i >= R.cmdsize)
911    return malformedError("load command " + Twine(LoadCommandIndex) +
912                          " LC_RPATH library name extends past the end of the "
913                          "load command");
914  return Error::success();
915}
916
917static Error checkEncryptCommand(const MachOObjectFile &Obj,
918                                 const MachOObjectFile::LoadCommandInfo &Load,
919                                 uint32_t LoadCommandIndex,
920                                 uint64_t cryptoff, uint64_t cryptsize,
921                                 const char **LoadCmd, const char *CmdName) {
922  if (*LoadCmd != nullptr)
923    return malformedError("more than one LC_ENCRYPTION_INFO and or "
924                          "LC_ENCRYPTION_INFO_64 command");
925  uint64_t FileSize = Obj.getData().size();
926  if (cryptoff > FileSize)
927    return malformedError("cryptoff field of " + Twine(CmdName) +
928                          " command " + Twine(LoadCommandIndex) + " extends "
929                          "past the end of the file");
930  uint64_t BigSize = cryptoff;
931  BigSize += cryptsize;
932  if (BigSize > FileSize)
933    return malformedError("cryptoff field plus cryptsize field of " +
934                          Twine(CmdName) + " command " +
935                          Twine(LoadCommandIndex) + " extends past the end of "
936                          "the file");
937  *LoadCmd = Load.Ptr;
938  return Error::success();
939}
940
941static Error checkLinkerOptCommand(const MachOObjectFile &Obj,
942                                   const MachOObjectFile::LoadCommandInfo &Load,
943                                   uint32_t LoadCommandIndex) {
944  if (Load.C.cmdsize < sizeof(MachO::linker_option_command))
945    return malformedError("load command " + Twine(LoadCommandIndex) +
946                          " LC_LINKER_OPTION cmdsize too small");
947  auto LinkOptionOrErr =
948    getStructOrErr<MachO::linker_option_command>(Obj, Load.Ptr);
949  if (!LinkOptionOrErr)
950    return LinkOptionOrErr.takeError();
951  MachO::linker_option_command L = LinkOptionOrErr.get();
952  // Make sure the count of strings is correct.
953  const char *string = (const char *)Load.Ptr +
954                       sizeof(struct MachO::linker_option_command);
955  uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);
956  uint32_t i = 0;
957  while (left > 0) {
958    while (*string == '\0' && left > 0) {
959      string++;
960      left--;
961    }
962    if (left > 0) {
963      i++;
964      uint32_t NullPos = StringRef(string, left).find('\0');
965      if (0xffffffff == NullPos)
966        return malformedError("load command " + Twine(LoadCommandIndex) +
967                              " LC_LINKER_OPTION string #" + Twine(i) +
968                              " is not NULL terminated");
969      uint32_t len = std::min(NullPos, left) + 1;
970      string += len;
971      left -= len;
972    }
973  }
974  if (L.count != i)
975    return malformedError("load command " + Twine(LoadCommandIndex) +
976                          " LC_LINKER_OPTION string count " + Twine(L.count) +
977                          " does not match number of strings");
978  return Error::success();
979}
980
981static Error checkSubCommand(const MachOObjectFile &Obj,
982                             const MachOObjectFile::LoadCommandInfo &Load,
983                             uint32_t LoadCommandIndex, const char *CmdName,
984                             size_t SizeOfCmd, const char *CmdStructName,
985                             uint32_t PathOffset, const char *PathFieldName) {
986  if (PathOffset < SizeOfCmd)
987    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
988                          CmdName + " " + PathFieldName + ".offset field too "
989                          "small, not past the end of the " + CmdStructName);
990  if (PathOffset >= Load.C.cmdsize)
991    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
992                          CmdName + " " + PathFieldName + ".offset field "
993                          "extends past the end of the load command");
994  // Make sure there is a null between the starting offset of the path and
995  // the end of the load command.
996  uint32_t i;
997  const char *P = (const char *)Load.Ptr;
998  for (i = PathOffset; i < Load.C.cmdsize; i++)
999    if (P[i] == '\0')
1000      break;
1001  if (i >= Load.C.cmdsize)
1002    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
1003                          CmdName + " " + PathFieldName + " name extends past "
1004                          "the end of the load command");
1005  return Error::success();
1006}
1007
1008static Error checkThreadCommand(const MachOObjectFile &Obj,
1009                                const MachOObjectFile::LoadCommandInfo &Load,
1010                                uint32_t LoadCommandIndex,
1011                                const char *CmdName) {
1012  if (Load.C.cmdsize < sizeof(MachO::thread_command))
1013    return malformedError("load command " + Twine(LoadCommandIndex) +
1014                          CmdName + " cmdsize too small");
1015  auto ThreadCommandOrErr =
1016    getStructOrErr<MachO::thread_command>(Obj, Load.Ptr);
1017  if (!ThreadCommandOrErr)
1018    return ThreadCommandOrErr.takeError();
1019  MachO::thread_command T = ThreadCommandOrErr.get();
1020  const char *state = Load.Ptr + sizeof(MachO::thread_command);
1021  const char *end = Load.Ptr + T.cmdsize;
1022  uint32_t nflavor = 0;
1023  uint32_t cputype = getCPUType(Obj);
1024  while (state < end) {
1025    if(state + sizeof(uint32_t) > end)
1026      return malformedError("load command " + Twine(LoadCommandIndex) +
1027                            "flavor in " + CmdName + " extends past end of "
1028                            "command");
1029    uint32_t flavor;
1030    memcpy(&flavor, state, sizeof(uint32_t));
1031    if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
1032      sys::swapByteOrder(flavor);
1033    state += sizeof(uint32_t);
1034
1035    if(state + sizeof(uint32_t) > end)
1036      return malformedError("load command " + Twine(LoadCommandIndex) +
1037                            " count in " + CmdName + " extends past end of "
1038                            "command");
1039    uint32_t count;
1040    memcpy(&count, state, sizeof(uint32_t));
1041    if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
1042      sys::swapByteOrder(count);
1043    state += sizeof(uint32_t);
1044
1045    if (cputype == MachO::CPU_TYPE_I386) {
1046      if (flavor == MachO::x86_THREAD_STATE32) {
1047        if (count != MachO::x86_THREAD_STATE32_COUNT)
1048          return malformedError("load command " + Twine(LoadCommandIndex) +
1049                                " count not x86_THREAD_STATE32_COUNT for "
1050                                "flavor number " + Twine(nflavor) + " which is "
1051                                "a x86_THREAD_STATE32 flavor in " + CmdName +
1052                                " command");
1053        if (state + sizeof(MachO::x86_thread_state32_t) > end)
1054          return malformedError("load command " + Twine(LoadCommandIndex) +
1055                                " x86_THREAD_STATE32 extends past end of "
1056                                "command in " + CmdName + " command");
1057        state += sizeof(MachO::x86_thread_state32_t);
1058      } else {
1059        return malformedError("load command " + Twine(LoadCommandIndex) +
1060                              " unknown flavor (" + Twine(flavor) + ") for "
1061                              "flavor number " + Twine(nflavor) + " in " +
1062                              CmdName + " command");
1063      }
1064    } else if (cputype == MachO::CPU_TYPE_X86_64) {
1065      if (flavor == MachO::x86_THREAD_STATE) {
1066        if (count != MachO::x86_THREAD_STATE_COUNT)
1067          return malformedError("load command " + Twine(LoadCommandIndex) +
1068                                " count not x86_THREAD_STATE_COUNT for "
1069                                "flavor number " + Twine(nflavor) + " which is "
1070                                "a x86_THREAD_STATE flavor in " + CmdName +
1071                                " command");
1072        if (state + sizeof(MachO::x86_thread_state_t) > end)
1073          return malformedError("load command " + Twine(LoadCommandIndex) +
1074                                " x86_THREAD_STATE extends past end of "
1075                                "command in " + CmdName + " command");
1076        state += sizeof(MachO::x86_thread_state_t);
1077      } else if (flavor == MachO::x86_FLOAT_STATE) {
1078        if (count != MachO::x86_FLOAT_STATE_COUNT)
1079          return malformedError("load command " + Twine(LoadCommandIndex) +
1080                                " count not x86_FLOAT_STATE_COUNT for "
1081                                "flavor number " + Twine(nflavor) + " which is "
1082                                "a x86_FLOAT_STATE flavor in " + CmdName +
1083                                " command");
1084        if (state + sizeof(MachO::x86_float_state_t) > end)
1085          return malformedError("load command " + Twine(LoadCommandIndex) +
1086                                " x86_FLOAT_STATE extends past end of "
1087                                "command in " + CmdName + " command");
1088        state += sizeof(MachO::x86_float_state_t);
1089      } else if (flavor == MachO::x86_EXCEPTION_STATE) {
1090        if (count != MachO::x86_EXCEPTION_STATE_COUNT)
1091          return malformedError("load command " + Twine(LoadCommandIndex) +
1092                                " count not x86_EXCEPTION_STATE_COUNT for "
1093                                "flavor number " + Twine(nflavor) + " which is "
1094                                "a x86_EXCEPTION_STATE flavor in " + CmdName +
1095                                " command");
1096        if (state + sizeof(MachO::x86_exception_state_t) > end)
1097          return malformedError("load command " + Twine(LoadCommandIndex) +
1098                                " x86_EXCEPTION_STATE extends past end of "
1099                                "command in " + CmdName + " command");
1100        state += sizeof(MachO::x86_exception_state_t);
1101      } else if (flavor == MachO::x86_THREAD_STATE64) {
1102        if (count != MachO::x86_THREAD_STATE64_COUNT)
1103          return malformedError("load command " + Twine(LoadCommandIndex) +
1104                                " count not x86_THREAD_STATE64_COUNT for "
1105                                "flavor number " + Twine(nflavor) + " which is "
1106                                "a x86_THREAD_STATE64 flavor in " + CmdName +
1107                                " command");
1108        if (state + sizeof(MachO::x86_thread_state64_t) > end)
1109          return malformedError("load command " + Twine(LoadCommandIndex) +
1110                                " x86_THREAD_STATE64 extends past end of "
1111                                "command in " + CmdName + " command");
1112        state += sizeof(MachO::x86_thread_state64_t);
1113      } else if (flavor == MachO::x86_EXCEPTION_STATE64) {
1114        if (count != MachO::x86_EXCEPTION_STATE64_COUNT)
1115          return malformedError("load command " + Twine(LoadCommandIndex) +
1116                                " count not x86_EXCEPTION_STATE64_COUNT for "
1117                                "flavor number " + Twine(nflavor) + " which is "
1118                                "a x86_EXCEPTION_STATE64 flavor in " + CmdName +
1119                                " command");
1120        if (state + sizeof(MachO::x86_exception_state64_t) > end)
1121          return malformedError("load command " + Twine(LoadCommandIndex) +
1122                                " x86_EXCEPTION_STATE64 extends past end of "
1123                                "command in " + CmdName + " command");
1124        state += sizeof(MachO::x86_exception_state64_t);
1125      } else {
1126        return malformedError("load command " + Twine(LoadCommandIndex) +
1127                              " unknown flavor (" + Twine(flavor) + ") for "
1128                              "flavor number " + Twine(nflavor) + " in " +
1129                              CmdName + " command");
1130      }
1131    } else if (cputype == MachO::CPU_TYPE_ARM) {
1132      if (flavor == MachO::ARM_THREAD_STATE) {
1133        if (count != MachO::ARM_THREAD_STATE_COUNT)
1134          return malformedError("load command " + Twine(LoadCommandIndex) +
1135                                " count not ARM_THREAD_STATE_COUNT for "
1136                                "flavor number " + Twine(nflavor) + " which is "
1137                                "a ARM_THREAD_STATE flavor in " + CmdName +
1138                                " command");
1139        if (state + sizeof(MachO::arm_thread_state32_t) > end)
1140          return malformedError("load command " + Twine(LoadCommandIndex) +
1141                                " ARM_THREAD_STATE extends past end of "
1142                                "command in " + CmdName + " command");
1143        state += sizeof(MachO::arm_thread_state32_t);
1144      } else {
1145        return malformedError("load command " + Twine(LoadCommandIndex) +
1146                              " unknown flavor (" + Twine(flavor) + ") for "
1147                              "flavor number " + Twine(nflavor) + " in " +
1148                              CmdName + " command");
1149      }
1150    } else if (cputype == MachO::CPU_TYPE_ARM64 ||
1151               cputype == MachO::CPU_TYPE_ARM64_32) {
1152      if (flavor == MachO::ARM_THREAD_STATE64) {
1153        if (count != MachO::ARM_THREAD_STATE64_COUNT)
1154          return malformedError("load command " + Twine(LoadCommandIndex) +
1155                                " count not ARM_THREAD_STATE64_COUNT for "
1156                                "flavor number " + Twine(nflavor) + " which is "
1157                                "a ARM_THREAD_STATE64 flavor in " + CmdName +
1158                                " command");
1159        if (state + sizeof(MachO::arm_thread_state64_t) > end)
1160          return malformedError("load command " + Twine(LoadCommandIndex) +
1161                                " ARM_THREAD_STATE64 extends past end of "
1162                                "command in " + CmdName + " command");
1163        state += sizeof(MachO::arm_thread_state64_t);
1164      } else {
1165        return malformedError("load command " + Twine(LoadCommandIndex) +
1166                              " unknown flavor (" + Twine(flavor) + ") for "
1167                              "flavor number " + Twine(nflavor) + " in " +
1168                              CmdName + " command");
1169      }
1170    } else if (cputype == MachO::CPU_TYPE_POWERPC) {
1171      if (flavor == MachO::PPC_THREAD_STATE) {
1172        if (count != MachO::PPC_THREAD_STATE_COUNT)
1173          return malformedError("load command " + Twine(LoadCommandIndex) +
1174                                " count not PPC_THREAD_STATE_COUNT for "
1175                                "flavor number " + Twine(nflavor) + " which is "
1176                                "a PPC_THREAD_STATE flavor in " + CmdName +
1177                                " command");
1178        if (state + sizeof(MachO::ppc_thread_state32_t) > end)
1179          return malformedError("load command " + Twine(LoadCommandIndex) +
1180                                " PPC_THREAD_STATE extends past end of "
1181                                "command in " + CmdName + " command");
1182        state += sizeof(MachO::ppc_thread_state32_t);
1183      } else {
1184        return malformedError("load command " + Twine(LoadCommandIndex) +
1185                              " unknown flavor (" + Twine(flavor) + ") for "
1186                              "flavor number " + Twine(nflavor) + " in " +
1187                              CmdName + " command");
1188      }
1189    } else {
1190      return malformedError("unknown cputype (" + Twine(cputype) + ") load "
1191                            "command " + Twine(LoadCommandIndex) + " for " +
1192                            CmdName + " command can't be checked");
1193    }
1194    nflavor++;
1195  }
1196  return Error::success();
1197}
1198
1199static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj,
1200                                       const MachOObjectFile::LoadCommandInfo
1201                                         &Load,
1202                                       uint32_t LoadCommandIndex,
1203                                       const char **LoadCmd,
1204                                       std::list<MachOElement> &Elements) {
1205  if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
1206    return malformedError("load command " + Twine(LoadCommandIndex) +
1207                          " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1208  if (*LoadCmd != nullptr)
1209    return malformedError("more than one LC_TWOLEVEL_HINTS command");
1210  auto HintsOrErr = getStructOrErr<MachO::twolevel_hints_command>(Obj, Load.Ptr);
1211  if(!HintsOrErr)
1212    return HintsOrErr.takeError();
1213  MachO::twolevel_hints_command Hints = HintsOrErr.get();
1214  uint64_t FileSize = Obj.getData().size();
1215  if (Hints.offset > FileSize)
1216    return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1217                          Twine(LoadCommandIndex) + " extends past the end of "
1218                          "the file");
1219  uint64_t BigSize = Hints.nhints;
1220  BigSize *= sizeof(MachO::twolevel_hint);
1221  BigSize += Hints.offset;
1222  if (BigSize > FileSize)
1223    return malformedError("offset field plus nhints times sizeof(struct "
1224                          "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1225                          Twine(LoadCommandIndex) + " extends past the end of "
1226                          "the file");
1227  if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints *
1228                                          sizeof(MachO::twolevel_hint),
1229                                          "two level hints"))
1230    return Err;
1231  *LoadCmd = Load.Ptr;
1232  return Error::success();
1233}
1234
1235// Returns true if the libObject code does not support the load command and its
1236// contents.  The cmd value it is treated as an unknown load command but with
1237// an error message that says the cmd value is obsolete.
1238static bool isLoadCommandObsolete(uint32_t cmd) {
1239  if (cmd == MachO::LC_SYMSEG ||
1240      cmd == MachO::LC_LOADFVMLIB ||
1241      cmd == MachO::LC_IDFVMLIB ||
1242      cmd == MachO::LC_IDENT ||
1243      cmd == MachO::LC_FVMFILE ||
1244      cmd == MachO::LC_PREPAGE ||
1245      cmd == MachO::LC_PREBOUND_DYLIB ||
1246      cmd == MachO::LC_TWOLEVEL_HINTS ||
1247      cmd == MachO::LC_PREBIND_CKSUM)
1248    return true;
1249  return false;
1250}
1251
1252Expected<std::unique_ptr<MachOObjectFile>>
1253MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
1254                        bool Is64Bits, uint32_t UniversalCputype,
1255                        uint32_t UniversalIndex,
1256                        size_t MachOFilesetEntryOffset) {
1257  Error Err = Error::success();
1258  std::unique_ptr<MachOObjectFile> Obj(new MachOObjectFile(
1259      std::move(Object), IsLittleEndian, Is64Bits, Err, UniversalCputype,
1260      UniversalIndex, MachOFilesetEntryOffset));
1261  if (Err)
1262    return std::move(Err);
1263  return std::move(Obj);
1264}
1265
1266MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
1267                                 bool Is64bits, Error &Err,
1268                                 uint32_t UniversalCputype,
1269                                 uint32_t UniversalIndex,
1270                                 size_t MachOFilesetEntryOffset)
1271    : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
1272      MachOFilesetEntryOffset(MachOFilesetEntryOffset) {
1273  ErrorAsOutParameter ErrAsOutParam(&Err);
1274  uint64_t SizeOfHeaders;
1275  uint32_t cputype;
1276  if (is64Bit()) {
1277    parseHeader(*this, Header64, Err);
1278    SizeOfHeaders = sizeof(MachO::mach_header_64);
1279    cputype = Header64.cputype;
1280  } else {
1281    parseHeader(*this, Header, Err);
1282    SizeOfHeaders = sizeof(MachO::mach_header);
1283    cputype = Header.cputype;
1284  }
1285  if (Err)
1286    return;
1287  SizeOfHeaders += getHeader().sizeofcmds;
1288  if (getData().data() + SizeOfHeaders > getData().end()) {
1289    Err = malformedError("load commands extend past the end of the file");
1290    return;
1291  }
1292  if (UniversalCputype != 0 && cputype != UniversalCputype) {
1293    Err = malformedError("universal header architecture: " +
1294                         Twine(UniversalIndex) + "'s cputype does not match "
1295                         "object file's mach header");
1296    return;
1297  }
1298  std::list<MachOElement> Elements;
1299  Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
1300
1301  uint32_t LoadCommandCount = getHeader().ncmds;
1302  LoadCommandInfo Load;
1303  if (LoadCommandCount != 0) {
1304    if (auto LoadOrErr = getFirstLoadCommandInfo(*this))
1305      Load = *LoadOrErr;
1306    else {
1307      Err = LoadOrErr.takeError();
1308      return;
1309    }
1310  }
1311
1312  const char *DyldIdLoadCmd = nullptr;
1313  const char *SplitInfoLoadCmd = nullptr;
1314  const char *CodeSignDrsLoadCmd = nullptr;
1315  const char *CodeSignLoadCmd = nullptr;
1316  const char *VersLoadCmd = nullptr;
1317  const char *SourceLoadCmd = nullptr;
1318  const char *EntryPointLoadCmd = nullptr;
1319  const char *EncryptLoadCmd = nullptr;
1320  const char *RoutinesLoadCmd = nullptr;
1321  const char *UnixThreadLoadCmd = nullptr;
1322  const char *TwoLevelHintsLoadCmd = nullptr;
1323  for (unsigned I = 0; I < LoadCommandCount; ++I) {
1324    if (is64Bit()) {
1325      if (Load.C.cmdsize % 8 != 0) {
1326        // We have a hack here to allow 64-bit Mach-O core files to have
1327        // LC_THREAD commands that are only a multiple of 4 and not 8 to be
1328        // allowed since the macOS kernel produces them.
1329        if (getHeader().filetype != MachO::MH_CORE ||
1330            Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) {
1331          Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1332                               "multiple of 8");
1333          return;
1334        }
1335      }
1336    } else {
1337      if (Load.C.cmdsize % 4 != 0) {
1338        Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1339                             "multiple of 4");
1340        return;
1341      }
1342    }
1343    LoadCommands.push_back(Load);
1344    if (Load.C.cmd == MachO::LC_SYMTAB) {
1345      if ((Err = checkSymtabCommand(*this, Load, I, &SymtabLoadCmd, Elements)))
1346        return;
1347    } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
1348      if ((Err = checkDysymtabCommand(*this, Load, I, &DysymtabLoadCmd,
1349                                      Elements)))
1350        return;
1351    } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
1352      if ((Err = checkLinkeditDataCommand(*this, Load, I, &DataInCodeLoadCmd,
1353                                          "LC_DATA_IN_CODE", Elements,
1354                                          "data in code info")))
1355        return;
1356    } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
1357      if ((Err = checkLinkeditDataCommand(*this, Load, I, &LinkOptHintsLoadCmd,
1358                                          "LC_LINKER_OPTIMIZATION_HINT",
1359                                          Elements, "linker optimization "
1360                                          "hints")))
1361        return;
1362    } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
1363      if ((Err = checkLinkeditDataCommand(*this, Load, I, &FuncStartsLoadCmd,
1364                                          "LC_FUNCTION_STARTS", Elements,
1365                                          "function starts data")))
1366        return;
1367    } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
1368      if ((Err = checkLinkeditDataCommand(*this, Load, I, &SplitInfoLoadCmd,
1369                                          "LC_SEGMENT_SPLIT_INFO", Elements,
1370                                          "split info data")))
1371        return;
1372    } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
1373      if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignDrsLoadCmd,
1374                                          "LC_DYLIB_CODE_SIGN_DRS", Elements,
1375                                          "code signing RDs data")))
1376        return;
1377    } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
1378      if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignLoadCmd,
1379                                          "LC_CODE_SIGNATURE", Elements,
1380                                          "code signature data")))
1381        return;
1382    } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
1383      if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
1384                                      "LC_DYLD_INFO", Elements)))
1385        return;
1386    } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
1387      if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
1388                                      "LC_DYLD_INFO_ONLY", Elements)))
1389        return;
1390    } else if (Load.C.cmd == MachO::LC_DYLD_CHAINED_FIXUPS) {
1391      if ((Err = checkLinkeditDataCommand(
1392               *this, Load, I, &DyldChainedFixupsLoadCmd,
1393               "LC_DYLD_CHAINED_FIXUPS", Elements, "chained fixups")))
1394        return;
1395    } else if (Load.C.cmd == MachO::LC_DYLD_EXPORTS_TRIE) {
1396      if ((Err = checkLinkeditDataCommand(
1397               *this, Load, I, &DyldExportsTrieLoadCmd, "LC_DYLD_EXPORTS_TRIE",
1398               Elements, "exports trie")))
1399        return;
1400    } else if (Load.C.cmd == MachO::LC_UUID) {
1401      if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
1402        Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
1403                             "cmdsize");
1404        return;
1405      }
1406      if (UuidLoadCmd) {
1407        Err = malformedError("more than one LC_UUID command");
1408        return;
1409      }
1410      UuidLoadCmd = Load.Ptr;
1411    } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
1412      if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
1413                                         MachO::section_64>(
1414                   *this, Load, Sections, HasPageZeroSegment, I,
1415                   "LC_SEGMENT_64", SizeOfHeaders, Elements)))
1416        return;
1417    } else if (Load.C.cmd == MachO::LC_SEGMENT) {
1418      if ((Err = parseSegmentLoadCommand<MachO::segment_command,
1419                                         MachO::section>(
1420                   *this, Load, Sections, HasPageZeroSegment, I,
1421                   "LC_SEGMENT", SizeOfHeaders, Elements)))
1422        return;
1423    } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
1424      if ((Err = checkDylibIdCommand(*this, Load, I, &DyldIdLoadCmd)))
1425        return;
1426    } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
1427      if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_DYLIB")))
1428        return;
1429      Libraries.push_back(Load.Ptr);
1430    } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
1431      if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_WEAK_DYLIB")))
1432        return;
1433      Libraries.push_back(Load.Ptr);
1434    } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
1435      if ((Err = checkDylibCommand(*this, Load, I, "LC_LAZY_LOAD_DYLIB")))
1436        return;
1437      Libraries.push_back(Load.Ptr);
1438    } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
1439      if ((Err = checkDylibCommand(*this, Load, I, "LC_REEXPORT_DYLIB")))
1440        return;
1441      Libraries.push_back(Load.Ptr);
1442    } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
1443      if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
1444        return;
1445      Libraries.push_back(Load.Ptr);
1446    } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
1447      if ((Err = checkDyldCommand(*this, Load, I, "LC_ID_DYLINKER")))
1448        return;
1449    } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
1450      if ((Err = checkDyldCommand(*this, Load, I, "LC_LOAD_DYLINKER")))
1451        return;
1452    } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
1453      if ((Err = checkDyldCommand(*this, Load, I, "LC_DYLD_ENVIRONMENT")))
1454        return;
1455    } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
1456      if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1457                                  "LC_VERSION_MIN_MACOSX")))
1458        return;
1459    } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
1460      if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1461                                  "LC_VERSION_MIN_IPHONEOS")))
1462        return;
1463    } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
1464      if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1465                                  "LC_VERSION_MIN_TVOS")))
1466        return;
1467    } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
1468      if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1469                                  "LC_VERSION_MIN_WATCHOS")))
1470        return;
1471    } else if (Load.C.cmd == MachO::LC_NOTE) {
1472      if ((Err = checkNoteCommand(*this, Load, I, Elements)))
1473        return;
1474    } else if (Load.C.cmd == MachO::LC_BUILD_VERSION) {
1475      if ((Err = parseBuildVersionCommand(*this, Load, BuildTools, I)))
1476        return;
1477    } else if (Load.C.cmd == MachO::LC_RPATH) {
1478      if ((Err = checkRpathCommand(*this, Load, I)))
1479        return;
1480    } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
1481      if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
1482        Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
1483                             " has incorrect cmdsize");
1484        return;
1485      }
1486      if (SourceLoadCmd) {
1487        Err = malformedError("more than one LC_SOURCE_VERSION command");
1488        return;
1489      }
1490      SourceLoadCmd = Load.Ptr;
1491    } else if (Load.C.cmd == MachO::LC_MAIN) {
1492      if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
1493        Err = malformedError("LC_MAIN command " + Twine(I) +
1494                             " has incorrect cmdsize");
1495        return;
1496      }
1497      if (EntryPointLoadCmd) {
1498        Err = malformedError("more than one LC_MAIN command");
1499        return;
1500      }
1501      EntryPointLoadCmd = Load.Ptr;
1502    } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) {
1503      if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
1504        Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
1505                             " has incorrect cmdsize");
1506        return;
1507      }
1508      MachO::encryption_info_command E =
1509        getStruct<MachO::encryption_info_command>(*this, Load.Ptr);
1510      if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
1511                                     &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
1512        return;
1513    } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
1514      if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
1515        Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
1516                             " has incorrect cmdsize");
1517        return;
1518      }
1519      MachO::encryption_info_command_64 E =
1520        getStruct<MachO::encryption_info_command_64>(*this, Load.Ptr);
1521      if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
1522                                     &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
1523        return;
1524    } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
1525      if ((Err = checkLinkerOptCommand(*this, Load, I)))
1526        return;
1527    } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
1528      if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
1529        Err =  malformedError("load command " + Twine(I) +
1530                              " LC_SUB_FRAMEWORK cmdsize too small");
1531        return;
1532      }
1533      MachO::sub_framework_command S =
1534        getStruct<MachO::sub_framework_command>(*this, Load.Ptr);
1535      if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_FRAMEWORK",
1536                                 sizeof(MachO::sub_framework_command),
1537                                 "sub_framework_command", S.umbrella,
1538                                 "umbrella")))
1539        return;
1540    } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
1541      if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
1542        Err =  malformedError("load command " + Twine(I) +
1543                              " LC_SUB_UMBRELLA cmdsize too small");
1544        return;
1545      }
1546      MachO::sub_umbrella_command S =
1547        getStruct<MachO::sub_umbrella_command>(*this, Load.Ptr);
1548      if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_UMBRELLA",
1549                                 sizeof(MachO::sub_umbrella_command),
1550                                 "sub_umbrella_command", S.sub_umbrella,
1551                                 "sub_umbrella")))
1552        return;
1553    } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
1554      if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
1555        Err =  malformedError("load command " + Twine(I) +
1556                              " LC_SUB_LIBRARY cmdsize too small");
1557        return;
1558      }
1559      MachO::sub_library_command S =
1560        getStruct<MachO::sub_library_command>(*this, Load.Ptr);
1561      if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_LIBRARY",
1562                                 sizeof(MachO::sub_library_command),
1563                                 "sub_library_command", S.sub_library,
1564                                 "sub_library")))
1565        return;
1566    } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
1567      if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
1568        Err =  malformedError("load command " + Twine(I) +
1569                              " LC_SUB_CLIENT cmdsize too small");
1570        return;
1571      }
1572      MachO::sub_client_command S =
1573        getStruct<MachO::sub_client_command>(*this, Load.Ptr);
1574      if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_CLIENT",
1575                                 sizeof(MachO::sub_client_command),
1576                                 "sub_client_command", S.client, "client")))
1577        return;
1578    } else if (Load.C.cmd == MachO::LC_ROUTINES) {
1579      if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
1580        Err = malformedError("LC_ROUTINES command " + Twine(I) +
1581                             " has incorrect cmdsize");
1582        return;
1583      }
1584      if (RoutinesLoadCmd) {
1585        Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1586                             "command");
1587        return;
1588      }
1589      RoutinesLoadCmd = Load.Ptr;
1590    } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
1591      if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
1592        Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
1593                             " has incorrect cmdsize");
1594        return;
1595      }
1596      if (RoutinesLoadCmd) {
1597        Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1598                             "command");
1599        return;
1600      }
1601      RoutinesLoadCmd = Load.Ptr;
1602    } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
1603      if ((Err = checkThreadCommand(*this, Load, I, "LC_UNIXTHREAD")))
1604        return;
1605      if (UnixThreadLoadCmd) {
1606        Err = malformedError("more than one LC_UNIXTHREAD command");
1607        return;
1608      }
1609      UnixThreadLoadCmd = Load.Ptr;
1610    } else if (Load.C.cmd == MachO::LC_THREAD) {
1611      if ((Err = checkThreadCommand(*this, Load, I, "LC_THREAD")))
1612        return;
1613    // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
1614    } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
1615      if ((Err = checkTwoLevelHintsCommand(*this, Load, I,
1616                                           &TwoLevelHintsLoadCmd, Elements)))
1617        return;
1618    } else if (Load.C.cmd == MachO::LC_IDENT) {
1619      // Note: LC_IDENT is ignored.
1620      continue;
1621    } else if (isLoadCommandObsolete(Load.C.cmd)) {
1622      Err = malformedError("load command " + Twine(I) + " for cmd value of: " +
1623                           Twine(Load.C.cmd) + " is obsolete and not "
1624                           "supported");
1625      return;
1626    }
1627    // TODO: generate a error for unknown load commands by default.  But still
1628    // need work out an approach to allow or not allow unknown values like this
1629    // as an option for some uses like lldb.
1630    if (I < LoadCommandCount - 1) {
1631      if (auto LoadOrErr = getNextLoadCommandInfo(*this, I, Load))
1632        Load = *LoadOrErr;
1633      else {
1634        Err = LoadOrErr.takeError();
1635        return;
1636      }
1637    }
1638  }
1639  if (!SymtabLoadCmd) {
1640    if (DysymtabLoadCmd) {
1641      Err = malformedError("contains LC_DYSYMTAB load command without a "
1642                           "LC_SYMTAB load command");
1643      return;
1644    }
1645  } else if (DysymtabLoadCmd) {
1646    MachO::symtab_command Symtab =
1647      getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
1648    MachO::dysymtab_command Dysymtab =
1649      getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
1650    if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
1651      Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
1652                           "extends past the end of the symbol table");
1653      return;
1654    }
1655    uint64_t BigSize = Dysymtab.ilocalsym;
1656    BigSize += Dysymtab.nlocalsym;
1657    if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) {
1658      Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
1659                           "command extends past the end of the symbol table");
1660      return;
1661    }
1662    if (Dysymtab.nextdefsym != 0 && Dysymtab.iextdefsym > Symtab.nsyms) {
1663      Err = malformedError("iextdefsym in LC_DYSYMTAB load command "
1664                           "extends past the end of the symbol table");
1665      return;
1666    }
1667    BigSize = Dysymtab.iextdefsym;
1668    BigSize += Dysymtab.nextdefsym;
1669    if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) {
1670      Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
1671                           "load command extends past the end of the symbol "
1672                           "table");
1673      return;
1674    }
1675    if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
1676      Err = malformedError("iundefsym in LC_DYSYMTAB load command "
1677                           "extends past the end of the symbol table");
1678      return;
1679    }
1680    BigSize = Dysymtab.iundefsym;
1681    BigSize += Dysymtab.nundefsym;
1682    if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) {
1683      Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
1684                           " command extends past the end of the symbol table");
1685      return;
1686    }
1687  }
1688  if ((getHeader().filetype == MachO::MH_DYLIB ||
1689       getHeader().filetype == MachO::MH_DYLIB_STUB) &&
1690       DyldIdLoadCmd == nullptr) {
1691    Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
1692                         "filetype");
1693    return;
1694  }
1695  assert(LoadCommands.size() == LoadCommandCount);
1696
1697  Err = Error::success();
1698}
1699
1700Error MachOObjectFile::checkSymbolTable() const {
1701  uint32_t Flags = 0;
1702  if (is64Bit()) {
1703    MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64();
1704    Flags = H_64.flags;
1705  } else {
1706    MachO::mach_header H = MachOObjectFile::getHeader();
1707    Flags = H.flags;
1708  }
1709  uint8_t NType = 0;
1710  uint8_t NSect = 0;
1711  uint16_t NDesc = 0;
1712  uint32_t NStrx = 0;
1713  uint64_t NValue = 0;
1714  uint32_t SymbolIndex = 0;
1715  MachO::symtab_command S = getSymtabLoadCommand();
1716  for (const SymbolRef &Symbol : symbols()) {
1717    DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
1718    if (is64Bit()) {
1719      MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI);
1720      NType = STE_64.n_type;
1721      NSect = STE_64.n_sect;
1722      NDesc = STE_64.n_desc;
1723      NStrx = STE_64.n_strx;
1724      NValue = STE_64.n_value;
1725    } else {
1726      MachO::nlist STE = getSymbolTableEntry(SymDRI);
1727      NType = STE.n_type;
1728      NSect = STE.n_sect;
1729      NDesc = STE.n_desc;
1730      NStrx = STE.n_strx;
1731      NValue = STE.n_value;
1732    }
1733    if ((NType & MachO::N_STAB) == 0) {
1734      if ((NType & MachO::N_TYPE) == MachO::N_SECT) {
1735        if (NSect == 0 || NSect > Sections.size())
1736          return malformedError("bad section index: " + Twine((int)NSect) +
1737                                " for symbol at index " + Twine(SymbolIndex));
1738      }
1739      if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
1740        if (NValue >= S.strsize)
1741          return malformedError("bad n_value: " + Twine((int)NValue) + " past "
1742                                "the end of string table, for N_INDR symbol at "
1743                                "index " + Twine(SymbolIndex));
1744      }
1745      if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
1746          (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
1747           (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
1748            uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
1749            if (LibraryOrdinal != 0 &&
1750                LibraryOrdinal != MachO::EXECUTABLE_ORDINAL &&
1751                LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL &&
1752                LibraryOrdinal - 1 >= Libraries.size() ) {
1753              return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) +
1754                                    " for symbol at index " + Twine(SymbolIndex));
1755            }
1756          }
1757    }
1758    if (NStrx >= S.strsize)
1759      return malformedError("bad string table index: " + Twine((int)NStrx) +
1760                            " past the end of string table, for symbol at "
1761                            "index " + Twine(SymbolIndex));
1762    SymbolIndex++;
1763  }
1764  return Error::success();
1765}
1766
1767void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
1768  unsigned SymbolTableEntrySize = is64Bit() ?
1769    sizeof(MachO::nlist_64) :
1770    sizeof(MachO::nlist);
1771  Symb.p += SymbolTableEntrySize;
1772}
1773
1774Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
1775  StringRef StringTable = getStringTableData();
1776  MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1777  if (Entry.n_strx == 0)
1778    // A n_strx value of 0 indicates that no name is associated with a
1779    // particular symbol table entry.
1780    return StringRef();
1781  const char *Start = &StringTable.data()[Entry.n_strx];
1782  if (Start < getData().begin() || Start >= getData().end()) {
1783    return malformedError("bad string index: " + Twine(Entry.n_strx) +
1784                          " for symbol at index " + Twine(getSymbolIndex(Symb)));
1785  }
1786  return StringRef(Start);
1787}
1788
1789unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
1790  DataRefImpl DRI = Sec.getRawDataRefImpl();
1791  uint32_t Flags = getSectionFlags(*this, DRI);
1792  return Flags & MachO::SECTION_TYPE;
1793}
1794
1795uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
1796  if (is64Bit()) {
1797    MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
1798    return Entry.n_value;
1799  }
1800  MachO::nlist Entry = getSymbolTableEntry(Sym);
1801  return Entry.n_value;
1802}
1803
1804// getIndirectName() returns the name of the alias'ed symbol who's string table
1805// index is in the n_value field.
1806std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
1807                                                 StringRef &Res) const {
1808  StringRef StringTable = getStringTableData();
1809  MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1810  if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
1811    return object_error::parse_failed;
1812  uint64_t NValue = getNValue(Symb);
1813  if (NValue >= StringTable.size())
1814    return object_error::parse_failed;
1815  const char *Start = &StringTable.data()[NValue];
1816  Res = StringRef(Start);
1817  return std::error_code();
1818}
1819
1820uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
1821  return getNValue(Sym);
1822}
1823
1824Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
1825  return getSymbolValue(Sym);
1826}
1827
1828uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
1829  uint32_t Flags = cantFail(getSymbolFlags(DRI));
1830  if (Flags & SymbolRef::SF_Common) {
1831    MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
1832    return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
1833  }
1834  return 0;
1835}
1836
1837uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
1838  return getNValue(DRI);
1839}
1840
1841Expected<SymbolRef::Type>
1842MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
1843  MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1844  uint8_t n_type = Entry.n_type;
1845
1846  // If this is a STAB debugging symbol, we can do nothing more.
1847  if (n_type & MachO::N_STAB)
1848    return SymbolRef::ST_Debug;
1849
1850  switch (n_type & MachO::N_TYPE) {
1851    case MachO::N_UNDF :
1852      return SymbolRef::ST_Unknown;
1853    case MachO::N_SECT :
1854      Expected<section_iterator> SecOrError = getSymbolSection(Symb);
1855      if (!SecOrError)
1856        return SecOrError.takeError();
1857      section_iterator Sec = *SecOrError;
1858      if (Sec == section_end())
1859        return SymbolRef::ST_Other;
1860      if (Sec->isData() || Sec->isBSS())
1861        return SymbolRef::ST_Data;
1862      return SymbolRef::ST_Function;
1863  }
1864  return SymbolRef::ST_Other;
1865}
1866
1867Expected<uint32_t> MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
1868  MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
1869
1870  uint8_t MachOType = Entry.n_type;
1871  uint16_t MachOFlags = Entry.n_desc;
1872
1873  uint32_t Result = SymbolRef::SF_None;
1874
1875  if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
1876    Result |= SymbolRef::SF_Indirect;
1877
1878  if (MachOType & MachO::N_STAB)
1879    Result |= SymbolRef::SF_FormatSpecific;
1880
1881  if (MachOType & MachO::N_EXT) {
1882    Result |= SymbolRef::SF_Global;
1883    if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
1884      if (getNValue(DRI))
1885        Result |= SymbolRef::SF_Common;
1886      else
1887        Result |= SymbolRef::SF_Undefined;
1888    }
1889
1890    if (MachOType & MachO::N_PEXT)
1891      Result |= SymbolRef::SF_Hidden;
1892    else
1893      Result |= SymbolRef::SF_Exported;
1894
1895  } else if (MachOType & MachO::N_PEXT)
1896    Result |= SymbolRef::SF_Hidden;
1897
1898  if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
1899    Result |= SymbolRef::SF_Weak;
1900
1901  if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
1902    Result |= SymbolRef::SF_Thumb;
1903
1904  if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
1905    Result |= SymbolRef::SF_Absolute;
1906
1907  return Result;
1908}
1909
1910Expected<section_iterator>
1911MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
1912  MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1913  uint8_t index = Entry.n_sect;
1914
1915  if (index == 0)
1916    return section_end();
1917  DataRefImpl DRI;
1918  DRI.d.a = index - 1;
1919  if (DRI.d.a >= Sections.size()){
1920    return malformedError("bad section index: " + Twine((int)index) +
1921                          " for symbol at index " + Twine(getSymbolIndex(Symb)));
1922  }
1923  return section_iterator(SectionRef(DRI, this));
1924}
1925
1926unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
1927  MachO::nlist_base Entry =
1928      getSymbolTableEntryBase(*this, Sym.getRawDataRefImpl());
1929  return Entry.n_sect - 1;
1930}
1931
1932void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
1933  Sec.d.a++;
1934}
1935
1936Expected<StringRef> MachOObjectFile::getSectionName(DataRefImpl Sec) const {
1937  ArrayRef<char> Raw = getSectionRawName(Sec);
1938  return parseSegmentOrSectionName(Raw.data());
1939}
1940
1941uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
1942  if (is64Bit())
1943    return getSection64(Sec).addr;
1944  return getSection(Sec).addr;
1945}
1946
1947uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
1948  return Sec.d.a;
1949}
1950
1951uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
1952  // In the case if a malformed Mach-O file where the section offset is past
1953  // the end of the file or some part of the section size is past the end of
1954  // the file return a size of zero or a size that covers the rest of the file
1955  // but does not extend past the end of the file.
1956  uint32_t SectOffset, SectType;
1957  uint64_t SectSize;
1958
1959  if (is64Bit()) {
1960    MachO::section_64 Sect = getSection64(Sec);
1961    SectOffset = Sect.offset;
1962    SectSize = Sect.size;
1963    SectType = Sect.flags & MachO::SECTION_TYPE;
1964  } else {
1965    MachO::section Sect = getSection(Sec);
1966    SectOffset = Sect.offset;
1967    SectSize = Sect.size;
1968    SectType = Sect.flags & MachO::SECTION_TYPE;
1969  }
1970  if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
1971    return SectSize;
1972  uint64_t FileSize = getData().size();
1973  if (SectOffset > FileSize)
1974    return 0;
1975  if (FileSize - SectOffset < SectSize)
1976    return FileSize - SectOffset;
1977  return SectSize;
1978}
1979
1980ArrayRef<uint8_t> MachOObjectFile::getSectionContents(uint32_t Offset,
1981                                                      uint64_t Size) const {
1982  return arrayRefFromStringRef(getData().substr(Offset, Size));
1983}
1984
1985Expected<ArrayRef<uint8_t>>
1986MachOObjectFile::getSectionContents(DataRefImpl Sec) const {
1987  uint32_t Offset;
1988  uint64_t Size;
1989
1990  if (is64Bit()) {
1991    MachO::section_64 Sect = getSection64(Sec);
1992    Offset = Sect.offset;
1993    Size = Sect.size;
1994  } else {
1995    MachO::section Sect = getSection(Sec);
1996    Offset = Sect.offset;
1997    Size = Sect.size;
1998  }
1999
2000  return getSectionContents(Offset, Size);
2001}
2002
2003uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
2004  uint32_t Align;
2005  if (is64Bit()) {
2006    MachO::section_64 Sect = getSection64(Sec);
2007    Align = Sect.align;
2008  } else {
2009    MachO::section Sect = getSection(Sec);
2010    Align = Sect.align;
2011  }
2012
2013  return uint64_t(1) << Align;
2014}
2015
2016Expected<SectionRef> MachOObjectFile::getSection(unsigned SectionIndex) const {
2017  if (SectionIndex < 1 || SectionIndex > Sections.size())
2018    return malformedError("bad section index: " + Twine((int)SectionIndex));
2019
2020  DataRefImpl DRI;
2021  DRI.d.a = SectionIndex - 1;
2022  return SectionRef(DRI, this);
2023}
2024
2025Expected<SectionRef> MachOObjectFile::getSection(StringRef SectionName) const {
2026  for (const SectionRef &Section : sections()) {
2027    auto NameOrErr = Section.getName();
2028    if (!NameOrErr)
2029      return NameOrErr.takeError();
2030    if (*NameOrErr == SectionName)
2031      return Section;
2032  }
2033  return errorCodeToError(object_error::parse_failed);
2034}
2035
2036bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
2037  return false;
2038}
2039
2040bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
2041  uint32_t Flags = getSectionFlags(*this, Sec);
2042  return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
2043}
2044
2045bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
2046  uint32_t Flags = getSectionFlags(*this, Sec);
2047  unsigned SectionType = Flags & MachO::SECTION_TYPE;
2048  return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
2049         !(SectionType == MachO::S_ZEROFILL ||
2050           SectionType == MachO::S_GB_ZEROFILL);
2051}
2052
2053bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
2054  uint32_t Flags = getSectionFlags(*this, Sec);
2055  unsigned SectionType = Flags & MachO::SECTION_TYPE;
2056  return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
2057         (SectionType == MachO::S_ZEROFILL ||
2058          SectionType == MachO::S_GB_ZEROFILL);
2059}
2060
2061bool MachOObjectFile::isDebugSection(DataRefImpl Sec) const {
2062  Expected<StringRef> SectionNameOrErr = getSectionName(Sec);
2063  if (!SectionNameOrErr) {
2064    // TODO: Report the error message properly.
2065    consumeError(SectionNameOrErr.takeError());
2066    return false;
2067  }
2068  StringRef SectionName = SectionNameOrErr.get();
2069  return SectionName.starts_with("__debug") ||
2070         SectionName.starts_with("__zdebug") ||
2071         SectionName.starts_with("__apple") || SectionName == "__gdb_index" ||
2072         SectionName == "__swift_ast";
2073}
2074
2075namespace {
2076template <typename LoadCommandType>
2077ArrayRef<uint8_t> getSegmentContents(const MachOObjectFile &Obj,
2078                                     MachOObjectFile::LoadCommandInfo LoadCmd,
2079                                     StringRef SegmentName) {
2080  auto SegmentOrErr = getStructOrErr<LoadCommandType>(Obj, LoadCmd.Ptr);
2081  if (!SegmentOrErr) {
2082    consumeError(SegmentOrErr.takeError());
2083    return {};
2084  }
2085  auto &Segment = SegmentOrErr.get();
2086  if (StringRef(Segment.segname, 16).starts_with(SegmentName))
2087    return arrayRefFromStringRef(Obj.getData().slice(
2088        Segment.fileoff, Segment.fileoff + Segment.filesize));
2089  return {};
2090}
2091
2092template <typename LoadCommandType>
2093ArrayRef<uint8_t> getSegmentContents(const MachOObjectFile &Obj,
2094                                     MachOObjectFile::LoadCommandInfo LoadCmd) {
2095  auto SegmentOrErr = getStructOrErr<LoadCommandType>(Obj, LoadCmd.Ptr);
2096  if (!SegmentOrErr) {
2097    consumeError(SegmentOrErr.takeError());
2098    return {};
2099  }
2100  auto &Segment = SegmentOrErr.get();
2101  return arrayRefFromStringRef(
2102      Obj.getData().slice(Segment.fileoff, Segment.fileoff + Segment.filesize));
2103}
2104} // namespace
2105
2106ArrayRef<uint8_t>
2107MachOObjectFile::getSegmentContents(StringRef SegmentName) const {
2108  for (auto LoadCmd : load_commands()) {
2109    ArrayRef<uint8_t> Contents;
2110    switch (LoadCmd.C.cmd) {
2111    case MachO::LC_SEGMENT:
2112      Contents = ::getSegmentContents<MachO::segment_command>(*this, LoadCmd,
2113                                                              SegmentName);
2114      break;
2115    case MachO::LC_SEGMENT_64:
2116      Contents = ::getSegmentContents<MachO::segment_command_64>(*this, LoadCmd,
2117                                                                 SegmentName);
2118      break;
2119    default:
2120      continue;
2121    }
2122    if (!Contents.empty())
2123      return Contents;
2124  }
2125  return {};
2126}
2127
2128ArrayRef<uint8_t>
2129MachOObjectFile::getSegmentContents(size_t SegmentIndex) const {
2130  size_t Idx = 0;
2131  for (auto LoadCmd : load_commands()) {
2132    switch (LoadCmd.C.cmd) {
2133    case MachO::LC_SEGMENT:
2134      if (Idx == SegmentIndex)
2135        return ::getSegmentContents<MachO::segment_command>(*this, LoadCmd);
2136      ++Idx;
2137      break;
2138    case MachO::LC_SEGMENT_64:
2139      if (Idx == SegmentIndex)
2140        return ::getSegmentContents<MachO::segment_command_64>(*this, LoadCmd);
2141      ++Idx;
2142      break;
2143    default:
2144      continue;
2145    }
2146  }
2147  return {};
2148}
2149
2150unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
2151  return Sec.getRawDataRefImpl().d.a;
2152}
2153
2154bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
2155  uint32_t Flags = getSectionFlags(*this, Sec);
2156  unsigned SectionType = Flags & MachO::SECTION_TYPE;
2157  return SectionType == MachO::S_ZEROFILL ||
2158         SectionType == MachO::S_GB_ZEROFILL;
2159}
2160
2161bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
2162  StringRef SegmentName = getSectionFinalSegmentName(Sec);
2163  if (Expected<StringRef> NameOrErr = getSectionName(Sec))
2164    return (SegmentName == "__LLVM" && *NameOrErr == "__bitcode");
2165  return false;
2166}
2167
2168bool MachOObjectFile::isSectionStripped(DataRefImpl Sec) const {
2169  if (is64Bit())
2170    return getSection64(Sec).offset == 0;
2171  return getSection(Sec).offset == 0;
2172}
2173
2174relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
2175  DataRefImpl Ret;
2176  Ret.d.a = Sec.d.a;
2177  Ret.d.b = 0;
2178  return relocation_iterator(RelocationRef(Ret, this));
2179}
2180
2181relocation_iterator
2182MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
2183  uint32_t Num;
2184  if (is64Bit()) {
2185    MachO::section_64 Sect = getSection64(Sec);
2186    Num = Sect.nreloc;
2187  } else {
2188    MachO::section Sect = getSection(Sec);
2189    Num = Sect.nreloc;
2190  }
2191
2192  DataRefImpl Ret;
2193  Ret.d.a = Sec.d.a;
2194  Ret.d.b = Num;
2195  return relocation_iterator(RelocationRef(Ret, this));
2196}
2197
2198relocation_iterator MachOObjectFile::extrel_begin() const {
2199  DataRefImpl Ret;
2200  // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2201  Ret.d.a = 0; // Would normally be a section index.
2202  Ret.d.b = 0; // Index into the external relocations
2203  return relocation_iterator(RelocationRef(Ret, this));
2204}
2205
2206relocation_iterator MachOObjectFile::extrel_end() const {
2207  MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
2208  DataRefImpl Ret;
2209  // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2210  Ret.d.a = 0; // Would normally be a section index.
2211  Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations
2212  return relocation_iterator(RelocationRef(Ret, this));
2213}
2214
2215relocation_iterator MachOObjectFile::locrel_begin() const {
2216  DataRefImpl Ret;
2217  // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2218  Ret.d.a = 1; // Would normally be a section index.
2219  Ret.d.b = 0; // Index into the local relocations
2220  return relocation_iterator(RelocationRef(Ret, this));
2221}
2222
2223relocation_iterator MachOObjectFile::locrel_end() const {
2224  MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
2225  DataRefImpl Ret;
2226  // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2227  Ret.d.a = 1; // Would normally be a section index.
2228  Ret.d.b = DysymtabLoadCmd.nlocrel; // Index into the local relocations
2229  return relocation_iterator(RelocationRef(Ret, this));
2230}
2231
2232void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
2233  ++Rel.d.b;
2234}
2235
2236uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
2237  assert((getHeader().filetype == MachO::MH_OBJECT ||
2238          getHeader().filetype == MachO::MH_KEXT_BUNDLE) &&
2239         "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
2240  MachO::any_relocation_info RE = getRelocation(Rel);
2241  return getAnyRelocationAddress(RE);
2242}
2243
2244symbol_iterator
2245MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
2246  MachO::any_relocation_info RE = getRelocation(Rel);
2247  if (isRelocationScattered(RE))
2248    return symbol_end();
2249
2250  uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
2251  bool isExtern = getPlainRelocationExternal(RE);
2252  if (!isExtern)
2253    return symbol_end();
2254
2255  MachO::symtab_command S = getSymtabLoadCommand();
2256  unsigned SymbolTableEntrySize = is64Bit() ?
2257    sizeof(MachO::nlist_64) :
2258    sizeof(MachO::nlist);
2259  uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
2260  DataRefImpl Sym;
2261  Sym.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2262  return symbol_iterator(SymbolRef(Sym, this));
2263}
2264
2265section_iterator
2266MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
2267  return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
2268}
2269
2270uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
2271  MachO::any_relocation_info RE = getRelocation(Rel);
2272  return getAnyRelocationType(RE);
2273}
2274
2275void MachOObjectFile::getRelocationTypeName(
2276    DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
2277  StringRef res;
2278  uint64_t RType = getRelocationType(Rel);
2279
2280  unsigned Arch = this->getArch();
2281
2282  switch (Arch) {
2283    case Triple::x86: {
2284      static const char *const Table[] =  {
2285        "GENERIC_RELOC_VANILLA",
2286        "GENERIC_RELOC_PAIR",
2287        "GENERIC_RELOC_SECTDIFF",
2288        "GENERIC_RELOC_PB_LA_PTR",
2289        "GENERIC_RELOC_LOCAL_SECTDIFF",
2290        "GENERIC_RELOC_TLV" };
2291
2292      if (RType > 5)
2293        res = "Unknown";
2294      else
2295        res = Table[RType];
2296      break;
2297    }
2298    case Triple::x86_64: {
2299      static const char *const Table[] =  {
2300        "X86_64_RELOC_UNSIGNED",
2301        "X86_64_RELOC_SIGNED",
2302        "X86_64_RELOC_BRANCH",
2303        "X86_64_RELOC_GOT_LOAD",
2304        "X86_64_RELOC_GOT",
2305        "X86_64_RELOC_SUBTRACTOR",
2306        "X86_64_RELOC_SIGNED_1",
2307        "X86_64_RELOC_SIGNED_2",
2308        "X86_64_RELOC_SIGNED_4",
2309        "X86_64_RELOC_TLV" };
2310
2311      if (RType > 9)
2312        res = "Unknown";
2313      else
2314        res = Table[RType];
2315      break;
2316    }
2317    case Triple::arm: {
2318      static const char *const Table[] =  {
2319        "ARM_RELOC_VANILLA",
2320        "ARM_RELOC_PAIR",
2321        "ARM_RELOC_SECTDIFF",
2322        "ARM_RELOC_LOCAL_SECTDIFF",
2323        "ARM_RELOC_PB_LA_PTR",
2324        "ARM_RELOC_BR24",
2325        "ARM_THUMB_RELOC_BR22",
2326        "ARM_THUMB_32BIT_BRANCH",
2327        "ARM_RELOC_HALF",
2328        "ARM_RELOC_HALF_SECTDIFF" };
2329
2330      if (RType > 9)
2331        res = "Unknown";
2332      else
2333        res = Table[RType];
2334      break;
2335    }
2336    case Triple::aarch64:
2337    case Triple::aarch64_32: {
2338      static const char *const Table[] = {
2339        "ARM64_RELOC_UNSIGNED",           "ARM64_RELOC_SUBTRACTOR",
2340        "ARM64_RELOC_BRANCH26",           "ARM64_RELOC_PAGE21",
2341        "ARM64_RELOC_PAGEOFF12",          "ARM64_RELOC_GOT_LOAD_PAGE21",
2342        "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
2343        "ARM64_RELOC_TLVP_LOAD_PAGE21",   "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
2344        "ARM64_RELOC_ADDEND"
2345      };
2346
2347      if (RType >= std::size(Table))
2348        res = "Unknown";
2349      else
2350        res = Table[RType];
2351      break;
2352    }
2353    case Triple::ppc: {
2354      static const char *const Table[] =  {
2355        "PPC_RELOC_VANILLA",
2356        "PPC_RELOC_PAIR",
2357        "PPC_RELOC_BR14",
2358        "PPC_RELOC_BR24",
2359        "PPC_RELOC_HI16",
2360        "PPC_RELOC_LO16",
2361        "PPC_RELOC_HA16",
2362        "PPC_RELOC_LO14",
2363        "PPC_RELOC_SECTDIFF",
2364        "PPC_RELOC_PB_LA_PTR",
2365        "PPC_RELOC_HI16_SECTDIFF",
2366        "PPC_RELOC_LO16_SECTDIFF",
2367        "PPC_RELOC_HA16_SECTDIFF",
2368        "PPC_RELOC_JBSR",
2369        "PPC_RELOC_LO14_SECTDIFF",
2370        "PPC_RELOC_LOCAL_SECTDIFF" };
2371
2372      if (RType > 15)
2373        res = "Unknown";
2374      else
2375        res = Table[RType];
2376      break;
2377    }
2378    case Triple::UnknownArch:
2379      res = "Unknown";
2380      break;
2381  }
2382  Result.append(res.begin(), res.end());
2383}
2384
2385uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
2386  MachO::any_relocation_info RE = getRelocation(Rel);
2387  return getAnyRelocationLength(RE);
2388}
2389
2390//
2391// guessLibraryShortName() is passed a name of a dynamic library and returns a
2392// guess on what the short name is.  Then name is returned as a substring of the
2393// StringRef Name passed in.  The name of the dynamic library is recognized as
2394// a framework if it has one of the two following forms:
2395//      Foo.framework/Versions/A/Foo
2396//      Foo.framework/Foo
2397// Where A and Foo can be any string.  And may contain a trailing suffix
2398// starting with an underbar.  If the Name is recognized as a framework then
2399// isFramework is set to true else it is set to false.  If the Name has a
2400// suffix then Suffix is set to the substring in Name that contains the suffix
2401// else it is set to a NULL StringRef.
2402//
2403// The Name of the dynamic library is recognized as a library name if it has
2404// one of the two following forms:
2405//      libFoo.A.dylib
2406//      libFoo.dylib
2407//
2408// The library may have a suffix trailing the name Foo of the form:
2409//      libFoo_profile.A.dylib
2410//      libFoo_profile.dylib
2411// These dyld image suffixes are separated from the short name by a '_'
2412// character. Because the '_' character is commonly used to separate words in
2413// filenames guessLibraryShortName() cannot reliably separate a dylib's short
2414// name from an arbitrary image suffix; imagine if both the short name and the
2415// suffix contains an '_' character! To better deal with this ambiguity,
2416// guessLibraryShortName() will recognize only "_debug" and "_profile" as valid
2417// Suffix values. Calling code needs to be tolerant of guessLibraryShortName()
2418// guessing incorrectly.
2419//
2420// The Name of the dynamic library is also recognized as a library name if it
2421// has the following form:
2422//      Foo.qtx
2423//
2424// If the Name of the dynamic library is none of the forms above then a NULL
2425// StringRef is returned.
2426StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
2427                                                 bool &isFramework,
2428                                                 StringRef &Suffix) {
2429  StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
2430  size_t a, b, c, d, Idx;
2431
2432  isFramework = false;
2433  Suffix = StringRef();
2434
2435  // Pull off the last component and make Foo point to it
2436  a = Name.rfind('/');
2437  if (a == Name.npos || a == 0)
2438    goto guess_library;
2439  Foo = Name.slice(a+1, Name.npos);
2440
2441  // Look for a suffix starting with a '_'
2442  Idx = Foo.rfind('_');
2443  if (Idx != Foo.npos && Foo.size() >= 2) {
2444    Suffix = Foo.slice(Idx, Foo.npos);
2445    if (Suffix != "_debug" && Suffix != "_profile")
2446      Suffix = StringRef();
2447    else
2448      Foo = Foo.slice(0, Idx);
2449  }
2450
2451  // First look for the form Foo.framework/Foo
2452  b = Name.rfind('/', a);
2453  if (b == Name.npos)
2454    Idx = 0;
2455  else
2456    Idx = b+1;
2457  F = Name.slice(Idx, Idx + Foo.size());
2458  DotFramework = Name.slice(Idx + Foo.size(),
2459                            Idx + Foo.size() + sizeof(".framework/")-1);
2460  if (F == Foo && DotFramework == ".framework/") {
2461    isFramework = true;
2462    return Foo;
2463  }
2464
2465  // Next look for the form Foo.framework/Versions/A/Foo
2466  if (b == Name.npos)
2467    goto guess_library;
2468  c =  Name.rfind('/', b);
2469  if (c == Name.npos || c == 0)
2470    goto guess_library;
2471  V = Name.slice(c+1, Name.npos);
2472  if (!V.starts_with("Versions/"))
2473    goto guess_library;
2474  d =  Name.rfind('/', c);
2475  if (d == Name.npos)
2476    Idx = 0;
2477  else
2478    Idx = d+1;
2479  F = Name.slice(Idx, Idx + Foo.size());
2480  DotFramework = Name.slice(Idx + Foo.size(),
2481                            Idx + Foo.size() + sizeof(".framework/")-1);
2482  if (F == Foo && DotFramework == ".framework/") {
2483    isFramework = true;
2484    return Foo;
2485  }
2486
2487guess_library:
2488  // pull off the suffix after the "." and make a point to it
2489  a = Name.rfind('.');
2490  if (a == Name.npos || a == 0)
2491    return StringRef();
2492  Dylib = Name.slice(a, Name.npos);
2493  if (Dylib != ".dylib")
2494    goto guess_qtx;
2495
2496  // First pull off the version letter for the form Foo.A.dylib if any.
2497  if (a >= 3) {
2498    Dot = Name.slice(a-2, a-1);
2499    if (Dot == ".")
2500      a = a - 2;
2501  }
2502
2503  b = Name.rfind('/', a);
2504  if (b == Name.npos)
2505    b = 0;
2506  else
2507    b = b+1;
2508  // ignore any suffix after an underbar like Foo_profile.A.dylib
2509  Idx = Name.rfind('_');
2510  if (Idx != Name.npos && Idx != b) {
2511    Lib = Name.slice(b, Idx);
2512    Suffix = Name.slice(Idx, a);
2513    if (Suffix != "_debug" && Suffix != "_profile") {
2514      Suffix = StringRef();
2515      Lib = Name.slice(b, a);
2516    }
2517  }
2518  else
2519    Lib = Name.slice(b, a);
2520  // There are incorrect library names of the form:
2521  // libATS.A_profile.dylib so check for these.
2522  if (Lib.size() >= 3) {
2523    Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2524    if (Dot == ".")
2525      Lib = Lib.slice(0, Lib.size()-2);
2526  }
2527  return Lib;
2528
2529guess_qtx:
2530  Qtx = Name.slice(a, Name.npos);
2531  if (Qtx != ".qtx")
2532    return StringRef();
2533  b = Name.rfind('/', a);
2534  if (b == Name.npos)
2535    Lib = Name.slice(0, a);
2536  else
2537    Lib = Name.slice(b+1, a);
2538  // There are library names of the form: QT.A.qtx so check for these.
2539  if (Lib.size() >= 3) {
2540    Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2541    if (Dot == ".")
2542      Lib = Lib.slice(0, Lib.size()-2);
2543  }
2544  return Lib;
2545}
2546
2547// getLibraryShortNameByIndex() is used to get the short name of the library
2548// for an undefined symbol in a linked Mach-O binary that was linked with the
2549// normal two-level namespace default (that is MH_TWOLEVEL in the header).
2550// It is passed the index (0 - based) of the library as translated from
2551// GET_LIBRARY_ORDINAL (1 - based).
2552std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
2553                                                         StringRef &Res) const {
2554  if (Index >= Libraries.size())
2555    return object_error::parse_failed;
2556
2557  // If the cache of LibrariesShortNames is not built up do that first for
2558  // all the Libraries.
2559  if (LibrariesShortNames.size() == 0) {
2560    for (unsigned i = 0; i < Libraries.size(); i++) {
2561      auto CommandOrErr =
2562        getStructOrErr<MachO::dylib_command>(*this, Libraries[i]);
2563      if (!CommandOrErr)
2564        return object_error::parse_failed;
2565      MachO::dylib_command D = CommandOrErr.get();
2566      if (D.dylib.name >= D.cmdsize)
2567        return object_error::parse_failed;
2568      const char *P = (const char *)(Libraries[i]) + D.dylib.name;
2569      StringRef Name = StringRef(P);
2570      if (D.dylib.name+Name.size() >= D.cmdsize)
2571        return object_error::parse_failed;
2572      StringRef Suffix;
2573      bool isFramework;
2574      StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
2575      if (shortName.empty())
2576        LibrariesShortNames.push_back(Name);
2577      else
2578        LibrariesShortNames.push_back(shortName);
2579    }
2580  }
2581
2582  Res = LibrariesShortNames[Index];
2583  return std::error_code();
2584}
2585
2586uint32_t MachOObjectFile::getLibraryCount() const {
2587  return Libraries.size();
2588}
2589
2590section_iterator
2591MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
2592  DataRefImpl Sec;
2593  Sec.d.a = Rel->getRawDataRefImpl().d.a;
2594  return section_iterator(SectionRef(Sec, this));
2595}
2596
2597basic_symbol_iterator MachOObjectFile::symbol_begin() const {
2598  DataRefImpl DRI;
2599  MachO::symtab_command Symtab = getSymtabLoadCommand();
2600  if (!SymtabLoadCmd || Symtab.nsyms == 0)
2601    return basic_symbol_iterator(SymbolRef(DRI, this));
2602
2603  return getSymbolByIndex(0);
2604}
2605
2606basic_symbol_iterator MachOObjectFile::symbol_end() const {
2607  DataRefImpl DRI;
2608  MachO::symtab_command Symtab = getSymtabLoadCommand();
2609  if (!SymtabLoadCmd || Symtab.nsyms == 0)
2610    return basic_symbol_iterator(SymbolRef(DRI, this));
2611
2612  unsigned SymbolTableEntrySize = is64Bit() ?
2613    sizeof(MachO::nlist_64) :
2614    sizeof(MachO::nlist);
2615  unsigned Offset = Symtab.symoff +
2616    Symtab.nsyms * SymbolTableEntrySize;
2617  DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2618  return basic_symbol_iterator(SymbolRef(DRI, this));
2619}
2620
2621symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
2622  MachO::symtab_command Symtab = getSymtabLoadCommand();
2623  if (!SymtabLoadCmd || Index >= Symtab.nsyms)
2624    report_fatal_error("Requested symbol index is out of range.");
2625  unsigned SymbolTableEntrySize =
2626    is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2627  DataRefImpl DRI;
2628  DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
2629  DRI.p += Index * SymbolTableEntrySize;
2630  return basic_symbol_iterator(SymbolRef(DRI, this));
2631}
2632
2633uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
2634  MachO::symtab_command Symtab = getSymtabLoadCommand();
2635  if (!SymtabLoadCmd)
2636    report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2637  unsigned SymbolTableEntrySize =
2638    is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
2639  DataRefImpl DRIstart;
2640  DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
2641  uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
2642  return Index;
2643}
2644
2645section_iterator MachOObjectFile::section_begin() const {
2646  DataRefImpl DRI;
2647  return section_iterator(SectionRef(DRI, this));
2648}
2649
2650section_iterator MachOObjectFile::section_end() const {
2651  DataRefImpl DRI;
2652  DRI.d.a = Sections.size();
2653  return section_iterator(SectionRef(DRI, this));
2654}
2655
2656uint8_t MachOObjectFile::getBytesInAddress() const {
2657  return is64Bit() ? 8 : 4;
2658}
2659
2660StringRef MachOObjectFile::getFileFormatName() const {
2661  unsigned CPUType = getCPUType(*this);
2662  if (!is64Bit()) {
2663    switch (CPUType) {
2664    case MachO::CPU_TYPE_I386:
2665      return "Mach-O 32-bit i386";
2666    case MachO::CPU_TYPE_ARM:
2667      return "Mach-O arm";
2668    case MachO::CPU_TYPE_ARM64_32:
2669      return "Mach-O arm64 (ILP32)";
2670    case MachO::CPU_TYPE_POWERPC:
2671      return "Mach-O 32-bit ppc";
2672    default:
2673      return "Mach-O 32-bit unknown";
2674    }
2675  }
2676
2677  switch (CPUType) {
2678  case MachO::CPU_TYPE_X86_64:
2679    return "Mach-O 64-bit x86-64";
2680  case MachO::CPU_TYPE_ARM64:
2681    return "Mach-O arm64";
2682  case MachO::CPU_TYPE_POWERPC64:
2683    return "Mach-O 64-bit ppc64";
2684  default:
2685    return "Mach-O 64-bit unknown";
2686  }
2687}
2688
2689Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) {
2690  switch (CPUType) {
2691  case MachO::CPU_TYPE_I386:
2692    return Triple::x86;
2693  case MachO::CPU_TYPE_X86_64:
2694    return Triple::x86_64;
2695  case MachO::CPU_TYPE_ARM:
2696    return Triple::arm;
2697  case MachO::CPU_TYPE_ARM64:
2698    return Triple::aarch64;
2699  case MachO::CPU_TYPE_ARM64_32:
2700    return Triple::aarch64_32;
2701  case MachO::CPU_TYPE_POWERPC:
2702    return Triple::ppc;
2703  case MachO::CPU_TYPE_POWERPC64:
2704    return Triple::ppc64;
2705  default:
2706    return Triple::UnknownArch;
2707  }
2708}
2709
2710Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
2711                                      const char **McpuDefault,
2712                                      const char **ArchFlag) {
2713  if (McpuDefault)
2714    *McpuDefault = nullptr;
2715  if (ArchFlag)
2716    *ArchFlag = nullptr;
2717
2718  switch (CPUType) {
2719  case MachO::CPU_TYPE_I386:
2720    switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2721    case MachO::CPU_SUBTYPE_I386_ALL:
2722      if (ArchFlag)
2723        *ArchFlag = "i386";
2724      return Triple("i386-apple-darwin");
2725    default:
2726      return Triple();
2727    }
2728  case MachO::CPU_TYPE_X86_64:
2729    switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2730    case MachO::CPU_SUBTYPE_X86_64_ALL:
2731      if (ArchFlag)
2732        *ArchFlag = "x86_64";
2733      return Triple("x86_64-apple-darwin");
2734    case MachO::CPU_SUBTYPE_X86_64_H:
2735      if (ArchFlag)
2736        *ArchFlag = "x86_64h";
2737      return Triple("x86_64h-apple-darwin");
2738    default:
2739      return Triple();
2740    }
2741  case MachO::CPU_TYPE_ARM:
2742    switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2743    case MachO::CPU_SUBTYPE_ARM_V4T:
2744      if (ArchFlag)
2745        *ArchFlag = "armv4t";
2746      return Triple("armv4t-apple-darwin");
2747    case MachO::CPU_SUBTYPE_ARM_V5TEJ:
2748      if (ArchFlag)
2749        *ArchFlag = "armv5e";
2750      return Triple("armv5e-apple-darwin");
2751    case MachO::CPU_SUBTYPE_ARM_XSCALE:
2752      if (ArchFlag)
2753        *ArchFlag = "xscale";
2754      return Triple("xscale-apple-darwin");
2755    case MachO::CPU_SUBTYPE_ARM_V6:
2756      if (ArchFlag)
2757        *ArchFlag = "armv6";
2758      return Triple("armv6-apple-darwin");
2759    case MachO::CPU_SUBTYPE_ARM_V6M:
2760      if (McpuDefault)
2761        *McpuDefault = "cortex-m0";
2762      if (ArchFlag)
2763        *ArchFlag = "armv6m";
2764      return Triple("armv6m-apple-darwin");
2765    case MachO::CPU_SUBTYPE_ARM_V7:
2766      if (ArchFlag)
2767        *ArchFlag = "armv7";
2768      return Triple("armv7-apple-darwin");
2769    case MachO::CPU_SUBTYPE_ARM_V7EM:
2770      if (McpuDefault)
2771        *McpuDefault = "cortex-m4";
2772      if (ArchFlag)
2773        *ArchFlag = "armv7em";
2774      return Triple("thumbv7em-apple-darwin");
2775    case MachO::CPU_SUBTYPE_ARM_V7K:
2776      if (McpuDefault)
2777        *McpuDefault = "cortex-a7";
2778      if (ArchFlag)
2779        *ArchFlag = "armv7k";
2780      return Triple("armv7k-apple-darwin");
2781    case MachO::CPU_SUBTYPE_ARM_V7M:
2782      if (McpuDefault)
2783        *McpuDefault = "cortex-m3";
2784      if (ArchFlag)
2785        *ArchFlag = "armv7m";
2786      return Triple("thumbv7m-apple-darwin");
2787    case MachO::CPU_SUBTYPE_ARM_V7S:
2788      if (McpuDefault)
2789        *McpuDefault = "cortex-a7";
2790      if (ArchFlag)
2791        *ArchFlag = "armv7s";
2792      return Triple("armv7s-apple-darwin");
2793    default:
2794      return Triple();
2795    }
2796  case MachO::CPU_TYPE_ARM64:
2797    switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2798    case MachO::CPU_SUBTYPE_ARM64_ALL:
2799      if (McpuDefault)
2800        *McpuDefault = "cyclone";
2801      if (ArchFlag)
2802        *ArchFlag = "arm64";
2803      return Triple("arm64-apple-darwin");
2804    case MachO::CPU_SUBTYPE_ARM64E:
2805      if (McpuDefault)
2806        *McpuDefault = "apple-a12";
2807      if (ArchFlag)
2808        *ArchFlag = "arm64e";
2809      return Triple("arm64e-apple-darwin");
2810    default:
2811      return Triple();
2812    }
2813  case MachO::CPU_TYPE_ARM64_32:
2814    switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2815    case MachO::CPU_SUBTYPE_ARM64_32_V8:
2816      if (McpuDefault)
2817        *McpuDefault = "cyclone";
2818      if (ArchFlag)
2819        *ArchFlag = "arm64_32";
2820      return Triple("arm64_32-apple-darwin");
2821    default:
2822      return Triple();
2823    }
2824  case MachO::CPU_TYPE_POWERPC:
2825    switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2826    case MachO::CPU_SUBTYPE_POWERPC_ALL:
2827      if (ArchFlag)
2828        *ArchFlag = "ppc";
2829      return Triple("ppc-apple-darwin");
2830    default:
2831      return Triple();
2832    }
2833  case MachO::CPU_TYPE_POWERPC64:
2834    switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2835    case MachO::CPU_SUBTYPE_POWERPC_ALL:
2836      if (ArchFlag)
2837        *ArchFlag = "ppc64";
2838      return Triple("ppc64-apple-darwin");
2839    default:
2840      return Triple();
2841    }
2842  default:
2843    return Triple();
2844  }
2845}
2846
2847Triple MachOObjectFile::getHostArch() {
2848  return Triple(sys::getDefaultTargetTriple());
2849}
2850
2851bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
2852  auto validArchs = getValidArchs();
2853  return llvm::is_contained(validArchs, ArchFlag);
2854}
2855
2856ArrayRef<StringRef> MachOObjectFile::getValidArchs() {
2857  static const std::array<StringRef, 18> ValidArchs = {{
2858      "i386",
2859      "x86_64",
2860      "x86_64h",
2861      "armv4t",
2862      "arm",
2863      "armv5e",
2864      "armv6",
2865      "armv6m",
2866      "armv7",
2867      "armv7em",
2868      "armv7k",
2869      "armv7m",
2870      "armv7s",
2871      "arm64",
2872      "arm64e",
2873      "arm64_32",
2874      "ppc",
2875      "ppc64",
2876  }};
2877
2878  return ValidArchs;
2879}
2880
2881Triple::ArchType MachOObjectFile::getArch() const {
2882  return getArch(getCPUType(*this), getCPUSubType(*this));
2883}
2884
2885Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
2886  return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
2887}
2888
2889relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
2890  DataRefImpl DRI;
2891  DRI.d.a = Index;
2892  return section_rel_begin(DRI);
2893}
2894
2895relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
2896  DataRefImpl DRI;
2897  DRI.d.a = Index;
2898  return section_rel_end(DRI);
2899}
2900
2901dice_iterator MachOObjectFile::begin_dices() const {
2902  DataRefImpl DRI;
2903  if (!DataInCodeLoadCmd)
2904    return dice_iterator(DiceRef(DRI, this));
2905
2906  MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2907  DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff));
2908  return dice_iterator(DiceRef(DRI, this));
2909}
2910
2911dice_iterator MachOObjectFile::end_dices() const {
2912  DataRefImpl DRI;
2913  if (!DataInCodeLoadCmd)
2914    return dice_iterator(DiceRef(DRI, this));
2915
2916  MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2917  unsigned Offset = DicLC.dataoff + DicLC.datasize;
2918  DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2919  return dice_iterator(DiceRef(DRI, this));
2920}
2921
2922ExportEntry::ExportEntry(Error *E, const MachOObjectFile *O,
2923                         ArrayRef<uint8_t> T) : E(E), O(O), Trie(T) {}
2924
2925void ExportEntry::moveToFirst() {
2926  ErrorAsOutParameter ErrAsOutParam(E);
2927  pushNode(0);
2928  if (*E)
2929    return;
2930  pushDownUntilBottom();
2931}
2932
2933void ExportEntry::moveToEnd() {
2934  Stack.clear();
2935  Done = true;
2936}
2937
2938bool ExportEntry::operator==(const ExportEntry &Other) const {
2939  // Common case, one at end, other iterating from begin.
2940  if (Done || Other.Done)
2941    return (Done == Other.Done);
2942  // Not equal if different stack sizes.
2943  if (Stack.size() != Other.Stack.size())
2944    return false;
2945  // Not equal if different cumulative strings.
2946  if (!CumulativeString.equals(Other.CumulativeString))
2947    return false;
2948  // Equal if all nodes in both stacks match.
2949  for (unsigned i=0; i < Stack.size(); ++i) {
2950    if (Stack[i].Start != Other.Stack[i].Start)
2951      return false;
2952  }
2953  return true;
2954}
2955
2956uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr, const char **error) {
2957  unsigned Count;
2958  uint64_t Result = decodeULEB128(Ptr, &Count, Trie.end(), error);
2959  Ptr += Count;
2960  if (Ptr > Trie.end())
2961    Ptr = Trie.end();
2962  return Result;
2963}
2964
2965StringRef ExportEntry::name() const {
2966  return CumulativeString;
2967}
2968
2969uint64_t ExportEntry::flags() const {
2970  return Stack.back().Flags;
2971}
2972
2973uint64_t ExportEntry::address() const {
2974  return Stack.back().Address;
2975}
2976
2977uint64_t ExportEntry::other() const {
2978  return Stack.back().Other;
2979}
2980
2981StringRef ExportEntry::otherName() const {
2982  const char* ImportName = Stack.back().ImportName;
2983  if (ImportName)
2984    return StringRef(ImportName);
2985  return StringRef();
2986}
2987
2988uint32_t ExportEntry::nodeOffset() const {
2989  return Stack.back().Start - Trie.begin();
2990}
2991
2992ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
2993    : Start(Ptr), Current(Ptr) {}
2994
2995void ExportEntry::pushNode(uint64_t offset) {
2996  ErrorAsOutParameter ErrAsOutParam(E);
2997  const uint8_t *Ptr = Trie.begin() + offset;
2998  NodeState State(Ptr);
2999  const char *error = nullptr;
3000  uint64_t ExportInfoSize = readULEB128(State.Current, &error);
3001  if (error) {
3002    *E = malformedError("export info size " + Twine(error) +
3003                        " in export trie data at node: 0x" +
3004                        Twine::utohexstr(offset));
3005    moveToEnd();
3006    return;
3007  }
3008  State.IsExportNode = (ExportInfoSize != 0);
3009  const uint8_t* Children = State.Current + ExportInfoSize;
3010  if (Children > Trie.end()) {
3011    *E = malformedError(
3012        "export info size: 0x" + Twine::utohexstr(ExportInfoSize) +
3013        " in export trie data at node: 0x" + Twine::utohexstr(offset) +
3014        " too big and extends past end of trie data");
3015    moveToEnd();
3016    return;
3017  }
3018  if (State.IsExportNode) {
3019    const uint8_t *ExportStart = State.Current;
3020    State.Flags = readULEB128(State.Current, &error);
3021    if (error) {
3022      *E = malformedError("flags " + Twine(error) +
3023                          " in export trie data at node: 0x" +
3024                          Twine::utohexstr(offset));
3025      moveToEnd();
3026      return;
3027    }
3028    uint64_t Kind = State.Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK;
3029    if (State.Flags != 0 &&
3030        (Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR &&
3031         Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE &&
3032         Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL)) {
3033      *E = malformedError(
3034          "unsupported exported symbol kind: " + Twine((int)Kind) +
3035          " in flags: 0x" + Twine::utohexstr(State.Flags) +
3036          " in export trie data at node: 0x" + Twine::utohexstr(offset));
3037      moveToEnd();
3038      return;
3039    }
3040    if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
3041      State.Address = 0;
3042      State.Other = readULEB128(State.Current, &error); // dylib ordinal
3043      if (error) {
3044        *E = malformedError("dylib ordinal of re-export " + Twine(error) +
3045                            " in export trie data at node: 0x" +
3046                            Twine::utohexstr(offset));
3047        moveToEnd();
3048        return;
3049      }
3050      if (O != nullptr) {
3051        // Only positive numbers represent library ordinals. Zero and negative
3052        // numbers have special meaning (see BindSpecialDylib).
3053        if ((int64_t)State.Other > 0 && State.Other > O->getLibraryCount()) {
3054          *E = malformedError(
3055              "bad library ordinal: " + Twine((int)State.Other) + " (max " +
3056              Twine((int)O->getLibraryCount()) +
3057              ") in export trie data at node: 0x" + Twine::utohexstr(offset));
3058          moveToEnd();
3059          return;
3060        }
3061      }
3062      State.ImportName = reinterpret_cast<const char*>(State.Current);
3063      if (*State.ImportName == '\0') {
3064        State.Current++;
3065      } else {
3066        const uint8_t *End = State.Current + 1;
3067        if (End >= Trie.end()) {
3068          *E = malformedError("import name of re-export in export trie data at "
3069                              "node: 0x" +
3070                              Twine::utohexstr(offset) +
3071                              " starts past end of trie data");
3072          moveToEnd();
3073          return;
3074        }
3075        while(*End != '\0' && End < Trie.end())
3076          End++;
3077        if (*End != '\0') {
3078          *E = malformedError("import name of re-export in export trie data at "
3079                              "node: 0x" +
3080                              Twine::utohexstr(offset) +
3081                              " extends past end of trie data");
3082          moveToEnd();
3083          return;
3084        }
3085        State.Current = End + 1;
3086      }
3087    } else {
3088      State.Address = readULEB128(State.Current, &error);
3089      if (error) {
3090        *E = malformedError("address " + Twine(error) +
3091                            " in export trie data at node: 0x" +
3092                            Twine::utohexstr(offset));
3093        moveToEnd();
3094        return;
3095      }
3096      if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
3097        State.Other = readULEB128(State.Current, &error);
3098        if (error) {
3099          *E = malformedError("resolver of stub and resolver " + Twine(error) +
3100                              " in export trie data at node: 0x" +
3101                              Twine::utohexstr(offset));
3102          moveToEnd();
3103          return;
3104        }
3105      }
3106    }
3107    if(ExportStart + ExportInfoSize != State.Current) {
3108      *E = malformedError(
3109          "inconsistent export info size: 0x" +
3110          Twine::utohexstr(ExportInfoSize) + " where actual size was: 0x" +
3111          Twine::utohexstr(State.Current - ExportStart) +
3112          " in export trie data at node: 0x" + Twine::utohexstr(offset));
3113      moveToEnd();
3114      return;
3115    }
3116  }
3117  State.ChildCount = *Children;
3118  if (State.ChildCount != 0 && Children + 1 >= Trie.end()) {
3119    *E = malformedError("byte for count of childern in export trie data at "
3120                        "node: 0x" +
3121                        Twine::utohexstr(offset) +
3122                        " extends past end of trie data");
3123    moveToEnd();
3124    return;
3125  }
3126  State.Current = Children + 1;
3127  State.NextChildIndex = 0;
3128  State.ParentStringLength = CumulativeString.size();
3129  Stack.push_back(State);
3130}
3131
3132void ExportEntry::pushDownUntilBottom() {
3133  ErrorAsOutParameter ErrAsOutParam(E);
3134  const char *error = nullptr;
3135  while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
3136    NodeState &Top = Stack.back();
3137    CumulativeString.resize(Top.ParentStringLength);
3138    for (;*Top.Current != 0 && Top.Current < Trie.end(); Top.Current++) {
3139      char C = *Top.Current;
3140      CumulativeString.push_back(C);
3141    }
3142    if (Top.Current >= Trie.end()) {
3143      *E = malformedError("edge sub-string in export trie data at node: 0x" +
3144                          Twine::utohexstr(Top.Start - Trie.begin()) +
3145                          " for child #" + Twine((int)Top.NextChildIndex) +
3146                          " extends past end of trie data");
3147      moveToEnd();
3148      return;
3149    }
3150    Top.Current += 1;
3151    uint64_t childNodeIndex = readULEB128(Top.Current, &error);
3152    if (error) {
3153      *E = malformedError("child node offset " + Twine(error) +
3154                          " in export trie data at node: 0x" +
3155                          Twine::utohexstr(Top.Start - Trie.begin()));
3156      moveToEnd();
3157      return;
3158    }
3159    for (const NodeState &node : nodes()) {
3160      if (node.Start == Trie.begin() + childNodeIndex){
3161        *E = malformedError("loop in childern in export trie data at node: 0x" +
3162                            Twine::utohexstr(Top.Start - Trie.begin()) +
3163                            " back to node: 0x" +
3164                            Twine::utohexstr(childNodeIndex));
3165        moveToEnd();
3166        return;
3167      }
3168    }
3169    Top.NextChildIndex += 1;
3170    pushNode(childNodeIndex);
3171    if (*E)
3172      return;
3173  }
3174  if (!Stack.back().IsExportNode) {
3175    *E = malformedError("node is not an export node in export trie data at "
3176                        "node: 0x" +
3177                        Twine::utohexstr(Stack.back().Start - Trie.begin()));
3178    moveToEnd();
3179    return;
3180  }
3181}
3182
3183// We have a trie data structure and need a way to walk it that is compatible
3184// with the C++ iterator model. The solution is a non-recursive depth first
3185// traversal where the iterator contains a stack of parent nodes along with a
3186// string that is the accumulation of all edge strings along the parent chain
3187// to this point.
3188//
3189// There is one "export" node for each exported symbol.  But because some
3190// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
3191// node may have child nodes too.
3192//
3193// The algorithm for moveNext() is to keep moving down the leftmost unvisited
3194// child until hitting a node with no children (which is an export node or
3195// else the trie is malformed). On the way down, each node is pushed on the
3196// stack ivar.  If there is no more ways down, it pops up one and tries to go
3197// down a sibling path until a childless node is reached.
3198void ExportEntry::moveNext() {
3199  assert(!Stack.empty() && "ExportEntry::moveNext() with empty node stack");
3200  if (!Stack.back().IsExportNode) {
3201    *E = malformedError("node is not an export node in export trie data at "
3202                        "node: 0x" +
3203                        Twine::utohexstr(Stack.back().Start - Trie.begin()));
3204    moveToEnd();
3205    return;
3206  }
3207
3208  Stack.pop_back();
3209  while (!Stack.empty()) {
3210    NodeState &Top = Stack.back();
3211    if (Top.NextChildIndex < Top.ChildCount) {
3212      pushDownUntilBottom();
3213      // Now at the next export node.
3214      return;
3215    } else {
3216      if (Top.IsExportNode) {
3217        // This node has no children but is itself an export node.
3218        CumulativeString.resize(Top.ParentStringLength);
3219        return;
3220      }
3221      Stack.pop_back();
3222    }
3223  }
3224  Done = true;
3225}
3226
3227iterator_range<export_iterator>
3228MachOObjectFile::exports(Error &E, ArrayRef<uint8_t> Trie,
3229                         const MachOObjectFile *O) {
3230  ExportEntry Start(&E, O, Trie);
3231  if (Trie.empty())
3232    Start.moveToEnd();
3233  else
3234    Start.moveToFirst();
3235
3236  ExportEntry Finish(&E, O, Trie);
3237  Finish.moveToEnd();
3238
3239  return make_range(export_iterator(Start), export_iterator(Finish));
3240}
3241
3242iterator_range<export_iterator> MachOObjectFile::exports(Error &Err) const {
3243  ArrayRef<uint8_t> Trie;
3244  if (DyldInfoLoadCmd)
3245    Trie = getDyldInfoExportsTrie();
3246  else if (DyldExportsTrieLoadCmd)
3247    Trie = getDyldExportsTrie();
3248
3249  return exports(Err, Trie, this);
3250}
3251
3252MachOAbstractFixupEntry::MachOAbstractFixupEntry(Error *E,
3253                                                 const MachOObjectFile *O)
3254    : E(E), O(O) {
3255  // Cache the vmaddress of __TEXT
3256  for (const auto &Command : O->load_commands()) {
3257    if (Command.C.cmd == MachO::LC_SEGMENT) {
3258      MachO::segment_command SLC = O->getSegmentLoadCommand(Command);
3259      if (StringRef(SLC.segname) == StringRef("__TEXT")) {
3260        TextAddress = SLC.vmaddr;
3261        break;
3262      }
3263    } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
3264      MachO::segment_command_64 SLC_64 = O->getSegment64LoadCommand(Command);
3265      if (StringRef(SLC_64.segname) == StringRef("__TEXT")) {
3266        TextAddress = SLC_64.vmaddr;
3267        break;
3268      }
3269    }
3270  }
3271}
3272
3273int32_t MachOAbstractFixupEntry::segmentIndex() const { return SegmentIndex; }
3274
3275uint64_t MachOAbstractFixupEntry::segmentOffset() const {
3276  return SegmentOffset;
3277}
3278
3279uint64_t MachOAbstractFixupEntry::segmentAddress() const {
3280  return O->BindRebaseAddress(SegmentIndex, 0);
3281}
3282
3283StringRef MachOAbstractFixupEntry::segmentName() const {
3284  return O->BindRebaseSegmentName(SegmentIndex);
3285}
3286
3287StringRef MachOAbstractFixupEntry::sectionName() const {
3288  return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3289}
3290
3291uint64_t MachOAbstractFixupEntry::address() const {
3292  return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3293}
3294
3295StringRef MachOAbstractFixupEntry::symbolName() const { return SymbolName; }
3296
3297int64_t MachOAbstractFixupEntry::addend() const { return Addend; }
3298
3299uint32_t MachOAbstractFixupEntry::flags() const { return Flags; }
3300
3301int MachOAbstractFixupEntry::ordinal() const { return Ordinal; }
3302
3303StringRef MachOAbstractFixupEntry::typeName() const { return "unknown"; }
3304
3305void MachOAbstractFixupEntry::moveToFirst() {
3306  SegmentOffset = 0;
3307  SegmentIndex = -1;
3308  Ordinal = 0;
3309  Flags = 0;
3310  Addend = 0;
3311  Done = false;
3312}
3313
3314void MachOAbstractFixupEntry::moveToEnd() { Done = true; }
3315
3316void MachOAbstractFixupEntry::moveNext() {}
3317
3318MachOChainedFixupEntry::MachOChainedFixupEntry(Error *E,
3319                                               const MachOObjectFile *O,
3320                                               bool Parse)
3321    : MachOAbstractFixupEntry(E, O) {
3322  ErrorAsOutParameter e(E);
3323  if (!Parse)
3324    return;
3325
3326  if (auto FixupTargetsOrErr = O->getDyldChainedFixupTargets()) {
3327    FixupTargets = *FixupTargetsOrErr;
3328  } else {
3329    *E = FixupTargetsOrErr.takeError();
3330    return;
3331  }
3332
3333  if (auto SegmentsOrErr = O->getChainedFixupsSegments()) {
3334    Segments = std::move(SegmentsOrErr->second);
3335  } else {
3336    *E = SegmentsOrErr.takeError();
3337    return;
3338  }
3339}
3340
3341void MachOChainedFixupEntry::findNextPageWithFixups() {
3342  auto FindInSegment = [this]() {
3343    const ChainedFixupsSegment &SegInfo = Segments[InfoSegIndex];
3344    while (PageIndex < SegInfo.PageStarts.size() &&
3345           SegInfo.PageStarts[PageIndex] == MachO::DYLD_CHAINED_PTR_START_NONE)
3346      ++PageIndex;
3347    return PageIndex < SegInfo.PageStarts.size();
3348  };
3349
3350  while (InfoSegIndex < Segments.size()) {
3351    if (FindInSegment()) {
3352      PageOffset = Segments[InfoSegIndex].PageStarts[PageIndex];
3353      SegmentData = O->getSegmentContents(Segments[InfoSegIndex].SegIdx);
3354      return;
3355    }
3356
3357    InfoSegIndex++;
3358    PageIndex = 0;
3359  }
3360}
3361
3362void MachOChainedFixupEntry::moveToFirst() {
3363  MachOAbstractFixupEntry::moveToFirst();
3364  if (Segments.empty()) {
3365    Done = true;
3366    return;
3367  }
3368
3369  InfoSegIndex = 0;
3370  PageIndex = 0;
3371
3372  findNextPageWithFixups();
3373  moveNext();
3374}
3375
3376void MachOChainedFixupEntry::moveToEnd() {
3377  MachOAbstractFixupEntry::moveToEnd();
3378}
3379
3380void MachOChainedFixupEntry::moveNext() {
3381  ErrorAsOutParameter ErrAsOutParam(E);
3382
3383  if (InfoSegIndex == Segments.size()) {
3384    Done = true;
3385    return;
3386  }
3387
3388  const ChainedFixupsSegment &SegInfo = Segments[InfoSegIndex];
3389  SegmentIndex = SegInfo.SegIdx;
3390  SegmentOffset = SegInfo.Header.page_size * PageIndex + PageOffset;
3391
3392  // FIXME: Handle other pointer formats.
3393  uint16_t PointerFormat = SegInfo.Header.pointer_format;
3394  if (PointerFormat != MachO::DYLD_CHAINED_PTR_64 &&
3395      PointerFormat != MachO::DYLD_CHAINED_PTR_64_OFFSET) {
3396    *E = createError("segment " + Twine(SegmentIndex) +
3397                     " has unsupported chained fixup pointer_format " +
3398                     Twine(PointerFormat));
3399    moveToEnd();
3400    return;
3401  }
3402
3403  Ordinal = 0;
3404  Flags = 0;
3405  Addend = 0;
3406  PointerValue = 0;
3407  SymbolName = {};
3408
3409  if (SegmentOffset + sizeof(RawValue) > SegmentData.size()) {
3410    *E = malformedError("fixup in segment " + Twine(SegmentIndex) +
3411                        " at offset " + Twine(SegmentOffset) +
3412                        " extends past segment's end");
3413    moveToEnd();
3414    return;
3415  }
3416
3417  static_assert(sizeof(RawValue) == sizeof(MachO::dyld_chained_import_addend));
3418  memcpy(&RawValue, SegmentData.data() + SegmentOffset, sizeof(RawValue));
3419  if (O->isLittleEndian() != sys::IsLittleEndianHost)
3420    sys::swapByteOrder(RawValue);
3421
3422  // The bit extraction below assumes little-endian fixup entries.
3423  assert(O->isLittleEndian() && "big-endian object should have been rejected "
3424                                "by getDyldChainedFixupTargets()");
3425  auto Field = [this](uint8_t Right, uint8_t Count) {
3426    return (RawValue >> Right) & ((1ULL << Count) - 1);
3427  };
3428
3429  // The `bind` field (most significant bit) of the encoded fixup determines
3430  // whether it is dyld_chained_ptr_64_bind or dyld_chained_ptr_64_rebase.
3431  bool IsBind = Field(63, 1);
3432  Kind = IsBind ? FixupKind::Bind : FixupKind::Rebase;
3433  uint32_t Next = Field(51, 12);
3434  if (IsBind) {
3435    uint32_t ImportOrdinal = Field(0, 24);
3436    uint8_t InlineAddend = Field(24, 8);
3437
3438    if (ImportOrdinal >= FixupTargets.size()) {
3439      *E = malformedError("fixup in segment " + Twine(SegmentIndex) +
3440                          " at offset " + Twine(SegmentOffset) +
3441                          "  has out-of range import ordinal " +
3442                          Twine(ImportOrdinal));
3443      moveToEnd();
3444      return;
3445    }
3446
3447    ChainedFixupTarget &Target = FixupTargets[ImportOrdinal];
3448    Ordinal = Target.libOrdinal();
3449    Addend = InlineAddend ? InlineAddend : Target.addend();
3450    Flags = Target.weakImport() ? MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT : 0;
3451    SymbolName = Target.symbolName();
3452  } else {
3453    uint64_t Target = Field(0, 36);
3454    uint64_t High8 = Field(36, 8);
3455
3456    PointerValue = Target | (High8 << 56);
3457    if (PointerFormat == MachO::DYLD_CHAINED_PTR_64_OFFSET)
3458      PointerValue += textAddress();
3459  }
3460
3461  // The stride is 4 bytes for DYLD_CHAINED_PTR_64(_OFFSET).
3462  if (Next != 0) {
3463    PageOffset += 4 * Next;
3464  } else {
3465    ++PageIndex;
3466    findNextPageWithFixups();
3467  }
3468}
3469
3470bool MachOChainedFixupEntry::operator==(
3471    const MachOChainedFixupEntry &Other) const {
3472  if (Done && Other.Done)
3473    return true;
3474  if (Done != Other.Done)
3475    return false;
3476  return InfoSegIndex == Other.InfoSegIndex && PageIndex == Other.PageIndex &&
3477         PageOffset == Other.PageOffset;
3478}
3479
3480MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,
3481                                   ArrayRef<uint8_t> Bytes, bool is64Bit)
3482    : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
3483      PointerSize(is64Bit ? 8 : 4) {}
3484
3485void MachORebaseEntry::moveToFirst() {
3486  Ptr = Opcodes.begin();
3487  moveNext();
3488}
3489
3490void MachORebaseEntry::moveToEnd() {
3491  Ptr = Opcodes.end();
3492  RemainingLoopCount = 0;
3493  Done = true;
3494}
3495
3496void MachORebaseEntry::moveNext() {
3497  ErrorAsOutParameter ErrAsOutParam(E);
3498  // If in the middle of some loop, move to next rebasing in loop.
3499  SegmentOffset += AdvanceAmount;
3500  if (RemainingLoopCount) {
3501    --RemainingLoopCount;
3502    return;
3503  }
3504  // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
3505  // pointer size. Therefore it is possible to reach the end without ever having
3506  // seen REBASE_OPCODE_DONE.
3507  if (Ptr == Opcodes.end()) {
3508    Done = true;
3509    return;
3510  }
3511  bool More = true;
3512  while (More) {
3513    // Parse next opcode and set up next loop.
3514    const uint8_t *OpcodeStart = Ptr;
3515    uint8_t Byte = *Ptr++;
3516    uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
3517    uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
3518    uint32_t Count, Skip;
3519    const char *error = nullptr;
3520    switch (Opcode) {
3521    case MachO::REBASE_OPCODE_DONE:
3522      More = false;
3523      Done = true;
3524      moveToEnd();
3525      DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n");
3526      break;
3527    case MachO::REBASE_OPCODE_SET_TYPE_IMM:
3528      RebaseType = ImmValue;
3529      if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) {
3530        *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
3531                            Twine((int)RebaseType) + " for opcode at: 0x" +
3532                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3533        moveToEnd();
3534        return;
3535      }
3536      DEBUG_WITH_TYPE(
3537          "mach-o-rebase",
3538          dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
3539                 << "RebaseType=" << (int) RebaseType << "\n");
3540      break;
3541    case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
3542      SegmentIndex = ImmValue;
3543      SegmentOffset = readULEB128(&error);
3544      if (error) {
3545        *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3546                            Twine(error) + " for opcode at: 0x" +
3547                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3548        moveToEnd();
3549        return;
3550      }
3551      error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3552                                               PointerSize);
3553      if (error) {
3554        *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3555                            Twine(error) + " for opcode at: 0x" +
3556                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3557        moveToEnd();
3558        return;
3559      }
3560      DEBUG_WITH_TYPE(
3561          "mach-o-rebase",
3562          dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3563                 << "SegmentIndex=" << SegmentIndex << ", "
3564                 << format("SegmentOffset=0x%06X", SegmentOffset)
3565                 << "\n");
3566      break;
3567    case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
3568      SegmentOffset += readULEB128(&error);
3569      if (error) {
3570        *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3571                            " for opcode at: 0x" +
3572                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3573        moveToEnd();
3574        return;
3575      }
3576      error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3577                                               PointerSize);
3578      if (error) {
3579        *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3580                            " for opcode at: 0x" +
3581                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3582        moveToEnd();
3583        return;
3584      }
3585      DEBUG_WITH_TYPE("mach-o-rebase",
3586                      dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
3587                             << format("SegmentOffset=0x%06X",
3588                                       SegmentOffset) << "\n");
3589      break;
3590    case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
3591      SegmentOffset += ImmValue * PointerSize;
3592      error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3593                                               PointerSize);
3594      if (error) {
3595        *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
3596                            Twine(error) + " for opcode at: 0x" +
3597                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3598        moveToEnd();
3599        return;
3600      }
3601      DEBUG_WITH_TYPE("mach-o-rebase",
3602                      dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
3603                             << format("SegmentOffset=0x%06X",
3604                                       SegmentOffset) << "\n");
3605      break;
3606    case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
3607      AdvanceAmount = PointerSize;
3608      Skip = 0;
3609      Count = ImmValue;
3610      if (ImmValue != 0)
3611        RemainingLoopCount = ImmValue - 1;
3612      else
3613        RemainingLoopCount = 0;
3614      error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3615                                               PointerSize, Count, Skip);
3616      if (error) {
3617        *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
3618                            Twine(error) + " for opcode at: 0x" +
3619                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3620        moveToEnd();
3621        return;
3622      }
3623      DEBUG_WITH_TYPE(
3624          "mach-o-rebase",
3625          dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
3626                 << format("SegmentOffset=0x%06X", SegmentOffset)
3627                 << ", AdvanceAmount=" << AdvanceAmount
3628                 << ", RemainingLoopCount=" << RemainingLoopCount
3629                 << "\n");
3630      return;
3631    case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
3632      AdvanceAmount = PointerSize;
3633      Skip = 0;
3634      Count = readULEB128(&error);
3635      if (error) {
3636        *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3637                            Twine(error) + " for opcode at: 0x" +
3638                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3639        moveToEnd();
3640        return;
3641      }
3642      if (Count != 0)
3643        RemainingLoopCount = Count - 1;
3644      else
3645        RemainingLoopCount = 0;
3646      error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3647                                               PointerSize, Count, Skip);
3648      if (error) {
3649        *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3650                            Twine(error) + " for opcode at: 0x" +
3651                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3652        moveToEnd();
3653        return;
3654      }
3655      DEBUG_WITH_TYPE(
3656          "mach-o-rebase",
3657          dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
3658                 << format("SegmentOffset=0x%06X", SegmentOffset)
3659                 << ", AdvanceAmount=" << AdvanceAmount
3660                 << ", RemainingLoopCount=" << RemainingLoopCount
3661                 << "\n");
3662      return;
3663    case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
3664      Skip = readULEB128(&error);
3665      if (error) {
3666        *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3667                            Twine(error) + " for opcode at: 0x" +
3668                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3669        moveToEnd();
3670        return;
3671      }
3672      AdvanceAmount = Skip + PointerSize;
3673      Count = 1;
3674      RemainingLoopCount = 0;
3675      error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3676                                               PointerSize, Count, Skip);
3677      if (error) {
3678        *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3679                            Twine(error) + " for opcode at: 0x" +
3680                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3681        moveToEnd();
3682        return;
3683      }
3684      DEBUG_WITH_TYPE(
3685          "mach-o-rebase",
3686          dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
3687                 << format("SegmentOffset=0x%06X", SegmentOffset)
3688                 << ", AdvanceAmount=" << AdvanceAmount
3689                 << ", RemainingLoopCount=" << RemainingLoopCount
3690                 << "\n");
3691      return;
3692    case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
3693      Count = readULEB128(&error);
3694      if (error) {
3695        *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3696                            "ULEB " +
3697                            Twine(error) + " for opcode at: 0x" +
3698                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3699        moveToEnd();
3700        return;
3701      }
3702      if (Count != 0)
3703        RemainingLoopCount = Count - 1;
3704      else
3705        RemainingLoopCount = 0;
3706      Skip = readULEB128(&error);
3707      if (error) {
3708        *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3709                            "ULEB " +
3710                            Twine(error) + " for opcode at: 0x" +
3711                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3712        moveToEnd();
3713        return;
3714      }
3715      AdvanceAmount = Skip + PointerSize;
3716
3717      error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3718                                               PointerSize, Count, Skip);
3719      if (error) {
3720        *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3721                            "ULEB " +
3722                            Twine(error) + " for opcode at: 0x" +
3723                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3724        moveToEnd();
3725        return;
3726      }
3727      DEBUG_WITH_TYPE(
3728          "mach-o-rebase",
3729          dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
3730                 << format("SegmentOffset=0x%06X", SegmentOffset)
3731                 << ", AdvanceAmount=" << AdvanceAmount
3732                 << ", RemainingLoopCount=" << RemainingLoopCount
3733                 << "\n");
3734      return;
3735    default:
3736      *E = malformedError("bad rebase info (bad opcode value 0x" +
3737                          Twine::utohexstr(Opcode) + " for opcode at: 0x" +
3738                          Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3739      moveToEnd();
3740      return;
3741    }
3742  }
3743}
3744
3745uint64_t MachORebaseEntry::readULEB128(const char **error) {
3746  unsigned Count;
3747  uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
3748  Ptr += Count;
3749  if (Ptr > Opcodes.end())
3750    Ptr = Opcodes.end();
3751  return Result;
3752}
3753
3754int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
3755
3756uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
3757
3758StringRef MachORebaseEntry::typeName() const {
3759  switch (RebaseType) {
3760  case MachO::REBASE_TYPE_POINTER:
3761    return "pointer";
3762  case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
3763    return "text abs32";
3764  case MachO::REBASE_TYPE_TEXT_PCREL32:
3765    return "text rel32";
3766  }
3767  return "unknown";
3768}
3769
3770// For use with the SegIndex of a checked Mach-O Rebase entry
3771// to get the segment name.
3772StringRef MachORebaseEntry::segmentName() const {
3773  return O->BindRebaseSegmentName(SegmentIndex);
3774}
3775
3776// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3777// to get the section name.
3778StringRef MachORebaseEntry::sectionName() const {
3779  return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3780}
3781
3782// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3783// to get the address.
3784uint64_t MachORebaseEntry::address() const {
3785  return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3786}
3787
3788bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
3789#ifdef EXPENSIVE_CHECKS
3790  assert(Opcodes == Other.Opcodes && "compare iterators of different files");
3791#else
3792  assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3793#endif
3794  return (Ptr == Other.Ptr) &&
3795         (RemainingLoopCount == Other.RemainingLoopCount) &&
3796         (Done == Other.Done);
3797}
3798
3799iterator_range<rebase_iterator>
3800MachOObjectFile::rebaseTable(Error &Err, MachOObjectFile *O,
3801                             ArrayRef<uint8_t> Opcodes, bool is64) {
3802  if (O->BindRebaseSectionTable == nullptr)
3803    O->BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(O);
3804  MachORebaseEntry Start(&Err, O, Opcodes, is64);
3805  Start.moveToFirst();
3806
3807  MachORebaseEntry Finish(&Err, O, Opcodes, is64);
3808  Finish.moveToEnd();
3809
3810  return make_range(rebase_iterator(Start), rebase_iterator(Finish));
3811}
3812
3813iterator_range<rebase_iterator> MachOObjectFile::rebaseTable(Error &Err) {
3814  return rebaseTable(Err, this, getDyldInfoRebaseOpcodes(), is64Bit());
3815}
3816
3817MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O,
3818                               ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
3819    : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
3820      PointerSize(is64Bit ? 8 : 4), TableKind(BK) {}
3821
3822void MachOBindEntry::moveToFirst() {
3823  Ptr = Opcodes.begin();
3824  moveNext();
3825}
3826
3827void MachOBindEntry::moveToEnd() {
3828  Ptr = Opcodes.end();
3829  RemainingLoopCount = 0;
3830  Done = true;
3831}
3832
3833void MachOBindEntry::moveNext() {
3834  ErrorAsOutParameter ErrAsOutParam(E);
3835  // If in the middle of some loop, move to next binding in loop.
3836  SegmentOffset += AdvanceAmount;
3837  if (RemainingLoopCount) {
3838    --RemainingLoopCount;
3839    return;
3840  }
3841  // BIND_OPCODE_DONE is only used for padding if we are not aligned to
3842  // pointer size. Therefore it is possible to reach the end without ever having
3843  // seen BIND_OPCODE_DONE.
3844  if (Ptr == Opcodes.end()) {
3845    Done = true;
3846    return;
3847  }
3848  bool More = true;
3849  while (More) {
3850    // Parse next opcode and set up next loop.
3851    const uint8_t *OpcodeStart = Ptr;
3852    uint8_t Byte = *Ptr++;
3853    uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
3854    uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
3855    int8_t SignExtended;
3856    const uint8_t *SymStart;
3857    uint32_t Count, Skip;
3858    const char *error = nullptr;
3859    switch (Opcode) {
3860    case MachO::BIND_OPCODE_DONE:
3861      if (TableKind == Kind::Lazy) {
3862        // Lazying bindings have a DONE opcode between entries.  Need to ignore
3863        // it to advance to next entry.  But need not if this is last entry.
3864        bool NotLastEntry = false;
3865        for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) {
3866          if (*P) {
3867            NotLastEntry = true;
3868          }
3869        }
3870        if (NotLastEntry)
3871          break;
3872      }
3873      More = false;
3874      moveToEnd();
3875      DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");
3876      break;
3877    case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
3878      if (TableKind == Kind::Weak) {
3879        *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
3880                            "weak bind table for opcode at: 0x" +
3881                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3882        moveToEnd();
3883        return;
3884      }
3885      Ordinal = ImmValue;
3886      LibraryOrdinalSet = true;
3887      if (ImmValue > O->getLibraryCount()) {
3888        *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3889                            "library ordinal: " +
3890                            Twine((int)ImmValue) + " (max " +
3891                            Twine((int)O->getLibraryCount()) +
3892                            ") for opcode at: 0x" +
3893                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3894        moveToEnd();
3895        return;
3896      }
3897      DEBUG_WITH_TYPE(
3898          "mach-o-bind",
3899          dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
3900                 << "Ordinal=" << Ordinal << "\n");
3901      break;
3902    case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
3903      if (TableKind == Kind::Weak) {
3904        *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
3905                            "weak bind table for opcode at: 0x" +
3906                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3907        moveToEnd();
3908        return;
3909      }
3910      Ordinal = readULEB128(&error);
3911      LibraryOrdinalSet = true;
3912      if (error) {
3913        *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
3914                            Twine(error) + " for opcode at: 0x" +
3915                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3916        moveToEnd();
3917        return;
3918      }
3919      if (Ordinal > (int)O->getLibraryCount()) {
3920        *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3921                            "library ordinal: " +
3922                            Twine((int)Ordinal) + " (max " +
3923                            Twine((int)O->getLibraryCount()) +
3924                            ") for opcode at: 0x" +
3925                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3926        moveToEnd();
3927        return;
3928      }
3929      DEBUG_WITH_TYPE(
3930          "mach-o-bind",
3931          dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
3932                 << "Ordinal=" << Ordinal << "\n");
3933      break;
3934    case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
3935      if (TableKind == Kind::Weak) {
3936        *E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
3937                            "weak bind table for opcode at: 0x" +
3938                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3939        moveToEnd();
3940        return;
3941      }
3942      if (ImmValue) {
3943        SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
3944        Ordinal = SignExtended;
3945        if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {
3946          *E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
3947                              "special ordinal: " +
3948                              Twine((int)Ordinal) + " for opcode at: 0x" +
3949                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3950          moveToEnd();
3951          return;
3952        }
3953      } else
3954        Ordinal = 0;
3955      LibraryOrdinalSet = true;
3956      DEBUG_WITH_TYPE(
3957          "mach-o-bind",
3958          dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
3959                 << "Ordinal=" << Ordinal << "\n");
3960      break;
3961    case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
3962      Flags = ImmValue;
3963      SymStart = Ptr;
3964      while (*Ptr && (Ptr < Opcodes.end())) {
3965        ++Ptr;
3966      }
3967      if (Ptr == Opcodes.end()) {
3968        *E = malformedError(
3969            "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
3970            "symbol name extends past opcodes for opcode at: 0x" +
3971            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3972        moveToEnd();
3973        return;
3974      }
3975      SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
3976                             Ptr-SymStart);
3977      ++Ptr;
3978      DEBUG_WITH_TYPE(
3979          "mach-o-bind",
3980          dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
3981                 << "SymbolName=" << SymbolName << "\n");
3982      if (TableKind == Kind::Weak) {
3983        if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
3984          return;
3985      }
3986      break;
3987    case MachO::BIND_OPCODE_SET_TYPE_IMM:
3988      BindType = ImmValue;
3989      if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) {
3990        *E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
3991                            Twine((int)ImmValue) + " for opcode at: 0x" +
3992                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3993        moveToEnd();
3994        return;
3995      }
3996      DEBUG_WITH_TYPE(
3997          "mach-o-bind",
3998          dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
3999                 << "BindType=" << (int)BindType << "\n");
4000      break;
4001    case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
4002      Addend = readSLEB128(&error);
4003      if (error) {
4004        *E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error) +
4005                            " for opcode at: 0x" +
4006                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4007        moveToEnd();
4008        return;
4009      }
4010      DEBUG_WITH_TYPE(
4011          "mach-o-bind",
4012          dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
4013                 << "Addend=" << Addend << "\n");
4014      break;
4015    case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
4016      SegmentIndex = ImmValue;
4017      SegmentOffset = readULEB128(&error);
4018      if (error) {
4019        *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
4020                            Twine(error) + " for opcode at: 0x" +
4021                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4022        moveToEnd();
4023        return;
4024      }
4025      error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
4026                                             PointerSize);
4027      if (error) {
4028        *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
4029                            Twine(error) + " for opcode at: 0x" +
4030                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4031        moveToEnd();
4032        return;
4033      }
4034      DEBUG_WITH_TYPE(
4035          "mach-o-bind",
4036          dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
4037                 << "SegmentIndex=" << SegmentIndex << ", "
4038                 << format("SegmentOffset=0x%06X", SegmentOffset)
4039                 << "\n");
4040      break;
4041    case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
4042      SegmentOffset += readULEB128(&error);
4043      if (error) {
4044        *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
4045                            " for opcode at: 0x" +
4046                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4047        moveToEnd();
4048        return;
4049      }
4050      error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
4051                                             PointerSize);
4052      if (error) {
4053        *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
4054                            " for opcode at: 0x" +
4055                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4056        moveToEnd();
4057        return;
4058      }
4059      DEBUG_WITH_TYPE("mach-o-bind",
4060                      dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
4061                             << format("SegmentOffset=0x%06X",
4062                                       SegmentOffset) << "\n");
4063      break;
4064    case MachO::BIND_OPCODE_DO_BIND:
4065      AdvanceAmount = PointerSize;
4066      RemainingLoopCount = 0;
4067      error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
4068                                             PointerSize);
4069      if (error) {
4070        *E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) +
4071                            " for opcode at: 0x" +
4072                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4073        moveToEnd();
4074        return;
4075      }
4076      if (SymbolName == StringRef()) {
4077        *E = malformedError(
4078            "for BIND_OPCODE_DO_BIND missing preceding "
4079            "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
4080            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4081        moveToEnd();
4082        return;
4083      }
4084      if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
4085        *E =
4086            malformedError("for BIND_OPCODE_DO_BIND missing preceding "
4087                           "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
4088                           Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4089        moveToEnd();
4090        return;
4091      }
4092      DEBUG_WITH_TYPE("mach-o-bind",
4093                      dbgs() << "BIND_OPCODE_DO_BIND: "
4094                             << format("SegmentOffset=0x%06X",
4095                                       SegmentOffset) << "\n");
4096      return;
4097     case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
4098      if (TableKind == Kind::Lazy) {
4099        *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
4100                            "lazy bind table for opcode at: 0x" +
4101                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4102        moveToEnd();
4103        return;
4104      }
4105      error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
4106                                             PointerSize);
4107      if (error) {
4108        *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
4109                            Twine(error) + " for opcode at: 0x" +
4110                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4111        moveToEnd();
4112        return;
4113      }
4114      if (SymbolName == StringRef()) {
4115        *E = malformedError(
4116            "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
4117            "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
4118            "at: 0x" +
4119            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4120        moveToEnd();
4121        return;
4122      }
4123      if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
4124        *E = malformedError(
4125            "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
4126            "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
4127            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4128        moveToEnd();
4129        return;
4130      }
4131      AdvanceAmount = readULEB128(&error) + PointerSize;
4132      if (error) {
4133        *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
4134                            Twine(error) + " for opcode at: 0x" +
4135                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4136        moveToEnd();
4137        return;
4138      }
4139      // Note, this is not really an error until the next bind but make no sense
4140      // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
4141      // bind operation.
4142      error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset +
4143                                            AdvanceAmount, PointerSize);
4144      if (error) {
4145        *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
4146                            "ULEB) " +
4147                            Twine(error) + " for opcode at: 0x" +
4148                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4149        moveToEnd();
4150        return;
4151      }
4152      RemainingLoopCount = 0;
4153      DEBUG_WITH_TYPE(
4154          "mach-o-bind",
4155          dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
4156                 << format("SegmentOffset=0x%06X", SegmentOffset)
4157                 << ", AdvanceAmount=" << AdvanceAmount
4158                 << ", RemainingLoopCount=" << RemainingLoopCount
4159                 << "\n");
4160      return;
4161    case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
4162      if (TableKind == Kind::Lazy) {
4163        *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
4164                            "allowed in lazy bind table for opcode at: 0x" +
4165                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4166        moveToEnd();
4167        return;
4168      }
4169      if (SymbolName == StringRef()) {
4170        *E = malformedError(
4171            "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
4172            "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
4173            "opcode at: 0x" +
4174            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4175        moveToEnd();
4176        return;
4177      }
4178      if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
4179        *E = malformedError(
4180            "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
4181            "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
4182            "at: 0x" +
4183            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4184        moveToEnd();
4185        return;
4186      }
4187      AdvanceAmount = ImmValue * PointerSize + PointerSize;
4188      RemainingLoopCount = 0;
4189      error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset +
4190                                             AdvanceAmount, PointerSize);
4191      if (error) {
4192        *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
4193                            Twine(error) + " for opcode at: 0x" +
4194                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4195        moveToEnd();
4196        return;
4197      }
4198      DEBUG_WITH_TYPE("mach-o-bind",
4199                      dbgs()
4200                      << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
4201                      << format("SegmentOffset=0x%06X", SegmentOffset) << "\n");
4202      return;
4203    case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
4204      if (TableKind == Kind::Lazy) {
4205        *E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
4206                            "allowed in lazy bind table for opcode at: 0x" +
4207                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4208        moveToEnd();
4209        return;
4210      }
4211      Count = readULEB128(&error);
4212      if (Count != 0)
4213        RemainingLoopCount = Count - 1;
4214      else
4215        RemainingLoopCount = 0;
4216      if (error) {
4217        *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
4218                            " (count value) " +
4219                            Twine(error) + " for opcode at: 0x" +
4220                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4221        moveToEnd();
4222        return;
4223      }
4224      Skip = readULEB128(&error);
4225      AdvanceAmount = Skip + PointerSize;
4226      if (error) {
4227        *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
4228                            " (skip value) " +
4229                            Twine(error) + " for opcode at: 0x" +
4230                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4231        moveToEnd();
4232        return;
4233      }
4234      if (SymbolName == StringRef()) {
4235        *E = malformedError(
4236            "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
4237            "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
4238            "opcode at: 0x" +
4239            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4240        moveToEnd();
4241        return;
4242      }
4243      if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
4244        *E = malformedError(
4245            "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
4246            "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
4247            "at: 0x" +
4248            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4249        moveToEnd();
4250        return;
4251      }
4252      error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
4253                                             PointerSize, Count, Skip);
4254      if (error) {
4255        *E =
4256            malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
4257                           Twine(error) + " for opcode at: 0x" +
4258                           Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4259        moveToEnd();
4260        return;
4261      }
4262      DEBUG_WITH_TYPE(
4263          "mach-o-bind",
4264          dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
4265                 << format("SegmentOffset=0x%06X", SegmentOffset)
4266                 << ", AdvanceAmount=" << AdvanceAmount
4267                 << ", RemainingLoopCount=" << RemainingLoopCount
4268                 << "\n");
4269      return;
4270    default:
4271      *E = malformedError("bad bind info (bad opcode value 0x" +
4272                          Twine::utohexstr(Opcode) + " for opcode at: 0x" +
4273                          Twine::utohexstr(OpcodeStart - Opcodes.begin()));
4274      moveToEnd();
4275      return;
4276    }
4277  }
4278}
4279
4280uint64_t MachOBindEntry::readULEB128(const char **error) {
4281  unsigned Count;
4282  uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
4283  Ptr += Count;
4284  if (Ptr > Opcodes.end())
4285    Ptr = Opcodes.end();
4286  return Result;
4287}
4288
4289int64_t MachOBindEntry::readSLEB128(const char **error) {
4290  unsigned Count;
4291  int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error);
4292  Ptr += Count;
4293  if (Ptr > Opcodes.end())
4294    Ptr = Opcodes.end();
4295  return Result;
4296}
4297
4298int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
4299
4300uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
4301
4302StringRef MachOBindEntry::typeName() const {
4303  switch (BindType) {
4304  case MachO::BIND_TYPE_POINTER:
4305    return "pointer";
4306  case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
4307    return "text abs32";
4308  case MachO::BIND_TYPE_TEXT_PCREL32:
4309    return "text rel32";
4310  }
4311  return "unknown";
4312}
4313
4314StringRef MachOBindEntry::symbolName() const { return SymbolName; }
4315
4316int64_t MachOBindEntry::addend() const { return Addend; }
4317
4318uint32_t MachOBindEntry::flags() const { return Flags; }
4319
4320int MachOBindEntry::ordinal() const { return Ordinal; }
4321
4322// For use with the SegIndex of a checked Mach-O Bind entry
4323// to get the segment name.
4324StringRef MachOBindEntry::segmentName() const {
4325  return O->BindRebaseSegmentName(SegmentIndex);
4326}
4327
4328// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
4329// to get the section name.
4330StringRef MachOBindEntry::sectionName() const {
4331  return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
4332}
4333
4334// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
4335// to get the address.
4336uint64_t MachOBindEntry::address() const {
4337  return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
4338}
4339
4340bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
4341#ifdef EXPENSIVE_CHECKS
4342  assert(Opcodes == Other.Opcodes && "compare iterators of different files");
4343#else
4344  assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
4345#endif
4346  return (Ptr == Other.Ptr) &&
4347         (RemainingLoopCount == Other.RemainingLoopCount) &&
4348         (Done == Other.Done);
4349}
4350
4351// Build table of sections so SegIndex/SegOffset pairs can be translated.
4352BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
4353  uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
4354  StringRef CurSegName;
4355  uint64_t CurSegAddress;
4356  for (const SectionRef &Section : Obj->sections()) {
4357    SectionInfo Info;
4358    Expected<StringRef> NameOrErr = Section.getName();
4359    if (!NameOrErr)
4360      consumeError(NameOrErr.takeError());
4361    else
4362      Info.SectionName = *NameOrErr;
4363    Info.Address = Section.getAddress();
4364    Info.Size = Section.getSize();
4365    Info.SegmentName =
4366        Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
4367    if (!Info.SegmentName.equals(CurSegName)) {
4368      ++CurSegIndex;
4369      CurSegName = Info.SegmentName;
4370      CurSegAddress = Info.Address;
4371    }
4372    Info.SegmentIndex = CurSegIndex - 1;
4373    Info.OffsetInSegment = Info.Address - CurSegAddress;
4374    Info.SegmentStartAddress = CurSegAddress;
4375    Sections.push_back(Info);
4376  }
4377  MaxSegIndex = CurSegIndex;
4378}
4379
4380// For use with a SegIndex, SegOffset, and PointerSize triple in
4381// MachOBindEntry::moveNext() to validate a MachOBindEntry or MachORebaseEntry.
4382//
4383// Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
4384// that fully contains a pointer at that location. Multiple fixups in a bind
4385// (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can
4386// be tested via the Count and Skip parameters.
4387const char * BindRebaseSegInfo::checkSegAndOffsets(int32_t SegIndex,
4388                                                   uint64_t SegOffset,
4389                                                   uint8_t PointerSize,
4390                                                   uint32_t Count,
4391                                                   uint32_t Skip) {
4392  if (SegIndex == -1)
4393    return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
4394  if (SegIndex >= MaxSegIndex)
4395    return "bad segIndex (too large)";
4396  for (uint32_t i = 0; i < Count; ++i) {
4397    uint32_t Start = SegOffset + i * (PointerSize + Skip);
4398    uint32_t End = Start + PointerSize;
4399    bool Found = false;
4400    for (const SectionInfo &SI : Sections) {
4401      if (SI.SegmentIndex != SegIndex)
4402        continue;
4403      if ((SI.OffsetInSegment<=Start) && (Start<(SI.OffsetInSegment+SI.Size))) {
4404        if (End <= SI.OffsetInSegment + SI.Size) {
4405          Found = true;
4406          break;
4407        }
4408        else
4409          return "bad offset, extends beyond section boundary";
4410      }
4411    }
4412    if (!Found)
4413      return "bad offset, not in section";
4414  }
4415  return nullptr;
4416}
4417
4418// For use with the SegIndex of a checked Mach-O Bind or Rebase entry
4419// to get the segment name.
4420StringRef BindRebaseSegInfo::segmentName(int32_t SegIndex) {
4421  for (const SectionInfo &SI : Sections) {
4422    if (SI.SegmentIndex == SegIndex)
4423      return SI.SegmentName;
4424  }
4425  llvm_unreachable("invalid SegIndex");
4426}
4427
4428// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4429// to get the SectionInfo.
4430const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection(
4431                                     int32_t SegIndex, uint64_t SegOffset) {
4432  for (const SectionInfo &SI : Sections) {
4433    if (SI.SegmentIndex != SegIndex)
4434      continue;
4435    if (SI.OffsetInSegment > SegOffset)
4436      continue;
4437    if (SegOffset >= (SI.OffsetInSegment + SI.Size))
4438      continue;
4439    return SI;
4440  }
4441  llvm_unreachable("SegIndex and SegOffset not in any section");
4442}
4443
4444// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4445// entry to get the section name.
4446StringRef BindRebaseSegInfo::sectionName(int32_t SegIndex,
4447                                         uint64_t SegOffset) {
4448  return findSection(SegIndex, SegOffset).SectionName;
4449}
4450
4451// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase
4452// entry to get the address.
4453uint64_t BindRebaseSegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {
4454  const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
4455  return SI.SegmentStartAddress + OffsetInSeg;
4456}
4457
4458iterator_range<bind_iterator>
4459MachOObjectFile::bindTable(Error &Err, MachOObjectFile *O,
4460                           ArrayRef<uint8_t> Opcodes, bool is64,
4461                           MachOBindEntry::Kind BKind) {
4462  if (O->BindRebaseSectionTable == nullptr)
4463    O->BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(O);
4464  MachOBindEntry Start(&Err, O, Opcodes, is64, BKind);
4465  Start.moveToFirst();
4466
4467  MachOBindEntry Finish(&Err, O, Opcodes, is64, BKind);
4468  Finish.moveToEnd();
4469
4470  return make_range(bind_iterator(Start), bind_iterator(Finish));
4471}
4472
4473iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) {
4474  return bindTable(Err, this, getDyldInfoBindOpcodes(), is64Bit(),
4475                   MachOBindEntry::Kind::Regular);
4476}
4477
4478iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) {
4479  return bindTable(Err, this, getDyldInfoLazyBindOpcodes(), is64Bit(),
4480                   MachOBindEntry::Kind::Lazy);
4481}
4482
4483iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) {
4484  return bindTable(Err, this, getDyldInfoWeakBindOpcodes(), is64Bit(),
4485                   MachOBindEntry::Kind::Weak);
4486}
4487
4488iterator_range<fixup_iterator> MachOObjectFile::fixupTable(Error &Err) {
4489  if (BindRebaseSectionTable == nullptr)
4490    BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(this);
4491
4492  MachOChainedFixupEntry Start(&Err, this, true);
4493  Start.moveToFirst();
4494
4495  MachOChainedFixupEntry Finish(&Err, this, false);
4496  Finish.moveToEnd();
4497
4498  return make_range(fixup_iterator(Start), fixup_iterator(Finish));
4499}
4500
4501MachOObjectFile::load_command_iterator
4502MachOObjectFile::begin_load_commands() const {
4503  return LoadCommands.begin();
4504}
4505
4506MachOObjectFile::load_command_iterator
4507MachOObjectFile::end_load_commands() const {
4508  return LoadCommands.end();
4509}
4510
4511iterator_range<MachOObjectFile::load_command_iterator>
4512MachOObjectFile::load_commands() const {
4513  return make_range(begin_load_commands(), end_load_commands());
4514}
4515
4516StringRef
4517MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
4518  ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);
4519  return parseSegmentOrSectionName(Raw.data());
4520}
4521
4522ArrayRef<char>
4523MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
4524  assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
4525  const section_base *Base =
4526    reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
4527  return ArrayRef(Base->sectname);
4528}
4529
4530ArrayRef<char>
4531MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
4532  assert(Sec.d.a < Sections.size() && "Should have detected this earlier");
4533  const section_base *Base =
4534    reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
4535  return ArrayRef(Base->segname);
4536}
4537
4538bool
4539MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE)
4540  const {
4541  if (getCPUType(*this) == MachO::CPU_TYPE_X86_64)
4542    return false;
4543  return getPlainRelocationAddress(RE) & MachO::R_SCATTERED;
4544}
4545
4546unsigned MachOObjectFile::getPlainRelocationSymbolNum(
4547    const MachO::any_relocation_info &RE) const {
4548  if (isLittleEndian())
4549    return RE.r_word1 & 0xffffff;
4550  return RE.r_word1 >> 8;
4551}
4552
4553bool MachOObjectFile::getPlainRelocationExternal(
4554    const MachO::any_relocation_info &RE) const {
4555  if (isLittleEndian())
4556    return (RE.r_word1 >> 27) & 1;
4557  return (RE.r_word1 >> 4) & 1;
4558}
4559
4560bool MachOObjectFile::getScatteredRelocationScattered(
4561    const MachO::any_relocation_info &RE) const {
4562  return RE.r_word0 >> 31;
4563}
4564
4565uint32_t MachOObjectFile::getScatteredRelocationValue(
4566    const MachO::any_relocation_info &RE) const {
4567  return RE.r_word1;
4568}
4569
4570uint32_t MachOObjectFile::getScatteredRelocationType(
4571    const MachO::any_relocation_info &RE) const {
4572  return (RE.r_word0 >> 24) & 0xf;
4573}
4574
4575unsigned MachOObjectFile::getAnyRelocationAddress(
4576    const MachO::any_relocation_info &RE) const {
4577  if (isRelocationScattered(RE))
4578    return getScatteredRelocationAddress(RE);
4579  return getPlainRelocationAddress(RE);
4580}
4581
4582unsigned MachOObjectFile::getAnyRelocationPCRel(
4583    const MachO::any_relocation_info &RE) const {
4584  if (isRelocationScattered(RE))
4585    return getScatteredRelocationPCRel(RE);
4586  return getPlainRelocationPCRel(*this, RE);
4587}
4588
4589unsigned MachOObjectFile::getAnyRelocationLength(
4590    const MachO::any_relocation_info &RE) const {
4591  if (isRelocationScattered(RE))
4592    return getScatteredRelocationLength(RE);
4593  return getPlainRelocationLength(*this, RE);
4594}
4595
4596unsigned
4597MachOObjectFile::getAnyRelocationType(
4598                                   const MachO::any_relocation_info &RE) const {
4599  if (isRelocationScattered(RE))
4600    return getScatteredRelocationType(RE);
4601  return getPlainRelocationType(*this, RE);
4602}
4603
4604SectionRef
4605MachOObjectFile::getAnyRelocationSection(
4606                                   const MachO::any_relocation_info &RE) const {
4607  if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
4608    return *section_end();
4609  unsigned SecNum = getPlainRelocationSymbolNum(RE);
4610  if (SecNum == MachO::R_ABS || SecNum > Sections.size())
4611    return *section_end();
4612  DataRefImpl DRI;
4613  DRI.d.a = SecNum - 1;
4614  return SectionRef(DRI, this);
4615}
4616
4617MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
4618  assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
4619  return getStruct<MachO::section>(*this, Sections[DRI.d.a]);
4620}
4621
4622MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
4623  assert(DRI.d.a < Sections.size() && "Should have detected this earlier");
4624  return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]);
4625}
4626
4627MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L,
4628                                           unsigned Index) const {
4629  const char *Sec = getSectionPtr(*this, L, Index);
4630  return getStruct<MachO::section>(*this, Sec);
4631}
4632
4633MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L,
4634                                                unsigned Index) const {
4635  const char *Sec = getSectionPtr(*this, L, Index);
4636  return getStruct<MachO::section_64>(*this, Sec);
4637}
4638
4639MachO::nlist
4640MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const {
4641  const char *P = reinterpret_cast<const char *>(DRI.p);
4642  return getStruct<MachO::nlist>(*this, P);
4643}
4644
4645MachO::nlist_64
4646MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const {
4647  const char *P = reinterpret_cast<const char *>(DRI.p);
4648  return getStruct<MachO::nlist_64>(*this, P);
4649}
4650
4651MachO::linkedit_data_command
4652MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const {
4653  return getStruct<MachO::linkedit_data_command>(*this, L.Ptr);
4654}
4655
4656MachO::segment_command
4657MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const {
4658  return getStruct<MachO::segment_command>(*this, L.Ptr);
4659}
4660
4661MachO::segment_command_64
4662MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const {
4663  return getStruct<MachO::segment_command_64>(*this, L.Ptr);
4664}
4665
4666MachO::linker_option_command
4667MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const {
4668  return getStruct<MachO::linker_option_command>(*this, L.Ptr);
4669}
4670
4671MachO::version_min_command
4672MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const {
4673  return getStruct<MachO::version_min_command>(*this, L.Ptr);
4674}
4675
4676MachO::note_command
4677MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo &L) const {
4678  return getStruct<MachO::note_command>(*this, L.Ptr);
4679}
4680
4681MachO::build_version_command
4682MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo &L) const {
4683  return getStruct<MachO::build_version_command>(*this, L.Ptr);
4684}
4685
4686MachO::build_tool_version
4687MachOObjectFile::getBuildToolVersion(unsigned index) const {
4688  return getStruct<MachO::build_tool_version>(*this, BuildTools[index]);
4689}
4690
4691MachO::dylib_command
4692MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const {
4693  return getStruct<MachO::dylib_command>(*this, L.Ptr);
4694}
4695
4696MachO::dyld_info_command
4697MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const {
4698  return getStruct<MachO::dyld_info_command>(*this, L.Ptr);
4699}
4700
4701MachO::dylinker_command
4702MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const {
4703  return getStruct<MachO::dylinker_command>(*this, L.Ptr);
4704}
4705
4706MachO::uuid_command
4707MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const {
4708  return getStruct<MachO::uuid_command>(*this, L.Ptr);
4709}
4710
4711MachO::rpath_command
4712MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const {
4713  return getStruct<MachO::rpath_command>(*this, L.Ptr);
4714}
4715
4716MachO::source_version_command
4717MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const {
4718  return getStruct<MachO::source_version_command>(*this, L.Ptr);
4719}
4720
4721MachO::entry_point_command
4722MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const {
4723  return getStruct<MachO::entry_point_command>(*this, L.Ptr);
4724}
4725
4726MachO::encryption_info_command
4727MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const {
4728  return getStruct<MachO::encryption_info_command>(*this, L.Ptr);
4729}
4730
4731MachO::encryption_info_command_64
4732MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const {
4733  return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr);
4734}
4735
4736MachO::sub_framework_command
4737MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const {
4738  return getStruct<MachO::sub_framework_command>(*this, L.Ptr);
4739}
4740
4741MachO::sub_umbrella_command
4742MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const {
4743  return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr);
4744}
4745
4746MachO::sub_library_command
4747MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const {
4748  return getStruct<MachO::sub_library_command>(*this, L.Ptr);
4749}
4750
4751MachO::sub_client_command
4752MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const {
4753  return getStruct<MachO::sub_client_command>(*this, L.Ptr);
4754}
4755
4756MachO::routines_command
4757MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const {
4758  return getStruct<MachO::routines_command>(*this, L.Ptr);
4759}
4760
4761MachO::routines_command_64
4762MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const {
4763  return getStruct<MachO::routines_command_64>(*this, L.Ptr);
4764}
4765
4766MachO::thread_command
4767MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
4768  return getStruct<MachO::thread_command>(*this, L.Ptr);
4769}
4770
4771MachO::fileset_entry_command
4772MachOObjectFile::getFilesetEntryLoadCommand(const LoadCommandInfo &L) const {
4773  return getStruct<MachO::fileset_entry_command>(*this, L.Ptr);
4774}
4775
4776MachO::any_relocation_info
4777MachOObjectFile::getRelocation(DataRefImpl Rel) const {
4778  uint32_t Offset;
4779  if (getHeader().filetype == MachO::MH_OBJECT) {
4780    DataRefImpl Sec;
4781    Sec.d.a = Rel.d.a;
4782    if (is64Bit()) {
4783      MachO::section_64 Sect = getSection64(Sec);
4784      Offset = Sect.reloff;
4785    } else {
4786      MachO::section Sect = getSection(Sec);
4787      Offset = Sect.reloff;
4788    }
4789  } else {
4790    MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
4791    if (Rel.d.a == 0)
4792      Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations
4793    else
4794      Offset = DysymtabLoadCmd.locreloff; // Offset to the local relocations
4795  }
4796
4797  auto P = reinterpret_cast<const MachO::any_relocation_info *>(
4798      getPtr(*this, Offset)) + Rel.d.b;
4799  return getStruct<MachO::any_relocation_info>(
4800      *this, reinterpret_cast<const char *>(P));
4801}
4802
4803MachO::data_in_code_entry
4804MachOObjectFile::getDice(DataRefImpl Rel) const {
4805  const char *P = reinterpret_cast<const char *>(Rel.p);
4806  return getStruct<MachO::data_in_code_entry>(*this, P);
4807}
4808
4809const MachO::mach_header &MachOObjectFile::getHeader() const {
4810  return Header;
4811}
4812
4813const MachO::mach_header_64 &MachOObjectFile::getHeader64() const {
4814  assert(is64Bit());
4815  return Header64;
4816}
4817
4818uint32_t MachOObjectFile::getIndirectSymbolTableEntry(
4819                                             const MachO::dysymtab_command &DLC,
4820                                             unsigned Index) const {
4821  uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t);
4822  return getStruct<uint32_t>(*this, getPtr(*this, Offset));
4823}
4824
4825MachO::data_in_code_entry
4826MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset,
4827                                         unsigned Index) const {
4828  uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry);
4829  return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset));
4830}
4831
4832MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const {
4833  if (SymtabLoadCmd)
4834    return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
4835
4836  // If there is no SymtabLoadCmd return a load command with zero'ed fields.
4837  MachO::symtab_command Cmd;
4838  Cmd.cmd = MachO::LC_SYMTAB;
4839  Cmd.cmdsize = sizeof(MachO::symtab_command);
4840  Cmd.symoff = 0;
4841  Cmd.nsyms = 0;
4842  Cmd.stroff = 0;
4843  Cmd.strsize = 0;
4844  return Cmd;
4845}
4846
4847MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const {
4848  if (DysymtabLoadCmd)
4849    return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
4850
4851  // If there is no DysymtabLoadCmd return a load command with zero'ed fields.
4852  MachO::dysymtab_command Cmd;
4853  Cmd.cmd = MachO::LC_DYSYMTAB;
4854  Cmd.cmdsize = sizeof(MachO::dysymtab_command);
4855  Cmd.ilocalsym = 0;
4856  Cmd.nlocalsym = 0;
4857  Cmd.iextdefsym = 0;
4858  Cmd.nextdefsym = 0;
4859  Cmd.iundefsym = 0;
4860  Cmd.nundefsym = 0;
4861  Cmd.tocoff = 0;
4862  Cmd.ntoc = 0;
4863  Cmd.modtaboff = 0;
4864  Cmd.nmodtab = 0;
4865  Cmd.extrefsymoff = 0;
4866  Cmd.nextrefsyms = 0;
4867  Cmd.indirectsymoff = 0;
4868  Cmd.nindirectsyms = 0;
4869  Cmd.extreloff = 0;
4870  Cmd.nextrel = 0;
4871  Cmd.locreloff = 0;
4872  Cmd.nlocrel = 0;
4873  return Cmd;
4874}
4875
4876MachO::linkedit_data_command
4877MachOObjectFile::getDataInCodeLoadCommand() const {
4878  if (DataInCodeLoadCmd)
4879    return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd);
4880
4881  // If there is no DataInCodeLoadCmd return a load command with zero'ed fields.
4882  MachO::linkedit_data_command Cmd;
4883  Cmd.cmd = MachO::LC_DATA_IN_CODE;
4884  Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4885  Cmd.dataoff = 0;
4886  Cmd.datasize = 0;
4887  return Cmd;
4888}
4889
4890MachO::linkedit_data_command
4891MachOObjectFile::getLinkOptHintsLoadCommand() const {
4892  if (LinkOptHintsLoadCmd)
4893    return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd);
4894
4895  // If there is no LinkOptHintsLoadCmd return a load command with zero'ed
4896  // fields.
4897  MachO::linkedit_data_command Cmd;
4898  Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT;
4899  Cmd.cmdsize = sizeof(MachO::linkedit_data_command);
4900  Cmd.dataoff = 0;
4901  Cmd.datasize = 0;
4902  return Cmd;
4903}
4904
4905ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {
4906  if (!DyldInfoLoadCmd)
4907    return std::nullopt;
4908
4909  auto DyldInfoOrErr =
4910    getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4911  if (!DyldInfoOrErr)
4912    return std::nullopt;
4913  MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
4914  const uint8_t *Ptr =
4915      reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off));
4916  return ArrayRef(Ptr, DyldInfo.rebase_size);
4917}
4918
4919ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {
4920  if (!DyldInfoLoadCmd)
4921    return std::nullopt;
4922
4923  auto DyldInfoOrErr =
4924    getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4925  if (!DyldInfoOrErr)
4926    return std::nullopt;
4927  MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
4928  const uint8_t *Ptr =
4929      reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off));
4930  return ArrayRef(Ptr, DyldInfo.bind_size);
4931}
4932
4933ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {
4934  if (!DyldInfoLoadCmd)
4935    return std::nullopt;
4936
4937  auto DyldInfoOrErr =
4938    getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4939  if (!DyldInfoOrErr)
4940    return std::nullopt;
4941  MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
4942  const uint8_t *Ptr =
4943      reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off));
4944  return ArrayRef(Ptr, DyldInfo.weak_bind_size);
4945}
4946
4947ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
4948  if (!DyldInfoLoadCmd)
4949    return std::nullopt;
4950
4951  auto DyldInfoOrErr =
4952      getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4953  if (!DyldInfoOrErr)
4954    return std::nullopt;
4955  MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
4956  const uint8_t *Ptr =
4957      reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off));
4958  return ArrayRef(Ptr, DyldInfo.lazy_bind_size);
4959}
4960
4961ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {
4962  if (!DyldInfoLoadCmd)
4963    return std::nullopt;
4964
4965  auto DyldInfoOrErr =
4966      getStructOrErr<MachO::dyld_info_command>(*this, DyldInfoLoadCmd);
4967  if (!DyldInfoOrErr)
4968    return std::nullopt;
4969  MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
4970  const uint8_t *Ptr =
4971      reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off));
4972  return ArrayRef(Ptr, DyldInfo.export_size);
4973}
4974
4975Expected<std::optional<MachO::linkedit_data_command>>
4976MachOObjectFile::getChainedFixupsLoadCommand() const {
4977  // Load the dyld chained fixups load command.
4978  if (!DyldChainedFixupsLoadCmd)
4979    return std::nullopt;
4980  auto DyldChainedFixupsOrErr = getStructOrErr<MachO::linkedit_data_command>(
4981      *this, DyldChainedFixupsLoadCmd);
4982  if (!DyldChainedFixupsOrErr)
4983    return DyldChainedFixupsOrErr.takeError();
4984  const MachO::linkedit_data_command &DyldChainedFixups =
4985      *DyldChainedFixupsOrErr;
4986
4987  // If the load command is present but the data offset has been zeroed out,
4988  // as is the case for dylib stubs, return std::nullopt (no error).
4989  if (!DyldChainedFixups.dataoff)
4990    return std::nullopt;
4991  return DyldChainedFixups;
4992}
4993
4994Expected<std::optional<MachO::dyld_chained_fixups_header>>
4995MachOObjectFile::getChainedFixupsHeader() const {
4996  auto CFOrErr = getChainedFixupsLoadCommand();
4997  if (!CFOrErr)
4998    return CFOrErr.takeError();
4999  if (!CFOrErr->has_value())
5000    return std::nullopt;
5001
5002  const MachO::linkedit_data_command &DyldChainedFixups = **CFOrErr;
5003
5004  uint64_t CFHeaderOffset = DyldChainedFixups.dataoff;
5005  uint64_t CFSize = DyldChainedFixups.datasize;
5006
5007  // Load the dyld chained fixups header.
5008  const char *CFHeaderPtr = getPtr(*this, CFHeaderOffset);
5009  auto CFHeaderOrErr =
5010      getStructOrErr<MachO::dyld_chained_fixups_header>(*this, CFHeaderPtr);
5011  if (!CFHeaderOrErr)
5012    return CFHeaderOrErr.takeError();
5013  MachO::dyld_chained_fixups_header CFHeader = CFHeaderOrErr.get();
5014
5015  // Reject unknown chained fixup formats.
5016  if (CFHeader.fixups_version != 0)
5017    return malformedError(Twine("bad chained fixups: unknown version: ") +
5018                          Twine(CFHeader.fixups_version));
5019  if (CFHeader.imports_format < 1 || CFHeader.imports_format > 3)
5020    return malformedError(
5021        Twine("bad chained fixups: unknown imports format: ") +
5022        Twine(CFHeader.imports_format));
5023
5024  // Validate the image format.
5025  //
5026  // Load the image starts.
5027  uint64_t CFImageStartsOffset = (CFHeaderOffset + CFHeader.starts_offset);
5028  if (CFHeader.starts_offset < sizeof(MachO::dyld_chained_fixups_header)) {
5029    return malformedError(Twine("bad chained fixups: image starts offset ") +
5030                          Twine(CFHeader.starts_offset) +
5031                          " overlaps with chained fixups header");
5032  }
5033  uint32_t EndOffset = CFHeaderOffset + CFSize;
5034  if (CFImageStartsOffset + sizeof(MachO::dyld_chained_starts_in_image) >
5035      EndOffset) {
5036    return malformedError(Twine("bad chained fixups: image starts end ") +
5037                          Twine(CFImageStartsOffset +
5038                                sizeof(MachO::dyld_chained_starts_in_image)) +
5039                          " extends past end " + Twine(EndOffset));
5040  }
5041
5042  return CFHeader;
5043}
5044
5045Expected<std::pair<size_t, std::vector<ChainedFixupsSegment>>>
5046MachOObjectFile::getChainedFixupsSegments() const {
5047  auto CFOrErr = getChainedFixupsLoadCommand();
5048  if (!CFOrErr)
5049    return CFOrErr.takeError();
5050
5051  std::vector<ChainedFixupsSegment> Segments;
5052  if (!CFOrErr->has_value())
5053    return std::make_pair(0, Segments);
5054
5055  const MachO::linkedit_data_command &DyldChainedFixups = **CFOrErr;
5056
5057  auto HeaderOrErr = getChainedFixupsHeader();
5058  if (!HeaderOrErr)
5059    return HeaderOrErr.takeError();
5060  if (!HeaderOrErr->has_value())
5061    return std::make_pair(0, Segments);
5062  const MachO::dyld_chained_fixups_header &Header = **HeaderOrErr;
5063
5064  const char *Contents = getPtr(*this, DyldChainedFixups.dataoff);
5065
5066  auto ImageStartsOrErr = getStructOrErr<MachO::dyld_chained_starts_in_image>(
5067      *this, Contents + Header.starts_offset);
5068  if (!ImageStartsOrErr)
5069    return ImageStartsOrErr.takeError();
5070  const MachO::dyld_chained_starts_in_image &ImageStarts = *ImageStartsOrErr;
5071
5072  const char *SegOffsPtr =
5073      Contents + Header.starts_offset +
5074      offsetof(MachO::dyld_chained_starts_in_image, seg_info_offset);
5075  const char *SegOffsEnd =
5076      SegOffsPtr + ImageStarts.seg_count * sizeof(uint32_t);
5077  if (SegOffsEnd > Contents + DyldChainedFixups.datasize)
5078    return malformedError(
5079        "bad chained fixups: seg_info_offset extends past end");
5080
5081  const char *LastSegEnd = nullptr;
5082  for (size_t I = 0, N = ImageStarts.seg_count; I < N; ++I) {
5083    auto OffOrErr =
5084        getStructOrErr<uint32_t>(*this, SegOffsPtr + I * sizeof(uint32_t));
5085    if (!OffOrErr)
5086      return OffOrErr.takeError();
5087    // seg_info_offset == 0 means there is no associated starts_in_segment
5088    // entry.
5089    if (!*OffOrErr)
5090      continue;
5091
5092    auto Fail = [&](Twine Message) {
5093      return malformedError("bad chained fixups: segment info" + Twine(I) +
5094                            " at offset " + Twine(*OffOrErr) + Message);
5095    };
5096
5097    const char *SegPtr = Contents + Header.starts_offset + *OffOrErr;
5098    if (LastSegEnd && SegPtr < LastSegEnd)
5099      return Fail(" overlaps with previous segment info");
5100
5101    auto SegOrErr =
5102        getStructOrErr<MachO::dyld_chained_starts_in_segment>(*this, SegPtr);
5103    if (!SegOrErr)
5104      return SegOrErr.takeError();
5105    const MachO::dyld_chained_starts_in_segment &Seg = *SegOrErr;
5106
5107    LastSegEnd = SegPtr + Seg.size;
5108    if (Seg.pointer_format < 1 || Seg.pointer_format > 12)
5109      return Fail(" has unknown pointer format: " + Twine(Seg.pointer_format));
5110
5111    const char *PageStart =
5112        SegPtr + offsetof(MachO::dyld_chained_starts_in_segment, page_start);
5113    const char *PageEnd = PageStart + Seg.page_count * sizeof(uint16_t);
5114    if (PageEnd > SegPtr + Seg.size)
5115      return Fail(" : page_starts extend past seg_info size");
5116
5117    // FIXME: This does not account for multiple offsets on a single page
5118    //        (DYLD_CHAINED_PTR_START_MULTI; 32-bit only).
5119    std::vector<uint16_t> PageStarts;
5120    for (size_t PageIdx = 0; PageIdx < Seg.page_count; ++PageIdx) {
5121      uint16_t Start;
5122      memcpy(&Start, PageStart + PageIdx * sizeof(uint16_t), sizeof(uint16_t));
5123      if (isLittleEndian() != sys::IsLittleEndianHost)
5124        sys::swapByteOrder(Start);
5125      PageStarts.push_back(Start);
5126    }
5127
5128    Segments.emplace_back(I, *OffOrErr, Seg, std::move(PageStarts));
5129  }
5130
5131  return std::make_pair(ImageStarts.seg_count, Segments);
5132}
5133
5134// The special library ordinals have a negative value, but they are encoded in
5135// an unsigned bitfield, so we need to sign extend the value.
5136template <typename T> static int getEncodedOrdinal(T Value) {
5137  if (Value == static_cast<T>(MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE) ||
5138      Value == static_cast<T>(MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) ||
5139      Value == static_cast<T>(MachO::BIND_SPECIAL_DYLIB_WEAK_LOOKUP))
5140    return SignExtend32<sizeof(T) * CHAR_BIT>(Value);
5141  return Value;
5142}
5143
5144template <typename T, unsigned N>
5145static std::array<T, N> getArray(const MachOObjectFile &O, const void *Ptr) {
5146  std::array<T, N> RawValue;
5147  memcpy(RawValue.data(), Ptr, N * sizeof(T));
5148  if (O.isLittleEndian() != sys::IsLittleEndianHost)
5149    for (auto &Element : RawValue)
5150      sys::swapByteOrder(Element);
5151  return RawValue;
5152}
5153
5154Expected<std::vector<ChainedFixupTarget>>
5155MachOObjectFile::getDyldChainedFixupTargets() const {
5156  auto CFOrErr = getChainedFixupsLoadCommand();
5157  if (!CFOrErr)
5158    return CFOrErr.takeError();
5159
5160  std::vector<ChainedFixupTarget> Targets;
5161  if (!CFOrErr->has_value())
5162    return Targets;
5163
5164  const MachO::linkedit_data_command &DyldChainedFixups = **CFOrErr;
5165
5166  auto CFHeaderOrErr = getChainedFixupsHeader();
5167  if (!CFHeaderOrErr)
5168    return CFHeaderOrErr.takeError();
5169  if (!(*CFHeaderOrErr))
5170    return Targets;
5171  const MachO::dyld_chained_fixups_header &Header = **CFHeaderOrErr;
5172
5173  size_t ImportSize = 0;
5174  if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT)
5175    ImportSize = sizeof(MachO::dyld_chained_import);
5176  else if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT_ADDEND)
5177    ImportSize = sizeof(MachO::dyld_chained_import_addend);
5178  else if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT_ADDEND64)
5179    ImportSize = sizeof(MachO::dyld_chained_import_addend64);
5180  else
5181    return malformedError("bad chained fixups: unknown imports format: " +
5182                          Twine(Header.imports_format));
5183
5184  const char *Contents = getPtr(*this, DyldChainedFixups.dataoff);
5185  const char *Imports = Contents + Header.imports_offset;
5186  size_t ImportsEndOffset =
5187      Header.imports_offset + ImportSize * Header.imports_count;
5188  const char *ImportsEnd = Contents + ImportsEndOffset;
5189  const char *Symbols = Contents + Header.symbols_offset;
5190  const char *SymbolsEnd = Contents + DyldChainedFixups.datasize;
5191
5192  if (ImportsEnd > Symbols)
5193    return malformedError("bad chained fixups: imports end " +
5194                          Twine(ImportsEndOffset) + " extends past end " +
5195                          Twine(DyldChainedFixups.datasize));
5196
5197  if (ImportsEnd > Symbols)
5198    return malformedError("bad chained fixups: imports end " +
5199                          Twine(ImportsEndOffset) + " overlaps with symbols");
5200
5201  // We use bit manipulation to extract data from the bitfields. This is correct
5202  // for both LE and BE hosts, but we assume that the object is little-endian.
5203  if (!isLittleEndian())
5204    return createError("parsing big-endian chained fixups is not implemented");
5205  for (const char *ImportPtr = Imports; ImportPtr < ImportsEnd;
5206       ImportPtr += ImportSize) {
5207    int LibOrdinal;
5208    bool WeakImport;
5209    uint32_t NameOffset;
5210    uint64_t Addend;
5211    if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT) {
5212      static_assert(sizeof(uint32_t) == sizeof(MachO::dyld_chained_import));
5213      auto RawValue = getArray<uint32_t, 1>(*this, ImportPtr);
5214
5215      LibOrdinal = getEncodedOrdinal<uint8_t>(RawValue[0] & 0xFF);
5216      WeakImport = (RawValue[0] >> 8) & 1;
5217      NameOffset = RawValue[0] >> 9;
5218      Addend = 0;
5219    } else if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT_ADDEND) {
5220      static_assert(sizeof(uint64_t) ==
5221                    sizeof(MachO::dyld_chained_import_addend));
5222      auto RawValue = getArray<uint32_t, 2>(*this, ImportPtr);
5223
5224      LibOrdinal = getEncodedOrdinal<uint8_t>(RawValue[0] & 0xFF);
5225      WeakImport = (RawValue[0] >> 8) & 1;
5226      NameOffset = RawValue[0] >> 9;
5227      Addend = bit_cast<int32_t>(RawValue[1]);
5228    } else if (Header.imports_format == MachO::DYLD_CHAINED_IMPORT_ADDEND64) {
5229      static_assert(2 * sizeof(uint64_t) ==
5230                    sizeof(MachO::dyld_chained_import_addend64));
5231      auto RawValue = getArray<uint64_t, 2>(*this, ImportPtr);
5232
5233      LibOrdinal = getEncodedOrdinal<uint16_t>(RawValue[0] & 0xFFFF);
5234      NameOffset = (RawValue[0] >> 16) & 1;
5235      WeakImport = RawValue[0] >> 17;
5236      Addend = RawValue[1];
5237    } else {
5238      llvm_unreachable("Import format should have been checked");
5239    }
5240
5241    const char *Str = Symbols + NameOffset;
5242    if (Str >= SymbolsEnd)
5243      return malformedError("bad chained fixups: symbol offset " +
5244                            Twine(NameOffset) + " extends past end " +
5245                            Twine(DyldChainedFixups.datasize));
5246    Targets.emplace_back(LibOrdinal, NameOffset, Str, Addend, WeakImport);
5247  }
5248
5249  return std::move(Targets);
5250}
5251
5252ArrayRef<uint8_t> MachOObjectFile::getDyldExportsTrie() const {
5253  if (!DyldExportsTrieLoadCmd)
5254    return std::nullopt;
5255
5256  auto DyldExportsTrieOrError = getStructOrErr<MachO::linkedit_data_command>(
5257      *this, DyldExportsTrieLoadCmd);
5258  if (!DyldExportsTrieOrError)
5259    return std::nullopt;
5260  MachO::linkedit_data_command DyldExportsTrie = DyldExportsTrieOrError.get();
5261  const uint8_t *Ptr =
5262      reinterpret_cast<const uint8_t *>(getPtr(*this, DyldExportsTrie.dataoff));
5263  return ArrayRef(Ptr, DyldExportsTrie.datasize);
5264}
5265
5266SmallVector<uint64_t> MachOObjectFile::getFunctionStarts() const {
5267  if (!FuncStartsLoadCmd)
5268    return {};
5269
5270  auto InfoOrErr =
5271      getStructOrErr<MachO::linkedit_data_command>(*this, FuncStartsLoadCmd);
5272  if (!InfoOrErr)
5273    return {};
5274
5275  MachO::linkedit_data_command Info = InfoOrErr.get();
5276  SmallVector<uint64_t, 8> FunctionStarts;
5277  this->ReadULEB128s(Info.dataoff, FunctionStarts);
5278  return std::move(FunctionStarts);
5279}
5280
5281ArrayRef<uint8_t> MachOObjectFile::getUuid() const {
5282  if (!UuidLoadCmd)
5283    return std::nullopt;
5284  // Returning a pointer is fine as uuid doesn't need endian swapping.
5285  const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid);
5286  return ArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16);
5287}
5288
5289StringRef MachOObjectFile::getStringTableData() const {
5290  MachO::symtab_command S = getSymtabLoadCommand();
5291  return getData().substr(S.stroff, S.strsize);
5292}
5293
5294bool MachOObjectFile::is64Bit() const {
5295  return getType() == getMachOType(false, true) ||
5296    getType() == getMachOType(true, true);
5297}
5298
5299void MachOObjectFile::ReadULEB128s(uint64_t Index,
5300                                   SmallVectorImpl<uint64_t> &Out) const {
5301  DataExtractor extractor(ObjectFile::getData(), true, 0);
5302
5303  uint64_t offset = Index;
5304  uint64_t data = 0;
5305  while (uint64_t delta = extractor.getULEB128(&offset)) {
5306    data += delta;
5307    Out.push_back(data);
5308  }
5309}
5310
5311bool MachOObjectFile::isRelocatableObject() const {
5312  return getHeader().filetype == MachO::MH_OBJECT;
5313}
5314
5315/// Create a MachOObjectFile instance from a given buffer.
5316///
5317/// \param Buffer Memory buffer containing the MachO binary data.
5318/// \param UniversalCputype CPU type when the MachO part of a universal binary.
5319/// \param UniversalIndex Index of the MachO within a universal binary.
5320/// \param MachOFilesetEntryOffset Offset of the MachO entry in a fileset MachO.
5321/// \returns A std::unique_ptr to a MachOObjectFile instance on success.
5322Expected<std::unique_ptr<MachOObjectFile>> ObjectFile::createMachOObjectFile(
5323    MemoryBufferRef Buffer, uint32_t UniversalCputype, uint32_t UniversalIndex,
5324    size_t MachOFilesetEntryOffset) {
5325  StringRef Magic = Buffer.getBuffer().slice(0, 4);
5326  if (Magic == "\xFE\xED\xFA\xCE")
5327    return MachOObjectFile::create(Buffer, false, false, UniversalCputype,
5328                                   UniversalIndex, MachOFilesetEntryOffset);
5329  if (Magic == "\xCE\xFA\xED\xFE")
5330    return MachOObjectFile::create(Buffer, true, false, UniversalCputype,
5331                                   UniversalIndex, MachOFilesetEntryOffset);
5332  if (Magic == "\xFE\xED\xFA\xCF")
5333    return MachOObjectFile::create(Buffer, false, true, UniversalCputype,
5334                                   UniversalIndex, MachOFilesetEntryOffset);
5335  if (Magic == "\xCF\xFA\xED\xFE")
5336    return MachOObjectFile::create(Buffer, true, true, UniversalCputype,
5337                                   UniversalIndex, MachOFilesetEntryOffset);
5338  return make_error<GenericBinaryError>("Unrecognized MachO magic number",
5339                                        object_error::invalid_file_type);
5340}
5341
5342StringRef MachOObjectFile::mapDebugSectionName(StringRef Name) const {
5343  return StringSwitch<StringRef>(Name)
5344      .Case("debug_str_offs", "debug_str_offsets")
5345      .Default(Name);
5346}
5347
5348Expected<std::vector<std::string>>
5349MachOObjectFile::findDsymObjectMembers(StringRef Path) {
5350  SmallString<256> BundlePath(Path);
5351  // Normalize input path. This is necessary to accept `bundle.dSYM/`.
5352  sys::path::remove_dots(BundlePath);
5353  if (!sys::fs::is_directory(BundlePath) ||
5354      sys::path::extension(BundlePath) != ".dSYM")
5355    return std::vector<std::string>();
5356  sys::path::append(BundlePath, "Contents", "Resources", "DWARF");
5357  bool IsDir;
5358  auto EC = sys::fs::is_directory(BundlePath, IsDir);
5359  if (EC == errc::no_such_file_or_directory || (!EC && !IsDir))
5360    return createStringError(
5361        EC, "%s: expected directory 'Contents/Resources/DWARF' in dSYM bundle",
5362        Path.str().c_str());
5363  if (EC)
5364    return createFileError(BundlePath, errorCodeToError(EC));
5365
5366  std::vector<std::string> ObjectPaths;
5367  for (sys::fs::directory_iterator Dir(BundlePath, EC), DirEnd;
5368       Dir != DirEnd && !EC; Dir.increment(EC)) {
5369    StringRef ObjectPath = Dir->path();
5370    sys::fs::file_status Status;
5371    if (auto EC = sys::fs::status(ObjectPath, Status))
5372      return createFileError(ObjectPath, errorCodeToError(EC));
5373    switch (Status.type()) {
5374    case sys::fs::file_type::regular_file:
5375    case sys::fs::file_type::symlink_file:
5376    case sys::fs::file_type::type_unknown:
5377      ObjectPaths.push_back(ObjectPath.str());
5378      break;
5379    default: /*ignore*/;
5380    }
5381  }
5382  if (EC)
5383    return createFileError(BundlePath, errorCodeToError(EC));
5384  if (ObjectPaths.empty())
5385    return createStringError(std::error_code(),
5386                             "%s: no objects found in dSYM bundle",
5387                             Path.str().c_str());
5388  return ObjectPaths;
5389}
5390
5391llvm::binaryformat::Swift5ReflectionSectionKind
5392MachOObjectFile::mapReflectionSectionNameToEnumValue(
5393    StringRef SectionName) const {
5394#define HANDLE_SWIFT_SECTION(KIND, MACHO, ELF, COFF)                           \
5395  .Case(MACHO, llvm::binaryformat::Swift5ReflectionSectionKind::KIND)
5396  return StringSwitch<llvm::binaryformat::Swift5ReflectionSectionKind>(
5397             SectionName)
5398#include "llvm/BinaryFormat/Swift.def"
5399      .Default(llvm::binaryformat::Swift5ReflectionSectionKind::unknown);
5400#undef HANDLE_SWIFT_SECTION
5401}
5402
5403bool MachOObjectFile::isMachOPairedReloc(uint64_t RelocType, uint64_t Arch) {
5404  switch (Arch) {
5405  case Triple::x86:
5406    return RelocType == MachO::GENERIC_RELOC_SECTDIFF ||
5407           RelocType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF;
5408  case Triple::x86_64:
5409    return RelocType == MachO::X86_64_RELOC_SUBTRACTOR;
5410  case Triple::arm:
5411  case Triple::thumb:
5412    return RelocType == MachO::ARM_RELOC_SECTDIFF ||
5413           RelocType == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
5414           RelocType == MachO::ARM_RELOC_HALF ||
5415           RelocType == MachO::ARM_RELOC_HALF_SECTDIFF;
5416  case Triple::aarch64:
5417    return RelocType == MachO::ARM64_RELOC_SUBTRACTOR;
5418  default:
5419    return false;
5420  }
5421}
5422