]> git.saurik.com Git - apple/ld64.git/blob - src/ld/parsers/macho_dylib_file.cpp
24d69c861e28d40004d171bea4fabd019306bf95
[apple/ld64.git] / src / ld / parsers / macho_dylib_file.cpp
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2005-2011 Apple Inc. All rights reserved.
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>
35 #include <map>
36 #include <algorithm>
37
38 #include "Architectures.hpp"
39 #include "Bitcode.hpp"
40 #include "MachOFileAbstraction.hpp"
41 #include "MachOTrie.hpp"
42 #include "generic_dylib_file.hpp"
43 #include "macho_dylib_file.h"
44 #include "../code-sign-blobs/superblob.h"
45
46 namespace mach_o {
47 namespace dylib {
48
49 //
50 // The reader for a dylib extracts all exported symbols names from the memory-mapped
51 // dylib, builds a hash table, then unmaps the file. This is an important memory
52 // savings for large dylibs.
53 //
54 template <typename A>
55 class File final : public generic::dylib::File<A>
56 {
57 using Base = generic::dylib::File<A>;
58
59 public:
60 static bool validFile(const uint8_t* fileContent, bool executableOrDylib, bool subTypeMustMatch=false);
61 File(const uint8_t* fileContent, uint64_t fileLength, const char* path,
62 time_t mTime, ld::File::Ordinal ordinal, bool linkingFlatNamespace,
63 bool linkingMainExecutable, bool hoistImplicitPublicDylibs,
64 Options::Platform platform, uint32_t linkMinOSVersion, bool allowSimToMacOSX,
65 bool addVers, bool buildingForSimulator,
66 bool logAllFiles, const char* installPath,
67 bool indirectDylib, bool ignoreMismatchPlatform, bool usingBitcode);
68 virtual ~File() noexcept {}
69
70 private:
71 using P = typename A::P;
72 using E = typename A::P::E;
73
74 void addDyldFastStub();
75 void buildExportHashTableFromExportInfo(const macho_dyld_info_command<P>* dyldInfo,
76 const uint8_t* fileContent);
77 void buildExportHashTableFromSymbolTable(const macho_dysymtab_command<P>* dynamicInfo,
78 const macho_nlist<P>* symbolTable, const char* strings,
79 const uint8_t* fileContent);
80 static const char* objCInfoSegmentName();
81 static const char* objCInfoSectionName();
82
83
84 uint64_t _fileLength;
85 uint32_t _linkeditStartOffset;
86
87 };
88
89 template <> const char* File<x86_64>::objCInfoSegmentName() { return "__DATA"; }
90 template <> const char* File<arm>::objCInfoSegmentName() { return "__DATA"; }
91 template <typename A> const char* File<A>::objCInfoSegmentName() { return "__OBJC"; }
92
93 template <> const char* File<x86_64>::objCInfoSectionName() { return "__objc_imageinfo"; }
94 template <> const char* File<arm>::objCInfoSectionName() { return "__objc_imageinfo"; }
95 template <typename A> const char* File<A>::objCInfoSectionName() { return "__image_info"; }
96
97 template <typename A>
98 File<A>::File(const uint8_t* fileContent, uint64_t fileLength, const char* path, time_t mTime,
99 ld::File::Ordinal ord, bool linkingFlatNamespace, bool linkingMainExecutable,
100 bool hoistImplicitPublicDylibs, Options::Platform platform, uint32_t linkMinOSVersion,
101 bool allowSimToMacOSX, bool addVers, bool buildingForSimulator, bool logAllFiles,
102 const char* targetInstallPath, bool indirectDylib, bool ignoreMismatchPlatform, bool usingBitcode)
103 : Base(strdup(path), mTime, ord, platform, linkMinOSVersion, linkingFlatNamespace,
104 hoistImplicitPublicDylibs, allowSimToMacOSX, addVers), _fileLength(fileLength), _linkeditStartOffset(0)
105 {
106 const macho_header<P>* header = (const macho_header<P>*)fileContent;
107 const uint32_t cmd_count = header->ncmds();
108 const macho_load_command<P>* const cmds = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>));
109 const macho_load_command<P>* const cmdsEnd = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>) + header->sizeofcmds());
110
111 // write out path for -t option
112 if ( logAllFiles )
113 printf("%s\n", path);
114
115 // a "blank" stub has zero load commands
116 if ( (header->filetype() == MH_DYLIB_STUB) && (cmd_count == 0) ) {
117 // no further processing needed
118 munmap((caddr_t)fileContent, fileLength);
119 return;
120 }
121
122
123 // optimize the case where we know there is no reason to look at indirect dylibs
124 this->_noRexports = (header->flags() & MH_NO_REEXPORTED_DYLIBS)
125 || (header->filetype() == MH_BUNDLE)
126 || (header->filetype() == MH_EXECUTE); // bundles and exectuables can be used via -bundle_loader
127 this->_hasWeakExports = (header->flags() & MH_WEAK_DEFINES);
128 this->_deadStrippable = (header->flags() & MH_DEAD_STRIPPABLE_DYLIB);
129 this->_appExtensionSafe = (header->flags() & MH_APP_EXTENSION_SAFE);
130
131 // pass 1: get pointers, and see if this dylib uses compressed LINKEDIT format
132 const macho_dysymtab_command<P>* dynamicInfo = nullptr;
133 const macho_dyld_info_command<P>* dyldInfo = nullptr;
134 const macho_nlist<P>* symbolTable = nullptr;
135 const macho_symtab_command<P>* symtab = nullptr;
136 const char* strings = nullptr;
137 bool compressedLinkEdit = false;
138 uint32_t dependentLibCount = 0;
139 Options::Platform lcPlatform = Options::kPlatformUnknown;
140 const macho_load_command<P>* cmd = cmds;
141 for (uint32_t i = 0; i < cmd_count; ++i) {
142 macho_dylib_command<P>* dylibID;
143 uint32_t cmdLength = cmd->cmdsize();
144 switch (cmd->cmd()) {
145 case LC_SYMTAB:
146 symtab = (macho_symtab_command<P>*)cmd;
147 symbolTable = (const macho_nlist<P>*)((char*)header + symtab->symoff());
148 strings = (char*)header + symtab->stroff();
149 if ( (symtab->stroff() + symtab->strsize()) > fileLength )
150 throwf("mach-o string pool extends beyond end of file in %s", path);
151 break;
152 case LC_DYSYMTAB:
153 dynamicInfo = (macho_dysymtab_command<P>*)cmd;
154 break;
155 case LC_DYLD_INFO:
156 case LC_DYLD_INFO_ONLY:
157 dyldInfo = (macho_dyld_info_command<P>*)cmd;
158 compressedLinkEdit = true;
159 break;
160 case LC_ID_DYLIB:
161 dylibID = (macho_dylib_command<P>*)cmd;
162 if ( dylibID->name_offset() > cmdLength )
163 throwf("malformed mach-o: LC_ID_DYLIB load command has offset (%u) outside its size (%u)", dylibID->name_offset(), cmdLength);
164 if ( (dylibID->name_offset() + strlen(dylibID->name()) + 1) > cmdLength )
165 throwf("malformed mach-o: LC_ID_DYLIB load command string extends beyond end of load command");
166 this->_dylibInstallPath = strdup(dylibID->name());
167 this->_dylibTimeStamp = dylibID->timestamp();
168 this->_dylibCurrentVersion = dylibID->current_version();
169 this->_dylibCompatibilityVersion = dylibID->compatibility_version();
170 this->_hasPublicInstallName = this->isPublicLocation(this->_dylibInstallPath);
171 break;
172 case LC_LOAD_DYLIB:
173 case LC_LOAD_WEAK_DYLIB:
174 ++dependentLibCount;
175 break;
176 case LC_REEXPORT_DYLIB:
177 this->_explictReExportFound = true;
178 ++dependentLibCount;
179 break;
180 case LC_SUB_FRAMEWORK:
181 this->_parentUmbrella = strdup(((macho_sub_framework_command<P>*)cmd)->umbrella());
182 break;
183 case LC_SUB_CLIENT:
184 this->_allowableClients.push_back(strdup(((macho_sub_client_command<P>*)cmd)->client()));
185 // <rdar://problem/20627554> Don't hoist "public" (in /usr/lib/) dylibs that should not be directly linked
186 this->_hasPublicInstallName = false;
187 break;
188 case LC_VERSION_MIN_MACOSX:
189 case LC_VERSION_MIN_IPHONEOS:
190 case LC_VERSION_MIN_WATCHOS:
191 #if SUPPORT_APPLE_TV
192 case LC_VERSION_MIN_TVOS:
193 #endif
194 this->_minVersionInDylib = (ld::MacVersionMin)((macho_version_min_command<P>*)cmd)->version();
195 this->_platformInDylib = cmd->cmd();
196 lcPlatform = Options::platformForLoadCommand(this->_platformInDylib);
197 break;
198 case LC_CODE_SIGNATURE:
199 break;
200 case macho_segment_command<P>::CMD:
201 // check for Objective-C info
202 if ( strncmp(((macho_segment_command<P>*)cmd)->segname(), objCInfoSegmentName(), 6) == 0 ) {
203 const macho_segment_command<P>* segment = (macho_segment_command<P>*)cmd;
204 const macho_section<P>* const sectionsStart = (macho_section<P>*)((char*)segment + sizeof(macho_segment_command<P>));
205 const macho_section<P>* const sectionsEnd = &sectionsStart[segment->nsects()];
206 for (const macho_section<P>* sect=sectionsStart; sect < sectionsEnd; ++sect) {
207 if ( strncmp(sect->sectname(), objCInfoSectionName(), strlen(objCInfoSectionName())) == 0 ) {
208 // struct objc_image_info {
209 // uint32_t version; // initially 0
210 // uint32_t flags;
211 // };
212 // #define OBJC_IMAGE_SUPPORTS_GC 2
213 // #define OBJC_IMAGE_GC_ONLY 4
214 // #define OBJC_IMAGE_IS_SIMULATED 32
215 //
216 const uint32_t* contents = (uint32_t*)(&fileContent[sect->offset()]);
217 if ( (sect->size() >= 8) && (contents[0] == 0) ) {
218 uint32_t flags = E::get32(contents[1]);
219 if ( (flags & 4) == 4 )
220 this->_objcConstraint = ld::File::objcConstraintGC;
221 else if ( (flags & 2) == 2 )
222 this->_objcConstraint = ld::File::objcConstraintRetainReleaseOrGC;
223 else if ( (flags & 32) == 32 )
224 this->_objcConstraint = ld::File::objcConstraintRetainReleaseForSimulator;
225 else
226 this->_objcConstraint = ld::File::objcConstraintRetainRelease;
227 this->_swiftVersion = ((flags >> 8) & 0xFF);
228 }
229 else if ( sect->size() > 0 ) {
230 warning("can't parse %s/%s section in %s", objCInfoSegmentName(), objCInfoSectionName(), path);
231 }
232 }
233 }
234 }
235 // Construct bitcode if there is a bitcode bundle section in the dylib
236 // Record the size of the section because the content is not checked
237 else if ( strcmp(((macho_segment_command<P>*)cmd)->segname(), "__LLVM") == 0 ) {
238 const macho_section<P>* const sect = (macho_section<P>*)((char*)cmd + sizeof(macho_segment_command<P>));
239 if ( strncmp(sect->sectname(), "__bundle", 8) == 0 )
240 this->_bitcode = std::unique_ptr<ld::Bitcode>(new ld::Bitcode(NULL, sect->size()));
241 }
242 else if ( strcmp(((macho_segment_command<P>*)cmd)->segname(), "__LINKEDIT") == 0 ) {
243 _linkeditStartOffset = ((macho_segment_command<P>*)cmd)->fileoff();
244 }
245 }
246 cmd = (const macho_load_command<P>*)(((char*)cmd)+cmdLength);
247 if ( cmd > cmdsEnd )
248 throwf("malformed dylb, load command #%d is outside size of load commands in %s", i, path);
249 }
250 // arm/arm64 objects are default to ios platform if not set.
251 // rdar://problem/21746314
252 if (lcPlatform == Options::kPlatformUnknown &&
253 (std::is_same<A, arm>::value || std::is_same<A, arm64>::value))
254 lcPlatform = Options::kPlatformiOS;
255
256 // check cross-linking
257 if ( lcPlatform != platform ) {
258 this->_wrongOS = true;
259 if ( this->_addVersionLoadCommand && !indirectDylib && !ignoreMismatchPlatform ) {
260 if ( buildingForSimulator ) {
261 if ( !this->_allowSimToMacOSXLinking ) {
262 switch (platform) {
263 case Options::kPlatformOSX:
264 case Options::kPlatformiOS:
265 if ( lcPlatform == Options::kPlatformUnknown )
266 break;
267 // fall through if the Platform is not Unknown
268 case Options::kPlatformWatchOS:
269 // WatchOS errors on cross-linking when building for bitcode
270 if ( usingBitcode )
271 throwf("building for %s simulator, but linking against dylib built for %s,",
272 Options::platformName(platform),
273 Options::platformName(lcPlatform));
274 else
275 warning("URGENT: building for %s simulator, but linking against dylib (%s) built for %s. "
276 "Note: This will be an error in the future.",
277 Options::platformName(platform), path,
278 Options::platformName(lcPlatform));
279 break;
280 #if SUPPORT_APPLE_TV
281 case Options::kPlatform_tvOS:
282 // tvOS is a warning temporarily. rdar://problem/21746965
283 if ( usingBitcode )
284 throwf("building for %s simulator, but linking against dylib built for %s,",
285 Options::platformName(platform),
286 Options::platformName(lcPlatform));
287 else
288 warning("URGENT: building for %s simulator, but linking against dylib (%s) built for %s. "
289 "Note: This will be an error in the future.",
290 Options::platformName(platform), path,
291 Options::platformName(lcPlatform));
292 break;
293 #endif
294 case Options::kPlatformUnknown:
295 // skip if the target platform is unknown
296 break;
297 }
298 }
299 }
300 else {
301 switch (platform) {
302 case Options::kPlatformOSX:
303 case Options::kPlatformiOS:
304 if ( lcPlatform == Options::kPlatformUnknown )
305 break;
306 // fall through if the Platform is not Unknown
307 case Options::kPlatformWatchOS:
308 // WatchOS errors on cross-linking when building for bitcode
309 if ( usingBitcode )
310 throwf("building for %s, but linking against dylib built for %s,",
311 Options::platformName(platform),
312 Options::platformName(lcPlatform));
313 else
314 warning("URGENT: building for %s, but linking against dylib (%s) built for %s. "
315 "Note: This will be an error in the future.",
316 Options::platformName(platform), path,
317 Options::platformName(lcPlatform));
318 break;
319 #if SUPPORT_APPLE_TV
320 case Options::kPlatform_tvOS:
321 // tvOS is a warning temporarily. rdar://problem/21746965
322 if ( usingBitcode )
323 throwf("building for %s, but linking against dylib built for %s,",
324 Options::platformName(platform),
325 Options::platformName(lcPlatform));
326 else
327 warning("URGENT: building for %s, but linking against dylib (%s) built for %s. "
328 "Note: This will be an error in the future.",
329 Options::platformName(platform), path,
330 Options::platformName(lcPlatform));
331 break;
332 #endif
333 case Options::kPlatformUnknown:
334 // skip if the target platform is unknown
335 break;
336 }
337 }
338 }
339 }
340
341 // figure out if we need to examine dependent dylibs
342 // with compressed LINKEDIT format, MH_NO_REEXPORTED_DYLIBS can be trusted
343 bool processDependentLibraries = true;
344 if ( compressedLinkEdit && this->_noRexports && !linkingFlatNamespace)
345 processDependentLibraries = false;
346
347 if ( processDependentLibraries ) {
348 // pass 2 builds list of all dependent libraries
349 this->_dependentDylibs.reserve(dependentLibCount);
350 cmd = cmds;
351 unsigned int reExportDylibCount = 0;
352 for (uint32_t i = 0; i < cmd_count; ++i) {
353 uint32_t cmdLength = cmd->cmdsize();
354 const macho_dylib_command<P>* dylibCmd = (macho_dylib_command<P>*)cmd;
355 switch (cmd->cmd()) {
356 case LC_LOAD_DYLIB:
357 case LC_LOAD_WEAK_DYLIB:
358 // with new linkedit format only care about LC_REEXPORT_DYLIB
359 if ( compressedLinkEdit && !linkingFlatNamespace )
360 break;
361 case LC_REEXPORT_DYLIB:
362 ++reExportDylibCount;
363 if ( dylibCmd->name_offset() > cmdLength )
364 throwf("malformed mach-o: LC_*_DYLIB load command has offset (%u) outside its size (%u)", dylibCmd->name_offset(), cmdLength);
365 if ( (dylibCmd->name_offset() + strlen(dylibCmd->name()) + 1) > cmdLength )
366 throwf("malformed mach-o: LC_*_DYLIB load command string extends beyond end of load command");
367 const char *path = strdup(dylibCmd->name());
368 bool reExport = (cmd->cmd() == LC_REEXPORT_DYLIB);
369 if ( (targetInstallPath == nullptr) || (strcmp(targetInstallPath, path) != 0) )
370 this->_dependentDylibs.emplace_back(path, reExport);
371 break;
372 }
373 cmd = (const macho_load_command<P>*)(((char*)cmd)+cmdLength);
374 }
375 // verify MH_NO_REEXPORTED_DYLIBS bit was correct
376 if ( compressedLinkEdit && !linkingFlatNamespace ) {
377 if ( reExportDylibCount == 0 )
378 throwf("malformed dylib has MH_NO_REEXPORTED_DYLIBS flag but no LC_REEXPORT_DYLIB load commands: %s", path);
379 }
380 // pass 3 add re-export info
381 cmd = cmds;
382 for (uint32_t i = 0; i < cmd_count; ++i) {
383 const char* frameworkLeafName;
384 const char* dylibBaseName;
385 switch (cmd->cmd()) {
386 case LC_SUB_UMBRELLA:
387 frameworkLeafName = ((macho_sub_umbrella_command<P>*)cmd)->sub_umbrella();
388 for (auto &dep : this->_dependentDylibs) {
389 const char* dylibName = dep.path;
390 const char* lastSlash = strrchr(dylibName, '/');
391 if ( (lastSlash != nullptr) && (strcmp(&lastSlash[1], frameworkLeafName) == 0) )
392 dep.reExport = true;
393 }
394 break;
395 case LC_SUB_LIBRARY:
396 dylibBaseName = ((macho_sub_library_command<P>*)cmd)->sub_library();
397 for (auto &dep : this->_dependentDylibs) {
398 const char* dylibName = dep.path;
399 const char* lastSlash = strrchr(dylibName, '/');
400 const char* leafStart = &lastSlash[1];
401 if ( lastSlash == nullptr )
402 leafStart = dylibName;
403 const char* firstDot = strchr(leafStart, '.');
404 int len = strlen(leafStart);
405 if ( firstDot != nullptr )
406 len = firstDot - leafStart;
407 if ( strncmp(leafStart, dylibBaseName, len) == 0 )
408 dep.reExport = true;
409 }
410 break;
411 }
412 cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
413 }
414 }
415
416 // if framework, capture framework name
417 if ( this->_dylibInstallPath != NULL ) {
418 const char* lastSlash = strrchr(this->_dylibInstallPath, '/');
419 if ( lastSlash != NULL ) {
420 const char* leafName = lastSlash+1;
421 char frname[strlen(leafName)+32];
422 strcpy(frname, leafName);
423 strcat(frname, ".framework/");
424
425 if ( strstr(this->_dylibInstallPath, frname) != NULL )
426 this->_frameworkName = leafName;
427 }
428 }
429
430 // validate minimal load commands
431 if ( (this->_dylibInstallPath == nullptr) && ((header->filetype() == MH_DYLIB) || (header->filetype() == MH_DYLIB_STUB)) )
432 throwf("dylib %s missing LC_ID_DYLIB load command", path);
433 if ( dyldInfo == nullptr ) {
434 if ( symbolTable == nullptr )
435 throw "binary missing LC_SYMTAB load command";
436 if ( dynamicInfo == nullptr )
437 throw "binary missing LC_DYSYMTAB load command";
438 }
439
440 if ( symtab != nullptr ) {
441 if ( symtab->symoff() < _linkeditStartOffset )
442 throwf("malformed mach-o, symbol table not in __LINKEDIT");
443 if ( symtab->stroff() < _linkeditStartOffset )
444 throwf("malformed mach-o, symbol table strings not in __LINKEDIT");
445 }
446
447 // if linking flat and this is a flat dylib, create one atom that references all imported symbols
448 if ( linkingFlatNamespace && linkingMainExecutable && ((header->flags() & MH_TWOLEVEL) == 0) ) {
449 std::vector<const char*> importNames;
450 importNames.reserve(dynamicInfo->nundefsym());
451 const macho_nlist<P>* start = &symbolTable[dynamicInfo->iundefsym()];
452 const macho_nlist<P>* end = &start[dynamicInfo->nundefsym()];
453 for (const macho_nlist<P>* sym=start; sym < end; ++sym) {
454 importNames.push_back(&strings[sym->n_strx()]);
455 }
456 this->_importAtom = new generic::dylib::ImportAtom<A>(*this, importNames);
457 }
458
459 // build hash table
460 if ( dyldInfo != nullptr )
461 buildExportHashTableFromExportInfo(dyldInfo, fileContent);
462 else
463 buildExportHashTableFromSymbolTable(dynamicInfo, symbolTable, strings, fileContent);
464
465 // unmap file
466 munmap((caddr_t)fileContent, fileLength);
467 }
468
469 template <typename A>
470 void File<A>::buildExportHashTableFromSymbolTable(const macho_dysymtab_command<P>* dynamicInfo,
471 const macho_nlist<P>* symbolTable,
472 const char* strings, const uint8_t* fileContent)
473 {
474 if ( dynamicInfo->tocoff() == 0 ) {
475 if ( this->_s_logHashtable )
476 fprintf(stderr, "ld: building hashtable of %u toc entries for %s\n", dynamicInfo->nextdefsym(), this->path());
477 const macho_nlist<P>* start = &symbolTable[dynamicInfo->iextdefsym()];
478 const macho_nlist<P>* end = &start[dynamicInfo->nextdefsym()];
479 this->_atoms.reserve(dynamicInfo->nextdefsym()); // set initial bucket count
480 for (const macho_nlist<P>* sym=start; sym < end; ++sym) {
481 this->addSymbol(&strings[sym->n_strx()], (sym->n_desc() & N_WEAK_DEF) != 0, false, sym->n_value());
482 }
483 }
484 else {
485 int32_t count = dynamicInfo->ntoc();
486 this->_atoms.reserve(count); // set initial bucket count
487 if ( this->_s_logHashtable )
488 fprintf(stderr, "ld: building hashtable of %u entries for %s\n", count, this->path());
489 const auto* toc = reinterpret_cast<const dylib_table_of_contents*>(fileContent + dynamicInfo->tocoff());
490 for (int32_t i = 0; i < count; ++i) {
491 const uint32_t index = E::get32(toc[i].symbol_index);
492 const macho_nlist<P>* sym = &symbolTable[index];
493 this->addSymbol(&strings[sym->n_strx()], (sym->n_desc() & N_WEAK_DEF) != 0, false, sym->n_value());
494 }
495 }
496
497 // special case old libSystem
498 if ( (this->_dylibInstallPath != nullptr) && (strcmp(this->_dylibInstallPath, "/usr/lib/libSystem.B.dylib") == 0) )
499 addDyldFastStub();
500 }
501
502
503 template <typename A>
504 void File<A>::buildExportHashTableFromExportInfo(const macho_dyld_info_command<P>* dyldInfo,
505 const uint8_t* fileContent)
506 {
507 if ( this->_s_logHashtable )
508 fprintf(stderr, "ld: building hashtable from export info in %s\n", this->path());
509 if ( dyldInfo->export_size() > 0 ) {
510 const uint8_t* start = fileContent + dyldInfo->export_off();
511 const uint8_t* end = &start[dyldInfo->export_size()];
512 if ( (dyldInfo->export_off() + dyldInfo->export_size()) > _fileLength )
513 throwf("malformed mach-o dylib, exports trie extends beyond end of file, ");
514 std::vector<mach_o::trie::Entry> list;
515 parseTrie(start, end, list);
516 for (const auto &entry : list)
517 this->addSymbol(entry.name,
518 entry.flags & EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION,
519 (entry.flags & EXPORT_SYMBOL_FLAGS_KIND_MASK) == EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL,
520 entry.address);
521 }
522 }
523
524
525 template <>
526 void File<x86_64>::addDyldFastStub()
527 {
528 addSymbol("dyld_stub_binder");
529 }
530
531 template <>
532 void File<x86>::addDyldFastStub()
533 {
534 addSymbol("dyld_stub_binder");
535 }
536
537 template <typename A>
538 void File<A>::addDyldFastStub()
539 {
540 // do nothing
541 }
542
543 template <typename A>
544 class Parser
545 {
546 public:
547 using P = typename A::P;
548
549 static bool validFile(const uint8_t* fileContent, bool executableOrDyliborBundle, bool subTypeMustMatch=false, uint32_t subType=0);
550 static const char* fileKind(const uint8_t* fileContent);
551 static ld::dylib::File* parse(const uint8_t* fileContent, uint64_t fileLength, const char* path,
552 time_t mTime, ld::File::Ordinal ordinal, const Options& opts,
553 bool indirectDylib)
554 {
555 return new File<A>(fileContent, fileLength, path, mTime, ordinal, opts.flatNamespace(),
556 opts.linkingMainExecutable(), opts.implicitlyLinkIndirectPublicDylibs(),
557 opts.platform(), opts.minOSversion(),
558 opts.allowSimulatorToLinkWithMacOSX(), opts.addVersionLoadCommand(),
559 opts.targetIOSSimulator(), opts.logAllFiles(), opts.installPath(),
560 indirectDylib, opts.outputKind() == Options::kPreload, opts.bundleBitcode());
561 }
562
563 };
564
565
566
567 template <>
568 bool Parser<x86>::validFile(const uint8_t* fileContent, bool executableOrDyliborBundle, bool subTypeMustMatch, uint32_t subType)
569 {
570 const auto* header = reinterpret_cast<const macho_header<P>*>(fileContent);
571 if ( header->magic() != MH_MAGIC )
572 return false;
573 if ( header->cputype() != CPU_TYPE_I386 )
574 return false;
575 switch ( header->filetype() ) {
576 case MH_DYLIB:
577 case MH_DYLIB_STUB:
578 return true;
579 case MH_BUNDLE:
580 if ( executableOrDyliborBundle )
581 return true;
582 else
583 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
584 case MH_EXECUTE:
585 if ( executableOrDyliborBundle )
586 return true;
587 else
588 throw "can't link with a main executable";
589 default:
590 return false;
591 }
592 }
593
594 template <>
595 bool Parser<x86_64>::validFile(const uint8_t* fileContent, bool executableOrDyliborBundle, bool subTypeMustMatch, uint32_t subType)
596 {
597 const auto* header = reinterpret_cast<const macho_header<P>*>(fileContent);
598 if ( header->magic() != MH_MAGIC_64 )
599 return false;
600 if ( header->cputype() != CPU_TYPE_X86_64 )
601 return false;
602 switch ( header->filetype() ) {
603 case MH_DYLIB:
604 case MH_DYLIB_STUB:
605 return true;
606 case MH_BUNDLE:
607 if ( executableOrDyliborBundle )
608 return true;
609 else
610 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
611 case MH_EXECUTE:
612 if ( executableOrDyliborBundle )
613 return true;
614 else
615 throw "can't link with a main executable";
616 default:
617 return false;
618 }
619 }
620
621 template <>
622 bool Parser<arm>::validFile(const uint8_t* fileContent, bool executableOrDyliborBundle, bool subTypeMustMatch, uint32_t subType)
623 {
624 const auto* header = reinterpret_cast<const macho_header<P>*>(fileContent);
625 if ( header->magic() != MH_MAGIC )
626 return false;
627 if ( header->cputype() != CPU_TYPE_ARM )
628 return false;
629 if ( subTypeMustMatch && (header->cpusubtype() != subType) )
630 return false;
631 switch ( header->filetype() ) {
632 case MH_DYLIB:
633 case MH_DYLIB_STUB:
634 return true;
635 case MH_BUNDLE:
636 if ( executableOrDyliborBundle )
637 return true;
638 else
639 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
640 case MH_EXECUTE:
641 if ( executableOrDyliborBundle )
642 return true;
643 else
644 throw "can't link with a main executable";
645 default:
646 return false;
647 }
648 }
649
650
651
652 template <>
653 bool Parser<arm64>::validFile(const uint8_t* fileContent, bool executableOrDyliborBundle, bool subTypeMustMatch, uint32_t subType)
654 {
655 const auto* header = reinterpret_cast<const macho_header<P>*>(fileContent);
656 if ( header->magic() != MH_MAGIC_64 )
657 return false;
658 if ( header->cputype() != CPU_TYPE_ARM64 )
659 return false;
660 switch ( header->filetype() ) {
661 case MH_DYLIB:
662 case MH_DYLIB_STUB:
663 return true;
664 case MH_BUNDLE:
665 if ( executableOrDyliborBundle )
666 return true;
667 else
668 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
669 case MH_EXECUTE:
670 if ( executableOrDyliborBundle )
671 return true;
672 else
673 throw "can't link with a main executable";
674 default:
675 return false;
676 }
677 }
678
679
680 bool isDylibFile(const uint8_t* fileContent, cpu_type_t* result, cpu_subtype_t* subResult)
681 {
682 if ( Parser<x86_64>::validFile(fileContent, false) ) {
683 *result = CPU_TYPE_X86_64;
684 const auto* header = reinterpret_cast<const macho_header<Pointer64<LittleEndian>>*>(fileContent);
685 *subResult = header->cpusubtype();
686 return true;
687 }
688 if ( Parser<x86>::validFile(fileContent, false) ) {
689 *result = CPU_TYPE_I386;
690 *subResult = CPU_SUBTYPE_X86_ALL;
691 return true;
692 }
693 if ( Parser<arm>::validFile(fileContent, false) ) {
694 *result = CPU_TYPE_ARM;
695 const auto* header = reinterpret_cast<const macho_header<Pointer32<LittleEndian>>*>(fileContent);
696 *subResult = header->cpusubtype();
697 return true;
698 }
699 if ( Parser<arm64>::validFile(fileContent, false) ) {
700 *result = CPU_TYPE_ARM64;
701 *subResult = CPU_SUBTYPE_ARM64_ALL;
702 return true;
703 }
704 return false;
705 }
706
707 template <>
708 const char* Parser<x86>::fileKind(const uint8_t* fileContent)
709 {
710 const auto* header = reinterpret_cast<const macho_header<P>*>(fileContent);
711 if ( header->magic() != MH_MAGIC )
712 return nullptr;
713 if ( header->cputype() != CPU_TYPE_I386 )
714 return nullptr;
715 return "i386";
716 }
717
718 template <>
719 const char* Parser<x86_64>::fileKind(const uint8_t* fileContent)
720 {
721 const auto* header = reinterpret_cast<const macho_header<P>*>(fileContent);
722 if ( header->magic() != MH_MAGIC_64 )
723 return nullptr;
724 if ( header->cputype() != CPU_TYPE_X86_64 )
725 return nullptr;
726 return "x86_64";
727 }
728
729 template <>
730 const char* Parser<arm>::fileKind(const uint8_t* fileContent)
731 {
732 const auto* header = reinterpret_cast<const macho_header<P>*>(fileContent);
733 if ( header->magic() != MH_MAGIC )
734 return nullptr;
735 if ( header->cputype() != CPU_TYPE_ARM )
736 return nullptr;
737 for (const auto* t = archInfoArray; t->archName != nullptr; ++t) {
738 if ( (t->cpuType == CPU_TYPE_ARM) && ((cpu_subtype_t)header->cpusubtype() == t->cpuSubType) ) {
739 return t->archName;
740 }
741 }
742 return "arm???";
743 }
744
745 #if SUPPORT_ARCH_arm64
746 template <>
747 const char* Parser<arm64>::fileKind(const uint8_t* fileContent)
748 {
749 const auto* header = reinterpret_cast<const macho_header<P>*>(fileContent);
750 if ( header->magic() != MH_MAGIC_64 )
751 return nullptr;
752 if ( header->cputype() != CPU_TYPE_ARM64 )
753 return nullptr;
754 return "arm64";
755 }
756 #endif
757
758 //
759 // used by linker is error messages to describe mismatched files
760 //
761 const char* archName(const uint8_t* fileContent)
762 {
763 if ( Parser<x86_64>::validFile(fileContent, true) ) {
764 return Parser<x86_64>::fileKind(fileContent);
765 }
766 if ( Parser<x86>::validFile(fileContent, true) ) {
767 return Parser<x86>::fileKind(fileContent);
768 }
769 if ( Parser<arm>::validFile(fileContent, true) ) {
770 return Parser<arm>::fileKind(fileContent);
771 }
772 #if SUPPORT_ARCH_arm64
773 if ( Parser<arm64>::validFile(fileContent, false) ) {
774 return Parser<arm64>::fileKind(fileContent);
775 }
776 #endif
777 return nullptr;
778 }
779
780
781 //
782 // main function used by linker to instantiate ld::Files
783 //
784 ld::dylib::File* parse(const uint8_t* fileContent, uint64_t fileLength, const char* path,
785 time_t modTime, const Options& opts, ld::File::Ordinal ordinal,
786 bool bundleLoader, bool indirectDylib)
787 {
788 bool subTypeMustMatch = opts.enforceDylibSubtypesMatch();
789 switch ( opts.architecture() ) {
790 #if SUPPORT_ARCH_x86_64
791 case CPU_TYPE_X86_64:
792 if ( Parser<x86_64>::validFile(fileContent, bundleLoader, subTypeMustMatch, opts.subArchitecture()) )
793 return Parser<x86_64>::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib);
794 break;
795 #endif
796 #if SUPPORT_ARCH_i386
797 case CPU_TYPE_I386:
798 if ( Parser<x86>::validFile(fileContent, bundleLoader, subTypeMustMatch, opts.subArchitecture()) )
799 return Parser<x86>::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib);
800 break;
801 #endif
802 #if SUPPORT_ARCH_arm_any
803 case CPU_TYPE_ARM:
804 if ( Parser<arm>::validFile(fileContent, bundleLoader, subTypeMustMatch, opts.subArchitecture()) )
805 return Parser<arm>::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib);
806 break;
807 #endif
808 #if SUPPORT_ARCH_arm64
809 case CPU_TYPE_ARM64:
810 if ( Parser<arm64>::validFile(fileContent, bundleLoader, subTypeMustMatch, opts.subArchitecture()) )
811 return Parser<arm64>::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib);
812 break;
813 #endif
814 }
815 return nullptr;
816 }
817
818
819 }; // namespace dylib
820 }; // namespace mach_o