#ifndef MachOLoaded_h
#define MachOLoaded_h
#include <stdint.h>
#include "MachOFile.h"
class CacheBuilder;
namespace dyld3 {
struct VIS_HIDDEN MachOLoaded : public MachOFile
{
typedef const MachOLoaded* (^DependentToMachOLoaded)(const MachOLoaded* image, uint32_t depIndex);
bool hasExportedSymbol(const char* symbolName, DependentToMachOLoaded finder, void** result,
bool* resultPointsToInstructions) const;
const char* segmentName(uint32_t segIndex) const;
bool intersectsRange(uintptr_t start, uintptr_t length) const;
intptr_t getSlide() const;
bool inDyldCache() const { return (this->flags & 0x80000000); }
bool findClosestSymbol(uint64_t unSlidAddr, const char** symbolName, uint64_t* symbolUnslidAddr) const;
const void* findSectionContent(const char* segName, const char* sectName, uint64_t& size) const;
bool cdHashOfCodeSignature(const void* codeSigStart, size_t codeSignLen, uint8_t cdHash[20]) const;
static const uint8_t* trieWalk(Diagnostics& diag, const uint8_t* start, const uint8_t* end, const char* symbol);
const char* dependentDylibLoadPath(uint32_t depIndex) const;
bool hasExportTrie(uint32_t& runtimeOffset, uint32_t& size) const;
union ChainedFixupPointerOnDisk
{
struct PlainRebase
{
uint64_t target : 51,
next : 11,
bind : 1, auth : 1; uint64_t signExtendedTarget() const;
};
struct PlainBind
{
uint64_t ordinal : 16,
zero : 16,
addend : 19,
next : 11,
bind : 1, auth : 1; uint64_t signExtendedAddend() const;
};
struct AuthRebase
{
uint64_t target : 32,
diversity : 16,
addrDiv : 1,
key : 2,
next : 11,
bind : 1, auth : 1; const char* keyName() const;
};
struct AuthBind
{
uint64_t ordinal : 16,
zero : 16,
diversity : 16,
addrDiv : 1,
key : 2,
next : 11,
bind : 1, auth : 1; const char* keyName() const;
};
uint64_t raw;
AuthRebase authRebase;
AuthBind authBind;
PlainRebase plainRebase;
PlainBind plainBind;
static const char* keyName(uint8_t keyBits);
static uint64_t signExtend51(uint64_t);
uint64_t signPointer(void* loc, uint64_t target) const;
};
protected:
friend CacheBuilder;
struct FoundSymbol {
enum class Kind { headerOffset, absolute, resolverOffset };
Kind kind;
bool isThreadLocal;
bool isWeakDef;
const MachOLoaded* foundInDylib;
uint64_t value;
uint32_t resolverFuncOffset;
const char* foundSymbolName;
};
struct LayoutInfo {
uintptr_t slide;
uintptr_t textUnslidVMAddr;
uintptr_t linkeditUnslidVMAddr;
uint32_t linkeditFileOffset;
uint32_t linkeditFileSize;
uint32_t linkeditSegIndex;
};
struct LinkEditInfo
{
const dyld_info_command* dyldInfo;
const symtab_command* symTab;
const dysymtab_command* dynSymTab;
const linkedit_data_command* splitSegInfo;
const linkedit_data_command* functionStarts;
const linkedit_data_command* dataInCode;
const linkedit_data_command* codeSig;
LayoutInfo layout;
};
bool findExportedSymbol(Diagnostics& diag, const char* symbolName, FoundSymbol& foundInfo, DependentToMachOLoaded finder) const;
void getLinkEditPointers(Diagnostics& diag, LinkEditInfo&) const;
void getLinkEditLoadCommands(Diagnostics& diag, LinkEditInfo& result) const;
void getLayoutInfo(LayoutInfo&) const;
const uint8_t* getLinkEditContent(const LayoutInfo& info, uint32_t fileOffset) const;
void forEachGlobalSymbol(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 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;
uint32_t dependentDylibCount() const;
bool findClosestFunctionStart(uint64_t address, uint64_t* functionStartAddress) const;
const void* findCodeDirectoryBlob(const void* codeSigStart, size_t codeSignLen) const;
};
}
#endif