1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2005-2011 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
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
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.
22 * @APPLE_LICENSE_HEADER_END@
29 #include <sys/param.h>
37 #include <unordered_map>
38 #include <unordered_set>
40 #include "Architectures.hpp"
41 #include "Bitcode.hpp"
42 #include "MachOFileAbstraction.hpp"
43 #include "MachOTrie.hpp"
44 #include "macho_dylib_file.h"
45 #include "../code-sign-blobs/superblob.h"
52 template <typename A
> class File
;
56 // An ExportAtom has no content. It exists so that the linker can track which imported
57 // symbols came from which dynamic libraries.
60 class ExportAtom
: public ld::Atom
63 ExportAtom(const File
<A
>& f
, const char* nm
, bool weakDef
,
64 bool tlv
, typename
A::P::uint_t address
)
65 : ld::Atom(f
._importProxySection
, ld::Atom::definitionProxy
,
66 (weakDef
? ld::Atom::combineByName
: ld::Atom::combineNever
),
67 ld::Atom::scopeLinkageUnit
,
68 (tlv
? ld::Atom::typeTLV
: ld::Atom::typeUnclassified
),
69 symbolTableNotIn
, false, false, false, ld::Atom::Alignment(0)),
70 _file(f
), _name(nm
), _address(address
) {}
71 // overrides of ld::Atom
72 virtual const ld::File
* file() const { return &_file
; }
73 virtual const char* name() const { return _name
; }
74 virtual uint64_t size() const { return 0; }
75 virtual uint64_t objectAddress() const { return _address
; }
76 virtual void copyRawContent(uint8_t buffer
[]) const { }
77 virtual void setScope(Scope
) { }
80 typedef typename
A::P P
;
81 typedef typename
A::P::uint_t pint_t
;
83 virtual ~ExportAtom() {}
93 // An ImportAtom has no content. It exists so that when linking a main executable flat-namespace
94 // the imports of all flat dylibs are checked
97 class ImportAtom
: public ld::Atom
100 ImportAtom(File
<A
>& f
, std::vector
<const char*>& imports
);
102 // overrides of ld::Atom
103 virtual ld::File
* file() const { return &_file
; }
104 virtual const char* name() const { return "import-atom"; }
105 virtual uint64_t size() const { return 0; }
106 virtual uint64_t objectAddress() const { return 0; }
107 virtual void copyRawContent(uint8_t buffer
[]) const { }
108 virtual void setScope(Scope
) { }
109 virtual ld::Fixup::iterator
fixupsBegin() const { return &_undefs
[0]; }
110 virtual ld::Fixup::iterator
fixupsEnd() const { return &_undefs
[_undefs
.size()]; }
113 typedef typename
A::P P
;
115 virtual ~ImportAtom() {}
119 mutable std::vector
<ld::Fixup
> _undefs
;
122 template <typename A
>
123 ImportAtom
<A
>::ImportAtom(File
<A
>& f
, std::vector
<const char*>& imports
)
124 : ld::Atom(f
._flatDummySection
, ld::Atom::definitionRegular
, ld::Atom::combineNever
, ld::Atom::scopeTranslationUnit
,
125 ld::Atom::typeUnclassified
, symbolTableNotIn
, false, false, false, ld::Atom::Alignment(0)), _file(f
)
127 for(std::vector
<const char*>::iterator it
=imports
.begin(); it
!= imports
.end(); ++it
) {
128 _undefs
.push_back(ld::Fixup(0, ld::Fixup::k1of1
, ld::Fixup::kindNone
, false, strdup(*it
)));
135 // The reader for a dylib extracts all exported symbols names from the memory-mapped
136 // dylib, builds a hash table, then unmaps the file. This is an important memory
137 // savings for large dylibs.
139 template <typename A
>
140 class File
: public ld::dylib::File
143 static bool validFile(const uint8_t* fileContent
, bool executableOrDylib
);
144 File(const uint8_t* fileContent
, uint64_t fileLength
, const char* path
,
145 time_t mTime
, ld::File::Ordinal ordinal
, bool linkingFlatNamespace
,
146 bool linkingMainExecutable
, bool hoistImplicitPublicDylibs
,
147 Options::Platform platform
, uint32_t linkMinOSVersion
, bool allowSimToMacOSX
,
148 bool addVers
, bool buildingForSimulator
,
149 bool logAllFiles
, const char* installPath
,
150 bool indirectDylib
, bool ignoreMismatchPlatform
, bool usingBitcode
);
153 // overrides of ld::File
154 virtual bool forEachAtom(ld::File::AtomHandler
&) const;
155 virtual bool justInTimeforEachAtom(const char* name
, ld::File::AtomHandler
&) const;
156 virtual ld::File::ObjcConstraint
objCConstraint() const { return _objcContraint
; }
157 virtual uint8_t swiftVersion() const { return _swiftVersion
; }
158 virtual uint32_t minOSVersion() const { return _minVersionInDylib
; }
159 virtual uint32_t platformLoadCommand() const { return _platformInDylib
; }
161 // overrides of ld::dylib::File
162 virtual void processIndirectLibraries(ld::dylib::File::DylibHandler
*, bool);
163 virtual bool providedExportAtom() const { return _providedAtom
; }
164 virtual const char* parentUmbrella() const { return _parentUmbrella
; }
165 virtual const std::vector
<const char*>* allowableClients() const { return _allowableClients
.size() != 0 ? &_allowableClients
: NULL
; }
166 virtual bool hasWeakExternals() const { return _hasWeakExports
; }
167 virtual bool deadStrippable() const { return _deadStrippable
; }
168 virtual bool hasPublicInstallName() const{ return _hasPublicInstallName
; }
169 virtual bool hasWeakDefinition(const char* name
) const;
170 virtual bool allSymbolsAreWeakImported() const;
171 virtual bool installPathVersionSpecific() const { return _installPathOverride
; }
172 virtual bool appExtensionSafe() const { return _appExtensionSafe
; };
173 virtual ld::Bitcode
* getBitcode() const { return _bitcode
.get(); }
176 virtual void assertNoReExportCycles(ReExportChain
*) const;
179 typedef typename
A::P P
;
180 typedef typename
A::P::E E
;
181 typedef typename
A::P::uint_t pint_t
;
183 friend class ExportAtom
<A
>;
184 friend class ImportAtom
<A
>;
187 std::size_t operator()(const char* __s
) const {
188 unsigned long __h
= 0;
190 __h
= 5 * __h
+ *__s
;
194 struct AtomAndWeak
{ ld::Atom
* atom
; bool weakDef
; bool tlv
; uint64_t address
; };
195 typedef std::unordered_map
<const char*, AtomAndWeak
, ld::CStringHash
, ld::CStringEquals
> NameToAtomMap
;
196 typedef std::unordered_set
<const char*, CStringHash
, ld::CStringEquals
> NameSet
;
198 struct Dependent
{ const char* path
; File
<A
>* dylib
; bool reExport
; };
200 virtual std::pair
<bool, bool> hasWeakDefinitionImpl(const char* name
) const;
201 virtual bool containsOrReExports(const char* name
, bool& weakDef
, bool& tlv
, uint64_t& defAddress
) const;
202 bool isPublicLocation(const char* pth
);
203 bool wrongOS() { return _wrongOS
; }
204 void addSymbol(const char* name
, bool weak
, bool tlv
, pint_t address
);
205 void addDyldFastStub();
206 void buildExportHashTableFromExportInfo(const macho_dyld_info_command
<P
>* dyldInfo
,
207 const uint8_t* fileContent
);
208 void buildExportHashTableFromSymbolTable(const macho_dysymtab_command
<P
>* dynamicInfo
,
209 const macho_nlist
<P
>* symbolTable
, const char* strings
,
210 const uint8_t* fileContent
);
211 static uint32_t parseVersionNumber32(const char* versionString
);
212 static const char* objCInfoSegmentName();
213 static const char* objCInfoSectionName();
215 const Options::Platform _platform
;
216 const uint32_t _linkMinOSVersion
;
217 const bool _allowSimToMacOSXLinking
;
218 const bool _addVersionLoadCommand
;
220 bool _implicitlyLinkPublicDylibs
;
221 ld::File::ObjcConstraint _objcContraint
;
222 uint8_t _swiftVersion
;
223 ld::Section _importProxySection
;
224 ld::Section _flatDummySection
;
225 std::vector
<Dependent
> _dependentDylibs
;
226 std::vector
<const char*> _allowableClients
;
227 mutable NameToAtomMap _atoms
;
228 NameSet _ignoreExports
;
229 const char* _parentUmbrella
;
230 ImportAtom
<A
>* _importAtom
;
232 bool _hasWeakExports
;
233 bool _deadStrippable
;
234 bool _hasPublicInstallName
;
235 mutable bool _providedAtom
;
236 bool _explictReExportFound
;
238 bool _installPathOverride
;
239 bool _indirectDylibsProcessed
;
240 bool _appExtensionSafe
;
242 uint32_t _minVersionInDylib
;
243 uint32_t _platformInDylib
;
244 std::unique_ptr
<ld::Bitcode
> _bitcode
;
246 static bool _s_logHashtable
;
249 template <typename A
>
250 bool File
<A
>::_s_logHashtable
= false;
252 template <> const char* File
<x86_64
>::objCInfoSegmentName() { return "__DATA"; }
253 template <> const char* File
<arm
>::objCInfoSegmentName() { return "__DATA"; }
254 template <typename A
> const char* File
<A
>::objCInfoSegmentName() { return "__OBJC"; }
256 template <> const char* File
<x86_64
>::objCInfoSectionName() { return "__objc_imageinfo"; }
257 template <> const char* File
<arm
>::objCInfoSectionName() { return "__objc_imageinfo"; }
258 template <typename A
> const char* File
<A
>::objCInfoSectionName() { return "__image_info"; }
260 template <typename A
>
261 File
<A
>::File(const uint8_t* fileContent
, uint64_t fileLength
, const char* pth
, time_t mTime
, ld::File::Ordinal ord
,
262 bool linkingFlatNamespace
, bool linkingMainExecutable
, bool hoistImplicitPublicDylibs
,
263 Options::Platform platform
, uint32_t linkMinOSVersion
, bool allowSimToMacOSX
, bool addVers
, bool buildingForSimulator
,
264 bool logAllFiles
, const char* targetInstallPath
, bool indirectDylib
, bool ignoreMismatchPlatform
, bool usingBitcode
)
265 : ld::dylib::File(strdup(pth
), mTime
, ord
),
266 _platform(platform
), _linkMinOSVersion(linkMinOSVersion
), _allowSimToMacOSXLinking(allowSimToMacOSX
), _addVersionLoadCommand(addVers
),
267 _linkingFlat(linkingFlatNamespace
), _implicitlyLinkPublicDylibs(hoistImplicitPublicDylibs
),
268 _objcContraint(ld::File::objcConstraintNone
), _swiftVersion(0),
269 _importProxySection("__TEXT", "__import", ld::Section::typeImportProxies
, true),
270 _flatDummySection("__LINKEDIT", "__flat_dummy", ld::Section::typeLinkEdit
, true),
271 _parentUmbrella(NULL
), _importAtom(NULL
),
272 _noRexports(false), _hasWeakExports(false),
273 _deadStrippable(false), _hasPublicInstallName(false),
274 _providedAtom(false), _explictReExportFound(false), _wrongOS(false), _installPathOverride(false),
275 _indirectDylibsProcessed(false), _appExtensionSafe(false), _usingBitcode(usingBitcode
),
276 _minVersionInDylib(0), _platformInDylib(Options::kPlatformUnknown
)
278 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
279 const uint32_t cmd_count
= header
->ncmds();
280 const macho_load_command
<P
>* const cmds
= (macho_load_command
<P
>*)((char*)header
+ sizeof(macho_header
<P
>));
281 const macho_load_command
<P
>* const cmdsEnd
= (macho_load_command
<P
>*)((char*)header
+ sizeof(macho_header
<P
>) + header
->sizeofcmds());
283 // write out path for -t option
287 // a "blank" stub has zero load commands
288 if ( (header
->filetype() == MH_DYLIB_STUB
) && (cmd_count
== 0) ) {
289 // no further processing needed
290 munmap((caddr_t
)fileContent
, fileLength
);
295 // optimize the case where we know there is no reason to look at indirect dylibs
296 _noRexports
= (header
->flags() & MH_NO_REEXPORTED_DYLIBS
)
297 || (header
->filetype() == MH_BUNDLE
)
298 || (header
->filetype() == MH_EXECUTE
); // bundles and exectuables can be used via -bundle_loader
299 _hasWeakExports
= (header
->flags() & MH_WEAK_DEFINES
);
300 _deadStrippable
= (header
->flags() & MH_DEAD_STRIPPABLE_DYLIB
);
301 _appExtensionSafe
= (header
->flags() & MH_APP_EXTENSION_SAFE
);
303 // pass 1: get pointers, and see if this dylib uses compressed LINKEDIT format
304 const macho_dysymtab_command
<P
>* dynamicInfo
= NULL
;
305 const macho_dyld_info_command
<P
>* dyldInfo
= NULL
;
306 const macho_nlist
<P
>* symbolTable
= NULL
;
307 const char* strings
= NULL
;
308 bool compressedLinkEdit
= false;
309 uint32_t dependentLibCount
= 0;
310 Options::Platform lcPlatform
= Options::kPlatformUnknown
;
311 const macho_load_command
<P
>* cmd
= cmds
;
312 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
313 macho_dylib_command
<P
>* dylibID
;
314 const macho_symtab_command
<P
>* symtab
;
315 switch (cmd
->cmd()) {
317 symtab
= (macho_symtab_command
<P
>*)cmd
;
318 symbolTable
= (const macho_nlist
<P
>*)((char*)header
+ symtab
->symoff());
319 strings
= (char*)header
+ symtab
->stroff();
320 if ( (symtab
->stroff() + symtab
->strsize()) > fileLength
)
321 throwf("mach-o string pool extends beyond end of file in %s", pth
);
324 dynamicInfo
= (macho_dysymtab_command
<P
>*)cmd
;
327 case LC_DYLD_INFO_ONLY
:
328 dyldInfo
= (macho_dyld_info_command
<P
>*)cmd
;
329 compressedLinkEdit
= true;
332 dylibID
= (macho_dylib_command
<P
>*)cmd
;
333 _dylibInstallPath
= strdup(dylibID
->name());
334 _dylibTimeStamp
= dylibID
->timestamp();
335 _dylibCurrentVersion
= dylibID
->current_version();
336 _dylibCompatibilityVersion
= dylibID
->compatibility_version();
337 _hasPublicInstallName
= isPublicLocation(_dylibInstallPath
);
340 case LC_LOAD_WEAK_DYLIB
:
343 case LC_REEXPORT_DYLIB
:
344 _explictReExportFound
= true;
347 case LC_SUB_FRAMEWORK
:
348 _parentUmbrella
= strdup(((macho_sub_framework_command
<P
>*)cmd
)->umbrella());
351 _allowableClients
.push_back(strdup(((macho_sub_client_command
<P
>*)cmd
)->client()));
352 // <rdar://problem/20627554> Don't hoist "public" (in /usr/lib/) dylibs that should not be directly linked
353 _hasPublicInstallName
= false;
355 case LC_VERSION_MIN_MACOSX
:
356 case LC_VERSION_MIN_IPHONEOS
:
357 case LC_VERSION_MIN_WATCHOS
:
359 case LC_VERSION_MIN_TVOS
:
361 _minVersionInDylib
= (ld::MacVersionMin
)((macho_version_min_command
<P
>*)cmd
)->version();
362 _platformInDylib
= cmd
->cmd();
363 lcPlatform
= Options::platformForLoadCommand(_platformInDylib
);
365 case LC_CODE_SIGNATURE
:
367 case macho_segment_command
<P
>::CMD
:
368 // check for Objective-C info
369 if ( strncmp(((macho_segment_command
<P
>*)cmd
)->segname(), objCInfoSegmentName(), 6) == 0 ) {
370 const macho_segment_command
<P
>* segment
= (macho_segment_command
<P
>*)cmd
;
371 const macho_section
<P
>* const sectionsStart
= (macho_section
<P
>*)((char*)segment
+ sizeof(macho_segment_command
<P
>));
372 const macho_section
<P
>* const sectionsEnd
= §ionsStart
[segment
->nsects()];
373 for (const macho_section
<P
>* sect
=sectionsStart
; sect
< sectionsEnd
; ++sect
) {
374 if ( strncmp(sect
->sectname(), objCInfoSectionName(), strlen(objCInfoSectionName())) == 0 ) {
375 // struct objc_image_info {
376 // uint32_t version; // initially 0
379 // #define OBJC_IMAGE_SUPPORTS_GC 2
380 // #define OBJC_IMAGE_GC_ONLY 4
381 // #define OBJC_IMAGE_IS_SIMULATED 32
383 const uint32_t* contents
= (uint32_t*)(&fileContent
[sect
->offset()]);
384 if ( (sect
->size() >= 8) && (contents
[0] == 0) ) {
385 uint32_t flags
= E::get32(contents
[1]);
386 if ( (flags
& 4) == 4 )
387 _objcContraint
= ld::File::objcConstraintGC
;
388 else if ( (flags
& 2) == 2 )
389 _objcContraint
= ld::File::objcConstraintRetainReleaseOrGC
;
390 else if ( (flags
& 32) == 32 )
391 _objcContraint
= ld::File::objcConstraintRetainReleaseForSimulator
;
393 _objcContraint
= ld::File::objcConstraintRetainRelease
;
394 _swiftVersion
= ((flags
>> 8) & 0xFF);
396 else if ( sect
->size() > 0 ) {
397 warning("can't parse %s/%s section in %s", objCInfoSegmentName(), objCInfoSectionName(), this->path());
402 // Construct bitcode if there is a bitcode bundle section in the dylib
403 // Record the size of the section because the content is not checked
404 else if ( strcmp(((macho_segment_command
<P
>*)cmd
)->segname(), "__LLVM") == 0 ) {
405 const macho_section
<P
>* const sect
= (macho_section
<P
>*)((char*)cmd
+ sizeof(macho_segment_command
<P
>));
406 if ( strncmp(sect
->sectname(), "__bundle", 8) == 0 )
407 _bitcode
= std::unique_ptr
<ld::Bitcode
>(new ld::Bitcode(NULL
, sect
->size()));
410 cmd
= (const macho_load_command
<P
>*)(((char*)cmd
)+cmd
->cmdsize());
412 throwf("malformed dylb, load command #%d is outside size of load commands in %s", i
, pth
);
414 // arm/arm64 objects are default to ios platform if not set.
415 // rdar://problem/21746314
416 if (lcPlatform
== Options::kPlatformUnknown
&&
417 (std::is_same
<A
, arm
>::value
|| std::is_same
<A
, arm64
>::value
))
418 lcPlatform
= Options::kPlatformiOS
;
420 // check cross-linking
421 if ( lcPlatform
!= platform
) {
423 if ( _addVersionLoadCommand
&& !indirectDylib
&& !ignoreMismatchPlatform
) {
424 if ( buildingForSimulator
) {
425 if ( !_allowSimToMacOSXLinking
) {
427 case Options::kPlatformOSX
:
428 case Options::kPlatformiOS
:
429 if ( lcPlatform
== Options::kPlatformUnknown
)
431 // fall through if the Platform is not Unknown
432 case Options::kPlatformWatchOS
:
433 // WatchOS errors on cross-linking all the time.
434 throwf("building for %s simulator, but linking against dylib built for %s,",
435 Options::platformName(platform
),
436 Options::platformName(lcPlatform
));
439 case Options::kPlatform_tvOS
:
440 // tvOS is a warning temporarily. rdar://problem/21746965
442 throwf("building for %s simulator, but linking against dylib built for %s,",
443 Options::platformName(platform
),
444 Options::platformName(lcPlatform
));
446 warning("URGENT: building for %s simulator, but linking against dylib (%s) built for %s. "
447 "Note: This will be an error in the future.",
448 Options::platformName(platform
), path(),
449 Options::platformName(lcPlatform
));
452 case Options::kPlatformUnknown
:
453 // skip if the target platform is unknown
460 case Options::kPlatformOSX
:
461 case Options::kPlatformiOS
:
462 if ( lcPlatform
== Options::kPlatformUnknown
)
464 // fall through if the Platform is not Unknown
465 case Options::kPlatformWatchOS
:
466 // WatchOS errors on cross-linking all the time.
467 throwf("building for %s, but linking against dylib built for %s,",
468 Options::platformName(platform
),
469 Options::platformName(lcPlatform
));
472 case Options::kPlatform_tvOS
:
473 // tvOS is a warning temporarily. rdar://problem/21746965
475 throwf("building for %s, but linking against dylib built for %s,",
476 Options::platformName(platform
),
477 Options::platformName(lcPlatform
));
479 warning("URGENT: building for %s, but linking against dylib (%s) built for %s. "
480 "Note: This will be an error in the future.",
481 Options::platformName(platform
), path(),
482 Options::platformName(lcPlatform
));
485 case Options::kPlatformUnknown
:
486 // skip if the target platform is unknown
493 // figure out if we need to examine dependent dylibs
494 // with compressed LINKEDIT format, MH_NO_REEXPORTED_DYLIBS can be trusted
495 bool processDependentLibraries
= true;
496 if ( compressedLinkEdit
&& _noRexports
&& !linkingFlatNamespace
)
497 processDependentLibraries
= false;
499 if ( processDependentLibraries
) {
500 // pass 2 builds list of all dependent libraries
501 _dependentDylibs
.reserve(dependentLibCount
);
503 unsigned int reExportDylibCount
= 0;
504 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
505 switch (cmd
->cmd()) {
507 case LC_LOAD_WEAK_DYLIB
:
508 // with new linkedit format only care about LC_REEXPORT_DYLIB
509 if ( compressedLinkEdit
&& !linkingFlatNamespace
)
511 case LC_REEXPORT_DYLIB
:
512 ++reExportDylibCount
;
514 entry
.path
= strdup(((macho_dylib_command
<P
>*)cmd
)->name());
516 entry
.reExport
= (cmd
->cmd() == LC_REEXPORT_DYLIB
);
517 if ( (targetInstallPath
== NULL
) || (strcmp(targetInstallPath
, entry
.path
) != 0) )
518 _dependentDylibs
.push_back(entry
);
521 cmd
= (const macho_load_command
<P
>*)(((char*)cmd
)+cmd
->cmdsize());
523 // verify MH_NO_REEXPORTED_DYLIBS bit was correct
524 if ( compressedLinkEdit
&& !linkingFlatNamespace
) {
525 if ( reExportDylibCount
== 0 )
526 throwf("malformed dylib has MH_NO_REEXPORTED_DYLIBS flag but no LC_REEXPORT_DYLIB load commands: %s", pth
);
528 // pass 3 add re-export info
530 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
531 const char* frameworkLeafName
;
532 const char* dylibBaseName
;
533 switch (cmd
->cmd()) {
534 case LC_SUB_UMBRELLA
:
535 frameworkLeafName
= ((macho_sub_umbrella_command
<P
>*)cmd
)->sub_umbrella();
536 for (typename
std::vector
<Dependent
>::iterator it
= _dependentDylibs
.begin(); it
!= _dependentDylibs
.end(); ++it
) {
537 const char* dylibName
= it
->path
;
538 const char* lastSlash
= strrchr(dylibName
, '/');
539 if ( (lastSlash
!= NULL
) && (strcmp(&lastSlash
[1], frameworkLeafName
) == 0) )
544 dylibBaseName
= ((macho_sub_library_command
<P
>*)cmd
)->sub_library();
545 for (typename
std::vector
<Dependent
>::iterator it
= _dependentDylibs
.begin(); it
!= _dependentDylibs
.end(); ++it
) {
546 const char* dylibName
= it
->path
;
547 const char* lastSlash
= strrchr(dylibName
, '/');
548 const char* leafStart
= &lastSlash
[1];
549 if ( lastSlash
== NULL
)
550 leafStart
= dylibName
;
551 const char* firstDot
= strchr(leafStart
, '.');
552 int len
= strlen(leafStart
);
553 if ( firstDot
!= NULL
)
554 len
= firstDot
- leafStart
;
555 if ( strncmp(leafStart
, dylibBaseName
, len
) == 0 )
560 cmd
= (const macho_load_command
<P
>*)(((char*)cmd
)+cmd
->cmdsize());
564 // validate minimal load commands
565 if ( (_dylibInstallPath
== NULL
) && ((header
->filetype() == MH_DYLIB
) || (header
->filetype() == MH_DYLIB_STUB
)) )
566 throwf("dylib %s missing LC_ID_DYLIB load command", pth
);
567 if ( dyldInfo
== NULL
) {
568 if ( symbolTable
== NULL
)
569 throw "binary missing LC_SYMTAB load command";
570 if ( dynamicInfo
== NULL
)
571 throw "binary missing LC_DYSYMTAB load command";
574 // if linking flat and this is a flat dylib, create one atom that references all imported symbols
575 if ( linkingFlatNamespace
&& linkingMainExecutable
&& ((header
->flags() & MH_TWOLEVEL
) == 0) ) {
576 std::vector
<const char*> importNames
;
577 importNames
.reserve(dynamicInfo
->nundefsym());
578 const macho_nlist
<P
>* start
= &symbolTable
[dynamicInfo
->iundefsym()];
579 const macho_nlist
<P
>* end
= &start
[dynamicInfo
->nundefsym()];
580 for (const macho_nlist
<P
>* sym
=start
; sym
< end
; ++sym
) {
581 importNames
.push_back(&strings
[sym
->n_strx()]);
583 _importAtom
= new ImportAtom
<A
>(*this, importNames
);
587 if ( dyldInfo
!= NULL
)
588 buildExportHashTableFromExportInfo(dyldInfo
, fileContent
);
590 buildExportHashTableFromSymbolTable(dynamicInfo
, symbolTable
, strings
, fileContent
);
593 munmap((caddr_t
)fileContent
, fileLength
);
598 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
600 template <typename A
>
601 uint32_t File
<A
>::parseVersionNumber32(const char* versionString
)
607 x
= strtoul(versionString
, &end
, 10);
609 y
= strtoul(&end
[1], &end
, 10);
611 z
= strtoul(&end
[1], &end
, 10);
614 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
615 throwf("malformed 32-bit x.y.z version number: %s", versionString
);
617 return (x
<< 16) | ( y
<< 8 ) | z
;
620 template <typename A
>
621 void File
<A
>::buildExportHashTableFromSymbolTable(const macho_dysymtab_command
<P
>* dynamicInfo
,
622 const macho_nlist
<P
>* symbolTable
, const char* strings
,
623 const uint8_t* fileContent
)
625 if ( dynamicInfo
->tocoff() == 0 ) {
626 if ( _s_logHashtable
) fprintf(stderr
, "ld: building hashtable of %u toc entries for %s\n", dynamicInfo
->nextdefsym(), this->path());
627 const macho_nlist
<P
>* start
= &symbolTable
[dynamicInfo
->iextdefsym()];
628 const macho_nlist
<P
>* end
= &start
[dynamicInfo
->nextdefsym()];
629 _atoms
.reserve(dynamicInfo
->nextdefsym()); // set initial bucket count
630 for (const macho_nlist
<P
>* sym
=start
; sym
< end
; ++sym
) {
631 this->addSymbol(&strings
[sym
->n_strx()], (sym
->n_desc() & N_WEAK_DEF
) != 0, false, sym
->n_value());
635 int32_t count
= dynamicInfo
->ntoc();
636 _atoms
.reserve(count
); // set initial bucket count
637 if ( _s_logHashtable
) fprintf(stderr
, "ld: building hashtable of %u entries for %s\n", count
, this->path());
638 const struct dylib_table_of_contents
* toc
= (dylib_table_of_contents
*)(fileContent
+ dynamicInfo
->tocoff());
639 for (int32_t i
= 0; i
< count
; ++i
) {
640 const uint32_t index
= E::get32(toc
[i
].symbol_index
);
641 const macho_nlist
<P
>* sym
= &symbolTable
[index
];
642 this->addSymbol(&strings
[sym
->n_strx()], (sym
->n_desc() & N_WEAK_DEF
) != 0, false, sym
->n_value());
646 // special case old libSystem
647 if ( (_dylibInstallPath
!= NULL
) && (strcmp(_dylibInstallPath
, "/usr/lib/libSystem.B.dylib") == 0) )
652 template <typename A
>
653 void File
<A
>::buildExportHashTableFromExportInfo(const macho_dyld_info_command
<P
>* dyldInfo
,
654 const uint8_t* fileContent
)
656 if ( _s_logHashtable
) fprintf(stderr
, "ld: building hashtable from export info in %s\n", this->path());
657 if ( dyldInfo
->export_size() > 0 ) {
658 const uint8_t* start
= fileContent
+ dyldInfo
->export_off();
659 const uint8_t* end
= &start
[dyldInfo
->export_size()];
660 std::vector
<mach_o::trie::Entry
> list
;
661 parseTrie(start
, end
, list
);
662 for (std::vector
<mach_o::trie::Entry
>::iterator it
=list
.begin(); it
!= list
.end(); ++it
)
663 this->addSymbol(it
->name
,
664 it
->flags
& EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION
,
665 (it
->flags
& EXPORT_SYMBOL_FLAGS_KIND_MASK
) == EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL
,
672 void File
<x86_64
>::addDyldFastStub()
674 addSymbol("dyld_stub_binder", false, false, 0);
678 void File
<x86
>::addDyldFastStub()
680 addSymbol("dyld_stub_binder", false, false, 0);
683 template <typename A
>
684 void File
<A
>::addDyldFastStub()
689 template <typename A
>
690 void File
<A
>::addSymbol(const char* name
, bool weakDef
, bool tlv
, pint_t address
)
692 //fprintf(stderr, "addSymbol() %s\n", name);
693 // symbols that start with $ld$ are meta-data to the static linker
694 // <rdar://problem/5182537> need way for ld and dyld to see different exported symbols in a dylib
695 if ( strncmp(name
, "$ld$", 4) == 0 ) {
696 // $ld$ <action> $ <condition> $ <symbol-name>
697 const char* symAction
= &name
[4];
698 const char* symCond
= strchr(symAction
, '$');
699 if ( symCond
!= NULL
) {
701 sprintf(curOSVers
, "$os%d.%d$", (_linkMinOSVersion
>> 16), ((_linkMinOSVersion
>> 8) & 0xFF));
702 if ( strncmp(symCond
, curOSVers
, strlen(curOSVers
)) == 0 ) {
703 const char* symName
= strchr(&symCond
[1], '$');
704 if ( symName
!= NULL
) {
706 if ( strncmp(symAction
, "hide$", 5) == 0 ) {
707 if ( _s_logHashtable
) fprintf(stderr
, " adding %s to ignore set for %s\n", symName
, this->path());
708 _ignoreExports
.insert(strdup(symName
));
711 else if ( strncmp(symAction
, "add$", 4) == 0 ) {
712 this->addSymbol(symName
, weakDef
, false, 0);
715 else if ( strncmp(symAction
, "install_name$", 13) == 0 ) {
716 _dylibInstallPath
= symName
;
717 _installPathOverride
= true;
718 // <rdar://problem/14448206> CoreGraphics redirects to ApplicationServices, but with wrong compat version
719 if ( strcmp(_dylibInstallPath
, "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices") == 0 )
720 _dylibCompatibilityVersion
= parseVersionNumber32("1.0");
723 else if ( strncmp(symAction
, "compatibility_version$", 22) == 0 ) {
724 _dylibCompatibilityVersion
= parseVersionNumber32(symName
);
728 warning("bad symbol action: %s in dylib %s", name
, this->path());
734 warning("bad symbol condition: %s in dylib %s", name
, this->path());
738 // add symbol as possible export if we are not supposed to ignore it
739 if ( _ignoreExports
.count(name
) == 0 ) {
742 bucket
.weakDef
= weakDef
;
744 bucket
.address
= address
;
745 if ( _s_logHashtable
) fprintf(stderr
, " adding %s to hash table for %s\n", name
, this->path());
746 _atoms
[strdup(name
)] = bucket
;
751 template <typename A
>
752 bool File
<A
>::forEachAtom(ld::File::AtomHandler
& handler
) const
754 handler
.doFile(*this);
755 // if doing flatnamespace and need all this dylib's imports resolve
756 // add atom which references alls undefines in this dylib
757 if ( _importAtom
!= NULL
) {
758 handler
.doAtom(*_importAtom
);
765 template <typename A
>
766 std::pair
<bool, bool> File
<A
>::hasWeakDefinitionImpl(const char* name
) const
768 const auto pos
= _atoms
.find(name
);
769 if ( pos
!= _atoms
.end() )
770 return std::make_pair(true, pos
->second
.weakDef
);
772 // look in children that I re-export
773 for (const auto &dep
: _dependentDylibs
) {
774 if ( dep
.reExport
) {
775 auto ret
= dep
.dylib
->hasWeakDefinitionImpl(name
);
780 return std::make_pair(false, false);
784 template <typename A
>
785 bool File
<A
>::hasWeakDefinition(const char* name
) const
787 // if supposed to ignore this export, then pretend I don't have it
788 if ( _ignoreExports
.count(name
) != 0 )
791 return hasWeakDefinitionImpl(name
).second
;
795 // <rdar://problem/5529626> If only weak_import symbols are used, linker should use LD_LOAD_WEAK_DYLIB
796 template <typename A
>
797 bool File
<A
>::allSymbolsAreWeakImported() const
799 bool foundNonWeakImport
= false;
800 bool foundWeakImport
= false;
801 //fprintf(stderr, "%s:\n", this->path());
802 for (typename
NameToAtomMap::const_iterator it
= _atoms
.begin(); it
!= _atoms
.end(); ++it
) {
803 const ld::Atom
* atom
= it
->second
.atom
;
804 if ( atom
!= NULL
) {
805 if ( atom
->weakImported() )
806 foundWeakImport
= true;
808 foundNonWeakImport
= true;
809 //fprintf(stderr, " weak_import=%d, name=%s\n", atom->weakImported(), it->first);
813 // don't automatically weak link dylib with no imports
814 // so at least one weak import symbol and no non-weak-imported symbols must be found
815 return foundWeakImport
&& !foundNonWeakImport
;
819 template <typename A
>
820 bool File
<A
>::containsOrReExports(const char* name
, bool& weakDef
, bool& tlv
, uint64_t& defAddress
) const
822 if ( _ignoreExports
.count(name
) != 0 )
826 const auto pos
= _atoms
.find(name
);
827 if ( pos
!= _atoms
.end() ) {
828 weakDef
= pos
->second
.weakDef
;
829 tlv
= pos
->second
.tlv
;
830 defAddress
= pos
->second
.address
;
834 // check dylibs I re-export
835 for (const auto &dep
: _dependentDylibs
) {
836 if ( dep
.reExport
&& !dep
.dylib
->implicitlyLinked() ) {
837 if ( dep
.dylib
->containsOrReExports(name
, weakDef
, tlv
, defAddress
) )
846 template <typename A
>
847 bool File
<A
>::justInTimeforEachAtom(const char* name
, ld::File::AtomHandler
& handler
) const
849 // if supposed to ignore this export, then pretend I don't have it
850 if ( _ignoreExports
.count(name
) != 0 )
855 if ( this->containsOrReExports(name
, bucket
.weakDef
, bucket
.tlv
, bucket
.address
) ) {
856 bucket
.atom
= new ExportAtom
<A
>(*this, name
, bucket
.weakDef
, bucket
.tlv
, bucket
.address
);
857 _atoms
[name
] = bucket
;
858 _providedAtom
= true;
859 if ( _s_logHashtable
) fprintf(stderr
, "getJustInTimeAtomsFor: %s found in %s\n", name
, this->path());
860 // call handler with new export atom
861 handler
.doAtom(*bucket
.atom
);
870 template <typename A
>
871 bool File
<A
>::isPublicLocation(const char* pth
)
873 // -no_implicit_dylibs disables this optimization
874 if ( ! _implicitlyLinkPublicDylibs
)
877 // /usr/lib is a public location
878 if ( (strncmp(pth
, "/usr/lib/", 9) == 0) && (strchr(&pth
[9], '/') == NULL
) )
881 // /System/Library/Frameworks/ is a public location
882 if ( strncmp(pth
, "/System/Library/Frameworks/", 27) == 0 ) {
883 const char* frameworkDot
= strchr(&pth
[27], '.');
884 // but only top level framework
885 // /System/Library/Frameworks/Foo.framework/Versions/A/Foo ==> true
886 // /System/Library/Frameworks/Foo.framework/Resources/libBar.dylib ==> false
887 // /System/Library/Frameworks/Foo.framework/Frameworks/Bar.framework/Bar ==> false
888 // /System/Library/Frameworks/Foo.framework/Frameworks/Xfoo.framework/XFoo ==> false
889 if ( frameworkDot
!= NULL
) {
890 int frameworkNameLen
= frameworkDot
- &pth
[27];
891 if ( strncmp(&pth
[strlen(pth
)-frameworkNameLen
-1], &pth
[26], frameworkNameLen
+1) == 0 )
899 template <typename A
>
900 void File
<A
>::processIndirectLibraries(ld::dylib::File::DylibHandler
* handler
, bool addImplicitDylibs
)
903 if ( _indirectDylibsProcessed
)
905 const static bool log
= false;
906 if ( log
) fprintf(stderr
, "processIndirectLibraries(%s)\n", this->installPath());
907 if ( _linkingFlat
) {
908 for (typename
std::vector
<Dependent
>::iterator it
= _dependentDylibs
.begin(); it
!= _dependentDylibs
.end(); it
++) {
909 it
->dylib
= (File
<A
>*)handler
->findDylib(it
->path
, this->path());
912 else if ( _noRexports
) {
913 // MH_NO_REEXPORTED_DYLIBS bit set, then nothing to do
916 // two-level, might have re-exports
917 for (typename
std::vector
<Dependent
>::iterator it
= _dependentDylibs
.begin(); it
!= _dependentDylibs
.end(); it
++) {
918 if ( it
->reExport
) {
919 if ( log
) fprintf(stderr
, "processIndirectLibraries() parent=%s, child=%s\n", this->installPath(), it
->path
);
920 // a LC_REEXPORT_DYLIB, LC_SUB_UMBRELLA or LC_SUB_LIBRARY says we re-export this child
921 it
->dylib
= (File
<A
>*)handler
->findDylib(it
->path
, this->path());
922 if ( it
->dylib
->hasPublicInstallName() && !it
->dylib
->wrongOS() ) {
923 // promote this child to be automatically added as a direct dependent if this already is
924 if ( (this->explicitlyLinked() || this->implicitlyLinked()) && (strcmp(it
->path
,it
->dylib
->installPath()) == 0) ) {
925 if ( log
) fprintf(stderr
, "processIndirectLibraries() implicitly linking %s\n", it
->dylib
->installPath());
926 it
->dylib
->setImplicitlyLinked();
928 else if ( it
->dylib
->explicitlyLinked() || it
->dylib
->implicitlyLinked() ) {
929 if ( log
) fprintf(stderr
, "processIndirectLibraries() parent is not directly linked, but child is, so no need to re-export child\n");
932 if ( log
) fprintf(stderr
, "processIndirectLibraries() parent is not directly linked, so parent=%s will re-export child=%s\n", this->installPath(), it
->path
);
936 // add all child's symbols to me
937 if ( log
) fprintf(stderr
, "processIndirectLibraries() child is not public, so parent=%s will re-export child=%s\n", this->installPath(), it
->path
);
940 else if ( !_explictReExportFound
) {
941 // see if child contains LC_SUB_FRAMEWORK with my name
942 it
->dylib
= (File
<A
>*)handler
->findDylib(it
->path
, this->path());
943 const char* parentUmbrellaName
= it
->dylib
->parentUmbrella();
944 if ( parentUmbrellaName
!= NULL
) {
945 const char* parentName
= this->path();
946 const char* lastSlash
= strrchr(parentName
, '/');
947 if ( (lastSlash
!= NULL
) && (strcmp(&lastSlash
[1], parentUmbrellaName
) == 0) ) {
948 // add all child's symbols to me
950 if ( log
) fprintf(stderr
, "processIndirectLibraries() umbrella=%s will re-export child=%s\n", this->installPath(), it
->path
);
957 // check for re-export cycles
961 this->assertNoReExportCycles(&chain
);
963 _indirectDylibsProcessed
= true;
966 template <typename A
>
967 void File
<A
>::assertNoReExportCycles(ReExportChain
* prev
) const
969 // recursively check my re-exported dylibs
973 for (const auto &dep
: _dependentDylibs
) {
974 if ( dep
.reExport
) {
975 ld::File
* child
= dep
.dylib
;
976 // check child is not already in chain
977 for (ReExportChain
* p
= prev
; p
!= nullptr; p
= p
->prev
) {
978 if ( p
->file
== child
) {
979 throwf("cycle in dylib re-exports with %s and %s", child
->path(), this->path());
982 if ( dep
.dylib
!= nullptr )
983 dep
.dylib
->assertNoReExportCycles(&chain
);
989 template <typename A
>
993 typedef typename
A::P P
;
995 static bool validFile(const uint8_t* fileContent
, bool executableOrDyliborBundle
);
996 static const char* fileKind(const uint8_t* fileContent
);
997 static ld::dylib::File
* parse(const uint8_t* fileContent
, uint64_t fileLength
,
998 const char* path
, time_t mTime
,
999 ld::File::Ordinal ordinal
, const Options
& opts
, bool indirectDylib
) {
1000 return new File
<A
>(fileContent
, fileLength
, path
, mTime
,
1001 ordinal
, opts
.flatNamespace(),
1002 opts
.linkingMainExecutable(),
1003 opts
.implicitlyLinkIndirectPublicDylibs(),
1005 opts
.minOSversion(),
1006 opts
.allowSimulatorToLinkWithMacOSX(),
1007 opts
.addVersionLoadCommand(),
1008 opts
.targetIOSSimulator(),
1012 opts
.outputKind() == Options::kPreload
,
1013 opts
.bundleBitcode());
1021 bool Parser
<x86
>::validFile(const uint8_t* fileContent
, bool executableOrDyliborBundle
)
1023 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1024 if ( header
->magic() != MH_MAGIC
)
1026 if ( header
->cputype() != CPU_TYPE_I386
)
1028 switch ( header
->filetype() ) {
1033 if ( executableOrDyliborBundle
)
1036 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
1038 if ( executableOrDyliborBundle
)
1041 throw "can't link with a main executable";
1048 bool Parser
<x86_64
>::validFile(const uint8_t* fileContent
, bool executableOrDyliborBundle
)
1050 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1051 if ( header
->magic() != MH_MAGIC_64
)
1053 if ( header
->cputype() != CPU_TYPE_X86_64
)
1055 switch ( header
->filetype() ) {
1060 if ( executableOrDyliborBundle
)
1063 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
1065 if ( executableOrDyliborBundle
)
1068 throw "can't link with a main executable";
1075 bool Parser
<arm
>::validFile(const uint8_t* fileContent
, bool executableOrDyliborBundle
)
1077 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1078 if ( header
->magic() != MH_MAGIC
)
1080 if ( header
->cputype() != CPU_TYPE_ARM
)
1082 switch ( header
->filetype() ) {
1087 if ( executableOrDyliborBundle
)
1090 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
1092 if ( executableOrDyliborBundle
)
1095 throw "can't link with a main executable";
1104 bool Parser
<arm64
>::validFile(const uint8_t* fileContent
, bool executableOrDyliborBundle
)
1106 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1107 if ( header
->magic() != MH_MAGIC_64
)
1109 if ( header
->cputype() != CPU_TYPE_ARM64
)
1111 switch ( header
->filetype() ) {
1116 if ( executableOrDyliborBundle
)
1119 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
1121 if ( executableOrDyliborBundle
)
1124 throw "can't link with a main executable";
1131 bool isDylibFile(const uint8_t* fileContent
, cpu_type_t
* result
, cpu_subtype_t
* subResult
)
1133 if ( Parser
<x86_64
>::validFile(fileContent
, false) ) {
1134 *result
= CPU_TYPE_X86_64
;
1135 const macho_header
<Pointer64
<LittleEndian
> >* header
= (const macho_header
<Pointer64
<LittleEndian
> >*)fileContent
;
1136 *subResult
= header
->cpusubtype();
1139 if ( Parser
<x86
>::validFile(fileContent
, false) ) {
1140 *result
= CPU_TYPE_I386
;
1141 *subResult
= CPU_SUBTYPE_X86_ALL
;
1144 if ( Parser
<arm
>::validFile(fileContent
, false) ) {
1145 *result
= CPU_TYPE_ARM
;
1146 const macho_header
<Pointer32
<LittleEndian
> >* header
= (const macho_header
<Pointer32
<LittleEndian
> >*)fileContent
;
1147 *subResult
= header
->cpusubtype();
1150 if ( Parser
<arm64
>::validFile(fileContent
, false) ) {
1151 *result
= CPU_TYPE_ARM64
;
1152 *subResult
= CPU_SUBTYPE_ARM64_ALL
;
1159 const char* Parser
<x86
>::fileKind(const uint8_t* fileContent
)
1161 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1162 if ( header
->magic() != MH_MAGIC
)
1164 if ( header
->cputype() != CPU_TYPE_I386
)
1170 const char* Parser
<x86_64
>::fileKind(const uint8_t* fileContent
)
1172 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1173 if ( header
->magic() != MH_MAGIC_64
)
1175 if ( header
->cputype() != CPU_TYPE_X86_64
)
1181 const char* Parser
<arm
>::fileKind(const uint8_t* fileContent
)
1183 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1184 if ( header
->magic() != MH_MAGIC
)
1186 if ( header
->cputype() != CPU_TYPE_ARM
)
1188 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
1189 if ( (t
->cpuType
== CPU_TYPE_ARM
) && ((cpu_subtype_t
)header
->cpusubtype() == t
->cpuSubType
) ) {
1196 #if SUPPORT_ARCH_arm64
1198 const char* Parser
<arm64
>::fileKind(const uint8_t* fileContent
)
1200 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1201 if ( header
->magic() != MH_MAGIC_64
)
1203 if ( header
->cputype() != CPU_TYPE_ARM64
)
1210 // used by linker is error messages to describe mismatched files
1212 const char* archName(const uint8_t* fileContent
)
1214 if ( Parser
<x86_64
>::validFile(fileContent
, true) ) {
1215 return Parser
<x86_64
>::fileKind(fileContent
);
1217 if ( Parser
<x86
>::validFile(fileContent
, true) ) {
1218 return Parser
<x86
>::fileKind(fileContent
);
1220 if ( Parser
<arm
>::validFile(fileContent
, true) ) {
1221 return Parser
<arm
>::fileKind(fileContent
);
1223 #if SUPPORT_ARCH_arm64
1224 if ( Parser
<arm64
>::validFile(fileContent
, false) ) {
1225 return Parser
<arm64
>::fileKind(fileContent
);
1233 // main function used by linker to instantiate ld::Files
1235 ld::dylib::File
* parse(const uint8_t* fileContent
, uint64_t fileLength
,
1236 const char* path
, time_t modTime
, const Options
& opts
, ld::File::Ordinal ordinal
,
1237 bool bundleLoader
, bool indirectDylib
)
1239 switch ( opts
.architecture() ) {
1240 #if SUPPORT_ARCH_x86_64
1241 case CPU_TYPE_X86_64
:
1242 if ( Parser
<x86_64
>::validFile(fileContent
, bundleLoader
) )
1243 return Parser
<x86_64
>::parse(fileContent
, fileLength
, path
, modTime
, ordinal
, opts
, indirectDylib
);
1246 #if SUPPORT_ARCH_i386
1248 if ( Parser
<x86
>::validFile(fileContent
, bundleLoader
) )
1249 return Parser
<x86
>::parse(fileContent
, fileLength
, path
, modTime
, ordinal
, opts
, indirectDylib
);
1252 #if SUPPORT_ARCH_arm_any
1254 if ( Parser
<arm
>::validFile(fileContent
, bundleLoader
) )
1255 return Parser
<arm
>::parse(fileContent
, fileLength
, path
, modTime
, ordinal
, opts
, indirectDylib
);
1258 #if SUPPORT_ARCH_arm64
1259 case CPU_TYPE_ARM64
:
1260 if ( Parser
<arm64
>::validFile(fileContent
, bundleLoader
) )
1261 return Parser
<arm64
>::parse(fileContent
, fileLength
, path
, modTime
, ordinal
, opts
, indirectDylib
);
1269 }; // namespace dylib
1270 }; // namespace mach_o