Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:19

0001 //===- MachO.h - MachO object file implementation ---------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file declares the MachOObjectFile class, which implement the ObjectFile
0010 // interface for MachO files.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_OBJECT_MACHO_H
0015 #define LLVM_OBJECT_MACHO_H
0016 
0017 #include "llvm/ADT/ArrayRef.h"
0018 #include "llvm/ADT/SmallString.h"
0019 #include "llvm/ADT/SmallVector.h"
0020 #include "llvm/ADT/StringExtras.h"
0021 #include "llvm/ADT/StringRef.h"
0022 #include "llvm/ADT/iterator_range.h"
0023 #include "llvm/BinaryFormat/MachO.h"
0024 #include "llvm/BinaryFormat/Swift.h"
0025 #include "llvm/Object/Binary.h"
0026 #include "llvm/Object/ObjectFile.h"
0027 #include "llvm/Object/SymbolicFile.h"
0028 #include "llvm/Support/Error.h"
0029 #include "llvm/Support/Format.h"
0030 #include "llvm/Support/MemoryBuffer.h"
0031 #include "llvm/Support/raw_ostream.h"
0032 #include "llvm/TargetParser/SubtargetFeature.h"
0033 #include "llvm/TargetParser/Triple.h"
0034 #include <cstdint>
0035 #include <memory>
0036 #include <string>
0037 #include <system_error>
0038 
0039 namespace llvm {
0040 namespace object {
0041 
0042 /// DiceRef - This is a value type class that represents a single
0043 /// data in code entry in the table in a Mach-O object file.
0044 class DiceRef {
0045   DataRefImpl DicePimpl;
0046   const ObjectFile *OwningObject = nullptr;
0047 
0048 public:
0049   DiceRef() = default;
0050   DiceRef(DataRefImpl DiceP, const ObjectFile *Owner);
0051 
0052   bool operator==(const DiceRef &Other) const;
0053   bool operator<(const DiceRef &Other) const;
0054 
0055   void moveNext();
0056 
0057   std::error_code getOffset(uint32_t &Result) const;
0058   std::error_code getLength(uint16_t &Result) const;
0059   std::error_code getKind(uint16_t &Result) const;
0060 
0061   DataRefImpl getRawDataRefImpl() const;
0062   const ObjectFile *getObjectFile() const;
0063 };
0064 using dice_iterator = content_iterator<DiceRef>;
0065 
0066 /// ExportEntry encapsulates the current-state-of-the-walk used when doing a
0067 /// non-recursive walk of the trie data structure.  This allows you to iterate
0068 /// across all exported symbols using:
0069 ///      Error Err = Error::success();
0070 ///      for (const llvm::object::ExportEntry &AnExport : Obj->exports(&Err)) {
0071 ///      }
0072 ///      if (Err) { report error ...
0073 class ExportEntry {
0074 public:
0075   ExportEntry(Error *Err, const MachOObjectFile *O, ArrayRef<uint8_t> Trie);
0076 
0077   StringRef name() const;
0078   uint64_t flags() const;
0079   uint64_t address() const;
0080   uint64_t other() const;
0081   StringRef otherName() const;
0082   uint32_t nodeOffset() const;
0083 
0084   bool operator==(const ExportEntry &) const;
0085 
0086   void moveNext();
0087 
0088 private:
0089   friend class MachOObjectFile;
0090 
0091   void moveToFirst();
0092   void moveToEnd();
0093   uint64_t readULEB128(const uint8_t *&p, const char **error);
0094   void pushDownUntilBottom();
0095   void pushNode(uint64_t Offset);
0096 
0097   // Represents a node in the mach-o exports trie.
0098   struct NodeState {
0099     NodeState(const uint8_t *Ptr);
0100 
0101     const uint8_t *Start;
0102     const uint8_t *Current;
0103     uint64_t Flags = 0;
0104     uint64_t Address = 0;
0105     uint64_t Other = 0;
0106     const char *ImportName = nullptr;
0107     unsigned ChildCount = 0;
0108     unsigned NextChildIndex = 0;
0109     unsigned ParentStringLength = 0;
0110     bool IsExportNode = false;
0111   };
0112   using NodeList = SmallVector<NodeState, 16>;
0113   using node_iterator = NodeList::const_iterator;
0114 
0115   Error *E;
0116   const MachOObjectFile *O;
0117   ArrayRef<uint8_t> Trie;
0118   SmallString<256> CumulativeString;
0119   NodeList Stack;
0120   bool Done = false;
0121 
0122   iterator_range<node_iterator> nodes() const {
0123     return make_range(Stack.begin(), Stack.end());
0124   }
0125 };
0126 using export_iterator = content_iterator<ExportEntry>;
0127 
0128 // Segment info so SegIndex/SegOffset pairs in a Mach-O Bind or Rebase entry
0129 // can be checked and translated.  Only the SegIndex/SegOffset pairs from
0130 // checked entries are to be used with the segmentName(), sectionName() and
0131 // address() methods below.
0132 class BindRebaseSegInfo {
0133 public:
0134   BindRebaseSegInfo(const MachOObjectFile *Obj);
0135 
0136   // Used to check a Mach-O Bind or Rebase entry for errors when iterating.
0137   const char *checkSegAndOffsets(int32_t SegIndex, uint64_t SegOffset,
0138                                  uint8_t PointerSize, uint64_t Count = 1,
0139                                  uint64_t Skip = 0);
0140   // Used with valid SegIndex/SegOffset values from checked entries.
0141   StringRef segmentName(int32_t SegIndex);
0142   StringRef sectionName(int32_t SegIndex, uint64_t SegOffset);
0143   uint64_t address(uint32_t SegIndex, uint64_t SegOffset);
0144 
0145 private:
0146   struct SectionInfo {
0147     uint64_t Address;
0148     uint64_t Size;
0149     StringRef SectionName;
0150     StringRef SegmentName;
0151     uint64_t OffsetInSegment;
0152     uint64_t SegmentStartAddress;
0153     int32_t SegmentIndex;
0154   };
0155   const SectionInfo &findSection(int32_t SegIndex, uint64_t SegOffset);
0156 
0157   SmallVector<SectionInfo, 32> Sections;
0158   int32_t MaxSegIndex;
0159 };
0160 
0161 /// MachORebaseEntry encapsulates the current state in the decompression of
0162 /// rebasing opcodes. This allows you to iterate through the compressed table of
0163 /// rebasing using:
0164 ///    Error Err = Error::success();
0165 ///    for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable(&Err)) {
0166 ///    }
0167 ///    if (Err) { report error ...
0168 class MachORebaseEntry {
0169 public:
0170   MachORebaseEntry(Error *Err, const MachOObjectFile *O,
0171                    ArrayRef<uint8_t> opcodes, bool is64Bit);
0172 
0173   int32_t segmentIndex() const;
0174   uint64_t segmentOffset() const;
0175   StringRef typeName() const;
0176   StringRef segmentName() const;
0177   StringRef sectionName() const;
0178   uint64_t address() const;
0179 
0180   bool operator==(const MachORebaseEntry &) const;
0181 
0182   void moveNext();
0183 
0184 private:
0185   friend class MachOObjectFile;
0186 
0187   void moveToFirst();
0188   void moveToEnd();
0189   uint64_t readULEB128(const char **error);
0190 
0191   Error *E;
0192   const MachOObjectFile *O;
0193   ArrayRef<uint8_t> Opcodes;
0194   const uint8_t *Ptr;
0195   uint64_t SegmentOffset = 0;
0196   int32_t SegmentIndex = -1;
0197   uint64_t RemainingLoopCount = 0;
0198   uint64_t AdvanceAmount = 0;
0199   uint8_t  RebaseType = 0;
0200   uint8_t  PointerSize;
0201   bool     Done = false;
0202 };
0203 using rebase_iterator = content_iterator<MachORebaseEntry>;
0204 
0205 /// MachOBindEntry encapsulates the current state in the decompression of
0206 /// binding opcodes. This allows you to iterate through the compressed table of
0207 /// bindings using:
0208 ///    Error Err = Error::success();
0209 ///    for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable(&Err)) {
0210 ///    }
0211 ///    if (Err) { report error ...
0212 class MachOBindEntry {
0213 public:
0214   enum class Kind { Regular, Lazy, Weak };
0215 
0216   MachOBindEntry(Error *Err, const MachOObjectFile *O,
0217                  ArrayRef<uint8_t> Opcodes, bool is64Bit, MachOBindEntry::Kind);
0218 
0219   int32_t segmentIndex() const;
0220   uint64_t segmentOffset() const;
0221   StringRef typeName() const;
0222   StringRef symbolName() const;
0223   uint32_t flags() const;
0224   int64_t addend() const;
0225   int ordinal() const;
0226 
0227   StringRef segmentName() const;
0228   StringRef sectionName() const;
0229   uint64_t address() const;
0230 
0231   bool operator==(const MachOBindEntry &) const;
0232 
0233   void moveNext();
0234 
0235 private:
0236   friend class MachOObjectFile;
0237 
0238   void moveToFirst();
0239   void moveToEnd();
0240   uint64_t readULEB128(const char **error);
0241   int64_t readSLEB128(const char **error);
0242 
0243   Error *E;
0244   const MachOObjectFile *O;
0245   ArrayRef<uint8_t> Opcodes;
0246   const uint8_t *Ptr;
0247   uint64_t SegmentOffset = 0;
0248   int32_t  SegmentIndex = -1;
0249   StringRef SymbolName;
0250   bool     LibraryOrdinalSet = false;
0251   int      Ordinal = 0;
0252   uint32_t Flags = 0;
0253   int64_t  Addend = 0;
0254   uint64_t RemainingLoopCount = 0;
0255   uint64_t AdvanceAmount = 0;
0256   uint8_t  BindType = 0;
0257   uint8_t  PointerSize;
0258   Kind     TableKind;
0259   bool     Done = false;
0260 };
0261 using bind_iterator = content_iterator<MachOBindEntry>;
0262 
0263 /// ChainedFixupTarget holds all the information about an external symbol
0264 /// necessary to bind this binary to that symbol. These values are referenced
0265 /// indirectly by chained fixup binds. This structure captures values from all
0266 /// import and symbol formats.
0267 ///
0268 /// Be aware there are two notions of weak here:
0269 ///   WeakImport == true
0270 ///     The associated bind may be set to 0 if this symbol is missing from its
0271 ///     parent library. This is called a "weak import."
0272 ///   LibOrdinal == BIND_SPECIAL_DYLIB_WEAK_LOOKUP
0273 ///     This symbol may be coalesced with other libraries vending the same
0274 ///     symbol. E.g., C++'s "operator new". This is called a "weak bind."
0275 struct ChainedFixupTarget {
0276 public:
0277   ChainedFixupTarget(int LibOrdinal, uint32_t NameOffset, StringRef Symbol,
0278                      uint64_t Addend, bool WeakImport)
0279       : LibOrdinal(LibOrdinal), NameOffset(NameOffset), SymbolName(Symbol),
0280         Addend(Addend), WeakImport(WeakImport) {}
0281 
0282   int libOrdinal() { return LibOrdinal; }
0283   uint32_t nameOffset() { return NameOffset; }
0284   StringRef symbolName() { return SymbolName; }
0285   uint64_t addend() { return Addend; }
0286   bool weakImport() { return WeakImport; }
0287   bool weakBind() {
0288     return LibOrdinal == MachO::BIND_SPECIAL_DYLIB_WEAK_LOOKUP;
0289   }
0290 
0291 private:
0292   int LibOrdinal;
0293   uint32_t NameOffset;
0294   StringRef SymbolName;
0295   uint64_t Addend;
0296   bool WeakImport;
0297 };
0298 
0299 struct ChainedFixupsSegment {
0300   ChainedFixupsSegment(uint8_t SegIdx, uint32_t Offset,
0301                        const MachO::dyld_chained_starts_in_segment &Header,
0302                        std::vector<uint16_t> &&PageStarts)
0303       : SegIdx(SegIdx), Offset(Offset), Header(Header),
0304         PageStarts(PageStarts){};
0305 
0306   uint32_t SegIdx;
0307   uint32_t Offset; // dyld_chained_starts_in_image::seg_info_offset[SegIdx]
0308   MachO::dyld_chained_starts_in_segment Header;
0309   std::vector<uint16_t> PageStarts; // page_start[] entries, host endianness
0310 };
0311 
0312 /// MachOAbstractFixupEntry is an abstract class representing a fixup in a
0313 /// MH_DYLDLINK file. Fixups generally represent rebases and binds. Binds also
0314 /// subdivide into additional subtypes (weak, lazy, reexport).
0315 ///
0316 /// The two concrete subclasses of MachOAbstractFixupEntry are:
0317 ///
0318 ///   MachORebaseBindEntry   - for dyld opcode-based tables, including threaded-
0319 ///                            rebase, where rebases are mixed in with other
0320 ///                            bind opcodes.
0321 ///   MachOChainedFixupEntry - for pointer chains embedded in data pages.
0322 class MachOAbstractFixupEntry {
0323 public:
0324   MachOAbstractFixupEntry(Error *Err, const MachOObjectFile *O);
0325 
0326   int32_t segmentIndex() const;
0327   uint64_t segmentOffset() const;
0328   uint64_t segmentAddress() const;
0329   StringRef segmentName() const;
0330   StringRef sectionName() const;
0331   StringRef typeName() const;
0332   StringRef symbolName() const;
0333   uint32_t flags() const;
0334   int64_t addend() const;
0335   int ordinal() const;
0336 
0337   /// \return the location of this fixup as a VM Address. For the VM
0338   /// Address this fixup is pointing to, use pointerValue().
0339   uint64_t address() const;
0340 
0341   /// \return the VM Address pointed to by this fixup. Use
0342   /// pointerValue() to compare against other VM Addresses, such as
0343   /// section addresses or segment vmaddrs.
0344   uint64_t pointerValue() const { return PointerValue; }
0345 
0346   /// \return the raw "on-disk" representation of the fixup. For
0347   /// Threaded rebases and Chained pointers these values are generally
0348   /// encoded into various different pointer formats. This value is
0349   /// exposed in API for tools that want to display and annotate the
0350   /// raw bits.
0351   uint64_t rawValue() const { return RawValue; }
0352 
0353   void moveNext();
0354 
0355 protected:
0356   Error *E;
0357   const MachOObjectFile *O;
0358   uint64_t SegmentOffset = 0;
0359   int32_t SegmentIndex = -1;
0360   StringRef SymbolName;
0361   int32_t Ordinal = 0;
0362   uint32_t Flags = 0;
0363   int64_t Addend = 0;
0364   uint64_t PointerValue = 0;
0365   uint64_t RawValue = 0;
0366   bool Done = false;
0367 
0368   void moveToFirst();
0369   void moveToEnd();
0370 
0371   /// \return the vm address of the start of __TEXT segment.
0372   uint64_t textAddress() const { return TextAddress; }
0373 
0374 private:
0375   uint64_t TextAddress;
0376 };
0377 
0378 class MachOChainedFixupEntry : public MachOAbstractFixupEntry {
0379 public:
0380   enum class FixupKind { Bind, Rebase };
0381 
0382   MachOChainedFixupEntry(Error *Err, const MachOObjectFile *O, bool Parse);
0383 
0384   bool operator==(const MachOChainedFixupEntry &) const;
0385 
0386   bool isBind() const { return Kind == FixupKind::Bind; }
0387   bool isRebase() const { return Kind == FixupKind::Rebase; }
0388 
0389   void moveNext();
0390   void moveToFirst();
0391   void moveToEnd();
0392 
0393 private:
0394   void findNextPageWithFixups();
0395 
0396   std::vector<ChainedFixupTarget> FixupTargets;
0397   std::vector<ChainedFixupsSegment> Segments;
0398   ArrayRef<uint8_t> SegmentData;
0399   FixupKind Kind;
0400   uint32_t InfoSegIndex = 0; // Index into Segments
0401   uint32_t PageIndex = 0;    // Index into Segments[InfoSegIdx].PageStarts
0402   uint32_t PageOffset = 0;   // Page offset of the current fixup
0403 };
0404 using fixup_iterator = content_iterator<MachOChainedFixupEntry>;
0405 
0406 class MachOObjectFile : public ObjectFile {
0407 public:
0408   struct LoadCommandInfo {
0409     const char *Ptr;      // Where in memory the load command is.
0410     MachO::load_command C; // The command itself.
0411   };
0412   using LoadCommandList = SmallVector<LoadCommandInfo, 4>;
0413   using load_command_iterator = LoadCommandList::const_iterator;
0414 
0415   static Expected<std::unique_ptr<MachOObjectFile>>
0416   create(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits,
0417          uint32_t UniversalCputype = 0, uint32_t UniversalIndex = 0,
0418          size_t MachOFilesetEntryOffset = 0);
0419 
0420   static bool isMachOPairedReloc(uint64_t RelocType, uint64_t Arch);
0421 
0422   void moveSymbolNext(DataRefImpl &Symb) const override;
0423 
0424   uint64_t getNValue(DataRefImpl Sym) const;
0425   Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
0426 
0427   // MachO specific.
0428   Error checkSymbolTable() const;
0429 
0430   std::error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const;
0431   unsigned getSectionType(SectionRef Sec) const;
0432 
0433   Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
0434   uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
0435   uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
0436   Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
0437   Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
0438   Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
0439   unsigned getSymbolSectionID(SymbolRef Symb) const;
0440   unsigned getSectionID(SectionRef Sec) const;
0441 
0442   void moveSectionNext(DataRefImpl &Sec) const override;
0443   Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
0444   uint64_t getSectionAddress(DataRefImpl Sec) const override;
0445   uint64_t getSectionIndex(DataRefImpl Sec) const override;
0446   uint64_t getSectionSize(DataRefImpl Sec) const override;
0447   ArrayRef<uint8_t> getSectionContents(uint32_t Offset, uint64_t Size) const;
0448   Expected<ArrayRef<uint8_t>>
0449   getSectionContents(DataRefImpl Sec) const override;
0450   uint64_t getSectionAlignment(DataRefImpl Sec) const override;
0451   Expected<SectionRef> getSection(unsigned SectionIndex) const;
0452   Expected<SectionRef> getSection(StringRef SectionName) const;
0453   bool isSectionCompressed(DataRefImpl Sec) const override;
0454   bool isSectionText(DataRefImpl Sec) const override;
0455   bool isSectionData(DataRefImpl Sec) const override;
0456   bool isSectionBSS(DataRefImpl Sec) const override;
0457   bool isSectionVirtual(DataRefImpl Sec) const override;
0458   bool isSectionBitcode(DataRefImpl Sec) const override;
0459   bool isDebugSection(DataRefImpl Sec) const override;
0460 
0461   /// Return the raw contents of an entire segment.
0462   ArrayRef<uint8_t> getSegmentContents(StringRef SegmentName) const;
0463   ArrayRef<uint8_t> getSegmentContents(size_t SegmentIndex) const;
0464 
0465   /// When dsymutil generates the companion file, it strips all unnecessary
0466   /// sections (e.g. everything in the _TEXT segment) by omitting their body
0467   /// and setting the offset in their corresponding load command to zero.
0468   ///
0469   /// While the load command itself is valid, reading the section corresponds
0470   /// to reading the number of bytes specified in the load command, starting
0471   /// from offset 0 (i.e. the Mach-O header at the beginning of the file).
0472   bool isSectionStripped(DataRefImpl Sec) const override;
0473 
0474   relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
0475   relocation_iterator section_rel_end(DataRefImpl Sec) const override;
0476 
0477   relocation_iterator extrel_begin() const;
0478   relocation_iterator extrel_end() const;
0479   iterator_range<relocation_iterator> external_relocations() const {
0480     return make_range(extrel_begin(), extrel_end());
0481   }
0482 
0483   relocation_iterator locrel_begin() const;
0484   relocation_iterator locrel_end() const;
0485 
0486   void moveRelocationNext(DataRefImpl &Rel) const override;
0487   uint64_t getRelocationOffset(DataRefImpl Rel) const override;
0488   symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
0489   section_iterator getRelocationSection(DataRefImpl Rel) const;
0490   uint64_t getRelocationType(DataRefImpl Rel) const override;
0491   void getRelocationTypeName(DataRefImpl Rel,
0492                              SmallVectorImpl<char> &Result) const override;
0493   uint8_t getRelocationLength(DataRefImpl Rel) const;
0494 
0495   // MachO specific.
0496   std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &) const;
0497   uint32_t getLibraryCount() const;
0498 
0499   section_iterator getRelocationRelocatedSection(relocation_iterator Rel) const;
0500 
0501   // TODO: Would be useful to have an iterator based version
0502   // of the load command interface too.
0503 
0504   basic_symbol_iterator symbol_begin() const override;
0505   basic_symbol_iterator symbol_end() const override;
0506 
0507   bool is64Bit() const override;
0508 
0509   // MachO specific.
0510   symbol_iterator getSymbolByIndex(unsigned Index) const;
0511   uint64_t getSymbolIndex(DataRefImpl Symb) const;
0512 
0513   section_iterator section_begin() const override;
0514   section_iterator section_end() const override;
0515 
0516   uint8_t getBytesInAddress() const override;
0517 
0518   StringRef getFileFormatName() const override;
0519   Triple::ArchType getArch() const override;
0520   Expected<SubtargetFeatures> getFeatures() const override {
0521     return SubtargetFeatures();
0522   }
0523   Triple getArchTriple(const char **McpuDefault = nullptr) const;
0524 
0525   relocation_iterator section_rel_begin(unsigned Index) const;
0526   relocation_iterator section_rel_end(unsigned Index) const;
0527 
0528   dice_iterator begin_dices() const;
0529   dice_iterator end_dices() const;
0530 
0531   load_command_iterator begin_load_commands() const;
0532   load_command_iterator end_load_commands() const;
0533   iterator_range<load_command_iterator> load_commands() const;
0534 
0535   /// For use iterating over all exported symbols.
0536   iterator_range<export_iterator> exports(Error &Err) const;
0537 
0538   /// For use examining a trie not in a MachOObjectFile.
0539   static iterator_range<export_iterator> exports(Error &Err,
0540                                                  ArrayRef<uint8_t> Trie,
0541                                                  const MachOObjectFile *O =
0542                                                                       nullptr);
0543 
0544   /// For use iterating over all rebase table entries.
0545   iterator_range<rebase_iterator> rebaseTable(Error &Err);
0546 
0547   /// For use examining rebase opcodes in a MachOObjectFile.
0548   static iterator_range<rebase_iterator> rebaseTable(Error &Err,
0549                                                      MachOObjectFile *O,
0550                                                      ArrayRef<uint8_t> Opcodes,
0551                                                      bool is64);
0552 
0553   /// For use iterating over all bind table entries.
0554   iterator_range<bind_iterator> bindTable(Error &Err);
0555 
0556   /// For iterating over all chained fixups.
0557   iterator_range<fixup_iterator> fixupTable(Error &Err);
0558 
0559   /// For use iterating over all lazy bind table entries.
0560   iterator_range<bind_iterator> lazyBindTable(Error &Err);
0561 
0562   /// For use iterating over all weak bind table entries.
0563   iterator_range<bind_iterator> weakBindTable(Error &Err);
0564 
0565   /// For use examining bind opcodes in a MachOObjectFile.
0566   static iterator_range<bind_iterator> bindTable(Error &Err,
0567                                                  MachOObjectFile *O,
0568                                                  ArrayRef<uint8_t> Opcodes,
0569                                                  bool is64,
0570                                                  MachOBindEntry::Kind);
0571 
0572   // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
0573   // that fully contains a pointer at that location. Multiple fixups in a bind
0574   // (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can
0575   // be tested via the Count and Skip parameters.
0576   //
0577   // This is used by MachOBindEntry::moveNext() to validate a MachOBindEntry.
0578   const char *BindEntryCheckSegAndOffsets(int32_t SegIndex, uint64_t SegOffset,
0579                                           uint8_t PointerSize,
0580                                           uint64_t Count = 1,
0581                                           uint64_t Skip = 0) const {
0582     return BindRebaseSectionTable->checkSegAndOffsets(SegIndex, SegOffset,
0583                                                      PointerSize, Count, Skip);
0584   }
0585 
0586   // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
0587   // that fully contains a pointer at that location. Multiple fixups in a rebase
0588   // (such as with the REBASE_OPCODE_DO_*_TIMES* opcodes) can be tested via the
0589   // Count and Skip parameters.
0590   //
0591   // This is used by MachORebaseEntry::moveNext() to validate a MachORebaseEntry
0592   const char *RebaseEntryCheckSegAndOffsets(int32_t SegIndex,
0593                                             uint64_t SegOffset,
0594                                             uint8_t PointerSize,
0595                                             uint64_t Count = 1,
0596                                             uint64_t Skip = 0) const {
0597     return BindRebaseSectionTable->checkSegAndOffsets(SegIndex, SegOffset,
0598                                                       PointerSize, Count, Skip);
0599   }
0600 
0601   /// For use with the SegIndex of a checked Mach-O Bind or Rebase entry to
0602   /// get the segment name.
0603   StringRef BindRebaseSegmentName(int32_t SegIndex) const {
0604     return BindRebaseSectionTable->segmentName(SegIndex);
0605   }
0606 
0607   /// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or
0608   /// Rebase entry to get the section name.
0609   StringRef BindRebaseSectionName(uint32_t SegIndex, uint64_t SegOffset) const {
0610     return BindRebaseSectionTable->sectionName(SegIndex, SegOffset);
0611   }
0612 
0613   /// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or
0614   /// Rebase entry to get the address.
0615   uint64_t BindRebaseAddress(uint32_t SegIndex, uint64_t SegOffset) const {
0616     return BindRebaseSectionTable->address(SegIndex, SegOffset);
0617   }
0618 
0619   // In a MachO file, sections have a segment name. This is used in the .o
0620   // files. They have a single segment, but this field specifies which segment
0621   // a section should be put in the final object.
0622   StringRef getSectionFinalSegmentName(DataRefImpl Sec) const;
0623 
0624   // Names are stored as 16 bytes. These returns the raw 16 bytes without
0625   // interpreting them as a C string.
0626   ArrayRef<char> getSectionRawName(DataRefImpl Sec) const;
0627   ArrayRef<char> getSectionRawFinalSegmentName(DataRefImpl Sec) const;
0628 
0629   // MachO specific Info about relocations.
0630   bool isRelocationScattered(const MachO::any_relocation_info &RE) const;
0631   unsigned getPlainRelocationSymbolNum(
0632                                     const MachO::any_relocation_info &RE) const;
0633   bool getPlainRelocationExternal(const MachO::any_relocation_info &RE) const;
0634   bool getScatteredRelocationScattered(
0635                                     const MachO::any_relocation_info &RE) const;
0636   uint32_t getScatteredRelocationValue(
0637                                     const MachO::any_relocation_info &RE) const;
0638   uint32_t getScatteredRelocationType(
0639                                     const MachO::any_relocation_info &RE) const;
0640   unsigned getAnyRelocationAddress(const MachO::any_relocation_info &RE) const;
0641   unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const;
0642   unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const;
0643   unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const;
0644   SectionRef getAnyRelocationSection(const MachO::any_relocation_info &RE) const;
0645 
0646   // MachO specific structures.
0647   MachO::section getSection(DataRefImpl DRI) const;
0648   MachO::section_64 getSection64(DataRefImpl DRI) const;
0649   MachO::section getSection(const LoadCommandInfo &L, unsigned Index) const;
0650   MachO::section_64 getSection64(const LoadCommandInfo &L,unsigned Index) const;
0651   MachO::nlist getSymbolTableEntry(DataRefImpl DRI) const;
0652   MachO::nlist_64 getSymbol64TableEntry(DataRefImpl DRI) const;
0653 
0654   MachO::linkedit_data_command
0655   getLinkeditDataLoadCommand(const LoadCommandInfo &L) const;
0656   MachO::segment_command
0657   getSegmentLoadCommand(const LoadCommandInfo &L) const;
0658   MachO::segment_command_64
0659   getSegment64LoadCommand(const LoadCommandInfo &L) const;
0660   MachO::linker_option_command
0661   getLinkerOptionLoadCommand(const LoadCommandInfo &L) const;
0662   MachO::version_min_command
0663   getVersionMinLoadCommand(const LoadCommandInfo &L) const;
0664   MachO::note_command
0665   getNoteLoadCommand(const LoadCommandInfo &L) const;
0666   MachO::build_version_command
0667   getBuildVersionLoadCommand(const LoadCommandInfo &L) const;
0668   MachO::build_tool_version
0669   getBuildToolVersion(unsigned index) const;
0670   MachO::dylib_command
0671   getDylibIDLoadCommand(const LoadCommandInfo &L) const;
0672   MachO::dyld_info_command
0673   getDyldInfoLoadCommand(const LoadCommandInfo &L) const;
0674   MachO::dylinker_command
0675   getDylinkerCommand(const LoadCommandInfo &L) const;
0676   MachO::uuid_command
0677   getUuidCommand(const LoadCommandInfo &L) const;
0678   MachO::rpath_command
0679   getRpathCommand(const LoadCommandInfo &L) const;
0680   MachO::source_version_command
0681   getSourceVersionCommand(const LoadCommandInfo &L) const;
0682   MachO::entry_point_command
0683   getEntryPointCommand(const LoadCommandInfo &L) const;
0684   MachO::encryption_info_command
0685   getEncryptionInfoCommand(const LoadCommandInfo &L) const;
0686   MachO::encryption_info_command_64
0687   getEncryptionInfoCommand64(const LoadCommandInfo &L) const;
0688   MachO::sub_framework_command
0689   getSubFrameworkCommand(const LoadCommandInfo &L) const;
0690   MachO::sub_umbrella_command
0691   getSubUmbrellaCommand(const LoadCommandInfo &L) const;
0692   MachO::sub_library_command
0693   getSubLibraryCommand(const LoadCommandInfo &L) const;
0694   MachO::sub_client_command
0695   getSubClientCommand(const LoadCommandInfo &L) const;
0696   MachO::routines_command
0697   getRoutinesCommand(const LoadCommandInfo &L) const;
0698   MachO::routines_command_64
0699   getRoutinesCommand64(const LoadCommandInfo &L) const;
0700   MachO::thread_command
0701   getThreadCommand(const LoadCommandInfo &L) const;
0702   MachO::fileset_entry_command
0703   getFilesetEntryLoadCommand(const LoadCommandInfo &L) const;
0704 
0705   MachO::any_relocation_info getRelocation(DataRefImpl Rel) const;
0706   MachO::data_in_code_entry getDice(DataRefImpl Rel) const;
0707   const MachO::mach_header &getHeader() const;
0708   const MachO::mach_header_64 &getHeader64() const;
0709   uint32_t
0710   getIndirectSymbolTableEntry(const MachO::dysymtab_command &DLC,
0711                               unsigned Index) const;
0712   MachO::data_in_code_entry getDataInCodeTableEntry(uint32_t DataOffset,
0713                                                     unsigned Index) const;
0714   MachO::symtab_command getSymtabLoadCommand() const;
0715   MachO::dysymtab_command getDysymtabLoadCommand() const;
0716   MachO::linkedit_data_command getDataInCodeLoadCommand() const;
0717   MachO::linkedit_data_command getLinkOptHintsLoadCommand() const;
0718   ArrayRef<uint8_t> getDyldInfoRebaseOpcodes() const;
0719   ArrayRef<uint8_t> getDyldInfoBindOpcodes() const;
0720   ArrayRef<uint8_t> getDyldInfoWeakBindOpcodes() const;
0721   ArrayRef<uint8_t> getDyldInfoLazyBindOpcodes() const;
0722   ArrayRef<uint8_t> getDyldInfoExportsTrie() const;
0723 
0724   /// If the optional is std::nullopt, no header was found, but the object was
0725   /// well-formed.
0726   Expected<std::optional<MachO::dyld_chained_fixups_header>>
0727   getChainedFixupsHeader() const;
0728   Expected<std::vector<ChainedFixupTarget>> getDyldChainedFixupTargets() const;
0729 
0730   // Note: This is a limited, temporary API, which will be removed when Apple
0731   // upstreams their implementation. Please do not rely on this.
0732   Expected<std::optional<MachO::linkedit_data_command>>
0733   getChainedFixupsLoadCommand() const;
0734   // Returns the number of sections listed in dyld_chained_starts_in_image, and
0735   // a ChainedFixupsSegment for each segment that has fixups.
0736   Expected<std::pair<size_t, std::vector<ChainedFixupsSegment>>>
0737   getChainedFixupsSegments() const;
0738   ArrayRef<uint8_t> getDyldExportsTrie() const;
0739 
0740   SmallVector<uint64_t> getFunctionStarts() const;
0741   ArrayRef<uint8_t> getUuid() const;
0742 
0743   StringRef getStringTableData() const;
0744 
0745   void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const;
0746 
0747   static StringRef guessLibraryShortName(StringRef Name, bool &isFramework,
0748                                          StringRef &Suffix);
0749 
0750   static Triple::ArchType getArch(uint32_t CPUType, uint32_t CPUSubType);
0751   static Triple getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
0752                               const char **McpuDefault = nullptr,
0753                               const char **ArchFlag = nullptr);
0754   static bool isValidArch(StringRef ArchFlag);
0755   static ArrayRef<StringRef> getValidArchs();
0756   static Triple getHostArch();
0757 
0758   bool isRelocatableObject() const override;
0759 
0760   StringRef mapDebugSectionName(StringRef Name) const override;
0761 
0762   llvm::binaryformat::Swift5ReflectionSectionKind
0763   mapReflectionSectionNameToEnumValue(StringRef SectionName) const override;
0764 
0765   bool hasPageZeroSegment() const { return HasPageZeroSegment; }
0766 
0767   size_t getMachOFilesetEntryOffset() const { return MachOFilesetEntryOffset; }
0768 
0769   static bool classof(const Binary *v) {
0770     return v->isMachO();
0771   }
0772 
0773   static uint32_t
0774   getVersionMinMajor(MachO::version_min_command &C, bool SDK) {
0775     uint32_t VersionOrSDK = (SDK) ? C.sdk : C.version;
0776     return (VersionOrSDK >> 16) & 0xffff;
0777   }
0778 
0779   static uint32_t
0780   getVersionMinMinor(MachO::version_min_command &C, bool SDK) {
0781     uint32_t VersionOrSDK = (SDK) ? C.sdk : C.version;
0782     return (VersionOrSDK >> 8) & 0xff;
0783   }
0784 
0785   static uint32_t
0786   getVersionMinUpdate(MachO::version_min_command &C, bool SDK) {
0787     uint32_t VersionOrSDK = (SDK) ? C.sdk : C.version;
0788     return VersionOrSDK & 0xff;
0789   }
0790 
0791   static std::string getBuildPlatform(uint32_t platform) {
0792     switch (platform) {
0793 #define PLATFORM(platform, id, name, build_name, target, tapi_target,          \
0794                  marketing)                                                    \
0795   case MachO::PLATFORM_##platform:                                             \
0796     return #name;
0797 #include "llvm/BinaryFormat/MachO.def"
0798     default:
0799       std::string ret;
0800       raw_string_ostream ss(ret);
0801       ss << format_hex(platform, 8, true);
0802       return ret;
0803     }
0804   }
0805 
0806   static std::string getBuildTool(uint32_t tools) {
0807     switch (tools) {
0808     case MachO::TOOL_CLANG: return "clang";
0809     case MachO::TOOL_SWIFT: return "swift";
0810     case MachO::TOOL_LD: return "ld";
0811     case MachO::TOOL_LLD:
0812       return "lld";
0813     default:
0814       std::string ret;
0815       raw_string_ostream ss(ret);
0816       ss << format_hex(tools, 8, true);
0817       return ret;
0818     }
0819   }
0820 
0821   static std::string getVersionString(uint32_t version) {
0822     uint32_t major = (version >> 16) & 0xffff;
0823     uint32_t minor = (version >> 8) & 0xff;
0824     uint32_t update = version & 0xff;
0825 
0826     SmallString<32> Version;
0827     Version = utostr(major) + "." + utostr(minor);
0828     if (update != 0)
0829       Version += "." + utostr(update);
0830     return std::string(std::string(Version));
0831   }
0832 
0833   /// If the input path is a .dSYM bundle (as created by the dsymutil tool),
0834   /// return the paths to the object files found in the bundle, otherwise return
0835   /// an empty vector. If the path appears to be a .dSYM bundle but no objects
0836   /// were found or there was a filesystem error, then return an error.
0837   static Expected<std::vector<std::string>>
0838   findDsymObjectMembers(StringRef Path);
0839 
0840 private:
0841   MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits,
0842                   Error &Err, uint32_t UniversalCputype = 0,
0843                   uint32_t UniversalIndex = 0,
0844                   size_t MachOFilesetEntryOffset = 0);
0845 
0846   uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
0847 
0848   union {
0849     MachO::mach_header_64 Header64;
0850     MachO::mach_header Header;
0851   };
0852   using SectionList = SmallVector<const char*, 1>;
0853   SectionList Sections;
0854   using LibraryList = SmallVector<const char*, 1>;
0855   LibraryList Libraries;
0856   LoadCommandList LoadCommands;
0857   using LibraryShortName = SmallVector<StringRef, 1>;
0858   using BuildToolList = SmallVector<const char*, 1>;
0859   BuildToolList BuildTools;
0860   mutable LibraryShortName LibrariesShortNames;
0861   std::unique_ptr<BindRebaseSegInfo> BindRebaseSectionTable;
0862   const char *SymtabLoadCmd = nullptr;
0863   const char *DysymtabLoadCmd = nullptr;
0864   const char *DataInCodeLoadCmd = nullptr;
0865   const char *LinkOptHintsLoadCmd = nullptr;
0866   const char *DyldInfoLoadCmd = nullptr;
0867   const char *FuncStartsLoadCmd = nullptr;
0868   const char *DyldChainedFixupsLoadCmd = nullptr;
0869   const char *DyldExportsTrieLoadCmd = nullptr;
0870   const char *UuidLoadCmd = nullptr;
0871   bool HasPageZeroSegment = false;
0872   size_t MachOFilesetEntryOffset = 0;
0873 };
0874 
0875 /// DiceRef
0876 inline DiceRef::DiceRef(DataRefImpl DiceP, const ObjectFile *Owner)
0877   : DicePimpl(DiceP) , OwningObject(Owner) {}
0878 
0879 inline bool DiceRef::operator==(const DiceRef &Other) const {
0880   return DicePimpl == Other.DicePimpl;
0881 }
0882 
0883 inline bool DiceRef::operator<(const DiceRef &Other) const {
0884   return DicePimpl < Other.DicePimpl;
0885 }
0886 
0887 inline void DiceRef::moveNext() {
0888   const MachO::data_in_code_entry *P =
0889     reinterpret_cast<const MachO::data_in_code_entry *>(DicePimpl.p);
0890   DicePimpl.p = reinterpret_cast<uintptr_t>(P + 1);
0891 }
0892 
0893 // Since a Mach-O data in code reference, a DiceRef, can only be created when
0894 // the OwningObject ObjectFile is a MachOObjectFile a static_cast<> is used for
0895 // the methods that get the values of the fields of the reference.
0896 
0897 inline std::error_code DiceRef::getOffset(uint32_t &Result) const {
0898   const MachOObjectFile *MachOOF =
0899     static_cast<const MachOObjectFile *>(OwningObject);
0900   MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl);
0901   Result = Dice.offset;
0902   return std::error_code();
0903 }
0904 
0905 inline std::error_code DiceRef::getLength(uint16_t &Result) const {
0906   const MachOObjectFile *MachOOF =
0907     static_cast<const MachOObjectFile *>(OwningObject);
0908   MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl);
0909   Result = Dice.length;
0910   return std::error_code();
0911 }
0912 
0913 inline std::error_code DiceRef::getKind(uint16_t &Result) const {
0914   const MachOObjectFile *MachOOF =
0915     static_cast<const MachOObjectFile *>(OwningObject);
0916   MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl);
0917   Result = Dice.kind;
0918   return std::error_code();
0919 }
0920 
0921 inline DataRefImpl DiceRef::getRawDataRefImpl() const {
0922   return DicePimpl;
0923 }
0924 
0925 inline const ObjectFile *DiceRef::getObjectFile() const {
0926   return OwningObject;
0927 }
0928 
0929 } // end namespace object
0930 } // end namespace llvm
0931 
0932 #endif // LLVM_OBJECT_MACHO_H