dyld-640.2.tar.gz
[apple/dyld.git] / dyld3 / MachOAnalyzer.h
1 /*
2 * Copyright (c) 2017 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #ifndef MachOAnalyzer_h
25 #define MachOAnalyzer_h
26
27
28 #define BIND_SPECIAL_DYLIB_WEAK_DEF_COALESCE (-3)
29
30 #include "MachOLoaded.h"
31 #include "ClosureFileSystem.h"
32
33 namespace dyld3 {
34
35 // Extra functionality on loaded mach-o files only used during closure building
36 struct VIS_HIDDEN MachOAnalyzer : public MachOLoaded
37 {
38 static closure::LoadedFileInfo load(Diagnostics& diag, const closure::FileSystem& fileSystem, const char* logicalPath, const char* reqArchName, Platform reqPlatform);
39 static const MachOAnalyzer* validMainExecutable(Diagnostics& diag, const mach_header* mh, const char* path, uint64_t sliceLength, const char* reqArchName, Platform reqPlatform);
40
41 bool validMachOForArchAndPlatform(Diagnostics& diag, size_t mappedSize, const char* path, const char* reqArchName, Platform reqPlatform) const;
42 uint64_t mappedSize() const;
43 bool hasObjC() const;
44 bool hasPlusLoadMethod(Diagnostics& diag) const;
45 uint64_t preferredLoadAddress() const;
46 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;
47 void forEachRPath(void (^callback)(const char* rPath, bool& stop)) const;
48
49 bool isEncrypted() const;
50 bool getCDHash(uint8_t cdHash[20]) const;
51 bool hasCodeSignature(uint32_t& fileOffset, uint32_t& size) const;
52 bool usesLibraryValidation() const;
53 bool isRestricted() const;
54 bool getEntry(uint32_t& offset, bool& usesCRT) const;
55 bool isSlideable() const;
56 bool hasInitializer(Diagnostics& diag, bool contentRebased, const void* dyldCache=nullptr) const;
57 void forEachInitializer(Diagnostics& diag, bool contentRebased, void (^callback)(uint32_t offset), const void* dyldCache=nullptr) const;
58 void forEachDOFSection(Diagnostics& diag, void (^callback)(uint32_t offset)) const;
59 uint32_t segmentCount() const;
60 void forEachExportedSymbol(Diagnostics diag, void (^callback)(const char* symbolName, uint64_t imageOffset, bool isReExport, bool& stop)) const;
61 void forEachRebase(Diagnostics& diag, void (^callback)(uint32_t dataSegIndex, uint64_t dataSegOffset, uint8_t type, bool& stop)) const;
62 void forEachWeakDef(Diagnostics& diag, void (^callback)(bool strongDef, uint32_t dataSegIndex, uint64_t dataSegOffset,
63 uint64_t addend, const char* symbolName, bool& stop)) const;
64 void forEachIndirectPointer(Diagnostics& diag, void (^handler)(uint64_t pointerAddress, bool bind, int bindLibOrdinal,
65 const char* bindSymbolName, bool bindWeakImport, bool bindLazy, bool selfModifyingStub, bool& stop)) const;
66 void forEachInterposingSection(Diagnostics& diag, void (^handler)(uint64_t vmOffset, uint64_t vmSize, bool& stop)) const;
67 const void* content(uint64_t vmOffset);
68 void forEachLocalReloc(void (^handler)(uint64_t runtimeOffset, bool& stop)) const;
69 void forEachExternalReloc(void (^handler)(uint64_t runtimeOffset, int libOrdinal, const char* symbolName, bool& stop)) const;
70
71 const void* getRebaseOpcodes(uint32_t& size) const;
72 const void* getBindOpcodes(uint32_t& size) const;
73 const void* getLazyBindOpcodes(uint32_t& size) const;
74 uint64_t segAndOffsetToRuntimeOffset(uint8_t segIndex, uint64_t segOffset) const;
75 bool hasLazyPointers(uint32_t& runtimeOffset, uint32_t& size) const;
76 void forEachRebase(Diagnostics& diag, bool ignoreLazyPointer, void (^callback)(uint64_t runtimeOffset, bool& stop)) const;
77 void forEachTextRebase(Diagnostics& diag, void (^callback)(uint64_t runtimeOffset, bool& stop)) const;
78 void forEachBind(Diagnostics& diag, void (^callback)(uint64_t runtimeOffset, int libOrdinal, const char* symbolName,
79 bool weakImport, uint64_t addend, bool& stop),
80 void (^strongHandler)(const char* symbolName)) const;
81 void forEachChainedFixupTarget(Diagnostics& diag, void (^callback)(int libOrdinal, const char* symbolName, uint64_t addend, bool weakImport, bool& stop)) const;
82 void forEachChainedFixupStart(Diagnostics& diag, void (^callback)(uint64_t runtimeOffset, bool& stop)) const;
83 bool canHavePrecomputedDlopenClosure(const char* path, void (^failureReason)(const char*)) const;
84 bool canBePlacedInDyldCache(const char* path, void (^failureReason)(const char*)) const;
85
86 #if DEBUG
87 void validateDyldCacheDylib(Diagnostics& diag, const char* path) const;
88 #endif
89
90 const MachOAnalyzer* remapIfZeroFill(Diagnostics& diag, const closure::FileSystem& fileSystem, closure::LoadedFileInfo& info) const;
91
92 // protected members of subclass promoted to public here
93 using MachOLoaded::SegmentInfo;
94 using MachOLoaded::SectionInfo;
95 using MachOLoaded::forEachSegment;
96 using MachOLoaded::forEachSection;
97 using MachOLoaded::forEachDependentDylib;
98 using MachOLoaded::getDylibInstallName;
99 using MachOLoaded::FoundSymbol;
100 using MachOLoaded::findExportedSymbol;
101
102 private:
103
104 struct SegmentStuff
105 {
106 uint64_t fileOffset;
107 uint64_t fileSize;
108 uint64_t writable : 1,
109 executable : 1,
110 textRelocsAllowed : 1, // segment supports text relocs (i386 only)
111 segSize : 61;
112 };
113
114 enum class Malformed { linkeditOrder, linkeditAlignment, dyldInfoAndlocalRelocs };
115 bool enforceFormat(Malformed) const;
116
117 const uint8_t* getContentForVMAddr(const LayoutInfo& info, uint64_t vmAddr) const;
118
119 bool validLoadCommands(Diagnostics& diag, const char* path, size_t fileLen) const;
120 bool validEmbeddedPaths(Diagnostics& diag, const char* path) const;
121 bool validSegments(Diagnostics& diag, const char* path, size_t fileLen) const;
122 bool validLinkedit(Diagnostics& diag, const char* path) const;
123 bool validLinkeditLayout(Diagnostics& diag, const char* path) const;
124 bool validRebaseInfo(Diagnostics& diag, const char* path) const;
125 bool validBindInfo(Diagnostics& diag, const char* path) const;
126 bool validMain(Diagnostics& diag, const char* path) const;
127 bool validChainedFixupsInfo(Diagnostics& diag, const char* path) const;
128
129 bool invalidRebaseState(Diagnostics& diag, const char* opcodeName, const char* path, const LinkEditInfo& leInfo, const SegmentInfo segments[],
130 bool segIndexSet, uint32_t pointerSize, uint8_t segmentIndex, uint64_t segmentOffset, uint8_t type) const;
131 bool invalidBindState(Diagnostics& diag, const char* opcodeName, const char* path, const LinkEditInfo& leInfo, const SegmentInfo segments[],
132 bool segIndexSet, bool libraryOrdinalSet, uint32_t dylibCount, int libOrdinal, uint32_t pointerSize,
133 uint8_t segmentIndex, uint64_t segmentOffset, uint8_t type, const char* symbolName) const;
134 bool doLocalReloc(Diagnostics& diag, uint32_t r_address, bool& stop, void (^callback)(uint32_t dataSegIndex, uint64_t dataSegOffset, uint8_t type, bool& stop)) const;
135 uint8_t relocPointerType() const;
136 int libOrdinalFromDesc(uint16_t n_desc) const;
137 bool doExternalReloc(Diagnostics& diag, uint32_t r_address, uint32_t r_symbolnum, LinkEditInfo& leInfo, bool& stop,
138 void (^callback)(uint32_t dataSegIndex, uint64_t dataSegOffset, uint8_t type, int libOrdinal,
139 uint64_t addend, const char* symbolName, bool weakImport, bool lazy, bool& stop)) const;
140
141 void getAllSegmentsInfos(Diagnostics& diag, SegmentInfo segments[]) const;
142 bool segmentHasTextRelocs(uint32_t segIndex) const;
143 uint64_t relocBaseAddress(const SegmentInfo segmentsInfos[], uint32_t segCount) const;
144 void forEachRebase(Diagnostics& diag, void (^handler)(const char* opcodeName, const LinkEditInfo& leInfo, const SegmentInfo segments[],
145 bool segIndexSet, uint32_t pointerSize, uint8_t segmentIndex, uint64_t segmentOffset, uint8_t type, bool& stop)) const;
146 bool segIndexAndOffsetForAddress(uint64_t addr, const SegmentInfo segmentsInfos[], uint32_t segCount, uint32_t& segIndex, uint64_t& segOffset) const;
147 void forEachBind(Diagnostics& diag, void (^handler)(const char* opcodeName, const LinkEditInfo& leInfo, const SegmentInfo segments[],
148 bool segIndexSet, bool libraryOrdinalSet, uint32_t dylibCount, int libOrdinal,
149 uint32_t pointerSize, uint8_t segmentIndex, uint64_t segmentOffset,
150 uint8_t type, const char* symbolName, bool weakImport, uint64_t addend, bool& stop),
151 void (^strongHandler)(const char* symbolName)) const;
152 void forEachChainedFixup(Diagnostics& diag, void (^targetCount)(uint32_t totalTargets, bool& stop),
153 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),
154 void (^addChainStart)(const LinkEditInfo& leInfo, const SegmentInfo segments[], uint8_t segmentIndex, bool segIndexSet, uint64_t segmentOffset, bool& stop)) const;
155 bool contentIsRegularStub(const uint8_t* helperContent) const;
156 uint64_t entryAddrFromThreadCmd(const thread_command* cmd) const;
157
158 };
159
160 } // namespace dyld3
161
162 #endif /* MachOAnalyzer_h */