#ifndef MachOAnalyzer_h
#define MachOAnalyzer_h
#define BIND_SPECIAL_DYLIB_WEAK_DEF_COALESCE (-3)
#include "MachOLoaded.h"
#include "ClosureFileSystem.h"
namespace dyld3 {
struct VIS_HIDDEN MachOAnalyzer : public MachOLoaded
{
static closure::LoadedFileInfo load(Diagnostics& diag, const closure::FileSystem& fileSystem, const char* logicalPath, const char* reqArchName, Platform reqPlatform);
static const MachOAnalyzer* validMainExecutable(Diagnostics& diag, const mach_header* mh, const char* path, uint64_t sliceLength, const char* reqArchName, Platform reqPlatform);
bool validMachOForArchAndPlatform(Diagnostics& diag, size_t mappedSize, const char* path, const char* reqArchName, Platform reqPlatform) const;
uint64_t mappedSize() const;
bool hasObjC() const;
bool hasPlusLoadMethod(Diagnostics& diag) const;
uint64_t preferredLoadAddress() const;
void forEachLocalSymbol(Diagnostics& diag, void (^callback)(const char* symbolName, uint64_t n_value, uint8_t n_type, uint8_t n_sect, uint16_t n_desc, bool& stop)) const;
void forEachRPath(void (^callback)(const char* rPath, bool& stop)) const;
bool isEncrypted() const;
bool getCDHash(uint8_t cdHash[20]) const;
bool hasCodeSignature(uint32_t& fileOffset, uint32_t& size) const;
bool usesLibraryValidation() const;
bool isRestricted() const;
bool getEntry(uint32_t& offset, bool& usesCRT) const;
bool isSlideable() const;
bool hasInitializer(Diagnostics& diag, bool contentRebased, const void* dyldCache=nullptr) const;
void forEachInitializer(Diagnostics& diag, bool contentRebased, void (^callback)(uint32_t offset), const void* dyldCache=nullptr) const;
void forEachDOFSection(Diagnostics& diag, void (^callback)(uint32_t offset)) const;
uint32_t segmentCount() const;
void forEachExportedSymbol(Diagnostics diag, void (^callback)(const char* symbolName, uint64_t imageOffset, bool isReExport, bool& stop)) const;
void forEachRebase(Diagnostics& diag, void (^callback)(uint32_t dataSegIndex, uint64_t dataSegOffset, uint8_t type, bool& stop)) const;
void forEachWeakDef(Diagnostics& diag, void (^callback)(bool strongDef, uint32_t dataSegIndex, uint64_t dataSegOffset,
uint64_t addend, const char* symbolName, bool& stop)) const;
void forEachIndirectPointer(Diagnostics& diag, void (^handler)(uint64_t pointerAddress, bool bind, int bindLibOrdinal,
const char* bindSymbolName, bool bindWeakImport, bool bindLazy, bool selfModifyingStub, bool& stop)) const;
void forEachInterposingSection(Diagnostics& diag, void (^handler)(uint64_t vmOffset, uint64_t vmSize, bool& stop)) const;
const void* content(uint64_t vmOffset);
void forEachLocalReloc(void (^handler)(uint64_t runtimeOffset, bool& stop)) const;
void forEachExternalReloc(void (^handler)(uint64_t runtimeOffset, int libOrdinal, const char* symbolName, bool& stop)) const;
const void* getRebaseOpcodes(uint32_t& size) const;
const void* getBindOpcodes(uint32_t& size) const;
const void* getLazyBindOpcodes(uint32_t& size) const;
uint64_t segAndOffsetToRuntimeOffset(uint8_t segIndex, uint64_t segOffset) const;
bool hasLazyPointers(uint32_t& runtimeOffset, uint32_t& size) const;
void forEachRebase(Diagnostics& diag, bool ignoreLazyPointer, void (^callback)(uint64_t runtimeOffset, bool& stop)) const;
void forEachTextRebase(Diagnostics& diag, void (^callback)(uint64_t runtimeOffset, bool& stop)) const;
void forEachBind(Diagnostics& diag, void (^callback)(uint64_t runtimeOffset, int libOrdinal, const char* symbolName,
bool weakImport, uint64_t addend, bool& stop),
void (^strongHandler)(const char* symbolName)) const;
void forEachChainedFixupTarget(Diagnostics& diag, void (^callback)(int libOrdinal, const char* symbolName, uint64_t addend, bool weakImport, bool& stop)) const;
void forEachChainedFixupStart(Diagnostics& diag, void (^callback)(uint64_t runtimeOffset, bool& stop)) const;
bool canHavePrecomputedDlopenClosure(const char* path, void (^failureReason)(const char*)) const;
bool canBePlacedInDyldCache(const char* path, void (^failureReason)(const char*)) const;
#if DEBUG
void validateDyldCacheDylib(Diagnostics& diag, const char* path) const;
#endif
const MachOAnalyzer* remapIfZeroFill(Diagnostics& diag, const closure::FileSystem& fileSystem, closure::LoadedFileInfo& info) const;
using MachOLoaded::SegmentInfo;
using MachOLoaded::SectionInfo;
using MachOLoaded::forEachSegment;
using MachOLoaded::forEachSection;
using MachOLoaded::forEachDependentDylib;
using MachOLoaded::getDylibInstallName;
using MachOLoaded::FoundSymbol;
using MachOLoaded::findExportedSymbol;
private:
struct SegmentStuff
{
uint64_t fileOffset;
uint64_t fileSize;
uint64_t writable : 1,
executable : 1,
textRelocsAllowed : 1, segSize : 61;
};
enum class Malformed { linkeditOrder, linkeditAlignment, dyldInfoAndlocalRelocs };
bool enforceFormat(Malformed) const;
const uint8_t* getContentForVMAddr(const LayoutInfo& info, uint64_t vmAddr) const;
bool validLoadCommands(Diagnostics& diag, const char* path, size_t fileLen) const;
bool validEmbeddedPaths(Diagnostics& diag, const char* path) const;
bool validSegments(Diagnostics& diag, const char* path, size_t fileLen) const;
bool validLinkedit(Diagnostics& diag, const char* path) const;
bool validLinkeditLayout(Diagnostics& diag, const char* path) const;
bool validRebaseInfo(Diagnostics& diag, const char* path) const;
bool validBindInfo(Diagnostics& diag, const char* path) const;
bool validMain(Diagnostics& diag, const char* path) const;
bool validChainedFixupsInfo(Diagnostics& diag, const char* path) const;
bool invalidRebaseState(Diagnostics& diag, const char* opcodeName, const char* path, const LinkEditInfo& leInfo, const SegmentInfo segments[],
bool segIndexSet, uint32_t pointerSize, uint8_t segmentIndex, uint64_t segmentOffset, uint8_t type) const;
bool invalidBindState(Diagnostics& diag, const char* opcodeName, const char* path, const LinkEditInfo& leInfo, const SegmentInfo segments[],
bool segIndexSet, bool libraryOrdinalSet, uint32_t dylibCount, int libOrdinal, uint32_t pointerSize,
uint8_t segmentIndex, uint64_t segmentOffset, uint8_t type, const char* symbolName) const;
bool doLocalReloc(Diagnostics& diag, uint32_t r_address, bool& stop, void (^callback)(uint32_t dataSegIndex, uint64_t dataSegOffset, uint8_t type, bool& stop)) const;
uint8_t relocPointerType() const;
int libOrdinalFromDesc(uint16_t n_desc) const;
bool doExternalReloc(Diagnostics& diag, uint32_t r_address, uint32_t r_symbolnum, LinkEditInfo& leInfo, bool& stop,
void (^callback)(uint32_t dataSegIndex, uint64_t dataSegOffset, uint8_t type, int libOrdinal,
uint64_t addend, const char* symbolName, bool weakImport, bool lazy, bool& stop)) const;
void getAllSegmentsInfos(Diagnostics& diag, SegmentInfo segments[]) const;
bool segmentHasTextRelocs(uint32_t segIndex) const;
uint64_t relocBaseAddress(const SegmentInfo segmentsInfos[], uint32_t segCount) const;
void forEachRebase(Diagnostics& diag, void (^handler)(const char* opcodeName, const LinkEditInfo& leInfo, const SegmentInfo segments[],
bool segIndexSet, uint32_t pointerSize, uint8_t segmentIndex, uint64_t segmentOffset, uint8_t type, bool& stop)) const;
bool segIndexAndOffsetForAddress(uint64_t addr, const SegmentInfo segmentsInfos[], uint32_t segCount, uint32_t& segIndex, uint64_t& segOffset) const;
void forEachBind(Diagnostics& diag, void (^handler)(const char* opcodeName, const LinkEditInfo& leInfo, const SegmentInfo segments[],
bool segIndexSet, bool libraryOrdinalSet, uint32_t dylibCount, int libOrdinal,
uint32_t pointerSize, uint8_t segmentIndex, uint64_t segmentOffset,
uint8_t type, const char* symbolName, bool weakImport, uint64_t addend, bool& stop),
void (^strongHandler)(const char* symbolName)) const;
void forEachChainedFixup(Diagnostics& diag, void (^targetCount)(uint32_t totalTargets, bool& stop),
void (^addTarget)(const LinkEditInfo& leInfo, const SegmentInfo segments[], bool libraryOrdinalSet, uint32_t dylibCount, int libOrdinal, uint8_t type, const char* symbolName, uint64_t addend, bool weakImport, bool& stop),
void (^addChainStart)(const LinkEditInfo& leInfo, const SegmentInfo segments[], uint8_t segmentIndex, bool segIndexSet, uint64_t segmentOffset, bool& stop)) const;
bool contentIsRegularStub(const uint8_t* helperContent) const;
uint64_t entryAddrFromThreadCmd(const thread_command* cmd) const;
};
}
#endif