]> git.saurik.com Git - apple/ld64.git/blame - src/ld/parsers/macho_dylib_file.cpp
ld64-242.tar.gz
[apple/ld64.git] / src / ld / parsers / macho_dylib_file.cpp
CommitLineData
f80fe69f 1
a645023d
A
2/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 *
afe874b1 4 * Copyright (c) 2005-2011 Apple Inc. All rights reserved.
a645023d
A
5 *
6 * @APPLE_LICENSE_HEADER_START@
7 *
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
13 * file.
14 *
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.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25
26
27#include <stdint.h>
28#include <math.h>
29#include <unistd.h>
30#include <sys/param.h>
31#include <sys/mman.h>
32
33
34#include <vector>
35#include <set>
36#include <algorithm>
d425e388
A
37#include <unordered_map>
38#include <unordered_set>
a645023d
A
39
40#include "Architectures.hpp"
41#include "MachOFileAbstraction.hpp"
42#include "MachOTrie.hpp"
43#include "macho_dylib_file.h"
ebf6f434 44#include "../code-sign-blobs/superblob.h"
a645023d
A
45
46namespace mach_o {
47namespace dylib {
48
49
50// forward reference
51template <typename A> class File;
52
53
54//
55// An ExportAtom has no content. It exists so that the linker can track which imported
56// symbols came from which dynamic libraries.
57//
58template <typename A>
59class ExportAtom : public ld::Atom
60{
61public:
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; }
a645023d
A
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) { }
77
78protected:
79 typedef typename A::P P;
80 typedef typename A::P::uint_t pint_t;
81
82 virtual ~ExportAtom() {}
83
84 const File<A>& _file;
85 const char* _name;
86 pint_t _address;
87};
88
89
90
91//
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
94//
95template <typename A>
96class ImportAtom : public ld::Atom
97{
98public:
99 ImportAtom(File<A>& f, std::vector<const char*>& imports);
100
101 // overrides of ld::Atom
102 virtual ld::File* file() const { return &_file; }
a645023d
A
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()]; }
110
111protected:
112 typedef typename A::P P;
113
114 virtual ~ImportAtom() {}
115
116
117 File<A>& _file;
118 mutable std::vector<ld::Fixup> _undefs;
119};
120
121template <typename A>
122ImportAtom<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)
125{
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)));
128 }
129}
130
131
132
133//
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.
137//
138template <typename A>
139class File : public ld::dylib::File
140{
141public:
142 static bool validFile(const uint8_t* fileContent, bool executableOrDylib);
143 File(const uint8_t* fileContent, uint64_t fileLength, const char* path,
ebf6f434 144 time_t mTime, ld::File::Ordinal ordinal, bool linkingFlatNamespace,
a645023d 145 bool linkingMainExecutable, bool hoistImplicitPublicDylibs,
f80fe69f 146 ld::MacVersionMin macMin, ld::IOSVersionMin iPhoneMin, bool allowSimToMacOSX, bool addVers,
afe874b1 147 bool logAllFiles, const char* installPath, bool indirectDylib);
a645023d
A
148 virtual ~File() {}
149
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; }
599556ff 154 virtual uint8_t swiftVersion() const { return _swiftVersion; }
a645023d
A
155
156 // overrides of ld::dylib::File
157 virtual void processIndirectLibraries(ld::dylib::File::DylibHandler*, bool);
158 virtual bool providedExportAtom() const { return _providedAtom; }
159 virtual const char* parentUmbrella() const { return _parentUmbrella; }
160 virtual const std::vector<const char*>* allowableClients() const { return _allowableClients.size() != 0 ? &_allowableClients : NULL; }
161 virtual bool hasWeakExternals() const { return _hasWeakExports; }
162 virtual bool deadStrippable() const { return _deadStrippable; }
163 virtual bool hasPublicInstallName() const{ return _hasPublicInstallName; }
164 virtual bool hasWeakDefinition(const char* name) const;
afe874b1 165 virtual bool allSymbolsAreWeakImported() const;
ebf6f434 166 virtual const void* codeSignatureDR() const { return _codeSignatureDR; }
f80fe69f 167 virtual bool installPathVersionSpecific() const { return _installPathOverride; }
599556ff
A
168 virtual bool appExtensionSafe() const { return _appExtensionSafe; };
169 virtual ld::MacVersionMin macMinVersion() const { return _macMinVersionInDylib; }
170 virtual ld::IOSVersionMin iOSMinVersion() const { return _iOSMinVersionInDylib; }
a645023d
A
171
172
173protected:
174
175 struct ReExportChain { ReExportChain* prev; File<A>* file; };
176
177 void assertNoReExportCycles(ReExportChain*);
178
179private:
180 typedef typename A::P P;
181 typedef typename A::P::E E;
182 typedef typename A::P::uint_t pint_t;
183
184 friend class ExportAtom<A>;
185 friend class ImportAtom<A>;
186
d425e388
A
187 struct CStringHash {
188 std::size_t operator()(const char* __s) const {
189 unsigned long __h = 0;
190 for ( ; *__s; ++__s)
191 __h = 5 * __h + *__s;
192 return size_t(__h);
193 };
a645023d 194 };
afe874b1 195 struct AtomAndWeak { ld::Atom* atom; bool weakDef; bool tlv; pint_t address; };
d425e388
A
196 typedef std::unordered_map<const char*, AtomAndWeak, ld::CStringHash, ld::CStringEquals> NameToAtomMap;
197 typedef std::unordered_set<const char*, CStringHash, ld::CStringEquals> NameSet;
a645023d
A
198
199 struct Dependent { const char* path; File<A>* dylib; bool reExport; };
200
201 bool containsOrReExports(const char* name, bool* weakDef, bool* tlv, pint_t* defAddress) const;
202 bool isPublicLocation(const char* pth);
f80fe69f 203 bool wrongOS() { return _wrongOS; }
a645023d
A
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);
9543cb2f 211 static uint32_t parseVersionNumber32(const char* versionString);
a645023d
A
212 static const char* objCInfoSegmentName();
213 static const char* objCInfoSectionName();
214
215 const ld::MacVersionMin _macVersionMin;
afe874b1 216 const ld::IOSVersionMin _iOSVersionMin;
f80fe69f 217 const bool _allowSimToMacOSXLinking;
afe874b1 218 const bool _addVersionLoadCommand;
a645023d
A
219 bool _linkingFlat;
220 bool _implicitlyLinkPublicDylibs;
221 ld::File::ObjcConstraint _objcContraint;
599556ff 222 uint8_t _swiftVersion;
a645023d
A
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;
ebf6f434 231 const void* _codeSignatureDR;
a645023d
A
232 bool _noRexports;
233 bool _hasWeakExports;
234 bool _deadStrippable;
235 bool _hasPublicInstallName;
236 mutable bool _providedAtom;
237 bool _explictReExportFound;
f80fe69f
A
238 bool _wrongOS;
239 bool _installPathOverride;
9543cb2f 240 bool _indirectDylibsProcessed;
599556ff
A
241 bool _appExtensionSafe;
242 ld::MacVersionMin _macMinVersionInDylib;
243 ld::IOSVersionMin _iOSMinVersionInDylib;
f80fe69f 244
a645023d
A
245 static bool _s_logHashtable;
246};
247
248template <typename A>
249bool File<A>::_s_logHashtable = false;
250
251template <> const char* File<x86_64>::objCInfoSegmentName() { return "__DATA"; }
252template <> const char* File<arm>::objCInfoSegmentName() { return "__DATA"; }
253template <typename A> const char* File<A>::objCInfoSegmentName() { return "__OBJC"; }
254
255template <> const char* File<x86_64>::objCInfoSectionName() { return "__objc_imageinfo"; }
256template <> const char* File<arm>::objCInfoSectionName() { return "__objc_imageinfo"; }
257template <typename A> const char* File<A>::objCInfoSectionName() { return "__image_info"; }
258
259template <typename A>
ebf6f434 260File<A>::File(const uint8_t* fileContent, uint64_t fileLength, const char* pth, time_t mTime, ld::File::Ordinal ord,
a645023d 261 bool linkingFlatNamespace, bool linkingMainExecutable, bool hoistImplicitPublicDylibs,
f80fe69f 262 ld::MacVersionMin macMin, ld::IOSVersionMin iOSMin, bool allowSimToMacOSX, bool addVers,
afe874b1 263 bool logAllFiles, const char* targetInstallPath, bool indirectDylib)
a645023d 264 : ld::dylib::File(strdup(pth), mTime, ord),
f80fe69f 265 _macVersionMin(macMin), _iOSVersionMin(iOSMin), _allowSimToMacOSXLinking(allowSimToMacOSX), _addVersionLoadCommand(addVers),
a645023d 266 _linkingFlat(linkingFlatNamespace), _implicitlyLinkPublicDylibs(hoistImplicitPublicDylibs),
599556ff 267 _objcContraint(ld::File::objcConstraintNone), _swiftVersion(0),
a645023d
A
268 _importProxySection("__TEXT", "__import", ld::Section::typeImportProxies, true),
269 _flatDummySection("__LINKEDIT", "__flat_dummy", ld::Section::typeLinkEdit, true),
ebf6f434
A
270 _parentUmbrella(NULL), _importAtom(NULL), _codeSignatureDR(NULL),
271 _noRexports(false), _hasWeakExports(false),
a645023d 272 _deadStrippable(false), _hasPublicInstallName(false),
599556ff
A
273 _providedAtom(false), _explictReExportFound(false), _wrongOS(false), _installPathOverride(false),
274 _indirectDylibsProcessed(false), _appExtensionSafe(false),
275 _macMinVersionInDylib(ld::macVersionUnset), _iOSMinVersionInDylib(ld::iOSVersionUnset)
a645023d
A
276{
277 const macho_header<P>* header = (const macho_header<P>*)fileContent;
278 const uint32_t cmd_count = header->ncmds();
279 const macho_load_command<P>* const cmds = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>));
280 const macho_load_command<P>* const cmdsEnd = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>) + header->sizeofcmds());
281
282 // write out path for -t option
283 if ( logAllFiles )
284 printf("%s\n", pth);
285
286 // a "blank" stub has zero load commands
287 if ( (header->filetype() == MH_DYLIB_STUB) && (cmd_count == 0) ) {
288 // no further processing needed
289 munmap((caddr_t)fileContent, fileLength);
290 return;
291 }
292
293
294 // optimize the case where we know there is no reason to look at indirect dylibs
295 _noRexports = (header->flags() & MH_NO_REEXPORTED_DYLIBS)
296 || (header->filetype() == MH_BUNDLE)
297 || (header->filetype() == MH_EXECUTE); // bundles and exectuables can be used via -bundle_loader
298 _hasWeakExports = (header->flags() & MH_WEAK_DEFINES);
299 _deadStrippable = (header->flags() & MH_DEAD_STRIPPABLE_DYLIB);
599556ff 300 _appExtensionSafe = (header->flags() & MH_APP_EXTENSION_SAFE);
a645023d
A
301
302 // pass 1: get pointers, and see if this dylib uses compressed LINKEDIT format
303 const macho_dysymtab_command<P>* dynamicInfo = NULL;
304 const macho_dyld_info_command<P>* dyldInfo = NULL;
ebf6f434 305 const macho_linkedit_data_command<P>* codeSignature = NULL;
a645023d
A
306 const macho_nlist<P>* symbolTable = NULL;
307 const char* strings = NULL;
308 bool compressedLinkEdit = false;
309 uint32_t dependentLibCount = 0;
310 const macho_load_command<P>* cmd = cmds;
311 for (uint32_t i = 0; i < cmd_count; ++i) {
312 macho_dylib_command<P>* dylibID;
313 const macho_symtab_command<P>* symtab;
314 switch (cmd->cmd()) {
315 case LC_SYMTAB:
316 symtab = (macho_symtab_command<P>*)cmd;
317 symbolTable = (const macho_nlist<P>*)((char*)header + symtab->symoff());
318 strings = (char*)header + symtab->stroff();
ebf6f434
A
319 if ( (symtab->stroff() + symtab->strsize()) > fileLength )
320 throwf("mach-o string pool extends beyond end of file in %s", pth);
a645023d
A
321 break;
322 case LC_DYSYMTAB:
323 dynamicInfo = (macho_dysymtab_command<P>*)cmd;
324 break;
325 case LC_DYLD_INFO:
326 case LC_DYLD_INFO_ONLY:
327 dyldInfo = (macho_dyld_info_command<P>*)cmd;
328 compressedLinkEdit = true;
329 break;
330 case LC_ID_DYLIB:
331 dylibID = (macho_dylib_command<P>*)cmd;
332 _dylibInstallPath = strdup(dylibID->name());
333 _dylibTimeStamp = dylibID->timestamp();
334 _dylibCurrentVersion = dylibID->current_version();
335 _dylibCompatibilityVersion = dylibID->compatibility_version();
336 _hasPublicInstallName = isPublicLocation(_dylibInstallPath);
337 break;
338 case LC_LOAD_DYLIB:
339 case LC_LOAD_WEAK_DYLIB:
340 ++dependentLibCount;
341 break;
342 case LC_REEXPORT_DYLIB:
343 _explictReExportFound = true;
344 ++dependentLibCount;
345 break;
346 case LC_SUB_FRAMEWORK:
347 _parentUmbrella = strdup(((macho_sub_framework_command<P>*)cmd)->umbrella());
348 break;
349 case LC_SUB_CLIENT:
350 _allowableClients.push_back(strdup(((macho_sub_client_command<P>*)cmd)->client()));
351 break;
afe874b1 352 case LC_VERSION_MIN_MACOSX:
f80fe69f
A
353 if ( (_iOSVersionMin != ld::iOSVersionUnset) && !_allowSimToMacOSXLinking ) {
354 _wrongOS = true;
355 if ( _addVersionLoadCommand && !indirectDylib )
356 throw "building for iOS Simulator, but linking against dylib built for MacOSX";
357 }
599556ff 358 _macMinVersionInDylib = (ld::MacVersionMin)((macho_version_min_command<P>*)cmd)->version();
afe874b1
A
359 break;
360 case LC_VERSION_MIN_IPHONEOS:
f80fe69f
A
361 if ( _macVersionMin != ld::macVersionUnset ) {
362 _wrongOS = true;
363 if ( _addVersionLoadCommand && !indirectDylib )
364 throw "building for MacOSX, but linking against dylib built for iOS Simulator";
365 }
599556ff 366 _iOSMinVersionInDylib = (ld::IOSVersionMin)((macho_version_min_command<P>*)cmd)->version();
afe874b1 367 break;
ebf6f434
A
368 case LC_CODE_SIGNATURE:
369 codeSignature = (macho_linkedit_data_command<P>* )cmd;
370 break;
a645023d
A
371 case macho_segment_command<P>::CMD:
372 // check for Objective-C info
373 if ( strcmp(((macho_segment_command<P>*)cmd)->segname(), objCInfoSegmentName()) == 0 ) {
374 const macho_segment_command<P>* segment = (macho_segment_command<P>*)cmd;
375 const macho_section<P>* const sectionsStart = (macho_section<P>*)((char*)segment + sizeof(macho_segment_command<P>));
376 const macho_section<P>* const sectionsEnd = &sectionsStart[segment->nsects()];
377 for (const macho_section<P>* sect=sectionsStart; sect < sectionsEnd; ++sect) {
378 if ( strncmp(sect->sectname(), objCInfoSectionName(), strlen(objCInfoSectionName())) == 0 ) {
379 // struct objc_image_info {
380 // uint32_t version; // initially 0
381 // uint32_t flags;
382 // };
383 // #define OBJC_IMAGE_SUPPORTS_GC 2
384 // #define OBJC_IMAGE_GC_ONLY 4
f80fe69f 385 // #define OBJC_IMAGE_IS_SIMULATED 32
a645023d
A
386 //
387 const uint32_t* contents = (uint32_t*)(&fileContent[sect->offset()]);
388 if ( (sect->size() >= 8) && (contents[0] == 0) ) {
389 uint32_t flags = E::get32(contents[1]);
390 if ( (flags & 4) == 4 )
391 _objcContraint = ld::File::objcConstraintGC;
392 else if ( (flags & 2) == 2 )
393 _objcContraint = ld::File::objcConstraintRetainReleaseOrGC;
f80fe69f
A
394 else if ( (flags & 32) == 32 )
395 _objcContraint = ld::File::objcConstraintRetainReleaseForSimulator;
a645023d
A
396 else
397 _objcContraint = ld::File::objcConstraintRetainRelease;
599556ff 398 _swiftVersion = ((flags >> 8) & 0xFF);
a645023d
A
399 }
400 else if ( sect->size() > 0 ) {
401 warning("can't parse %s/%s section in %s", objCInfoSegmentName(), objCInfoSectionName(), this->path());
402 }
403 }
404 }
405 }
406 }
407 cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
408 if ( cmd > cmdsEnd )
409 throwf("malformed dylb, load command #%d is outside size of load commands in %s", i, pth);
410 }
411
412 // figure out if we need to examine dependent dylibs
413 // with compressed LINKEDIT format, MH_NO_REEXPORTED_DYLIBS can be trusted
414 bool processDependentLibraries = true;
415 if ( compressedLinkEdit && _noRexports && !linkingFlatNamespace)
416 processDependentLibraries = false;
417
418 if ( processDependentLibraries ) {
419 // pass 2 builds list of all dependent libraries
420 _dependentDylibs.reserve(dependentLibCount);
421 cmd = cmds;
b1f7435d 422 unsigned int reExportDylibCount = 0;
a645023d
A
423 for (uint32_t i = 0; i < cmd_count; ++i) {
424 switch (cmd->cmd()) {
425 case LC_LOAD_DYLIB:
426 case LC_LOAD_WEAK_DYLIB:
427 // with new linkedit format only care about LC_REEXPORT_DYLIB
428 if ( compressedLinkEdit && !linkingFlatNamespace )
429 break;
430 case LC_REEXPORT_DYLIB:
b1f7435d 431 ++reExportDylibCount;
a645023d
A
432 Dependent entry;
433 entry.path = strdup(((macho_dylib_command<P>*)cmd)->name());
434 entry.dylib = NULL;
435 entry.reExport = (cmd->cmd() == LC_REEXPORT_DYLIB);
afe874b1
A
436 if ( (targetInstallPath == NULL) || (strcmp(targetInstallPath, entry.path) != 0) )
437 _dependentDylibs.push_back(entry);
a645023d
A
438 break;
439 }
440 cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
441 }
442 // verify MH_NO_REEXPORTED_DYLIBS bit was correct
443 if ( compressedLinkEdit && !linkingFlatNamespace ) {
b1f7435d 444 assert(reExportDylibCount != 0);
a645023d
A
445 }
446 // pass 3 add re-export info
447 cmd = cmds;
448 for (uint32_t i = 0; i < cmd_count; ++i) {
449 const char* frameworkLeafName;
450 const char* dylibBaseName;
451 switch (cmd->cmd()) {
452 case LC_SUB_UMBRELLA:
453 frameworkLeafName = ((macho_sub_umbrella_command<P>*)cmd)->sub_umbrella();
454 for (typename std::vector<Dependent>::iterator it = _dependentDylibs.begin(); it != _dependentDylibs.end(); ++it) {
455 const char* dylibName = it->path;
456 const char* lastSlash = strrchr(dylibName, '/');
457 if ( (lastSlash != NULL) && (strcmp(&lastSlash[1], frameworkLeafName) == 0) )
458 it->reExport = true;
459 }
460 break;
461 case LC_SUB_LIBRARY:
462 dylibBaseName = ((macho_sub_library_command<P>*)cmd)->sub_library();
463 for (typename std::vector<Dependent>::iterator it = _dependentDylibs.begin(); it != _dependentDylibs.end(); ++it) {
464 const char* dylibName = it->path;
465 const char* lastSlash = strrchr(dylibName, '/');
466 const char* leafStart = &lastSlash[1];
467 if ( lastSlash == NULL )
468 leafStart = dylibName;
469 const char* firstDot = strchr(leafStart, '.');
470 int len = strlen(leafStart);
471 if ( firstDot != NULL )
472 len = firstDot - leafStart;
473 if ( strncmp(leafStart, dylibBaseName, len) == 0 )
474 it->reExport = true;
475 }
476 break;
477 }
478 cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
479 }
480 }
481
482 // validate minimal load commands
483 if ( (_dylibInstallPath == NULL) && ((header->filetype() == MH_DYLIB) || (header->filetype() == MH_DYLIB_STUB)) )
484 throwf("dylib %s missing LC_ID_DYLIB load command", pth);
485 if ( dyldInfo == NULL ) {
486 if ( symbolTable == NULL )
487 throw "binary missing LC_SYMTAB load command";
488 if ( dynamicInfo == NULL )
489 throw "binary missing LC_DYSYMTAB load command";
490 }
491
492 // if linking flat and this is a flat dylib, create one atom that references all imported symbols
493 if ( linkingFlatNamespace && linkingMainExecutable && ((header->flags() & MH_TWOLEVEL) == 0) ) {
494 std::vector<const char*> importNames;
495 importNames.reserve(dynamicInfo->nundefsym());
496 const macho_nlist<P>* start = &symbolTable[dynamicInfo->iundefsym()];
497 const macho_nlist<P>* end = &start[dynamicInfo->nundefsym()];
498 for (const macho_nlist<P>* sym=start; sym < end; ++sym) {
499 importNames.push_back(&strings[sym->n_strx()]);
500 }
501 _importAtom = new ImportAtom<A>(*this, importNames);
502 }
503
ebf6f434
A
504 // if the dylib is code signed, look for its Designated Requirement
505 if ( codeSignature != NULL ) {
506 const Security::BlobCore* overallSignature = (Security::BlobCore*)((char*)header + codeSignature->dataoff());
507 typedef Security::SuperBlob<Security::kSecCodeMagicEmbeddedSignature> EmbeddedSignatureBlob;
508 typedef Security::SuperBlob<Security::kSecCodeMagicRequirementSet> InternalRequirementsBlob;
509 const EmbeddedSignatureBlob* signature = EmbeddedSignatureBlob::specific(overallSignature);
510 if ( signature->validateBlob(codeSignature->datasize()) ) {
511 const InternalRequirementsBlob* ireq = signature->find<InternalRequirementsBlob>(Security::cdRequirementsSlot);
512 if ( (ireq != NULL) && ireq->validateBlob() ) {
513 const Security::BlobCore* dr = ireq->find(Security::kSecDesignatedRequirementType);
514 if ( (dr != NULL) && dr->validateBlob(Security::kSecCodeMagicRequirement) ) {
515 // <rdar://problem/10968461> make copy because mapped file is about to be unmapped
516 _codeSignatureDR = ::malloc(dr->length());
517 ::memcpy((void*)_codeSignatureDR, dr, dr->length());
518 }
519 }
520 }
521 }
522
a645023d
A
523 // build hash table
524 if ( dyldInfo != NULL )
525 buildExportHashTableFromExportInfo(dyldInfo, fileContent);
526 else
527 buildExportHashTableFromSymbolTable(dynamicInfo, symbolTable, strings, fileContent);
528
529 // unmap file
530 munmap((caddr_t)fileContent, fileLength);
531}
532
9543cb2f
A
533//
534// Parses number of form X[.Y[.Z]] into a uint32_t where the nibbles are xxxx.yy.zz
535//
536template <typename A>
537uint32_t File<A>::parseVersionNumber32(const char* versionString)
538{
539 uint32_t x = 0;
540 uint32_t y = 0;
541 uint32_t z = 0;
542 char* end;
543 x = strtoul(versionString, &end, 10);
544 if ( *end == '.' ) {
545 y = strtoul(&end[1], &end, 10);
546 if ( *end == '.' ) {
547 z = strtoul(&end[1], &end, 10);
548 }
549 }
550 if ( (*end != '\0') || (x > 0xffff) || (y > 0xff) || (z > 0xff) )
551 throwf("malformed 32-bit x.y.z version number: %s", versionString);
552
553 return (x << 16) | ( y << 8 ) | z;
554}
a645023d
A
555
556template <typename A>
557void File<A>::buildExportHashTableFromSymbolTable(const macho_dysymtab_command<P>* dynamicInfo,
558 const macho_nlist<P>* symbolTable, const char* strings,
559 const uint8_t* fileContent)
560{
561 if ( dynamicInfo->tocoff() == 0 ) {
562 if ( _s_logHashtable ) fprintf(stderr, "ld: building hashtable of %u toc entries for %s\n", dynamicInfo->nextdefsym(), this->path());
563 const macho_nlist<P>* start = &symbolTable[dynamicInfo->iextdefsym()];
564 const macho_nlist<P>* end = &start[dynamicInfo->nextdefsym()];
d425e388 565 _atoms.reserve(dynamicInfo->nextdefsym()); // set initial bucket count
a645023d
A
566 for (const macho_nlist<P>* sym=start; sym < end; ++sym) {
567 this->addSymbol(&strings[sym->n_strx()], (sym->n_desc() & N_WEAK_DEF) != 0, false, sym->n_value());
568 }
569 }
570 else {
571 int32_t count = dynamicInfo->ntoc();
d425e388 572 _atoms.reserve(count); // set initial bucket count
a645023d
A
573 if ( _s_logHashtable ) fprintf(stderr, "ld: building hashtable of %u entries for %s\n", count, this->path());
574 const struct dylib_table_of_contents* toc = (dylib_table_of_contents*)(fileContent + dynamicInfo->tocoff());
575 for (int32_t i = 0; i < count; ++i) {
576 const uint32_t index = E::get32(toc[i].symbol_index);
577 const macho_nlist<P>* sym = &symbolTable[index];
578 this->addSymbol(&strings[sym->n_strx()], (sym->n_desc() & N_WEAK_DEF) != 0, false, sym->n_value());
579 }
580 }
581
582 // special case old libSystem
583 if ( (_dylibInstallPath != NULL) && (strcmp(_dylibInstallPath, "/usr/lib/libSystem.B.dylib") == 0) )
584 addDyldFastStub();
585}
586
587
588template <typename A>
589void File<A>::buildExportHashTableFromExportInfo(const macho_dyld_info_command<P>* dyldInfo,
590 const uint8_t* fileContent)
591{
592 if ( _s_logHashtable ) fprintf(stderr, "ld: building hashtable from export info in %s\n", this->path());
593 if ( dyldInfo->export_size() > 0 ) {
594 const uint8_t* start = fileContent + dyldInfo->export_off();
595 const uint8_t* end = &start[dyldInfo->export_size()];
596 std::vector<mach_o::trie::Entry> list;
597 parseTrie(start, end, list);
598 for (std::vector<mach_o::trie::Entry>::iterator it=list.begin(); it != list.end(); ++it)
599 this->addSymbol(it->name,
600 it->flags & EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION,
601 (it->flags & EXPORT_SYMBOL_FLAGS_KIND_MASK) == EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL,
602 it->address);
603 }
604}
605
606
607template <>
608void File<x86_64>::addDyldFastStub()
609{
610 addSymbol("dyld_stub_binder", false, false, 0);
611}
612
613template <>
614void File<x86>::addDyldFastStub()
615{
616 addSymbol("dyld_stub_binder", false, false, 0);
617}
618
619template <typename A>
620void File<A>::addDyldFastStub()
621{
622 // do nothing
623}
624
625template <typename A>
626void File<A>::addSymbol(const char* name, bool weakDef, bool tlv, pint_t address)
627{
a645023d
A
628 //fprintf(stderr, "addSymbol() %s\n", name);
629 // symbols that start with $ld$ are meta-data to the static linker
630 // <rdar://problem/5182537> need way for ld and dyld to see different exported symbols in a dylib
631 if ( strncmp(name, "$ld$", 4) == 0 ) {
632 // $ld$ <action> $ <condition> $ <symbol-name>
633 const char* symAction = &name[4];
634 const char* symCond = strchr(symAction, '$');
635 if ( symCond != NULL ) {
636 char curOSVers[16];
637 if ( _macVersionMin != ld::macVersionUnset ) {
638 sprintf(curOSVers, "$os%d.%d$", (_macVersionMin >> 16), ((_macVersionMin >> 8) & 0xFF));
639 }
afe874b1
A
640 else if ( _iOSVersionMin != ld::iOSVersionUnset ) {
641 sprintf(curOSVers, "$os%d.%d$", (_iOSVersionMin >> 16), ((_iOSVersionMin >> 8) & 0xFF));
a645023d
A
642 }
643 else {
644 assert(0 && "targeting neither macosx nor iphoneos");
645 }
646 if ( strncmp(symCond, curOSVers, strlen(curOSVers)) == 0 ) {
647 const char* symName = strchr(&symCond[1], '$');
648 if ( symName != NULL ) {
649 ++symName;
650 if ( strncmp(symAction, "hide$", 5) == 0 ) {
651 if ( _s_logHashtable ) fprintf(stderr, " adding %s to ignore set for %s\n", symName, this->path());
652 _ignoreExports.insert(strdup(symName));
653 return;
654 }
655 else if ( strncmp(symAction, "add$", 4) == 0 ) {
656 this->addSymbol(symName, weakDef, false, 0);
657 return;
658 }
ebf6f434
A
659 else if ( strncmp(symAction, "install_name$", 13) == 0 ) {
660 _dylibInstallPath = symName;
f80fe69f 661 _installPathOverride = true;
9543cb2f
A
662 // <rdar://problem/14448206> CoreGraphics redirects to ApplicationServices, but with wrong compat version
663 if ( strcmp(_dylibInstallPath, "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices") == 0 )
664 _dylibCompatibilityVersion = parseVersionNumber32("1.0");
665 return;
666 }
667 else if ( strncmp(symAction, "compatibility_version$", 22) == 0 ) {
668 _dylibCompatibilityVersion = parseVersionNumber32(symName);
ebf6f434
A
669 return;
670 }
a645023d
A
671 else {
672 warning("bad symbol action: %s in dylib %s", name, this->path());
673 }
674 }
675 }
676 }
677 else {
678 warning("bad symbol condition: %s in dylib %s", name, this->path());
679 }
680 }
681
682 // add symbol as possible export if we are not supposed to ignore it
683 if ( _ignoreExports.count(name) == 0 ) {
684 AtomAndWeak bucket;
685 bucket.atom = NULL;
afe874b1 686 bucket.weakDef = weakDef;
a645023d
A
687 bucket.tlv = tlv;
688 bucket.address = address;
689 if ( _s_logHashtable ) fprintf(stderr, " adding %s to hash table for %s\n", name, this->path());
690 _atoms[strdup(name)] = bucket;
691 }
692}
693
694
695template <typename A>
696bool File<A>::forEachAtom(ld::File::AtomHandler& handler) const
697{
698 handler.doFile(*this);
699 // if doing flatnamespace and need all this dylib's imports resolve
700 // add atom which references alls undefines in this dylib
701 if ( _importAtom != NULL ) {
702 handler.doAtom(*_importAtom);
703 return true;
704 }
705 return false;
706}
707
708template <typename A>
709bool File<A>::hasWeakDefinition(const char* name) const
710{
711 // if supposed to ignore this export, then pretend I don't have it
712 if ( _ignoreExports.count(name) != 0 )
713 return false;
714
715 typename NameToAtomMap::const_iterator pos = _atoms.find(name);
716 if ( pos != _atoms.end() ) {
afe874b1 717 return pos->second.weakDef;
a645023d
A
718 }
719 else {
720 // look in children that I re-export
721 for (typename std::vector<Dependent>::const_iterator it = _dependentDylibs.begin(); it != _dependentDylibs.end(); ++it) {
722 if ( it->reExport ) {
723 //fprintf(stderr, "getJustInTimeAtomsFor: %s NOT found in %s, looking in child %s\n", name, this->path(), (*it)->getInstallPath());
724 typename NameToAtomMap::iterator cpos = it->dylib->_atoms.find(name);
725 if ( cpos != it->dylib->_atoms.end() )
afe874b1 726 return cpos->second.weakDef;
a645023d
A
727 }
728 }
729 }
730 return false;
731}
732
afe874b1
A
733
734// <rdar://problem/5529626> If only weak_import symbols are used, linker should use LD_LOAD_WEAK_DYLIB
735template <typename A>
736bool File<A>::allSymbolsAreWeakImported() const
737{
738 bool foundNonWeakImport = false;
739 bool foundWeakImport = false;
740 //fprintf(stderr, "%s:\n", this->path());
741 for (typename NameToAtomMap::const_iterator it = _atoms.begin(); it != _atoms.end(); ++it) {
742 const ld::Atom* atom = it->second.atom;
743 if ( atom != NULL ) {
744 if ( atom->weakImported() )
745 foundWeakImport = true;
746 else
747 foundNonWeakImport = true;
748 //fprintf(stderr, " weak_import=%d, name=%s\n", atom->weakImported(), it->first);
749 }
750 }
751
752 // don't automatically weak link dylib with no imports
753 // so at least one weak import symbol and no non-weak-imported symbols must be found
754 return foundWeakImport && !foundNonWeakImport;
755}
756
757
a645023d
A
758template <typename A>
759bool File<A>::containsOrReExports(const char* name, bool* weakDef, bool* tlv, pint_t* defAddress) const
760{
afe874b1
A
761 if ( _ignoreExports.count(name) != 0 )
762 return false;
763
d425e388 764 // check myself
a645023d
A
765 typename NameToAtomMap::iterator pos = _atoms.find(name);
766 if ( pos != _atoms.end() ) {
afe874b1 767 *weakDef = pos->second.weakDef;
a645023d
A
768 *tlv = pos->second.tlv;
769 *defAddress = pos->second.address;
770 return true;
771 }
772
773 // check dylibs I re-export
774 for (typename std::vector<Dependent>::const_iterator it = _dependentDylibs.begin(); it != _dependentDylibs.end(); ++it) {
775 if ( it->reExport && !it->dylib->implicitlyLinked() ) {
776 if ( it->dylib->containsOrReExports(name, weakDef, tlv, defAddress) )
777 return true;
778 }
779 }
780
781 return false;
782}
783
784
785template <typename A>
786bool File<A>::justInTimeforEachAtom(const char* name, ld::File::AtomHandler& handler) const
787{
788 // if supposed to ignore this export, then pretend I don't have it
789 if ( _ignoreExports.count(name) != 0 )
790 return false;
791
792
793 AtomAndWeak bucket;
afe874b1
A
794 if ( this->containsOrReExports(name, &bucket.weakDef, &bucket.tlv, &bucket.address) ) {
795 bucket.atom = new ExportAtom<A>(*this, name, bucket.weakDef, bucket.tlv, bucket.address);
a645023d
A
796 _atoms[name] = bucket;
797 _providedAtom = true;
798 if ( _s_logHashtable ) fprintf(stderr, "getJustInTimeAtomsFor: %s found in %s\n", name, this->path());
799 // call handler with new export atom
800 handler.doAtom(*bucket.atom);
801 return true;
802 }
803
804 return false;
805}
806
807
808
809template <typename A>
810bool File<A>::isPublicLocation(const char* pth)
811{
812 // -no_implicit_dylibs disables this optimization
813 if ( ! _implicitlyLinkPublicDylibs )
814 return false;
815
816 // /usr/lib is a public location
817 if ( (strncmp(pth, "/usr/lib/", 9) == 0) && (strchr(&pth[9], '/') == NULL) )
818 return true;
819
820 // /System/Library/Frameworks/ is a public location
821 if ( strncmp(pth, "/System/Library/Frameworks/", 27) == 0 ) {
822 const char* frameworkDot = strchr(&pth[27], '.');
823 // but only top level framework
824 // /System/Library/Frameworks/Foo.framework/Versions/A/Foo ==> true
825 // /System/Library/Frameworks/Foo.framework/Resources/libBar.dylib ==> false
826 // /System/Library/Frameworks/Foo.framework/Frameworks/Bar.framework/Bar ==> false
827 // /System/Library/Frameworks/Foo.framework/Frameworks/Xfoo.framework/XFoo ==> false
828 if ( frameworkDot != NULL ) {
829 int frameworkNameLen = frameworkDot - &pth[27];
830 if ( strncmp(&pth[strlen(pth)-frameworkNameLen-1], &pth[26], frameworkNameLen+1) == 0 )
831 return true;
832 }
833 }
834
835 return false;
836}
837
838template <typename A>
839void File<A>::processIndirectLibraries(ld::dylib::File::DylibHandler* handler, bool addImplicitDylibs)
840{
9543cb2f
A
841 // only do this once
842 if ( _indirectDylibsProcessed )
843 return;
a645023d
A
844 const static bool log = false;
845 if ( log ) fprintf(stderr, "processIndirectLibraries(%s)\n", this->installPath());
846 if ( _linkingFlat ) {
847 for (typename std::vector<Dependent>::iterator it = _dependentDylibs.begin(); it != _dependentDylibs.end(); it++) {
848 it->dylib = (File<A>*)handler->findDylib(it->path, this->path());
849 }
850 }
851 else if ( _noRexports ) {
852 // MH_NO_REEXPORTED_DYLIBS bit set, then nothing to do
853 }
854 else {
855 // two-level, might have re-exports
856 for (typename std::vector<Dependent>::iterator it = _dependentDylibs.begin(); it != _dependentDylibs.end(); it++) {
857 if ( it->reExport ) {
858 if ( log ) fprintf(stderr, "processIndirectLibraries() parent=%s, child=%s\n", this->installPath(), it->path);
859 // a LC_REEXPORT_DYLIB, LC_SUB_UMBRELLA or LC_SUB_LIBRARY says we re-export this child
860 it->dylib = (File<A>*)handler->findDylib(it->path, this->path());
f80fe69f 861 if ( it->dylib->hasPublicInstallName() && !it->dylib->wrongOS() ) {
a645023d
A
862 // promote this child to be automatically added as a direct dependent if this already is
863 if ( (this->explicitlyLinked() || this->implicitlyLinked()) && (strcmp(it->path,it->dylib->installPath()) == 0) ) {
864 if ( log ) fprintf(stderr, "processIndirectLibraries() implicitly linking %s\n", it->dylib->installPath());
865 it->dylib->setImplicitlyLinked();
866 }
867 else if ( it->dylib->explicitlyLinked() || it->dylib->implicitlyLinked() ) {
868 if ( log ) fprintf(stderr, "processIndirectLibraries() parent is not directly linked, but child is, so no need to re-export child\n");
869 }
870 else {
871 if ( log ) fprintf(stderr, "processIndirectLibraries() parent is not directly linked, so parent=%s will re-export child=%s\n", this->installPath(), it->path);
872 }
873 }
874 else {
875 // add all child's symbols to me
876 if ( log ) fprintf(stderr, "processIndirectLibraries() child is not public, so parent=%s will re-export child=%s\n", this->installPath(), it->path);
877 }
878 }
879 else if ( !_explictReExportFound ) {
880 // see if child contains LC_SUB_FRAMEWORK with my name
881 it->dylib = (File<A>*)handler->findDylib(it->path, this->path());
882 const char* parentUmbrellaName = it->dylib->parentUmbrella();
883 if ( parentUmbrellaName != NULL ) {
884 const char* parentName = this->path();
885 const char* lastSlash = strrchr(parentName, '/');
886 if ( (lastSlash != NULL) && (strcmp(&lastSlash[1], parentUmbrellaName) == 0) ) {
887 // add all child's symbols to me
888 it->reExport = true;
889 if ( log ) fprintf(stderr, "processIndirectLibraries() umbrella=%s will re-export child=%s\n", this->installPath(), it->path);
890 }
891 }
892 }
893 }
894 }
895
896 // check for re-export cycles
897 ReExportChain chain;
898 chain.prev = NULL;
899 chain.file = this;
900 this->assertNoReExportCycles(&chain);
9543cb2f
A
901
902 _indirectDylibsProcessed = true;
a645023d
A
903}
904
905template <typename A>
906void File<A>::assertNoReExportCycles(ReExportChain* prev)
907{
908 // recursively check my re-exported dylibs
909 ReExportChain chain;
910 chain.prev = prev;
911 chain.file = this;
912 for (typename std::vector<Dependent>::iterator it = _dependentDylibs.begin(); it != _dependentDylibs.end(); it++) {
913 if ( it->reExport ) {
914 ld::File* child = it->dylib;
915 // check child is not already in chain
916 for (ReExportChain* p = prev; p != NULL; p = p->prev) {
917 if ( p->file == child ) {
918 throwf("cycle in dylib re-exports with %s and %s", child->path(), this->path());
919 }
920 }
921 if ( it->dylib != NULL )
922 it->dylib->assertNoReExportCycles(&chain);
923 }
924 }
925}
926
927
a645023d
A
928template <typename A>
929class Parser
930{
931public:
932 typedef typename A::P P;
933
934 static bool validFile(const uint8_t* fileContent, bool executableOrDyliborBundle);
f80fe69f 935 static const char* fileKind(const uint8_t* fileContent);
a645023d
A
936 static ld::dylib::File* parse(const uint8_t* fileContent, uint64_t fileLength,
937 const char* path, time_t mTime,
ebf6f434
A
938 ld::File::Ordinal ordinal, const Options& opts, bool indirectDylib) {
939 return new File<A>(fileContent, fileLength, path, mTime,
a645023d
A
940 ordinal, opts.flatNamespace(),
941 opts.linkingMainExecutable(),
942 opts.implicitlyLinkIndirectPublicDylibs(),
943 opts.macosxVersionMin(),
afe874b1 944 opts.iOSVersionMin(),
f80fe69f 945 opts.allowSimulatorToLinkWithMacOSX(),
afe874b1
A
946 opts.addVersionLoadCommand(),
947 opts.logAllFiles(),
948 opts.installPath(),
949 indirectDylib);
a645023d
A
950 }
951
952};
953
954
955
a645023d
A
956template <>
957bool Parser<x86>::validFile(const uint8_t* fileContent, bool executableOrDyliborBundle)
958{
959 const macho_header<P>* header = (const macho_header<P>*)fileContent;
960 if ( header->magic() != MH_MAGIC )
961 return false;
962 if ( header->cputype() != CPU_TYPE_I386 )
963 return false;
964 switch ( header->filetype() ) {
965 case MH_DYLIB:
966 case MH_DYLIB_STUB:
967 return true;
968 case MH_BUNDLE:
969 if ( executableOrDyliborBundle )
970 return true;
971 else
972 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
973 case MH_EXECUTE:
974 if ( executableOrDyliborBundle )
975 return true;
976 else
977 throw "can't link with a main executable";
978 default:
979 return false;
980 }
981}
982
983template <>
984bool Parser<x86_64>::validFile(const uint8_t* fileContent, bool executableOrDyliborBundle)
985{
986 const macho_header<P>* header = (const macho_header<P>*)fileContent;
987 if ( header->magic() != MH_MAGIC_64 )
988 return false;
989 if ( header->cputype() != CPU_TYPE_X86_64 )
990 return false;
991 switch ( header->filetype() ) {
992 case MH_DYLIB:
993 case MH_DYLIB_STUB:
994 return true;
995 case MH_BUNDLE:
996 if ( executableOrDyliborBundle )
997 return true;
998 else
999 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
1000 case MH_EXECUTE:
1001 if ( executableOrDyliborBundle )
1002 return true;
1003 else
1004 throw "can't link with a main executable";
1005 default:
1006 return false;
1007 }
1008}
1009
1010template <>
1011bool Parser<arm>::validFile(const uint8_t* fileContent, bool executableOrDyliborBundle)
1012{
1013 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1014 if ( header->magic() != MH_MAGIC )
1015 return false;
1016 if ( header->cputype() != CPU_TYPE_ARM )
1017 return false;
1018 switch ( header->filetype() ) {
1019 case MH_DYLIB:
1020 case MH_DYLIB_STUB:
1021 return true;
1022 case MH_BUNDLE:
1023 if ( executableOrDyliborBundle )
1024 return true;
1025 else
1026 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
1027 case MH_EXECUTE:
1028 if ( executableOrDyliborBundle )
1029 return true;
1030 else
1031 throw "can't link with a main executable";
1032 default:
1033 return false;
1034 }
1035}
1036
1037
1038
f80fe69f
A
1039template <>
1040bool Parser<arm64>::validFile(const uint8_t* fileContent, bool executableOrDyliborBundle)
1041{
1042 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1043 if ( header->magic() != MH_MAGIC_64 )
1044 return false;
1045 if ( header->cputype() != CPU_TYPE_ARM64 )
1046 return false;
1047 switch ( header->filetype() ) {
1048 case MH_DYLIB:
1049 case MH_DYLIB_STUB:
1050 return true;
1051 case MH_BUNDLE:
1052 if ( executableOrDyliborBundle )
1053 return true;
1054 else
1055 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
1056 case MH_EXECUTE:
1057 if ( executableOrDyliborBundle )
1058 return true;
1059 else
1060 throw "can't link with a main executable";
1061 default:
1062 return false;
1063 }
1064}
1065
1066
1067bool isDylibFile(const uint8_t* fileContent, cpu_type_t* result, cpu_subtype_t* subResult)
1068{
1069 if ( Parser<x86_64>::validFile(fileContent, false) ) {
1070 *result = CPU_TYPE_X86_64;
9543cb2f
A
1071 const macho_header<Pointer64<LittleEndian> >* header = (const macho_header<Pointer64<LittleEndian> >*)fileContent;
1072 *subResult = header->cpusubtype();
f80fe69f
A
1073 return true;
1074 }
1075 if ( Parser<x86>::validFile(fileContent, false) ) {
1076 *result = CPU_TYPE_I386;
1077 *subResult = CPU_SUBTYPE_X86_ALL;
1078 return true;
1079 }
1080 if ( Parser<arm>::validFile(fileContent, false) ) {
1081 *result = CPU_TYPE_ARM;
1082 const macho_header<Pointer32<LittleEndian> >* header = (const macho_header<Pointer32<LittleEndian> >*)fileContent;
1083 *subResult = header->cpusubtype();
1084 return true;
1085 }
1086 if ( Parser<arm64>::validFile(fileContent, false) ) {
1087 *result = CPU_TYPE_ARM64;
1088 *subResult = CPU_SUBTYPE_ARM64_ALL;
1089 return true;
1090 }
f80fe69f
A
1091 return false;
1092}
1093
1094template <>
1095const char* Parser<x86>::fileKind(const uint8_t* fileContent)
1096{
1097 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1098 if ( header->magic() != MH_MAGIC )
1099 return NULL;
1100 if ( header->cputype() != CPU_TYPE_I386 )
1101 return NULL;
1102 return "i386";
1103}
1104
1105template <>
1106const char* Parser<x86_64>::fileKind(const uint8_t* fileContent)
1107{
1108 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1109 if ( header->magic() != MH_MAGIC_64 )
1110 return NULL;
1111 if ( header->cputype() != CPU_TYPE_X86_64 )
1112 return NULL;
1113 return "x86_64";
1114}
1115
1116template <>
1117const char* Parser<arm>::fileKind(const uint8_t* fileContent)
1118{
1119 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1120 if ( header->magic() != MH_MAGIC )
1121 return NULL;
1122 if ( header->cputype() != CPU_TYPE_ARM )
1123 return NULL;
1124 for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) {
1125 if ( (t->cpuType == CPU_TYPE_ARM) && ((cpu_subtype_t)header->cpusubtype() == t->cpuSubType) ) {
1126 return t->archName;
1127 }
1128 }
1129 return "arm???";
1130}
1131
1132#if SUPPORT_ARCH_arm64
1133template <>
1134const char* Parser<arm64>::fileKind(const uint8_t* fileContent)
1135{
1136 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1137 if ( header->magic() != MH_MAGIC_64 )
1138 return NULL;
1139 if ( header->cputype() != CPU_TYPE_ARM64 )
1140 return NULL;
1141 return "arm64";
1142}
1143#endif
1144
1145//
1146// used by linker is error messages to describe mismatched files
1147//
1148const char* archName(const uint8_t* fileContent)
1149{
1150 if ( Parser<x86_64>::validFile(fileContent, true) ) {
1151 return Parser<x86_64>::fileKind(fileContent);
1152 }
1153 if ( Parser<x86>::validFile(fileContent, true) ) {
1154 return Parser<x86>::fileKind(fileContent);
1155 }
1156 if ( Parser<arm>::validFile(fileContent, true) ) {
1157 return Parser<arm>::fileKind(fileContent);
1158 }
1159#if SUPPORT_ARCH_arm64
1160 if ( Parser<arm64>::validFile(fileContent, false) ) {
1161 return Parser<arm64>::fileKind(fileContent);
1162 }
1163#endif
1164 return NULL;
1165}
1166
1167
a645023d
A
1168//
1169// main function used by linker to instantiate ld::Files
1170//
1171ld::dylib::File* parse(const uint8_t* fileContent, uint64_t fileLength,
ebf6f434 1172 const char* path, time_t modTime, const Options& opts, ld::File::Ordinal ordinal,
afe874b1 1173 bool bundleLoader, bool indirectDylib)
a645023d
A
1174{
1175 switch ( opts.architecture() ) {
ebf6f434 1176#if SUPPORT_ARCH_x86_64
a645023d
A
1177 case CPU_TYPE_X86_64:
1178 if ( Parser<x86_64>::validFile(fileContent, bundleLoader) )
afe874b1 1179 return Parser<x86_64>::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib);
a645023d 1180 break;
ebf6f434
A
1181#endif
1182#if SUPPORT_ARCH_i386
a645023d
A
1183 case CPU_TYPE_I386:
1184 if ( Parser<x86>::validFile(fileContent, bundleLoader) )
afe874b1 1185 return Parser<x86>::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib);
a645023d 1186 break;
ebf6f434
A
1187#endif
1188#if SUPPORT_ARCH_arm_any
a645023d
A
1189 case CPU_TYPE_ARM:
1190 if ( Parser<arm>::validFile(fileContent, bundleLoader) )
afe874b1 1191 return Parser<arm>::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib);
a645023d 1192 break;
f80fe69f
A
1193#endif
1194#if SUPPORT_ARCH_arm64
1195 case CPU_TYPE_ARM64:
1196 if ( Parser<arm64>::validFile(fileContent, bundleLoader) )
1197 return Parser<arm64>::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib);
1198 break;
ebf6f434 1199#endif
a645023d
A
1200 }
1201 return NULL;
1202}
1203
1204
1205}; // namespace dylib
1206}; // namespace mach_o
1207
1208