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