]>
Commit | Line | Data |
---|---|---|
eaf282aa A |
1 | /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- |
2 | * | |
3 | * Copyright (c) 2015 Apple Inc. All rights reserved. | |
4 | * | |
5 | * @APPLE_LICENSE_HEADER_START@ | |
6 | * | |
7 | * This file contains Original Code and/or Modifications of Original Code | |
8 | * as defined in and that are subject to the Apple Public Source License | |
9 | * Version 2.0 (the 'License'). You may not use this file except in | |
10 | * compliance with the License. Please obtain a copy of the License at | |
11 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
12 | * file. | |
13 | * | |
14 | * The Original Code and all software distributed under the License are | |
15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
18 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
19 | * Please see the License for the specific language governing rights and | |
20 | * limitations under the License. | |
21 | * | |
22 | * @APPLE_LICENSE_HEADER_END@ | |
23 | */ | |
24 | ||
25 | ||
26 | #include <sys/param.h> | |
27 | #include <sys/mman.h> | |
0a8dc3df | 28 | #include <tapi/tapi.h> |
eaf282aa A |
29 | #include <vector> |
30 | ||
31 | #include "Architectures.hpp" | |
f410558f | 32 | #include "Bitcode.hpp" |
eaf282aa A |
33 | #include "MachOFileAbstraction.hpp" |
34 | #include "MachOTrie.hpp" | |
ec29ba20 | 35 | #include "generic_dylib_file.hpp" |
eaf282aa A |
36 | #include "textstub_dylib_file.hpp" |
37 | ||
eaf282aa A |
38 | |
39 | namespace textstub { | |
40 | namespace dylib { | |
41 | ||
eaf282aa A |
42 | // |
43 | // The reader for a dylib extracts all exported symbols names from the memory-mapped | |
44 | // dylib, builds a hash table, then unmaps the file. This is an important memory | |
45 | // savings for large dylibs. | |
46 | // | |
47 | template <typename A> | |
ec29ba20 | 48 | class File final : public generic::dylib::File<A> |
eaf282aa | 49 | { |
ec29ba20 A |
50 | using Base = generic::dylib::File<A>; |
51 | ||
eaf282aa | 52 | public: |
f410558f A |
53 | File(const char* path, const uint8_t* fileContent, uint64_t fileLength, const Options *opts, |
54 | time_t mTime, ld::File::Ordinal ordinal, bool linkingFlatNamespace, | |
55 | bool linkingMainExecutable, bool hoistImplicitPublicDylibs, | |
e456bf10 | 56 | const ld::VersionSet& platforms, bool allowWeakImports, |
f410558f A |
57 | cpu_type_t cpuType, cpu_subtype_t cpuSubType, bool enforceDylibSubtypesMatch, |
58 | bool allowSimToMacOSX, bool addVers, bool buildingForSimulator, | |
e456bf10 A |
59 | bool logAllFiles, const char* installPath, bool indirectDylib, |
60 | bool ignoreMismatchPlatform, bool usingBitcode); | |
61 | File(tapi::LinkerInterfaceFile* file, const char *path, const Options *opts, | |
eaf282aa | 62 | time_t mTime, ld::File::Ordinal ordinal, bool linkingFlatNamespace, |
0a8dc3df | 63 | bool linkingMainExecutable, bool hoistImplicitPublicDylibs, |
e456bf10 | 64 | const ld::VersionSet& platforms, bool allowWeakImports, |
0a8dc3df | 65 | cpu_type_t cpuType, cpu_subtype_t cpuSubType, bool enforceDylibSubtypesMatch, |
eaf282aa | 66 | bool allowSimToMacOSX, bool addVers, bool buildingForSimulator, |
e456bf10 A |
67 | bool logAllFiles, const char* installPath, bool indirectDylib, |
68 | bool ignoreMismatchPlatform, bool usingBitcode); | |
ec29ba20 | 69 | virtual ~File() noexcept {} |
f410558f A |
70 | |
71 | // overrides of generic::dylib::File | |
72 | virtual void processIndirectLibraries(ld::dylib::File::DylibHandler*, bool addImplicitDylibs) override final; | |
eaf282aa A |
73 | |
74 | private: | |
e456bf10 A |
75 | void init(tapi::LinkerInterfaceFile* file, const Options *opts, bool buildingForSimulator, |
76 | bool indirectDylib, bool linkingFlatNamespace, bool linkingMainExecutable, | |
77 | const char *path, const ld::VersionSet& platforms, const char *targetInstallPath, | |
78 | bool ignoreMismatchPlatform, bool usingBitcode); | |
79 | void buildExportHashTable(const tapi::LinkerInterfaceFile* file); | |
80 | static bool useSimulatorVariant(); | |
f410558f | 81 | |
e456bf10 A |
82 | const Options* _opts; |
83 | tapi::LinkerInterfaceFile* _interface; | |
ec29ba20 | 84 | }; |
eaf282aa | 85 | |
e456bf10 A |
86 | template <> bool File<x86>::useSimulatorVariant() { return true; } |
87 | template <> bool File<x86_64>::useSimulatorVariant() { return true; } | |
88 | template <typename A> bool File<A>::useSimulatorVariant() { return false; } | |
0a8dc3df | 89 | |
0a8dc3df | 90 | |
e456bf10 A |
91 | static ld::VersionSet mapPlatform(tapi::Platform platform, bool useSimulatorVariant) { |
92 | ld::VersionSet platforms; | |
0a8dc3df A |
93 | switch (platform) { |
94 | case tapi::Platform::Unknown: | |
e456bf10 | 95 | break; |
0a8dc3df | 96 | case tapi::Platform::OSX: |
e456bf10 A |
97 | platforms.add({ld::kPlatform_macOS, 0}); |
98 | break; | |
0a8dc3df | 99 | case tapi::Platform::iOS: |
e456bf10 A |
100 | if (useSimulatorVariant) |
101 | platforms.add({ld::kPlatform_iOSSimulator, 0}); | |
102 | else | |
103 | platforms.add({ld::kPlatform_iOS, 0}); | |
104 | break; | |
0a8dc3df | 105 | case tapi::Platform::watchOS: |
e456bf10 A |
106 | if (useSimulatorVariant) |
107 | platforms.add({ld::kPlatform_watchOSSimulator, 0}); | |
108 | else | |
109 | platforms.add({ld::kPlatform_watchOS, 0}); | |
110 | break; | |
0a8dc3df | 111 | case tapi::Platform::tvOS: |
e456bf10 A |
112 | if (useSimulatorVariant) |
113 | platforms.add({ld::kPlatform_tvOSSimulator, 0}); | |
114 | else | |
115 | platforms.add({ld::kPlatform_tvOS, 0}); | |
116 | break; | |
bee7e226 A |
117 | #if ((TAPI_API_VERSION_MAJOR == 1 && TAPI_API_VERSION_MINOR >= 2) || (TAPI_API_VERSION_MAJOR > 1)) |
118 | case tapi::Platform::bridgeOS: | |
e456bf10 A |
119 | platforms.add({ld::kPlatform_bridgeOS, 0}); |
120 | break; | |
121 | #endif | |
122 | #if ((TAPI_API_VERSION_MAJOR == 1 && TAPI_API_VERSION_MINOR >= 4) || (TAPI_API_VERSION_MAJOR > 1)) | |
123 | case tapi::Platform::iOSMac: | |
124 | platforms.add({ld::kPlatform_iOSMac, 0}); | |
125 | break; | |
126 | case tapi::Platform::zippered: | |
127 | platforms.add({ld::kPlatform_macOS, 0}); | |
128 | platforms.add({ld::kPlatform_iOSMac, 0}); | |
129 | break; | |
bee7e226 | 130 | #endif |
0a8dc3df A |
131 | } |
132 | ||
e456bf10 | 133 | return platforms; |
0a8dc3df A |
134 | } |
135 | ||
e456bf10 A |
136 | template <typename A> |
137 | File<A>::File(const char* path, const uint8_t* fileContent, uint64_t fileLength, const Options *opts, | |
138 | time_t mTime, ld::File::Ordinal ord, bool linkingFlatNamespace, | |
139 | bool linkingMainExecutable, bool hoistImplicitPublicDylibs, const ld::VersionSet& platforms, | |
140 | bool allowWeakImports, cpu_type_t cpuType, cpu_subtype_t cpuSubType, | |
141 | bool enforceDylibSubtypesMatch, bool allowSimToMacOSX, bool addVers, | |
142 | bool buildingForSimulator, bool logAllFiles, const char* targetInstallPath, | |
143 | bool indirectDylib, bool ignoreMismatchPlatform, bool usingBitcode) | |
144 | : Base(strdup(path), mTime, ord, platforms, allowWeakImports, linkingFlatNamespace, | |
145 | hoistImplicitPublicDylibs, allowSimToMacOSX, addVers) | |
eaf282aa | 146 | { |
e456bf10 | 147 | std::unique_ptr<tapi::LinkerInterfaceFile> file; |
82b4b32b | 148 | std::string errorMessage; |
e456bf10 A |
149 | __block uint32_t linkMinOSVersion = 0; |
150 | //FIXME handle this correctly once we have multi-platfrom TAPI | |
151 | platforms.forEach(^(ld::Platform platform, uint32_t version, bool &stop) { | |
152 | if (linkMinOSVersion == 0) | |
153 | linkMinOSVersion = version; | |
154 | if (platform == ld::kPlatform_macOS) | |
155 | linkMinOSVersion = version; | |
156 | }); | |
82b4b32b A |
157 | |
158 | // <rdar://problem/29038544> Support $ld$weak symbols in .tbd files | |
f410558f | 159 | #if ((TAPI_API_VERSION_MAJOR == 1 && TAPI_API_VERSION_MINOR >= 3) || (TAPI_API_VERSION_MAJOR > 1)) |
82b4b32b | 160 | // Check if the library supports the new create API. |
f410558f A |
161 | if (tapi::APIVersion::isAtLeast(1, 3)) { |
162 | tapi::ParsingFlags flags = tapi::ParsingFlags::None; | |
163 | if (enforceDylibSubtypesMatch) | |
164 | flags |= tapi::ParsingFlags::ExactCpuSubType; | |
165 | ||
166 | if (!allowWeakImports) | |
167 | flags |= tapi::ParsingFlags::DisallowWeakImports; | |
168 | ||
e456bf10 | 169 | _interface = tapi::LinkerInterfaceFile::create( |
f410558f | 170 | path, cpuType, cpuSubType, flags, |
e456bf10 | 171 | tapi::PackedVersion32(linkMinOSVersion), errorMessage); |
f410558f A |
172 | } else |
173 | #endif | |
174 | #if ((TAPI_API_VERSION_MAJOR == 1 && TAPI_API_VERSION_MINOR >= 1) || (TAPI_API_VERSION_MAJOR > 1)) | |
82b4b32b A |
175 | if (tapi::APIVersion::isAtLeast(1, 1)) { |
176 | tapi::ParsingFlags flags = tapi::ParsingFlags::None; | |
177 | if (enforceDylibSubtypesMatch) | |
178 | flags |= tapi::ParsingFlags::ExactCpuSubType; | |
179 | ||
180 | if (!allowWeakImports) | |
181 | flags |= tapi::ParsingFlags::DisallowWeakImports; | |
182 | ||
e456bf10 | 183 | _interface = tapi::LinkerInterfaceFile::create( |
82b4b32b | 184 | path, fileContent, fileLength, cpuType, cpuSubType, flags, |
e456bf10 | 185 | tapi::PackedVersion32(linkMinOSVersion), errorMessage); |
f410558f A |
186 | } else |
187 | #endif | |
188 | #if (TAPI_API_VERSION_MAJOR >= 1) | |
189 | { | |
82b4b32b | 190 | auto matchingType = enforceDylibSubtypesMatch ? |
f410558f | 191 | tapi::CpuSubTypeMatching::Exact : tapi::CpuSubTypeMatching::ABI_Compatible; |
82b4b32b | 192 | |
e456bf10 | 193 | _interface = tapi::LinkerInterfaceFile::create( |
82b4b32b | 194 | path, fileContent, fileLength, cpuType, cpuSubType, matchingType, |
e456bf10 | 195 | tapi::PackedVersion32(linkMinOSVersion), errorMessage); |
82b4b32b | 196 | } |
82b4b32b | 197 | #endif |
0a8dc3df | 198 | |
f410558f | 199 | if (!_interface) |
0a8dc3df A |
200 | throw strdup(errorMessage.c_str()); |
201 | ||
202 | // unmap file - it is no longer needed. | |
203 | munmap((caddr_t)fileContent, fileLength); | |
ec29ba20 | 204 | |
eaf282aa A |
205 | // write out path for -t option |
206 | if ( logAllFiles ) | |
207 | printf("%s\n", path); | |
208 | ||
e456bf10 A |
209 | init(_interface, opts, buildingForSimulator, indirectDylib, linkingFlatNamespace, |
210 | linkingMainExecutable, path, platforms, targetInstallPath, ignoreMismatchPlatform, usingBitcode); | |
f410558f A |
211 | } |
212 | ||
213 | template<typename A> | |
e456bf10 | 214 | File<A>::File(tapi::LinkerInterfaceFile* file, const char* path, const Options *opts, |
f410558f A |
215 | time_t mTime, ld::File::Ordinal ordinal, bool linkingFlatNamespace, |
216 | bool linkingMainExecutable, bool hoistImplicitPublicDylibs, | |
e456bf10 | 217 | const ld::VersionSet& platforms, bool allowWeakImports, |
f410558f A |
218 | cpu_type_t cpuType, cpu_subtype_t cpuSubType, bool enforceDylibSubtypesMatch, |
219 | bool allowSimToMacOSX, bool addVers, bool buildingForSimulator, | |
e456bf10 A |
220 | bool logAllFiles, const char* installPath, bool indirectDylib, |
221 | bool ignoreMismatchPlatform, bool usingBitcode) | |
222 | : Base(strdup(path), mTime, ordinal, platforms, allowWeakImports, linkingFlatNamespace, | |
223 | hoistImplicitPublicDylibs, allowSimToMacOSX, addVers), _interface(file) | |
f410558f | 224 | { |
e456bf10 A |
225 | init(_interface, opts, buildingForSimulator, indirectDylib, linkingFlatNamespace, |
226 | linkingMainExecutable, path, platforms, installPath, ignoreMismatchPlatform, usingBitcode); | |
f410558f A |
227 | } |
228 | ||
229 | template<typename A> | |
e456bf10 | 230 | void File<A>::init(tapi::LinkerInterfaceFile* file, const Options *opts, bool buildingForSimulator, |
f410558f | 231 | bool indirectDylib, bool linkingFlatNamespace, bool linkingMainExecutable, |
e456bf10 A |
232 | const char *path, const ld::VersionSet& platforms, const char *targetInstallPath, |
233 | bool ignoreMismatchPlatform, bool usingBitcode) { | |
f410558f | 234 | _opts = opts; |
0a8dc3df A |
235 | this->_bitcode = std::unique_ptr<ld::Bitcode>(new ld::Bitcode(nullptr, 0)); |
236 | this->_noRexports = !file->hasReexportedLibraries(); | |
237 | this->_hasWeakExports = file->hasWeakDefinedExports(); | |
238 | this->_dylibInstallPath = strdup(file->getInstallName().c_str()); | |
239 | this->_installPathOverride = file->isInstallNameVersionSpecific(); | |
240 | this->_dylibCurrentVersion = file->getCurrentVersion(); | |
241 | this->_dylibCompatibilityVersion = file->getCompatibilityVersion(); | |
242 | this->_swiftVersion = file->getSwiftVersion(); | |
0a8dc3df A |
243 | this->_parentUmbrella = file->getParentFrameworkName().empty() ? nullptr : strdup(file->getParentFrameworkName().c_str()); |
244 | this->_appExtensionSafe = file->isApplicationExtensionSafe(); | |
ec29ba20 A |
245 | |
246 | // if framework, capture framework name | |
247 | const char* lastSlash = strrchr(this->_dylibInstallPath, '/'); | |
248 | if ( lastSlash != NULL ) { | |
249 | const char* leafName = lastSlash+1; | |
250 | char frname[strlen(leafName)+32]; | |
251 | strcpy(frname, leafName); | |
252 | strcat(frname, ".framework/"); | |
253 | ||
254 | if ( strstr(this->_dylibInstallPath, frname) != NULL ) | |
255 | this->_frameworkName = leafName; | |
256 | } | |
f410558f | 257 | |
0a8dc3df A |
258 | for (auto &client : file->allowableClients()) |
259 | this->_allowableClients.push_back(strdup(client.c_str())); | |
f410558f | 260 | |
eaf282aa | 261 | // <rdar://problem/20659505> [TAPI] Don't hoist "public" (in /usr/lib/) dylibs that should not be directly linked |
0a8dc3df | 262 | this->_hasPublicInstallName = file->hasAllowableClients() ? false : this->isPublicLocation(file->getInstallName().c_str()); |
f410558f | 263 | |
0a8dc3df A |
264 | for (const auto &client : file->allowableClients()) |
265 | this->_allowableClients.emplace_back(strdup(client.c_str())); | |
e456bf10 A |
266 | |
267 | ld::VersionSet lcPlatforms = mapPlatform(file->getPlatform(), useSimulatorVariant()); | |
268 | this->_platforms = lcPlatforms; | |
269 | ||
270 | // check cross-linking | |
271 | platforms.forEach(^(ld::Platform platform, uint32_t version, bool &stop) { | |
272 | if (!lcPlatforms.contains(platform) ) { | |
273 | this->_wrongOS = true; | |
274 | if ( this->_addVersionLoadCommand && !indirectDylib && !ignoreMismatchPlatform ) { | |
275 | if (buildingForSimulator && !this->_allowSimToMacOSXLinking) { | |
276 | if ( usingBitcode ) | |
277 | throwf("building for %s simulator, but linking against dylib built for %s,", | |
278 | platforms.to_str().c_str(), lcPlatforms.to_str().c_str()); | |
279 | else | |
280 | warning("URGENT: building for %s simulator, but linking against dylib (%s) built for %s. " | |
281 | "Note: This will be an error in the future.", | |
282 | platforms.to_str().c_str(), path, lcPlatforms.to_str().c_str()); | |
283 | } | |
eaf282aa | 284 | } else { |
e456bf10 A |
285 | if ( usingBitcode ) |
286 | throwf("building for %s, but linking against dylib built for %s,", | |
287 | platforms.to_str().c_str(), lcPlatforms.to_str().c_str()); | |
288 | else if ( (getenv("RC_XBS") != NULL) && (getenv("RC_BUILDIT") == NULL) ) // FIXME: remove after platform bringup | |
289 | warning("URGENT: building for %s, but linking against dylib (%s) built for %s. " | |
290 | "Note: This will be an error in the future.", | |
291 | platforms.to_str().c_str(), path, lcPlatforms.to_str().c_str()); | |
eaf282aa A |
292 | } |
293 | } | |
e456bf10 | 294 | }); |
f410558f | 295 | |
0a8dc3df A |
296 | for (const auto& reexport : file->reexportedLibraries()) { |
297 | const char *path = strdup(reexport.c_str()); | |
ec29ba20 A |
298 | if ( (targetInstallPath == nullptr) || (strcmp(targetInstallPath, path) != 0) ) |
299 | this->_dependentDylibs.emplace_back(path, true); | |
eaf282aa | 300 | } |
f410558f | 301 | |
0a8dc3df A |
302 | for (const auto& symbol : file->ignoreExports()) |
303 | this->_ignoreExports.insert(strdup(symbol.c_str())); | |
f410558f | 304 | |
0a8dc3df A |
305 | // if linking flat and this is a flat dylib, create one atom that references all imported symbols. |
306 | if ( linkingFlatNamespace && linkingMainExecutable && (file->hasTwoLevelNamespace() == false) ) { | |
307 | std::vector<const char*> importNames; | |
308 | importNames.reserve(file->undefineds().size()); | |
309 | // We do not need to strdup the name, because that will be done by the | |
310 | // ImportAtom constructor. | |
311 | for (const auto &sym : file->undefineds()) | |
312 | importNames.emplace_back(sym.getName().c_str()); | |
313 | this->_importAtom = new generic::dylib::ImportAtom<A>(*this, importNames); | |
314 | } | |
f410558f | 315 | |
0a8dc3df | 316 | // build hash table |
f410558f | 317 | buildExportHashTable(file); |
eaf282aa A |
318 | } |
319 | ||
320 | template <typename A> | |
0a8dc3df | 321 | void File<A>::buildExportHashTable(const tapi::LinkerInterfaceFile* file) { |
ec29ba20 | 322 | if (this->_s_logHashtable ) |
eaf282aa A |
323 | fprintf(stderr, "ld: building hashtable from text-stub info in %s\n", this->path()); |
324 | ||
0a8dc3df A |
325 | for (const auto &sym : file->exports()) { |
326 | const char* name = sym.getName().c_str(); | |
327 | bool weakDef = sym.isWeakDefined(); | |
328 | bool tlv = sym.isThreadLocalValue(); | |
eaf282aa | 329 | |
0a8dc3df A |
330 | typename Base::AtomAndWeak bucket = { nullptr, weakDef, tlv, 0 }; |
331 | if ( this->_s_logHashtable ) | |
332 | fprintf(stderr, " adding %s to hash table for %s\n", name, this->path()); | |
333 | this->_atoms[strdup(name)] = bucket; | |
eaf282aa | 334 | } |
eaf282aa A |
335 | } |
336 | ||
f410558f A |
337 | template <typename A> |
338 | void File<A>::processIndirectLibraries(ld::dylib::File::DylibHandler* handler, bool addImplicitDylibs) { | |
339 | if (_interface) | |
e456bf10 | 340 | _opts->addTAPIInterface(_interface, this->path()); |
f410558f A |
341 | Base::processIndirectLibraries(handler, addImplicitDylibs); |
342 | } | |
343 | ||
eaf282aa A |
344 | template <typename A> |
345 | class Parser | |
346 | { | |
347 | public: | |
ec29ba20 | 348 | using P = typename A::P; |
eaf282aa | 349 | |
0a8dc3df A |
350 | static ld::dylib::File* parse(const char* path, const uint8_t* fileContent, |
351 | uint64_t fileLength, time_t mTime, | |
352 | ld::File::Ordinal ordinal, const Options& opts, | |
e456bf10 | 353 | bool indirectDylib, cpu_type_t architecture, cpu_subtype_t subArchitecture) |
ec29ba20 | 354 | { |
f410558f | 355 | return new File<A>(path, fileContent, fileLength, &opts, mTime, ordinal, |
eaf282aa | 356 | opts.flatNamespace(), |
0a8dc3df | 357 | opts.linkingMainExecutable(), |
eaf282aa | 358 | opts.implicitlyLinkIndirectPublicDylibs(), |
e456bf10 | 359 | opts.platforms(), |
0a8dc3df | 360 | opts.allowWeakImports(), |
e456bf10 A |
361 | architecture, |
362 | subArchitecture, | |
0a8dc3df | 363 | opts.enforceDylibSubtypesMatch(), |
eaf282aa A |
364 | opts.allowSimulatorToLinkWithMacOSX(), |
365 | opts.addVersionLoadCommand(), | |
366 | opts.targetIOSSimulator(), | |
367 | opts.logAllFiles(), | |
368 | opts.installPath(), | |
e456bf10 A |
369 | indirectDylib, |
370 | opts.outputKind() == Options::kPreload, | |
371 | opts.bundleBitcode()); | |
eaf282aa | 372 | } |
f410558f | 373 | |
e456bf10 | 374 | static ld::dylib::File* parse(const char* path, tapi::LinkerInterfaceFile* file, time_t mTime, |
f410558f | 375 | ld::File::Ordinal ordinal, const Options& opts, |
e456bf10 | 376 | bool indirectDylib, cpu_type_t architecture, cpu_subtype_t subArchitecture) |
f410558f | 377 | { |
e456bf10 | 378 | return new File<A>(file, path, &opts, mTime, ordinal, |
f410558f A |
379 | opts.flatNamespace(), |
380 | opts.linkingMainExecutable(), | |
381 | opts.implicitlyLinkIndirectPublicDylibs(), | |
e456bf10 | 382 | opts.platforms(), |
f410558f | 383 | opts.allowWeakImports(), |
e456bf10 A |
384 | architecture, |
385 | subArchitecture, | |
f410558f A |
386 | opts.enforceDylibSubtypesMatch(), |
387 | opts.allowSimulatorToLinkWithMacOSX(), | |
388 | opts.addVersionLoadCommand(), | |
389 | opts.targetIOSSimulator(), | |
390 | opts.logAllFiles(), | |
391 | opts.installPath(), | |
e456bf10 A |
392 | indirectDylib, |
393 | opts.outputKind() == Options::kPreload, | |
394 | opts.bundleBitcode()); | |
f410558f A |
395 | } |
396 | ||
eaf282aa A |
397 | }; |
398 | ||
0a8dc3df | 399 | |
e456bf10 A |
400 | static ld::dylib::File* parseAsArchitecture(const uint8_t* fileContent, uint64_t fileLength, const char* path, |
401 | time_t modTime, ld::File::Ordinal ordinal, const Options& opts, | |
402 | bool bundleLoader, bool indirectDylib, | |
403 | cpu_type_t architecture, cpu_subtype_t subArchitecture) | |
404 | { | |
405 | switch ( architecture ) { | |
eaf282aa A |
406 | #if SUPPORT_ARCH_x86_64 |
407 | case CPU_TYPE_X86_64: | |
e456bf10 | 408 | return Parser<x86_64>::parse(path, fileContent, fileLength, modTime, ordinal, opts, indirectDylib, architecture, subArchitecture); |
eaf282aa A |
409 | #endif |
410 | #if SUPPORT_ARCH_i386 | |
411 | case CPU_TYPE_I386: | |
e456bf10 | 412 | return Parser<x86>::parse(path, fileContent, fileLength, modTime, ordinal, opts, indirectDylib, architecture, subArchitecture); |
eaf282aa A |
413 | #endif |
414 | #if SUPPORT_ARCH_arm_any | |
415 | case CPU_TYPE_ARM: | |
e456bf10 | 416 | return Parser<arm>::parse(path, fileContent, fileLength, modTime, ordinal, opts, indirectDylib, architecture, subArchitecture); |
eaf282aa A |
417 | #endif |
418 | #if SUPPORT_ARCH_arm64 | |
419 | case CPU_TYPE_ARM64: | |
e456bf10 | 420 | return Parser<arm64>::parse(path, fileContent, fileLength, modTime, ordinal, opts, indirectDylib, architecture, subArchitecture); |
eaf282aa | 421 | #endif |
e456bf10 A |
422 | default: |
423 | throwf("unsupported architecture for tbd file"); | |
eaf282aa | 424 | } |
e456bf10 | 425 | assert(0 && "function should return valid pointer or throw"); |
eaf282aa | 426 | } |
f410558f | 427 | |
e456bf10 A |
428 | |
429 | static ld::dylib::File *parseAsArchitecture(const char *path, tapi::LinkerInterfaceFile* file, time_t modTime, | |
430 | ld::File::Ordinal ordinal, const Options& opts, bool indirectDylib, | |
431 | cpu_type_t architecture, cpu_subtype_t subArchitecture) | |
432 | { | |
433 | switch ( architecture ) { | |
f410558f A |
434 | #if SUPPORT_ARCH_x86_64 |
435 | case CPU_TYPE_X86_64: | |
e456bf10 | 436 | return Parser<x86_64>::parse(path, file, modTime, ordinal, opts, indirectDylib, architecture, subArchitecture); |
f410558f A |
437 | #endif |
438 | #if SUPPORT_ARCH_i386 | |
439 | case CPU_TYPE_I386: | |
e456bf10 | 440 | return Parser<x86>::parse(path, file, modTime, ordinal, opts, indirectDylib, architecture, subArchitecture); |
f410558f A |
441 | #endif |
442 | #if SUPPORT_ARCH_arm_any | |
443 | case CPU_TYPE_ARM: | |
e456bf10 | 444 | return Parser<arm>::parse(path, file, modTime, ordinal, opts, indirectDylib, architecture, subArchitecture); |
f410558f A |
445 | #endif |
446 | #if SUPPORT_ARCH_arm64 | |
447 | case CPU_TYPE_ARM64: | |
e456bf10 | 448 | return Parser<arm64>::parse(path, file, modTime, ordinal, opts, indirectDylib, architecture, subArchitecture); |
f410558f | 449 | #endif |
e456bf10 A |
450 | default: |
451 | throwf("unsupported architecture for tbd file"); | |
f410558f | 452 | } |
e456bf10 A |
453 | assert(0 && "function should return valid pointer or throw"); |
454 | } | |
f410558f | 455 | |
e456bf10 A |
456 | |
457 | // | |
458 | // main function used by linker to instantiate ld::Files | |
459 | // | |
460 | ld::dylib::File* parse(const uint8_t* fileContent, uint64_t fileLength, const char* path, | |
461 | time_t modtime, const Options& opts, ld::File::Ordinal ordinal, | |
462 | bool bundleLoader, bool indirectDylib) | |
463 | { | |
464 | if (!tapi::LinkerInterfaceFile::isSupported(path, fileContent, fileLength)) | |
465 | return nullptr; | |
466 | ||
467 | try { | |
468 | return parseAsArchitecture(fileContent, fileLength, path, modtime, ordinal, opts, bundleLoader, indirectDylib, opts.architecture(), opts.subArchitecture()); | |
469 | } catch (...) { | |
470 | if (!opts.fallbackArchitecture()) | |
471 | throw; | |
472 | } | |
473 | ||
474 | warning("architecture %s not present in TBD %s, attempting fallback", opts.architectureName(), path); | |
475 | return parseAsArchitecture(fileContent, fileLength, path, modtime, ordinal, opts, bundleLoader, indirectDylib, opts.fallbackArchitecture(), opts.fallbackSubArchitecture()); | |
f410558f A |
476 | } |
477 | ||
e456bf10 A |
478 | ld::dylib::File *parse(const char *path, tapi::LinkerInterfaceFile* file, time_t modTime, |
479 | ld::File::Ordinal ordinal, const Options& opts, bool indirectDylib) { | |
480 | try { | |
481 | return parseAsArchitecture(path, file, modTime, ordinal, opts, indirectDylib, opts.architecture(), opts.subArchitecture()); | |
482 | } catch (...) { | |
483 | if (!opts.fallbackArchitecture()) | |
484 | throw; | |
485 | } | |
486 | ||
487 | warning("architecture %s not present in TBD %s, attempting fallback", opts.architectureName(), path); | |
488 | return parseAsArchitecture(path, file, modTime, ordinal, opts, indirectDylib, opts.fallbackArchitecture(), opts.fallbackSubArchitecture()); | |
489 | } | |
f410558f | 490 | |
eaf282aa A |
491 | } // namespace dylib |
492 | } // namespace textstub |