]> git.saurik.com Git - apple/ld64.git/blame - src/ld/parsers/textstub_dylib_file.cpp
ld64-409.12.tar.gz
[apple/ld64.git] / src / ld / parsers / textstub_dylib_file.cpp
CommitLineData
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
39namespace textstub {
40namespace 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//
47template <typename A>
ec29ba20 48class File final : public generic::dylib::File<A>
eaf282aa 49{
ec29ba20
A
50 using Base = generic::dylib::File<A>;
51
eaf282aa 52public:
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
74private:
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
86template <> bool File<x86>::useSimulatorVariant() { return true; }
87template <> bool File<x86_64>::useSimulatorVariant() { return true; }
88template <typename A> bool File<A>::useSimulatorVariant() { return false; }
0a8dc3df 89
0a8dc3df 90
e456bf10
A
91static 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
136template <typename A>
137File<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
229template<typename A>
e456bf10 230void 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
320template <typename A>
0a8dc3df 321void 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
337template <typename A>
338void 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
344template <typename A>
345class Parser
346{
347public:
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
400static 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
429static 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//
460ld::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
478ld::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