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@
24 #ifndef MachOAnalyzer_h
25 #define MachOAnalyzer_h
28 #define BIND_SPECIAL_DYLIB_WEAK_DEF_COALESCE (-3)
30 #include "MachOLoaded.h"
31 #include "ClosureFileSystem.h"
35 // Extra functionality on loaded mach-o files only used during closure building
36 struct VIS_HIDDEN MachOAnalyzer
: public MachOLoaded
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
);
41 bool validMachOForArchAndPlatform(Diagnostics
& diag
, size_t mappedSize
, const char* path
, const char* reqArchName
, Platform reqPlatform
) const;
42 uint64_t mappedSize() 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;
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;
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;
87 void validateDyldCacheDylib(Diagnostics
& diag
, const char* path
) const;
90 const MachOAnalyzer
* remapIfZeroFill(Diagnostics
& diag
, const closure::FileSystem
& fileSystem
, closure::LoadedFileInfo
& info
) const;
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
;
108 uint64_t writable
: 1,
110 textRelocsAllowed
: 1, // segment supports text relocs (i386 only)
114 enum class Malformed
{ linkeditOrder
, linkeditAlignment
, dyldInfoAndlocalRelocs
};
115 bool enforceFormat(Malformed
) const;
117 const uint8_t* getContentForVMAddr(const LayoutInfo
& info
, uint64_t vmAddr
) const;
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;
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;
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;
162 #endif /* MachOAnalyzer_h */