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@
28 #include <mach-o/loader.h>
29 #include <mach-o/fat.h>
30 #include <uuid/uuid.h>
32 #include "Diagnostics.h"
33 #include "SupportedArchs.h"
34 #include <mach-o/fixup-chains.h>
35 #include <mach-o/loader.h>
37 // needed until dyld builds with a newer SDK
38 #ifndef CPU_SUBTYPE_ARM64E
39 #define CPU_SUBTYPE_ARM64E 2
41 #ifndef CPU_TYPE_ARM64_32
42 #define CPU_TYPE_ARM64_32 0x0200000C
44 #ifndef CPU_SUBTYPE_ARM64_32_V8
45 #define CPU_SUBTYPE_ARM64_32_V8 1
47 #ifndef BIND_OPCODE_THREADED
48 #define BIND_OPCODE_THREADED 0xD0
50 #ifndef BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB
51 #define BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB 0x00
53 #ifndef BIND_SUBOPCODE_THREADED_APPLY
54 #define BIND_SUBOPCODE_THREADED_APPLY 0x01
56 #ifndef BIND_SPECIAL_DYLIB_WEAK_LOOKUP
57 #define BIND_SPECIAL_DYLIB_WEAK_LOOKUP (-3)
59 #ifndef EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE
60 #define EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE 0x02
63 #define SG_READ_ONLY 0x10
66 #ifndef LC_DYLD_EXPORTS_TRIE
67 #define LC_DYLD_EXPORTS_TRIE 0x80000033
69 #ifndef LC_DYLD_CHAINED_FIXUPS
70 #define LC_DYLD_CHAINED_FIXUPS 0x80000034
73 #ifndef S_INIT_FUNC_OFFSETS
74 #define S_INIT_FUNC_OFFSETS 0x16
81 /// Returns true if (addLHS + addRHS) > b, or if the add overflowed
83 inline bool greaterThanAddOrOverflow(uint32_t addLHS
, uint32_t addRHS
, T b
) {
84 return (addLHS
> b
) || (addRHS
> (b
-addLHS
));
87 /// Returns true if (addLHS + addRHS) > b, or if the add overflowed
89 inline bool greaterThanAddOrOverflow(uint64_t addLHS
, uint64_t addRHS
, T b
) {
90 return (addLHS
> b
) || (addRHS
> (b
-addLHS
));
94 // Note, this should match PLATFORM_* values in <mach-o/loader.h>
97 macOS
= 1, // PLATFORM_MACOS
98 iOS
= 2, // PLATFORM_IOS
99 tvOS
= 3, // PLATFORM_TVOS
100 watchOS
= 4, // PLATFORM_WATCHOS
101 bridgeOS
= 5, // PLATFORM_BRIDGEOS
102 iOSMac
= 6, // PLATFORM_IOSMAC
103 iOS_simulator
= 7, // PLATFORM_IOSSIMULATOR
104 tvOS_simulator
= 8, // PLATFORM_TVOSSIMULATOR
105 watchOS_simulator
= 9, // PLATFORM_WATCHOSSIMULATOR
106 driverKit
= 10, // PLATFORM_DRIVERKIT
109 struct MachOFile
; // forward ref
111 // A prioritized list of architectures
112 class VIS_HIDDEN GradedArchs
{
114 // never construct new ones - just use existing static instances
115 GradedArchs() = delete;
116 GradedArchs(const GradedArchs
&) = delete;
118 static const GradedArchs
& forCurrentOS(const MachOFile
* mainExecutable
);
119 static const GradedArchs
& forName(const char* archName
, bool forMainExecutable
= false);
121 int grade(uint32_t cputype
, uint32_t cpusubtype
) const;
122 const char* name() const;
124 // pre-built lists for existing hardware
125 static const GradedArchs i386
; // 32-bit Mac
126 static const GradedArchs x86_64
; // older Mac
127 static const GradedArchs x86_64h
; // haswell Mac
128 static const GradedArchs arm64
; // A11 or earlier iPhone or iPad
129 #if SUPPORT_ARCH_arm64e
130 static const GradedArchs arm64e
; // A12 or later iPhone or iPad
131 static const GradedArchs arm64e_compat
; // A12 running arm64 main executable
133 static const GradedArchs armv7k
; // watch thru series 3
134 static const GradedArchs armv7s
; // deprecated
135 static const GradedArchs armv7
; // deprecated
136 #if SUPPORT_ARCH_arm64_32
137 static const GradedArchs arm64_32
; // watch series 4 and later
141 // should be private, but compiler won't statically initialize static members above
142 struct CpuGrade
{ uint32_t type
; uint32_t subtype
; uint32_t grade
; };
143 const CpuGrade _orderedCpuTypes
[3]; // zero terminated
147 // A file read/mapped into memory
148 struct VIS_HIDDEN FatFile
: fat_header
150 static const FatFile
* isFatFile(const void* fileContent
);
151 void forEachSlice(Diagnostics
& diag
, uint64_t fileLen
, void (^callback
)(uint32_t sliceCpuType
, uint32_t sliceCpuSubType
, const void* sliceStart
, uint64_t sliceSize
, bool& stop
)) const;
152 bool isFatFileWithSlice(Diagnostics
& diag
, uint64_t fileLen
, const GradedArchs
& archs
, uint64_t& sliceOffset
, uint64_t& sliceLen
, bool& missingSlice
) const;
155 bool isValidSlice(Diagnostics
& diag
, uint64_t fileLen
, uint32_t sliceIndex
,
156 uint32_t sliceCpuType
, uint32_t sliceCpuSubType
, uint64_t sliceOffset
, uint64_t sliceLen
) const;
160 // A mach-o file read/mapped into memory
161 // Only info from mach_header or load commands is accessible (no LINKEDIT info)
162 struct VIS_HIDDEN MachOFile
: mach_header
164 static const char* archName(uint32_t cputype
, uint32_t cpusubtype
);
165 static const char* platformName(Platform platform
);
166 static uint32_t cpuTypeFromArchName(const char* archName
);
167 static uint32_t cpuSubtypeFromArchName(const char* archName
);
168 static void packedVersionToString(uint32_t packedVersion
, char versionString
[32]);
169 static const char* currentArchName();
170 static Platform
currentPlatform();
171 static uint64_t read_uleb128(Diagnostics
& diag
, const uint8_t*& p
, const uint8_t* end
);
172 static int64_t read_sleb128(Diagnostics
& diag
, const uint8_t*& p
, const uint8_t* end
);
173 static bool isSimulatorPlatform(Platform platform
);
174 static bool isSharedCacheEligiblePath(const char* path
);
176 bool hasMachOMagic() const;
177 bool isMachO(Diagnostics
& diag
, uint64_t fileSize
) const;
178 bool isDylib() const;
179 bool isBundle() const;
180 bool isMainExecutable() const;
181 bool isDynamicExecutable() const;
182 bool isStaticExecutable() const;
183 bool isPreload() const;
185 bool isArch(const char* archName
) const;
186 const char* archName() const;
188 size_t machHeaderSize() const;
189 uint32_t pointerSize() const;
190 bool uses16KPages() const;
191 bool supportsPlatform(Platform
) const;
192 bool isZippered() const;
193 bool inDyldCache() const;
194 bool isSimulatorBinary() const;
195 bool getUuid(uuid_t uuid
) const;
196 bool hasWeakDefs() const;
197 bool hasThreadLocalVariables() const;
198 bool getDylibInstallName(const char** installName
, uint32_t* compatVersion
, uint32_t* currentVersion
) const;
199 void forEachSupportedPlatform(void (^callback
)(Platform platform
, uint32_t minOS
, uint32_t sdk
)) const;
200 const char* installName() const; // returns nullptr is no install name
201 void forEachDependentDylib(void (^callback
)(const char* loadPath
, bool isWeak
, bool isReExport
, bool isUpward
, uint32_t compatVersion
, uint32_t curVersion
, bool& stop
)) const;
202 bool canBePlacedInDyldCache(const char* path
, void (^failureReason
)(const char*)) const;
203 bool canBeFairPlayEncrypted() const;
204 bool isFairPlayEncrypted(uint32_t& textOffset
, uint32_t& size
) const;
205 bool allowsAlternatePlatform() const;
206 bool hasChainedFixups() const;
207 void forDyldEnv(void (^callback
)(const char* envVar
, bool& stop
)) const;
208 bool enforceCompatVersion() const;
216 uint64_t sizeOfSections
;
218 uint32_t loadCommandOffset
;
219 uint32_t protections
;
220 uint32_t textRelocs
: 1, // segment has text relocs (i386 only)
222 isProtected
: 1, // segment is protected
225 bool readable() const { return protections
& VM_PROT_READ
; }
226 bool writable() const { return protections
& VM_PROT_WRITE
; }
227 bool executable() const { return protections
& VM_PROT_EXECUTE
; }
235 const char* sectName
;
236 uint32_t sectFileOffset
;
238 uint32_t sectAlignP2
;
243 void forEachSegment(void (^callback
)(const SegmentInfo
& info
, bool& stop
)) const;
244 void forEachSection(void (^callback
)(const SectionInfo
& sectInfo
, bool malformedSectionRange
, bool& stop
)) const;
247 bool hasMachOBigEndianMagic() const;
248 void forEachLoadCommand(Diagnostics
& diag
, void (^callback
)(const load_command
* cmd
, bool& stop
)) const;
249 bool hasLoadCommand(uint32_t) const;
251 const encryption_info_command
* findFairPlayEncryptionLoadCommand() const;
259 static const ArchInfo _s_archInfos
[];
265 uint32_t loadCommand
;
267 static const PlatformInfo _s_platformInfos
[];
273 #endif /* MachOFile_h */