]> git.saurik.com Git - apple/ld64.git/blob - ld64-134.9/src/ld/parsers/macho_dylib_file.cpp
20b062bb716b9411ff5936806a7cdebb939e6335
[apple/ld64.git] / ld64-134.9 / 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 <algorithm>
36 #include <ext/hash_map>
37 #include <ext/hash_set>
38
39 #include "Architectures.hpp"
40 #include "MachOFileAbstraction.hpp"
41 #include "MachOTrie.hpp"
42 #include "macho_dylib_file.h"
43 #include "../code-sign-blobs/superblob.h"
44
45 namespace mach_o {
46 namespace dylib {
47
48
49 // forward reference
50 template <typename A> class File;
51
52
53 //
54 // An ExportAtom has no content. It exists so that the linker can track which imported
55 // symbols came from which dynamic libraries.
56 //
57 template <typename A>
58 class ExportAtom : public ld::Atom
59 {
60 public:
61 ExportAtom(const File<A>& f, const char* nm, bool weakDef,
62 bool tlv, typename A::P::uint_t address)
63 : ld::Atom(f._importProxySection, ld::Atom::definitionProxy,
64 (weakDef? ld::Atom::combineByName : ld::Atom::combineNever),
65 ld::Atom::scopeLinkageUnit,
66 (tlv ? ld::Atom::typeTLV : ld::Atom::typeUnclassified),
67 symbolTableNotIn, false, false, false, ld::Atom::Alignment(0)),
68 _file(f), _name(nm), _address(address) {}
69 // overrides of ld::Atom
70 virtual const ld::File* file() const { return &_file; }
71 virtual const char* name() const { return _name; }
72 virtual uint64_t size() const { return 0; }
73 virtual uint64_t objectAddress() const { return _address; }
74 virtual void copyRawContent(uint8_t buffer[]) const { }
75 virtual void setScope(Scope) { }
76
77 protected:
78 typedef typename A::P P;
79 typedef typename A::P::uint_t pint_t;
80
81 virtual ~ExportAtom() {}
82
83 const File<A>& _file;
84 const char* _name;
85 pint_t _address;
86 };
87
88
89
90 //
91 // An ImportAtom has no content. It exists so that when linking a main executable flat-namespace
92 // the imports of all flat dylibs are checked
93 //
94 template <typename A>
95 class ImportAtom : public ld::Atom
96 {
97 public:
98 ImportAtom(File<A>& f, std::vector<const char*>& imports);
99
100 // overrides of ld::Atom
101 virtual ld::File* file() const { return &_file; }
102 virtual const char* name() const { return "import-atom"; }
103 virtual uint64_t size() const { return 0; }
104 virtual uint64_t objectAddress() const { return 0; }
105 virtual void copyRawContent(uint8_t buffer[]) const { }
106 virtual void setScope(Scope) { }
107 virtual ld::Fixup::iterator fixupsBegin() const { return &_undefs[0]; }
108 virtual ld::Fixup::iterator fixupsEnd() const { return &_undefs[_undefs.size()]; }
109
110 protected:
111 typedef typename A::P P;
112
113 virtual ~ImportAtom() {}
114
115
116 File<A>& _file;
117 mutable std::vector<ld::Fixup> _undefs;
118 };
119
120 template <typename A>
121 ImportAtom<A>::ImportAtom(File<A>& f, std::vector<const char*>& imports)
122 : ld::Atom(f._flatDummySection, ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeTranslationUnit,
123 ld::Atom::typeUnclassified, symbolTableNotIn, false, false, false, ld::Atom::Alignment(0)), _file(f)
124 {
125 for(std::vector<const char*>::iterator it=imports.begin(); it != imports.end(); ++it) {
126 _undefs.push_back(ld::Fixup(0, ld::Fixup::k1of1, ld::Fixup::kindNone, false, strdup(*it)));
127 }
128 }
129
130
131
132 //
133 // The reader for a dylib extracts all exported symbols names from the memory-mapped
134 // dylib, builds a hash table, then unmaps the file. This is an important memory
135 // savings for large dylibs.
136 //
137 template <typename A>
138 class File : public ld::dylib::File
139 {
140 public:
141 static bool validFile(const uint8_t* fileContent, bool executableOrDylib);
142 File(const uint8_t* fileContent, uint64_t fileLength, const char* path,
143 time_t mTime, ld::File::Ordinal ordinal, bool linkingFlatNamespace,
144 bool linkingMainExecutable, bool hoistImplicitPublicDylibs,
145 ld::MacVersionMin macMin, ld::IOSVersionMin iPhoneMin, bool addVers,
146 bool logAllFiles, const char* installPath, bool indirectDylib);
147 virtual ~File() {}
148
149 // overrides of ld::File
150 virtual bool forEachAtom(ld::File::AtomHandler&) const;
151 virtual bool justInTimeforEachAtom(const char* name, ld::File::AtomHandler&) const;
152 virtual ld::File::ObjcConstraint objCConstraint() const { return _objcContraint; }
153
154 // overrides of ld::dylib::File
155 virtual void processIndirectLibraries(ld::dylib::File::DylibHandler*, bool);
156 virtual bool providedExportAtom() const { return _providedAtom; }
157 virtual const char* parentUmbrella() const { return _parentUmbrella; }
158 virtual const std::vector<const char*>* allowableClients() const { return _allowableClients.size() != 0 ? &_allowableClients : NULL; }
159 virtual bool hasWeakExternals() const { return _hasWeakExports; }
160 virtual bool deadStrippable() const { return _deadStrippable; }
161 virtual bool hasPublicInstallName() const{ return _hasPublicInstallName; }
162 virtual bool hasWeakDefinition(const char* name) const;
163 virtual bool allSymbolsAreWeakImported() const;
164 virtual const void* codeSignatureDR() const { return _codeSignatureDR; }
165
166
167 protected:
168
169 struct ReExportChain { ReExportChain* prev; File<A>* file; };
170
171 void assertNoReExportCycles(ReExportChain*);
172
173 private:
174 typedef typename A::P P;
175 typedef typename A::P::E E;
176 typedef typename A::P::uint_t pint_t;
177
178 friend class ExportAtom<A>;
179 friend class ImportAtom<A>;
180
181 class CStringEquals
182 {
183 public:
184 bool operator()(const char* left, const char* right) const { return (strcmp(left, right) == 0); }
185 };
186 struct AtomAndWeak { ld::Atom* atom; bool weakDef; bool tlv; pint_t address; };
187 typedef __gnu_cxx::hash_map<const char*, AtomAndWeak, __gnu_cxx::hash<const char*>, CStringEquals> NameToAtomMap;
188 typedef __gnu_cxx::hash_set<const char*, __gnu_cxx::hash<const char*>, CStringEquals> NameSet;
189
190 struct Dependent { const char* path; File<A>* dylib; bool reExport; };
191
192 bool containsOrReExports(const char* name, bool* weakDef, bool* tlv, pint_t* defAddress) const;
193 bool isPublicLocation(const char* pth);
194 void addSymbol(const char* name, bool weak, bool tlv, pint_t address);
195 void addDyldFastStub();
196 void buildExportHashTableFromExportInfo(const macho_dyld_info_command<P>* dyldInfo,
197 const uint8_t* fileContent);
198 void buildExportHashTableFromSymbolTable(const macho_dysymtab_command<P>* dynamicInfo,
199 const macho_nlist<P>* symbolTable, const char* strings,
200 const uint8_t* fileContent);
201 static const char* objCInfoSegmentName();
202 static const char* objCInfoSectionName();
203
204 const ld::MacVersionMin _macVersionMin;
205 const ld::IOSVersionMin _iOSVersionMin;
206 const bool _addVersionLoadCommand;
207 bool _linkingFlat;
208 bool _implicitlyLinkPublicDylibs;
209 ld::File::ObjcConstraint _objcContraint;
210 ld::Section _importProxySection;
211 ld::Section _flatDummySection;
212 std::vector<Dependent> _dependentDylibs;
213 std::vector<const char*> _allowableClients;
214 mutable NameToAtomMap _atoms;
215 NameSet _ignoreExports;
216 const char* _parentUmbrella;
217 ImportAtom<A>* _importAtom;
218 const void* _codeSignatureDR;
219 bool _noRexports;
220 bool _hasWeakExports;
221 bool _deadStrippable;
222 bool _hasPublicInstallName;
223 mutable bool _providedAtom;
224 bool _explictReExportFound;
225
226 static bool _s_logHashtable;
227 };
228
229 template <typename A>
230 bool File<A>::_s_logHashtable = false;
231
232 template <> const char* File<x86_64>::objCInfoSegmentName() { return "__DATA"; }
233 template <> const char* File<arm>::objCInfoSegmentName() { return "__DATA"; }
234 template <typename A> const char* File<A>::objCInfoSegmentName() { return "__OBJC"; }
235
236 template <> const char* File<x86_64>::objCInfoSectionName() { return "__objc_imageinfo"; }
237 template <> const char* File<arm>::objCInfoSectionName() { return "__objc_imageinfo"; }
238 template <typename A> const char* File<A>::objCInfoSectionName() { return "__image_info"; }
239
240 template <typename A>
241 File<A>::File(const uint8_t* fileContent, uint64_t fileLength, const char* pth, time_t mTime, ld::File::Ordinal ord,
242 bool linkingFlatNamespace, bool linkingMainExecutable, bool hoistImplicitPublicDylibs,
243 ld::MacVersionMin macMin, ld::IOSVersionMin iOSMin, bool addVers,
244 bool logAllFiles, const char* targetInstallPath, bool indirectDylib)
245 : ld::dylib::File(strdup(pth), mTime, ord),
246 _macVersionMin(macMin), _iOSVersionMin(iOSMin), _addVersionLoadCommand(addVers),
247 _linkingFlat(linkingFlatNamespace), _implicitlyLinkPublicDylibs(hoistImplicitPublicDylibs),
248 _objcContraint(ld::File::objcConstraintNone),
249 _importProxySection("__TEXT", "__import", ld::Section::typeImportProxies, true),
250 _flatDummySection("__LINKEDIT", "__flat_dummy", ld::Section::typeLinkEdit, true),
251 _parentUmbrella(NULL), _importAtom(NULL), _codeSignatureDR(NULL),
252 _noRexports(false), _hasWeakExports(false),
253 _deadStrippable(false), _hasPublicInstallName(false),
254 _providedAtom(false), _explictReExportFound(false)
255 {
256 const macho_header<P>* header = (const macho_header<P>*)fileContent;
257 const uint32_t cmd_count = header->ncmds();
258 const macho_load_command<P>* const cmds = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>));
259 const macho_load_command<P>* const cmdsEnd = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>) + header->sizeofcmds());
260
261 // write out path for -t option
262 if ( logAllFiles )
263 printf("%s\n", pth);
264
265 // a "blank" stub has zero load commands
266 if ( (header->filetype() == MH_DYLIB_STUB) && (cmd_count == 0) ) {
267 // no further processing needed
268 munmap((caddr_t)fileContent, fileLength);
269 return;
270 }
271
272
273 // optimize the case where we know there is no reason to look at indirect dylibs
274 _noRexports = (header->flags() & MH_NO_REEXPORTED_DYLIBS)
275 || (header->filetype() == MH_BUNDLE)
276 || (header->filetype() == MH_EXECUTE); // bundles and exectuables can be used via -bundle_loader
277 _hasWeakExports = (header->flags() & MH_WEAK_DEFINES);
278 _deadStrippable = (header->flags() & MH_DEAD_STRIPPABLE_DYLIB);
279
280 // pass 1: get pointers, and see if this dylib uses compressed LINKEDIT format
281 const macho_dysymtab_command<P>* dynamicInfo = NULL;
282 const macho_dyld_info_command<P>* dyldInfo = NULL;
283 const macho_linkedit_data_command<P>* codeSignature = NULL;
284 const macho_nlist<P>* symbolTable = NULL;
285 const char* strings = NULL;
286 bool compressedLinkEdit = false;
287 uint32_t dependentLibCount = 0;
288 const macho_load_command<P>* cmd = cmds;
289 for (uint32_t i = 0; i < cmd_count; ++i) {
290 macho_dylib_command<P>* dylibID;
291 const macho_symtab_command<P>* symtab;
292 switch (cmd->cmd()) {
293 case LC_SYMTAB:
294 symtab = (macho_symtab_command<P>*)cmd;
295 symbolTable = (const macho_nlist<P>*)((char*)header + symtab->symoff());
296 strings = (char*)header + symtab->stroff();
297 if ( (symtab->stroff() + symtab->strsize()) > fileLength )
298 throwf("mach-o string pool extends beyond end of file in %s", pth);
299 break;
300 case LC_DYSYMTAB:
301 dynamicInfo = (macho_dysymtab_command<P>*)cmd;
302 break;
303 case LC_DYLD_INFO:
304 case LC_DYLD_INFO_ONLY:
305 dyldInfo = (macho_dyld_info_command<P>*)cmd;
306 compressedLinkEdit = true;
307 break;
308 case LC_ID_DYLIB:
309 dylibID = (macho_dylib_command<P>*)cmd;
310 _dylibInstallPath = strdup(dylibID->name());
311 _dylibTimeStamp = dylibID->timestamp();
312 _dylibCurrentVersion = dylibID->current_version();
313 _dylibCompatibilityVersion = dylibID->compatibility_version();
314 _hasPublicInstallName = isPublicLocation(_dylibInstallPath);
315 break;
316 case LC_LOAD_DYLIB:
317 case LC_LOAD_WEAK_DYLIB:
318 ++dependentLibCount;
319 break;
320 case LC_REEXPORT_DYLIB:
321 _explictReExportFound = true;
322 ++dependentLibCount;
323 break;
324 case LC_SUB_FRAMEWORK:
325 _parentUmbrella = strdup(((macho_sub_framework_command<P>*)cmd)->umbrella());
326 break;
327 case LC_SUB_CLIENT:
328 _allowableClients.push_back(strdup(((macho_sub_client_command<P>*)cmd)->client()));
329 break;
330 case LC_VERSION_MIN_MACOSX:
331 if ( _addVersionLoadCommand && !indirectDylib && (_iOSVersionMin != ld::iOSVersionUnset) )
332 warning("building for iOS, but linking against dylib built for MacOSX: %s", pth);
333 break;
334 case LC_VERSION_MIN_IPHONEOS:
335 if ( _addVersionLoadCommand && !indirectDylib && (_macVersionMin != ld::macVersionUnset) )
336 warning("building for MacOSX, but linking against dylib built for iOS: %s", pth);
337 break;
338 case LC_CODE_SIGNATURE:
339 codeSignature = (macho_linkedit_data_command<P>* )cmd;
340 break;
341 case macho_segment_command<P>::CMD:
342 // check for Objective-C info
343 if ( strcmp(((macho_segment_command<P>*)cmd)->segname(), objCInfoSegmentName()) == 0 ) {
344 const macho_segment_command<P>* segment = (macho_segment_command<P>*)cmd;
345 const macho_section<P>* const sectionsStart = (macho_section<P>*)((char*)segment + sizeof(macho_segment_command<P>));
346 const macho_section<P>* const sectionsEnd = &sectionsStart[segment->nsects()];
347 for (const macho_section<P>* sect=sectionsStart; sect < sectionsEnd; ++sect) {
348 if ( strncmp(sect->sectname(), objCInfoSectionName(), strlen(objCInfoSectionName())) == 0 ) {
349 // struct objc_image_info {
350 // uint32_t version; // initially 0
351 // uint32_t flags;
352 // };
353 // #define OBJC_IMAGE_SUPPORTS_GC 2
354 // #define OBJC_IMAGE_GC_ONLY 4
355 //
356 const uint32_t* contents = (uint32_t*)(&fileContent[sect->offset()]);
357 if ( (sect->size() >= 8) && (contents[0] == 0) ) {
358 uint32_t flags = E::get32(contents[1]);
359 if ( (flags & 4) == 4 )
360 _objcContraint = ld::File::objcConstraintGC;
361 else if ( (flags & 2) == 2 )
362 _objcContraint = ld::File::objcConstraintRetainReleaseOrGC;
363 else
364 _objcContraint = ld::File::objcConstraintRetainRelease;
365 }
366 else if ( sect->size() > 0 ) {
367 warning("can't parse %s/%s section in %s", objCInfoSegmentName(), objCInfoSectionName(), this->path());
368 }
369 }
370 }
371 }
372 }
373 cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
374 if ( cmd > cmdsEnd )
375 throwf("malformed dylb, load command #%d is outside size of load commands in %s", i, pth);
376 }
377
378 // figure out if we need to examine dependent dylibs
379 // with compressed LINKEDIT format, MH_NO_REEXPORTED_DYLIBS can be trusted
380 bool processDependentLibraries = true;
381 if ( compressedLinkEdit && _noRexports && !linkingFlatNamespace)
382 processDependentLibraries = false;
383
384 if ( processDependentLibraries ) {
385 // pass 2 builds list of all dependent libraries
386 _dependentDylibs.reserve(dependentLibCount);
387 cmd = cmds;
388 unsigned int reExportDylibCount = 0;
389 for (uint32_t i = 0; i < cmd_count; ++i) {
390 switch (cmd->cmd()) {
391 case LC_LOAD_DYLIB:
392 case LC_LOAD_WEAK_DYLIB:
393 // with new linkedit format only care about LC_REEXPORT_DYLIB
394 if ( compressedLinkEdit && !linkingFlatNamespace )
395 break;
396 case LC_REEXPORT_DYLIB:
397 ++reExportDylibCount;
398 Dependent entry;
399 entry.path = strdup(((macho_dylib_command<P>*)cmd)->name());
400 entry.dylib = NULL;
401 entry.reExport = (cmd->cmd() == LC_REEXPORT_DYLIB);
402 if ( (targetInstallPath == NULL) || (strcmp(targetInstallPath, entry.path) != 0) )
403 _dependentDylibs.push_back(entry);
404 break;
405 }
406 cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
407 }
408 // verify MH_NO_REEXPORTED_DYLIBS bit was correct
409 if ( compressedLinkEdit && !linkingFlatNamespace ) {
410 assert(reExportDylibCount != 0);
411 }
412 // pass 3 add re-export info
413 cmd = cmds;
414 for (uint32_t i = 0; i < cmd_count; ++i) {
415 const char* frameworkLeafName;
416 const char* dylibBaseName;
417 switch (cmd->cmd()) {
418 case LC_SUB_UMBRELLA:
419 frameworkLeafName = ((macho_sub_umbrella_command<P>*)cmd)->sub_umbrella();
420 for (typename std::vector<Dependent>::iterator it = _dependentDylibs.begin(); it != _dependentDylibs.end(); ++it) {
421 const char* dylibName = it->path;
422 const char* lastSlash = strrchr(dylibName, '/');
423 if ( (lastSlash != NULL) && (strcmp(&lastSlash[1], frameworkLeafName) == 0) )
424 it->reExport = true;
425 }
426 break;
427 case LC_SUB_LIBRARY:
428 dylibBaseName = ((macho_sub_library_command<P>*)cmd)->sub_library();
429 for (typename std::vector<Dependent>::iterator it = _dependentDylibs.begin(); it != _dependentDylibs.end(); ++it) {
430 const char* dylibName = it->path;
431 const char* lastSlash = strrchr(dylibName, '/');
432 const char* leafStart = &lastSlash[1];
433 if ( lastSlash == NULL )
434 leafStart = dylibName;
435 const char* firstDot = strchr(leafStart, '.');
436 int len = strlen(leafStart);
437 if ( firstDot != NULL )
438 len = firstDot - leafStart;
439 if ( strncmp(leafStart, dylibBaseName, len) == 0 )
440 it->reExport = true;
441 }
442 break;
443 }
444 cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
445 }
446 }
447
448 // validate minimal load commands
449 if ( (_dylibInstallPath == NULL) && ((header->filetype() == MH_DYLIB) || (header->filetype() == MH_DYLIB_STUB)) )
450 throwf("dylib %s missing LC_ID_DYLIB load command", pth);
451 if ( dyldInfo == NULL ) {
452 if ( symbolTable == NULL )
453 throw "binary missing LC_SYMTAB load command";
454 if ( dynamicInfo == NULL )
455 throw "binary missing LC_DYSYMTAB load command";
456 }
457
458 // if linking flat and this is a flat dylib, create one atom that references all imported symbols
459 if ( linkingFlatNamespace && linkingMainExecutable && ((header->flags() & MH_TWOLEVEL) == 0) ) {
460 std::vector<const char*> importNames;
461 importNames.reserve(dynamicInfo->nundefsym());
462 const macho_nlist<P>* start = &symbolTable[dynamicInfo->iundefsym()];
463 const macho_nlist<P>* end = &start[dynamicInfo->nundefsym()];
464 for (const macho_nlist<P>* sym=start; sym < end; ++sym) {
465 importNames.push_back(&strings[sym->n_strx()]);
466 }
467 _importAtom = new ImportAtom<A>(*this, importNames);
468 }
469
470 // if the dylib is code signed, look for its Designated Requirement
471 if ( codeSignature != NULL ) {
472 const Security::BlobCore* overallSignature = (Security::BlobCore*)((char*)header + codeSignature->dataoff());
473 typedef Security::SuperBlob<Security::kSecCodeMagicEmbeddedSignature> EmbeddedSignatureBlob;
474 typedef Security::SuperBlob<Security::kSecCodeMagicRequirementSet> InternalRequirementsBlob;
475 const EmbeddedSignatureBlob* signature = EmbeddedSignatureBlob::specific(overallSignature);
476 if ( signature->validateBlob(codeSignature->datasize()) ) {
477 const InternalRequirementsBlob* ireq = signature->find<InternalRequirementsBlob>(Security::cdRequirementsSlot);
478 if ( (ireq != NULL) && ireq->validateBlob() ) {
479 const Security::BlobCore* dr = ireq->find(Security::kSecDesignatedRequirementType);
480 if ( (dr != NULL) && dr->validateBlob(Security::kSecCodeMagicRequirement) ) {
481 // <rdar://problem/10968461> make copy because mapped file is about to be unmapped
482 _codeSignatureDR = ::malloc(dr->length());
483 ::memcpy((void*)_codeSignatureDR, dr, dr->length());
484 }
485 }
486 }
487 }
488
489 // build hash table
490 if ( dyldInfo != NULL )
491 buildExportHashTableFromExportInfo(dyldInfo, fileContent);
492 else
493 buildExportHashTableFromSymbolTable(dynamicInfo, symbolTable, strings, fileContent);
494
495 // unmap file
496 munmap((caddr_t)fileContent, fileLength);
497 }
498
499
500 template <typename A>
501 void File<A>::buildExportHashTableFromSymbolTable(const macho_dysymtab_command<P>* dynamicInfo,
502 const macho_nlist<P>* symbolTable, const char* strings,
503 const uint8_t* fileContent)
504 {
505 if ( dynamicInfo->tocoff() == 0 ) {
506 if ( _s_logHashtable ) fprintf(stderr, "ld: building hashtable of %u toc entries for %s\n", dynamicInfo->nextdefsym(), this->path());
507 const macho_nlist<P>* start = &symbolTable[dynamicInfo->iextdefsym()];
508 const macho_nlist<P>* end = &start[dynamicInfo->nextdefsym()];
509 _atoms.resize(dynamicInfo->nextdefsym()); // set initial bucket count
510 for (const macho_nlist<P>* sym=start; sym < end; ++sym) {
511 this->addSymbol(&strings[sym->n_strx()], (sym->n_desc() & N_WEAK_DEF) != 0, false, sym->n_value());
512 }
513 }
514 else {
515 int32_t count = dynamicInfo->ntoc();
516 _atoms.resize(count); // set initial bucket count
517 if ( _s_logHashtable ) fprintf(stderr, "ld: building hashtable of %u entries for %s\n", count, this->path());
518 const struct dylib_table_of_contents* toc = (dylib_table_of_contents*)(fileContent + dynamicInfo->tocoff());
519 for (int32_t i = 0; i < count; ++i) {
520 const uint32_t index = E::get32(toc[i].symbol_index);
521 const macho_nlist<P>* sym = &symbolTable[index];
522 this->addSymbol(&strings[sym->n_strx()], (sym->n_desc() & N_WEAK_DEF) != 0, false, sym->n_value());
523 }
524 }
525
526 // special case old libSystem
527 if ( (_dylibInstallPath != NULL) && (strcmp(_dylibInstallPath, "/usr/lib/libSystem.B.dylib") == 0) )
528 addDyldFastStub();
529 }
530
531
532 template <typename A>
533 void File<A>::buildExportHashTableFromExportInfo(const macho_dyld_info_command<P>* dyldInfo,
534 const uint8_t* fileContent)
535 {
536 if ( _s_logHashtable ) fprintf(stderr, "ld: building hashtable from export info in %s\n", this->path());
537 if ( dyldInfo->export_size() > 0 ) {
538 const uint8_t* start = fileContent + dyldInfo->export_off();
539 const uint8_t* end = &start[dyldInfo->export_size()];
540 std::vector<mach_o::trie::Entry> list;
541 parseTrie(start, end, list);
542 for (std::vector<mach_o::trie::Entry>::iterator it=list.begin(); it != list.end(); ++it)
543 this->addSymbol(it->name,
544 it->flags & EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION,
545 (it->flags & EXPORT_SYMBOL_FLAGS_KIND_MASK) == EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL,
546 it->address);
547 }
548 }
549
550
551 template <>
552 void File<x86_64>::addDyldFastStub()
553 {
554 addSymbol("dyld_stub_binder", false, false, 0);
555 }
556
557 template <>
558 void File<x86>::addDyldFastStub()
559 {
560 addSymbol("dyld_stub_binder", false, false, 0);
561 }
562
563 template <typename A>
564 void File<A>::addDyldFastStub()
565 {
566 // do nothing
567 }
568
569 template <typename A>
570 void File<A>::addSymbol(const char* name, bool weakDef, bool tlv, pint_t address)
571 {
572 if ( weakDef ) {
573 assert(_hasWeakExports);
574 }
575 //fprintf(stderr, "addSymbol() %s\n", name);
576 // symbols that start with $ld$ are meta-data to the static linker
577 // <rdar://problem/5182537> need way for ld and dyld to see different exported symbols in a dylib
578 if ( strncmp(name, "$ld$", 4) == 0 ) {
579 // $ld$ <action> $ <condition> $ <symbol-name>
580 const char* symAction = &name[4];
581 const char* symCond = strchr(symAction, '$');
582 if ( symCond != NULL ) {
583 char curOSVers[16];
584 if ( _macVersionMin != ld::macVersionUnset ) {
585 sprintf(curOSVers, "$os%d.%d$", (_macVersionMin >> 16), ((_macVersionMin >> 8) & 0xFF));
586 }
587 else if ( _iOSVersionMin != ld::iOSVersionUnset ) {
588 sprintf(curOSVers, "$os%d.%d$", (_iOSVersionMin >> 16), ((_iOSVersionMin >> 8) & 0xFF));
589 }
590 else {
591 assert(0 && "targeting neither macosx nor iphoneos");
592 }
593 if ( strncmp(symCond, curOSVers, strlen(curOSVers)) == 0 ) {
594 const char* symName = strchr(&symCond[1], '$');
595 if ( symName != NULL ) {
596 ++symName;
597 if ( strncmp(symAction, "hide$", 5) == 0 ) {
598 if ( _s_logHashtable ) fprintf(stderr, " adding %s to ignore set for %s\n", symName, this->path());
599 _ignoreExports.insert(strdup(symName));
600 return;
601 }
602 else if ( strncmp(symAction, "add$", 4) == 0 ) {
603 this->addSymbol(symName, weakDef, false, 0);
604 return;
605 }
606 else if ( strncmp(symAction, "install_name$", 13) == 0 ) {
607 _dylibInstallPath = symName;
608 return;
609 }
610 else {
611 warning("bad symbol action: %s in dylib %s", name, this->path());
612 }
613 }
614 }
615 }
616 else {
617 warning("bad symbol condition: %s in dylib %s", name, this->path());
618 }
619 }
620
621 // add symbol as possible export if we are not supposed to ignore it
622 if ( _ignoreExports.count(name) == 0 ) {
623 AtomAndWeak bucket;
624 bucket.atom = NULL;
625 bucket.weakDef = weakDef;
626 bucket.tlv = tlv;
627 bucket.address = address;
628 if ( _s_logHashtable ) fprintf(stderr, " adding %s to hash table for %s\n", name, this->path());
629 _atoms[strdup(name)] = bucket;
630 }
631 }
632
633
634 template <typename A>
635 bool File<A>::forEachAtom(ld::File::AtomHandler& handler) const
636 {
637 handler.doFile(*this);
638 // if doing flatnamespace and need all this dylib's imports resolve
639 // add atom which references alls undefines in this dylib
640 if ( _importAtom != NULL ) {
641 handler.doAtom(*_importAtom);
642 return true;
643 }
644 return false;
645 }
646
647 template <typename A>
648 bool File<A>::hasWeakDefinition(const char* name) const
649 {
650 // if supposed to ignore this export, then pretend I don't have it
651 if ( _ignoreExports.count(name) != 0 )
652 return false;
653
654 typename NameToAtomMap::const_iterator pos = _atoms.find(name);
655 if ( pos != _atoms.end() ) {
656 return pos->second.weakDef;
657 }
658 else {
659 // look in children that I re-export
660 for (typename std::vector<Dependent>::const_iterator it = _dependentDylibs.begin(); it != _dependentDylibs.end(); ++it) {
661 if ( it->reExport ) {
662 //fprintf(stderr, "getJustInTimeAtomsFor: %s NOT found in %s, looking in child %s\n", name, this->path(), (*it)->getInstallPath());
663 typename NameToAtomMap::iterator cpos = it->dylib->_atoms.find(name);
664 if ( cpos != it->dylib->_atoms.end() )
665 return cpos->second.weakDef;
666 }
667 }
668 }
669 return false;
670 }
671
672
673 // <rdar://problem/5529626> If only weak_import symbols are used, linker should use LD_LOAD_WEAK_DYLIB
674 template <typename A>
675 bool File<A>::allSymbolsAreWeakImported() const
676 {
677 bool foundNonWeakImport = false;
678 bool foundWeakImport = false;
679 //fprintf(stderr, "%s:\n", this->path());
680 for (typename NameToAtomMap::const_iterator it = _atoms.begin(); it != _atoms.end(); ++it) {
681 const ld::Atom* atom = it->second.atom;
682 if ( atom != NULL ) {
683 if ( atom->weakImported() )
684 foundWeakImport = true;
685 else
686 foundNonWeakImport = true;
687 //fprintf(stderr, " weak_import=%d, name=%s\n", atom->weakImported(), it->first);
688 }
689 }
690
691 // don't automatically weak link dylib with no imports
692 // so at least one weak import symbol and no non-weak-imported symbols must be found
693 return foundWeakImport && !foundNonWeakImport;
694 }
695
696
697 template <typename A>
698 bool File<A>::containsOrReExports(const char* name, bool* weakDef, bool* tlv, pint_t* defAddress) const
699 {
700 if ( _ignoreExports.count(name) != 0 )
701 return false;
702
703 // check myself
704 typename NameToAtomMap::iterator pos = _atoms.find(name);
705 if ( pos != _atoms.end() ) {
706 *weakDef = pos->second.weakDef;
707 *tlv = pos->second.tlv;
708 *defAddress = pos->second.address;
709 return true;
710 }
711
712 // check dylibs I re-export
713 for (typename std::vector<Dependent>::const_iterator it = _dependentDylibs.begin(); it != _dependentDylibs.end(); ++it) {
714 if ( it->reExport && !it->dylib->implicitlyLinked() ) {
715 if ( it->dylib->containsOrReExports(name, weakDef, tlv, defAddress) )
716 return true;
717 }
718 }
719
720 return false;
721 }
722
723
724 template <typename A>
725 bool File<A>::justInTimeforEachAtom(const char* name, ld::File::AtomHandler& handler) const
726 {
727 // if supposed to ignore this export, then pretend I don't have it
728 if ( _ignoreExports.count(name) != 0 )
729 return false;
730
731
732 AtomAndWeak bucket;
733 if ( this->containsOrReExports(name, &bucket.weakDef, &bucket.tlv, &bucket.address) ) {
734 bucket.atom = new ExportAtom<A>(*this, name, bucket.weakDef, bucket.tlv, bucket.address);
735 _atoms[name] = bucket;
736 _providedAtom = true;
737 if ( _s_logHashtable ) fprintf(stderr, "getJustInTimeAtomsFor: %s found in %s\n", name, this->path());
738 // call handler with new export atom
739 handler.doAtom(*bucket.atom);
740 return true;
741 }
742
743 return false;
744 }
745
746
747
748 template <typename A>
749 bool File<A>::isPublicLocation(const char* pth)
750 {
751 // -no_implicit_dylibs disables this optimization
752 if ( ! _implicitlyLinkPublicDylibs )
753 return false;
754
755 // /usr/lib is a public location
756 if ( (strncmp(pth, "/usr/lib/", 9) == 0) && (strchr(&pth[9], '/') == NULL) )
757 return true;
758
759 // /System/Library/Frameworks/ is a public location
760 if ( strncmp(pth, "/System/Library/Frameworks/", 27) == 0 ) {
761 const char* frameworkDot = strchr(&pth[27], '.');
762 // but only top level framework
763 // /System/Library/Frameworks/Foo.framework/Versions/A/Foo ==> true
764 // /System/Library/Frameworks/Foo.framework/Resources/libBar.dylib ==> false
765 // /System/Library/Frameworks/Foo.framework/Frameworks/Bar.framework/Bar ==> false
766 // /System/Library/Frameworks/Foo.framework/Frameworks/Xfoo.framework/XFoo ==> false
767 if ( frameworkDot != NULL ) {
768 int frameworkNameLen = frameworkDot - &pth[27];
769 if ( strncmp(&pth[strlen(pth)-frameworkNameLen-1], &pth[26], frameworkNameLen+1) == 0 )
770 return true;
771 }
772 }
773
774 return false;
775 }
776
777 template <typename A>
778 void File<A>::processIndirectLibraries(ld::dylib::File::DylibHandler* handler, bool addImplicitDylibs)
779 {
780 const static bool log = false;
781 if ( log ) fprintf(stderr, "processIndirectLibraries(%s)\n", this->installPath());
782 if ( _linkingFlat ) {
783 for (typename std::vector<Dependent>::iterator it = _dependentDylibs.begin(); it != _dependentDylibs.end(); it++) {
784 it->dylib = (File<A>*)handler->findDylib(it->path, this->path());
785 }
786 }
787 else if ( _noRexports ) {
788 // MH_NO_REEXPORTED_DYLIBS bit set, then nothing to do
789 }
790 else {
791 // two-level, might have re-exports
792 for (typename std::vector<Dependent>::iterator it = _dependentDylibs.begin(); it != _dependentDylibs.end(); it++) {
793 if ( it->reExport ) {
794 if ( log ) fprintf(stderr, "processIndirectLibraries() parent=%s, child=%s\n", this->installPath(), it->path);
795 // a LC_REEXPORT_DYLIB, LC_SUB_UMBRELLA or LC_SUB_LIBRARY says we re-export this child
796 it->dylib = (File<A>*)handler->findDylib(it->path, this->path());
797 if ( it->dylib->hasPublicInstallName() ) {
798 // promote this child to be automatically added as a direct dependent if this already is
799 if ( (this->explicitlyLinked() || this->implicitlyLinked()) && (strcmp(it->path,it->dylib->installPath()) == 0) ) {
800 if ( log ) fprintf(stderr, "processIndirectLibraries() implicitly linking %s\n", it->dylib->installPath());
801 it->dylib->setImplicitlyLinked();
802 }
803 else if ( it->dylib->explicitlyLinked() || it->dylib->implicitlyLinked() ) {
804 if ( log ) fprintf(stderr, "processIndirectLibraries() parent is not directly linked, but child is, so no need to re-export child\n");
805 }
806 else {
807 if ( log ) fprintf(stderr, "processIndirectLibraries() parent is not directly linked, so parent=%s will re-export child=%s\n", this->installPath(), it->path);
808 }
809 }
810 else {
811 // add all child's symbols to me
812 if ( log ) fprintf(stderr, "processIndirectLibraries() child is not public, so parent=%s will re-export child=%s\n", this->installPath(), it->path);
813 }
814 }
815 else if ( !_explictReExportFound ) {
816 // see if child contains LC_SUB_FRAMEWORK with my name
817 it->dylib = (File<A>*)handler->findDylib(it->path, this->path());
818 const char* parentUmbrellaName = it->dylib->parentUmbrella();
819 if ( parentUmbrellaName != NULL ) {
820 const char* parentName = this->path();
821 const char* lastSlash = strrchr(parentName, '/');
822 if ( (lastSlash != NULL) && (strcmp(&lastSlash[1], parentUmbrellaName) == 0) ) {
823 // add all child's symbols to me
824 it->reExport = true;
825 if ( log ) fprintf(stderr, "processIndirectLibraries() umbrella=%s will re-export child=%s\n", this->installPath(), it->path);
826 }
827 }
828 }
829 }
830 }
831
832 // check for re-export cycles
833 ReExportChain chain;
834 chain.prev = NULL;
835 chain.file = this;
836 this->assertNoReExportCycles(&chain);
837 }
838
839 template <typename A>
840 void File<A>::assertNoReExportCycles(ReExportChain* prev)
841 {
842 // recursively check my re-exported dylibs
843 ReExportChain chain;
844 chain.prev = prev;
845 chain.file = this;
846 for (typename std::vector<Dependent>::iterator it = _dependentDylibs.begin(); it != _dependentDylibs.end(); it++) {
847 if ( it->reExport ) {
848 ld::File* child = it->dylib;
849 // check child is not already in chain
850 for (ReExportChain* p = prev; p != NULL; p = p->prev) {
851 if ( p->file == child ) {
852 throwf("cycle in dylib re-exports with %s and %s", child->path(), this->path());
853 }
854 }
855 if ( it->dylib != NULL )
856 it->dylib->assertNoReExportCycles(&chain);
857 }
858 }
859 }
860
861
862 template <typename A>
863 class Parser
864 {
865 public:
866 typedef typename A::P P;
867
868 static bool validFile(const uint8_t* fileContent, bool executableOrDyliborBundle);
869 static ld::dylib::File* parse(const uint8_t* fileContent, uint64_t fileLength,
870 const char* path, time_t mTime,
871 ld::File::Ordinal ordinal, const Options& opts, bool indirectDylib) {
872 return new File<A>(fileContent, fileLength, path, mTime,
873 ordinal, opts.flatNamespace(),
874 opts.linkingMainExecutable(),
875 opts.implicitlyLinkIndirectPublicDylibs(),
876 opts.macosxVersionMin(),
877 opts.iOSVersionMin(),
878 opts.addVersionLoadCommand(),
879 opts.logAllFiles(),
880 opts.installPath(),
881 indirectDylib);
882 }
883
884 };
885
886
887
888 template <>
889 bool Parser<x86>::validFile(const uint8_t* fileContent, bool executableOrDyliborBundle)
890 {
891 const macho_header<P>* header = (const macho_header<P>*)fileContent;
892 if ( header->magic() != MH_MAGIC )
893 return false;
894 if ( header->cputype() != CPU_TYPE_I386 )
895 return false;
896 switch ( header->filetype() ) {
897 case MH_DYLIB:
898 case MH_DYLIB_STUB:
899 return true;
900 case MH_BUNDLE:
901 if ( executableOrDyliborBundle )
902 return true;
903 else
904 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
905 case MH_EXECUTE:
906 if ( executableOrDyliborBundle )
907 return true;
908 else
909 throw "can't link with a main executable";
910 default:
911 return false;
912 }
913 }
914
915 template <>
916 bool Parser<x86_64>::validFile(const uint8_t* fileContent, bool executableOrDyliborBundle)
917 {
918 const macho_header<P>* header = (const macho_header<P>*)fileContent;
919 if ( header->magic() != MH_MAGIC_64 )
920 return false;
921 if ( header->cputype() != CPU_TYPE_X86_64 )
922 return false;
923 switch ( header->filetype() ) {
924 case MH_DYLIB:
925 case MH_DYLIB_STUB:
926 return true;
927 case MH_BUNDLE:
928 if ( executableOrDyliborBundle )
929 return true;
930 else
931 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
932 case MH_EXECUTE:
933 if ( executableOrDyliborBundle )
934 return true;
935 else
936 throw "can't link with a main executable";
937 default:
938 return false;
939 }
940 }
941
942 template <>
943 bool Parser<arm>::validFile(const uint8_t* fileContent, bool executableOrDyliborBundle)
944 {
945 const macho_header<P>* header = (const macho_header<P>*)fileContent;
946 if ( header->magic() != MH_MAGIC )
947 return false;
948 if ( header->cputype() != CPU_TYPE_ARM )
949 return false;
950 switch ( header->filetype() ) {
951 case MH_DYLIB:
952 case MH_DYLIB_STUB:
953 return true;
954 case MH_BUNDLE:
955 if ( executableOrDyliborBundle )
956 return true;
957 else
958 throw "can't link with bundle (MH_BUNDLE) only dylibs (MH_DYLIB)";
959 case MH_EXECUTE:
960 if ( executableOrDyliborBundle )
961 return true;
962 else
963 throw "can't link with a main executable";
964 default:
965 return false;
966 }
967 }
968
969
970
971 //
972 // main function used by linker to instantiate ld::Files
973 //
974 ld::dylib::File* parse(const uint8_t* fileContent, uint64_t fileLength,
975 const char* path, time_t modTime, const Options& opts, ld::File::Ordinal ordinal,
976 bool bundleLoader, bool indirectDylib)
977 {
978 switch ( opts.architecture() ) {
979 #if SUPPORT_ARCH_x86_64
980 case CPU_TYPE_X86_64:
981 if ( Parser<x86_64>::validFile(fileContent, bundleLoader) )
982 return Parser<x86_64>::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib);
983 break;
984 #endif
985 #if SUPPORT_ARCH_i386
986 case CPU_TYPE_I386:
987 if ( Parser<x86>::validFile(fileContent, bundleLoader) )
988 return Parser<x86>::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib);
989 break;
990 #endif
991 #if SUPPORT_ARCH_arm_any
992 case CPU_TYPE_ARM:
993 if ( Parser<arm>::validFile(fileContent, bundleLoader) )
994 return Parser<arm>::parse(fileContent, fileLength, path, modTime, ordinal, opts, indirectDylib);
995 break;
996 #endif
997 }
998 return NULL;
999 }
1000
1001
1002 }; // namespace dylib
1003 }; // namespace mach_o
1004
1005