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