]>
git.saurik.com Git - apple/dyld.git/blob - dyld3/MachOParser.h
2 * Copyright (c) 2017 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
29 #include <uuid/uuid.h>
30 #include <mach-o/loader.h>
36 #include "Diagnostics.h"
39 #define BIND_TYPE_IMPORT_JMP_REL32 4
43 // Note, this should make PLATFORM_* values in <mach-o/loader.h>
53 struct VIS_HIDDEN UUID
{
55 UUID(const UUID
& other
) { uuid_copy(&_bytes
[0], &other
._bytes
[0]); }
56 UUID(const uuid_t other_uuid
) { uuid_copy(&_bytes
[0], other_uuid
); }
57 bool operator<(const UUID
& other
) const { return uuid_compare(&_bytes
[0], &other
._bytes
[0]) < 0; }
58 bool operator==(const UUID
& other
) const { return uuid_compare(&_bytes
[0], &other
._bytes
[0]) == 0; }
59 bool operator!=(const UUID
& other
) const { return !(*this == other
); }
64 for (auto i
= 0; i
< 16 / sizeof(size_t); ++i
) {
65 retval
^= ((size_t*)(&_bytes
[0]))[i
];
69 const unsigned char* get() const { return &_bytes
[0]; };
71 std::array
<unsigned char, 16> _bytes
;
74 class VIS_HIDDEN MachOParser
78 static bool isValidMachO(Diagnostics
& diag
, const std::string
& archName
, Platform platform
, const void* fileContent
, size_t fileLength
, const std::string
& pathOpened
, bool ignoreMainExecutables
);
79 static bool isArch(const mach_header
* mh
, const std::string
& archName
);
80 static std::string
archName(uint32_t cputype
, uint32_t cpusubtype
);
81 static std::string
platformName(Platform platform
);
82 static std::string
versionString(uint32_t packedVersion
);
83 static uint32_t cpuTypeFromArchName(const std::string
& archName
);
84 static uint32_t cpuSubtypeFromArchName(const std::string
& archName
);
86 static bool isMachO(Diagnostics
& diag
, const void* fileContent
, size_t fileLength
);
87 static bool wellFormedMachHeaderAndLoadCommands(const mach_header
* mh
);
89 MachOParser(const mach_header
* mh
, bool dyldCacheIsRaw
=false);
90 bool valid(Diagnostics
& diag
);
92 const mach_header
* header() const;
93 uint32_t fileType() const;
94 std::string
archName() const;
96 bool inDyldCache() const;
97 bool hasThreadLocalVariables() const;
98 Platform
platform() const;
99 uint64_t preferredLoadAddress() const;
101 bool getUuid(uuid_t uuid
) const;
102 bool getPlatformAndVersion(Platform
* platform
, uint32_t* minOS
, uint32_t* sdk
) const;
103 bool isSimulatorBinary() const;
104 bool getDylibInstallName(const char** installName
, uint32_t* compatVersion
, uint32_t* currentVersion
) const;
105 const char* installName() const;
106 uint32_t dependentDylibCount() const;
107 const char* dependentDylibLoadPath(uint32_t depIndex
) const;
108 void forEachDependentDylib(void (^callback
)(const char* loadPath
, bool isWeak
, bool isReExport
, bool isUpward
, uint32_t compatVersion
, uint32_t curVersion
, bool& stop
)) const;
109 void forEachSection(void (^callback
)(const char* segName
, const char* sectionName
, uint32_t flags
, const void* content
, size_t size
, bool illegalSectionSize
, bool& stop
)) const;
110 void forEachSegment(void (^callback
)(const char* segName
, uint32_t fileOffset
, uint32_t fileSize
, uint64_t vmAddr
, uint64_t vmSize
, uint8_t protections
, bool& stop
)) const;
111 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;
112 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;
113 void forEachRPath(void (^callback
)(const char* rPath
, bool& stop
)) const;
114 void forEachSection(void (^callback
)(const char* segName
, const char* sectionName
, uint32_t flags
, uint64_t addr
, const void* content
,
115 uint64_t size
, uint32_t alignP2
, uint32_t reserved1
, uint32_t reserved2
, bool illegalSectionSize
, bool& stop
)) const;
118 enum class Kind
{ headerOffset
, absolute
, resolverOffset
};
121 const mach_header
* foundInDylib
;
124 uint32_t resolverFuncOffset
;
125 const char* foundSymbolName
;
128 typedef bool (^DependentFinder
)(uint32_t depIndex
, const char* depLoadPath
, void* extra
, const mach_header
** foundMH
, void** foundExtra
);
130 bool findExportedSymbol(Diagnostics
& diag
, const char* symbolName
, void* extra
, FoundSymbol
& foundInfo
, DependentFinder finder
) const;
131 bool findClosestSymbol(uint64_t unSlidAddr
, const char** symbolName
, uint64_t* symbolUnslidAddr
) const;
132 bool isFairPlayEncrypted(uint32_t& textOffset
, uint32_t& size
);
135 intptr_t getSlide() const;
136 bool hasExportedSymbol(const char* symbolName
, DependentFinder finder
, void** result
) const;
137 bool findClosestSymbol(const void* addr
, const char** symbolName
, const void** symbolAddress
) const;
138 const char* segmentName(uint32_t segIndex
) const;
141 bool uses16KPages() const;
142 bool hasObjC() const;
143 bool hasWeakDefs() const;
144 bool isEncrypted() const;
145 bool hasPlusLoadMethod(Diagnostics
& diag
) const;
146 bool hasInitializer(Diagnostics
& diag
) const;
147 bool getCDHash(uint8_t cdHash
[20]);
148 bool hasCodeSignature(uint32_t& fileOffset
, uint32_t& size
);
149 bool usesLibraryValidation() const;
150 bool isRestricted() const;
151 bool getEntry(uint32_t& offset
, bool& usesCRT
);
152 bool canBePlacedInDyldCache(const std::string
& path
) const;
153 bool canBePlacedInDyldCache(const std::string
& path
, std::set
<std::string
>& reasons
) const;
154 bool isDynamicExecutable() const;
155 bool isSlideable() const;
156 void forEachInitializer(Diagnostics
& diag
, void (^callback
)(uint32_t offset
)) const;
157 void forEachDOFSection(Diagnostics
& diag
, void (^callback
)(uint32_t offset
)) const;
158 uint32_t segmentCount() const;
159 void forEachExportedSymbol(Diagnostics diag
, void (^callback
)(const char* symbolName
, uint64_t imageOffset
, bool isReExport
, bool& stop
)) const;
160 void forEachSegment(void (^callback
)(const char* segName
, uint32_t fileOffset
, uint32_t fileSize
, uint64_t vmAddr
, uint64_t vmSize
, uint8_t protections
, uint32_t segIndex
, uint64_t sizeOfSections
, uint8_t p2align
, bool& stop
)) const;
161 void forEachRebase(Diagnostics
& diag
, void (^callback
)(uint32_t dataSegIndex
, uint64_t dataSegOffset
, uint8_t type
, bool& stop
)) const;
162 void forEachBind(Diagnostics
& diag
, void (^callback
)(uint32_t dataSegIndex
, uint64_t dataSegOffset
, uint8_t type
, int libOrdinal
,
163 uint64_t addend
, const char* symbolName
, bool weakImport
, bool lazy
, bool& stop
)) const;
164 void forEachWeakDef(Diagnostics
& diag
, void (^callback
)(bool strongDef
, uint32_t dataSegIndex
, uint64_t dataSegOffset
,
165 uint64_t addend
, const char* symbolName
, bool& stop
)) const;
166 void forEachIndirectPointer(Diagnostics
& diag
, void (^handler
)(uint32_t dataSegIndex
, uint64_t dataSegOffset
, bool bind
, int bindLibOrdinal
,
167 const char* bindSymbolName
, bool bindWeakImport
, bool bindLazy
, bool selfModifyingStub
, bool& stop
)) const;
168 void forEachInterposingTuple(Diagnostics
& diag
, void (^handler
)(uint32_t segIndex
, uint64_t replacementSegOffset
, uint64_t replaceeSegOffset
, uint64_t replacementContent
, bool& stop
)) const;
169 const void* content(uint64_t vmOffset
);
172 static const uint8_t* trieWalk(Diagnostics
& diag
, const uint8_t* start
, const uint8_t* end
, const char* symbol
);
173 static uint64_t read_uleb128(Diagnostics
& diag
, const uint8_t*& p
, const uint8_t* end
);
174 static int64_t read_sleb128(Diagnostics
& diag
, const uint8_t*& p
, const uint8_t* end
);
175 static bool cdHashOfCodeSignature(const void* codeSigStart
, size_t codeSignLen
, uint8_t cdHash
[20]);
176 static Platform
currentPlatform();
182 uintptr_t textUnslidVMAddr
;
183 uintptr_t linkeditUnslidVMAddr
;
184 uint32_t linkeditFileOffset
;
186 uint32_t segmentCount
;
187 uint32_t linkeditSegIndex
;
189 uint64_t mappingOffset
;
192 uint64_t segUnslidAddress
;
193 uint64_t writable
: 1,
195 textRelocsAllowed
: 1, // segment supports text relocs (i386 only)
203 const dyld_info_command
* dyldInfo
;
204 const symtab_command
* symTab
;
205 const dysymtab_command
* dynSymTab
;
206 const linkedit_data_command
* splitSegInfo
;
207 const linkedit_data_command
* functionStarts
;
208 const linkedit_data_command
* dataInCode
;
209 const linkedit_data_command
* codeSig
;
213 void getLinkEditPointers(Diagnostics
& diag
, LinkEditInfo
&) const;
214 void getLinkEditLoadCommands(Diagnostics
& diag
, LinkEditInfo
& result
) const;
215 void getLayoutInfo(LayoutInfo
&) const;
216 const uint8_t* getLinkEditContent(const LayoutInfo
& info
, uint32_t fileOffset
) const;
225 static const ArchInfo _s_archInfos
[];
227 const uint8_t* getContentForVMAddr(const LayoutInfo
& info
, uint64_t vmAddr
) const;
228 bool doLocalReloc(Diagnostics
& diag
, uint32_t r_address
, bool& stop
, void (^callback
)(uint32_t dataSegIndex
, uint64_t dataSegOffset
, uint8_t type
, bool& stop
)) const;
229 uint8_t relocPointerType() const;
230 int libOrdinalFromDesc(uint16_t n_desc
) const;
231 bool doExternalReloc(Diagnostics
& diag
, uint32_t r_address
, uint32_t r_symbolnum
, LinkEditInfo
& leInfo
, bool& stop
,
232 void (^callback
)(uint32_t dataSegIndex
, uint64_t dataSegOffset
, uint8_t type
, int libOrdinal
,
233 uint64_t addend
, const char* symbolName
, bool weakImport
, bool lazy
, bool& stop
)) const;
234 bool validLoadCommands(Diagnostics
& diag
, size_t fileLen
);
235 bool validEmbeddedPaths(Diagnostics
& diag
);
236 bool validSegments(Diagnostics
& diag
, size_t fileLen
);
237 bool validLinkeditLayout(Diagnostics
& diag
);
238 bool invalidBindState(Diagnostics
& diag
, const char* opcodeName
, const MachOParser::LinkEditInfo
& leInfo
, bool segIndexSet
, bool libraryOrdinalSet
,
239 uint32_t dylibCount
, int libOrdinal
, uint32_t pointerSize
, uint8_t segmentIndex
, uint64_t segmentOffset
, uint8_t type
, const char* symbolName
) const;
240 bool invalidRebaseState(Diagnostics
& diag
, const char* opcodeName
, const MachOParser::LinkEditInfo
& leInfo
, bool segIndexSet
,
241 uint32_t pointerSize
, uint8_t segmentIndex
, uint64_t segmentOffset
, uint8_t type
) const;
243 static const void* findCodeDirectoryBlob(const void* codeSigStart
, size_t codeSignLen
);
244 void forEachSection(void (^callback
)(const char* segName
, uint32_t segIndex
, uint64_t segVMAddr
, const char* sectionName
, uint32_t sectFlags
,
245 uint64_t sectAddr
, uint64_t size
, uint32_t alignP2
, uint32_t reserved1
, uint32_t reserved2
, bool illegalSectionSize
, bool& stop
)) const;
247 void forEachLoadCommand(Diagnostics
& diag
, void (^callback
)(const load_command
* cmd
, bool& stop
)) const;
249 bool inRawCache() const;
251 long _data
; // if low bit true, then this is raw file (not loaded image)
256 class VIS_HIDDEN FatUtil
259 static bool isFatFile(const void* fileStart
);
260 static void forEachSlice(Diagnostics
& diag
, const void* fileContent
, size_t fileLen
, void (^callback
)(uint32_t sliceCpuType
, uint32_t sliceCpuSubType
, const void* sliceStart
, size_t sliceSize
, bool& stop
));
262 static bool isFatFileWithSlice(Diagnostics
& diag
, const void* fileContent
, size_t fileLen
, const std::string
& archName
, size_t& sliceOffset
, size_t& sliceLen
, bool& missingSlice
);
271 struct hash
<dyld3::UUID
> {
272 size_t operator()(const dyld3::UUID
& x
) const
279 #endif // MachOParser_h