#ifndef MachOLoaded_h
#define MachOLoaded_h
#include <stdint.h>
#include "Array.h"
#include "MachOFile.h"
class SharedCacheBuilder;
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 findClosestSymbol(uint64_t unSlidAddr, const char** symbolName, uint64_t* symbolUnslidAddr) const;
const void* findSectionContent(const char* segName, const char* sectName, uint64_t& size) const;
void forEachCDHashOfCodeSignature(const void* codeSigStart, size_t codeSignLen,
void (^callback)(const 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;
#if BUILDING_DYLD || BUILDING_LIBDYLD
void fixupAllChainedFixups(Diagnostics& diag, const dyld_chained_starts_in_image* starts, uintptr_t slide,
Array<const void*> bindTargets, void (^fixupLogger)(void* loc, void* newValue)) const;
#endif
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;
union ChainedFixupPointerOnDisk
{
union Arm64e {
dyld_chained_ptr_arm64e_auth_rebase authRebase;
dyld_chained_ptr_arm64e_auth_bind authBind;
dyld_chained_ptr_arm64e_rebase rebase;
dyld_chained_ptr_arm64e_bind bind;
dyld_chained_ptr_arm64e_bind24 bind24;
dyld_chained_ptr_arm64e_auth_bind24 authBind24;
uint64_t signExtendedAddend() const;
uint64_t unpackTarget() const;
const char* keyName() const;
uint64_t signPointer(void* loc, uint64_t target) const;
static uint64_t signPointer(uint64_t unsignedPtr, void* loc, bool addrDiv, uint16_t diversity, uint8_t key);
static const char* keyName(uint8_t keyBits);
};
union Generic64 {
dyld_chained_ptr_64_rebase rebase;
dyld_chained_ptr_64_bind bind;
uint64_t signExtendedAddend() const;
uint64_t unpackedTarget() const;
};
union Generic32 {
dyld_chained_ptr_32_rebase rebase;
dyld_chained_ptr_32_bind bind;
uint64_t signExtendedAddend() const;
};
struct Kernel64 : dyld_chained_ptr_64_kernel_cache_rebase {
const char* keyName() const;
};
struct Firm32 : dyld_chained_ptr_32_firmware_rebase { };
typedef dyld_chained_ptr_32_cache_rebase Cache32;
uint64_t raw64;
Arm64e arm64e;
Generic64 generic64;
Kernel64 kernel64;
uint32_t raw32;
Generic32 generic32;
Cache32 cache32;
Firm32 firmware32;
bool isRebase(uint16_t pointerFormat, uint64_t preferedLoadAddress, uint64_t& targetRuntimeOffset) const;
bool isBind(uint16_t pointerFormat, uint32_t& bindOrdinal, int64_t& addend) const;
static unsigned strideSize(uint16_t pointerFormat);
};
struct LayoutInfo {
uintptr_t slide;
uintptr_t textUnslidVMAddr;
uintptr_t linkeditUnslidVMAddr;
uint32_t linkeditFileOffset;
uint32_t linkeditFileSize;
uint32_t linkeditSegIndex;
uint32_t lastSegIndex;
};
struct LinkEditInfo
{
const dyld_info_command* dyldInfo;
const linkedit_data_command* exportsTrie;
const linkedit_data_command* chainedFixups;
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;
};
void getLinkEditPointers(Diagnostics& diag, LinkEditInfo&) const;
void forEachFixupChainSegment(Diagnostics& diag, const dyld_chained_starts_in_image* starts,
void (^handler)(const dyld_chained_starts_in_segment* segInfo, uint32_t segIndex, bool& stop)) const;
void forEachFixupInSegmentChains(Diagnostics& diag, const dyld_chained_starts_in_segment* segInfo, bool notifyNonPointers,
void (^handler)(ChainedFixupPointerOnDisk* fixupLocation, const dyld_chained_starts_in_segment* segInfo, bool& stop)) const;
void forEachFixupInAllChains(Diagnostics& diag, const dyld_chained_starts_in_image* starts, bool notifyNonPointers,
void (^callback)(ChainedFixupPointerOnDisk* fixupLocation, const dyld_chained_starts_in_segment* segInfo, bool& stop)) const;
void forEachFixupInAllChains(Diagnostics& diag, uint16_t pointer_format, uint32_t starts_count, const uint32_t chain_starts[],
void (^handler)(ChainedFixupPointerOnDisk* fixupLocation, bool& stop)) const;
protected:
friend SharedCacheBuilder;
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;
};
bool findExportedSymbol(Diagnostics& diag, const char* symbolName, bool weakImport, FoundSymbol& foundInfo, DependentToMachOLoaded finder) const;
void getLinkEditLoadCommands(Diagnostics& diag, LinkEditInfo& result) const;
void getLayoutInfo(LayoutInfo&) const;
const uint8_t* getLinkEditContent(const LayoutInfo& info, uint32_t fileOffset) const;
const uint8_t* getExportsTrie(const LinkEditInfo& info, uint64_t& trieSize) 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;
void forEachCodeDirectoryBlob(const void* codeSigStart, size_t codeSignLen, void (^callback)(const void* cd)) const;
bool walkChain(Diagnostics& diag, ChainedFixupPointerOnDisk* start, uint16_t pointer_format, bool notifyNonPointers, uint32_t max_valid_pointer,
void (^handler)(ChainedFixupPointerOnDisk* fixupLocation, bool& stop)) const;
};
}
#endif