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>
38 #include "Architectures.hpp"
39 #include "Bitcode.hpp"
40 #include "MachOFileAbstraction.hpp"
41 #include "MachOTrie.hpp"
42 #include "generic_dylib_file.hpp"
43 #include "macho_dylib_file.h"
44 #include "../code-sign-blobs/superblob.h"
50 // The reader for a dylib extracts all exported symbols names from the memory-mapped
51 // dylib, builds a hash table, then unmaps the file. This is an important memory
52 // savings for large dylibs.
55 class File final
: public generic::dylib::File
<A
>
57 using Base
= generic::dylib::File
<A
>;
60 static bool validFile(const uint8_t* fileContent
, bool executableOrDylib
, bool subTypeMustMatch
=false);
61 File(const uint8_t* fileContent
, uint64_t fileLength
, const char* path
,
62 time_t mTime
, ld::File::Ordinal ordinal
, bool linkingFlatNamespace
,
63 bool linkingMainExecutable
, bool hoistImplicitPublicDylibs
,
64 Options::Platform platform
, uint32_t linkMinOSVersion
, bool allowSimToMacOSX
,
65 bool addVers
, bool buildingForSimulator
,
66 bool logAllFiles
, const char* installPath
,
67 bool indirectDylib
, bool ignoreMismatchPlatform
, bool usingBitcode
);
68 virtual ~File() noexcept {}
71 using P
= typename
A::P
;
72 using E
= typename
A::P::E
;
74 void addDyldFastStub();
75 void buildExportHashTableFromExportInfo(const macho_dyld_info_command
<P
>* dyldInfo
,
76 const uint8_t* fileContent
);
77 void buildExportHashTableFromSymbolTable(const macho_dysymtab_command
<P
>* dynamicInfo
,
78 const macho_nlist
<P
>* symbolTable
, const char* strings
,
79 const uint8_t* fileContent
);
80 static const char* objCInfoSegmentName();
81 static const char* objCInfoSectionName();
85 uint32_t _linkeditStartOffset
;
89 template <> const char* File
<x86_64
>::objCInfoSegmentName() { return "__DATA"; }
90 template <> const char* File
<arm
>::objCInfoSegmentName() { return "__DATA"; }
91 template <typename A
> const char* File
<A
>::objCInfoSegmentName() { return "__OBJC"; }
93 template <> const char* File
<x86_64
>::objCInfoSectionName() { return "__objc_imageinfo"; }
94 template <> const char* File
<arm
>::objCInfoSectionName() { return "__objc_imageinfo"; }
95 template <typename A
> const char* File
<A
>::objCInfoSectionName() { return "__image_info"; }
98 File
<A
>::File(const uint8_t* fileContent
, uint64_t fileLength
, const char* path
, time_t mTime
,
99 ld::File::Ordinal ord
, bool linkingFlatNamespace
, bool linkingMainExecutable
,
100 bool hoistImplicitPublicDylibs
, Options::Platform platform
, uint32_t linkMinOSVersion
,
101 bool allowSimToMacOSX
, bool addVers
, bool buildingForSimulator
, bool logAllFiles
,
102 const char* targetInstallPath
, bool indirectDylib
, bool ignoreMismatchPlatform
, bool usingBitcode
)
103 : Base(strdup(path
), mTime
, ord
, platform
, linkMinOSVersion
, linkingFlatNamespace
,
104 hoistImplicitPublicDylibs
, allowSimToMacOSX
, addVers
), _fileLength(fileLength
), _linkeditStartOffset(0)
106 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
107 const uint32_t cmd_count
= header
->ncmds();
108 const macho_load_command
<P
>* const cmds
= (macho_load_command
<P
>*)((char*)header
+ sizeof(macho_header
<P
>));
109 const macho_load_command
<P
>* const cmdsEnd
= (macho_load_command
<P
>*)((char*)header
+ sizeof(macho_header
<P
>) + header
->sizeofcmds());
111 // write out path for -t option
113 printf("%s\n", path
);
115 // a "blank" stub has zero load commands
116 if ( (header
->filetype() == MH_DYLIB_STUB
) && (cmd_count
== 0) ) {
117 // no further processing needed
118 munmap((caddr_t
)fileContent
, fileLength
);
123 // optimize the case where we know there is no reason to look at indirect dylibs
124 this->_noRexports
= (header
->flags() & MH_NO_REEXPORTED_DYLIBS
)
125 || (header
->filetype() == MH_BUNDLE
)
126 || (header
->filetype() == MH_EXECUTE
); // bundles and exectuables can be used via -bundle_loader
127 this->_hasWeakExports
= (header
->flags() & MH_WEAK_DEFINES
);
128 this->_deadStrippable
= (header
->flags() & MH_DEAD_STRIPPABLE_DYLIB
);
129 this->_appExtensionSafe
= (header
->flags() & MH_APP_EXTENSION_SAFE
);
131 // pass 1: get pointers, and see if this dylib uses compressed LINKEDIT format
132 const macho_dysymtab_command
<P
>* dynamicInfo
= nullptr;
133 const macho_dyld_info_command
<P
>* dyldInfo
= nullptr;
134 const macho_nlist
<P
>* symbolTable
= nullptr;
135 const macho_symtab_command
<P
>* symtab
= nullptr;
136 const char* strings
= nullptr;
137 bool compressedLinkEdit
= false;
138 uint32_t dependentLibCount
= 0;
139 Options::Platform lcPlatform
= Options::kPlatformUnknown
;
140 const macho_load_command
<P
>* cmd
= cmds
;
141 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
142 macho_dylib_command
<P
>* dylibID
;
143 uint32_t cmdLength
= cmd
->cmdsize();
144 switch (cmd
->cmd()) {
146 symtab
= (macho_symtab_command
<P
>*)cmd
;
147 symbolTable
= (const macho_nlist
<P
>*)((char*)header
+ symtab
->symoff());
148 strings
= (char*)header
+ symtab
->stroff();
149 if ( (symtab
->stroff() + symtab
->strsize()) > fileLength
)
150 throwf("mach-o string pool extends beyond end of file in %s", path
);
153 dynamicInfo
= (macho_dysymtab_command
<P
>*)cmd
;
156 case LC_DYLD_INFO_ONLY
:
157 dyldInfo
= (macho_dyld_info_command
<P
>*)cmd
;
158 compressedLinkEdit
= true;
161 dylibID
= (macho_dylib_command
<P
>*)cmd
;
162 if ( dylibID
->name_offset() > cmdLength
)
163 throwf("malformed mach-o: LC_ID_DYLIB load command has offset (%u) outside its size (%u)", dylibID
->name_offset(), cmdLength
);
164 if ( (dylibID
->name_offset() + strlen(dylibID
->name()) + 1) > cmdLength
)
165 throwf("malformed mach-o: LC_ID_DYLIB load command string extends beyond end of load command");
166 this->_dylibInstallPath
= strdup(dylibID
->name());
167 this->_dylibTimeStamp
= dylibID
->timestamp();
168 this->_dylibCurrentVersion
= dylibID
->current_version();
169 this->_dylibCompatibilityVersion
= dylibID
->compatibility_version();
170 this->_hasPublicInstallName
= this->isPublicLocation(this->_dylibInstallPath
);
173 case LC_LOAD_WEAK_DYLIB
:
176 case LC_REEXPORT_DYLIB
:
177 this->_explictReExportFound
= true;
180 case LC_SUB_FRAMEWORK
:
181 this->_parentUmbrella
= strdup(((macho_sub_framework_command
<P
>*)cmd
)->umbrella());
184 this->_allowableClients
.push_back(strdup(((macho_sub_client_command
<P
>*)cmd
)->client()));
185 // <rdar://problem/20627554> Don't hoist "public" (in /usr/lib/) dylibs that should not be directly linked
186 this->_hasPublicInstallName
= false;
188 case LC_VERSION_MIN_MACOSX
:
189 case LC_VERSION_MIN_IPHONEOS
:
190 case LC_VERSION_MIN_WATCHOS
:
192 case LC_VERSION_MIN_TVOS
:
194 this->_minVersionInDylib
= (ld::MacVersionMin
)((macho_version_min_command
<P
>*)cmd
)->version();
195 this->_platformInDylib
= cmd
->cmd();
196 lcPlatform
= Options::platformForLoadCommand(this->_platformInDylib
);
198 case LC_CODE_SIGNATURE
:
200 case macho_segment_command
<P
>::CMD
:
201 // check for Objective-C info
202 if ( strncmp(((macho_segment_command
<P
>*)cmd
)->segname(), objCInfoSegmentName(), 6) == 0 ) {
203 const macho_segment_command
<P
>* segment
= (macho_segment_command
<P
>*)cmd
;
204 const macho_section
<P
>* const sectionsStart
= (macho_section
<P
>*)((char*)segment
+ sizeof(macho_segment_command
<P
>));
205 const macho_section
<P
>* const sectionsEnd
= §ionsStart
[segment
->nsects()];
206 for (const macho_section
<P
>* sect
=sectionsStart
; sect
< sectionsEnd
; ++sect
) {
207 if ( strncmp(sect
->sectname(), objCInfoSectionName(), strlen(objCInfoSectionName())) == 0 ) {
208 // struct objc_image_info {
209 // uint32_t version; // initially 0
212 // #define OBJC_IMAGE_SUPPORTS_GC 2
213 // #define OBJC_IMAGE_GC_ONLY 4
214 // #define OBJC_IMAGE_IS_SIMULATED 32
216 const uint32_t* contents
= (uint32_t*)(&fileContent
[sect
->offset()]);
217 if ( (sect
->size() >= 8) && (contents
[0] == 0) ) {
218 uint32_t flags
= E::get32(contents
[1]);
219 if ( (flags
& 4) == 4 )
220 this->_objcConstraint
= ld::File::objcConstraintGC
;
221 else if ( (flags
& 2) == 2 )
222 this->_objcConstraint
= ld::File::objcConstraintRetainReleaseOrGC
;
223 else if ( (flags
& 32) == 32 )
224 this->_objcConstraint
= ld::File::objcConstraintRetainReleaseForSimulator
;
226 this->_objcConstraint
= ld::File::objcConstraintRetainRelease
;
227 this->_swiftVersion
= ((flags
>> 8) & 0xFF);
229 else if ( sect
->size() > 0 ) {
230 warning("can't parse %s/%s section in %s", objCInfoSegmentName(), objCInfoSectionName(), path
);
235 // Construct bitcode if there is a bitcode bundle section in the dylib
236 // Record the size of the section because the content is not checked
237 else if ( strcmp(((macho_segment_command
<P
>*)cmd
)->segname(), "__LLVM") == 0 ) {
238 const macho_section
<P
>* const sect
= (macho_section
<P
>*)((char*)cmd
+ sizeof(macho_segment_command
<P
>));
239 if ( strncmp(sect
->sectname(), "__bundle", 8) == 0 )
240 this->_bitcode
= std::unique_ptr
<ld::Bitcode
>(new ld::Bitcode(NULL
, sect
->size()));
242 else if ( strcmp(((macho_segment_command
<P
>*)cmd
)->segname(), "__LINKEDIT") == 0 ) {
243 _linkeditStartOffset
= ((macho_segment_command
<P
>*)cmd
)->fileoff();
246 cmd
= (const macho_load_command
<P
>*)(((char*)cmd
)+cmdLength
);
248 throwf("malformed dylb, load command #%d is outside size of load commands in %s", i
, path
);
250 // arm/arm64 objects are default to ios platform if not set.
251 // rdar://problem/21746314
252 if (lcPlatform
== Options::kPlatformUnknown
&&
253 (std::is_same
<A
, arm
>::value
|| std::is_same
<A
, arm64
>::value
))
254 lcPlatform
= Options::kPlatformiOS
;
256 // check cross-linking
257 if ( lcPlatform
!= platform
) {
258 this->_wrongOS
= true;
259 if ( this->_addVersionLoadCommand
&& !indirectDylib
&& !ignoreMismatchPlatform
) {
260 if ( buildingForSimulator
) {
261 if ( !this->_allowSimToMacOSXLinking
) {
263 case Options::kPlatformOSX
:
264 case Options::kPlatformiOS
:
265 if ( lcPlatform
== Options::kPlatformUnknown
)
267 // fall through if the Platform is not Unknown
268 case Options::kPlatformWatchOS
:
269 // WatchOS errors on cross-linking when building for bitcode
271 throwf("building for %s simulator, but linking against dylib built for %s,",
272 Options::platformName(platform
),
273 Options::platformName(lcPlatform
));
275 warning("URGENT: building for %s simulator, but linking against dylib (%s) built for %s. "
276 "Note: This will be an error in the future.",
277 Options::platformName(platform
), path
,
278 Options::platformName(lcPlatform
));
281 case Options::kPlatform_tvOS
:
282 // tvOS is a warning temporarily. rdar://problem/21746965
284 throwf("building for %s simulator, but linking against dylib built for %s,",
285 Options::platformName(platform
),
286 Options::platformName(lcPlatform
));
288 warning("URGENT: building for %s simulator, but linking against dylib (%s) built for %s. "
289 "Note: This will be an error in the future.",
290 Options::platformName(platform
), path
,
291 Options::platformName(lcPlatform
));
294 case Options::kPlatformUnknown
:
295 // skip if the target platform is unknown
302 case Options::kPlatformOSX
:
303 case Options::kPlatformiOS
:
304 if ( lcPlatform
== Options::kPlatformUnknown
)
306 // fall through if the Platform is not Unknown
307 case Options::kPlatformWatchOS
:
308 // WatchOS errors on cross-linking when building for bitcode
310 throwf("building for %s, but linking against dylib built for %s,",
311 Options::platformName(platform
),
312 Options::platformName(lcPlatform
));
314 warning("URGENT: building for %s, but linking against dylib (%s) built for %s. "
315 "Note: This will be an error in the future.",
316 Options::platformName(platform
), path
,
317 Options::platformName(lcPlatform
));
320 case Options::kPlatform_tvOS
:
321 // tvOS is a warning temporarily. rdar://problem/21746965
323 throwf("building for %s, but linking against dylib built for %s,",
324 Options::platformName(platform
),
325 Options::platformName(lcPlatform
));
327 warning("URGENT: building for %s, but linking against dylib (%s) built for %s. "
328 "Note: This will be an error in the future.",
329 Options::platformName(platform
), path
,
330 Options::platformName(lcPlatform
));
333 case Options::kPlatformUnknown
:
334 // skip if the target platform is unknown
341 // figure out if we need to examine dependent dylibs
342 // with compressed LINKEDIT format, MH_NO_REEXPORTED_DYLIBS can be trusted
343 bool processDependentLibraries
= true;
344 if ( compressedLinkEdit
&& this->_noRexports
&& !linkingFlatNamespace
)
345 processDependentLibraries
= false;
347 if ( processDependentLibraries
) {
348 // pass 2 builds list of all dependent libraries
349 this->_dependentDylibs
.reserve(dependentLibCount
);
351 unsigned int reExportDylibCount
= 0;
352 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
353 uint32_t cmdLength
= cmd
->cmdsize();
354 const macho_dylib_command
<P
>* dylibCmd
= (macho_dylib_command
<P
>*)cmd
;
355 switch (cmd
->cmd()) {
357 case LC_LOAD_WEAK_DYLIB
:
358 // with new linkedit format only care about LC_REEXPORT_DYLIB
359 if ( compressedLinkEdit
&& !linkingFlatNamespace
)
361 case LC_REEXPORT_DYLIB
:
362 ++reExportDylibCount
;
363 if ( dylibCmd
->name_offset() > cmdLength
)
364 throwf("malformed mach-o: LC_*_DYLIB load command has offset (%u) outside its size (%u)", dylibCmd
->name_offset(), cmdLength
);
365 if ( (dylibCmd
->name_offset() + strlen(dylibCmd
->name()) + 1) > cmdLength
)
366 throwf("malformed mach-o: LC_*_DYLIB load command string extends beyond end of load command");
367 const char *path
= strdup(dylibCmd
->name());
368 bool reExport
= (cmd
->cmd() == LC_REEXPORT_DYLIB
);
369 if ( (targetInstallPath
== nullptr) || (strcmp(targetInstallPath
, path
) != 0) )
370 this->_dependentDylibs
.emplace_back(path
, reExport
);
373 cmd
= (const macho_load_command
<P
>*)(((char*)cmd
)+cmdLength
);
375 // verify MH_NO_REEXPORTED_DYLIBS bit was correct
376 if ( compressedLinkEdit
&& !linkingFlatNamespace
) {
377 if ( reExportDylibCount
== 0 )
378 throwf("malformed dylib has MH_NO_REEXPORTED_DYLIBS flag but no LC_REEXPORT_DYLIB load commands: %s", path
);
380 // pass 3 add re-export info
382 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
383 const char* frameworkLeafName
;
384 const char* dylibBaseName
;
385 switch (cmd
->cmd()) {
386 case LC_SUB_UMBRELLA
:
387 frameworkLeafName
= ((macho_sub_umbrella_command
<P
>*)cmd
)->sub_umbrella();
388 for (auto &dep
: this->_dependentDylibs
) {
389 const char* dylibName
= dep
.path
;
390 const char* lastSlash
= strrchr(dylibName
, '/');
391 if ( (lastSlash
!= nullptr) && (strcmp(&lastSlash
[1], frameworkLeafName
) == 0) )
396 dylibBaseName
= ((macho_sub_library_command
<P
>*)cmd
)->sub_library();
397 for (auto &dep
: this->_dependentDylibs
) {
398 const char* dylibName
= dep
.path
;
399 const char* lastSlash
= strrchr(dylibName
, '/');
400 const char* leafStart
= &lastSlash
[1];
401 if ( lastSlash
== nullptr )
402 leafStart
= dylibName
;
403 const char* firstDot
= strchr(leafStart
, '.');
404 int len
= strlen(leafStart
);
405 if ( firstDot
!= nullptr )
406 len
= firstDot
- leafStart
;
407 if ( strncmp(leafStart
, dylibBaseName
, len
) == 0 )
412 cmd
= (const macho_load_command
<P
>*)(((char*)cmd
)+cmd
->cmdsize());
416 // if framework, capture framework name
417 if ( this->_dylibInstallPath
!= NULL
) {
418 const char* lastSlash
= strrchr(this->_dylibInstallPath
, '/');
419 if ( lastSlash
!= NULL
) {
420 const char* leafName
= lastSlash
+1;
421 char frname
[strlen(leafName
)+32];
422 strcpy(frname
, leafName
);
423 strcat(frname
, ".framework/");
425 if ( strstr(this->_dylibInstallPath
, frname
) != NULL
)
426 this->_frameworkName
= leafName
;
430 // validate minimal load commands
431 if ( (this->_dylibInstallPath
== nullptr) && ((header
->filetype() == MH_DYLIB
) || (header
->filetype() == MH_DYLIB_STUB
)) )
432 throwf("dylib %s missing LC_ID_DYLIB load command", path
);
433 if ( dyldInfo
== nullptr ) {
434 if ( symbolTable
== nullptr )
435 throw "binary missing LC_SYMTAB load command";
436 if ( dynamicInfo
== nullptr )
437 throw "binary missing LC_DYSYMTAB load command";
440 if ( symtab
!= nullptr ) {
441 if ( symtab
->symoff() < _linkeditStartOffset
)
442 throwf("malformed mach-o, symbol table not in __LINKEDIT");
443 if ( symtab
->stroff() < _linkeditStartOffset
)
444 throwf("malformed mach-o, symbol table strings not in __LINKEDIT");
447 // if linking flat and this is a flat dylib, create one atom that references all imported symbols
448 if ( linkingFlatNamespace
&& linkingMainExecutable
&& ((header
->flags() & MH_TWOLEVEL
) == 0) ) {
449 std::vector
<const char*> importNames
;
450 importNames
.reserve(dynamicInfo
->nundefsym());
451 const macho_nlist
<P
>* start
= &symbolTable
[dynamicInfo
->iundefsym()];
452 const macho_nlist
<P
>* end
= &start
[dynamicInfo
->nundefsym()];
453 for (const macho_nlist
<P
>* sym
=start
; sym
< end
; ++sym
) {
454 importNames
.push_back(&strings
[sym
->n_strx()]);
456 this->_importAtom
= new generic::dylib::ImportAtom
<A
>(*this, importNames
);
460 if ( dyldInfo
!= nullptr )
461 buildExportHashTableFromExportInfo(dyldInfo
, fileContent
);
463 buildExportHashTableFromSymbolTable(dynamicInfo
, symbolTable
, strings
, fileContent
);
466 munmap((caddr_t
)fileContent
, fileLength
);
469 template <typename A
>
470 void File
<A
>::buildExportHashTableFromSymbolTable(const macho_dysymtab_command
<P
>* dynamicInfo
,
471 const macho_nlist
<P
>* symbolTable
,
472 const char* strings
, const uint8_t* fileContent
)
474 if ( dynamicInfo
->tocoff() == 0 ) {
475 if ( this->_s_logHashtable
)
476 fprintf(stderr
, "ld: building hashtable of %u toc entries for %s\n", dynamicInfo
->nextdefsym(), this->path());
477 const macho_nlist
<P
>* start
= &symbolTable
[dynamicInfo
->iextdefsym()];
478 const macho_nlist
<P
>* end
= &start
[dynamicInfo
->nextdefsym()];
479 this->_atoms
.reserve(dynamicInfo
->nextdefsym()); // set initial bucket count
480 for (const macho_nlist
<P
>* sym
=start
; sym
< end
; ++sym
) {
481 this->addSymbol(&strings
[sym
->n_strx()], (sym
->n_desc() & N_WEAK_DEF
) != 0, false, sym
->n_value());
485 int32_t count
= dynamicInfo
->ntoc();
486 this->_atoms
.reserve(count
); // set initial bucket count
487 if ( this->_s_logHashtable
)
488 fprintf(stderr
, "ld: building hashtable of %u entries for %s\n", count
, this->path());
489 const auto* toc
= reinterpret_cast<const dylib_table_of_contents
*>(fileContent
+ dynamicInfo
->tocoff());
490 for (int32_t i
= 0; i
< count
; ++i
) {
491 const uint32_t index
= E::get32(toc
[i
].symbol_index
);
492 const macho_nlist
<P
>* sym
= &symbolTable
[index
];
493 this->addSymbol(&strings
[sym
->n_strx()], (sym
->n_desc() & N_WEAK_DEF
) != 0, false, sym
->n_value());
497 // special case old libSystem
498 if ( (this->_dylibInstallPath
!= nullptr) && (strcmp(this->_dylibInstallPath
, "/usr/lib/libSystem.B.dylib") == 0) )
503 template <typename A
>
504 void File
<A
>::buildExportHashTableFromExportInfo(const macho_dyld_info_command
<P
>* dyldInfo
,
505 const uint8_t* fileContent
)
507 if ( this->_s_logHashtable
)
508 fprintf(stderr
, "ld: building hashtable from export info in %s\n", this->path());
509 if ( dyldInfo
->export_size() > 0 ) {
510 const uint8_t* start
= fileContent
+ dyldInfo
->export_off();
511 const uint8_t* end
= &start
[dyldInfo
->export_size()];
512 if ( (dyldInfo
->export_off() + dyldInfo
->export_size()) > _fileLength
)
513 throwf("malformed mach-o dylib, exports trie extends beyond end of file, ");
514 std::vector
<mach_o::trie::Entry
> list
;
515 parseTrie(start
, end
, list
);
516 for (const auto &entry
: list
)
517 this->addSymbol(entry
.name
,
518 entry
.flags
& EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION
,
519 (entry
.flags
& EXPORT_SYMBOL_FLAGS_KIND_MASK
) == EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL
,
526 void File
<x86_64
>::addDyldFastStub()
528 addSymbol("dyld_stub_binder");
532 void File
<x86
>::addDyldFastStub()
534 addSymbol("dyld_stub_binder");
537 template <typename A
>
538 void File
<A
>::addDyldFastStub()
543 template <typename A
>
547 using P
= typename
A::P
;
549 static bool validFile(const uint8_t* fileContent
, bool executableOrDyliborBundle
, bool subTypeMustMatch
=false, uint32_t subType
=0);
550 static const char* fileKind(const uint8_t* fileContent
);
551 static ld::dylib::File
* parse(const uint8_t* fileContent
, uint64_t fileLength
, const char* path
,
552 time_t mTime
, ld::File::Ordinal ordinal
, const Options
& opts
,
555 return new File
<A
>(fileContent
, fileLength
, path
, mTime
, ordinal
, opts
.flatNamespace(),
556 opts
.linkingMainExecutable(), opts
.implicitlyLinkIndirectPublicDylibs(),
557 opts
.platform(), opts
.minOSversion(),
558 opts
.allowSimulatorToLinkWithMacOSX(), opts
.addVersionLoadCommand(),
559 opts
.targetIOSSimulator(), opts
.logAllFiles(), opts
.installPath(),
560 indirectDylib
, opts
.outputKind() == Options::kPreload
, opts
.bundleBitcode());
568 bool Parser
<x86
>::validFile(const uint8_t* fileContent
, bool executableOrDyliborBundle
, bool subTypeMustMatch
, uint32_t subType
)
570 const auto* header
= reinterpret_cast<const macho_header
<P
>*>(fileContent
);
571 if ( header
->magic() != MH_MAGIC
)
573 if ( header
->cputype() != CPU_TYPE_I386
)
575 switch ( header
->filetype() ) {
580 if ( executableOrDyliborBundle
)
583 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
585 if ( executableOrDyliborBundle
)
588 throw "can't link with a main executable";
595 bool Parser
<x86_64
>::validFile(const uint8_t* fileContent
, bool executableOrDyliborBundle
, bool subTypeMustMatch
, uint32_t subType
)
597 const auto* header
= reinterpret_cast<const macho_header
<P
>*>(fileContent
);
598 if ( header
->magic() != MH_MAGIC_64
)
600 if ( header
->cputype() != CPU_TYPE_X86_64
)
602 switch ( header
->filetype() ) {
607 if ( executableOrDyliborBundle
)
610 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
612 if ( executableOrDyliborBundle
)
615 throw "can't link with a main executable";
622 bool Parser
<arm
>::validFile(const uint8_t* fileContent
, bool executableOrDyliborBundle
, bool subTypeMustMatch
, uint32_t subType
)
624 const auto* header
= reinterpret_cast<const macho_header
<P
>*>(fileContent
);
625 if ( header
->magic() != MH_MAGIC
)
627 if ( header
->cputype() != CPU_TYPE_ARM
)
629 if ( subTypeMustMatch
&& (header
->cpusubtype() != subType
) )
631 switch ( header
->filetype() ) {
636 if ( executableOrDyliborBundle
)
639 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
641 if ( executableOrDyliborBundle
)
644 throw "can't link with a main executable";
653 bool Parser
<arm64
>::validFile(const uint8_t* fileContent
, bool executableOrDyliborBundle
, bool subTypeMustMatch
, uint32_t subType
)
655 const auto* header
= reinterpret_cast<const macho_header
<P
>*>(fileContent
);
656 if ( header
->magic() != MH_MAGIC_64
)
658 if ( header
->cputype() != CPU_TYPE_ARM64
)
660 switch ( header
->filetype() ) {
665 if ( executableOrDyliborBundle
)
668 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
670 if ( executableOrDyliborBundle
)
673 throw "can't link with a main executable";
680 bool isDylibFile(const uint8_t* fileContent
, cpu_type_t
* result
, cpu_subtype_t
* subResult
)
682 if ( Parser
<x86_64
>::validFile(fileContent
, false) ) {
683 *result
= CPU_TYPE_X86_64
;
684 const auto* header
= reinterpret_cast<const macho_header
<Pointer64
<LittleEndian
>>*>(fileContent
);
685 *subResult
= header
->cpusubtype();
688 if ( Parser
<x86
>::validFile(fileContent
, false) ) {
689 *result
= CPU_TYPE_I386
;
690 *subResult
= CPU_SUBTYPE_X86_ALL
;
693 if ( Parser
<arm
>::validFile(fileContent
, false) ) {
694 *result
= CPU_TYPE_ARM
;
695 const auto* header
= reinterpret_cast<const macho_header
<Pointer32
<LittleEndian
>>*>(fileContent
);
696 *subResult
= header
->cpusubtype();
699 if ( Parser
<arm64
>::validFile(fileContent
, false) ) {
700 *result
= CPU_TYPE_ARM64
;
701 *subResult
= CPU_SUBTYPE_ARM64_ALL
;
708 const char* Parser
<x86
>::fileKind(const uint8_t* fileContent
)
710 const auto* header
= reinterpret_cast<const macho_header
<P
>*>(fileContent
);
711 if ( header
->magic() != MH_MAGIC
)
713 if ( header
->cputype() != CPU_TYPE_I386
)
719 const char* Parser
<x86_64
>::fileKind(const uint8_t* fileContent
)
721 const auto* header
= reinterpret_cast<const macho_header
<P
>*>(fileContent
);
722 if ( header
->magic() != MH_MAGIC_64
)
724 if ( header
->cputype() != CPU_TYPE_X86_64
)
730 const char* Parser
<arm
>::fileKind(const uint8_t* fileContent
)
732 const auto* header
= reinterpret_cast<const macho_header
<P
>*>(fileContent
);
733 if ( header
->magic() != MH_MAGIC
)
735 if ( header
->cputype() != CPU_TYPE_ARM
)
737 for (const auto* t
= archInfoArray
; t
->archName
!= nullptr; ++t
) {
738 if ( (t
->cpuType
== CPU_TYPE_ARM
) && ((cpu_subtype_t
)header
->cpusubtype() == t
->cpuSubType
) ) {
745 #if SUPPORT_ARCH_arm64
747 const char* Parser
<arm64
>::fileKind(const uint8_t* fileContent
)
749 const auto* header
= reinterpret_cast<const macho_header
<P
>*>(fileContent
);
750 if ( header
->magic() != MH_MAGIC_64
)
752 if ( header
->cputype() != CPU_TYPE_ARM64
)
759 // used by linker is error messages to describe mismatched files
761 const char* archName(const uint8_t* fileContent
)
763 if ( Parser
<x86_64
>::validFile(fileContent
, true) ) {
764 return Parser
<x86_64
>::fileKind(fileContent
);
766 if ( Parser
<x86
>::validFile(fileContent
, true) ) {
767 return Parser
<x86
>::fileKind(fileContent
);
769 if ( Parser
<arm
>::validFile(fileContent
, true) ) {
770 return Parser
<arm
>::fileKind(fileContent
);
772 #if SUPPORT_ARCH_arm64
773 if ( Parser
<arm64
>::validFile(fileContent
, false) ) {
774 return Parser
<arm64
>::fileKind(fileContent
);
782 // main function used by linker to instantiate ld::Files
784 ld::dylib::File
* parse(const uint8_t* fileContent
, uint64_t fileLength
, const char* path
,
785 time_t modTime
, const Options
& opts
, ld::File::Ordinal ordinal
,
786 bool bundleLoader
, bool indirectDylib
)
788 bool subTypeMustMatch
= opts
.enforceDylibSubtypesMatch();
789 switch ( opts
.architecture() ) {
790 #if SUPPORT_ARCH_x86_64
791 case CPU_TYPE_X86_64
:
792 if ( Parser
<x86_64
>::validFile(fileContent
, bundleLoader
, subTypeMustMatch
, opts
.subArchitecture()) )
793 return Parser
<x86_64
>::parse(fileContent
, fileLength
, path
, modTime
, ordinal
, opts
, indirectDylib
);
796 #if SUPPORT_ARCH_i386
798 if ( Parser
<x86
>::validFile(fileContent
, bundleLoader
, subTypeMustMatch
, opts
.subArchitecture()) )
799 return Parser
<x86
>::parse(fileContent
, fileLength
, path
, modTime
, ordinal
, opts
, indirectDylib
);
802 #if SUPPORT_ARCH_arm_any
804 if ( Parser
<arm
>::validFile(fileContent
, bundleLoader
, subTypeMustMatch
, opts
.subArchitecture()) )
805 return Parser
<arm
>::parse(fileContent
, fileLength
, path
, modTime
, ordinal
, opts
, indirectDylib
);
808 #if SUPPORT_ARCH_arm64
810 if ( Parser
<arm64
>::validFile(fileContent
, bundleLoader
, subTypeMustMatch
, opts
.subArchitecture()) )
811 return Parser
<arm64
>::parse(fileContent
, fileLength
, path
, modTime
, ordinal
, opts
, indirectDylib
);
819 }; // namespace dylib
820 }; // namespace mach_o