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