]> git.saurik.com Git - apple/dyld.git/blob - interlinked-dylibs/Manifest.h
dyld-433.5.tar.gz
[apple/dyld.git] / interlinked-dylibs / Manifest.h
1 //
2 // Manifest.h
3 // dyld
4 //
5 // Created by Louis Gerbarg on 7/23/15.
6 //
7 //
8
9 #ifndef Manifest_h
10 #define Manifest_h
11
12 #include <map>
13 #include <set>
14 #include <string>
15 #include <vector>
16
17 #include <unordered_map>
18 #include <unordered_set>
19
20 #include <assert.h>
21
22 struct MachOProxy;
23
24 extern void terminate(const char* format, ...) __printflike(1, 2) __attribute__((noreturn));
25 extern std::string toolDir();
26
27 struct SharedCache;
28 struct Manifest;
29
30 struct Manifest {
31 struct Project {
32 std::vector<std::string> sources;
33 };
34
35 struct File {
36 MachOProxy* proxy;
37
38 File( MachOProxy* P ) : proxy( P ) {}
39 };
40
41 struct Anchor {
42 ImageIdentifier identifier;
43 bool required;
44 Anchor( const ImageIdentifier& I ) : identifier( I ) {}
45 };
46
47 struct SegmentInfo {
48 std::string name;
49 uint64_t startAddr;
50 uint64_t endAddr;
51 };
52
53 struct SegmentInfoHasher {
54 std::size_t operator()(const SegmentInfo &x) const {
55 return std::hash<std::string>()(x.name) ^ std::hash<uint64_t>()(x.startAddr) ^ std::hash<uint64_t>()(x.endAddr);
56 }
57 };
58
59 struct CacheInfo {
60 std::vector<SegmentInfo> regions;
61 std::string cdHash;
62 };
63
64 struct DylibInfo {
65 bool included;
66 std::string exclusionInfo;
67 UUID uuid;
68 std::string installname;
69 std::vector<SegmentInfo> segments;
70 DylibInfo(void) : included(true) {}
71 };
72
73 struct Results {
74 std::string failure;
75 std::map<ImageIdentifier, DylibInfo> dylibs;
76 std::vector<std::string> warnings;
77 CacheInfo developmentCache;
78 CacheInfo productionCache;
79 DylibInfo& dylibForInstallname(const std::string& installname)
80 {
81 auto i = find_if(dylibs.begin(), dylibs.end(), [&installname](std::pair<ImageIdentifier, DylibInfo> d) { return d.second.installname == installname; });
82 assert(i != dylibs.end());
83 return i->second;
84 }
85 void exclude(MachOProxy* proxy, const std::string& reason);
86 };
87
88 struct Architecture {
89 std::vector<Anchor> anchors;
90 mutable Results results;
91
92 bool operator==(const Architecture& O) const
93 {
94 for (auto& dylib : results.dylibs) {
95 if (dylib.second.included) {
96 auto Odylib = O.results.dylibs.find(dylib.first);
97 if (Odylib == O.results.dylibs.end()
98 || Odylib->second.included == false
99 || Odylib->second.uuid != dylib.second.uuid)
100 return false;
101 }
102 }
103
104 for (const auto& Odylib : O.results.dylibs) {
105 if (Odylib.second.included) {
106 auto dylib = results.dylibs.find(Odylib.first);
107 if (dylib == results.dylibs.end()
108 || dylib->second.included == false
109 || dylib->second.uuid != Odylib.second.uuid)
110 return false;
111 }
112 }
113
114 return true;
115 }
116
117 bool operator!=(const Architecture& other) const { return !(*this == other); }
118 };
119
120 struct Configuration {
121 std::string platformName;
122 std::string metabomTag;
123 std::set<std::string> metabomExcludeTags;
124 std::set<std::string> metabomRestrictTags;
125 std::set<std::string> restrictedInstallnames;
126 std::map<std::string, Architecture> architectures;
127
128 bool operator==(const Configuration& O) const
129 {
130 return architectures == O.architectures;
131 }
132
133 bool operator!=(const Configuration& other) const { return !(*this == other); }
134
135 const Architecture& architecture(const std::string& architecture) const
136 {
137 assert(architectures.find(architecture) != architectures.end());
138 return architectures.find(architecture)->second;
139 }
140
141 void forEachArchitecture(std::function<void(const std::string& archName)> lambda)
142 {
143 for (const auto& architecutre : architectures) {
144 lambda(architecutre.first);
145 }
146 }
147 };
148
149 const std::map<std::string, Project>& projects()
150 {
151 return _projects;
152 }
153
154 const Configuration& configuration(const std::string& configuration) const
155 {
156 assert(_configurations.find(configuration) != _configurations.end());
157 return _configurations.find(configuration)->second;
158 }
159
160 void forEachConfiguration(std::function<void(const std::string& configName)> lambda)
161 {
162 for (const auto& configuration : _configurations) {
163 lambda(configuration.first);
164 }
165 }
166
167 void addProjectSource(const std::string& project, const std::string& source, bool first = false)
168 {
169 auto& sources = _projects[project].sources;
170 if (std::find(sources.begin(), sources.end(), source) == sources.end()) {
171 if (first) {
172 sources.insert(sources.begin(), source);
173 } else {
174 sources.push_back(source);
175 }
176 }
177 }
178
179 const std::string projectPath(const std::string& projectName)
180 {
181 auto project = _projects.find(projectName);
182 if (project == _projects.end())
183 return "";
184 if (project->second.sources.size() == 0)
185 return "";
186 return project->second.sources[0];
187 }
188
189
190 const bool empty(void) {
191 for (const auto& configuration : _configurations) {
192 if (configuration.second.architectures.size() != 0)
193 return false;
194 }
195 return true;
196 }
197
198 const std::string dylibOrderFile() const { return _dylibOrderFile; };
199 void setDylibOrderFile(const std::string& dylibOrderFile) { _dylibOrderFile = dylibOrderFile; };
200
201 const std::string dirtyDataOrderFile() const { return _dirtyDataOrderFile; };
202 void setDirtyDataOrderFile(const std::string& dirtyDataOrderFile) { _dirtyDataOrderFile = dirtyDataOrderFile; };
203
204 const std::string metabomFile() const { return _metabomFile; };
205 void setMetabomFile(const std::string& metabomFile) { _metabomFile = metabomFile; };
206
207 const std::string platform() const { return _platform; };
208 void setPlatform(const std::string& platform) { _platform = platform; };
209
210 const std::string& build() const { return _build; };
211 void setBuild(const std::string& build) { _build = build; };
212 const uint32_t version() const { return _manifestVersion; };
213 void setVersion(const uint32_t manifestVersion) { _manifestVersion = manifestVersion; };
214 bool normalized;
215
216 Manifest(void) {}
217 Manifest(const std::set<std::string>& archs, const std::string& overlayPath, const std::string& rootPath, const std::set<std::string>& paths);
218 #if BOM_SUPPORT
219 Manifest(const std::string& path);
220 Manifest(const std::string& path, const std::set<std::string>& overlays);
221 #endif
222 void write(const std::string& path);
223 void canonicalize(void);
224 void calculateClosure(bool enforeceRootless);
225 bool sameContentsAsCacheAtPath(const std::string& configuration, const std::string& architecture,
226 const std::string& path) const;
227 void remove(const std::string& config, const std::string& arch);
228 MachOProxy* removeLargestLeafDylib(const std::string& configuration, const std::string& architecture);
229 bool checkLinks();
230 void runConcurrently(dispatch_queue_t queue, dispatch_semaphore_t concurrencyLimitingSemaphore, std::function<void(const std::string configuration, const std::string architecture)> lambda);
231 bool filterForConfig(const std::string& configName);
232
233 private:
234 uint32_t _manifestVersion;
235 std::string _build;
236 std::string _dylibOrderFile;
237 std::string _dirtyDataOrderFile;
238 std::string _metabomFile;
239 std::string _platform;
240 std::map<std::string, Project> _projects;
241 std::map<std::string, Configuration> _configurations;
242 void removeDylib(MachOProxy* proxy, const std::string& reason, const std::string& configuration, const std::string& architecture,
243 std::unordered_set<ImageIdentifier>& processedIdentifiers);
244 void calculateClosure(const std::string& configuration, const std::string& architecture);
245 void canonicalizeDylib(const std::string& installname);
246 template <typename P>
247 void canonicalizeDylib(const std::string& installname, const uint8_t* p);
248 void addImplicitAliases(void);
249 MachOProxy* dylibProxy(const std::string& installname, const std::string& arch);
250 };
251
252
253 #endif /* Manifest_h */