mirror of
https://github.com/darlinghq/darling-dyld.git
synced 2024-11-26 22:00:26 +00:00
221 lines
9.9 KiB
C++
221 lines
9.9 KiB
C++
/*
|
|
* Copyright (c) 2017 Apple Inc. All rights reserved.
|
|
*
|
|
* @APPLE_LICENSE_HEADER_START@
|
|
*
|
|
* This file contains Original Code and/or Modifications of Original Code
|
|
* as defined in and that are subject to the Apple Public Source License
|
|
* Version 2.0 (the 'License'). You may not use this file except in
|
|
* compliance with the License. Please obtain a copy of the License at
|
|
* http://www.opensource.apple.com/apsl/ and read it before using this
|
|
* file.
|
|
*
|
|
* The Original Code and all software distributed under the License are
|
|
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
|
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
|
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
|
* Please see the License for the specific language governing rights and
|
|
* limitations under the License.
|
|
*
|
|
* @APPLE_LICENSE_HEADER_END@
|
|
*/
|
|
|
|
#ifndef MachOLoaded_h
|
|
#define MachOLoaded_h
|
|
|
|
#include <stdint.h>
|
|
|
|
#include "Array.h"
|
|
#include "MachOFile.h"
|
|
|
|
|
|
class SharedCacheBuilder;
|
|
|
|
namespace dyld3 {
|
|
|
|
|
|
// A mach-o mapped into memory with zero-fill expansion
|
|
// Can be used in dyld at runtime or during closure building
|
|
struct VIS_HIDDEN MachOLoaded : public MachOFile
|
|
{
|
|
typedef const MachOLoaded* (^DependentToMachOLoaded)(const MachOLoaded* image, uint32_t depIndex);
|
|
|
|
// for dlsym()
|
|
bool hasExportedSymbol(const char* symbolName, DependentToMachOLoaded finder, void** result,
|
|
bool* resultPointsToInstructions) const;
|
|
|
|
// for DYLD_PRINT_SEGMENTS
|
|
const char* segmentName(uint32_t segIndex) const;
|
|
|
|
// used to see if main executable overlaps shared region
|
|
bool intersectsRange(uintptr_t start, uintptr_t length) const;
|
|
|
|
// for _dyld_get_image_slide()
|
|
intptr_t getSlide() const;
|
|
|
|
// for dladdr()
|
|
bool findClosestSymbol(uint64_t unSlidAddr, const char** symbolName, uint64_t* symbolUnslidAddr) const;
|
|
|
|
// for _dyld_find_unwind_sections()
|
|
const void* findSectionContent(const char* segName, const char* sectName, uint64_t& size) const;
|
|
|
|
// used at runtime to validate loaded image matches closure
|
|
void forEachCDHashOfCodeSignature(const void* codeSigStart, size_t codeSignLen,
|
|
void (^callback)(const uint8_t cdHash[20])) const;
|
|
|
|
// used by DyldSharedCache to find closure
|
|
static const uint8_t* trieWalk(Diagnostics& diag, const uint8_t* start, const uint8_t* end, const char* symbol);
|
|
|
|
// used by cache builder during error handling in chain bind processing
|
|
const char* dependentDylibLoadPath(uint32_t depIndex) const;
|
|
|
|
// used by closure builder to find the offset and size of the trie.
|
|
bool hasExportTrie(uint32_t& runtimeOffset, uint32_t& size) const;
|
|
|
|
// used by dyld/libdyld to apply fixups
|
|
#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;
|
|
|
|
|
|
// For use with new rebase/bind scheme were each fixup location on disk contains info on what
|
|
// fix up it needs plus the offset to the next fixup.
|
|
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;
|
|
|
|
// for dyld loaded images
|
|
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;
|
|
// for preload images
|
|
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;
|
|
|
|
// This calls the callback for all code directories required for a given platform/binary combination.
|
|
// On watchOS main executables this is all cd hashes.
|
|
// On watchOS dylibs this is only the single cd hash we need (by rank defined by dyld, not the kernel).
|
|
// On all other platforms this always returns a single best cd hash (ranked to match the kernel).
|
|
// Note the callback parameter is really a CS_CodeDirectory.
|
|
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;
|
|
|
|
};
|
|
|
|
} // namespace dyld3
|
|
|
|
#endif /* MachOLoaded_h */
|