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/iterator_range.h"
230b57cec5SDimitry Andric #include "llvm/BinaryFormat/MachO.h"
241fd87a68SDimitry Andric #include "llvm/BinaryFormat/Swift.h"
250b57cec5SDimitry Andric #include "llvm/Object/Binary.h"
260b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h"
270b57cec5SDimitry Andric #include "llvm/Object/SymbolicFile.h"
280b57cec5SDimitry Andric #include "llvm/Support/Error.h"
290b57cec5SDimitry Andric #include "llvm/Support/Format.h"
300b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
310b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
3206c3fb27SDimitry Andric #include "llvm/TargetParser/SubtargetFeature.h"
3306c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
340b57cec5SDimitry Andric #include <cstdint>
350b57cec5SDimitry Andric #include <memory>
360b57cec5SDimitry Andric #include <string>
370b57cec5SDimitry Andric #include <system_error>
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric namespace llvm {
400b57cec5SDimitry Andric namespace object {
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric /// DiceRef - This is a value type class that represents a single
430b57cec5SDimitry Andric /// data in code entry in the table in a Mach-O object file.
440b57cec5SDimitry Andric class DiceRef {
450b57cec5SDimitry Andric   DataRefImpl DicePimpl;
460b57cec5SDimitry Andric   const ObjectFile *OwningObject = nullptr;
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric public:
490b57cec5SDimitry Andric   DiceRef() = default;
500b57cec5SDimitry Andric   DiceRef(DataRefImpl DiceP, const ObjectFile *Owner);
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   bool operator==(const DiceRef &Other) const;
530b57cec5SDimitry Andric   bool operator<(const DiceRef &Other) const;
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   void moveNext();
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   std::error_code getOffset(uint32_t &Result) const;
580b57cec5SDimitry Andric   std::error_code getLength(uint16_t &Result) const;
590b57cec5SDimitry Andric   std::error_code getKind(uint16_t &Result) const;
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric   DataRefImpl getRawDataRefImpl() const;
620b57cec5SDimitry Andric   const ObjectFile *getObjectFile() const;
630b57cec5SDimitry Andric };
640b57cec5SDimitry Andric using dice_iterator = content_iterator<DiceRef>;
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric /// ExportEntry encapsulates the current-state-of-the-walk used when doing a
670b57cec5SDimitry Andric /// non-recursive walk of the trie data structure.  This allows you to iterate
680b57cec5SDimitry Andric /// across all exported symbols using:
695ffd83dbSDimitry Andric ///      Error Err = Error::success();
700b57cec5SDimitry Andric ///      for (const llvm::object::ExportEntry &AnExport : Obj->exports(&Err)) {
710b57cec5SDimitry Andric ///      }
720b57cec5SDimitry Andric ///      if (Err) { report error ...
730b57cec5SDimitry Andric class ExportEntry {
740b57cec5SDimitry Andric public:
750b57cec5SDimitry Andric   ExportEntry(Error *Err, const MachOObjectFile *O, ArrayRef<uint8_t> Trie);
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   StringRef name() const;
780b57cec5SDimitry Andric   uint64_t flags() const;
790b57cec5SDimitry Andric   uint64_t address() const;
800b57cec5SDimitry Andric   uint64_t other() const;
810b57cec5SDimitry Andric   StringRef otherName() const;
820b57cec5SDimitry Andric   uint32_t nodeOffset() const;
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   bool operator==(const ExportEntry &) const;
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   void moveNext();
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric private:
890b57cec5SDimitry Andric   friend class MachOObjectFile;
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   void moveToFirst();
920b57cec5SDimitry Andric   void moveToEnd();
930b57cec5SDimitry Andric   uint64_t readULEB128(const uint8_t *&p, const char **error);
940b57cec5SDimitry Andric   void pushDownUntilBottom();
950b57cec5SDimitry Andric   void pushNode(uint64_t Offset);
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   // Represents a node in the mach-o exports trie.
980b57cec5SDimitry Andric   struct NodeState {
990b57cec5SDimitry Andric     NodeState(const uint8_t *Ptr);
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric     const uint8_t *Start;
1020b57cec5SDimitry Andric     const uint8_t *Current;
1030b57cec5SDimitry Andric     uint64_t Flags = 0;
1040b57cec5SDimitry Andric     uint64_t Address = 0;
1050b57cec5SDimitry Andric     uint64_t Other = 0;
1060b57cec5SDimitry Andric     const char *ImportName = nullptr;
1070b57cec5SDimitry Andric     unsigned ChildCount = 0;
1080b57cec5SDimitry Andric     unsigned NextChildIndex = 0;
1090b57cec5SDimitry Andric     unsigned ParentStringLength = 0;
1100b57cec5SDimitry Andric     bool IsExportNode = false;
1110b57cec5SDimitry Andric   };
1120b57cec5SDimitry Andric   using NodeList = SmallVector<NodeState, 16>;
1130b57cec5SDimitry Andric   using node_iterator = NodeList::const_iterator;
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   Error *E;
1160b57cec5SDimitry Andric   const MachOObjectFile *O;
1170b57cec5SDimitry Andric   ArrayRef<uint8_t> Trie;
1180b57cec5SDimitry Andric   SmallString<256> CumulativeString;
1190b57cec5SDimitry Andric   NodeList Stack;
1200b57cec5SDimitry Andric   bool Done = false;
1210b57cec5SDimitry Andric 
nodes()1220b57cec5SDimitry Andric   iterator_range<node_iterator> nodes() const {
1230b57cec5SDimitry Andric     return make_range(Stack.begin(), Stack.end());
1240b57cec5SDimitry Andric   }
1250b57cec5SDimitry Andric };
1260b57cec5SDimitry Andric using export_iterator = content_iterator<ExportEntry>;
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric // Segment info so SegIndex/SegOffset pairs in a Mach-O Bind or Rebase entry
1290b57cec5SDimitry Andric // can be checked and translated.  Only the SegIndex/SegOffset pairs from
1300b57cec5SDimitry Andric // checked entries are to be used with the segmentName(), sectionName() and
1310b57cec5SDimitry Andric // address() methods below.
1320b57cec5SDimitry Andric class BindRebaseSegInfo {
1330b57cec5SDimitry Andric public:
1340b57cec5SDimitry Andric   BindRebaseSegInfo(const MachOObjectFile *Obj);
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric   // Used to check a Mach-O Bind or Rebase entry for errors when iterating.
1370b57cec5SDimitry Andric   const char* checkSegAndOffsets(int32_t SegIndex, uint64_t SegOffset,
1380b57cec5SDimitry Andric                                  uint8_t PointerSize, uint32_t Count=1,
1390b57cec5SDimitry Andric                                  uint32_t Skip=0);
1400b57cec5SDimitry Andric   // Used with valid SegIndex/SegOffset values from checked entries.
1410b57cec5SDimitry Andric   StringRef segmentName(int32_t SegIndex);
1420b57cec5SDimitry Andric   StringRef sectionName(int32_t SegIndex, uint64_t SegOffset);
1430b57cec5SDimitry Andric   uint64_t address(uint32_t SegIndex, uint64_t SegOffset);
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric private:
1460b57cec5SDimitry Andric   struct SectionInfo {
1470b57cec5SDimitry Andric     uint64_t Address;
1480b57cec5SDimitry Andric     uint64_t Size;
1490b57cec5SDimitry Andric     StringRef SectionName;
1500b57cec5SDimitry Andric     StringRef SegmentName;
1510b57cec5SDimitry Andric     uint64_t OffsetInSegment;
1520b57cec5SDimitry Andric     uint64_t SegmentStartAddress;
1530b57cec5SDimitry Andric     int32_t SegmentIndex;
1540b57cec5SDimitry Andric   };
1550b57cec5SDimitry Andric   const SectionInfo &findSection(int32_t SegIndex, uint64_t SegOffset);
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric   SmallVector<SectionInfo, 32> Sections;
1580b57cec5SDimitry Andric   int32_t MaxSegIndex;
1590b57cec5SDimitry Andric };
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric /// MachORebaseEntry encapsulates the current state in the decompression of
1620b57cec5SDimitry Andric /// rebasing opcodes. This allows you to iterate through the compressed table of
1630b57cec5SDimitry Andric /// rebasing using:
1645ffd83dbSDimitry Andric ///    Error Err = Error::success();
1650b57cec5SDimitry Andric ///    for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable(&Err)) {
1660b57cec5SDimitry Andric ///    }
1670b57cec5SDimitry Andric ///    if (Err) { report error ...
1680b57cec5SDimitry Andric class MachORebaseEntry {
1690b57cec5SDimitry Andric public:
1700b57cec5SDimitry Andric   MachORebaseEntry(Error *Err, const MachOObjectFile *O,
1710b57cec5SDimitry Andric                    ArrayRef<uint8_t> opcodes, bool is64Bit);
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric   int32_t segmentIndex() const;
1740b57cec5SDimitry Andric   uint64_t segmentOffset() const;
1750b57cec5SDimitry Andric   StringRef typeName() const;
1760b57cec5SDimitry Andric   StringRef segmentName() const;
1770b57cec5SDimitry Andric   StringRef sectionName() const;
1780b57cec5SDimitry Andric   uint64_t address() const;
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric   bool operator==(const MachORebaseEntry &) const;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   void moveNext();
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric private:
1850b57cec5SDimitry Andric   friend class MachOObjectFile;
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric   void moveToFirst();
1880b57cec5SDimitry Andric   void moveToEnd();
1890b57cec5SDimitry Andric   uint64_t readULEB128(const char **error);
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   Error *E;
1920b57cec5SDimitry Andric   const MachOObjectFile *O;
1930b57cec5SDimitry Andric   ArrayRef<uint8_t> Opcodes;
1940b57cec5SDimitry Andric   const uint8_t *Ptr;
1950b57cec5SDimitry Andric   uint64_t SegmentOffset = 0;
1960b57cec5SDimitry Andric   int32_t SegmentIndex = -1;
1970b57cec5SDimitry Andric   uint64_t RemainingLoopCount = 0;
1980b57cec5SDimitry Andric   uint64_t AdvanceAmount = 0;
1990b57cec5SDimitry Andric   uint8_t  RebaseType = 0;
2000b57cec5SDimitry Andric   uint8_t  PointerSize;
2010b57cec5SDimitry Andric   bool     Done = false;
2020b57cec5SDimitry Andric };
2030b57cec5SDimitry Andric using rebase_iterator = content_iterator<MachORebaseEntry>;
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric /// MachOBindEntry encapsulates the current state in the decompression of
2060b57cec5SDimitry Andric /// binding opcodes. This allows you to iterate through the compressed table of
2070b57cec5SDimitry Andric /// bindings using:
2085ffd83dbSDimitry Andric ///    Error Err = Error::success();
2090b57cec5SDimitry Andric ///    for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(&Err)) {
2100b57cec5SDimitry Andric ///    }
2110b57cec5SDimitry Andric ///    if (Err) { report error ...
2120b57cec5SDimitry Andric class MachOBindEntry {
2130b57cec5SDimitry Andric public:
2140b57cec5SDimitry Andric   enum class Kind { Regular, Lazy, Weak };
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric   MachOBindEntry(Error *Err, const MachOObjectFile *O,
2170b57cec5SDimitry Andric                  ArrayRef<uint8_t> Opcodes, bool is64Bit, MachOBindEntry::Kind);
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   int32_t segmentIndex() const;
2200b57cec5SDimitry Andric   uint64_t segmentOffset() const;
2210b57cec5SDimitry Andric   StringRef typeName() const;
2220b57cec5SDimitry Andric   StringRef symbolName() const;
2230b57cec5SDimitry Andric   uint32_t flags() const;
2240b57cec5SDimitry Andric   int64_t addend() const;
2250b57cec5SDimitry Andric   int ordinal() const;
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric   StringRef segmentName() const;
2280b57cec5SDimitry Andric   StringRef sectionName() const;
2290b57cec5SDimitry Andric   uint64_t address() const;
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric   bool operator==(const MachOBindEntry &) const;
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric   void moveNext();
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric private:
2360b57cec5SDimitry Andric   friend class MachOObjectFile;
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   void moveToFirst();
2390b57cec5SDimitry Andric   void moveToEnd();
2400b57cec5SDimitry Andric   uint64_t readULEB128(const char **error);
2410b57cec5SDimitry Andric   int64_t readSLEB128(const char **error);
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   Error *E;
2440b57cec5SDimitry Andric   const MachOObjectFile *O;
2450b57cec5SDimitry Andric   ArrayRef<uint8_t> Opcodes;
2460b57cec5SDimitry Andric   const uint8_t *Ptr;
2470b57cec5SDimitry Andric   uint64_t SegmentOffset = 0;
2480b57cec5SDimitry Andric   int32_t  SegmentIndex = -1;
2490b57cec5SDimitry Andric   StringRef SymbolName;
2500b57cec5SDimitry Andric   bool     LibraryOrdinalSet = false;
2510b57cec5SDimitry Andric   int      Ordinal = 0;
2520b57cec5SDimitry Andric   uint32_t Flags = 0;
2530b57cec5SDimitry Andric   int64_t  Addend = 0;
2540b57cec5SDimitry Andric   uint64_t RemainingLoopCount = 0;
2550b57cec5SDimitry Andric   uint64_t AdvanceAmount = 0;
2560b57cec5SDimitry Andric   uint8_t  BindType = 0;
2570b57cec5SDimitry Andric   uint8_t  PointerSize;
2580b57cec5SDimitry Andric   Kind     TableKind;
2590b57cec5SDimitry Andric   bool     Done = false;
2600b57cec5SDimitry Andric };
2610b57cec5SDimitry Andric using bind_iterator = content_iterator<MachOBindEntry>;
2620b57cec5SDimitry Andric 
26381ad6265SDimitry Andric /// ChainedFixupTarget holds all the information about an external symbol
26481ad6265SDimitry Andric /// necessary to bind this binary to that symbol. These values are referenced
26581ad6265SDimitry Andric /// indirectly by chained fixup binds. This structure captures values from all
26681ad6265SDimitry Andric /// import and symbol formats.
26781ad6265SDimitry Andric ///
26881ad6265SDimitry Andric /// Be aware there are two notions of weak here:
26981ad6265SDimitry Andric ///   WeakImport == true
27081ad6265SDimitry Andric ///     The associated bind may be set to 0 if this symbol is missing from its
27181ad6265SDimitry Andric ///     parent library. This is called a "weak import."
27281ad6265SDimitry Andric ///   LibOrdinal == BIND_SPECIAL_DYLIB_WEAK_LOOKUP
27381ad6265SDimitry Andric ///     This symbol may be coalesced with other libraries vending the same
27481ad6265SDimitry Andric ///     symbol. E.g., C++'s "operator new". This is called a "weak bind."
27581ad6265SDimitry Andric struct ChainedFixupTarget {
27681ad6265SDimitry Andric public:
ChainedFixupTargetChainedFixupTarget277bdd1243dSDimitry Andric   ChainedFixupTarget(int LibOrdinal, uint32_t NameOffset, StringRef Symbol,
278bdd1243dSDimitry Andric                      uint64_t Addend, bool WeakImport)
279bdd1243dSDimitry Andric       : LibOrdinal(LibOrdinal), NameOffset(NameOffset), SymbolName(Symbol),
280bdd1243dSDimitry Andric         Addend(Addend), WeakImport(WeakImport) {}
28181ad6265SDimitry Andric 
libOrdinalChainedFixupTarget28281ad6265SDimitry Andric   int libOrdinal() { return LibOrdinal; }
nameOffsetChainedFixupTarget283bdd1243dSDimitry Andric   uint32_t nameOffset() { return NameOffset; }
symbolNameChainedFixupTarget28481ad6265SDimitry Andric   StringRef symbolName() { return SymbolName; }
addendChainedFixupTarget28581ad6265SDimitry Andric   uint64_t addend() { return Addend; }
weakImportChainedFixupTarget28681ad6265SDimitry Andric   bool weakImport() { return WeakImport; }
weakBindChainedFixupTarget28781ad6265SDimitry Andric   bool weakBind() {
28881ad6265SDimitry Andric     return LibOrdinal == MachO::BIND_SPECIAL_DYLIB_WEAK_LOOKUP;
28981ad6265SDimitry Andric   }
29081ad6265SDimitry Andric 
29181ad6265SDimitry Andric private:
29281ad6265SDimitry Andric   int LibOrdinal;
293bdd1243dSDimitry Andric   uint32_t NameOffset;
29481ad6265SDimitry Andric   StringRef SymbolName;
29581ad6265SDimitry Andric   uint64_t Addend;
29681ad6265SDimitry Andric   bool WeakImport;
29781ad6265SDimitry Andric };
29881ad6265SDimitry Andric 
299bdd1243dSDimitry Andric struct ChainedFixupsSegment {
ChainedFixupsSegmentChainedFixupsSegment300bdd1243dSDimitry Andric   ChainedFixupsSegment(uint8_t SegIdx, uint32_t Offset,
301bdd1243dSDimitry Andric                        const MachO::dyld_chained_starts_in_segment &Header,
302bdd1243dSDimitry Andric                        std::vector<uint16_t> &&PageStarts)
303bdd1243dSDimitry Andric       : SegIdx(SegIdx), Offset(Offset), Header(Header),
304bdd1243dSDimitry Andric         PageStarts(PageStarts){};
305bdd1243dSDimitry Andric 
306bdd1243dSDimitry Andric   uint32_t SegIdx;
307bdd1243dSDimitry Andric   uint32_t Offset; // dyld_chained_starts_in_image::seg_info_offset[SegIdx]
308bdd1243dSDimitry Andric   MachO::dyld_chained_starts_in_segment Header;
309bdd1243dSDimitry Andric   std::vector<uint16_t> PageStarts; // page_start[] entries, host endianness
310bdd1243dSDimitry Andric };
311bdd1243dSDimitry Andric 
31281ad6265SDimitry Andric /// MachOAbstractFixupEntry is an abstract class representing a fixup in a
31381ad6265SDimitry Andric /// MH_DYLDLINK file. Fixups generally represent rebases and binds. Binds also
31481ad6265SDimitry Andric /// subdivide into additional subtypes (weak, lazy, reexport).
31581ad6265SDimitry Andric ///
31681ad6265SDimitry Andric /// The two concrete subclasses of MachOAbstractFixupEntry are:
31781ad6265SDimitry Andric ///
31881ad6265SDimitry Andric ///   MachORebaseBindEntry   - for dyld opcode-based tables, including threaded-
31981ad6265SDimitry Andric ///                            rebase, where rebases are mixed in with other
32081ad6265SDimitry Andric ///                            bind opcodes.
32181ad6265SDimitry Andric ///   MachOChainedFixupEntry - for pointer chains embedded in data pages.
32281ad6265SDimitry Andric class MachOAbstractFixupEntry {
32381ad6265SDimitry Andric public:
32481ad6265SDimitry Andric   MachOAbstractFixupEntry(Error *Err, const MachOObjectFile *O);
32581ad6265SDimitry Andric 
32681ad6265SDimitry Andric   int32_t segmentIndex() const;
32781ad6265SDimitry Andric   uint64_t segmentOffset() const;
32881ad6265SDimitry Andric   uint64_t segmentAddress() const;
32981ad6265SDimitry Andric   StringRef segmentName() const;
33081ad6265SDimitry Andric   StringRef sectionName() const;
33181ad6265SDimitry Andric   StringRef typeName() const;
33281ad6265SDimitry Andric   StringRef symbolName() const;
33381ad6265SDimitry Andric   uint32_t flags() const;
33481ad6265SDimitry Andric   int64_t addend() const;
33581ad6265SDimitry Andric   int ordinal() const;
33681ad6265SDimitry Andric 
33781ad6265SDimitry Andric   /// \return the location of this fixup as a VM Address. For the VM
33881ad6265SDimitry Andric   /// Address this fixup is pointing to, use pointerValue().
33981ad6265SDimitry Andric   uint64_t address() const;
34081ad6265SDimitry Andric 
34181ad6265SDimitry Andric   /// \return the VM Address pointed to by this fixup. Use
34281ad6265SDimitry Andric   /// pointerValue() to compare against other VM Addresses, such as
34381ad6265SDimitry Andric   /// section addresses or segment vmaddrs.
pointerValue()34481ad6265SDimitry Andric   uint64_t pointerValue() const { return PointerValue; }
34581ad6265SDimitry Andric 
34681ad6265SDimitry Andric   /// \return the raw "on-disk" representation of the fixup. For
34781ad6265SDimitry Andric   /// Threaded rebases and Chained pointers these values are generally
34881ad6265SDimitry Andric   /// encoded into various different pointer formats. This value is
34981ad6265SDimitry Andric   /// exposed in API for tools that want to display and annotate the
35081ad6265SDimitry Andric   /// raw bits.
rawValue()35181ad6265SDimitry Andric   uint64_t rawValue() const { return RawValue; }
35281ad6265SDimitry Andric 
35381ad6265SDimitry Andric   void moveNext();
35481ad6265SDimitry Andric 
35581ad6265SDimitry Andric protected:
35681ad6265SDimitry Andric   Error *E;
35781ad6265SDimitry Andric   const MachOObjectFile *O;
35881ad6265SDimitry Andric   uint64_t SegmentOffset = 0;
35981ad6265SDimitry Andric   int32_t SegmentIndex = -1;
36081ad6265SDimitry Andric   StringRef SymbolName;
36181ad6265SDimitry Andric   int32_t Ordinal = 0;
36281ad6265SDimitry Andric   uint32_t Flags = 0;
36381ad6265SDimitry Andric   int64_t Addend = 0;
36481ad6265SDimitry Andric   uint64_t PointerValue = 0;
36581ad6265SDimitry Andric   uint64_t RawValue = 0;
36681ad6265SDimitry Andric   bool Done = false;
36781ad6265SDimitry Andric 
36881ad6265SDimitry Andric   void moveToFirst();
36981ad6265SDimitry Andric   void moveToEnd();
37081ad6265SDimitry Andric 
37181ad6265SDimitry Andric   /// \return the vm address of the start of __TEXT segment.
textAddress()37281ad6265SDimitry Andric   uint64_t textAddress() const { return TextAddress; }
37381ad6265SDimitry Andric 
37481ad6265SDimitry Andric private:
37581ad6265SDimitry Andric   uint64_t TextAddress;
37681ad6265SDimitry Andric };
37781ad6265SDimitry Andric 
37881ad6265SDimitry Andric class MachOChainedFixupEntry : public MachOAbstractFixupEntry {
37981ad6265SDimitry Andric public:
380bdd1243dSDimitry Andric   enum class FixupKind { Bind, Rebase };
38181ad6265SDimitry Andric 
38281ad6265SDimitry Andric   MachOChainedFixupEntry(Error *Err, const MachOObjectFile *O, bool Parse);
38381ad6265SDimitry Andric 
38481ad6265SDimitry Andric   bool operator==(const MachOChainedFixupEntry &) const;
38581ad6265SDimitry Andric 
isBind()386bdd1243dSDimitry Andric   bool isBind() const { return Kind == FixupKind::Bind; }
isRebase()387bdd1243dSDimitry Andric   bool isRebase() const { return Kind == FixupKind::Rebase; }
388bdd1243dSDimitry Andric 
38981ad6265SDimitry Andric   void moveNext();
39081ad6265SDimitry Andric   void moveToFirst();
39181ad6265SDimitry Andric   void moveToEnd();
39281ad6265SDimitry Andric 
39381ad6265SDimitry Andric private:
394bdd1243dSDimitry Andric   void findNextPageWithFixups();
395bdd1243dSDimitry Andric 
39681ad6265SDimitry Andric   std::vector<ChainedFixupTarget> FixupTargets;
397bdd1243dSDimitry Andric   std::vector<ChainedFixupsSegment> Segments;
398bdd1243dSDimitry Andric   ArrayRef<uint8_t> SegmentData;
399bdd1243dSDimitry Andric   FixupKind Kind;
400bdd1243dSDimitry Andric   uint32_t InfoSegIndex = 0; // Index into Segments
401bdd1243dSDimitry Andric   uint32_t PageIndex = 0;    // Index into Segments[InfoSegIdx].PageStarts
402bdd1243dSDimitry Andric   uint32_t PageOffset = 0;   // Page offset of the current fixup
40381ad6265SDimitry Andric };
40481ad6265SDimitry Andric using fixup_iterator = content_iterator<MachOChainedFixupEntry>;
40581ad6265SDimitry Andric 
4060b57cec5SDimitry Andric class MachOObjectFile : public ObjectFile {
4070b57cec5SDimitry Andric public:
4080b57cec5SDimitry Andric   struct LoadCommandInfo {
4090b57cec5SDimitry Andric     const char *Ptr;      // Where in memory the load command is.
4100b57cec5SDimitry Andric     MachO::load_command C; // The command itself.
4110b57cec5SDimitry Andric   };
4120b57cec5SDimitry Andric   using LoadCommandList = SmallVector<LoadCommandInfo, 4>;
4130b57cec5SDimitry Andric   using load_command_iterator = LoadCommandList::const_iterator;
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric   static Expected<std::unique_ptr<MachOObjectFile>>
4160b57cec5SDimitry Andric   create(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits,
4175f757f3fSDimitry Andric          uint32_t UniversalCputype = 0, uint32_t UniversalIndex = 0,
4185f757f3fSDimitry Andric          size_t MachOFilesetEntryOffset = 0);
4190b57cec5SDimitry Andric 
42081ad6265SDimitry Andric   static bool isMachOPairedReloc(uint64_t RelocType, uint64_t Arch);
42181ad6265SDimitry Andric 
4220b57cec5SDimitry Andric   void moveSymbolNext(DataRefImpl &Symb) const override;
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric   uint64_t getNValue(DataRefImpl Sym) const;
4250b57cec5SDimitry Andric   Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric   // MachO specific.
4280b57cec5SDimitry Andric   Error checkSymbolTable() const;
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric   std::error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const;
4310b57cec5SDimitry Andric   unsigned getSectionType(SectionRef Sec) const;
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric   Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
4340b57cec5SDimitry Andric   uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
4350b57cec5SDimitry Andric   uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
4360b57cec5SDimitry Andric   Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
4375ffd83dbSDimitry Andric   Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
4380b57cec5SDimitry Andric   Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
4390b57cec5SDimitry Andric   unsigned getSymbolSectionID(SymbolRef Symb) const;
4400b57cec5SDimitry Andric   unsigned getSectionID(SectionRef Sec) const;
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric   void moveSectionNext(DataRefImpl &Sec) const override;
4430b57cec5SDimitry Andric   Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
4440b57cec5SDimitry Andric   uint64_t getSectionAddress(DataRefImpl Sec) const override;
4450b57cec5SDimitry Andric   uint64_t getSectionIndex(DataRefImpl Sec) const override;
4460b57cec5SDimitry Andric   uint64_t getSectionSize(DataRefImpl Sec) const override;
4478bcb0991SDimitry Andric   ArrayRef<uint8_t> getSectionContents(uint32_t Offset, uint64_t Size) const;
4480b57cec5SDimitry Andric   Expected<ArrayRef<uint8_t>>
4490b57cec5SDimitry Andric   getSectionContents(DataRefImpl Sec) const override;
4500b57cec5SDimitry Andric   uint64_t getSectionAlignment(DataRefImpl Sec) const override;
4510b57cec5SDimitry Andric   Expected<SectionRef> getSection(unsigned SectionIndex) const;
4520b57cec5SDimitry Andric   Expected<SectionRef> getSection(StringRef SectionName) const;
4530b57cec5SDimitry Andric   bool isSectionCompressed(DataRefImpl Sec) const override;
4540b57cec5SDimitry Andric   bool isSectionText(DataRefImpl Sec) const override;
4550b57cec5SDimitry Andric   bool isSectionData(DataRefImpl Sec) const override;
4560b57cec5SDimitry Andric   bool isSectionBSS(DataRefImpl Sec) const override;
4570b57cec5SDimitry Andric   bool isSectionVirtual(DataRefImpl Sec) const override;
4580b57cec5SDimitry Andric   bool isSectionBitcode(DataRefImpl Sec) const override;
459fe6060f1SDimitry Andric   bool isDebugSection(DataRefImpl Sec) const override;
4600b57cec5SDimitry Andric 
461349cc55cSDimitry Andric   /// Return the raw contents of an entire segment.
462349cc55cSDimitry Andric   ArrayRef<uint8_t> getSegmentContents(StringRef SegmentName) const;
463bdd1243dSDimitry Andric   ArrayRef<uint8_t> getSegmentContents(size_t SegmentIndex) const;
464349cc55cSDimitry Andric 
4650b57cec5SDimitry Andric   /// When dsymutil generates the companion file, it strips all unnecessary
4660b57cec5SDimitry Andric   /// sections (e.g. everything in the _TEXT segment) by omitting their body
4670b57cec5SDimitry Andric   /// and setting the offset in their corresponding load command to zero.
4680b57cec5SDimitry Andric   ///
4690b57cec5SDimitry Andric   /// While the load command itself is valid, reading the section corresponds
4700b57cec5SDimitry Andric   /// to reading the number of bytes specified in the load command, starting
4710b57cec5SDimitry Andric   /// from offset 0 (i.e. the Mach-O header at the beginning of the file).
4720b57cec5SDimitry Andric   bool isSectionStripped(DataRefImpl Sec) const override;
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric   relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
4750b57cec5SDimitry Andric   relocation_iterator section_rel_end(DataRefImpl Sec) const override;
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric   relocation_iterator extrel_begin() const;
4780b57cec5SDimitry Andric   relocation_iterator extrel_end() const;
external_relocations()4790b57cec5SDimitry Andric   iterator_range<relocation_iterator> external_relocations() const {
4800b57cec5SDimitry Andric     return make_range(extrel_begin(), extrel_end());
4810b57cec5SDimitry Andric   }
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric   relocation_iterator locrel_begin() const;
4840b57cec5SDimitry Andric   relocation_iterator locrel_end() const;
4850b57cec5SDimitry Andric 
4860b57cec5SDimitry Andric   void moveRelocationNext(DataRefImpl &Rel) const override;
4870b57cec5SDimitry Andric   uint64_t getRelocationOffset(DataRefImpl Rel) const override;
4880b57cec5SDimitry Andric   symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
4890b57cec5SDimitry Andric   section_iterator getRelocationSection(DataRefImpl Rel) const;
4900b57cec5SDimitry Andric   uint64_t getRelocationType(DataRefImpl Rel) const override;
4910b57cec5SDimitry Andric   void getRelocationTypeName(DataRefImpl Rel,
4920b57cec5SDimitry Andric                              SmallVectorImpl<char> &Result) const override;
4930b57cec5SDimitry Andric   uint8_t getRelocationLength(DataRefImpl Rel) const;
4940b57cec5SDimitry Andric 
4950b57cec5SDimitry Andric   // MachO specific.
4960b57cec5SDimitry Andric   std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &) const;
4970b57cec5SDimitry Andric   uint32_t getLibraryCount() const;
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric   section_iterator getRelocationRelocatedSection(relocation_iterator Rel) const;
5000b57cec5SDimitry Andric 
5010b57cec5SDimitry Andric   // TODO: Would be useful to have an iterator based version
5020b57cec5SDimitry Andric   // of the load command interface too.
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric   basic_symbol_iterator symbol_begin() const override;
5050b57cec5SDimitry Andric   basic_symbol_iterator symbol_end() const override;
5060b57cec5SDimitry Andric 
50706c3fb27SDimitry Andric   bool is64Bit() const override;
50806c3fb27SDimitry Andric 
5090b57cec5SDimitry Andric   // MachO specific.
5100b57cec5SDimitry Andric   symbol_iterator getSymbolByIndex(unsigned Index) const;
5110b57cec5SDimitry Andric   uint64_t getSymbolIndex(DataRefImpl Symb) const;
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric   section_iterator section_begin() const override;
5140b57cec5SDimitry Andric   section_iterator section_end() const override;
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric   uint8_t getBytesInAddress() const override;
5170b57cec5SDimitry Andric 
5180b57cec5SDimitry Andric   StringRef getFileFormatName() const override;
5190b57cec5SDimitry Andric   Triple::ArchType getArch() const override;
getFeatures()520bdd1243dSDimitry Andric   Expected<SubtargetFeatures> getFeatures() const override {
521bdd1243dSDimitry Andric     return SubtargetFeatures();
522bdd1243dSDimitry Andric   }
5230b57cec5SDimitry Andric   Triple getArchTriple(const char **McpuDefault = nullptr) const;
5240b57cec5SDimitry Andric 
5250b57cec5SDimitry Andric   relocation_iterator section_rel_begin(unsigned Index) const;
5260b57cec5SDimitry Andric   relocation_iterator section_rel_end(unsigned Index) const;
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric   dice_iterator begin_dices() const;
5290b57cec5SDimitry Andric   dice_iterator end_dices() const;
5300b57cec5SDimitry Andric 
5310b57cec5SDimitry Andric   load_command_iterator begin_load_commands() const;
5320b57cec5SDimitry Andric   load_command_iterator end_load_commands() const;
5330b57cec5SDimitry Andric   iterator_range<load_command_iterator> load_commands() const;
5340b57cec5SDimitry Andric 
5350b57cec5SDimitry Andric   /// For use iterating over all exported symbols.
5360b57cec5SDimitry Andric   iterator_range<export_iterator> exports(Error &Err) const;
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric   /// For use examining a trie not in a MachOObjectFile.
5390b57cec5SDimitry Andric   static iterator_range<export_iterator> exports(Error &Err,
5400b57cec5SDimitry Andric                                                  ArrayRef<uint8_t> Trie,
5410b57cec5SDimitry Andric                                                  const MachOObjectFile *O =
5420b57cec5SDimitry Andric                                                                       nullptr);
5430b57cec5SDimitry Andric 
5440b57cec5SDimitry Andric   /// For use iterating over all rebase table entries.
5450b57cec5SDimitry Andric   iterator_range<rebase_iterator> rebaseTable(Error &Err);
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric   /// For use examining rebase opcodes in a MachOObjectFile.
5480b57cec5SDimitry Andric   static iterator_range<rebase_iterator> rebaseTable(Error &Err,
5490b57cec5SDimitry Andric                                                      MachOObjectFile *O,
5500b57cec5SDimitry Andric                                                      ArrayRef<uint8_t> Opcodes,
5510b57cec5SDimitry Andric                                                      bool is64);
5520b57cec5SDimitry Andric 
5530b57cec5SDimitry Andric   /// For use iterating over all bind table entries.
5540b57cec5SDimitry Andric   iterator_range<bind_iterator> bindTable(Error &Err);
5550b57cec5SDimitry Andric 
55681ad6265SDimitry Andric   /// For iterating over all chained fixups.
55781ad6265SDimitry Andric   iterator_range<fixup_iterator> fixupTable(Error &Err);
55881ad6265SDimitry Andric 
5590b57cec5SDimitry Andric   /// For use iterating over all lazy bind table entries.
5600b57cec5SDimitry Andric   iterator_range<bind_iterator> lazyBindTable(Error &Err);
5610b57cec5SDimitry Andric 
5620b57cec5SDimitry Andric   /// For use iterating over all weak bind table entries.
5630b57cec5SDimitry Andric   iterator_range<bind_iterator> weakBindTable(Error &Err);
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric   /// For use examining bind opcodes in a MachOObjectFile.
5660b57cec5SDimitry Andric   static iterator_range<bind_iterator> bindTable(Error &Err,
5670b57cec5SDimitry Andric                                                  MachOObjectFile *O,
5680b57cec5SDimitry Andric                                                  ArrayRef<uint8_t> Opcodes,
5690b57cec5SDimitry Andric                                                  bool is64,
5700b57cec5SDimitry Andric                                                  MachOBindEntry::Kind);
5710b57cec5SDimitry Andric 
5720b57cec5SDimitry Andric   // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
5730b57cec5SDimitry Andric   // that fully contains a pointer at that location. Multiple fixups in a bind
5740b57cec5SDimitry Andric   // (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can
5750b57cec5SDimitry Andric   // be tested via the Count and Skip parameters.
5760b57cec5SDimitry Andric   //
5770b57cec5SDimitry Andric   // This is used by MachOBindEntry::moveNext() to validate a MachOBindEntry.
5780b57cec5SDimitry Andric   const char *BindEntryCheckSegAndOffsets(int32_t SegIndex, uint64_t SegOffset,
5790b57cec5SDimitry Andric                                          uint8_t PointerSize, uint32_t Count=1,
5800b57cec5SDimitry Andric                                           uint32_t Skip=0) const {
5810b57cec5SDimitry Andric     return BindRebaseSectionTable->checkSegAndOffsets(SegIndex, SegOffset,
5820b57cec5SDimitry Andric                                                      PointerSize, Count, Skip);
5830b57cec5SDimitry Andric   }
5840b57cec5SDimitry Andric 
5850b57cec5SDimitry Andric   // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
5860b57cec5SDimitry Andric   // that fully contains a pointer at that location. Multiple fixups in a rebase
5870b57cec5SDimitry Andric   // (such as with the REBASE_OPCODE_DO_*_TIMES* opcodes) can be tested via the
5880b57cec5SDimitry Andric   // Count and Skip parameters.
5890b57cec5SDimitry Andric   //
5900b57cec5SDimitry Andric   // This is used by MachORebaseEntry::moveNext() to validate a MachORebaseEntry
5910b57cec5SDimitry Andric   const char *RebaseEntryCheckSegAndOffsets(int32_t SegIndex,
5920b57cec5SDimitry Andric                                             uint64_t SegOffset,
5930b57cec5SDimitry Andric                                             uint8_t PointerSize,
5940b57cec5SDimitry Andric                                             uint32_t Count=1,
5950b57cec5SDimitry Andric                                             uint32_t Skip=0) const {
5960b57cec5SDimitry Andric     return BindRebaseSectionTable->checkSegAndOffsets(SegIndex, SegOffset,
5970b57cec5SDimitry Andric                                                       PointerSize, Count, Skip);
5980b57cec5SDimitry Andric   }
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric   /// For use with the SegIndex of a checked Mach-O Bind or Rebase entry to
6010b57cec5SDimitry Andric   /// get the segment name.
BindRebaseSegmentName(int32_t SegIndex)6020b57cec5SDimitry Andric   StringRef BindRebaseSegmentName(int32_t SegIndex) const {
6030b57cec5SDimitry Andric     return BindRebaseSectionTable->segmentName(SegIndex);
6040b57cec5SDimitry Andric   }
6050b57cec5SDimitry Andric 
6060b57cec5SDimitry Andric   /// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or
6070b57cec5SDimitry Andric   /// Rebase entry to get the section name.
BindRebaseSectionName(uint32_t SegIndex,uint64_t SegOffset)6080b57cec5SDimitry Andric   StringRef BindRebaseSectionName(uint32_t SegIndex, uint64_t SegOffset) const {
6090b57cec5SDimitry Andric     return BindRebaseSectionTable->sectionName(SegIndex, SegOffset);
6100b57cec5SDimitry Andric   }
6110b57cec5SDimitry Andric 
6120b57cec5SDimitry Andric   /// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or
6130b57cec5SDimitry Andric   /// Rebase entry to get the address.
BindRebaseAddress(uint32_t SegIndex,uint64_t SegOffset)6140b57cec5SDimitry Andric   uint64_t BindRebaseAddress(uint32_t SegIndex, uint64_t SegOffset) const {
6150b57cec5SDimitry Andric     return BindRebaseSectionTable->address(SegIndex, SegOffset);
6160b57cec5SDimitry Andric   }
6170b57cec5SDimitry Andric 
6180b57cec5SDimitry Andric   // In a MachO file, sections have a segment name. This is used in the .o
6190b57cec5SDimitry Andric   // files. They have a single segment, but this field specifies which segment
6200b57cec5SDimitry Andric   // a section should be put in the final object.
6210b57cec5SDimitry Andric   StringRef getSectionFinalSegmentName(DataRefImpl Sec) const;
6220b57cec5SDimitry Andric 
6230b57cec5SDimitry Andric   // Names are stored as 16 bytes. These returns the raw 16 bytes without
6240b57cec5SDimitry Andric   // interpreting them as a C string.
6250b57cec5SDimitry Andric   ArrayRef<char> getSectionRawName(DataRefImpl Sec) const;
6260b57cec5SDimitry Andric   ArrayRef<char> getSectionRawFinalSegmentName(DataRefImpl Sec) const;
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric   // MachO specific Info about relocations.
6290b57cec5SDimitry Andric   bool isRelocationScattered(const MachO::any_relocation_info &RE) const;
6300b57cec5SDimitry Andric   unsigned getPlainRelocationSymbolNum(
6310b57cec5SDimitry Andric                                     const MachO::any_relocation_info &RE) const;
6320b57cec5SDimitry Andric   bool getPlainRelocationExternal(const MachO::any_relocation_info &RE) const;
6330b57cec5SDimitry Andric   bool getScatteredRelocationScattered(
6340b57cec5SDimitry Andric                                     const MachO::any_relocation_info &RE) const;
6350b57cec5SDimitry Andric   uint32_t getScatteredRelocationValue(
6360b57cec5SDimitry Andric                                     const MachO::any_relocation_info &RE) const;
6370b57cec5SDimitry Andric   uint32_t getScatteredRelocationType(
6380b57cec5SDimitry Andric                                     const MachO::any_relocation_info &RE) const;
6390b57cec5SDimitry Andric   unsigned getAnyRelocationAddress(const MachO::any_relocation_info &RE) const;
6400b57cec5SDimitry Andric   unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const;
6410b57cec5SDimitry Andric   unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const;
6420b57cec5SDimitry Andric   unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const;
6430b57cec5SDimitry Andric   SectionRef getAnyRelocationSection(const MachO::any_relocation_info &RE) const;
6440b57cec5SDimitry Andric 
6450b57cec5SDimitry Andric   // MachO specific structures.
6460b57cec5SDimitry Andric   MachO::section getSection(DataRefImpl DRI) const;
6470b57cec5SDimitry Andric   MachO::section_64 getSection64(DataRefImpl DRI) const;
6480b57cec5SDimitry Andric   MachO::section getSection(const LoadCommandInfo &L, unsigned Index) const;
6490b57cec5SDimitry Andric   MachO::section_64 getSection64(const LoadCommandInfo &L,unsigned Index) const;
6500b57cec5SDimitry Andric   MachO::nlist getSymbolTableEntry(DataRefImpl DRI) const;
6510b57cec5SDimitry Andric   MachO::nlist_64 getSymbol64TableEntry(DataRefImpl DRI) const;
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric   MachO::linkedit_data_command
6540b57cec5SDimitry Andric   getLinkeditDataLoadCommand(const LoadCommandInfo &L) const;
6550b57cec5SDimitry Andric   MachO::segment_command
6560b57cec5SDimitry Andric   getSegmentLoadCommand(const LoadCommandInfo &L) const;
6570b57cec5SDimitry Andric   MachO::segment_command_64
6580b57cec5SDimitry Andric   getSegment64LoadCommand(const LoadCommandInfo &L) const;
6590b57cec5SDimitry Andric   MachO::linker_option_command
6600b57cec5SDimitry Andric   getLinkerOptionLoadCommand(const LoadCommandInfo &L) const;
6610b57cec5SDimitry Andric   MachO::version_min_command
6620b57cec5SDimitry Andric   getVersionMinLoadCommand(const LoadCommandInfo &L) const;
6630b57cec5SDimitry Andric   MachO::note_command
6640b57cec5SDimitry Andric   getNoteLoadCommand(const LoadCommandInfo &L) const;
6650b57cec5SDimitry Andric   MachO::build_version_command
6660b57cec5SDimitry Andric   getBuildVersionLoadCommand(const LoadCommandInfo &L) const;
6670b57cec5SDimitry Andric   MachO::build_tool_version
6680b57cec5SDimitry Andric   getBuildToolVersion(unsigned index) const;
6690b57cec5SDimitry Andric   MachO::dylib_command
6700b57cec5SDimitry Andric   getDylibIDLoadCommand(const LoadCommandInfo &L) const;
6710b57cec5SDimitry Andric   MachO::dyld_info_command
6720b57cec5SDimitry Andric   getDyldInfoLoadCommand(const LoadCommandInfo &L) const;
6730b57cec5SDimitry Andric   MachO::dylinker_command
6740b57cec5SDimitry Andric   getDylinkerCommand(const LoadCommandInfo &L) const;
6750b57cec5SDimitry Andric   MachO::uuid_command
6760b57cec5SDimitry Andric   getUuidCommand(const LoadCommandInfo &L) const;
6770b57cec5SDimitry Andric   MachO::rpath_command
6780b57cec5SDimitry Andric   getRpathCommand(const LoadCommandInfo &L) const;
6790b57cec5SDimitry Andric   MachO::source_version_command
6800b57cec5SDimitry Andric   getSourceVersionCommand(const LoadCommandInfo &L) const;
6810b57cec5SDimitry Andric   MachO::entry_point_command
6820b57cec5SDimitry Andric   getEntryPointCommand(const LoadCommandInfo &L) const;
6830b57cec5SDimitry Andric   MachO::encryption_info_command
6840b57cec5SDimitry Andric   getEncryptionInfoCommand(const LoadCommandInfo &L) const;
6850b57cec5SDimitry Andric   MachO::encryption_info_command_64
6860b57cec5SDimitry Andric   getEncryptionInfoCommand64(const LoadCommandInfo &L) const;
6870b57cec5SDimitry Andric   MachO::sub_framework_command
6880b57cec5SDimitry Andric   getSubFrameworkCommand(const LoadCommandInfo &L) const;
6890b57cec5SDimitry Andric   MachO::sub_umbrella_command
6900b57cec5SDimitry Andric   getSubUmbrellaCommand(const LoadCommandInfo &L) const;
6910b57cec5SDimitry Andric   MachO::sub_library_command
6920b57cec5SDimitry Andric   getSubLibraryCommand(const LoadCommandInfo &L) const;
6930b57cec5SDimitry Andric   MachO::sub_client_command
6940b57cec5SDimitry Andric   getSubClientCommand(const LoadCommandInfo &L) const;
6950b57cec5SDimitry Andric   MachO::routines_command
6960b57cec5SDimitry Andric   getRoutinesCommand(const LoadCommandInfo &L) const;
6970b57cec5SDimitry Andric   MachO::routines_command_64
6980b57cec5SDimitry Andric   getRoutinesCommand64(const LoadCommandInfo &L) const;
6990b57cec5SDimitry Andric   MachO::thread_command
7000b57cec5SDimitry Andric   getThreadCommand(const LoadCommandInfo &L) const;
7015f757f3fSDimitry Andric   MachO::fileset_entry_command
7025f757f3fSDimitry Andric   getFilesetEntryLoadCommand(const LoadCommandInfo &L) const;
7030b57cec5SDimitry Andric 
7040b57cec5SDimitry Andric   MachO::any_relocation_info getRelocation(DataRefImpl Rel) const;
7050b57cec5SDimitry Andric   MachO::data_in_code_entry getDice(DataRefImpl Rel) const;
7060b57cec5SDimitry Andric   const MachO::mach_header &getHeader() const;
7070b57cec5SDimitry Andric   const MachO::mach_header_64 &getHeader64() const;
7080b57cec5SDimitry Andric   uint32_t
7090b57cec5SDimitry Andric   getIndirectSymbolTableEntry(const MachO::dysymtab_command &DLC,
7100b57cec5SDimitry Andric                               unsigned Index) const;
7110b57cec5SDimitry Andric   MachO::data_in_code_entry getDataInCodeTableEntry(uint32_t DataOffset,
7120b57cec5SDimitry Andric                                                     unsigned Index) const;
7130b57cec5SDimitry Andric   MachO::symtab_command getSymtabLoadCommand() const;
7140b57cec5SDimitry Andric   MachO::dysymtab_command getDysymtabLoadCommand() const;
7150b57cec5SDimitry Andric   MachO::linkedit_data_command getDataInCodeLoadCommand() const;
7160b57cec5SDimitry Andric   MachO::linkedit_data_command getLinkOptHintsLoadCommand() const;
7170b57cec5SDimitry Andric   ArrayRef<uint8_t> getDyldInfoRebaseOpcodes() const;
7180b57cec5SDimitry Andric   ArrayRef<uint8_t> getDyldInfoBindOpcodes() const;
7190b57cec5SDimitry Andric   ArrayRef<uint8_t> getDyldInfoWeakBindOpcodes() const;
7200b57cec5SDimitry Andric   ArrayRef<uint8_t> getDyldInfoLazyBindOpcodes() const;
721bdd1243dSDimitry Andric   ArrayRef<uint8_t> getDyldInfoExportsTrie() const;
722bdd1243dSDimitry Andric 
72306c3fb27SDimitry Andric   /// If the optional is std::nullopt, no header was found, but the object was
724bdd1243dSDimitry Andric   /// well-formed.
725bdd1243dSDimitry Andric   Expected<std::optional<MachO::dyld_chained_fixups_header>>
72681ad6265SDimitry Andric   getChainedFixupsHeader() const;
72781ad6265SDimitry Andric   Expected<std::vector<ChainedFixupTarget>> getDyldChainedFixupTargets() const;
728bdd1243dSDimitry Andric 
729bdd1243dSDimitry Andric   // Note: This is a limited, temporary API, which will be removed when Apple
730bdd1243dSDimitry Andric   // upstreams their implementation. Please do not rely on this.
731bdd1243dSDimitry Andric   Expected<std::optional<MachO::linkedit_data_command>>
732bdd1243dSDimitry Andric   getChainedFixupsLoadCommand() const;
733bdd1243dSDimitry Andric   // Returns the number of sections listed in dyld_chained_starts_in_image, and
734bdd1243dSDimitry Andric   // a ChainedFixupsSegment for each segment that has fixups.
735bdd1243dSDimitry Andric   Expected<std::pair<size_t, std::vector<ChainedFixupsSegment>>>
736bdd1243dSDimitry Andric   getChainedFixupsSegments() const;
737bdd1243dSDimitry Andric   ArrayRef<uint8_t> getDyldExportsTrie() const;
738bdd1243dSDimitry Andric 
73981ad6265SDimitry Andric   SmallVector<uint64_t> getFunctionStarts() const;
7400b57cec5SDimitry Andric   ArrayRef<uint8_t> getUuid() const;
7410b57cec5SDimitry Andric 
7420b57cec5SDimitry Andric   StringRef getStringTableData() const;
74306c3fb27SDimitry Andric 
7440b57cec5SDimitry Andric   void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const;
7450b57cec5SDimitry Andric 
7460b57cec5SDimitry Andric   static StringRef guessLibraryShortName(StringRef Name, bool &isFramework,
7470b57cec5SDimitry Andric                                          StringRef &Suffix);
7480b57cec5SDimitry Andric 
749480093f4SDimitry Andric   static Triple::ArchType getArch(uint32_t CPUType, uint32_t CPUSubType);
7500b57cec5SDimitry Andric   static Triple getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
7510b57cec5SDimitry Andric                               const char **McpuDefault = nullptr,
7520b57cec5SDimitry Andric                               const char **ArchFlag = nullptr);
7530b57cec5SDimitry Andric   static bool isValidArch(StringRef ArchFlag);
7540b57cec5SDimitry Andric   static ArrayRef<StringRef> getValidArchs();
7550b57cec5SDimitry Andric   static Triple getHostArch();
7560b57cec5SDimitry Andric 
7570b57cec5SDimitry Andric   bool isRelocatableObject() const override;
7580b57cec5SDimitry Andric 
7590b57cec5SDimitry Andric   StringRef mapDebugSectionName(StringRef Name) const override;
7600b57cec5SDimitry Andric 
7611fd87a68SDimitry Andric   llvm::binaryformat::Swift5ReflectionSectionKind
7621fd87a68SDimitry Andric   mapReflectionSectionNameToEnumValue(StringRef SectionName) const override;
7631fd87a68SDimitry Andric 
hasPageZeroSegment()7640b57cec5SDimitry Andric   bool hasPageZeroSegment() const { return HasPageZeroSegment; }
7650b57cec5SDimitry Andric 
getMachOFilesetEntryOffset()7665f757f3fSDimitry Andric   size_t getMachOFilesetEntryOffset() const { return MachOFilesetEntryOffset; }
7675f757f3fSDimitry Andric 
classof(const Binary * v)7680b57cec5SDimitry Andric   static bool classof(const Binary *v) {
7690b57cec5SDimitry Andric     return v->isMachO();
7700b57cec5SDimitry Andric   }
7710b57cec5SDimitry Andric 
7720b57cec5SDimitry Andric   static uint32_t
getVersionMinMajor(MachO::version_min_command & C,bool SDK)7730b57cec5SDimitry Andric   getVersionMinMajor(MachO::version_min_command &C, bool SDK) {
7740b57cec5SDimitry Andric     uint32_t VersionOrSDK = (SDK) ? C.sdk : C.version;
7750b57cec5SDimitry Andric     return (VersionOrSDK >> 16) & 0xffff;
7760b57cec5SDimitry Andric   }
7770b57cec5SDimitry Andric 
7780b57cec5SDimitry Andric   static uint32_t
getVersionMinMinor(MachO::version_min_command & C,bool SDK)7790b57cec5SDimitry Andric   getVersionMinMinor(MachO::version_min_command &C, bool SDK) {
7800b57cec5SDimitry Andric     uint32_t VersionOrSDK = (SDK) ? C.sdk : C.version;
7810b57cec5SDimitry Andric     return (VersionOrSDK >> 8) & 0xff;
7820b57cec5SDimitry Andric   }
7830b57cec5SDimitry Andric 
7840b57cec5SDimitry Andric   static uint32_t
getVersionMinUpdate(MachO::version_min_command & C,bool SDK)7850b57cec5SDimitry Andric   getVersionMinUpdate(MachO::version_min_command &C, bool SDK) {
7860b57cec5SDimitry Andric     uint32_t VersionOrSDK = (SDK) ? C.sdk : C.version;
7870b57cec5SDimitry Andric     return VersionOrSDK & 0xff;
7880b57cec5SDimitry Andric   }
7890b57cec5SDimitry Andric 
getBuildPlatform(uint32_t platform)7900b57cec5SDimitry Andric   static std::string getBuildPlatform(uint32_t platform) {
7910b57cec5SDimitry Andric     switch (platform) {
7925f757f3fSDimitry Andric #define PLATFORM(platform, id, name, build_name, target, tapi_target,          \
7935f757f3fSDimitry Andric                  marketing)                                                    \
7945f757f3fSDimitry Andric   case MachO::PLATFORM_##platform:                                             \
7955f757f3fSDimitry Andric     return #name;
7965f757f3fSDimitry Andric #include "llvm/BinaryFormat/MachO.def"
7970b57cec5SDimitry Andric     default:
7980b57cec5SDimitry Andric       std::string ret;
7990b57cec5SDimitry Andric       raw_string_ostream ss(ret);
8000b57cec5SDimitry Andric       ss << format_hex(platform, 8, true);
8010b57cec5SDimitry Andric       return ss.str();
8020b57cec5SDimitry Andric     }
8030b57cec5SDimitry Andric   }
8040b57cec5SDimitry Andric 
getBuildTool(uint32_t tools)8050b57cec5SDimitry Andric   static std::string getBuildTool(uint32_t tools) {
8060b57cec5SDimitry Andric     switch (tools) {
8070b57cec5SDimitry Andric     case MachO::TOOL_CLANG: return "clang";
8080b57cec5SDimitry Andric     case MachO::TOOL_SWIFT: return "swift";
8090b57cec5SDimitry Andric     case MachO::TOOL_LD: return "ld";
81006c3fb27SDimitry Andric     case MachO::TOOL_LLD:
81106c3fb27SDimitry Andric       return "lld";
8120b57cec5SDimitry Andric     default:
8130b57cec5SDimitry Andric       std::string ret;
8140b57cec5SDimitry Andric       raw_string_ostream ss(ret);
8150b57cec5SDimitry Andric       ss << format_hex(tools, 8, true);
8160b57cec5SDimitry Andric       return ss.str();
8170b57cec5SDimitry Andric     }
8180b57cec5SDimitry Andric   }
8190b57cec5SDimitry Andric 
getVersionString(uint32_t version)8200b57cec5SDimitry Andric   static std::string getVersionString(uint32_t version) {
8210b57cec5SDimitry Andric     uint32_t major = (version >> 16) & 0xffff;
8220b57cec5SDimitry Andric     uint32_t minor = (version >> 8) & 0xff;
8230b57cec5SDimitry Andric     uint32_t update = version & 0xff;
8240b57cec5SDimitry Andric 
8250b57cec5SDimitry Andric     SmallString<32> Version;
8260b57cec5SDimitry Andric     Version = utostr(major) + "." + utostr(minor);
8270b57cec5SDimitry Andric     if (update != 0)
8280b57cec5SDimitry Andric       Version += "." + utostr(update);
8297a6dacacSDimitry Andric     return std::string(std::string(Version));
8300b57cec5SDimitry Andric   }
8310b57cec5SDimitry Andric 
8320eae32dcSDimitry Andric   /// If the input path is a .dSYM bundle (as created by the dsymutil tool),
8330eae32dcSDimitry Andric   /// return the paths to the object files found in the bundle, otherwise return
8340eae32dcSDimitry Andric   /// an empty vector. If the path appears to be a .dSYM bundle but no objects
8350eae32dcSDimitry Andric   /// were found or there was a filesystem error, then return an error.
8360eae32dcSDimitry Andric   static Expected<std::vector<std::string>>
8370eae32dcSDimitry Andric   findDsymObjectMembers(StringRef Path);
8380eae32dcSDimitry Andric 
8390b57cec5SDimitry Andric private:
8400b57cec5SDimitry Andric   MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits,
8410b57cec5SDimitry Andric                   Error &Err, uint32_t UniversalCputype = 0,
8425f757f3fSDimitry Andric                   uint32_t UniversalIndex = 0,
8435f757f3fSDimitry Andric                   size_t MachOFilesetEntryOffset = 0);
8440b57cec5SDimitry Andric 
8450b57cec5SDimitry Andric   uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
8460b57cec5SDimitry Andric 
8470b57cec5SDimitry Andric   union {
8480b57cec5SDimitry Andric     MachO::mach_header_64 Header64;
8490b57cec5SDimitry Andric     MachO::mach_header Header;
8500b57cec5SDimitry Andric   };
8510b57cec5SDimitry Andric   using SectionList = SmallVector<const char*, 1>;
8520b57cec5SDimitry Andric   SectionList Sections;
8530b57cec5SDimitry Andric   using LibraryList = SmallVector<const char*, 1>;
8540b57cec5SDimitry Andric   LibraryList Libraries;
8550b57cec5SDimitry Andric   LoadCommandList LoadCommands;
8560b57cec5SDimitry Andric   using LibraryShortName = SmallVector<StringRef, 1>;
8570b57cec5SDimitry Andric   using BuildToolList = SmallVector<const char*, 1>;
8580b57cec5SDimitry Andric   BuildToolList BuildTools;
8590b57cec5SDimitry Andric   mutable LibraryShortName LibrariesShortNames;
8600b57cec5SDimitry Andric   std::unique_ptr<BindRebaseSegInfo> BindRebaseSectionTable;
8610b57cec5SDimitry Andric   const char *SymtabLoadCmd = nullptr;
8620b57cec5SDimitry Andric   const char *DysymtabLoadCmd = nullptr;
8630b57cec5SDimitry Andric   const char *DataInCodeLoadCmd = nullptr;
8640b57cec5SDimitry Andric   const char *LinkOptHintsLoadCmd = nullptr;
8650b57cec5SDimitry Andric   const char *DyldInfoLoadCmd = nullptr;
86681ad6265SDimitry Andric   const char *FuncStartsLoadCmd = nullptr;
86781ad6265SDimitry Andric   const char *DyldChainedFixupsLoadCmd = nullptr;
868bdd1243dSDimitry Andric   const char *DyldExportsTrieLoadCmd = nullptr;
8690b57cec5SDimitry Andric   const char *UuidLoadCmd = nullptr;
8700b57cec5SDimitry Andric   bool HasPageZeroSegment = false;
8715f757f3fSDimitry Andric   size_t MachOFilesetEntryOffset = 0;
8720b57cec5SDimitry Andric };
8730b57cec5SDimitry Andric 
8740b57cec5SDimitry Andric /// DiceRef
DiceRef(DataRefImpl DiceP,const ObjectFile * Owner)8750b57cec5SDimitry Andric inline DiceRef::DiceRef(DataRefImpl DiceP, const ObjectFile *Owner)
8760b57cec5SDimitry Andric   : DicePimpl(DiceP) , OwningObject(Owner) {}
8770b57cec5SDimitry Andric 
8780b57cec5SDimitry Andric inline bool DiceRef::operator==(const DiceRef &Other) const {
8790b57cec5SDimitry Andric   return DicePimpl == Other.DicePimpl;
8800b57cec5SDimitry Andric }
8810b57cec5SDimitry Andric 
8820b57cec5SDimitry Andric inline bool DiceRef::operator<(const DiceRef &Other) const {
8830b57cec5SDimitry Andric   return DicePimpl < Other.DicePimpl;
8840b57cec5SDimitry Andric }
8850b57cec5SDimitry Andric 
moveNext()8860b57cec5SDimitry Andric inline void DiceRef::moveNext() {
8870b57cec5SDimitry Andric   const MachO::data_in_code_entry *P =
8880b57cec5SDimitry Andric     reinterpret_cast<const MachO::data_in_code_entry *>(DicePimpl.p);
8890b57cec5SDimitry Andric   DicePimpl.p = reinterpret_cast<uintptr_t>(P + 1);
8900b57cec5SDimitry Andric }
8910b57cec5SDimitry Andric 
8920b57cec5SDimitry Andric // Since a Mach-O data in code reference, a DiceRef, can only be created when
8930b57cec5SDimitry Andric // the OwningObject ObjectFile is a MachOObjectFile a static_cast<> is used for
8940b57cec5SDimitry Andric // the methods that get the values of the fields of the reference.
8950b57cec5SDimitry Andric 
getOffset(uint32_t & Result)8960b57cec5SDimitry Andric inline std::error_code DiceRef::getOffset(uint32_t &Result) const {
8970b57cec5SDimitry Andric   const MachOObjectFile *MachOOF =
8980b57cec5SDimitry Andric     static_cast<const MachOObjectFile *>(OwningObject);
8990b57cec5SDimitry Andric   MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl);
9000b57cec5SDimitry Andric   Result = Dice.offset;
9010b57cec5SDimitry Andric   return std::error_code();
9020b57cec5SDimitry Andric }
9030b57cec5SDimitry Andric 
getLength(uint16_t & Result)9040b57cec5SDimitry Andric inline std::error_code DiceRef::getLength(uint16_t &Result) const {
9050b57cec5SDimitry Andric   const MachOObjectFile *MachOOF =
9060b57cec5SDimitry Andric     static_cast<const MachOObjectFile *>(OwningObject);
9070b57cec5SDimitry Andric   MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl);
9080b57cec5SDimitry Andric   Result = Dice.length;
9090b57cec5SDimitry Andric   return std::error_code();
9100b57cec5SDimitry Andric }
9110b57cec5SDimitry Andric 
getKind(uint16_t & Result)9120b57cec5SDimitry Andric inline std::error_code DiceRef::getKind(uint16_t &Result) const {
9130b57cec5SDimitry Andric   const MachOObjectFile *MachOOF =
9140b57cec5SDimitry Andric     static_cast<const MachOObjectFile *>(OwningObject);
9150b57cec5SDimitry Andric   MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl);
9160b57cec5SDimitry Andric   Result = Dice.kind;
9170b57cec5SDimitry Andric   return std::error_code();
9180b57cec5SDimitry Andric }
9190b57cec5SDimitry Andric 
getRawDataRefImpl()9200b57cec5SDimitry Andric inline DataRefImpl DiceRef::getRawDataRefImpl() const {
9210b57cec5SDimitry Andric   return DicePimpl;
9220b57cec5SDimitry Andric }
9230b57cec5SDimitry Andric 
getObjectFile()9240b57cec5SDimitry Andric inline const ObjectFile *DiceRef::getObjectFile() const {
9250b57cec5SDimitry Andric   return OwningObject;
9260b57cec5SDimitry Andric }
9270b57cec5SDimitry Andric 
9280b57cec5SDimitry Andric } // end namespace object
9290b57cec5SDimitry Andric } // end namespace llvm
9300b57cec5SDimitry Andric 
9310b57cec5SDimitry Andric #endif // LLVM_OBJECT_MACHO_H
932