]> git.saurik.com Git - apple/ld64.git/blame - src/ld/parsers/macho_dylib_file.cpp
ld64-264.3.101.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>
a645023d
A
37
38#include "Architectures.hpp"
eaf282aa 39#include "Bitcode.hpp"
a645023d
A
40#include "MachOFileAbstraction.hpp"
41#include "MachOTrie.hpp"
ec29ba20 42#include "generic_dylib_file.hpp"
a645023d 43#include "macho_dylib_file.h"
ebf6f434 44#include "../code-sign-blobs/superblob.h"
a645023d
A
45
46namespace mach_o {
47namespace dylib {
48
a645023d
A
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//
54template <typename A>
ec29ba20 55class File final : public generic::dylib::File<A>
a645023d 56{
ec29ba20
A
57 using Base = generic::dylib::File<A>;
58
a645023d 59public:
ec29ba20 60 static bool validFile(const uint8_t* fileContent, bool executableOrDylib, bool subTypeMustMatch=false);
a645023d 61 File(const uint8_t* fileContent, uint64_t fileLength, const char* path,
ebf6f434 62 time_t mTime, ld::File::Ordinal ordinal, bool linkingFlatNamespace,
a645023d 63 bool linkingMainExecutable, bool hoistImplicitPublicDylibs,
eaf282aa
A
64 Options::Platform platform, uint32_t linkMinOSVersion, bool allowSimToMacOSX,
65 bool addVers, bool buildingForSimulator,
66 bool logAllFiles, const char* installPath,
dd9e569f 67 bool indirectDylib, bool ignoreMismatchPlatform, bool usingBitcode);
ec29ba20 68 virtual ~File() noexcept {}
a645023d
A
69
70private:
ec29ba20
A
71 using P = typename A::P;
72 using E = typename A::P::E;
a645023d 73
ec29ba20
A
74 void addDyldFastStub();
75 void buildExportHashTableFromExportInfo(const macho_dyld_info_command<P>* dyldInfo,
a645023d 76 const uint8_t* fileContent);
ec29ba20 77 void buildExportHashTableFromSymbolTable(const macho_dysymtab_command<P>* dynamicInfo,
a645023d
A
78 const macho_nlist<P>* symbolTable, const char* strings,
79 const uint8_t* fileContent);
ec29ba20
A
80 static const char* objCInfoSegmentName();
81 static const char* objCInfoSectionName();
eaf282aa 82
a645023d 83
ec29ba20
A
84 uint64_t _fileLength;
85 uint32_t _linkeditStartOffset;
86
87};
a645023d
A
88
89template <> const char* File<x86_64>::objCInfoSegmentName() { return "__DATA"; }
90template <> const char* File<arm>::objCInfoSegmentName() { return "__DATA"; }
91template <typename A> const char* File<A>::objCInfoSegmentName() { return "__OBJC"; }
92
93template <> const char* File<x86_64>::objCInfoSectionName() { return "__objc_imageinfo"; }
94template <> const char* File<arm>::objCInfoSectionName() { return "__objc_imageinfo"; }
95template <typename A> const char* File<A>::objCInfoSectionName() { return "__image_info"; }
96
97template <typename A>
ec29ba20
A
98File<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)
a645023d
A
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 )
ec29ba20 113 printf("%s\n", path);
a645023d
A
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
ec29ba20
A
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);
a645023d
A
130
131 // pass 1: get pointers, and see if this dylib uses compressed LINKEDIT format
ec29ba20
A
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;
a645023d
A
137 bool compressedLinkEdit = false;
138 uint32_t dependentLibCount = 0;
eaf282aa 139 Options::Platform lcPlatform = Options::kPlatformUnknown;
a645023d
A
140 const macho_load_command<P>* cmd = cmds;
141 for (uint32_t i = 0; i < cmd_count; ++i) {
142 macho_dylib_command<P>* dylibID;
ec29ba20 143 uint32_t cmdLength = cmd->cmdsize();
a645023d
A
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();
ebf6f434 149 if ( (symtab->stroff() + symtab->strsize()) > fileLength )
ec29ba20 150 throwf("mach-o string pool extends beyond end of file in %s", path);
a645023d
A
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;
ec29ba20
A
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);
a645023d
A
171 break;
172 case LC_LOAD_DYLIB:
173 case LC_LOAD_WEAK_DYLIB:
174 ++dependentLibCount;
175 break;
176 case LC_REEXPORT_DYLIB:
ec29ba20 177 this->_explictReExportFound = true;
a645023d
A
178 ++dependentLibCount;
179 break;
180 case LC_SUB_FRAMEWORK:
ec29ba20 181 this->_parentUmbrella = strdup(((macho_sub_framework_command<P>*)cmd)->umbrella());
a645023d
A
182 break;
183 case LC_SUB_CLIENT:
ec29ba20 184 this->_allowableClients.push_back(strdup(((macho_sub_client_command<P>*)cmd)->client()));
eaf282aa 185 // <rdar://problem/20627554> Don't hoist "public" (in /usr/lib/) dylibs that should not be directly linked
ec29ba20 186 this->_hasPublicInstallName = false;
a645023d 187 break;
afe874b1 188 case LC_VERSION_MIN_MACOSX:
afe874b1 189 case LC_VERSION_MIN_IPHONEOS:
eaf282aa
A
190 case LC_VERSION_MIN_WATCHOS:
191 #if SUPPORT_APPLE_TV
192 case LC_VERSION_MIN_TVOS:
193 #endif
ec29ba20
A
194 this->_minVersionInDylib = (ld::MacVersionMin)((macho_version_min_command<P>*)cmd)->version();
195 this->_platformInDylib = cmd->cmd();
196 lcPlatform = Options::platformForLoadCommand(this->_platformInDylib);
afe874b1 197 break;
ebf6f434 198 case LC_CODE_SIGNATURE:
ebf6f434 199 break;
a645023d
A
200 case macho_segment_command<P>::CMD:
201 // check for Objective-C info
eaf282aa 202 if ( strncmp(((macho_segment_command<P>*)cmd)->segname(), objCInfoSegmentName(), 6) == 0 ) {
a645023d
A
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
f80fe69f 214 // #define OBJC_IMAGE_IS_SIMULATED 32
a645023d
A
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 )
ec29ba20 220 this->_objcConstraint = ld::File::objcConstraintGC;
a645023d 221 else if ( (flags & 2) == 2 )
ec29ba20 222 this->_objcConstraint = ld::File::objcConstraintRetainReleaseOrGC;
f80fe69f 223 else if ( (flags & 32) == 32 )
ec29ba20 224 this->_objcConstraint = ld::File::objcConstraintRetainReleaseForSimulator;
a645023d 225 else
ec29ba20
A
226 this->_objcConstraint = ld::File::objcConstraintRetainRelease;
227 this->_swiftVersion = ((flags >> 8) & 0xFF);
a645023d
A
228 }
229 else if ( sect->size() > 0 ) {
ec29ba20 230 warning("can't parse %s/%s section in %s", objCInfoSegmentName(), objCInfoSectionName(), path);
a645023d
A
231 }
232 }
233 }
234 }
eaf282aa
A
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 )
ec29ba20
A
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();
eaf282aa 244 }
a645023d 245 }
ec29ba20 246 cmd = (const macho_load_command<P>*)(((char*)cmd)+cmdLength);
a645023d 247 if ( cmd > cmdsEnd )
ec29ba20 248 throwf("malformed dylb, load command #%d is outside size of load commands in %s", i, path);
a645023d 249 }
eaf282aa
A
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 ) {
ec29ba20
A
258 this->_wrongOS = true;
259 if ( this->_addVersionLoadCommand && !indirectDylib && !ignoreMismatchPlatform ) {
eaf282aa 260 if ( buildingForSimulator ) {
ec29ba20 261 if ( !this->_allowSimToMacOSXLinking ) {
eaf282aa
A
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:
ec29ba20
A
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,",
eaf282aa
A
272 Options::platformName(platform),
273 Options::platformName(lcPlatform));
ec29ba20
A
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));
eaf282aa
A
279 break;
280 #if SUPPORT_APPLE_TV
281 case Options::kPlatform_tvOS:
282 // tvOS is a warning temporarily. rdar://problem/21746965
dd9e569f
A
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
eaf282aa
A
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.",
ec29ba20 290 Options::platformName(platform), path,
eaf282aa
A
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:
ec29ba20
A
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,",
eaf282aa
A
311 Options::platformName(platform),
312 Options::platformName(lcPlatform));
ec29ba20
A
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));
eaf282aa
A
318 break;
319 #if SUPPORT_APPLE_TV
320 case Options::kPlatform_tvOS:
321 // tvOS is a warning temporarily. rdar://problem/21746965
ec29ba20 322 if ( usingBitcode )
dd9e569f
A
323 throwf("building for %s, but linking against dylib built for %s,",
324 Options::platformName(platform),
325 Options::platformName(lcPlatform));
326 else
eaf282aa
A
327 warning("URGENT: building for %s, but linking against dylib (%s) built for %s. "
328 "Note: This will be an error in the future.",
ec29ba20 329 Options::platformName(platform), path,
eaf282aa
A
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 }
a645023d
A
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;
ec29ba20 344 if ( compressedLinkEdit && this->_noRexports && !linkingFlatNamespace)
a645023d
A
345 processDependentLibraries = false;
346
347 if ( processDependentLibraries ) {
348 // pass 2 builds list of all dependent libraries
ec29ba20 349 this->_dependentDylibs.reserve(dependentLibCount);
a645023d 350 cmd = cmds;
b1f7435d 351 unsigned int reExportDylibCount = 0;
a645023d 352 for (uint32_t i = 0; i < cmd_count; ++i) {
ec29ba20
A
353 uint32_t cmdLength = cmd->cmdsize();
354 const macho_dylib_command<P>* dylibCmd = (macho_dylib_command<P>*)cmd;
a645023d
A
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:
b1f7435d 362 ++reExportDylibCount;
ec29ba20
A
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);
a645023d
A
371 break;
372 }
ec29ba20 373 cmd = (const macho_load_command<P>*)(((char*)cmd)+cmdLength);
a645023d
A
374 }
375 // verify MH_NO_REEXPORTED_DYLIBS bit was correct
376 if ( compressedLinkEdit && !linkingFlatNamespace ) {
eaf282aa 377 if ( reExportDylibCount == 0 )
ec29ba20 378 throwf("malformed dylib has MH_NO_REEXPORTED_DYLIBS flag but no LC_REEXPORT_DYLIB load commands: %s", path);
a645023d
A
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();
ec29ba20
A
388 for (auto &dep : this->_dependentDylibs) {
389 const char* dylibName = dep.path;
a645023d 390 const char* lastSlash = strrchr(dylibName, '/');
ec29ba20
A
391 if ( (lastSlash != nullptr) && (strcmp(&lastSlash[1], frameworkLeafName) == 0) )
392 dep.reExport = true;
a645023d
A
393 }
394 break;
395 case LC_SUB_LIBRARY:
396 dylibBaseName = ((macho_sub_library_command<P>*)cmd)->sub_library();
ec29ba20
A
397 for (auto &dep : this->_dependentDylibs) {
398 const char* dylibName = dep.path;
a645023d
A
399 const char* lastSlash = strrchr(dylibName, '/');
400 const char* leafStart = &lastSlash[1];
ec29ba20 401 if ( lastSlash == nullptr )
a645023d
A
402 leafStart = dylibName;
403 const char* firstDot = strchr(leafStart, '.');
404 int len = strlen(leafStart);
ec29ba20 405 if ( firstDot != nullptr )
a645023d
A
406 len = firstDot - leafStart;
407 if ( strncmp(leafStart, dylibBaseName, len) == 0 )
ec29ba20 408 dep.reExport = true;
a645023d
A
409 }
410 break;
411 }
412 cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
413 }
414 }
ec29ba20
A
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
a645023d 430 // validate minimal load commands
ec29ba20
A
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 )
a645023d 435 throw "binary missing LC_SYMTAB load command";
ec29ba20 436 if ( dynamicInfo == nullptr )
a645023d
A
437 throw "binary missing LC_DYSYMTAB load command";
438 }
ec29ba20
A
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
a645023d
A
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 }
ec29ba20 456 this->_importAtom = new generic::dylib::ImportAtom<A>(*this, importNames);
a645023d 457 }
eaf282aa 458
a645023d 459 // build hash table
ec29ba20 460 if ( dyldInfo != nullptr )
a645023d
A
461 buildExportHashTableFromExportInfo(dyldInfo, fileContent);
462 else
463 buildExportHashTableFromSymbolTable(dynamicInfo, symbolTable, strings, fileContent);
464
465 // unmap file
466 munmap((caddr_t)fileContent, fileLength);
467}
468
a645023d 469template <typename A>
ec29ba20
A
470void File<A>::buildExportHashTableFromSymbolTable(const macho_dysymtab_command<P>* dynamicInfo,
471 const macho_nlist<P>* symbolTable,
472 const char* strings, const uint8_t* fileContent)
a645023d
A
473{
474 if ( dynamicInfo->tocoff() == 0 ) {
ec29ba20
A
475 if ( this->_s_logHashtable )
476 fprintf(stderr, "ld: building hashtable of %u toc entries for %s\n", dynamicInfo->nextdefsym(), this->path());
a645023d
A
477 const macho_nlist<P>* start = &symbolTable[dynamicInfo->iextdefsym()];
478 const macho_nlist<P>* end = &start[dynamicInfo->nextdefsym()];
ec29ba20 479 this->_atoms.reserve(dynamicInfo->nextdefsym()); // set initial bucket count
a645023d
A
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();
ec29ba20
A
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());
a645023d
A
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
ec29ba20 498 if ( (this->_dylibInstallPath != nullptr) && (strcmp(this->_dylibInstallPath, "/usr/lib/libSystem.B.dylib") == 0) )
a645023d
A
499 addDyldFastStub();
500}
501
502
503template <typename A>
ec29ba20
A
504void File<A>::buildExportHashTableFromExportInfo(const macho_dyld_info_command<P>* dyldInfo,
505 const uint8_t* fileContent)
a645023d 506{
ec29ba20
A
507 if ( this->_s_logHashtable )
508 fprintf(stderr, "ld: building hashtable from export info in %s\n", this->path());
a645023d
A
509 if ( dyldInfo->export_size() > 0 ) {
510 const uint8_t* start = fileContent + dyldInfo->export_off();
511 const uint8_t* end = &start[dyldInfo->export_size()];
ec29ba20
A
512 if ( (dyldInfo->export_off() + dyldInfo->export_size()) > _fileLength )
513 throwf("malformed mach-o dylib, exports trie extends beyond end of file, ");
a645023d
A
514 std::vector<mach_o::trie::Entry> list;
515 parseTrie(start, end, list);
ec29ba20
A
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);
a645023d
A
521 }
522}
523
524
525template <>
526void File<x86_64>::addDyldFastStub()
527{
ec29ba20 528 addSymbol("dyld_stub_binder");
a645023d
A
529}
530
531template <>
532void File<x86>::addDyldFastStub()
533{
ec29ba20 534 addSymbol("dyld_stub_binder");
a645023d
A
535}
536
537template <typename A>
538void File<A>::addDyldFastStub()
539{
540 // do nothing
541}
542
a645023d
A
543template <typename A>
544class Parser
545{
546public:
ec29ba20
A
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 }
a645023d
A
562
563};
564
565
566
a645023d 567template <>
ec29ba20 568bool Parser<x86>::validFile(const uint8_t* fileContent, bool executableOrDyliborBundle, bool subTypeMustMatch, uint32_t subType)
a645023d 569{
ec29ba20 570 const auto* header = reinterpret_cast<const macho_header<P>*>(fileContent);
a645023d
A
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
594template <>
ec29ba20 595bool Parser<x86_64>::validFile(const uint8_t* fileContent, bool executableOrDyliborBundle, bool subTypeMustMatch, uint32_t subType)
a645023d 596{
ec29ba20 597 const auto* header = reinterpret_cast<const macho_header<P>*>(fileContent);
a645023d
A
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
621template <>
ec29ba20 622bool Parser<arm>::validFile(const uint8_t* fileContent, bool executableOrDyliborBundle, bool subTypeMustMatch, uint32_t subType)
a645023d 623{
ec29ba20 624 const auto* header = reinterpret_cast<const macho_header<P>*>(fileContent);
a645023d
A
625 if ( header->magic() != MH_MAGIC )
626 return false;
627 if ( header->cputype() != CPU_TYPE_ARM )
628 return false;
ec29ba20
A
629 if ( subTypeMustMatch && (header->cpusubtype() != subType) )
630 return false;
a645023d
A
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
f80fe69f 652template <>
ec29ba20 653bool Parser<arm64>::validFile(const uint8_t* fileContent, bool executableOrDyliborBundle, bool subTypeMustMatch, uint32_t subType)
f80fe69f 654{
ec29ba20 655 const auto* header = reinterpret_cast<const macho_header<P>*>(fileContent);
f80fe69f
A
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
680bool 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;
ec29ba20 684 const auto* header = reinterpret_cast<const macho_header<Pointer64<LittleEndian>>*>(fileContent);
9543cb2f 685 *subResult = header->cpusubtype();
f80fe69f
A
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;
ec29ba20 695 const auto* header = reinterpret_cast<const macho_header<Pointer32<LittleEndian>>*>(fileContent);
f80fe69f
A
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 }
f80fe69f
A
704 return false;
705}
706
707template <>
708const char* Parser<x86>::fileKind(const uint8_t* fileContent)
709{
ec29ba20 710 const auto* header = reinterpret_cast<const macho_header<P>*>(fileContent);
f80fe69f 711 if ( header->magic() != MH_MAGIC )
ec29ba20 712 return nullptr;
f80fe69f 713 if ( header->cputype() != CPU_TYPE_I386 )
ec29ba20 714 return nullptr;
f80fe69f
A
715 return "i386";
716}
717
718template <>
719const char* Parser<x86_64>::fileKind(const uint8_t* fileContent)
720{
ec29ba20 721 const auto* header = reinterpret_cast<const macho_header<P>*>(fileContent);
f80fe69f 722 if ( header->magic() != MH_MAGIC_64 )
ec29ba20 723 return nullptr;
f80fe69f 724 if ( header->cputype() != CPU_TYPE_X86_64 )
ec29ba20 725 return nullptr;
f80fe69f
A
726 return "x86_64";
727}
728
729template <>
730const char* Parser<arm>::fileKind(const uint8_t* fileContent)
731{
ec29ba20 732 const auto* header = reinterpret_cast<const macho_header<P>*>(fileContent);
f80fe69f 733 if ( header->magic() != MH_MAGIC )
ec29ba20 734 return nullptr;
f80fe69f 735 if ( header->cputype() != CPU_TYPE_ARM )
ec29ba20
A
736 return nullptr;
737 for (const auto* t = archInfoArray; t->archName != nullptr; ++t) {
f80fe69f
A
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
746template <>
747const char* Parser<arm64>::fileKind(const uint8_t* fileContent)
748{
ec29ba20 749 const auto* header = reinterpret_cast<const macho_header<P>*>(fileContent);
f80fe69f 750 if ( header->magic() != MH_MAGIC_64 )
ec29ba20 751 return nullptr;
f80fe69f 752 if ( header->cputype() != CPU_TYPE_ARM64 )
ec29ba20 753 return nullptr;
f80fe69f
A
754 return "arm64";
755}
756#endif
757
758//
759// used by linker is error messages to describe mismatched files
760//
761const 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
ec29ba20 777 return nullptr;
f80fe69f
A
778}
779
780
a645023d
A
781//
782// main function used by linker to instantiate ld::Files
783//
ec29ba20
A
784ld::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)
a645023d 787{
ec29ba20 788 bool subTypeMustMatch = opts.enforceDylibSubtypesMatch();
a645023d 789 switch ( opts.architecture() ) {
ebf6f434 790#if SUPPORT_ARCH_x86_64
a645023d 791 case CPU_TYPE_X86_64:
ec29ba20 792 if ( Parser<x86_64>::validFile(fileContent, bundleLoader, subTypeMustMatch, opts.subArchitecture()) )
afe874b1 793 return Parser<x86_64>::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib);
a645023d 794 break;
ebf6f434
A
795#endif
796#if SUPPORT_ARCH_i386
a645023d 797 case CPU_TYPE_I386:
ec29ba20 798 if ( Parser<x86>::validFile(fileContent, bundleLoader, subTypeMustMatch, opts.subArchitecture()) )
afe874b1 799 return Parser<x86>::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib);
a645023d 800 break;
ebf6f434
A
801#endif
802#if SUPPORT_ARCH_arm_any
a645023d 803 case CPU_TYPE_ARM:
ec29ba20 804 if ( Parser<arm>::validFile(fileContent, bundleLoader, subTypeMustMatch, opts.subArchitecture()) )
afe874b1 805 return Parser<arm>::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib);
a645023d 806 break;
f80fe69f
A
807#endif
808#if SUPPORT_ARCH_arm64
809 case CPU_TYPE_ARM64:
ec29ba20 810 if ( Parser<arm64>::validFile(fileContent, bundleLoader, subTypeMustMatch, opts.subArchitecture()) )
f80fe69f
A
811 return Parser<arm64>::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib);
812 break;
ebf6f434 813#endif
a645023d 814 }
ec29ba20 815 return nullptr;
a645023d
A
816}
817
818
819}; // namespace dylib
820}; // namespace mach_o