]> git.saurik.com Git - apple/ld64.git/blob - src/ld/InputFiles.cpp
ld64-133.3.tar.gz
[apple/ld64.git] / src / ld / InputFiles.cpp
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-*
2 *
3 * Copyright (c) 2009-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 <stdlib.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <sys/mman.h>
30 #include <sys/sysctl.h>
31 #include <fcntl.h>
32 #include <errno.h>
33 #include <limits.h>
34 #include <unistd.h>
35 #include <mach/mach_time.h>
36 #include <mach/vm_statistics.h>
37 #include <mach/mach_init.h>
38 #include <mach/mach_host.h>
39 #include <dlfcn.h>
40 #include <mach-o/dyld.h>
41 #include <mach-o/fat.h>
42 #include <sys/sysctl.h>
43 #include <libkern/OSAtomic.h>
44
45 #include <string>
46 #include <map>
47 #include <set>
48 #include <string>
49 #include <vector>
50 #include <list>
51 #include <algorithm>
52 #include <ext/hash_map>
53 #include <ext/hash_set>
54 #include <dlfcn.h>
55 #include <AvailabilityMacros.h>
56
57 #include "Options.h"
58
59 #include "InputFiles.h"
60 #include "macho_relocatable_file.h"
61 #include "macho_dylib_file.h"
62 #include "archive_file.h"
63 #include "lto_file.h"
64 #include "opaque_section_file.h"
65 #include "Snapshot.h"
66
67 const bool _s_logPThreads = false;
68
69 namespace ld {
70 namespace tool {
71
72 class IgnoredFile : public ld::File {
73 public:
74 IgnoredFile(const char* pth, time_t modTime, Ordinal ord, Type type) : ld::File(pth, modTime, ord, type) {};
75 virtual bool forEachAtom(AtomHandler&) const { return false; };
76 virtual bool justInTimeforEachAtom(const char* name, AtomHandler&) const { return false; };
77 };
78
79
80 class DSOHandleAtom : public ld::Atom {
81 public:
82 DSOHandleAtom(const char* nm, ld::Atom::Scope sc,
83 ld::Atom::SymbolTableInclusion inc, bool preload=false)
84 : ld::Atom(preload ? _s_section_preload : _s_section,
85 ld::Atom::definitionRegular, ld::Atom::combineNever,
86 sc, ld::Atom::typeUnclassified, inc, true, false, false,
87 ld::Atom::Alignment(1)), _name(nm) {}
88
89 virtual ld::File* file() const { return NULL; }
90 virtual bool translationUnitSource(const char** dir, const char** ) const
91 { return false; }
92 virtual const char* name() const { return _name; }
93 virtual uint64_t size() const { return 0; }
94 virtual uint64_t objectAddress() const { return 0; }
95 virtual void copyRawContent(uint8_t buffer[]) const
96 { }
97 virtual void setScope(Scope) { }
98
99 virtual ~DSOHandleAtom() {}
100
101 static ld::Section _s_section;
102 static ld::Section _s_section_preload;
103 static DSOHandleAtom _s_atomAll;
104 static DSOHandleAtom _s_atomExecutable;
105 static DSOHandleAtom _s_atomDylib;
106 static DSOHandleAtom _s_atomBundle;
107 static DSOHandleAtom _s_atomDyld;
108 static DSOHandleAtom _s_atomObjectFile;
109 static DSOHandleAtom _s_atomPreload;
110 private:
111 const char* _name;
112 };
113 ld::Section DSOHandleAtom::_s_section("__TEXT", "__mach_header", ld::Section::typeMachHeader, true);
114 ld::Section DSOHandleAtom::_s_section_preload("__HEADER", "__mach_header", ld::Section::typeMachHeader, true);
115 DSOHandleAtom DSOHandleAtom::_s_atomAll("___dso_handle", ld::Atom::scopeLinkageUnit, ld::Atom::symbolTableNotIn);
116 DSOHandleAtom DSOHandleAtom::_s_atomExecutable("__mh_execute_header", ld::Atom::scopeGlobal, ld::Atom::symbolTableInAndNeverStrip);
117 DSOHandleAtom DSOHandleAtom::_s_atomDylib("__mh_dylib_header", ld::Atom::scopeLinkageUnit, ld::Atom::symbolTableNotIn);
118 DSOHandleAtom DSOHandleAtom::_s_atomBundle("__mh_bundle_header", ld::Atom::scopeLinkageUnit, ld::Atom::symbolTableNotIn);
119 DSOHandleAtom DSOHandleAtom::_s_atomDyld("__mh_dylinker_header", ld::Atom::scopeLinkageUnit, ld::Atom::symbolTableNotIn);
120 DSOHandleAtom DSOHandleAtom::_s_atomObjectFile("__mh_object_header", ld::Atom::scopeLinkageUnit, ld::Atom::symbolTableNotIn);
121 DSOHandleAtom DSOHandleAtom::_s_atomPreload("__mh_preload_header", ld::Atom::scopeLinkageUnit, ld::Atom::symbolTableNotIn, true);
122
123
124
125 class PageZeroAtom : public ld::Atom {
126 public:
127 PageZeroAtom(uint64_t sz)
128 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
129 ld::Atom::scopeTranslationUnit, ld::Atom::typeZeroFill,
130 symbolTableNotIn, true, false, false, ld::Atom::Alignment(12)),
131 _size(sz) {}
132
133 virtual ld::File* file() const { return NULL; }
134 virtual bool translationUnitSource(const char** dir, const char** ) const
135 { return false; }
136 virtual const char* name() const { return "page zero"; }
137 virtual uint64_t size() const { return _size; }
138 virtual uint64_t objectAddress() const { return 0; }
139 virtual void copyRawContent(uint8_t buffer[]) const
140 { }
141 virtual void setScope(Scope) { }
142
143 virtual ~PageZeroAtom() {}
144
145 static ld::Section _s_section;
146 static DSOHandleAtom _s_atomAll;
147 private:
148 uint64_t _size;
149 };
150 ld::Section PageZeroAtom::_s_section("__PAGEZERO", "__pagezero", ld::Section::typePageZero, true);
151
152
153 class CustomStackAtom : public ld::Atom {
154 public:
155 CustomStackAtom(uint64_t sz)
156 : ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
157 ld::Atom::scopeTranslationUnit, ld::Atom::typeZeroFill,
158 symbolTableNotIn, false, false, false, ld::Atom::Alignment(12)),
159 _size(sz) {}
160
161 virtual ld::File* file() const { return NULL; }
162 virtual bool translationUnitSource(const char** dir, const char** ) const
163 { return false; }
164 virtual const char* name() const { return "custom stack"; }
165 virtual uint64_t size() const { return _size; }
166 virtual uint64_t objectAddress() const { return 0; }
167 virtual void copyRawContent(uint8_t buffer[]) const
168 { }
169 virtual void setScope(Scope) { }
170
171 virtual ~CustomStackAtom() {}
172
173 private:
174 uint64_t _size;
175 static ld::Section _s_section;
176 };
177 ld::Section CustomStackAtom::_s_section("__UNIXSTACK", "__stack", ld::Section::typeStack, true);
178
179
180
181 const char* InputFiles::fileArch(const uint8_t* p, unsigned len)
182 {
183 const char* result = mach_o::relocatable::archName(p);
184 if ( result != NULL )
185 return result;
186
187 result = lto::archName(p, len);
188 if ( result != NULL )
189 return result;
190
191 if ( strncmp((const char*)p, "!<arch>\n", 8) == 0 )
192 return "archive";
193
194 char *unsupported = (char *)malloc(128);
195 strcpy(unsupported, "unsupported file format (");
196 for (unsigned i=0; i<len && i < 16; i++) {
197 char buf[8];
198 sprintf(buf, " 0x%2x", p[i]);
199 strcat(unsupported, buf);
200 }
201 strcat(unsupported, " )");
202 return unsupported;
203 }
204
205
206 ld::File* InputFiles::makeFile(const Options::FileInfo& info, bool indirectDylib)
207 {
208 // map in whole file
209 uint64_t len = info.fileLen;
210 int fd = ::open(info.path, O_RDONLY, 0);
211 if ( fd == -1 )
212 throwf("can't open file, errno=%d", errno);
213 if ( info.fileLen < 20 )
214 throw "file too small";
215
216 uint8_t* p = (uint8_t*)::mmap(NULL, info.fileLen, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
217 if ( p == (uint8_t*)(-1) )
218 throwf("can't map file, errno=%d", errno);
219
220 // if fat file, skip to architecture we want
221 // Note: fat header is always big-endian
222 bool isFatFile = false;
223 uint32_t sliceToUse, sliceCount;
224 const fat_header* fh = (fat_header*)p;
225 if ( fh->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) {
226 isFatFile = true;
227 const struct fat_arch* archs = (struct fat_arch*)(p + sizeof(struct fat_header));
228 bool sliceFound = false;
229 sliceCount = OSSwapBigToHostInt32(fh->nfat_arch);
230 if ( _options.preferSubArchitecture() ) {
231 // first try to find a slice that match cpu-type and cpu-sub-type
232 for (uint32_t i=0; i < sliceCount; ++i) {
233 if ( (OSSwapBigToHostInt32(archs[i].cputype) == (uint32_t)_options.architecture())
234 && (OSSwapBigToHostInt32(archs[i].cpusubtype) == (uint32_t)_options.subArchitecture()) ) {
235 sliceToUse = i;
236 sliceFound = true;
237 break;
238 }
239 }
240 }
241 if ( !sliceFound ) {
242 // look for any slice that matches just cpu-type
243 for (uint32_t i=0; i < sliceCount; ++i) {
244 if ( OSSwapBigToHostInt32(archs[i].cputype) == (uint32_t)_options.architecture() ) {
245 sliceToUse = i;
246 sliceFound = true;
247 break;
248 }
249 }
250 }
251 if ( sliceFound ) {
252 uint32_t fileOffset = OSSwapBigToHostInt32(archs[sliceToUse].offset);
253 len = OSSwapBigToHostInt32(archs[sliceToUse].size);
254 if ( fileOffset+len > info.fileLen ) {
255 throwf("truncated fat file. Slice from %u to %llu is past end of file with length %llu",
256 fileOffset, fileOffset+len, info.fileLen);
257 }
258 // if requested architecture is page aligned within fat file, then remap just that portion of file
259 if ( (fileOffset & 0x00000FFF) == 0 ) {
260 // unmap whole file
261 munmap((caddr_t)p, info.fileLen);
262 // re-map just part we need
263 p = (uint8_t*)::mmap(NULL, len, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, fileOffset);
264 if ( p == (uint8_t*)(-1) )
265 throwf("can't re-map file, errno=%d", errno);
266 }
267 else {
268 p = &p[fileOffset];
269 }
270 }
271 }
272 ::close(fd);
273
274 // see if it is an object file
275 mach_o::relocatable::ParserOptions objOpts;
276 objOpts.architecture = _options.architecture();
277 objOpts.objSubtypeMustMatch = !_options.allowSubArchitectureMismatches();
278 objOpts.logAllFiles = _options.logAllFiles();
279 objOpts.convertUnwindInfo = _options.needsUnwindInfoSection();
280 objOpts.subType = _options.subArchitecture();
281 ld::relocatable::File* objResult = mach_o::relocatable::parse(p, len, info.path, info.modTime, info.ordinal, objOpts);
282 if ( objResult != NULL ) {
283 OSAtomicAdd64(len, &_totalObjectSize);
284 OSAtomicIncrement32(&_totalObjectLoaded);
285 return objResult;
286 }
287
288 // see if it is an llvm object file
289 objResult = lto::parse(p, len, info.path, info.modTime, _options.architecture(), _options.subArchitecture(), _options.logAllFiles());
290 if ( objResult != NULL ) {
291 OSAtomicAdd64(len, &_totalObjectSize);
292 OSAtomicIncrement32(&_totalObjectLoaded);
293 return objResult;
294 }
295
296 // see if it is a dynamic library
297 ld::dylib::File* dylibResult = mach_o::dylib::parse(p, len, info.path, info.modTime, _options, info.ordinal, info.options.fBundleLoader, indirectDylib);
298 if ( dylibResult != NULL ) {
299 return dylibResult;
300 }
301
302 // see if it is a static library
303 ::archive::ParserOptions archOpts;
304 archOpts.objOpts = objOpts;
305 archOpts.forceLoadThisArchive = info.options.fForceLoad;
306 archOpts.forceLoadAll = _options.fullyLoadArchives();
307 archOpts.forceLoadObjC = _options.loadAllObjcObjectsFromArchives();
308 archOpts.objcABI2 = _options.objCABIVersion2POverride();
309 archOpts.verboseLoad = _options.whyLoad();
310 archOpts.logAllFiles = _options.logAllFiles();
311 ld::archive::File* archiveResult = ::archive::parse(p, len, info.path, info.modTime, info.ordinal, archOpts);
312 if ( archiveResult != NULL ) {
313 OSAtomicAdd64(len, &_totalArchiveSize);
314 OSAtomicIncrement32(&_totalArchivesLoaded);
315 return archiveResult;
316 }
317
318 // does not seem to be any valid linker input file, check LTO misconfiguration problems
319 if ( lto::archName((uint8_t*)p, len) != NULL ) {
320 if ( lto::libLTOisLoaded() ) {
321 throwf("lto file was built for %s which is not the architecture being linked (%s): %s", fileArch(p, len), _options.architectureName(), info.path);
322 }
323 else {
324 const char* libLTO = "libLTO.dylib";
325 char ldPath[PATH_MAX];
326 char tmpPath[PATH_MAX];
327 char libLTOPath[PATH_MAX];
328 uint32_t bufSize = PATH_MAX;
329 if ( _options.overridePathlibLTO() != NULL ) {
330 libLTO = _options.overridePathlibLTO();
331 }
332 else if ( _NSGetExecutablePath(ldPath, &bufSize) != -1 ) {
333 if ( realpath(ldPath, tmpPath) != NULL ) {
334 char* lastSlash = strrchr(tmpPath, '/');
335 if ( lastSlash != NULL )
336 strcpy(lastSlash, "/../lib/libLTO.dylib");
337 libLTO = tmpPath;
338 if ( realpath(tmpPath, libLTOPath) != NULL )
339 libLTO = libLTOPath;
340 }
341 }
342 throwf("could not process llvm bitcode object file, because %s could not be loaded", libLTO);
343 }
344 }
345
346 // error handling
347 if ( ((fat_header*)p)->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) {
348 throwf("missing required architecture %s in file %s (%u slices)", _options.architectureName(), info.path, sliceCount);
349 }
350 else {
351 if ( isFatFile )
352 throwf("file is universal (%u slices) but does not contain a(n) %s slice: %s", sliceCount, _options.architectureName(), info.path);
353 else
354 throwf("file was built for %s which is not the architecture being linked (%s): %s", fileArch(p, len), _options.architectureName(), info.path);
355 }
356 }
357
358 void InputFiles::logDylib(ld::File* file, bool indirect)
359 {
360 if ( _options.traceDylibs() ) {
361 const char* fullPath = file->path();
362 char realName[MAXPATHLEN];
363 if ( realpath(fullPath, realName) != NULL )
364 fullPath = realName;
365 const ld::dylib::File* dylib = dynamic_cast<const ld::dylib::File*>(file);
366 if ( (dylib != NULL ) && dylib->willBeUpwardDylib() ) {
367 // don't log upward dylibs when XBS is computing dependencies
368 logTraceInfo("[Logging for XBS] Used upward dynamic library: %s\n", fullPath);
369 }
370 else {
371 if ( indirect )
372 logTraceInfo("[Logging for XBS] Used indirect dynamic library: %s\n", fullPath);
373 else
374 logTraceInfo("[Logging for XBS] Used dynamic library: %s\n", fullPath);
375 }
376 }
377 }
378
379 void InputFiles::logArchive(ld::File* file) const
380 {
381 if ( _options.traceArchives() && (_archiveFilesLogged.count(file) == 0) ) {
382 // <rdar://problem/4947347> LD_TRACE_ARCHIVES should only print out when a .o is actually used from an archive
383 _archiveFilesLogged.insert(file);
384 const char* fullPath = file->path();
385 char realName[MAXPATHLEN];
386 if ( realpath(fullPath, realName) != NULL )
387 fullPath = realName;
388 logTraceInfo("[Logging for XBS] Used static archive: %s\n", fullPath);
389 }
390 }
391
392
393 void InputFiles::logTraceInfo(const char* format, ...) const
394 {
395 // one time open() of custom LD_TRACE_FILE
396 static int trace_file = -1;
397 if ( trace_file == -1 ) {
398 const char *trace_file_path = _options.traceOutputFile();
399 if ( trace_file_path != NULL ) {
400 trace_file = open(trace_file_path, O_WRONLY | O_APPEND | O_CREAT, 0666);
401 if ( trace_file == -1 )
402 throwf("Could not open or create trace file: %s", trace_file_path);
403 }
404 else {
405 trace_file = fileno(stderr);
406 }
407 }
408
409 char trace_buffer[MAXPATHLEN * 2];
410 va_list ap;
411 va_start(ap, format);
412 int length = vsnprintf(trace_buffer, sizeof(trace_buffer), format, ap);
413 va_end(ap);
414 char* buffer_ptr = trace_buffer;
415
416 while (length > 0) {
417 ssize_t amount_written = write(trace_file, buffer_ptr, length);
418 if(amount_written == -1)
419 /* Failure to write shouldn't fail the build. */
420 return;
421 buffer_ptr += amount_written;
422 length -= amount_written;
423 }
424 }
425
426 ld::dylib::File* InputFiles::findDylib(const char* installPath, const char* fromPath)
427 {
428 //fprintf(stderr, "findDylib(%s, %s)\n", installPath, fromPath);
429 InstallNameToDylib::iterator pos = _installPathToDylibs.find(installPath);
430 if ( pos != _installPathToDylibs.end() ) {
431 return pos->second;
432 }
433 else {
434 // allow -dylib_path option to override indirect library to use
435 for (std::vector<Options::DylibOverride>::const_iterator dit = _options.dylibOverrides().begin(); dit != _options.dylibOverrides().end(); ++dit) {
436 if ( strcmp(dit->installName,installPath) == 0 ) {
437 try {
438 Options::FileInfo info = _options.findFile(dit->useInstead);
439 _indirectDylibOrdinal = _indirectDylibOrdinal.nextIndirectDylibOrdinal();
440 info.ordinal = _indirectDylibOrdinal;
441 ld::File* reader = this->makeFile(info, true);
442 ld::dylib::File* dylibReader = dynamic_cast<ld::dylib::File*>(reader);
443 if ( dylibReader != NULL ) {
444 addDylib(dylibReader, info);
445 //_installPathToDylibs[strdup(installPath)] = dylibReader;
446 this->logDylib(dylibReader, true);
447 return dylibReader;
448 }
449 else
450 throwf("indirect dylib at %s is not a dylib", dit->useInstead);
451 }
452 catch (const char* msg) {
453 warning("ignoring -dylib_file option, %s", msg);
454 }
455 }
456 }
457 char newPath[MAXPATHLEN];
458 // handle @loader_path
459 if ( strncmp(installPath, "@loader_path/", 13) == 0 ) {
460 strcpy(newPath, fromPath);
461 char* addPoint = strrchr(newPath,'/');
462 if ( addPoint != NULL )
463 strcpy(&addPoint[1], &installPath[13]);
464 else
465 strcpy(newPath, &installPath[13]);
466 installPath = newPath;
467 }
468 // note: @executable_path case is handled inside findFileUsingPaths()
469 // search for dylib using -F and -L paths
470 Options::FileInfo info = _options.findFileUsingPaths(installPath);
471 _indirectDylibOrdinal = _indirectDylibOrdinal.nextIndirectDylibOrdinal();
472 info.ordinal = _indirectDylibOrdinal;
473 try {
474 ld::File* reader = this->makeFile(info, true);
475 ld::dylib::File* dylibReader = dynamic_cast<ld::dylib::File*>(reader);
476 if ( dylibReader != NULL ) {
477 //assert(_installPathToDylibs.find(installPath) != _installPathToDylibs.end());
478 //_installPathToDylibs[strdup(installPath)] = dylibReader;
479 addDylib(dylibReader, info);
480 this->logDylib(dylibReader, true);
481 return dylibReader;
482 }
483 else
484 throwf("indirect dylib at %s is not a dylib", info.path);
485 }
486 catch (const char* msg) {
487 throwf("in %s, %s", info.path, msg);
488 }
489 }
490 }
491
492
493
494 void InputFiles::createIndirectDylibs()
495 {
496 _allDirectDylibsLoaded = true;
497 _indirectDylibOrdinal = ld::File::Ordinal::indirectDylibBase();
498
499 // mark all dylibs initially specified as required and check if they can be used
500 for (InstallNameToDylib::iterator it=_installPathToDylibs.begin(); it != _installPathToDylibs.end(); it++) {
501 it->second->setExplicitlyLinked();
502 this->checkDylibClientRestrictions(it->second);
503 }
504
505 // keep processing dylibs until no more dylibs are added
506 unsigned long lastMapSize = 0;
507 std::set<ld::dylib::File*> dylibsProcessed;
508 while ( lastMapSize != _allDylibs.size() ) {
509 lastMapSize = _allDylibs.size();
510 // can't iterator _installPathToDylibs while modifying it, so use temp buffer
511 std::vector<ld::dylib::File*> unprocessedDylibs;
512 for (std::set<ld::dylib::File*>::iterator it=_allDylibs.begin(); it != _allDylibs.end(); it++) {
513 if ( dylibsProcessed.count(*it) == 0 )
514 unprocessedDylibs.push_back(*it);
515 }
516 for (std::vector<ld::dylib::File*>::iterator it=unprocessedDylibs.begin(); it != unprocessedDylibs.end(); it++) {
517 dylibsProcessed.insert(*it);
518 (*it)->processIndirectLibraries(this, _options.implicitlyLinkIndirectPublicDylibs());
519 }
520 }
521
522 // go back over original dylibs and mark sub frameworks as re-exported
523 if ( _options.outputKind() == Options::kDynamicLibrary ) {
524 const char* myLeaf = strrchr(_options.installPath(), '/');
525 if ( myLeaf != NULL ) {
526 for (std::vector<class ld::File*>::const_iterator it=_inputFiles.begin(); it != _inputFiles.end(); it++) {
527 ld::dylib::File* dylibReader = dynamic_cast<ld::dylib::File*>(*it);
528 if ( dylibReader != NULL ) {
529 const char* childParent = dylibReader->parentUmbrella();
530 if ( childParent != NULL ) {
531 if ( strcmp(childParent, &myLeaf[1]) == 0 ) {
532 // mark that this dylib will be re-exported
533 dylibReader->setWillBeReExported();
534 }
535 }
536 }
537 }
538 }
539 }
540
541 }
542
543 void InputFiles::createOpaqueFileSections()
544 {
545 // extra command line section always at end
546 for (Options::ExtraSection::const_iterator it=_options.extraSectionsBegin(); it != _options.extraSectionsEnd(); ++it) {
547 _inputFiles.push_back(opaque_section::parse(it->segmentName, it->sectionName, it->path, it->data, it->dataLen));
548 }
549
550 }
551
552
553 void InputFiles::checkDylibClientRestrictions(ld::dylib::File* dylib)
554 {
555 // Check for any restrictions on who can link with this dylib
556 const char* dylibParentName = dylib->parentUmbrella() ;
557 const std::vector<const char*>* clients = dylib->allowableClients();
558 if ( (dylibParentName != NULL) || (clients != NULL) ) {
559 // only dylibs that are in an umbrella or have a client list need verification
560 const char* installName = _options.installPath();
561 const char* installNameLastSlash = strrchr(installName, '/');
562 bool isParent = false;
563 bool isSibling = false;
564 bool isAllowableClient = false;
565 // There are three cases:
566 if ( (dylibParentName != NULL) && (installNameLastSlash != NULL) ) {
567 // starts after last slash
568 const char* myName = &installNameLastSlash[1];
569 unsigned int myNameLen = strlen(myName);
570 if ( strncmp(myName, "lib", 3) == 0 )
571 myName = &myName[3];
572 // up to first dot
573 const char* firstDot = strchr(myName, '.');
574 if ( firstDot != NULL )
575 myNameLen = firstDot - myName;
576 // up to first underscore
577 const char* firstUnderscore = strchr(myName, '_');
578 if ( (firstUnderscore != NULL) && ((firstUnderscore - myName) < (int)myNameLen) )
579 myNameLen = firstUnderscore - myName;
580
581 // case 1) The dylib has a parent umbrella, and we are creating the parent umbrella
582 isParent = ( (strlen(dylibParentName) == myNameLen) && (strncmp(myName, dylibParentName, myNameLen) == 0) );
583
584 // case 2) The dylib has a parent umbrella, and we are creating a sibling with the same parent
585 isSibling = ( (_options.umbrellaName() != NULL) && (strcmp(_options.umbrellaName(), dylibParentName) == 0) );
586 }
587
588 if ( !isParent && !isSibling && (clients != NULL) ) {
589 // case 3) the dylib has a list of allowable clients, and we are creating one of them
590 const char* clientName = _options.clientName();
591 int clientNameLen = 0;
592 if ( clientName != NULL ) {
593 // use client name as specified on command line
594 clientNameLen = strlen(clientName);
595 }
596 else {
597 // infer client name from output path (e.g. xxx/libfoo_variant.A.dylib --> foo, Bar.framework/Bar_variant --> Bar)
598 clientName = installName;
599 clientNameLen = strlen(clientName);
600 // starts after last slash
601 if ( installNameLastSlash != NULL )
602 clientName = &installNameLastSlash[1];
603 if ( strncmp(clientName, "lib", 3) == 0 )
604 clientName = &clientName[3];
605 // up to first dot
606 const char* firstDot = strchr(clientName, '.');
607 if ( firstDot != NULL )
608 clientNameLen = firstDot - clientName;
609 // up to first underscore
610 const char* firstUnderscore = strchr(clientName, '_');
611 if ( (firstUnderscore != NULL) && ((firstUnderscore - clientName) < clientNameLen) )
612 clientNameLen = firstUnderscore - clientName;
613 }
614
615 // Use clientName to check if this dylib is able to link against the allowable clients.
616 for (std::vector<const char*>::const_iterator it = clients->begin(); it != clients->end(); it++) {
617 if ( strncmp(*it, clientName, clientNameLen) == 0 )
618 isAllowableClient = true;
619 }
620 }
621
622 if ( !isParent && !isSibling && !isAllowableClient ) {
623 if ( dylibParentName != NULL ) {
624 throwf("cannot link directly with %s. Link against the umbrella framework '%s.framework' instead.",
625 dylib->path(), dylibParentName);
626 }
627 else {
628 throwf("cannot link directly with %s", dylib->path());
629 }
630 }
631 }
632 }
633
634
635 void InputFiles::inferArchitecture(Options& opts, const char** archName)
636 {
637 _inferredArch = true;
638 // scan all input files, looking for a thin .o file.
639 // the first one found is presumably the architecture to link
640 uint8_t buffer[sizeof(mach_header_64)];
641 const std::vector<Options::FileInfo>& files = opts.getInputFiles();
642 for (std::vector<Options::FileInfo>::const_iterator it = files.begin(); it != files.end(); ++it) {
643 int fd = ::open(it->path, O_RDONLY, 0);
644 if ( fd != -1 ) {
645 ssize_t amount = read(fd, buffer, sizeof(buffer));
646 ::close(fd);
647 if ( amount >= (ssize_t)sizeof(buffer) ) {
648 cpu_type_t type;
649 cpu_subtype_t subtype;
650 if ( mach_o::relocatable::isObjectFile(buffer, &type, &subtype) ) {
651 opts.setArchitecture(type, subtype);
652 *archName = opts.architectureName();
653 return;
654 }
655 }
656 }
657 }
658
659 // no thin .o files found, so default to same architecture this tool was built as
660 warning("-arch not specified");
661 #if __i386__
662 opts.setArchitecture(CPU_TYPE_I386, CPU_SUBTYPE_X86_ALL);
663 #elif __x86_64__
664 opts.setArchitecture(CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL);
665 #elif __arm__
666 opts.setArchitecture(CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6);
667 #else
668 #error unknown default architecture
669 #endif
670 *archName = opts.architectureName();
671 }
672
673
674 InputFiles::InputFiles(Options& opts, const char** archName)
675 : _totalObjectSize(0), _totalArchiveSize(0),
676 _totalObjectLoaded(0), _totalArchivesLoaded(0), _totalDylibsLoaded(0),
677 _options(opts), _bundleLoader(NULL),
678 _allDirectDylibsLoaded(false), _inferredArch(false), _fileMonitor(-1),
679 _exception(NULL)
680 {
681 // fStartCreateReadersTime = mach_absolute_time();
682 if ( opts.architecture() == 0 ) {
683 // command line missing -arch, so guess arch
684 inferArchitecture(opts, archName);
685 }
686 #if HAVE_PTHREADS
687 pthread_mutex_init(&_parseLock, NULL);
688 pthread_cond_init(&_parseWorkReady, NULL);
689 pthread_cond_init(&_newFileAvailable, NULL);
690 #endif
691 const std::vector<Options::FileInfo>& files = _options.getInputFiles();
692 if ( files.size() == 0 )
693 throw "no object files specified";
694
695 _inputFiles.reserve(files.size());
696 #if HAVE_PTHREADS
697 unsigned int inputFileSlot = 0;
698 _availableInputFiles = 0;
699 _parseCursor = 0;
700 #endif
701 Options::FileInfo* entry;
702 for (std::vector<Options::FileInfo>::const_iterator it = files.begin(); it != files.end(); ++it) {
703 entry = (Options::FileInfo*)&(*it);
704 #if HAVE_PTHREADS
705 // Assign input file slots to all the FileInfos.
706 // Also chain all FileInfos into one big list to set up for worker threads to do parsing.
707 entry->inputFileSlot = inputFileSlot;
708 entry->readyToParse = !entry->fromFileList || !_options.pipelineEnabled();
709 if (entry->readyToParse)
710 _availableInputFiles++;
711 _inputFiles.push_back(NULL);
712 inputFileSlot++;
713 #else
714 // In the non-threaded case just parse the file now.
715 _inputFiles.push_back(makeFile(*entry, false));
716 #endif
717 }
718
719 #if HAVE_PTHREADS
720 _remainingInputFiles = files.size();
721
722 // initialize info for parsing input files on worker threads
723 unsigned int ncpus;
724 int mib[2];
725 size_t len = sizeof(ncpus);
726 mib[0] = CTL_HW;
727 mib[1] = HW_NCPU;
728 if (sysctl(mib, 2, &ncpus, &len, NULL, 0) != 0) {
729 ncpus = 1;
730 }
731 _availableWorkers = MIN(ncpus, files.size()); // max # workers we permit
732 _idleWorkers = 0;
733
734 if (_options.pipelineEnabled()) {
735 // start up a thread to listen for available input files
736 startThread(InputFiles::waitForInputFiles);
737 }
738
739 // Start up one parser thread. More start on demand as parsed input files get consumed.
740 startThread(InputFiles::parseWorkerThread);
741 _availableWorkers--;
742 #else
743 if (_options.pipelineEnabled()) {
744 throwf("pipelined linking not supported on this platform");
745 }
746 #endif
747 }
748
749
750 #if HAVE_PTHREADS
751 void InputFiles::startThread(void (*threadFunc)(InputFiles *)) const {
752 pthread_t thread;
753 pthread_attr_t attr;
754 pthread_attr_init(&attr);
755 // set a nice big stack (same as main thread) because some code uses potentially large stack buffers
756 pthread_attr_setstacksize(&attr, 8 * 1024 * 1024);
757 pthread_create(&thread, &attr, (void *(*)(void*))threadFunc, (void *)this);
758 pthread_detach(thread);
759 pthread_attr_destroy(&attr);
760 }
761
762 // Work loop for input file parsing threads
763 void InputFiles::parseWorkerThread() {
764 ld::File *file;
765 const char *exception = NULL;
766 pthread_mutex_lock(&_parseLock);
767 const std::vector<Options::FileInfo>& files = _options.getInputFiles();
768 if (_s_logPThreads) printf("worker starting\n");
769 do {
770 if (_availableInputFiles == 0) {
771 _idleWorkers++;
772 pthread_cond_wait(&_parseWorkReady, &_parseLock);
773 _idleWorkers--;
774 } else {
775 int slot = _parseCursor;
776 while (slot < (int)files.size() && (_inputFiles[slot] != NULL || !files[slot].readyToParse))
777 slot++;
778 assert(slot < (int)files.size());
779 Options::FileInfo& entry = (Options::FileInfo&)files[slot];
780 _parseCursor = slot+1;
781 _availableInputFiles--;
782 entry.readyToParse = false; // to avoid multiple threads finding this file
783 pthread_mutex_unlock(&_parseLock);
784 if (_s_logPThreads) printf("parsing index %u\n", slot);
785 try {
786 file = makeFile(entry, false);
787 } catch (const char *msg) {
788 if ( (strstr(msg, "architecture") != NULL) && !_options.errorOnOtherArchFiles() ) {
789 if ( _options.ignoreOtherArchInputFiles() ) {
790 // ignore, because this is about an architecture not in use
791 }
792 else {
793 warning("ignoring file %s, %s", entry.path, msg);
794 }
795 } else {
796 exception = msg;
797 }
798 file = new IgnoredFile(entry.path, entry.modTime, entry.ordinal, ld::File::Other);
799 }
800 pthread_mutex_lock(&_parseLock);
801 if (_remainingInputFiles > 0)
802 _remainingInputFiles--;
803 if (_s_logPThreads) printf("done with index %u, %d remaining\n", slot, _remainingInputFiles);
804 if (exception) {
805 // We are about to die, so set to zero to stop other threads from doing unneeded work.
806 _remainingInputFiles = 0;
807 _exception = exception;
808 } else {
809 _inputFiles[slot] = file;
810 if (_neededFileSlot == slot)
811 pthread_cond_signal(&_newFileAvailable);
812 }
813 }
814 } while (_remainingInputFiles);
815 if (_s_logPThreads) printf("worker exiting\n");
816 pthread_cond_broadcast(&_parseWorkReady);
817 pthread_cond_signal(&_newFileAvailable);
818 pthread_mutex_unlock(&_parseLock);
819 }
820
821
822 void InputFiles::parseWorkerThread(InputFiles *inputFiles) {
823 inputFiles->parseWorkerThread();
824 }
825 #endif
826
827
828 ld::File* InputFiles::addDylib(ld::dylib::File* reader, const Options::FileInfo& info)
829 {
830 _allDylibs.insert(reader);
831
832 if ( (reader->installPath() == NULL) && !info.options.fBundleLoader ) {
833 // this is a "blank" stub
834 // silently ignore it
835 return reader;
836 }
837 // store options about how dylib will be used in dylib itself
838 if ( info.options.fWeakImport )
839 reader->setForcedWeakLinked();
840 if ( info.options.fReExport )
841 reader->setWillBeReExported();
842 if ( info.options.fUpward ) {
843 if ( _options.outputKind() == Options::kDynamicLibrary )
844 reader->setWillBeUpwardDylib();
845 else
846 warning("ignoring upward dylib option for %s\n", info.path);
847 }
848 if ( info.options.fLazyLoad )
849 reader->setWillBeLazyLoadedDylb();
850
851 // add to map of loaded dylibs
852 const char* installPath = reader->installPath();
853 if ( installPath != NULL ) {
854 InstallNameToDylib::iterator pos = _installPathToDylibs.find(installPath);
855 if ( pos == _installPathToDylibs.end() ) {
856 _installPathToDylibs[strdup(installPath)] = reader;
857 }
858 else {
859 bool dylibOnCommandLineTwice = ( strcmp(pos->second->path(), reader->path()) == 0 );
860 bool isSymlink = false;
861 // ignore if this is a symlink to a dylib we've already loaded
862 if ( !dylibOnCommandLineTwice ) {
863 char existingDylibPath[PATH_MAX];
864 if ( realpath(pos->second->path(), existingDylibPath) != NULL ) {
865 char newDylibPath[PATH_MAX];
866 if ( realpath(reader->path(), newDylibPath) != NULL ) {
867 isSymlink = ( strcmp(existingDylibPath, newDylibPath) == 0 );
868 }
869 }
870 }
871 // remove warning for <rdar://problem/10860629> Same install name for CoreServices and CFNetwork?
872 //if ( !dylibOnCommandLineTwice && !isSymlink )
873 // warning("dylibs with same install name: %s and %s", pos->second->path(), reader->path());
874 }
875 }
876 else if ( info.options.fBundleLoader )
877 _bundleLoader = reader;
878
879 // log direct readers
880 if ( !_allDirectDylibsLoaded )
881 this->logDylib(reader, false);
882
883 // update stats
884 _totalDylibsLoaded++;
885
886 _searchLibraries.push_back(LibraryInfo(reader));
887 return reader;
888 }
889
890
891 #if HAVE_PTHREADS
892 // Called during pipelined linking to listen for available input files.
893 // Available files are enqueued for parsing.
894 void InputFiles::waitForInputFiles()
895 {
896 if (_s_logPThreads) printf("starting pipeline listener\n");
897 try {
898 const char *fifo = _options.pipelineFifo();
899 assert(fifo);
900 std::map<const char *, const Options::FileInfo*, strcompclass> fileMap;
901 const std::vector<Options::FileInfo>& files = _options.getInputFiles();
902 for (std::vector<Options::FileInfo>::const_iterator it = files.begin(); it != files.end(); ++it) {
903 const Options::FileInfo& entry = *it;
904 if (entry.fromFileList) {
905 fileMap[entry.path] = &entry;
906 }
907 }
908 FILE *fileStream = fopen(fifo, "r");
909 if (!fileStream)
910 throwf("pipelined linking error - failed to open stream. fopen() returns %s for \"%s\"\n", strerror(errno), fifo);
911 while (fileMap.size() > 0) {
912 char path_buf[PATH_MAX+1];
913 if (fgets(path_buf, PATH_MAX, fileStream) == NULL)
914 throwf("pipelined linking error - %lu missing input files", fileMap.size());
915 int len = strlen(path_buf);
916 if (path_buf[len-1] == '\n')
917 path_buf[len-1] = 0;
918 std::map<const char *, const Options::FileInfo*, strcompclass>::iterator it = fileMap.find(path_buf);
919 if (it == fileMap.end())
920 throwf("pipelined linking error - not in file list: %s\n", path_buf);
921 Options::FileInfo* inputInfo = (Options::FileInfo*)it->second;
922 if (!inputInfo->checkFileExists())
923 throwf("pipelined linking error - file does not exist: %s\n", inputInfo->path);
924 pthread_mutex_lock(&_parseLock);
925 if (_idleWorkers)
926 pthread_cond_signal(&_parseWorkReady);
927 inputInfo->readyToParse = true;
928 if (_parseCursor > inputInfo->inputFileSlot)
929 _parseCursor = inputInfo->inputFileSlot;
930 _availableInputFiles++;
931 if (_s_logPThreads) printf("pipeline listener: %s slot=%d, _parseCursor=%d, _availableInputFiles = %d remaining = %ld\n", path_buf, inputInfo->inputFileSlot, _parseCursor, _availableInputFiles, fileMap.size()-1);
932 pthread_mutex_unlock(&_parseLock);
933 fileMap.erase(it);
934 }
935 } catch (const char *msg) {
936 pthread_mutex_lock(&_parseLock);
937 _exception = msg;
938 pthread_cond_signal(&_newFileAvailable);
939 pthread_mutex_unlock(&_parseLock);
940 }
941 }
942
943
944 void InputFiles::waitForInputFiles(InputFiles *inputFiles) {
945 inputFiles->waitForInputFiles();
946 }
947 #endif
948
949
950 void InputFiles::forEachInitialAtom(ld::File::AtomHandler& handler)
951 {
952 // add all direct object, archives, and dylibs
953 const std::vector<Options::FileInfo>& files = _options.getInputFiles();
954 size_t fileIndex;
955 for (fileIndex=0; fileIndex<_inputFiles.size(); fileIndex++) {
956 ld::File *file;
957 #if HAVE_PTHREADS
958 pthread_mutex_lock(&_parseLock);
959
960 // this loop waits for the needed file to be ready (parsed by worker thread)
961 while (_inputFiles[fileIndex] == NULL && _exception == NULL) {
962 // We are starved for input. If there are still files to parse and we have
963 // not maxed out the worker thread count start a new worker thread.
964 if (_availableInputFiles > 0 && _availableWorkers > 0) {
965 if (_s_logPThreads) printf("starting worker\n");
966 startThread(InputFiles::parseWorkerThread);
967 _availableWorkers--;
968 }
969 _neededFileSlot = fileIndex;
970 if (_s_logPThreads) printf("consumer blocking for %lu: %s\n", fileIndex, files[fileIndex].path);
971 pthread_cond_wait(&_newFileAvailable, &_parseLock);
972 }
973
974 if (_exception)
975 throw _exception;
976
977 // The input file is parsed. Assimilate it and call its atom iterator.
978 if (_s_logPThreads) printf("consuming slot %lu\n", fileIndex);
979 file = _inputFiles[fileIndex];
980 pthread_mutex_unlock(&_parseLock);
981 #else
982 file = _inputFiles[fileIndex];
983 #endif
984 const Options::FileInfo& info = files[fileIndex];
985 switch (file->type()) {
986 case ld::File::Reloc:
987 {
988 ld::relocatable::File* reloc = (ld::relocatable::File*)file;
989 _options.snapshot().recordObjectFile(reloc->path());
990 }
991 break;
992 case ld::File::Dylib:
993 {
994 ld::dylib::File* dylib = (ld::dylib::File*)file;
995 addDylib(dylib, info);
996 }
997 break;
998 case ld::File::Archive:
999 {
1000 ld::archive::File* archive = (ld::archive::File*)file;
1001 // <rdar://problem/9740166> force loaded archives should be in LD_TRACE
1002 if ( (info.options.fForceLoad || _options.fullyLoadArchives()) && _options.traceArchives() )
1003 logArchive(archive);
1004 _searchLibraries.push_back(LibraryInfo(archive));
1005 }
1006 break;
1007 case ld::File::Other:
1008 break;
1009 default:
1010 {
1011 throwf("Unknown file type for %s", file->path());
1012 }
1013 break;
1014 }
1015 file->forEachAtom(handler);
1016 }
1017
1018 createIndirectDylibs();
1019 createOpaqueFileSections();
1020
1021 while (fileIndex < _inputFiles.size()) {
1022 ld::File *file = _inputFiles[fileIndex];
1023 file->forEachAtom(handler);
1024 fileIndex++;
1025 }
1026
1027 switch ( _options.outputKind() ) {
1028 case Options::kStaticExecutable:
1029 case Options::kDynamicExecutable:
1030 // add implicit __dso_handle label
1031 handler.doAtom(DSOHandleAtom::_s_atomExecutable);
1032 handler.doAtom(DSOHandleAtom::_s_atomAll);
1033 if ( _options.pageZeroSize() != 0 )
1034 handler.doAtom(*new PageZeroAtom(_options.pageZeroSize()));
1035 if ( _options.hasCustomStack() && !_options.needsEntryPointLoadCommand() )
1036 handler.doAtom(*new CustomStackAtom(_options.customStackSize()));
1037 break;
1038 case Options::kDynamicLibrary:
1039 // add implicit __dso_handle label
1040 handler.doAtom(DSOHandleAtom::_s_atomDylib);
1041 handler.doAtom(DSOHandleAtom::_s_atomAll);
1042 break;
1043 case Options::kDynamicBundle:
1044 // add implicit __dso_handle label
1045 handler.doAtom(DSOHandleAtom::_s_atomBundle);
1046 handler.doAtom(DSOHandleAtom::_s_atomAll);
1047 break;
1048 case Options::kDyld:
1049 // add implicit __dso_handle label
1050 handler.doAtom(DSOHandleAtom::_s_atomDyld);
1051 handler.doAtom(DSOHandleAtom::_s_atomAll);
1052 break;
1053 case Options::kPreload:
1054 // add implicit __mh_preload_header label
1055 handler.doAtom(DSOHandleAtom::_s_atomPreload);
1056 handler.doAtom(DSOHandleAtom::_s_atomAll);
1057 break;
1058 case Options::kObjectFile:
1059 handler.doAtom(DSOHandleAtom::_s_atomObjectFile);
1060 break;
1061 case Options::kKextBundle:
1062 // add implicit __dso_handle label
1063 handler.doAtom(DSOHandleAtom::_s_atomAll);
1064 break;
1065 }
1066 }
1067
1068
1069 bool InputFiles::searchLibraries(const char* name, bool searchDylibs, bool searchArchives, bool dataSymbolOnly, ld::File::AtomHandler& handler) const
1070 {
1071 // Check each input library.
1072 std::vector<LibraryInfo>::const_iterator libIterator = _searchLibraries.begin();
1073
1074
1075 while (libIterator != _searchLibraries.end()) {
1076 LibraryInfo lib = *libIterator;
1077 if (lib.isDylib()) {
1078 if (searchDylibs) {
1079 ld::dylib::File *dylibFile = lib.dylib();
1080 //fprintf(stderr, "searchLibraries(%s), looking in linked %s\n", name, dylibFile->path() );
1081 if ( dylibFile->justInTimeforEachAtom(name, handler) ) {
1082 // we found a definition in this dylib
1083 // done, unless it is a weak definition in which case we keep searching
1084 _options.snapshot().recordDylibSymbol(dylibFile, name);
1085 if ( !dylibFile->hasWeakExternals() || !dylibFile->hasWeakDefinition(name)) {
1086 return true;
1087 }
1088 // else continue search for a non-weak definition
1089 }
1090 }
1091 } else {
1092 if (searchArchives) {
1093 ld::archive::File *archiveFile = lib.archive();
1094 if ( dataSymbolOnly ) {
1095 if ( archiveFile->justInTimeDataOnlyforEachAtom(name, handler) ) {
1096 if ( _options.traceArchives() )
1097 logArchive(archiveFile);
1098 _options.snapshot().recordArchive(archiveFile->path());
1099 // found data definition in static library, done
1100 return true;
1101 }
1102 }
1103 else {
1104 if ( archiveFile->justInTimeforEachAtom(name, handler) ) {
1105 if ( _options.traceArchives() )
1106 logArchive(archiveFile);
1107 _options.snapshot().recordArchive(archiveFile->path());
1108 // found definition in static library, done
1109 return true;
1110 }
1111 }
1112 }
1113 }
1114 libIterator++;
1115 }
1116
1117 // search indirect dylibs
1118 if ( searchDylibs ) {
1119 for (InstallNameToDylib::const_iterator it=_installPathToDylibs.begin(); it != _installPathToDylibs.end(); ++it) {
1120 ld::dylib::File* dylibFile = it->second;
1121 bool searchThisDylib = false;
1122 if ( _options.nameSpace() == Options::kTwoLevelNameSpace ) {
1123 // for two level namesapce, just check all implicitly linked dylibs
1124 searchThisDylib = dylibFile->implicitlyLinked() && !dylibFile->explicitlyLinked();
1125 }
1126 else {
1127 // for flat namespace, check all indirect dylibs
1128 searchThisDylib = ! dylibFile->explicitlyLinked();
1129 }
1130 if ( searchThisDylib ) {
1131 //fprintf(stderr, "searchLibraries(%s), looking in implicitly linked %s\n", name, dylibFile->path() );
1132 if ( dylibFile->justInTimeforEachAtom(name, handler) ) {
1133 // we found a definition in this dylib
1134 // done, unless it is a weak definition in which case we keep searching
1135 _options.snapshot().recordDylibSymbol(dylibFile, name);
1136 if ( !dylibFile->hasWeakExternals() || !dylibFile->hasWeakDefinition(name)) {
1137 return true;
1138 }
1139 // else continue search for a non-weak definition
1140 }
1141 }
1142 }
1143 }
1144
1145 return false;
1146 }
1147
1148
1149 bool InputFiles::searchWeakDefInDylib(const char* name) const
1150 {
1151 // search all relevant dylibs to see if any of a weak-def with this name
1152 for (InstallNameToDylib::const_iterator it=_installPathToDylibs.begin(); it != _installPathToDylibs.end(); ++it) {
1153 ld::dylib::File* dylibFile = it->second;
1154 if ( dylibFile->implicitlyLinked() || dylibFile->explicitlyLinked() ) {
1155 if ( dylibFile->hasWeakExternals() && dylibFile->hasWeakDefinition(name) ) {
1156 return true;
1157 }
1158 }
1159 }
1160 return false;
1161 }
1162
1163 static bool vectorContains(const std::vector<ld::dylib::File*>& vec, ld::dylib::File* key)
1164 {
1165 return std::find(vec.begin(), vec.end(), key) != vec.end();
1166 }
1167
1168 void InputFiles::dylibs(ld::Internal& state)
1169 {
1170 bool dylibsOK = false;
1171 switch ( _options.outputKind() ) {
1172 case Options::kDynamicExecutable:
1173 case Options::kDynamicLibrary:
1174 case Options::kDynamicBundle:
1175 dylibsOK = true;
1176 break;
1177 case Options::kStaticExecutable:
1178 case Options::kDyld:
1179 case Options::kPreload:
1180 case Options::kObjectFile:
1181 case Options::kKextBundle:
1182 dylibsOK = false;
1183 break;
1184 }
1185
1186 // add command line dylibs in order
1187 for (std::vector<ld::File*>::const_iterator it=_inputFiles.begin(); it != _inputFiles.end(); ++it) {
1188 ld::dylib::File* dylibFile = dynamic_cast<ld::dylib::File*>(*it);
1189 // only add dylibs that are not "blank" dylib stubs
1190 if ( (dylibFile != NULL) && ((dylibFile->installPath() != NULL) || (dylibFile == _bundleLoader)) ) {
1191 if ( dylibsOK ) {
1192 if ( ! vectorContains(state.dylibs, dylibFile) ) {
1193 state.dylibs.push_back(dylibFile);
1194 }
1195 }
1196 else
1197 warning("unexpected dylib (%s) on link line", dylibFile->path());
1198 }
1199 }
1200 // add implicitly linked dylibs
1201 if ( _options.nameSpace() == Options::kTwoLevelNameSpace ) {
1202 for (InstallNameToDylib::const_iterator it=_installPathToDylibs.begin(); it != _installPathToDylibs.end(); ++it) {
1203 ld::dylib::File* dylibFile = it->second;
1204 if ( dylibFile->implicitlyLinked() && dylibsOK ) {
1205 if ( ! vectorContains(state.dylibs, dylibFile) ) {
1206 state.dylibs.push_back(dylibFile);
1207 }
1208 }
1209 }
1210 }
1211
1212 //fprintf(stderr, "all dylibs:\n");
1213 //for(std::vector<ld::dylib::File*>::iterator it=state.dylibs.begin(); it != state.dylibs.end(); ++it) {
1214 // const ld::dylib::File* dylib = *it;
1215 // fprintf(stderr, " %p %s\n", dylib, dylib->path());
1216 //}
1217
1218 // and -bundle_loader
1219 state.bundleLoader = _bundleLoader;
1220
1221 // <rdar://problem/10807040> give an error when -nostdlib is used and libSystem is missing
1222 if ( (state.dylibs.size() == 0) && _options.needsEntryPointLoadCommand() )
1223 throw "dynamic main executables must link with libSystem.dylib";
1224 }
1225
1226
1227 } // namespace tool
1228 } // namespace ld
1229
1230