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