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