1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-*
3 * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
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
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.
22 * @APPLE_LICENSE_HEADER_END@
27 #include <sys/types.h>
30 #include <sys/sysctl.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>
40 #include <mach-o/dyld.h>
41 #include <mach-o/fat.h>
42 #include <sys/sysctl.h>
43 #include <libkern/OSAtomic.h>
52 #include <ext/hash_map>
53 #include <ext/hash_set>
55 #include <AvailabilityMacros.h>
59 #include "InputFiles.h"
60 #include "macho_relocatable_file.h"
61 #include "macho_dylib_file.h"
62 #include "archive_file.h"
64 #include "opaque_section_file.h"
67 const bool _s_logPThreads
= false;
72 class IgnoredFile
: public ld::File
{
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; };
80 class DSOHandleAtom
: public ld::Atom
{
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
) {}
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
96 virtual void setScope(Scope
) { }
98 virtual ~DSOHandleAtom() {}
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
;
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
);
128 class PageZeroAtom
: public ld::Atom
{
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)),
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
142 virtual void setScope(Scope
) { }
144 virtual ~PageZeroAtom() {}
146 static ld::Section _s_section
;
147 static DSOHandleAtom _s_atomAll
;
151 ld::Section
PageZeroAtom::_s_section("__PAGEZERO", "__pagezero", ld::Section::typePageZero
, true);
154 class CustomStackAtom
: public ld::Atom
{
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)),
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
168 virtual void setScope(Scope
) { }
170 virtual ~CustomStackAtom() {}
174 static ld::Section _s_section
;
176 ld::Section
CustomStackAtom::_s_section("__UNIXSTACK", "__stack", ld::Section::typeStack
, true);
180 const char* InputFiles::fileArch(const uint8_t* p
, unsigned len
)
182 const char* result
= mach_o::relocatable::archName(p
);
183 if ( result
!= NULL
)
186 result
= lto::archName(p
, len
);
187 if ( result
!= NULL
)
190 if ( strncmp((const char*)p
, "!<arch>\n", 8) == 0 )
193 char *unsupported
= (char *)malloc(128);
194 strcpy(unsupported
, "unsupported file format (");
195 for (unsigned i
=0; i
<len
&& i
< 16; i
++) {
197 sprintf(buf
, " 0x%2x", p
[i
]);
198 strcat(unsupported
, buf
);
200 strcat(unsupported
, " )");
205 ld::File
* InputFiles::makeFile(const Options::FileInfo
& info
, bool indirectDylib
)
208 uint64_t len
= info
.fileLen
;
209 int fd
= ::open(info
.path
, O_RDONLY
, 0);
211 throwf("can't open file, errno=%d", errno
);
212 if ( info
.fileLen
< 20 )
213 throw "file too small";
215 uint8_t* p
= (uint8_t*)::mmap(NULL
, info
.fileLen
, PROT_READ
, MAP_FILE
| MAP_PRIVATE
, fd
, 0);
216 if ( p
== (uint8_t*)(-1) )
217 throwf("can't map file, errno=%d", errno
);
219 // if fat file, skip to architecture we want
220 // Note: fat header is always big-endian
221 bool isFatFile
= false;
222 uint32_t sliceToUse
, sliceCount
;
223 const fat_header
* fh
= (fat_header
*)p
;
224 if ( fh
->magic
== OSSwapBigToHostInt32(FAT_MAGIC
) ) {
226 const struct fat_arch
* archs
= (struct fat_arch
*)(p
+ sizeof(struct fat_header
));
227 bool sliceFound
= false;
228 sliceCount
= OSSwapBigToHostInt32(fh
->nfat_arch
);
229 if ( _options
.preferSubArchitecture() ) {
230 // first try to find a slice that match cpu-type and cpu-sub-type
231 for (uint32_t i
=0; i
< sliceCount
; ++i
) {
232 if ( (OSSwapBigToHostInt32(archs
[i
].cputype
) == (uint32_t)_options
.architecture())
233 && (OSSwapBigToHostInt32(archs
[i
].cpusubtype
) == (uint32_t)_options
.subArchitecture()) ) {
241 // look for any slice that matches just cpu-type
242 for (uint32_t i
=0; i
< sliceCount
; ++i
) {
243 if ( OSSwapBigToHostInt32(archs
[i
].cputype
) == (uint32_t)_options
.architecture() ) {
251 uint32_t fileOffset
= OSSwapBigToHostInt32(archs
[sliceToUse
].offset
);
252 len
= OSSwapBigToHostInt32(archs
[sliceToUse
].size
);
253 if ( fileOffset
+len
> info
.fileLen
) {
254 throwf("truncated fat file. Slice from %u to %llu is past end of file with length %llu",
255 fileOffset
, fileOffset
+len
, info
.fileLen
);
257 // if requested architecture is page aligned within fat file, then remap just that portion of file
258 if ( (fileOffset
& 0x00000FFF) == 0 ) {
260 munmap((caddr_t
)p
, info
.fileLen
);
261 // re-map just part we need
262 p
= (uint8_t*)::mmap(NULL
, len
, PROT_READ
, MAP_FILE
| MAP_PRIVATE
, fd
, fileOffset
);
263 if ( p
== (uint8_t*)(-1) )
264 throwf("can't re-map file, errno=%d", errno
);
273 // see if it is an object file
274 mach_o::relocatable::ParserOptions objOpts
;
275 objOpts
.architecture
= _options
.architecture();
276 objOpts
.objSubtypeMustMatch
= !_options
.allowSubArchitectureMismatches();
277 objOpts
.logAllFiles
= _options
.logAllFiles();
278 objOpts
.convertUnwindInfo
= _options
.needsUnwindInfoSection();
279 objOpts
.subType
= _options
.subArchitecture();
280 ld::relocatable::File
* objResult
= mach_o::relocatable::parse(p
, len
, info
.path
, info
.modTime
, info
.ordinal
, objOpts
);
281 if ( objResult
!= NULL
) {
282 OSAtomicAdd64(len
, &_totalObjectSize
);
283 OSAtomicIncrement32(&_totalObjectLoaded
);
287 // see if it is an llvm object file
288 objResult
= lto::parse(p
, len
, info
.path
, info
.modTime
, info
.ordinal
, _options
.architecture(), _options
.subArchitecture(), _options
.logAllFiles());
289 if ( objResult
!= NULL
) {
290 OSAtomicAdd64(len
, &_totalObjectSize
);
291 OSAtomicIncrement32(&_totalObjectLoaded
);
295 // see if it is a dynamic library
296 ld::dylib::File
* dylibResult
= mach_o::dylib::parse(p
, len
, info
.path
, info
.modTime
, _options
, info
.ordinal
, info
.options
.fBundleLoader
, indirectDylib
);
297 if ( dylibResult
!= NULL
) {
301 // see if it is a static library
302 ::archive::ParserOptions archOpts
;
303 archOpts
.objOpts
= objOpts
;
304 archOpts
.forceLoadThisArchive
= info
.options
.fForceLoad
;
305 archOpts
.forceLoadAll
= _options
.fullyLoadArchives();
306 archOpts
.forceLoadObjC
= _options
.loadAllObjcObjectsFromArchives();
307 archOpts
.objcABI2
= _options
.objCABIVersion2POverride();
308 archOpts
.verboseLoad
= _options
.whyLoad();
309 archOpts
.logAllFiles
= _options
.logAllFiles();
310 ld::archive::File
* archiveResult
= ::archive::parse(p
, len
, info
.path
, info
.modTime
, info
.ordinal
, archOpts
);
311 if ( archiveResult
!= NULL
) {
312 OSAtomicAdd64(len
, &_totalArchiveSize
);
313 OSAtomicIncrement32(&_totalArchivesLoaded
);
314 return archiveResult
;
317 // does not seem to be any valid linker input file, check LTO misconfiguration problems
318 if ( lto::archName((uint8_t*)p
, len
) != NULL
) {
319 if ( lto::libLTOisLoaded() ) {
320 throwf("lto file was built for %s which is not the architecture being linked (%s): %s", fileArch(p
, len
), _options
.architectureName(), info
.path
);
323 const char* libLTO
= "libLTO.dylib";
324 char ldPath
[PATH_MAX
];
325 char tmpPath
[PATH_MAX
];
326 char libLTOPath
[PATH_MAX
];
327 uint32_t bufSize
= PATH_MAX
;
328 if ( _options
.overridePathlibLTO() != NULL
) {
329 libLTO
= _options
.overridePathlibLTO();
331 else if ( _NSGetExecutablePath(ldPath
, &bufSize
) != -1 ) {
332 if ( realpath(ldPath
, tmpPath
) != NULL
) {
333 char* lastSlash
= strrchr(tmpPath
, '/');
334 if ( lastSlash
!= NULL
)
335 strcpy(lastSlash
, "/../lib/libLTO.dylib");
337 if ( realpath(tmpPath
, libLTOPath
) != NULL
)
341 throwf("could not process llvm bitcode object file, because %s could not be loaded", libLTO
);
346 if ( ((fat_header
*)p
)->magic
== OSSwapBigToHostInt32(FAT_MAGIC
) ) {
347 throwf("missing required architecture %s in file %s (%u slices)", _options
.architectureName(), info
.path
, sliceCount
);
351 throwf("file is universal (%u slices) but does not contain a(n) %s slice: %s", sliceCount
, _options
.architectureName(), info
.path
);
353 throwf("file was built for %s which is not the architecture being linked (%s): %s", fileArch(p
, len
), _options
.architectureName(), info
.path
);
357 void InputFiles::logDylib(ld::File
* file
, bool indirect
)
359 if ( _options
.traceDylibs() ) {
360 const char* fullPath
= file
->path();
361 char realName
[MAXPATHLEN
];
362 if ( realpath(fullPath
, realName
) != NULL
)
364 const ld::dylib::File
* dylib
= dynamic_cast<const ld::dylib::File
*>(file
);
365 if ( (dylib
!= NULL
) && dylib
->willBeUpwardDylib() ) {
366 // don't log upward dylibs when XBS is computing dependencies
367 logTraceInfo("[Logging for XBS] Used upward dynamic library: %s\n", fullPath
);
371 logTraceInfo("[Logging for XBS] Used indirect dynamic library: %s\n", fullPath
);
373 logTraceInfo("[Logging for XBS] Used dynamic library: %s\n", fullPath
);
378 void InputFiles::logArchive(ld::File
* file
) const
380 if ( _options
.traceArchives() && (_archiveFilesLogged
.count(file
) == 0) ) {
381 // <rdar://problem/4947347> LD_TRACE_ARCHIVES should only print out when a .o is actually used from an archive
382 _archiveFilesLogged
.insert(file
);
383 const char* fullPath
= file
->path();
384 char realName
[MAXPATHLEN
];
385 if ( realpath(fullPath
, realName
) != NULL
)
387 logTraceInfo("[Logging for XBS] Used static archive: %s\n", fullPath
);
392 void InputFiles::logTraceInfo(const char* format
, ...) const
394 // one time open() of custom LD_TRACE_FILE
395 static int trace_file
= -1;
396 if ( trace_file
== -1 ) {
397 const char *trace_file_path
= _options
.traceOutputFile();
398 if ( trace_file_path
!= NULL
) {
399 trace_file
= open(trace_file_path
, O_WRONLY
| O_APPEND
| O_CREAT
, 0666);
400 if ( trace_file
== -1 )
401 throwf("Could not open or create trace file: %s", trace_file_path
);
404 trace_file
= fileno(stderr
);
408 char trace_buffer
[MAXPATHLEN
* 2];
410 va_start(ap
, format
);
411 int length
= vsnprintf(trace_buffer
, sizeof(trace_buffer
), format
, ap
);
413 char* buffer_ptr
= trace_buffer
;
416 ssize_t amount_written
= write(trace_file
, buffer_ptr
, length
);
417 if(amount_written
== -1)
418 /* Failure to write shouldn't fail the build. */
420 buffer_ptr
+= amount_written
;
421 length
-= amount_written
;
425 ld::dylib::File
* InputFiles::findDylib(const char* installPath
, const char* fromPath
)
427 //fprintf(stderr, "findDylib(%s, %s)\n", installPath, fromPath);
428 InstallNameToDylib::iterator pos
= _installPathToDylibs
.find(installPath
);
429 if ( pos
!= _installPathToDylibs
.end() ) {
433 // allow -dylib_path option to override indirect library to use
434 for (std::vector
<Options::DylibOverride
>::const_iterator dit
= _options
.dylibOverrides().begin(); dit
!= _options
.dylibOverrides().end(); ++dit
) {
435 if ( strcmp(dit
->installName
,installPath
) == 0 ) {
437 Options::FileInfo info
= _options
.findFile(dit
->useInstead
);
438 _indirectDylibOrdinal
= _indirectDylibOrdinal
.nextIndirectDylibOrdinal();
439 info
.ordinal
= _indirectDylibOrdinal
;
440 ld::File
* reader
= this->makeFile(info
, true);
441 ld::dylib::File
* dylibReader
= dynamic_cast<ld::dylib::File
*>(reader
);
442 if ( dylibReader
!= NULL
) {
443 addDylib(dylibReader
, info
);
444 //_installPathToDylibs[strdup(installPath)] = dylibReader;
445 this->logDylib(dylibReader
, true);
449 throwf("indirect dylib at %s is not a dylib", dit
->useInstead
);
451 catch (const char* msg
) {
452 warning("ignoring -dylib_file option, %s", msg
);
456 char newPath
[MAXPATHLEN
];
457 // handle @loader_path
458 if ( strncmp(installPath
, "@loader_path/", 13) == 0 ) {
459 strcpy(newPath
, fromPath
);
460 char* addPoint
= strrchr(newPath
,'/');
461 if ( addPoint
!= NULL
)
462 strcpy(&addPoint
[1], &installPath
[13]);
464 strcpy(newPath
, &installPath
[13]);
465 installPath
= newPath
;
467 // note: @executable_path case is handled inside findFileUsingPaths()
468 // search for dylib using -F and -L paths
469 Options::FileInfo info
= _options
.findFileUsingPaths(installPath
);
470 _indirectDylibOrdinal
= _indirectDylibOrdinal
.nextIndirectDylibOrdinal();
471 info
.ordinal
= _indirectDylibOrdinal
;
473 ld::File
* reader
= this->makeFile(info
, true);
474 ld::dylib::File
* dylibReader
= dynamic_cast<ld::dylib::File
*>(reader
);
475 if ( dylibReader
!= NULL
) {
476 //assert(_installPathToDylibs.find(installPath) != _installPathToDylibs.end());
477 //_installPathToDylibs[strdup(installPath)] = dylibReader;
478 addDylib(dylibReader
, info
);
479 this->logDylib(dylibReader
, true);
483 throwf("indirect dylib at %s is not a dylib", info
.path
);
485 catch (const char* msg
) {
486 throwf("in %s, %s", info
.path
, msg
);
493 void InputFiles::createIndirectDylibs()
495 _allDirectDylibsLoaded
= true;
496 _indirectDylibOrdinal
= ld::File::Ordinal::indirectDylibBase();
498 // mark all dylibs initially specified as required and check if they can be used
499 for (InstallNameToDylib::iterator it
=_installPathToDylibs
.begin(); it
!= _installPathToDylibs
.end(); it
++) {
500 it
->second
->setExplicitlyLinked();
501 this->checkDylibClientRestrictions(it
->second
);
504 // keep processing dylibs until no more dylibs are added
505 unsigned long lastMapSize
= 0;
506 std::set
<ld::dylib::File
*> dylibsProcessed
;
507 while ( lastMapSize
!= _allDylibs
.size() ) {
508 lastMapSize
= _allDylibs
.size();
509 // can't iterator _installPathToDylibs while modifying it, so use temp buffer
510 std::vector
<ld::dylib::File
*> unprocessedDylibs
;
511 for (std::set
<ld::dylib::File
*>::iterator it
=_allDylibs
.begin(); it
!= _allDylibs
.end(); it
++) {
512 if ( dylibsProcessed
.count(*it
) == 0 )
513 unprocessedDylibs
.push_back(*it
);
515 for (std::vector
<ld::dylib::File
*>::iterator it
=unprocessedDylibs
.begin(); it
!= unprocessedDylibs
.end(); it
++) {
516 dylibsProcessed
.insert(*it
);
517 (*it
)->processIndirectLibraries(this, _options
.implicitlyLinkIndirectPublicDylibs());
521 // go back over original dylibs and mark sub frameworks as re-exported
522 if ( _options
.outputKind() == Options::kDynamicLibrary
) {
523 const char* myLeaf
= strrchr(_options
.installPath(), '/');
524 if ( myLeaf
!= NULL
) {
525 for (std::vector
<class ld::File
*>::const_iterator it
=_inputFiles
.begin(); it
!= _inputFiles
.end(); it
++) {
526 ld::dylib::File
* dylibReader
= dynamic_cast<ld::dylib::File
*>(*it
);
527 if ( dylibReader
!= NULL
) {
528 const char* childParent
= dylibReader
->parentUmbrella();
529 if ( childParent
!= NULL
) {
530 if ( strcmp(childParent
, &myLeaf
[1]) == 0 ) {
531 // mark that this dylib will be re-exported
532 dylibReader
->setWillBeReExported();
542 void InputFiles::createOpaqueFileSections()
544 // extra command line section always at end
545 for (Options::ExtraSection::const_iterator it
=_options
.extraSectionsBegin(); it
!= _options
.extraSectionsEnd(); ++it
) {
546 _inputFiles
.push_back(opaque_section::parse(it
->segmentName
, it
->sectionName
, it
->path
, it
->data
, it
->dataLen
));
552 void InputFiles::checkDylibClientRestrictions(ld::dylib::File
* dylib
)
554 // Check for any restrictions on who can link with this dylib
555 const char* dylibParentName
= dylib
->parentUmbrella() ;
556 const std::vector
<const char*>* clients
= dylib
->allowableClients();
557 if ( (dylibParentName
!= NULL
) || (clients
!= NULL
) ) {
558 // only dylibs that are in an umbrella or have a client list need verification
559 const char* installName
= _options
.installPath();
560 const char* installNameLastSlash
= strrchr(installName
, '/');
561 bool isParent
= false;
562 bool isSibling
= false;
563 bool isAllowableClient
= false;
564 // There are three cases:
565 if ( (dylibParentName
!= NULL
) && (installNameLastSlash
!= NULL
) ) {
566 // starts after last slash
567 const char* myName
= &installNameLastSlash
[1];
568 unsigned int myNameLen
= strlen(myName
);
569 if ( strncmp(myName
, "lib", 3) == 0 )
572 const char* firstDot
= strchr(myName
, '.');
573 if ( firstDot
!= NULL
)
574 myNameLen
= firstDot
- myName
;
575 // up to first underscore
576 const char* firstUnderscore
= strchr(myName
, '_');
577 if ( (firstUnderscore
!= NULL
) && ((firstUnderscore
- myName
) < (int)myNameLen
) )
578 myNameLen
= firstUnderscore
- myName
;
580 // case 1) The dylib has a parent umbrella, and we are creating the parent umbrella
581 isParent
= ( (strlen(dylibParentName
) == myNameLen
) && (strncmp(myName
, dylibParentName
, myNameLen
) == 0) );
583 // case 2) The dylib has a parent umbrella, and we are creating a sibling with the same parent
584 isSibling
= ( (_options
.umbrellaName() != NULL
) && (strcmp(_options
.umbrellaName(), dylibParentName
) == 0) );
587 if ( !isParent
&& !isSibling
&& (clients
!= NULL
) ) {
588 // case 3) the dylib has a list of allowable clients, and we are creating one of them
589 const char* clientName
= _options
.clientName();
590 int clientNameLen
= 0;
591 if ( clientName
!= NULL
) {
592 // use client name as specified on command line
593 clientNameLen
= strlen(clientName
);
596 // infer client name from output path (e.g. xxx/libfoo_variant.A.dylib --> foo, Bar.framework/Bar_variant --> Bar)
597 clientName
= installName
;
598 clientNameLen
= strlen(clientName
);
599 // starts after last slash
600 if ( installNameLastSlash
!= NULL
)
601 clientName
= &installNameLastSlash
[1];
602 if ( strncmp(clientName
, "lib", 3) == 0 )
603 clientName
= &clientName
[3];
605 const char* firstDot
= strchr(clientName
, '.');
606 if ( firstDot
!= NULL
)
607 clientNameLen
= firstDot
- clientName
;
608 // up to first underscore
609 const char* firstUnderscore
= strchr(clientName
, '_');
610 if ( (firstUnderscore
!= NULL
) && ((firstUnderscore
- clientName
) < clientNameLen
) )
611 clientNameLen
= firstUnderscore
- clientName
;
614 // Use clientName to check if this dylib is able to link against the allowable clients.
615 for (std::vector
<const char*>::const_iterator it
= clients
->begin(); it
!= clients
->end(); it
++) {
616 if ( strncmp(*it
, clientName
, clientNameLen
) == 0 )
617 isAllowableClient
= true;
621 if ( !isParent
&& !isSibling
&& !isAllowableClient
) {
622 if ( dylibParentName
!= NULL
) {
623 throwf("cannot link directly with %s. Link against the umbrella framework '%s.framework' instead.",
624 dylib
->path(), dylibParentName
);
627 throwf("cannot link directly with %s", dylib
->path());
634 void InputFiles::inferArchitecture(Options
& opts
, const char** archName
)
636 _inferredArch
= true;
637 // scan all input files, looking for a thin .o file.
638 // the first one found is presumably the architecture to link
639 uint8_t buffer
[sizeof(mach_header_64
)];
640 const std::vector
<Options::FileInfo
>& files
= opts
.getInputFiles();
641 for (std::vector
<Options::FileInfo
>::const_iterator it
= files
.begin(); it
!= files
.end(); ++it
) {
642 int fd
= ::open(it
->path
, O_RDONLY
, 0);
644 ssize_t amount
= read(fd
, buffer
, sizeof(buffer
));
646 if ( amount
>= (ssize_t
)sizeof(buffer
) ) {
648 cpu_subtype_t subtype
;
649 if ( mach_o::relocatable::isObjectFile(buffer
, &type
, &subtype
) ) {
650 opts
.setArchitecture(type
, subtype
);
651 *archName
= opts
.architectureName();
658 // no thin .o files found, so default to same architecture this tool was built as
659 warning("-arch not specified");
661 opts
.setArchitecture(CPU_TYPE_I386
, CPU_SUBTYPE_X86_ALL
);
663 opts
.setArchitecture(CPU_TYPE_X86_64
, CPU_SUBTYPE_X86_64_ALL
);
665 opts
.setArchitecture(CPU_TYPE_ARM
, CPU_SUBTYPE_ARM_V6
);
667 #error unknown default architecture
669 *archName
= opts
.architectureName();
673 InputFiles::InputFiles(Options
& opts
, const char** archName
)
674 : _totalObjectSize(0), _totalArchiveSize(0),
675 _totalObjectLoaded(0), _totalArchivesLoaded(0), _totalDylibsLoaded(0),
676 _options(opts
), _bundleLoader(NULL
),
677 _allDirectDylibsLoaded(false), _inferredArch(false), _fileMonitor(-1),
680 // fStartCreateReadersTime = mach_absolute_time();
681 if ( opts
.architecture() == 0 ) {
682 // command line missing -arch, so guess arch
683 inferArchitecture(opts
, archName
);
686 pthread_mutex_init(&_parseLock
, NULL
);
687 pthread_cond_init(&_parseWorkReady
, NULL
);
688 pthread_cond_init(&_newFileAvailable
, NULL
);
690 const std::vector
<Options::FileInfo
>& files
= _options
.getInputFiles();
691 if ( files
.size() == 0 )
692 throw "no object files specified";
694 _inputFiles
.reserve(files
.size());
696 unsigned int inputFileSlot
= 0;
697 _availableInputFiles
= 0;
700 Options::FileInfo
* entry
;
701 for (std::vector
<Options::FileInfo
>::const_iterator it
= files
.begin(); it
!= files
.end(); ++it
) {
702 entry
= (Options::FileInfo
*)&(*it
);
704 // Assign input file slots to all the FileInfos.
705 // Also chain all FileInfos into one big list to set up for worker threads to do parsing.
706 entry
->inputFileSlot
= inputFileSlot
;
707 entry
->readyToParse
= !entry
->fromFileList
|| !_options
.pipelineEnabled();
708 if (entry
->readyToParse
)
709 _availableInputFiles
++;
710 _inputFiles
.push_back(NULL
);
713 // In the non-threaded case just parse the file now.
714 _inputFiles
.push_back(makeFile(*entry
, false));
719 _remainingInputFiles
= files
.size();
721 // initialize info for parsing input files on worker threads
724 size_t len
= sizeof(ncpus
);
727 if (sysctl(mib
, 2, &ncpus
, &len
, NULL
, 0) != 0) {
730 _availableWorkers
= MIN(ncpus
, files
.size()); // max # workers we permit
733 if (_options
.pipelineEnabled()) {
734 // start up a thread to listen for available input files
735 startThread(InputFiles::waitForInputFiles
);
738 // Start up one parser thread. More start on demand as parsed input files get consumed.
739 startThread(InputFiles::parseWorkerThread
);
742 if (_options
.pipelineEnabled()) {
743 throwf("pipelined linking not supported on this platform");
750 void InputFiles::startThread(void (*threadFunc
)(InputFiles
*)) const {
753 pthread_attr_init(&attr
);
754 // set a nice big stack (same as main thread) because some code uses potentially large stack buffers
755 pthread_attr_setstacksize(&attr
, 8 * 1024 * 1024);
756 pthread_create(&thread
, &attr
, (void *(*)(void*))threadFunc
, (void *)this);
757 pthread_detach(thread
);
758 pthread_attr_destroy(&attr
);
761 // Work loop for input file parsing threads
762 void InputFiles::parseWorkerThread() {
764 const char *exception
= NULL
;
765 pthread_mutex_lock(&_parseLock
);
766 const std::vector
<Options::FileInfo
>& files
= _options
.getInputFiles();
767 if (_s_logPThreads
) printf("worker starting\n");
769 if (_availableInputFiles
== 0) {
771 pthread_cond_wait(&_parseWorkReady
, &_parseLock
);
774 int slot
= _parseCursor
;
775 while (slot
< (int)files
.size() && (_inputFiles
[slot
] != NULL
|| !files
[slot
].readyToParse
))
777 assert(slot
< (int)files
.size());
778 Options::FileInfo
& entry
= (Options::FileInfo
&)files
[slot
];
779 _parseCursor
= slot
+1;
780 _availableInputFiles
--;
781 entry
.readyToParse
= false; // to avoid multiple threads finding this file
782 pthread_mutex_unlock(&_parseLock
);
783 if (_s_logPThreads
) printf("parsing index %u\n", slot
);
785 file
= makeFile(entry
, false);
786 } catch (const char *msg
) {
787 if ( (strstr(msg
, "architecture") != NULL
) && !_options
.errorOnOtherArchFiles() ) {
788 if ( _options
.ignoreOtherArchInputFiles() ) {
789 // ignore, because this is about an architecture not in use
792 warning("ignoring file %s, %s", entry
.path
, msg
);
797 file
= new IgnoredFile(entry
.path
, entry
.modTime
, entry
.ordinal
, ld::File::Other
);
799 pthread_mutex_lock(&_parseLock
);
800 if (_remainingInputFiles
> 0)
801 _remainingInputFiles
--;
802 if (_s_logPThreads
) printf("done with index %u, %d remaining\n", slot
, _remainingInputFiles
);
804 // We are about to die, so set to zero to stop other threads from doing unneeded work.
805 _remainingInputFiles
= 0;
806 _exception
= exception
;
808 _inputFiles
[slot
] = file
;
809 if (_neededFileSlot
== slot
)
810 pthread_cond_signal(&_newFileAvailable
);
813 } while (_remainingInputFiles
);
814 if (_s_logPThreads
) printf("worker exiting\n");
815 pthread_cond_broadcast(&_parseWorkReady
);
816 pthread_cond_signal(&_newFileAvailable
);
817 pthread_mutex_unlock(&_parseLock
);
821 void InputFiles::parseWorkerThread(InputFiles
*inputFiles
) {
822 inputFiles
->parseWorkerThread();
827 ld::File
* InputFiles::addDylib(ld::dylib::File
* reader
, const Options::FileInfo
& info
)
829 _allDylibs
.insert(reader
);
831 if ( (reader
->installPath() == NULL
) && !info
.options
.fBundleLoader
) {
832 // this is a "blank" stub
833 // silently ignore it
836 // store options about how dylib will be used in dylib itself
837 if ( info
.options
.fWeakImport
)
838 reader
->setForcedWeakLinked();
839 if ( info
.options
.fReExport
)
840 reader
->setWillBeReExported();
841 if ( info
.options
.fUpward
) {
842 if ( _options
.outputKind() == Options::kDynamicLibrary
)
843 reader
->setWillBeUpwardDylib();
845 warning("ignoring upward dylib option for %s\n", info
.path
);
847 if ( info
.options
.fLazyLoad
)
848 reader
->setWillBeLazyLoadedDylb();
850 // add to map of loaded dylibs
851 const char* installPath
= reader
->installPath();
852 if ( installPath
!= NULL
) {
853 InstallNameToDylib::iterator pos
= _installPathToDylibs
.find(installPath
);
854 if ( pos
== _installPathToDylibs
.end() ) {
855 _installPathToDylibs
[strdup(installPath
)] = reader
;
858 bool dylibOnCommandLineTwice
= ( strcmp(pos
->second
->path(), reader
->path()) == 0 );
859 bool isSymlink
= false;
860 // ignore if this is a symlink to a dylib we've already loaded
861 if ( !dylibOnCommandLineTwice
) {
862 char existingDylibPath
[PATH_MAX
];
863 if ( realpath(pos
->second
->path(), existingDylibPath
) != NULL
) {
864 char newDylibPath
[PATH_MAX
];
865 if ( realpath(reader
->path(), newDylibPath
) != NULL
) {
866 isSymlink
= ( strcmp(existingDylibPath
, newDylibPath
) == 0 );
870 // remove warning for <rdar://problem/10860629> Same install name for CoreServices and CFNetwork?
871 //if ( !dylibOnCommandLineTwice && !isSymlink )
872 // warning("dylibs with same install name: %s and %s", pos->second->path(), reader->path());
875 else if ( info
.options
.fBundleLoader
)
876 _bundleLoader
= reader
;
878 // log direct readers
879 if ( !_allDirectDylibsLoaded
)
880 this->logDylib(reader
, false);
883 _totalDylibsLoaded
++;
885 _searchLibraries
.push_back(LibraryInfo(reader
));
891 // Called during pipelined linking to listen for available input files.
892 // Available files are enqueued for parsing.
893 void InputFiles::waitForInputFiles()
895 if (_s_logPThreads
) printf("starting pipeline listener\n");
897 const char *fifo
= _options
.pipelineFifo();
899 std::map
<const char *, const Options::FileInfo
*, strcompclass
> fileMap
;
900 const std::vector
<Options::FileInfo
>& files
= _options
.getInputFiles();
901 for (std::vector
<Options::FileInfo
>::const_iterator it
= files
.begin(); it
!= files
.end(); ++it
) {
902 const Options::FileInfo
& entry
= *it
;
903 if (entry
.fromFileList
) {
904 fileMap
[entry
.path
] = &entry
;
907 FILE *fileStream
= fopen(fifo
, "r");
909 throwf("pipelined linking error - failed to open stream. fopen() returns %s for \"%s\"\n", strerror(errno
), fifo
);
910 while (fileMap
.size() > 0) {
911 char path_buf
[PATH_MAX
+1];
912 if (fgets(path_buf
, PATH_MAX
, fileStream
) == NULL
)
913 throwf("pipelined linking error - %lu missing input files", fileMap
.size());
914 int len
= strlen(path_buf
);
915 if (path_buf
[len
-1] == '\n')
917 std::map
<const char *, const Options::FileInfo
*, strcompclass
>::iterator it
= fileMap
.find(path_buf
);
918 if (it
== fileMap
.end())
919 throwf("pipelined linking error - not in file list: %s\n", path_buf
);
920 Options::FileInfo
* inputInfo
= (Options::FileInfo
*)it
->second
;
921 if (!inputInfo
->checkFileExists())
922 throwf("pipelined linking error - file does not exist: %s\n", inputInfo
->path
);
923 pthread_mutex_lock(&_parseLock
);
925 pthread_cond_signal(&_parseWorkReady
);
926 inputInfo
->readyToParse
= true;
927 if (_parseCursor
> inputInfo
->inputFileSlot
)
928 _parseCursor
= inputInfo
->inputFileSlot
;
929 _availableInputFiles
++;
930 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);
931 pthread_mutex_unlock(&_parseLock
);
934 } catch (const char *msg
) {
935 pthread_mutex_lock(&_parseLock
);
937 pthread_cond_signal(&_newFileAvailable
);
938 pthread_mutex_unlock(&_parseLock
);
943 void InputFiles::waitForInputFiles(InputFiles
*inputFiles
) {
944 inputFiles
->waitForInputFiles();
949 void InputFiles::forEachInitialAtom(ld::File::AtomHandler
& handler
)
951 // add all direct object, archives, and dylibs
952 const std::vector
<Options::FileInfo
>& files
= _options
.getInputFiles();
954 for (fileIndex
=0; fileIndex
<_inputFiles
.size(); fileIndex
++) {
957 pthread_mutex_lock(&_parseLock
);
959 // this loop waits for the needed file to be ready (parsed by worker thread)
960 while (_inputFiles
[fileIndex
] == NULL
&& _exception
== NULL
) {
961 // We are starved for input. If there are still files to parse and we have
962 // not maxed out the worker thread count start a new worker thread.
963 if (_availableInputFiles
> 0 && _availableWorkers
> 0) {
964 if (_s_logPThreads
) printf("starting worker\n");
965 startThread(InputFiles::parseWorkerThread
);
968 _neededFileSlot
= fileIndex
;
969 if (_s_logPThreads
) printf("consumer blocking for %lu: %s\n", fileIndex
, files
[fileIndex
].path
);
970 pthread_cond_wait(&_newFileAvailable
, &_parseLock
);
976 // The input file is parsed. Assimilate it and call its atom iterator.
977 if (_s_logPThreads
) printf("consuming slot %lu\n", fileIndex
);
978 file
= _inputFiles
[fileIndex
];
979 pthread_mutex_unlock(&_parseLock
);
981 file
= _inputFiles
[fileIndex
];
983 const Options::FileInfo
& info
= files
[fileIndex
];
984 switch (file
->type()) {
985 case ld::File::Reloc
:
987 ld::relocatable::File
* reloc
= (ld::relocatable::File
*)file
;
988 _options
.snapshot().recordObjectFile(reloc
->path());
991 case ld::File::Dylib
:
993 ld::dylib::File
* dylib
= (ld::dylib::File
*)file
;
994 addDylib(dylib
, info
);
997 case ld::File::Archive
:
999 ld::archive::File
* archive
= (ld::archive::File
*)file
;
1000 // <rdar://problem/9740166> force loaded archives should be in LD_TRACE
1001 if ( (info
.options
.fForceLoad
|| _options
.fullyLoadArchives()) && _options
.traceArchives() )
1002 logArchive(archive
);
1003 _searchLibraries
.push_back(LibraryInfo(archive
));
1006 case ld::File::Other
:
1010 throwf("Unknown file type for %s", file
->path());
1014 file
->forEachAtom(handler
);
1017 createIndirectDylibs();
1018 createOpaqueFileSections();
1020 while (fileIndex
< _inputFiles
.size()) {
1021 ld::File
*file
= _inputFiles
[fileIndex
];
1022 file
->forEachAtom(handler
);
1026 switch ( _options
.outputKind() ) {
1027 case Options::kStaticExecutable
:
1028 case Options::kDynamicExecutable
:
1029 // add implicit __dso_handle label
1030 handler
.doAtom(DSOHandleAtom::_s_atomExecutable
);
1031 handler
.doAtom(DSOHandleAtom::_s_atomAll
);
1032 if ( _options
.pageZeroSize() != 0 )
1033 handler
.doAtom(*new PageZeroAtom(_options
.pageZeroSize()));
1034 if ( _options
.hasCustomStack() && !_options
.needsEntryPointLoadCommand() )
1035 handler
.doAtom(*new CustomStackAtom(_options
.customStackSize()));
1037 case Options::kDynamicLibrary
:
1038 // add implicit __dso_handle label
1039 handler
.doAtom(DSOHandleAtom::_s_atomDylib
);
1040 handler
.doAtom(DSOHandleAtom::_s_atomAll
);
1042 case Options::kDynamicBundle
:
1043 // add implicit __dso_handle label
1044 handler
.doAtom(DSOHandleAtom::_s_atomBundle
);
1045 handler
.doAtom(DSOHandleAtom::_s_atomAll
);
1047 case Options::kDyld
:
1048 // add implicit __dso_handle label
1049 handler
.doAtom(DSOHandleAtom::_s_atomDyld
);
1050 handler
.doAtom(DSOHandleAtom::_s_atomAll
);
1052 case Options::kPreload
:
1053 // add implicit __mh_preload_header label
1054 handler
.doAtom(DSOHandleAtom::_s_atomPreload
);
1055 // add implicit __dso_handle label, but put it in __text section because
1056 // with -preload the mach_header is no in the address space.
1057 handler
.doAtom(DSOHandleAtom::_s_atomPreloadDSO
);
1059 case Options::kObjectFile
:
1060 handler
.doAtom(DSOHandleAtom::_s_atomObjectFile
);
1062 case Options::kKextBundle
:
1063 // add implicit __dso_handle label
1064 handler
.doAtom(DSOHandleAtom::_s_atomAll
);
1070 bool InputFiles::searchLibraries(const char* name
, bool searchDylibs
, bool searchArchives
, bool dataSymbolOnly
, ld::File::AtomHandler
& handler
) const
1072 // Check each input library.
1073 std::vector
<LibraryInfo
>::const_iterator libIterator
= _searchLibraries
.begin();
1076 while (libIterator
!= _searchLibraries
.end()) {
1077 LibraryInfo lib
= *libIterator
;
1078 if (lib
.isDylib()) {
1080 ld::dylib::File
*dylibFile
= lib
.dylib();
1081 //fprintf(stderr, "searchLibraries(%s), looking in linked %s\n", name, dylibFile->path() );
1082 if ( dylibFile
->justInTimeforEachAtom(name
, handler
) ) {
1083 // we found a definition in this dylib
1084 // done, unless it is a weak definition in which case we keep searching
1085 _options
.snapshot().recordDylibSymbol(dylibFile
, name
);
1086 if ( !dylibFile
->hasWeakExternals() || !dylibFile
->hasWeakDefinition(name
)) {
1089 // else continue search for a non-weak definition
1093 if (searchArchives
) {
1094 ld::archive::File
*archiveFile
= lib
.archive();
1095 if ( dataSymbolOnly
) {
1096 if ( archiveFile
->justInTimeDataOnlyforEachAtom(name
, handler
) ) {
1097 if ( _options
.traceArchives() )
1098 logArchive(archiveFile
);
1099 _options
.snapshot().recordArchive(archiveFile
->path());
1100 // found data definition in static library, done
1105 if ( archiveFile
->justInTimeforEachAtom(name
, handler
) ) {
1106 if ( _options
.traceArchives() )
1107 logArchive(archiveFile
);
1108 _options
.snapshot().recordArchive(archiveFile
->path());
1109 // found definition in static library, done
1118 // search indirect dylibs
1119 if ( searchDylibs
) {
1120 for (InstallNameToDylib::const_iterator it
=_installPathToDylibs
.begin(); it
!= _installPathToDylibs
.end(); ++it
) {
1121 ld::dylib::File
* dylibFile
= it
->second
;
1122 bool searchThisDylib
= false;
1123 if ( _options
.nameSpace() == Options::kTwoLevelNameSpace
) {
1124 // for two level namesapce, just check all implicitly linked dylibs
1125 searchThisDylib
= dylibFile
->implicitlyLinked() && !dylibFile
->explicitlyLinked();
1128 // for flat namespace, check all indirect dylibs
1129 searchThisDylib
= ! dylibFile
->explicitlyLinked();
1131 if ( searchThisDylib
) {
1132 //fprintf(stderr, "searchLibraries(%s), looking in implicitly linked %s\n", name, dylibFile->path() );
1133 if ( dylibFile
->justInTimeforEachAtom(name
, handler
) ) {
1134 // we found a definition in this dylib
1135 // done, unless it is a weak definition in which case we keep searching
1136 _options
.snapshot().recordDylibSymbol(dylibFile
, name
);
1137 if ( !dylibFile
->hasWeakExternals() || !dylibFile
->hasWeakDefinition(name
)) {
1140 // else continue search for a non-weak definition
1150 bool InputFiles::searchWeakDefInDylib(const char* name
) const
1152 // search all relevant dylibs to see if any of a weak-def with this name
1153 for (InstallNameToDylib::const_iterator it
=_installPathToDylibs
.begin(); it
!= _installPathToDylibs
.end(); ++it
) {
1154 ld::dylib::File
* dylibFile
= it
->second
;
1155 if ( dylibFile
->implicitlyLinked() || dylibFile
->explicitlyLinked() ) {
1156 if ( dylibFile
->hasWeakExternals() && dylibFile
->hasWeakDefinition(name
) ) {
1164 static bool vectorContains(const std::vector
<ld::dylib::File
*>& vec
, ld::dylib::File
* key
)
1166 return std::find(vec
.begin(), vec
.end(), key
) != vec
.end();
1169 void InputFiles::dylibs(ld::Internal
& state
)
1171 bool dylibsOK
= false;
1172 switch ( _options
.outputKind() ) {
1173 case Options::kDynamicExecutable
:
1174 case Options::kDynamicLibrary
:
1175 case Options::kDynamicBundle
:
1178 case Options::kStaticExecutable
:
1179 case Options::kDyld
:
1180 case Options::kPreload
:
1181 case Options::kObjectFile
:
1182 case Options::kKextBundle
:
1187 // add command line dylibs in order
1188 for (std::vector
<ld::File
*>::const_iterator it
=_inputFiles
.begin(); it
!= _inputFiles
.end(); ++it
) {
1189 ld::dylib::File
* dylibFile
= dynamic_cast<ld::dylib::File
*>(*it
);
1190 // only add dylibs that are not "blank" dylib stubs
1191 if ( (dylibFile
!= NULL
) && ((dylibFile
->installPath() != NULL
) || (dylibFile
== _bundleLoader
)) ) {
1193 if ( ! vectorContains(state
.dylibs
, dylibFile
) ) {
1194 state
.dylibs
.push_back(dylibFile
);
1198 warning("unexpected dylib (%s) on link line", dylibFile
->path());
1201 // add implicitly linked dylibs
1202 if ( _options
.nameSpace() == Options::kTwoLevelNameSpace
) {
1203 for (InstallNameToDylib::const_iterator it
=_installPathToDylibs
.begin(); it
!= _installPathToDylibs
.end(); ++it
) {
1204 ld::dylib::File
* dylibFile
= it
->second
;
1205 if ( dylibFile
->implicitlyLinked() && dylibsOK
) {
1206 if ( ! vectorContains(state
.dylibs
, dylibFile
) ) {
1207 state
.dylibs
.push_back(dylibFile
);
1213 //fprintf(stderr, "all dylibs:\n");
1214 //for(std::vector<ld::dylib::File*>::iterator it=state.dylibs.begin(); it != state.dylibs.end(); ++it) {
1215 // const ld::dylib::File* dylib = *it;
1216 // fprintf(stderr, " %p %s\n", dylib, dylib->path());
1219 // and -bundle_loader
1220 state
.bundleLoader
= _bundleLoader
;
1222 // <rdar://problem/10807040> give an error when -nostdlib is used and libSystem is missing
1223 if ( (state
.dylibs
.size() == 0) && _options
.needsEntryPointLoadCommand() )
1224 throw "dynamic main executables must link with libSystem.dylib";