10b57cec5SDimitry Andric //===- MachO.h - MachO object file implementation ---------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file declares the MachOObjectFile class, which implement the ObjectFile
100b57cec5SDimitry Andric // interface for MachO files.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #ifndef LLVM_OBJECT_MACHO_H
150b57cec5SDimitry Andric #define LLVM_OBJECT_MACHO_H
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
180b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
190b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
200b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
210b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
220b57cec5SDimitry Andric #include "llvm/ADT/Triple.h"
230b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h"
240b57cec5SDimitry Andric #include "llvm/BinaryFormat/MachO.h"
250b57cec5SDimitry Andric #include "llvm/MC/SubtargetFeature.h"
260b57cec5SDimitry Andric #include "llvm/Object/Binary.h"
270b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h"
280b57cec5SDimitry Andric #include "llvm/Object/SymbolicFile.h"
290b57cec5SDimitry Andric #include "llvm/Support/Error.h"
300b57cec5SDimitry Andric #include "llvm/Support/Format.h"
310b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
320b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
330b57cec5SDimitry Andric #include <cstdint>
340b57cec5SDimitry Andric #include <memory>
350b57cec5SDimitry Andric #include <string>
360b57cec5SDimitry Andric #include <system_error>
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric namespace llvm {
390b57cec5SDimitry Andric namespace object {
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric /// DiceRef - This is a value type class that represents a single
420b57cec5SDimitry Andric /// data in code entry in the table in a Mach-O object file.
430b57cec5SDimitry Andric class DiceRef {
440b57cec5SDimitry Andric   DataRefImpl DicePimpl;
450b57cec5SDimitry Andric   const ObjectFile *OwningObject = nullptr;
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric public:
480b57cec5SDimitry Andric   DiceRef() = default;
490b57cec5SDimitry Andric   DiceRef(DataRefImpl DiceP, const ObjectFile *Owner);
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric   bool operator==(const DiceRef &Other) const;
520b57cec5SDimitry Andric   bool operator<(const DiceRef &Other) const;
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   void moveNext();
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric   std::error_code getOffset(uint32_t &Result) const;
570b57cec5SDimitry Andric   std::error_code getLength(uint16_t &Result) const;
580b57cec5SDimitry Andric   std::error_code getKind(uint16_t &Result) const;
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   DataRefImpl getRawDataRefImpl() const;
610b57cec5SDimitry Andric   const ObjectFile *getObjectFile() const;
620b57cec5SDimitry Andric };
630b57cec5SDimitry Andric using dice_iterator = content_iterator<DiceRef>;
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric /// ExportEntry encapsulates the current-state-of-the-walk used when doing a
660b57cec5SDimitry Andric /// non-recursive walk of the trie data structure.  This allows you to iterate
670b57cec5SDimitry Andric /// across all exported symbols using:
685ffd83dbSDimitry Andric ///      Error Err = Error::success();
690b57cec5SDimitry Andric ///      for (const llvm::object::ExportEntry &AnExport : Obj->exports(&Err)) {
700b57cec5SDimitry Andric ///      }
710b57cec5SDimitry Andric ///      if (Err) { report error ...
720b57cec5SDimitry Andric class ExportEntry {
730b57cec5SDimitry Andric public:
740b57cec5SDimitry Andric   ExportEntry(Error *Err, const MachOObjectFile *O, ArrayRef<uint8_t> Trie);
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   StringRef name() const;
770b57cec5SDimitry Andric   uint64_t flags() const;
780b57cec5SDimitry Andric   uint64_t address() const;
790b57cec5SDimitry Andric   uint64_t other() const;
800b57cec5SDimitry Andric   StringRef otherName() const;
810b57cec5SDimitry Andric   uint32_t nodeOffset() const;
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   bool operator==(const ExportEntry &) const;
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   void moveNext();
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric private:
880b57cec5SDimitry Andric   friend class MachOObjectFile;
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric   void moveToFirst();
910b57cec5SDimitry Andric   void moveToEnd();
920b57cec5SDimitry Andric   uint64_t readULEB128(const uint8_t *&p, const char **error);
930b57cec5SDimitry Andric   void pushDownUntilBottom();
940b57cec5SDimitry Andric   void pushNode(uint64_t Offset);
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   // Represents a node in the mach-o exports trie.
970b57cec5SDimitry Andric   struct NodeState {
980b57cec5SDimitry Andric     NodeState(const uint8_t *Ptr);
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric     const uint8_t *Start;
1010b57cec5SDimitry Andric     const uint8_t *Current;
1020b57cec5SDimitry Andric     uint64_t Flags = 0;
1030b57cec5SDimitry Andric     uint64_t Address = 0;
1040b57cec5SDimitry Andric     uint64_t Other = 0;
1050b57cec5SDimitry Andric     const char *ImportName = nullptr;
1060b57cec5SDimitry Andric     unsigned ChildCount = 0;
1070b57cec5SDimitry Andric     unsigned NextChildIndex = 0;
1080b57cec5SDimitry Andric     unsigned ParentStringLength = 0;
1090b57cec5SDimitry Andric     bool IsExportNode = false;
1100b57cec5SDimitry Andric   };
1110b57cec5SDimitry Andric   using NodeList = SmallVector<NodeState, 16>;
1120b57cec5SDimitry Andric   using node_iterator = NodeList::const_iterator;
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   Error *E;
1150b57cec5SDimitry Andric   const MachOObjectFile *O;
1160b57cec5SDimitry Andric   ArrayRef<uint8_t> Trie;
1170b57cec5SDimitry Andric   SmallString<256> CumulativeString;
1180b57cec5SDimitry Andric   NodeList Stack;
1190b57cec5SDimitry Andric   bool Done = false;
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   iterator_range<node_iterator> nodes() const {
1220b57cec5SDimitry Andric     return make_range(Stack.begin(), Stack.end());
1230b57cec5SDimitry Andric   }
1240b57cec5SDimitry Andric };
1250b57cec5SDimitry Andric using export_iterator = content_iterator<ExportEntry>;
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric // Segment info so SegIndex/SegOffset pairs in a Mach-O Bind or Rebase entry
1280b57cec5SDimitry Andric // can be checked and translated.  Only the SegIndex/SegOffset pairs from
1290b57cec5SDimitry Andric // checked entries are to be used with the segmentName(), sectionName() and
1300b57cec5SDimitry Andric // address() methods below.
1310b57cec5SDimitry Andric class BindRebaseSegInfo {
1320b57cec5SDimitry Andric public:
1330b57cec5SDimitry Andric   BindRebaseSegInfo(const MachOObjectFile *Obj);
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric   // Used to check a Mach-O Bind or Rebase entry for errors when iterating.
1360b57cec5SDimitry Andric   const char* checkSegAndOffsets(int32_t SegIndex, uint64_t SegOffset,
1370b57cec5SDimitry Andric                                  uint8_t PointerSize, uint32_t Count=1,
1380b57cec5SDimitry Andric                                  uint32_t Skip=0);
1390b57cec5SDimitry Andric   // Used with valid SegIndex/SegOffset values from checked entries.
1400b57cec5SDimitry Andric   StringRef segmentName(int32_t SegIndex);
1410b57cec5SDimitry Andric   StringRef sectionName(int32_t SegIndex, uint64_t SegOffset);
1420b57cec5SDimitry Andric   uint64_t address(uint32_t SegIndex, uint64_t SegOffset);
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric private:
1450b57cec5SDimitry Andric   struct SectionInfo {
1460b57cec5SDimitry Andric     uint64_t Address;
1470b57cec5SDimitry Andric     uint64_t Size;
1480b57cec5SDimitry Andric     StringRef SectionName;
1490b57cec5SDimitry Andric     StringRef SegmentName;
1500b57cec5SDimitry Andric     uint64_t OffsetInSegment;
1510b57cec5SDimitry Andric     uint64_t SegmentStartAddress;
1520b57cec5SDimitry Andric     int32_t SegmentIndex;
1530b57cec5SDimitry Andric   };
1540b57cec5SDimitry Andric   const SectionInfo &findSection(int32_t SegIndex, uint64_t SegOffset);
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   SmallVector<SectionInfo, 32> Sections;
1570b57cec5SDimitry Andric   int32_t MaxSegIndex;
1580b57cec5SDimitry Andric };
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric /// MachORebaseEntry encapsulates the current state in the decompression of
1610b57cec5SDimitry Andric /// rebasing opcodes. This allows you to iterate through the compressed table of
1620b57cec5SDimitry Andric /// rebasing using:
1635ffd83dbSDimitry Andric ///    Error Err = Error::success();
1640b57cec5SDimitry Andric ///    for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable(&Err)) {
1650b57cec5SDimitry Andric ///    }
1660b57cec5SDimitry Andric ///    if (Err) { report error ...
1670b57cec5SDimitry Andric class MachORebaseEntry {
1680b57cec5SDimitry Andric public:
1690b57cec5SDimitry Andric   MachORebaseEntry(Error *Err, const MachOObjectFile *O,
1700b57cec5SDimitry Andric                    ArrayRef<uint8_t> opcodes, bool is64Bit);
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   int32_t segmentIndex() const;
1730b57cec5SDimitry Andric   uint64_t segmentOffset() const;
1740b57cec5SDimitry Andric   StringRef typeName() const;
1750b57cec5SDimitry Andric   StringRef segmentName() const;
1760b57cec5SDimitry Andric   StringRef sectionName() const;
1770b57cec5SDimitry Andric   uint64_t address() const;
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric   bool operator==(const MachORebaseEntry &) const;
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   void moveNext();
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric private:
1840b57cec5SDimitry Andric   friend class MachOObjectFile;
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   void moveToFirst();
1870b57cec5SDimitry Andric   void moveToEnd();
1880b57cec5SDimitry Andric   uint64_t readULEB128(const char **error);
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric   Error *E;
1910b57cec5SDimitry Andric   const MachOObjectFile *O;
1920b57cec5SDimitry Andric   ArrayRef<uint8_t> Opcodes;
1930b57cec5SDimitry Andric   const uint8_t *Ptr;
1940b57cec5SDimitry Andric   uint64_t SegmentOffset = 0;
1950b57cec5SDimitry Andric   int32_t SegmentIndex = -1;
1960b57cec5SDimitry Andric   uint64_t RemainingLoopCount = 0;
1970b57cec5SDimitry Andric   uint64_t AdvanceAmount = 0;
1980b57cec5SDimitry Andric   uint8_t  RebaseType = 0;
1990b57cec5SDimitry Andric   uint8_t  PointerSize;
2000b57cec5SDimitry Andric   bool     Done = false;
2010b57cec5SDimitry Andric };
2020b57cec5SDimitry Andric using rebase_iterator = content_iterator<MachORebaseEntry>;
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric /// MachOBindEntry encapsulates the current state in the decompression of
2050b57cec5SDimitry Andric /// binding opcodes. This allows you to iterate through the compressed table of
2060b57cec5SDimitry Andric /// bindings using:
2075ffd83dbSDimitry Andric ///    Error Err = Error::success();
2080b57cec5SDimitry Andric ///    for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(&Err)) {
2090b57cec5SDimitry Andric ///    }
2100b57cec5SDimitry Andric ///    if (Err) { report error ...
2110b57cec5SDimitry Andric class MachOBindEntry {
2120b57cec5SDimitry Andric public:
2130b57cec5SDimitry Andric   enum class Kind { Regular, Lazy, Weak };
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   MachOBindEntry(Error *Err, const MachOObjectFile *O,
2160b57cec5SDimitry Andric                  ArrayRef<uint8_t> Opcodes, bool is64Bit, MachOBindEntry::Kind);
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric   int32_t segmentIndex() const;
2190b57cec5SDimitry Andric   uint64_t segmentOffset() const;
2200b57cec5SDimitry Andric   StringRef typeName() const;
2210b57cec5SDimitry Andric   StringRef symbolName() const;
2220b57cec5SDimitry Andric   uint32_t flags() const;
2230b57cec5SDimitry Andric   int64_t addend() const;
2240b57cec5SDimitry Andric   int ordinal() const;
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   StringRef segmentName() const;
2270b57cec5SDimitry Andric   StringRef sectionName() const;
2280b57cec5SDimitry Andric   uint64_t address() const;
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric   bool operator==(const MachOBindEntry &) const;
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric   void moveNext();
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric private:
2350b57cec5SDimitry Andric   friend class MachOObjectFile;
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric   void moveToFirst();
2380b57cec5SDimitry Andric   void moveToEnd();
2390b57cec5SDimitry Andric   uint64_t readULEB128(const char **error);
2400b57cec5SDimitry Andric   int64_t readSLEB128(const char **error);
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric   Error *E;
2430b57cec5SDimitry Andric   const MachOObjectFile *O;
2440b57cec5SDimitry Andric   ArrayRef<uint8_t> Opcodes;
2450b57cec5SDimitry Andric   const uint8_t *Ptr;
2460b57cec5SDimitry Andric   uint64_t SegmentOffset = 0;
2470b57cec5SDimitry Andric   int32_t  SegmentIndex = -1;
2480b57cec5SDimitry Andric   StringRef SymbolName;
2490b57cec5SDimitry Andric   bool     LibraryOrdinalSet = false;
2500b57cec5SDimitry Andric   int      Ordinal = 0;
2510b57cec5SDimitry Andric   uint32_t Flags = 0;
2520b57cec5SDimitry Andric   int64_t  Addend = 0;
2530b57cec5SDimitry Andric   uint64_t RemainingLoopCount = 0;
2540b57cec5SDimitry Andric   uint64_t AdvanceAmount = 0;
2550b57cec5SDimitry Andric   uint8_t  BindType = 0;
2560b57cec5SDimitry Andric   uint8_t  PointerSize;
2570b57cec5SDimitry Andric   Kind     TableKind;
2580b57cec5SDimitry Andric   bool     Done = false;
2590b57cec5SDimitry Andric };
2600b57cec5SDimitry Andric using bind_iterator = content_iterator<MachOBindEntry>;
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric class MachOObjectFile : public ObjectFile {
2630b57cec5SDimitry Andric public:
2640b57cec5SDimitry Andric   struct LoadCommandInfo {
2650b57cec5SDimitry Andric     const char *Ptr;      // Where in memory the load command is.
2660b57cec5SDimitry Andric     MachO::load_command C; // The command itself.
2670b57cec5SDimitry Andric   };
2680b57cec5SDimitry Andric   using LoadCommandList = SmallVector<LoadCommandInfo, 4>;
2690b57cec5SDimitry Andric   using load_command_iterator = LoadCommandList::const_iterator;
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric   static Expected<std::unique_ptr<MachOObjectFile>>
2720b57cec5SDimitry Andric   create(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits,
2730b57cec5SDimitry Andric          uint32_t UniversalCputype = 0, uint32_t UniversalIndex = 0);
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric   void moveSymbolNext(DataRefImpl &Symb) const override;
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric   uint64_t getNValue(DataRefImpl Sym) const;
2780b57cec5SDimitry Andric   Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric   // MachO specific.
2810b57cec5SDimitry Andric   Error checkSymbolTable() const;
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric   std::error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const;
2840b57cec5SDimitry Andric   unsigned getSectionType(SectionRef Sec) const;
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
2870b57cec5SDimitry Andric   uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
2880b57cec5SDimitry Andric   uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
2890b57cec5SDimitry Andric   Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
2905ffd83dbSDimitry Andric   Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
2910b57cec5SDimitry Andric   Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
2920b57cec5SDimitry Andric   unsigned getSymbolSectionID(SymbolRef Symb) const;
2930b57cec5SDimitry Andric   unsigned getSectionID(SectionRef Sec) const;
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric   void moveSectionNext(DataRefImpl &Sec) const override;
2960b57cec5SDimitry Andric   Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
2970b57cec5SDimitry Andric   uint64_t getSectionAddress(DataRefImpl Sec) const override;
2980b57cec5SDimitry Andric   uint64_t getSectionIndex(DataRefImpl Sec) const override;
2990b57cec5SDimitry Andric   uint64_t getSectionSize(DataRefImpl Sec) const override;
3008bcb0991SDimitry Andric   ArrayRef<uint8_t> getSectionContents(uint32_t Offset, uint64_t Size) const;
3010b57cec5SDimitry Andric   Expected<ArrayRef<uint8_t>>
3020b57cec5SDimitry Andric   getSectionContents(DataRefImpl Sec) const override;
3030b57cec5SDimitry Andric   uint64_t getSectionAlignment(DataRefImpl Sec) const override;
3040b57cec5SDimitry Andric   Expected<SectionRef> getSection(unsigned SectionIndex) const;
3050b57cec5SDimitry Andric   Expected<SectionRef> getSection(StringRef SectionName) const;
3060b57cec5SDimitry Andric   bool isSectionCompressed(DataRefImpl Sec) const override;
3070b57cec5SDimitry Andric   bool isSectionText(DataRefImpl Sec) const override;
3080b57cec5SDimitry Andric   bool isSectionData(DataRefImpl Sec) const override;
3090b57cec5SDimitry Andric   bool isSectionBSS(DataRefImpl Sec) const override;
3100b57cec5SDimitry Andric   bool isSectionVirtual(DataRefImpl Sec) const override;
3110b57cec5SDimitry Andric   bool isSectionBitcode(DataRefImpl Sec) const override;
312fe6060f1SDimitry Andric   bool isDebugSection(DataRefImpl Sec) const override;
3130b57cec5SDimitry Andric 
314349cc55cSDimitry Andric   /// Return the raw contents of an entire segment.
315349cc55cSDimitry Andric   ArrayRef<uint8_t> getSegmentContents(StringRef SegmentName) const;
316349cc55cSDimitry Andric 
3170b57cec5SDimitry Andric   /// When dsymutil generates the companion file, it strips all unnecessary
3180b57cec5SDimitry Andric   /// sections (e.g. everything in the _TEXT segment) by omitting their body
3190b57cec5SDimitry Andric   /// and setting the offset in their corresponding load command to zero.
3200b57cec5SDimitry Andric   ///
3210b57cec5SDimitry Andric   /// While the load command itself is valid, reading the section corresponds
3220b57cec5SDimitry Andric   /// to reading the number of bytes specified in the load command, starting
3230b57cec5SDimitry Andric   /// from offset 0 (i.e. the Mach-O header at the beginning of the file).
3240b57cec5SDimitry Andric   bool isSectionStripped(DataRefImpl Sec) const override;
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric   relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
3270b57cec5SDimitry Andric   relocation_iterator section_rel_end(DataRefImpl Sec) const override;
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric   relocation_iterator extrel_begin() const;
3300b57cec5SDimitry Andric   relocation_iterator extrel_end() const;
3310b57cec5SDimitry Andric   iterator_range<relocation_iterator> external_relocations() const {
3320b57cec5SDimitry Andric     return make_range(extrel_begin(), extrel_end());
3330b57cec5SDimitry Andric   }
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric   relocation_iterator locrel_begin() const;
3360b57cec5SDimitry Andric   relocation_iterator locrel_end() const;
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric   void moveRelocationNext(DataRefImpl &Rel) const override;
3390b57cec5SDimitry Andric   uint64_t getRelocationOffset(DataRefImpl Rel) const override;
3400b57cec5SDimitry Andric   symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
3410b57cec5SDimitry Andric   section_iterator getRelocationSection(DataRefImpl Rel) const;
3420b57cec5SDimitry Andric   uint64_t getRelocationType(DataRefImpl Rel) const override;
3430b57cec5SDimitry Andric   void getRelocationTypeName(DataRefImpl Rel,
3440b57cec5SDimitry Andric                              SmallVectorImpl<char> &Result) const override;
3450b57cec5SDimitry Andric   uint8_t getRelocationLength(DataRefImpl Rel) const;
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric   // MachO specific.
3480b57cec5SDimitry Andric   std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &) const;
3490b57cec5SDimitry Andric   uint32_t getLibraryCount() const;
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric   section_iterator getRelocationRelocatedSection(relocation_iterator Rel) const;
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric   // TODO: Would be useful to have an iterator based version
3540b57cec5SDimitry Andric   // of the load command interface too.
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric   basic_symbol_iterator symbol_begin() const override;
3570b57cec5SDimitry Andric   basic_symbol_iterator symbol_end() const override;
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric   // MachO specific.
3600b57cec5SDimitry Andric   symbol_iterator getSymbolByIndex(unsigned Index) const;
3610b57cec5SDimitry Andric   uint64_t getSymbolIndex(DataRefImpl Symb) const;
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric   section_iterator section_begin() const override;
3640b57cec5SDimitry Andric   section_iterator section_end() const override;
3650b57cec5SDimitry Andric 
3660b57cec5SDimitry Andric   uint8_t getBytesInAddress() const override;
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric   StringRef getFileFormatName() const override;
3690b57cec5SDimitry Andric   Triple::ArchType getArch() const override;
3700b57cec5SDimitry Andric   SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); }
3710b57cec5SDimitry Andric   Triple getArchTriple(const char **McpuDefault = nullptr) const;
3720b57cec5SDimitry Andric 
3730b57cec5SDimitry Andric   relocation_iterator section_rel_begin(unsigned Index) const;
3740b57cec5SDimitry Andric   relocation_iterator section_rel_end(unsigned Index) const;
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric   dice_iterator begin_dices() const;
3770b57cec5SDimitry Andric   dice_iterator end_dices() const;
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric   load_command_iterator begin_load_commands() const;
3800b57cec5SDimitry Andric   load_command_iterator end_load_commands() const;
3810b57cec5SDimitry Andric   iterator_range<load_command_iterator> load_commands() const;
3820b57cec5SDimitry Andric 
3830b57cec5SDimitry Andric   /// For use iterating over all exported symbols.
3840b57cec5SDimitry Andric   iterator_range<export_iterator> exports(Error &Err) const;
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric   /// For use examining a trie not in a MachOObjectFile.
3870b57cec5SDimitry Andric   static iterator_range<export_iterator> exports(Error &Err,
3880b57cec5SDimitry Andric                                                  ArrayRef<uint8_t> Trie,
3890b57cec5SDimitry Andric                                                  const MachOObjectFile *O =
3900b57cec5SDimitry Andric                                                                       nullptr);
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric   /// For use iterating over all rebase table entries.
3930b57cec5SDimitry Andric   iterator_range<rebase_iterator> rebaseTable(Error &Err);
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric   /// For use examining rebase opcodes in a MachOObjectFile.
3960b57cec5SDimitry Andric   static iterator_range<rebase_iterator> rebaseTable(Error &Err,
3970b57cec5SDimitry Andric                                                      MachOObjectFile *O,
3980b57cec5SDimitry Andric                                                      ArrayRef<uint8_t> Opcodes,
3990b57cec5SDimitry Andric                                                      bool is64);
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric   /// For use iterating over all bind table entries.
4020b57cec5SDimitry Andric   iterator_range<bind_iterator> bindTable(Error &Err);
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric   /// For use iterating over all lazy bind table entries.
4050b57cec5SDimitry Andric   iterator_range<bind_iterator> lazyBindTable(Error &Err);
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric   /// For use iterating over all weak bind table entries.
4080b57cec5SDimitry Andric   iterator_range<bind_iterator> weakBindTable(Error &Err);
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric   /// For use examining bind opcodes in a MachOObjectFile.
4110b57cec5SDimitry Andric   static iterator_range<bind_iterator> bindTable(Error &Err,
4120b57cec5SDimitry Andric                                                  MachOObjectFile *O,
4130b57cec5SDimitry Andric                                                  ArrayRef<uint8_t> Opcodes,
4140b57cec5SDimitry Andric                                                  bool is64,
4150b57cec5SDimitry Andric                                                  MachOBindEntry::Kind);
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric   // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
4180b57cec5SDimitry Andric   // that fully contains a pointer at that location. Multiple fixups in a bind
4190b57cec5SDimitry Andric   // (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can
4200b57cec5SDimitry Andric   // be tested via the Count and Skip parameters.
4210b57cec5SDimitry Andric   //
4220b57cec5SDimitry Andric   // This is used by MachOBindEntry::moveNext() to validate a MachOBindEntry.
4230b57cec5SDimitry Andric   const char *BindEntryCheckSegAndOffsets(int32_t SegIndex, uint64_t SegOffset,
4240b57cec5SDimitry Andric                                          uint8_t PointerSize, uint32_t Count=1,
4250b57cec5SDimitry Andric                                           uint32_t Skip=0) const {
4260b57cec5SDimitry Andric     return BindRebaseSectionTable->checkSegAndOffsets(SegIndex, SegOffset,
4270b57cec5SDimitry Andric                                                      PointerSize, Count, Skip);
4280b57cec5SDimitry Andric   }
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric   // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
4310b57cec5SDimitry Andric   // that fully contains a pointer at that location. Multiple fixups in a rebase
4320b57cec5SDimitry Andric   // (such as with the REBASE_OPCODE_DO_*_TIMES* opcodes) can be tested via the
4330b57cec5SDimitry Andric   // Count and Skip parameters.
4340b57cec5SDimitry Andric   //
4350b57cec5SDimitry Andric   // This is used by MachORebaseEntry::moveNext() to validate a MachORebaseEntry
4360b57cec5SDimitry Andric   const char *RebaseEntryCheckSegAndOffsets(int32_t SegIndex,
4370b57cec5SDimitry Andric                                             uint64_t SegOffset,
4380b57cec5SDimitry Andric                                             uint8_t PointerSize,
4390b57cec5SDimitry Andric                                             uint32_t Count=1,
4400b57cec5SDimitry Andric                                             uint32_t Skip=0) const {
4410b57cec5SDimitry Andric     return BindRebaseSectionTable->checkSegAndOffsets(SegIndex, SegOffset,
4420b57cec5SDimitry Andric                                                       PointerSize, Count, Skip);
4430b57cec5SDimitry Andric   }
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric   /// For use with the SegIndex of a checked Mach-O Bind or Rebase entry to
4460b57cec5SDimitry Andric   /// get the segment name.
4470b57cec5SDimitry Andric   StringRef BindRebaseSegmentName(int32_t SegIndex) const {
4480b57cec5SDimitry Andric     return BindRebaseSectionTable->segmentName(SegIndex);
4490b57cec5SDimitry Andric   }
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric   /// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or
4520b57cec5SDimitry Andric   /// Rebase entry to get the section name.
4530b57cec5SDimitry Andric   StringRef BindRebaseSectionName(uint32_t SegIndex, uint64_t SegOffset) const {
4540b57cec5SDimitry Andric     return BindRebaseSectionTable->sectionName(SegIndex, SegOffset);
4550b57cec5SDimitry Andric   }
4560b57cec5SDimitry Andric 
4570b57cec5SDimitry Andric   /// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or
4580b57cec5SDimitry Andric   /// Rebase entry to get the address.
4590b57cec5SDimitry Andric   uint64_t BindRebaseAddress(uint32_t SegIndex, uint64_t SegOffset) const {
4600b57cec5SDimitry Andric     return BindRebaseSectionTable->address(SegIndex, SegOffset);
4610b57cec5SDimitry Andric   }
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric   // In a MachO file, sections have a segment name. This is used in the .o
4640b57cec5SDimitry Andric   // files. They have a single segment, but this field specifies which segment
4650b57cec5SDimitry Andric   // a section should be put in the final object.
4660b57cec5SDimitry Andric   StringRef getSectionFinalSegmentName(DataRefImpl Sec) const;
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric   // Names are stored as 16 bytes. These returns the raw 16 bytes without
4690b57cec5SDimitry Andric   // interpreting them as a C string.
4700b57cec5SDimitry Andric   ArrayRef<char> getSectionRawName(DataRefImpl Sec) const;
4710b57cec5SDimitry Andric   ArrayRef<char> getSectionRawFinalSegmentName(DataRefImpl Sec) const;
4720b57cec5SDimitry Andric 
4730b57cec5SDimitry Andric   // MachO specific Info about relocations.
4740b57cec5SDimitry Andric   bool isRelocationScattered(const MachO::any_relocation_info &RE) const;
4750b57cec5SDimitry Andric   unsigned getPlainRelocationSymbolNum(
4760b57cec5SDimitry Andric                                     const MachO::any_relocation_info &RE) const;
4770b57cec5SDimitry Andric   bool getPlainRelocationExternal(const MachO::any_relocation_info &RE) const;
4780b57cec5SDimitry Andric   bool getScatteredRelocationScattered(
4790b57cec5SDimitry Andric                                     const MachO::any_relocation_info &RE) const;
4800b57cec5SDimitry Andric   uint32_t getScatteredRelocationValue(
4810b57cec5SDimitry Andric                                     const MachO::any_relocation_info &RE) const;
4820b57cec5SDimitry Andric   uint32_t getScatteredRelocationType(
4830b57cec5SDimitry Andric                                     const MachO::any_relocation_info &RE) const;
4840b57cec5SDimitry Andric   unsigned getAnyRelocationAddress(const MachO::any_relocation_info &RE) const;
4850b57cec5SDimitry Andric   unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const;
4860b57cec5SDimitry Andric   unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const;
4870b57cec5SDimitry Andric   unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const;
4880b57cec5SDimitry Andric   SectionRef getAnyRelocationSection(const MachO::any_relocation_info &RE) const;
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric   // MachO specific structures.
4910b57cec5SDimitry Andric   MachO::section getSection(DataRefImpl DRI) const;
4920b57cec5SDimitry Andric   MachO::section_64 getSection64(DataRefImpl DRI) const;
4930b57cec5SDimitry Andric   MachO::section getSection(const LoadCommandInfo &L, unsigned Index) const;
4940b57cec5SDimitry Andric   MachO::section_64 getSection64(const LoadCommandInfo &L,unsigned Index) const;
4950b57cec5SDimitry Andric   MachO::nlist getSymbolTableEntry(DataRefImpl DRI) const;
4960b57cec5SDimitry Andric   MachO::nlist_64 getSymbol64TableEntry(DataRefImpl DRI) const;
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric   MachO::linkedit_data_command
4990b57cec5SDimitry Andric   getLinkeditDataLoadCommand(const LoadCommandInfo &L) const;
5000b57cec5SDimitry Andric   MachO::segment_command
5010b57cec5SDimitry Andric   getSegmentLoadCommand(const LoadCommandInfo &L) const;
5020b57cec5SDimitry Andric   MachO::segment_command_64
5030b57cec5SDimitry Andric   getSegment64LoadCommand(const LoadCommandInfo &L) const;
5040b57cec5SDimitry Andric   MachO::linker_option_command
5050b57cec5SDimitry Andric   getLinkerOptionLoadCommand(const LoadCommandInfo &L) const;
5060b57cec5SDimitry Andric   MachO::version_min_command
5070b57cec5SDimitry Andric   getVersionMinLoadCommand(const LoadCommandInfo &L) const;
5080b57cec5SDimitry Andric   MachO::note_command
5090b57cec5SDimitry Andric   getNoteLoadCommand(const LoadCommandInfo &L) const;
5100b57cec5SDimitry Andric   MachO::build_version_command
5110b57cec5SDimitry Andric   getBuildVersionLoadCommand(const LoadCommandInfo &L) const;
5120b57cec5SDimitry Andric   MachO::build_tool_version
5130b57cec5SDimitry Andric   getBuildToolVersion(unsigned index) const;
5140b57cec5SDimitry Andric   MachO::dylib_command
5150b57cec5SDimitry Andric   getDylibIDLoadCommand(const LoadCommandInfo &L) const;
5160b57cec5SDimitry Andric   MachO::dyld_info_command
5170b57cec5SDimitry Andric   getDyldInfoLoadCommand(const LoadCommandInfo &L) const;
5180b57cec5SDimitry Andric   MachO::dylinker_command
5190b57cec5SDimitry Andric   getDylinkerCommand(const LoadCommandInfo &L) const;
5200b57cec5SDimitry Andric   MachO::uuid_command
5210b57cec5SDimitry Andric   getUuidCommand(const LoadCommandInfo &L) const;
5220b57cec5SDimitry Andric   MachO::rpath_command
5230b57cec5SDimitry Andric   getRpathCommand(const LoadCommandInfo &L) const;
5240b57cec5SDimitry Andric   MachO::source_version_command
5250b57cec5SDimitry Andric   getSourceVersionCommand(const LoadCommandInfo &L) const;
5260b57cec5SDimitry Andric   MachO::entry_point_command
5270b57cec5SDimitry Andric   getEntryPointCommand(const LoadCommandInfo &L) const;
5280b57cec5SDimitry Andric   MachO::encryption_info_command
5290b57cec5SDimitry Andric   getEncryptionInfoCommand(const LoadCommandInfo &L) const;
5300b57cec5SDimitry Andric   MachO::encryption_info_command_64
5310b57cec5SDimitry Andric   getEncryptionInfoCommand64(const LoadCommandInfo &L) const;
5320b57cec5SDimitry Andric   MachO::sub_framework_command
5330b57cec5SDimitry Andric   getSubFrameworkCommand(const LoadCommandInfo &L) const;
5340b57cec5SDimitry Andric   MachO::sub_umbrella_command
5350b57cec5SDimitry Andric   getSubUmbrellaCommand(const LoadCommandInfo &L) const;
5360b57cec5SDimitry Andric   MachO::sub_library_command
5370b57cec5SDimitry Andric   getSubLibraryCommand(const LoadCommandInfo &L) const;
5380b57cec5SDimitry Andric   MachO::sub_client_command
5390b57cec5SDimitry Andric   getSubClientCommand(const LoadCommandInfo &L) const;
5400b57cec5SDimitry Andric   MachO::routines_command
5410b57cec5SDimitry Andric   getRoutinesCommand(const LoadCommandInfo &L) const;
5420b57cec5SDimitry Andric   MachO::routines_command_64
5430b57cec5SDimitry Andric   getRoutinesCommand64(const LoadCommandInfo &L) const;
5440b57cec5SDimitry Andric   MachO::thread_command
5450b57cec5SDimitry Andric   getThreadCommand(const LoadCommandInfo &L) const;
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric   MachO::any_relocation_info getRelocation(DataRefImpl Rel) const;
5480b57cec5SDimitry Andric   MachO::data_in_code_entry getDice(DataRefImpl Rel) const;
5490b57cec5SDimitry Andric   const MachO::mach_header &getHeader() const;
5500b57cec5SDimitry Andric   const MachO::mach_header_64 &getHeader64() const;
5510b57cec5SDimitry Andric   uint32_t
5520b57cec5SDimitry Andric   getIndirectSymbolTableEntry(const MachO::dysymtab_command &DLC,
5530b57cec5SDimitry Andric                               unsigned Index) const;
5540b57cec5SDimitry Andric   MachO::data_in_code_entry getDataInCodeTableEntry(uint32_t DataOffset,
5550b57cec5SDimitry Andric                                                     unsigned Index) const;
5560b57cec5SDimitry Andric   MachO::symtab_command getSymtabLoadCommand() const;
5570b57cec5SDimitry Andric   MachO::dysymtab_command getDysymtabLoadCommand() const;
5580b57cec5SDimitry Andric   MachO::linkedit_data_command getDataInCodeLoadCommand() const;
5590b57cec5SDimitry Andric   MachO::linkedit_data_command getLinkOptHintsLoadCommand() const;
5600b57cec5SDimitry Andric   ArrayRef<uint8_t> getDyldInfoRebaseOpcodes() const;
5610b57cec5SDimitry Andric   ArrayRef<uint8_t> getDyldInfoBindOpcodes() const;
5620b57cec5SDimitry Andric   ArrayRef<uint8_t> getDyldInfoWeakBindOpcodes() const;
5630b57cec5SDimitry Andric   ArrayRef<uint8_t> getDyldInfoLazyBindOpcodes() const;
5640b57cec5SDimitry Andric   ArrayRef<uint8_t> getDyldInfoExportsTrie() const;
5650b57cec5SDimitry Andric   ArrayRef<uint8_t> getUuid() const;
5660b57cec5SDimitry Andric 
5670b57cec5SDimitry Andric   StringRef getStringTableData() const;
5680b57cec5SDimitry Andric   bool is64Bit() const;
5690b57cec5SDimitry Andric   void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const;
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric   static StringRef guessLibraryShortName(StringRef Name, bool &isFramework,
5720b57cec5SDimitry Andric                                          StringRef &Suffix);
5730b57cec5SDimitry Andric 
574480093f4SDimitry Andric   static Triple::ArchType getArch(uint32_t CPUType, uint32_t CPUSubType);
5750b57cec5SDimitry Andric   static Triple getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
5760b57cec5SDimitry Andric                               const char **McpuDefault = nullptr,
5770b57cec5SDimitry Andric                               const char **ArchFlag = nullptr);
5780b57cec5SDimitry Andric   static bool isValidArch(StringRef ArchFlag);
5790b57cec5SDimitry Andric   static ArrayRef<StringRef> getValidArchs();
5800b57cec5SDimitry Andric   static Triple getHostArch();
5810b57cec5SDimitry Andric 
5820b57cec5SDimitry Andric   bool isRelocatableObject() const override;
5830b57cec5SDimitry Andric 
5840b57cec5SDimitry Andric   StringRef mapDebugSectionName(StringRef Name) const override;
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric   bool hasPageZeroSegment() const { return HasPageZeroSegment; }
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric   static bool classof(const Binary *v) {
5890b57cec5SDimitry Andric     return v->isMachO();
5900b57cec5SDimitry Andric   }
5910b57cec5SDimitry Andric 
5920b57cec5SDimitry Andric   static uint32_t
5930b57cec5SDimitry Andric   getVersionMinMajor(MachO::version_min_command &C, bool SDK) {
5940b57cec5SDimitry Andric     uint32_t VersionOrSDK = (SDK) ? C.sdk : C.version;
5950b57cec5SDimitry Andric     return (VersionOrSDK >> 16) & 0xffff;
5960b57cec5SDimitry Andric   }
5970b57cec5SDimitry Andric 
5980b57cec5SDimitry Andric   static uint32_t
5990b57cec5SDimitry Andric   getVersionMinMinor(MachO::version_min_command &C, bool SDK) {
6000b57cec5SDimitry Andric     uint32_t VersionOrSDK = (SDK) ? C.sdk : C.version;
6010b57cec5SDimitry Andric     return (VersionOrSDK >> 8) & 0xff;
6020b57cec5SDimitry Andric   }
6030b57cec5SDimitry Andric 
6040b57cec5SDimitry Andric   static uint32_t
6050b57cec5SDimitry Andric   getVersionMinUpdate(MachO::version_min_command &C, bool SDK) {
6060b57cec5SDimitry Andric     uint32_t VersionOrSDK = (SDK) ? C.sdk : C.version;
6070b57cec5SDimitry Andric     return VersionOrSDK & 0xff;
6080b57cec5SDimitry Andric   }
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric   static std::string getBuildPlatform(uint32_t platform) {
6110b57cec5SDimitry Andric     switch (platform) {
6120b57cec5SDimitry Andric     case MachO::PLATFORM_MACOS: return "macos";
6130b57cec5SDimitry Andric     case MachO::PLATFORM_IOS: return "ios";
6140b57cec5SDimitry Andric     case MachO::PLATFORM_TVOS: return "tvos";
6150b57cec5SDimitry Andric     case MachO::PLATFORM_WATCHOS: return "watchos";
6160b57cec5SDimitry Andric     case MachO::PLATFORM_BRIDGEOS: return "bridgeos";
6170b57cec5SDimitry Andric     case MachO::PLATFORM_MACCATALYST: return "macCatalyst";
6180b57cec5SDimitry Andric     case MachO::PLATFORM_IOSSIMULATOR: return "iossimulator";
6190b57cec5SDimitry Andric     case MachO::PLATFORM_TVOSSIMULATOR: return "tvossimulator";
6200b57cec5SDimitry Andric     case MachO::PLATFORM_WATCHOSSIMULATOR: return "watchossimulator";
621e8d8bef9SDimitry Andric     case MachO::PLATFORM_DRIVERKIT: return "driverkit";
6220b57cec5SDimitry Andric     default:
6230b57cec5SDimitry Andric       std::string ret;
6240b57cec5SDimitry Andric       raw_string_ostream ss(ret);
6250b57cec5SDimitry Andric       ss << format_hex(platform, 8, true);
6260b57cec5SDimitry Andric       return ss.str();
6270b57cec5SDimitry Andric     }
6280b57cec5SDimitry Andric   }
6290b57cec5SDimitry Andric 
6300b57cec5SDimitry Andric   static std::string getBuildTool(uint32_t tools) {
6310b57cec5SDimitry Andric     switch (tools) {
6320b57cec5SDimitry Andric     case MachO::TOOL_CLANG: return "clang";
6330b57cec5SDimitry Andric     case MachO::TOOL_SWIFT: return "swift";
6340b57cec5SDimitry Andric     case MachO::TOOL_LD: return "ld";
6350b57cec5SDimitry Andric     default:
6360b57cec5SDimitry Andric       std::string ret;
6370b57cec5SDimitry Andric       raw_string_ostream ss(ret);
6380b57cec5SDimitry Andric       ss << format_hex(tools, 8, true);
6390b57cec5SDimitry Andric       return ss.str();
6400b57cec5SDimitry Andric     }
6410b57cec5SDimitry Andric   }
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric   static std::string getVersionString(uint32_t version) {
6440b57cec5SDimitry Andric     uint32_t major = (version >> 16) & 0xffff;
6450b57cec5SDimitry Andric     uint32_t minor = (version >> 8) & 0xff;
6460b57cec5SDimitry Andric     uint32_t update = version & 0xff;
6470b57cec5SDimitry Andric 
6480b57cec5SDimitry Andric     SmallString<32> Version;
6490b57cec5SDimitry Andric     Version = utostr(major) + "." + utostr(minor);
6500b57cec5SDimitry Andric     if (update != 0)
6510b57cec5SDimitry Andric       Version += "." + utostr(update);
6525ffd83dbSDimitry Andric     return std::string(std::string(Version.str()));
6530b57cec5SDimitry Andric   }
6540b57cec5SDimitry Andric 
6550eae32dcSDimitry Andric   /// If the input path is a .dSYM bundle (as created by the dsymutil tool),
6560eae32dcSDimitry Andric   /// return the paths to the object files found in the bundle, otherwise return
6570eae32dcSDimitry Andric   /// an empty vector. If the path appears to be a .dSYM bundle but no objects
6580eae32dcSDimitry Andric   /// were found or there was a filesystem error, then return an error.
6590eae32dcSDimitry Andric   static Expected<std::vector<std::string>>
6600eae32dcSDimitry Andric   findDsymObjectMembers(StringRef Path);
6610eae32dcSDimitry Andric 
6620b57cec5SDimitry Andric private:
6630b57cec5SDimitry Andric   MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits,
6640b57cec5SDimitry Andric                   Error &Err, uint32_t UniversalCputype = 0,
6650b57cec5SDimitry Andric                   uint32_t UniversalIndex = 0);
6660b57cec5SDimitry Andric 
6670b57cec5SDimitry Andric   uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
6680b57cec5SDimitry Andric 
6690b57cec5SDimitry Andric   union {
6700b57cec5SDimitry Andric     MachO::mach_header_64 Header64;
6710b57cec5SDimitry Andric     MachO::mach_header Header;
6720b57cec5SDimitry Andric   };
6730b57cec5SDimitry Andric   using SectionList = SmallVector<const char*, 1>;
6740b57cec5SDimitry Andric   SectionList Sections;
6750b57cec5SDimitry Andric   using LibraryList = SmallVector<const char*, 1>;
6760b57cec5SDimitry Andric   LibraryList Libraries;
6770b57cec5SDimitry Andric   LoadCommandList LoadCommands;
6780b57cec5SDimitry Andric   using LibraryShortName = SmallVector<StringRef, 1>;
6790b57cec5SDimitry Andric   using BuildToolList = SmallVector<const char*, 1>;
6800b57cec5SDimitry Andric   BuildToolList BuildTools;
6810b57cec5SDimitry Andric   mutable LibraryShortName LibrariesShortNames;
6820b57cec5SDimitry Andric   std::unique_ptr<BindRebaseSegInfo> BindRebaseSectionTable;
6830b57cec5SDimitry Andric   const char *SymtabLoadCmd = nullptr;
6840b57cec5SDimitry Andric   const char *DysymtabLoadCmd = nullptr;
6850b57cec5SDimitry Andric   const char *DataInCodeLoadCmd = nullptr;
6860b57cec5SDimitry Andric   const char *LinkOptHintsLoadCmd = nullptr;
6870b57cec5SDimitry Andric   const char *DyldInfoLoadCmd = nullptr;
6880b57cec5SDimitry Andric   const char *UuidLoadCmd = nullptr;
6890b57cec5SDimitry Andric   bool HasPageZeroSegment = false;
6900b57cec5SDimitry Andric };
6910b57cec5SDimitry Andric 
6920b57cec5SDimitry Andric /// DiceRef
6930b57cec5SDimitry Andric inline DiceRef::DiceRef(DataRefImpl DiceP, const ObjectFile *Owner)
6940b57cec5SDimitry Andric   : DicePimpl(DiceP) , OwningObject(Owner) {}
6950b57cec5SDimitry Andric 
6960b57cec5SDimitry Andric inline bool DiceRef::operator==(const DiceRef &Other) const {
6970b57cec5SDimitry Andric   return DicePimpl == Other.DicePimpl;
6980b57cec5SDimitry Andric }
6990b57cec5SDimitry Andric 
7000b57cec5SDimitry Andric inline bool DiceRef::operator<(const DiceRef &Other) const {
7010b57cec5SDimitry Andric   return DicePimpl < Other.DicePimpl;
7020b57cec5SDimitry Andric }
7030b57cec5SDimitry Andric 
7040b57cec5SDimitry Andric inline void DiceRef::moveNext() {
7050b57cec5SDimitry Andric   const MachO::data_in_code_entry *P =
7060b57cec5SDimitry Andric     reinterpret_cast<const MachO::data_in_code_entry *>(DicePimpl.p);
7070b57cec5SDimitry Andric   DicePimpl.p = reinterpret_cast<uintptr_t>(P + 1);
7080b57cec5SDimitry Andric }
7090b57cec5SDimitry Andric 
7100b57cec5SDimitry Andric // Since a Mach-O data in code reference, a DiceRef, can only be created when
7110b57cec5SDimitry Andric // the OwningObject ObjectFile is a MachOObjectFile a static_cast<> is used for
7120b57cec5SDimitry Andric // the methods that get the values of the fields of the reference.
7130b57cec5SDimitry Andric 
7140b57cec5SDimitry Andric inline std::error_code DiceRef::getOffset(uint32_t &Result) const {
7150b57cec5SDimitry Andric   const MachOObjectFile *MachOOF =
7160b57cec5SDimitry Andric     static_cast<const MachOObjectFile *>(OwningObject);
7170b57cec5SDimitry Andric   MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl);
7180b57cec5SDimitry Andric   Result = Dice.offset;
7190b57cec5SDimitry Andric   return std::error_code();
7200b57cec5SDimitry Andric }
7210b57cec5SDimitry Andric 
7220b57cec5SDimitry Andric inline std::error_code DiceRef::getLength(uint16_t &Result) const {
7230b57cec5SDimitry Andric   const MachOObjectFile *MachOOF =
7240b57cec5SDimitry Andric     static_cast<const MachOObjectFile *>(OwningObject);
7250b57cec5SDimitry Andric   MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl);
7260b57cec5SDimitry Andric   Result = Dice.length;
7270b57cec5SDimitry Andric   return std::error_code();
7280b57cec5SDimitry Andric }
7290b57cec5SDimitry Andric 
7300b57cec5SDimitry Andric inline std::error_code DiceRef::getKind(uint16_t &Result) const {
7310b57cec5SDimitry Andric   const MachOObjectFile *MachOOF =
7320b57cec5SDimitry Andric     static_cast<const MachOObjectFile *>(OwningObject);
7330b57cec5SDimitry Andric   MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl);
7340b57cec5SDimitry Andric   Result = Dice.kind;
7350b57cec5SDimitry Andric   return std::error_code();
7360b57cec5SDimitry Andric }
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric inline DataRefImpl DiceRef::getRawDataRefImpl() const {
7390b57cec5SDimitry Andric   return DicePimpl;
7400b57cec5SDimitry Andric }
7410b57cec5SDimitry Andric 
7420b57cec5SDimitry Andric inline const ObjectFile *DiceRef::getObjectFile() const {
7430b57cec5SDimitry Andric   return OwningObject;
7440b57cec5SDimitry Andric }
7450b57cec5SDimitry Andric 
7460b57cec5SDimitry Andric } // end namespace object
7470b57cec5SDimitry Andric } // end namespace llvm
7480b57cec5SDimitry Andric 
7490b57cec5SDimitry Andric #endif // LLVM_OBJECT_MACHO_H
750