2 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
4 * Copyright (c) 2005-2011 Apple Inc. All rights reserved.
6 * @APPLE_LICENSE_HEADER_START@
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
30 #include <sys/param.h>
37 #include <unordered_map>
38 #include <unordered_set>
40 #include "Architectures.hpp"
41 #include "MachOFileAbstraction.hpp"
42 #include "MachOTrie.hpp"
43 #include "macho_dylib_file.h"
44 #include "../code-sign-blobs/superblob.h"
51 template <typename A
> class File
;
55 // An ExportAtom has no content. It exists so that the linker can track which imported
56 // symbols came from which dynamic libraries.
59 class ExportAtom
: public ld::Atom
62 ExportAtom(const File
<A
>& f
, const char* nm
, bool weakDef
,
63 bool tlv
, typename
A::P::uint_t address
)
64 : ld::Atom(f
._importProxySection
, ld::Atom::definitionProxy
,
65 (weakDef
? ld::Atom::combineByName
: ld::Atom::combineNever
),
66 ld::Atom::scopeLinkageUnit
,
67 (tlv
? ld::Atom::typeTLV
: ld::Atom::typeUnclassified
),
68 symbolTableNotIn
, false, false, false, ld::Atom::Alignment(0)),
69 _file(f
), _name(nm
), _address(address
) {}
70 // overrides of ld::Atom
71 virtual const ld::File
* file() const { return &_file
; }
72 virtual const char* name() const { return _name
; }
73 virtual uint64_t size() const { return 0; }
74 virtual uint64_t objectAddress() const { return _address
; }
75 virtual void copyRawContent(uint8_t buffer
[]) const { }
76 virtual void setScope(Scope
) { }
79 typedef typename
A::P P
;
80 typedef typename
A::P::uint_t pint_t
;
82 virtual ~ExportAtom() {}
92 // An ImportAtom has no content. It exists so that when linking a main executable flat-namespace
93 // the imports of all flat dylibs are checked
96 class ImportAtom
: public ld::Atom
99 ImportAtom(File
<A
>& f
, std::vector
<const char*>& imports
);
101 // overrides of ld::Atom
102 virtual ld::File
* file() const { return &_file
; }
103 virtual const char* name() const { return "import-atom"; }
104 virtual uint64_t size() const { return 0; }
105 virtual uint64_t objectAddress() const { return 0; }
106 virtual void copyRawContent(uint8_t buffer
[]) const { }
107 virtual void setScope(Scope
) { }
108 virtual ld::Fixup::iterator
fixupsBegin() const { return &_undefs
[0]; }
109 virtual ld::Fixup::iterator
fixupsEnd() const { return &_undefs
[_undefs
.size()]; }
112 typedef typename
A::P P
;
114 virtual ~ImportAtom() {}
118 mutable std::vector
<ld::Fixup
> _undefs
;
121 template <typename A
>
122 ImportAtom
<A
>::ImportAtom(File
<A
>& f
, std::vector
<const char*>& imports
)
123 : ld::Atom(f
._flatDummySection
, ld::Atom::definitionRegular
, ld::Atom::combineNever
, ld::Atom::scopeTranslationUnit
,
124 ld::Atom::typeUnclassified
, symbolTableNotIn
, false, false, false, ld::Atom::Alignment(0)), _file(f
)
126 for(std::vector
<const char*>::iterator it
=imports
.begin(); it
!= imports
.end(); ++it
) {
127 _undefs
.push_back(ld::Fixup(0, ld::Fixup::k1of1
, ld::Fixup::kindNone
, false, strdup(*it
)));
134 // The reader for a dylib extracts all exported symbols names from the memory-mapped
135 // dylib, builds a hash table, then unmaps the file. This is an important memory
136 // savings for large dylibs.
138 template <typename A
>
139 class File
: public ld::dylib::File
142 static bool validFile(const uint8_t* fileContent
, bool executableOrDylib
);
143 File(const uint8_t* fileContent
, uint64_t fileLength
, const char* path
,
144 time_t mTime
, ld::File::Ordinal ordinal
, bool linkingFlatNamespace
,
145 bool linkingMainExecutable
, bool hoistImplicitPublicDylibs
,
146 ld::MacVersionMin macMin
, ld::IOSVersionMin iPhoneMin
, bool allowSimToMacOSX
, bool addVers
,
147 bool logAllFiles
, const char* installPath
, bool indirectDylib
);
150 // overrides of ld::File
151 virtual bool forEachAtom(ld::File::AtomHandler
&) const;
152 virtual bool justInTimeforEachAtom(const char* name
, ld::File::AtomHandler
&) const;
153 virtual ld::File::ObjcConstraint
objCConstraint() const { return _objcContraint
; }
155 // overrides of ld::dylib::File
156 virtual void processIndirectLibraries(ld::dylib::File::DylibHandler
*, bool);
157 virtual bool providedExportAtom() const { return _providedAtom
; }
158 virtual const char* parentUmbrella() const { return _parentUmbrella
; }
159 virtual const std::vector
<const char*>* allowableClients() const { return _allowableClients
.size() != 0 ? &_allowableClients
: NULL
; }
160 virtual bool hasWeakExternals() const { return _hasWeakExports
; }
161 virtual bool deadStrippable() const { return _deadStrippable
; }
162 virtual bool hasPublicInstallName() const{ return _hasPublicInstallName
; }
163 virtual bool hasWeakDefinition(const char* name
) const;
164 virtual bool allSymbolsAreWeakImported() const;
165 virtual const void* codeSignatureDR() const { return _codeSignatureDR
; }
166 virtual bool installPathVersionSpecific() const { return _installPathOverride
; }
171 struct ReExportChain
{ ReExportChain
* prev
; File
<A
>* file
; };
173 void assertNoReExportCycles(ReExportChain
*);
176 typedef typename
A::P P
;
177 typedef typename
A::P::E E
;
178 typedef typename
A::P::uint_t pint_t
;
180 friend class ExportAtom
<A
>;
181 friend class ImportAtom
<A
>;
184 std::size_t operator()(const char* __s
) const {
185 unsigned long __h
= 0;
187 __h
= 5 * __h
+ *__s
;
191 struct AtomAndWeak
{ ld::Atom
* atom
; bool weakDef
; bool tlv
; pint_t address
; };
192 typedef std::unordered_map
<const char*, AtomAndWeak
, ld::CStringHash
, ld::CStringEquals
> NameToAtomMap
;
193 typedef std::unordered_set
<const char*, CStringHash
, ld::CStringEquals
> NameSet
;
195 struct Dependent
{ const char* path
; File
<A
>* dylib
; bool reExport
; };
197 bool containsOrReExports(const char* name
, bool* weakDef
, bool* tlv
, pint_t
* defAddress
) const;
198 bool isPublicLocation(const char* pth
);
199 bool wrongOS() { return _wrongOS
; }
200 void addSymbol(const char* name
, bool weak
, bool tlv
, pint_t address
);
201 void addDyldFastStub();
202 void buildExportHashTableFromExportInfo(const macho_dyld_info_command
<P
>* dyldInfo
,
203 const uint8_t* fileContent
);
204 void buildExportHashTableFromSymbolTable(const macho_dysymtab_command
<P
>* dynamicInfo
,
205 const macho_nlist
<P
>* symbolTable
, const char* strings
,
206 const uint8_t* fileContent
);
207 static uint32_t parseVersionNumber32(const char* versionString
);
208 static const char* objCInfoSegmentName();
209 static const char* objCInfoSectionName();
211 const ld::MacVersionMin _macVersionMin
;
212 const ld::IOSVersionMin _iOSVersionMin
;
213 const bool _allowSimToMacOSXLinking
;
214 const bool _addVersionLoadCommand
;
216 bool _implicitlyLinkPublicDylibs
;
217 ld::File::ObjcConstraint _objcContraint
;
218 ld::Section _importProxySection
;
219 ld::Section _flatDummySection
;
220 std::vector
<Dependent
> _dependentDylibs
;
221 std::vector
<const char*> _allowableClients
;
222 mutable NameToAtomMap _atoms
;
223 NameSet _ignoreExports
;
224 const char* _parentUmbrella
;
225 ImportAtom
<A
>* _importAtom
;
226 const void* _codeSignatureDR
;
228 bool _hasWeakExports
;
229 bool _deadStrippable
;
230 bool _hasPublicInstallName
;
231 mutable bool _providedAtom
;
232 bool _explictReExportFound
;
234 bool _installPathOverride
;
235 bool _indirectDylibsProcessed
;
237 static bool _s_logHashtable
;
240 template <typename A
>
241 bool File
<A
>::_s_logHashtable
= false;
243 template <> const char* File
<x86_64
>::objCInfoSegmentName() { return "__DATA"; }
244 template <> const char* File
<arm
>::objCInfoSegmentName() { return "__DATA"; }
245 template <typename A
> const char* File
<A
>::objCInfoSegmentName() { return "__OBJC"; }
247 template <> const char* File
<x86_64
>::objCInfoSectionName() { return "__objc_imageinfo"; }
248 template <> const char* File
<arm
>::objCInfoSectionName() { return "__objc_imageinfo"; }
249 template <typename A
> const char* File
<A
>::objCInfoSectionName() { return "__image_info"; }
251 template <typename A
>
252 File
<A
>::File(const uint8_t* fileContent
, uint64_t fileLength
, const char* pth
, time_t mTime
, ld::File::Ordinal ord
,
253 bool linkingFlatNamespace
, bool linkingMainExecutable
, bool hoistImplicitPublicDylibs
,
254 ld::MacVersionMin macMin
, ld::IOSVersionMin iOSMin
, bool allowSimToMacOSX
, bool addVers
,
255 bool logAllFiles
, const char* targetInstallPath
, bool indirectDylib
)
256 : ld::dylib::File(strdup(pth
), mTime
, ord
),
257 _macVersionMin(macMin
), _iOSVersionMin(iOSMin
), _allowSimToMacOSXLinking(allowSimToMacOSX
), _addVersionLoadCommand(addVers
),
258 _linkingFlat(linkingFlatNamespace
), _implicitlyLinkPublicDylibs(hoistImplicitPublicDylibs
),
259 _objcContraint(ld::File::objcConstraintNone
),
260 _importProxySection("__TEXT", "__import", ld::Section::typeImportProxies
, true),
261 _flatDummySection("__LINKEDIT", "__flat_dummy", ld::Section::typeLinkEdit
, true),
262 _parentUmbrella(NULL
), _importAtom(NULL
), _codeSignatureDR(NULL
),
263 _noRexports(false), _hasWeakExports(false),
264 _deadStrippable(false), _hasPublicInstallName(false),
265 _providedAtom(false), _explictReExportFound(false), _wrongOS(false), _installPathOverride(false), _indirectDylibsProcessed(false)
267 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
268 const uint32_t cmd_count
= header
->ncmds();
269 const macho_load_command
<P
>* const cmds
= (macho_load_command
<P
>*)((char*)header
+ sizeof(macho_header
<P
>));
270 const macho_load_command
<P
>* const cmdsEnd
= (macho_load_command
<P
>*)((char*)header
+ sizeof(macho_header
<P
>) + header
->sizeofcmds());
272 // write out path for -t option
276 // a "blank" stub has zero load commands
277 if ( (header
->filetype() == MH_DYLIB_STUB
) && (cmd_count
== 0) ) {
278 // no further processing needed
279 munmap((caddr_t
)fileContent
, fileLength
);
284 // optimize the case where we know there is no reason to look at indirect dylibs
285 _noRexports
= (header
->flags() & MH_NO_REEXPORTED_DYLIBS
)
286 || (header
->filetype() == MH_BUNDLE
)
287 || (header
->filetype() == MH_EXECUTE
); // bundles and exectuables can be used via -bundle_loader
288 _hasWeakExports
= (header
->flags() & MH_WEAK_DEFINES
);
289 _deadStrippable
= (header
->flags() & MH_DEAD_STRIPPABLE_DYLIB
);
291 // pass 1: get pointers, and see if this dylib uses compressed LINKEDIT format
292 const macho_dysymtab_command
<P
>* dynamicInfo
= NULL
;
293 const macho_dyld_info_command
<P
>* dyldInfo
= NULL
;
294 const macho_linkedit_data_command
<P
>* codeSignature
= NULL
;
295 const macho_nlist
<P
>* symbolTable
= NULL
;
296 const char* strings
= NULL
;
297 bool compressedLinkEdit
= false;
298 uint32_t dependentLibCount
= 0;
299 const macho_load_command
<P
>* cmd
= cmds
;
300 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
301 macho_dylib_command
<P
>* dylibID
;
302 const macho_symtab_command
<P
>* symtab
;
303 switch (cmd
->cmd()) {
305 symtab
= (macho_symtab_command
<P
>*)cmd
;
306 symbolTable
= (const macho_nlist
<P
>*)((char*)header
+ symtab
->symoff());
307 strings
= (char*)header
+ symtab
->stroff();
308 if ( (symtab
->stroff() + symtab
->strsize()) > fileLength
)
309 throwf("mach-o string pool extends beyond end of file in %s", pth
);
312 dynamicInfo
= (macho_dysymtab_command
<P
>*)cmd
;
315 case LC_DYLD_INFO_ONLY
:
316 dyldInfo
= (macho_dyld_info_command
<P
>*)cmd
;
317 compressedLinkEdit
= true;
320 dylibID
= (macho_dylib_command
<P
>*)cmd
;
321 _dylibInstallPath
= strdup(dylibID
->name());
322 _dylibTimeStamp
= dylibID
->timestamp();
323 _dylibCurrentVersion
= dylibID
->current_version();
324 _dylibCompatibilityVersion
= dylibID
->compatibility_version();
325 _hasPublicInstallName
= isPublicLocation(_dylibInstallPath
);
328 case LC_LOAD_WEAK_DYLIB
:
331 case LC_REEXPORT_DYLIB
:
332 _explictReExportFound
= true;
335 case LC_SUB_FRAMEWORK
:
336 _parentUmbrella
= strdup(((macho_sub_framework_command
<P
>*)cmd
)->umbrella());
339 _allowableClients
.push_back(strdup(((macho_sub_client_command
<P
>*)cmd
)->client()));
341 case LC_VERSION_MIN_MACOSX
:
342 if ( (_iOSVersionMin
!= ld::iOSVersionUnset
) && !_allowSimToMacOSXLinking
) {
344 if ( _addVersionLoadCommand
&& !indirectDylib
)
345 throw "building for iOS Simulator, but linking against dylib built for MacOSX";
348 case LC_VERSION_MIN_IPHONEOS
:
349 if ( _macVersionMin
!= ld::macVersionUnset
) {
351 if ( _addVersionLoadCommand
&& !indirectDylib
)
352 throw "building for MacOSX, but linking against dylib built for iOS Simulator";
355 case LC_CODE_SIGNATURE
:
356 codeSignature
= (macho_linkedit_data_command
<P
>* )cmd
;
358 case macho_segment_command
<P
>::CMD
:
359 // check for Objective-C info
360 if ( strcmp(((macho_segment_command
<P
>*)cmd
)->segname(), objCInfoSegmentName()) == 0 ) {
361 const macho_segment_command
<P
>* segment
= (macho_segment_command
<P
>*)cmd
;
362 const macho_section
<P
>* const sectionsStart
= (macho_section
<P
>*)((char*)segment
+ sizeof(macho_segment_command
<P
>));
363 const macho_section
<P
>* const sectionsEnd
= §ionsStart
[segment
->nsects()];
364 for (const macho_section
<P
>* sect
=sectionsStart
; sect
< sectionsEnd
; ++sect
) {
365 if ( strncmp(sect
->sectname(), objCInfoSectionName(), strlen(objCInfoSectionName())) == 0 ) {
366 // struct objc_image_info {
367 // uint32_t version; // initially 0
370 // #define OBJC_IMAGE_SUPPORTS_GC 2
371 // #define OBJC_IMAGE_GC_ONLY 4
372 // #define OBJC_IMAGE_IS_SIMULATED 32
374 const uint32_t* contents
= (uint32_t*)(&fileContent
[sect
->offset()]);
375 if ( (sect
->size() >= 8) && (contents
[0] == 0) ) {
376 uint32_t flags
= E::get32(contents
[1]);
377 if ( (flags
& 4) == 4 )
378 _objcContraint
= ld::File::objcConstraintGC
;
379 else if ( (flags
& 2) == 2 )
380 _objcContraint
= ld::File::objcConstraintRetainReleaseOrGC
;
381 else if ( (flags
& 32) == 32 )
382 _objcContraint
= ld::File::objcConstraintRetainReleaseForSimulator
;
384 _objcContraint
= ld::File::objcConstraintRetainRelease
;
386 else if ( sect
->size() > 0 ) {
387 warning("can't parse %s/%s section in %s", objCInfoSegmentName(), objCInfoSectionName(), this->path());
393 cmd
= (const macho_load_command
<P
>*)(((char*)cmd
)+cmd
->cmdsize());
395 throwf("malformed dylb, load command #%d is outside size of load commands in %s", i
, pth
);
398 // figure out if we need to examine dependent dylibs
399 // with compressed LINKEDIT format, MH_NO_REEXPORTED_DYLIBS can be trusted
400 bool processDependentLibraries
= true;
401 if ( compressedLinkEdit
&& _noRexports
&& !linkingFlatNamespace
)
402 processDependentLibraries
= false;
404 if ( processDependentLibraries
) {
405 // pass 2 builds list of all dependent libraries
406 _dependentDylibs
.reserve(dependentLibCount
);
408 unsigned int reExportDylibCount
= 0;
409 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
410 switch (cmd
->cmd()) {
412 case LC_LOAD_WEAK_DYLIB
:
413 // with new linkedit format only care about LC_REEXPORT_DYLIB
414 if ( compressedLinkEdit
&& !linkingFlatNamespace
)
416 case LC_REEXPORT_DYLIB
:
417 ++reExportDylibCount
;
419 entry
.path
= strdup(((macho_dylib_command
<P
>*)cmd
)->name());
421 entry
.reExport
= (cmd
->cmd() == LC_REEXPORT_DYLIB
);
422 if ( (targetInstallPath
== NULL
) || (strcmp(targetInstallPath
, entry
.path
) != 0) )
423 _dependentDylibs
.push_back(entry
);
426 cmd
= (const macho_load_command
<P
>*)(((char*)cmd
)+cmd
->cmdsize());
428 // verify MH_NO_REEXPORTED_DYLIBS bit was correct
429 if ( compressedLinkEdit
&& !linkingFlatNamespace
) {
430 assert(reExportDylibCount
!= 0);
432 // pass 3 add re-export info
434 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
435 const char* frameworkLeafName
;
436 const char* dylibBaseName
;
437 switch (cmd
->cmd()) {
438 case LC_SUB_UMBRELLA
:
439 frameworkLeafName
= ((macho_sub_umbrella_command
<P
>*)cmd
)->sub_umbrella();
440 for (typename
std::vector
<Dependent
>::iterator it
= _dependentDylibs
.begin(); it
!= _dependentDylibs
.end(); ++it
) {
441 const char* dylibName
= it
->path
;
442 const char* lastSlash
= strrchr(dylibName
, '/');
443 if ( (lastSlash
!= NULL
) && (strcmp(&lastSlash
[1], frameworkLeafName
) == 0) )
448 dylibBaseName
= ((macho_sub_library_command
<P
>*)cmd
)->sub_library();
449 for (typename
std::vector
<Dependent
>::iterator it
= _dependentDylibs
.begin(); it
!= _dependentDylibs
.end(); ++it
) {
450 const char* dylibName
= it
->path
;
451 const char* lastSlash
= strrchr(dylibName
, '/');
452 const char* leafStart
= &lastSlash
[1];
453 if ( lastSlash
== NULL
)
454 leafStart
= dylibName
;
455 const char* firstDot
= strchr(leafStart
, '.');
456 int len
= strlen(leafStart
);
457 if ( firstDot
!= NULL
)
458 len
= firstDot
- leafStart
;
459 if ( strncmp(leafStart
, dylibBaseName
, len
) == 0 )
464 cmd
= (const macho_load_command
<P
>*)(((char*)cmd
)+cmd
->cmdsize());
468 // validate minimal load commands
469 if ( (_dylibInstallPath
== NULL
) && ((header
->filetype() == MH_DYLIB
) || (header
->filetype() == MH_DYLIB_STUB
)) )
470 throwf("dylib %s missing LC_ID_DYLIB load command", pth
);
471 if ( dyldInfo
== NULL
) {
472 if ( symbolTable
== NULL
)
473 throw "binary missing LC_SYMTAB load command";
474 if ( dynamicInfo
== NULL
)
475 throw "binary missing LC_DYSYMTAB load command";
478 // if linking flat and this is a flat dylib, create one atom that references all imported symbols
479 if ( linkingFlatNamespace
&& linkingMainExecutable
&& ((header
->flags() & MH_TWOLEVEL
) == 0) ) {
480 std::vector
<const char*> importNames
;
481 importNames
.reserve(dynamicInfo
->nundefsym());
482 const macho_nlist
<P
>* start
= &symbolTable
[dynamicInfo
->iundefsym()];
483 const macho_nlist
<P
>* end
= &start
[dynamicInfo
->nundefsym()];
484 for (const macho_nlist
<P
>* sym
=start
; sym
< end
; ++sym
) {
485 importNames
.push_back(&strings
[sym
->n_strx()]);
487 _importAtom
= new ImportAtom
<A
>(*this, importNames
);
490 // if the dylib is code signed, look for its Designated Requirement
491 if ( codeSignature
!= NULL
) {
492 const Security::BlobCore
* overallSignature
= (Security::BlobCore
*)((char*)header
+ codeSignature
->dataoff());
493 typedef Security::SuperBlob
<Security::kSecCodeMagicEmbeddedSignature
> EmbeddedSignatureBlob
;
494 typedef Security::SuperBlob
<Security::kSecCodeMagicRequirementSet
> InternalRequirementsBlob
;
495 const EmbeddedSignatureBlob
* signature
= EmbeddedSignatureBlob::specific(overallSignature
);
496 if ( signature
->validateBlob(codeSignature
->datasize()) ) {
497 const InternalRequirementsBlob
* ireq
= signature
->find
<InternalRequirementsBlob
>(Security::cdRequirementsSlot
);
498 if ( (ireq
!= NULL
) && ireq
->validateBlob() ) {
499 const Security::BlobCore
* dr
= ireq
->find(Security::kSecDesignatedRequirementType
);
500 if ( (dr
!= NULL
) && dr
->validateBlob(Security::kSecCodeMagicRequirement
) ) {
501 // <rdar://problem/10968461> make copy because mapped file is about to be unmapped
502 _codeSignatureDR
= ::malloc(dr
->length());
503 ::memcpy((void*)_codeSignatureDR
, dr
, dr
->length());
510 if ( dyldInfo
!= NULL
)
511 buildExportHashTableFromExportInfo(dyldInfo
, fileContent
);
513 buildExportHashTableFromSymbolTable(dynamicInfo
, symbolTable
, strings
, fileContent
);
516 munmap((caddr_t
)fileContent
, fileLength
);
520 // Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
522 template <typename A
>
523 uint32_t File
<A
>::parseVersionNumber32(const char* versionString
)
529 x
= strtoul(versionString
, &end
, 10);
531 y
= strtoul(&end
[1], &end
, 10);
533 z
= strtoul(&end
[1], &end
, 10);
536 if ( (*end
!= '\0') || (x
> 0xffff) || (y
> 0xff) || (z
> 0xff) )
537 throwf("malformed 32-bit x.y.z version number: %s", versionString
);
539 return (x
<< 16) | ( y
<< 8 ) | z
;
542 template <typename A
>
543 void File
<A
>::buildExportHashTableFromSymbolTable(const macho_dysymtab_command
<P
>* dynamicInfo
,
544 const macho_nlist
<P
>* symbolTable
, const char* strings
,
545 const uint8_t* fileContent
)
547 if ( dynamicInfo
->tocoff() == 0 ) {
548 if ( _s_logHashtable
) fprintf(stderr
, "ld: building hashtable of %u toc entries for %s\n", dynamicInfo
->nextdefsym(), this->path());
549 const macho_nlist
<P
>* start
= &symbolTable
[dynamicInfo
->iextdefsym()];
550 const macho_nlist
<P
>* end
= &start
[dynamicInfo
->nextdefsym()];
551 _atoms
.reserve(dynamicInfo
->nextdefsym()); // set initial bucket count
552 for (const macho_nlist
<P
>* sym
=start
; sym
< end
; ++sym
) {
553 this->addSymbol(&strings
[sym
->n_strx()], (sym
->n_desc() & N_WEAK_DEF
) != 0, false, sym
->n_value());
557 int32_t count
= dynamicInfo
->ntoc();
558 _atoms
.reserve(count
); // set initial bucket count
559 if ( _s_logHashtable
) fprintf(stderr
, "ld: building hashtable of %u entries for %s\n", count
, this->path());
560 const struct dylib_table_of_contents
* toc
= (dylib_table_of_contents
*)(fileContent
+ dynamicInfo
->tocoff());
561 for (int32_t i
= 0; i
< count
; ++i
) {
562 const uint32_t index
= E::get32(toc
[i
].symbol_index
);
563 const macho_nlist
<P
>* sym
= &symbolTable
[index
];
564 this->addSymbol(&strings
[sym
->n_strx()], (sym
->n_desc() & N_WEAK_DEF
) != 0, false, sym
->n_value());
568 // special case old libSystem
569 if ( (_dylibInstallPath
!= NULL
) && (strcmp(_dylibInstallPath
, "/usr/lib/libSystem.B.dylib") == 0) )
574 template <typename A
>
575 void File
<A
>::buildExportHashTableFromExportInfo(const macho_dyld_info_command
<P
>* dyldInfo
,
576 const uint8_t* fileContent
)
578 if ( _s_logHashtable
) fprintf(stderr
, "ld: building hashtable from export info in %s\n", this->path());
579 if ( dyldInfo
->export_size() > 0 ) {
580 const uint8_t* start
= fileContent
+ dyldInfo
->export_off();
581 const uint8_t* end
= &start
[dyldInfo
->export_size()];
582 std::vector
<mach_o::trie::Entry
> list
;
583 parseTrie(start
, end
, list
);
584 for (std::vector
<mach_o::trie::Entry
>::iterator it
=list
.begin(); it
!= list
.end(); ++it
)
585 this->addSymbol(it
->name
,
586 it
->flags
& EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION
,
587 (it
->flags
& EXPORT_SYMBOL_FLAGS_KIND_MASK
) == EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL
,
594 void File
<x86_64
>::addDyldFastStub()
596 addSymbol("dyld_stub_binder", false, false, 0);
600 void File
<x86
>::addDyldFastStub()
602 addSymbol("dyld_stub_binder", false, false, 0);
605 template <typename A
>
606 void File
<A
>::addDyldFastStub()
611 template <typename A
>
612 void File
<A
>::addSymbol(const char* name
, bool weakDef
, bool tlv
, pint_t address
)
614 //fprintf(stderr, "addSymbol() %s\n", name);
615 // symbols that start with $ld$ are meta-data to the static linker
616 // <rdar://problem/5182537> need way for ld and dyld to see different exported symbols in a dylib
617 if ( strncmp(name
, "$ld$", 4) == 0 ) {
618 // $ld$ <action> $ <condition> $ <symbol-name>
619 const char* symAction
= &name
[4];
620 const char* symCond
= strchr(symAction
, '$');
621 if ( symCond
!= NULL
) {
623 if ( _macVersionMin
!= ld::macVersionUnset
) {
624 sprintf(curOSVers
, "$os%d.%d$", (_macVersionMin
>> 16), ((_macVersionMin
>> 8) & 0xFF));
626 else if ( _iOSVersionMin
!= ld::iOSVersionUnset
) {
627 sprintf(curOSVers
, "$os%d.%d$", (_iOSVersionMin
>> 16), ((_iOSVersionMin
>> 8) & 0xFF));
630 assert(0 && "targeting neither macosx nor iphoneos");
632 if ( strncmp(symCond
, curOSVers
, strlen(curOSVers
)) == 0 ) {
633 const char* symName
= strchr(&symCond
[1], '$');
634 if ( symName
!= NULL
) {
636 if ( strncmp(symAction
, "hide$", 5) == 0 ) {
637 if ( _s_logHashtable
) fprintf(stderr
, " adding %s to ignore set for %s\n", symName
, this->path());
638 _ignoreExports
.insert(strdup(symName
));
641 else if ( strncmp(symAction
, "add$", 4) == 0 ) {
642 this->addSymbol(symName
, weakDef
, false, 0);
645 else if ( strncmp(symAction
, "install_name$", 13) == 0 ) {
646 _dylibInstallPath
= symName
;
647 _installPathOverride
= true;
648 // <rdar://problem/14448206> CoreGraphics redirects to ApplicationServices, but with wrong compat version
649 if ( strcmp(_dylibInstallPath
, "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices") == 0 )
650 _dylibCompatibilityVersion
= parseVersionNumber32("1.0");
653 else if ( strncmp(symAction
, "compatibility_version$", 22) == 0 ) {
654 _dylibCompatibilityVersion
= parseVersionNumber32(symName
);
658 warning("bad symbol action: %s in dylib %s", name
, this->path());
664 warning("bad symbol condition: %s in dylib %s", name
, this->path());
668 // add symbol as possible export if we are not supposed to ignore it
669 if ( _ignoreExports
.count(name
) == 0 ) {
672 bucket
.weakDef
= weakDef
;
674 bucket
.address
= address
;
675 if ( _s_logHashtable
) fprintf(stderr
, " adding %s to hash table for %s\n", name
, this->path());
676 _atoms
[strdup(name
)] = bucket
;
681 template <typename A
>
682 bool File
<A
>::forEachAtom(ld::File::AtomHandler
& handler
) const
684 handler
.doFile(*this);
685 // if doing flatnamespace and need all this dylib's imports resolve
686 // add atom which references alls undefines in this dylib
687 if ( _importAtom
!= NULL
) {
688 handler
.doAtom(*_importAtom
);
694 template <typename A
>
695 bool File
<A
>::hasWeakDefinition(const char* name
) const
697 // if supposed to ignore this export, then pretend I don't have it
698 if ( _ignoreExports
.count(name
) != 0 )
701 typename
NameToAtomMap::const_iterator pos
= _atoms
.find(name
);
702 if ( pos
!= _atoms
.end() ) {
703 return pos
->second
.weakDef
;
706 // look in children that I re-export
707 for (typename
std::vector
<Dependent
>::const_iterator it
= _dependentDylibs
.begin(); it
!= _dependentDylibs
.end(); ++it
) {
708 if ( it
->reExport
) {
709 //fprintf(stderr, "getJustInTimeAtomsFor: %s NOT found in %s, looking in child %s\n", name, this->path(), (*it)->getInstallPath());
710 typename
NameToAtomMap::iterator cpos
= it
->dylib
->_atoms
.find(name
);
711 if ( cpos
!= it
->dylib
->_atoms
.end() )
712 return cpos
->second
.weakDef
;
720 // <rdar://problem/5529626> If only weak_import symbols are used, linker should use LD_LOAD_WEAK_DYLIB
721 template <typename A
>
722 bool File
<A
>::allSymbolsAreWeakImported() const
724 bool foundNonWeakImport
= false;
725 bool foundWeakImport
= false;
726 //fprintf(stderr, "%s:\n", this->path());
727 for (typename
NameToAtomMap::const_iterator it
= _atoms
.begin(); it
!= _atoms
.end(); ++it
) {
728 const ld::Atom
* atom
= it
->second
.atom
;
729 if ( atom
!= NULL
) {
730 if ( atom
->weakImported() )
731 foundWeakImport
= true;
733 foundNonWeakImport
= true;
734 //fprintf(stderr, " weak_import=%d, name=%s\n", atom->weakImported(), it->first);
738 // don't automatically weak link dylib with no imports
739 // so at least one weak import symbol and no non-weak-imported symbols must be found
740 return foundWeakImport
&& !foundNonWeakImport
;
744 template <typename A
>
745 bool File
<A
>::containsOrReExports(const char* name
, bool* weakDef
, bool* tlv
, pint_t
* defAddress
) const
747 if ( _ignoreExports
.count(name
) != 0 )
751 typename
NameToAtomMap::iterator pos
= _atoms
.find(name
);
752 if ( pos
!= _atoms
.end() ) {
753 *weakDef
= pos
->second
.weakDef
;
754 *tlv
= pos
->second
.tlv
;
755 *defAddress
= pos
->second
.address
;
759 // check dylibs I re-export
760 for (typename
std::vector
<Dependent
>::const_iterator it
= _dependentDylibs
.begin(); it
!= _dependentDylibs
.end(); ++it
) {
761 if ( it
->reExport
&& !it
->dylib
->implicitlyLinked() ) {
762 if ( it
->dylib
->containsOrReExports(name
, weakDef
, tlv
, defAddress
) )
771 template <typename A
>
772 bool File
<A
>::justInTimeforEachAtom(const char* name
, ld::File::AtomHandler
& handler
) const
774 // if supposed to ignore this export, then pretend I don't have it
775 if ( _ignoreExports
.count(name
) != 0 )
780 if ( this->containsOrReExports(name
, &bucket
.weakDef
, &bucket
.tlv
, &bucket
.address
) ) {
781 bucket
.atom
= new ExportAtom
<A
>(*this, name
, bucket
.weakDef
, bucket
.tlv
, bucket
.address
);
782 _atoms
[name
] = bucket
;
783 _providedAtom
= true;
784 if ( _s_logHashtable
) fprintf(stderr
, "getJustInTimeAtomsFor: %s found in %s\n", name
, this->path());
785 // call handler with new export atom
786 handler
.doAtom(*bucket
.atom
);
795 template <typename A
>
796 bool File
<A
>::isPublicLocation(const char* pth
)
798 // -no_implicit_dylibs disables this optimization
799 if ( ! _implicitlyLinkPublicDylibs
)
802 // /usr/lib is a public location
803 if ( (strncmp(pth
, "/usr/lib/", 9) == 0) && (strchr(&pth
[9], '/') == NULL
) )
806 // /System/Library/Frameworks/ is a public location
807 if ( strncmp(pth
, "/System/Library/Frameworks/", 27) == 0 ) {
808 const char* frameworkDot
= strchr(&pth
[27], '.');
809 // but only top level framework
810 // /System/Library/Frameworks/Foo.framework/Versions/A/Foo ==> true
811 // /System/Library/Frameworks/Foo.framework/Resources/libBar.dylib ==> false
812 // /System/Library/Frameworks/Foo.framework/Frameworks/Bar.framework/Bar ==> false
813 // /System/Library/Frameworks/Foo.framework/Frameworks/Xfoo.framework/XFoo ==> false
814 if ( frameworkDot
!= NULL
) {
815 int frameworkNameLen
= frameworkDot
- &pth
[27];
816 if ( strncmp(&pth
[strlen(pth
)-frameworkNameLen
-1], &pth
[26], frameworkNameLen
+1) == 0 )
824 template <typename A
>
825 void File
<A
>::processIndirectLibraries(ld::dylib::File::DylibHandler
* handler
, bool addImplicitDylibs
)
828 if ( _indirectDylibsProcessed
)
830 const static bool log
= false;
831 if ( log
) fprintf(stderr
, "processIndirectLibraries(%s)\n", this->installPath());
832 if ( _linkingFlat
) {
833 for (typename
std::vector
<Dependent
>::iterator it
= _dependentDylibs
.begin(); it
!= _dependentDylibs
.end(); it
++) {
834 it
->dylib
= (File
<A
>*)handler
->findDylib(it
->path
, this->path());
837 else if ( _noRexports
) {
838 // MH_NO_REEXPORTED_DYLIBS bit set, then nothing to do
841 // two-level, might have re-exports
842 for (typename
std::vector
<Dependent
>::iterator it
= _dependentDylibs
.begin(); it
!= _dependentDylibs
.end(); it
++) {
843 if ( it
->reExport
) {
844 if ( log
) fprintf(stderr
, "processIndirectLibraries() parent=%s, child=%s\n", this->installPath(), it
->path
);
845 // a LC_REEXPORT_DYLIB, LC_SUB_UMBRELLA or LC_SUB_LIBRARY says we re-export this child
846 it
->dylib
= (File
<A
>*)handler
->findDylib(it
->path
, this->path());
847 if ( it
->dylib
->hasPublicInstallName() && !it
->dylib
->wrongOS() ) {
848 // promote this child to be automatically added as a direct dependent if this already is
849 if ( (this->explicitlyLinked() || this->implicitlyLinked()) && (strcmp(it
->path
,it
->dylib
->installPath()) == 0) ) {
850 if ( log
) fprintf(stderr
, "processIndirectLibraries() implicitly linking %s\n", it
->dylib
->installPath());
851 it
->dylib
->setImplicitlyLinked();
853 else if ( it
->dylib
->explicitlyLinked() || it
->dylib
->implicitlyLinked() ) {
854 if ( log
) fprintf(stderr
, "processIndirectLibraries() parent is not directly linked, but child is, so no need to re-export child\n");
857 if ( log
) fprintf(stderr
, "processIndirectLibraries() parent is not directly linked, so parent=%s will re-export child=%s\n", this->installPath(), it
->path
);
861 // add all child's symbols to me
862 if ( log
) fprintf(stderr
, "processIndirectLibraries() child is not public, so parent=%s will re-export child=%s\n", this->installPath(), it
->path
);
865 else if ( !_explictReExportFound
) {
866 // see if child contains LC_SUB_FRAMEWORK with my name
867 it
->dylib
= (File
<A
>*)handler
->findDylib(it
->path
, this->path());
868 const char* parentUmbrellaName
= it
->dylib
->parentUmbrella();
869 if ( parentUmbrellaName
!= NULL
) {
870 const char* parentName
= this->path();
871 const char* lastSlash
= strrchr(parentName
, '/');
872 if ( (lastSlash
!= NULL
) && (strcmp(&lastSlash
[1], parentUmbrellaName
) == 0) ) {
873 // add all child's symbols to me
875 if ( log
) fprintf(stderr
, "processIndirectLibraries() umbrella=%s will re-export child=%s\n", this->installPath(), it
->path
);
882 // check for re-export cycles
886 this->assertNoReExportCycles(&chain
);
888 _indirectDylibsProcessed
= true;
891 template <typename A
>
892 void File
<A
>::assertNoReExportCycles(ReExportChain
* prev
)
894 // recursively check my re-exported dylibs
898 for (typename
std::vector
<Dependent
>::iterator it
= _dependentDylibs
.begin(); it
!= _dependentDylibs
.end(); it
++) {
899 if ( it
->reExport
) {
900 ld::File
* child
= it
->dylib
;
901 // check child is not already in chain
902 for (ReExportChain
* p
= prev
; p
!= NULL
; p
= p
->prev
) {
903 if ( p
->file
== child
) {
904 throwf("cycle in dylib re-exports with %s and %s", child
->path(), this->path());
907 if ( it
->dylib
!= NULL
)
908 it
->dylib
->assertNoReExportCycles(&chain
);
914 template <typename A
>
918 typedef typename
A::P P
;
920 static bool validFile(const uint8_t* fileContent
, bool executableOrDyliborBundle
);
921 static const char* fileKind(const uint8_t* fileContent
);
922 static ld::dylib::File
* parse(const uint8_t* fileContent
, uint64_t fileLength
,
923 const char* path
, time_t mTime
,
924 ld::File::Ordinal ordinal
, const Options
& opts
, bool indirectDylib
) {
925 return new File
<A
>(fileContent
, fileLength
, path
, mTime
,
926 ordinal
, opts
.flatNamespace(),
927 opts
.linkingMainExecutable(),
928 opts
.implicitlyLinkIndirectPublicDylibs(),
929 opts
.macosxVersionMin(),
930 opts
.iOSVersionMin(),
931 opts
.allowSimulatorToLinkWithMacOSX(),
932 opts
.addVersionLoadCommand(),
943 bool Parser
<x86
>::validFile(const uint8_t* fileContent
, bool executableOrDyliborBundle
)
945 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
946 if ( header
->magic() != MH_MAGIC
)
948 if ( header
->cputype() != CPU_TYPE_I386
)
950 switch ( header
->filetype() ) {
955 if ( executableOrDyliborBundle
)
958 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
960 if ( executableOrDyliborBundle
)
963 throw "can't link with a main executable";
970 bool Parser
<x86_64
>::validFile(const uint8_t* fileContent
, bool executableOrDyliborBundle
)
972 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
973 if ( header
->magic() != MH_MAGIC_64
)
975 if ( header
->cputype() != CPU_TYPE_X86_64
)
977 switch ( header
->filetype() ) {
982 if ( executableOrDyliborBundle
)
985 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
987 if ( executableOrDyliborBundle
)
990 throw "can't link with a main executable";
997 bool Parser
<arm
>::validFile(const uint8_t* fileContent
, bool executableOrDyliborBundle
)
999 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1000 if ( header
->magic() != MH_MAGIC
)
1002 if ( header
->cputype() != CPU_TYPE_ARM
)
1004 switch ( header
->filetype() ) {
1009 if ( executableOrDyliborBundle
)
1012 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
1014 if ( executableOrDyliborBundle
)
1017 throw "can't link with a main executable";
1026 bool Parser
<arm64
>::validFile(const uint8_t* fileContent
, bool executableOrDyliborBundle
)
1028 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1029 if ( header
->magic() != MH_MAGIC_64
)
1031 if ( header
->cputype() != CPU_TYPE_ARM64
)
1033 switch ( header
->filetype() ) {
1038 if ( executableOrDyliborBundle
)
1041 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
1043 if ( executableOrDyliborBundle
)
1046 throw "can't link with a main executable";
1053 bool isDylibFile(const uint8_t* fileContent
, cpu_type_t
* result
, cpu_subtype_t
* subResult
)
1055 if ( Parser
<x86_64
>::validFile(fileContent
, false) ) {
1056 *result
= CPU_TYPE_X86_64
;
1057 const macho_header
<Pointer64
<LittleEndian
> >* header
= (const macho_header
<Pointer64
<LittleEndian
> >*)fileContent
;
1058 *subResult
= header
->cpusubtype();
1061 if ( Parser
<x86
>::validFile(fileContent
, false) ) {
1062 *result
= CPU_TYPE_I386
;
1063 *subResult
= CPU_SUBTYPE_X86_ALL
;
1066 if ( Parser
<arm
>::validFile(fileContent
, false) ) {
1067 *result
= CPU_TYPE_ARM
;
1068 const macho_header
<Pointer32
<LittleEndian
> >* header
= (const macho_header
<Pointer32
<LittleEndian
> >*)fileContent
;
1069 *subResult
= header
->cpusubtype();
1072 if ( Parser
<arm64
>::validFile(fileContent
, false) ) {
1073 *result
= CPU_TYPE_ARM64
;
1074 *subResult
= CPU_SUBTYPE_ARM64_ALL
;
1077 if ( Parser
<ppc
>::validFile(fileContent
, false) ) {
1078 *result
= CPU_TYPE_POWERPC
;
1079 const macho_header
<Pointer32
<BigEndian
> >* header
= (const macho_header
<Pointer32
<BigEndian
> >*)fileContent
;
1080 *subResult
= header
->cpusubtype();
1083 if ( Parser
<ppc64
>::validFile(fileContent
, false) ) {
1084 *result
= CPU_TYPE_POWERPC64
;
1085 *subResult
= CPU_SUBTYPE_POWERPC_ALL
;
1092 const char* Parser
<x86
>::fileKind(const uint8_t* fileContent
)
1094 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1095 if ( header
->magic() != MH_MAGIC
)
1097 if ( header
->cputype() != CPU_TYPE_I386
)
1103 const char* Parser
<x86_64
>::fileKind(const uint8_t* fileContent
)
1105 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1106 if ( header
->magic() != MH_MAGIC_64
)
1108 if ( header
->cputype() != CPU_TYPE_X86_64
)
1114 const char* Parser
<arm
>::fileKind(const uint8_t* fileContent
)
1116 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1117 if ( header
->magic() != MH_MAGIC
)
1119 if ( header
->cputype() != CPU_TYPE_ARM
)
1121 for (const ArchInfo
* t
=archInfoArray
; t
->archName
!= NULL
; ++t
) {
1122 if ( (t
->cpuType
== CPU_TYPE_ARM
) && ((cpu_subtype_t
)header
->cpusubtype() == t
->cpuSubType
) ) {
1129 #if SUPPORT_ARCH_arm64
1131 const char* Parser
<arm64
>::fileKind(const uint8_t* fileContent
)
1133 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1134 if ( header
->magic() != MH_MAGIC_64
)
1136 if ( header
->cputype() != CPU_TYPE_ARM64
)
1143 // used by linker is error messages to describe mismatched files
1145 const char* archName(const uint8_t* fileContent
)
1147 if ( Parser
<x86_64
>::validFile(fileContent
, true) ) {
1148 return Parser
<x86_64
>::fileKind(fileContent
);
1150 if ( Parser
<x86
>::validFile(fileContent
, true) ) {
1151 return Parser
<x86
>::fileKind(fileContent
);
1153 if ( Parser
<arm
>::validFile(fileContent
, true) ) {
1154 return Parser
<arm
>::fileKind(fileContent
);
1156 #if SUPPORT_ARCH_arm64
1157 if ( Parser
<arm64
>::validFile(fileContent
, false) ) {
1158 return Parser
<arm64
>::fileKind(fileContent
);
1166 // main function used by linker to instantiate ld::Files
1168 ld::dylib::File
* parse(const uint8_t* fileContent
, uint64_t fileLength
,
1169 const char* path
, time_t modTime
, const Options
& opts
, ld::File::Ordinal ordinal
,
1170 bool bundleLoader
, bool indirectDylib
)
1172 switch ( opts
.architecture() ) {
1173 #if SUPPORT_ARCH_x86_64
1174 case CPU_TYPE_X86_64
:
1175 if ( Parser
<x86_64
>::validFile(fileContent
, bundleLoader
) )
1176 return Parser
<x86_64
>::parse(fileContent
, fileLength
, path
, modTime
, ordinal
, opts
, indirectDylib
);
1179 #if SUPPORT_ARCH_i386
1181 if ( Parser
<x86
>::validFile(fileContent
, bundleLoader
) )
1182 return Parser
<x86
>::parse(fileContent
, fileLength
, path
, modTime
, ordinal
, opts
, indirectDylib
);
1185 #if SUPPORT_ARCH_arm_any
1187 if ( Parser
<arm
>::validFile(fileContent
, bundleLoader
) )
1188 return Parser
<arm
>::parse(fileContent
, fileLength
, path
, modTime
, ordinal
, opts
, indirectDylib
);
1191 #if SUPPORT_ARCH_arm64
1192 case CPU_TYPE_ARM64
:
1193 if ( Parser
<arm64
>::validFile(fileContent
, bundleLoader
) )
1194 return Parser
<arm64
>::parse(fileContent
, fileLength
, path
, modTime
, ordinal
, opts
, indirectDylib
);
1202 }; // namespace dylib
1203 }; // namespace mach_o