2 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <sys/types.h>
28 #include <mach-o/loader.h>
29 #include <mach-o/fat.h>
37 #include <ext/hash_map>
41 #include "ObjectFile.h"
42 #include "ObjectFileMachO-all.h"
44 #include "ExecutableFile.h"
45 #include "ExecutableFileMachO-all.h"
47 #include "SectCreate.h"
50 static void dumpAtom(ObjectFile::Atom
* atom
)
52 //printf("atom: %p\n", atom);
55 printf("name: %s\n", atom
->getDisplayName());
58 switch ( atom
->getScope() ) {
59 case ObjectFile::Atom::scopeTranslationUnit
:
60 printf("scope: translation unit\n");
62 case ObjectFile::Atom::scopeLinkageUnit
:
63 printf("scope: linkage unit\n");
65 case ObjectFile::Atom::scopeGlobal
:
66 printf("scope: global\n");
69 printf("scope: unknown\n");
72 // segment and section
73 printf("section: %s,%s\n", atom
->getSegment().getName(), atom
->getSectionName());
77 if ( atom
->isTentativekDefinition() )
79 else if ( atom
->isWeakDefinition() )
81 if ( atom
->isCoalesableByName() )
82 printf("coalesce-by-name ");
83 if ( atom
->isCoalesableByValue() )
84 printf("coalesce-by-value ");
85 if ( atom
->dontDeadStrip() )
86 printf("dont-dead-strip ");
87 if ( atom
->isZeroFill() )
92 printf("size: 0x%012llX\n", atom
->getSize());
95 uint8_t content
[atom
->getSize()];
96 atom
->copyRawContent(content
);
98 if ( strcmp(atom
->getSectionName(), "__cstring") == 0 ) {
99 printf("\"%s\"", content
);
102 for (unsigned int i
=0; i
< sizeof(content
); ++i
)
103 printf("%02X ", content
[i
]);
108 std::vector
<ObjectFile::Reference
*>& references
= atom
->getReferences();
109 const int refCount
= references
.size();
110 printf("references: (%u)\n", refCount
);
111 for (int i
=0; i
< refCount
; ++i
) {
112 ObjectFile::Reference
* ref
= references
[i
];
113 printf(" %s\n", ref
->getDescription());
122 class CStringComparor
125 bool operator()(const char* left
, const char* right
) const { return (strcmp(left
, right
) < 0); }
131 bool operator()(const char* left
, const char* right
) const { return (strcmp(left
, right
) == 0); }
134 class Section
: public ObjectFile::Section
137 static Section
* find(const char* sectionName
, const char* segmentName
, bool zeroFill
);
138 static void assignIndexes();
141 Section(const char* sectionName
, const char* segmentName
, bool zeroFill
);
144 static int segmentOrdinal(const char* segName
);
145 bool operator()(Section
* left
, Section
* right
);
148 typedef __gnu_cxx::hash_map
<const char*, class Section
*, __gnu_cxx::hash
<const char*>, CStringEquals
> NameToSection
;
149 //typedef std::map<const char*, class Section*, CStringComparor> NameToSection;
151 const char* fSectionName
;
152 const char* fSegmentName
;
155 static NameToSection fgMapping
;
156 static std::vector
<Section
*> fgSections
;
159 Section::NameToSection
Section::fgMapping
;
160 std::vector
<Section
*> Section::fgSections
;
162 Section::Section(const char* sectionName
, const char* segmentName
, bool zeroFill
)
163 : fSectionName(sectionName
), fSegmentName(segmentName
), fZeroFill(zeroFill
)
165 //fprintf(stderr, "new Section(%s, %s)\n", sectionName, segmentName);
168 Section
* Section::find(const char* sectionName
, const char* segmentName
, bool zeroFill
)
171 std::pair
<NameToSection::iterator
, NameToSection::iterator
> range
= fgMapping
.equal_range(sectionName
);
172 for (NameToSection::iterator it
=range
.first
; it
!= range
.second
; it
++) {
173 if ( strcmp(it
->second
->fSegmentName
, segmentName
) == 0 )
177 NameToSection::iterator pos
= fgMapping
.find(sectionName
);
178 if ( pos
!= fgMapping
.end() ) {
179 if ( strcmp(pos
->second
->fSegmentName
, segmentName
) == 0 )
181 // otherwise same section name is used in different segments, look slow way
182 for (std::vector
<Section
*>::iterator it
=fgSections
.begin(); it
!= fgSections
.end(); it
++) {
183 if ( (strcmp((*it
)->fSectionName
, sectionName
) == 0) && (strcmp((*it
)->fSegmentName
, segmentName
) == 0) )
188 // does not exist, so make a new one
189 Section
* sect
= new Section(sectionName
, segmentName
, zeroFill
);
190 sect
->fIndex
= fgMapping
.size();
191 fgMapping
[sectionName
] = sect
;
192 fgSections
.push_back(sect
);
196 int Section::Sorter::segmentOrdinal(const char* segName
)
198 if ( strcmp(segName
, "__PAGEZERO") == 0 )
200 if ( strcmp(segName
, "__TEXT") == 0 )
202 if ( strcmp(segName
, "__DATA") == 0 )
204 if ( strcmp(segName
, "__OBJC") == 0 )
206 if ( strcmp(segName
, "__LINKEDIT") == 0 )
207 return INT_MAX
; // linkedit segment should always sort last
213 bool Section::Sorter::operator()(Section
* left
, Section
* right
)
215 // Segment is primary sort key
216 const char* leftSegName
= left
->fSegmentName
;
217 const char* rightSegName
= right
->fSegmentName
;
218 int segNameCmp
= strcmp(leftSegName
, rightSegName
);
219 if ( segNameCmp
!= 0 )
221 int leftSegOrdinal
= segmentOrdinal(leftSegName
);
222 int rightSegOrdinal
= segmentOrdinal(rightSegName
);
223 if ( leftSegOrdinal
< rightSegOrdinal
)
225 if ( leftSegOrdinal
== rightSegOrdinal
)
226 return segNameCmp
< 0;
230 // zerofill section sort to the end
231 if ( !left
->fZeroFill
&& right
->fZeroFill
)
233 if ( left
->fZeroFill
&& !right
->fZeroFill
)
236 // section discovery order is last sort key
237 return left
->fIndex
< right
->fIndex
;
240 void Section::assignIndexes()
242 //printf("unsorted:\n");
243 //for (std::vector<Section*>::iterator it=fgSections.begin(); it != fgSections.end(); it++) {
244 // printf("section: name=%s, segment: name=%s, discovery order=%d\n", (*it)->fSectionName, (*it)->fSegmentName, (*it)->fIndex);
248 std::sort(fgSections
.begin(), fgSections
.end(), Section::Sorter());
250 // assign correct section ordering to each Section object
251 unsigned int newOrder
= 1;
252 for (std::vector
<Section
*>::iterator it
=fgSections
.begin(); it
!= fgSections
.end(); it
++)
253 (*it
)->fIndex
= newOrder
++;
255 //printf("sorted:\n");
256 //for (std::vector<Section*>::iterator it=fgSections.begin(); it != fgSections.end(); it++) {
257 // printf("section: name=%s\n", (*it)->fSectionName);
263 Linker(int argc
, const char* argv
[]);
265 void createReaders();
267 void addInputFile(ObjectFile::Reader
* reader
);
268 void setOutputFile(ExecutableFile::Writer
* writer
);
273 ObjectFile::Reader
* createReader(const Options::FileInfo
&);
274 void addAtom(ObjectFile::Atom
& atom
);
275 void addAtoms(std::vector
<class ObjectFile::Atom
*>& atoms
);
276 void buildAtomList();
277 void loadUndefines();
278 void addWeakAtomOverrides();
279 void resolveReferences();
285 void resolve(ObjectFile::Reference
* reference
);
286 void addJustInTimeAtoms(const char* name
);
288 void addDylib(ObjectFile::Reader
* reader
, const Options::FileInfo
& info
);
289 void addIndirectLibraries(ObjectFile::Reader
* reader
);
290 bool haveIndirectLibrary(const char* path
, ObjectFile::Reader
* reader
);
291 bool haveDirectLibrary(const char* path
);
293 struct SegmentAndItsAtoms
295 class Segment
* fSegment
;
296 uint64_t fSegmentSize
;
297 uint64_t fSegmentBaseAddress
;
298 std::vector
<class ObjectFile::Atom
*> fAtoms
;
305 SymbolTable(Linker
&);
306 void require(const char* name
);
307 bool add(ObjectFile::Atom
& atom
);
308 ObjectFile::Atom
* find(const char* name
);
309 unsigned int getRequireCount() { return fRequireCount
; }
310 void getNeededNames(bool andWeakDefintions
, std::vector
<const char*>& undefines
);
312 typedef std::map
<const char*, ObjectFile::Atom
*, CStringComparor
> Mapper
;
315 unsigned int fRequireCount
;
320 bool operator()(ObjectFile::Atom
* left
, ObjectFile::Atom
* right
);
323 typedef std::map
<const char*, uint32_t, CStringComparor
> SectionOrder
;
325 struct IndirectLibrary
{
328 ObjectFile::Reader
* reader
;
329 std::set
<ObjectFile::Reader
*> parents
;
330 ObjectFile::Reader
* reExportParent
;
334 SymbolTable fGlobalSymbolTable
;
335 unsigned int fWeakSymbolsAddedCount
;
336 std::vector
<class ObjectFile::Reader
*> fInputFiles
;
337 ExecutableFile::Writer
* fOutputFile
;
338 std::vector
<ExecutableFile::DyLibUsed
> fDynamicLibraries
;
339 std::list
<IndirectLibrary
> fIndirectDynamicLibraries
;
340 std::vector
<class ObjectFile::Atom
*> fAllAtoms
;
341 std::vector
< SegmentAndItsAtoms
> fAllAtomsBySegment
;
342 std::set
<class ObjectFile::Atom
*> fDeadAtoms
;
343 SectionOrder fSectionOrder
;
344 unsigned int fNextSortOrder
;
345 bool fDirectLibrariesComplete
;
350 Linker::Linker(int argc
, const char* argv
[])
351 : fOptions(argc
, argv
), fGlobalSymbolTable(*this), fOutputFile(NULL
), fNextSortOrder(1), fDirectLibrariesComplete(false)
355 void Linker::addInputFile(ObjectFile::Reader
* reader
)
357 fInputFiles
.push_back(reader
);
360 void Linker::setOutputFile(ExecutableFile::Writer
* writer
)
362 fOutputFile
= writer
;
367 this->buildAtomList();
368 this->loadUndefines();
369 this->resolveReferences();
376 inline void Linker::addAtom(ObjectFile::Atom
& atom
)
378 // add to list of all atoms
379 fAllAtoms
.push_back(&atom
);
381 // add atom's references's names to symbol table as to-be-resolved-later
382 std::vector
<class ObjectFile::Reference
*>& references
= atom
.getReferences();
383 for (std::vector
<ObjectFile::Reference
*>::iterator it
=references
.begin(); it
!= references
.end(); it
++) {
384 ObjectFile::Reference
* reference
= *it
;
385 if ( reference
->isUnbound() ) {
386 fGlobalSymbolTable
.require(reference
->getTargetName());
390 // if in global namespace, add atom itself to symbol table
391 ObjectFile::Atom::Scope scope
= atom
.getScope();
392 const char* name
= atom
.getName();
393 if ( (scope
!= ObjectFile::Atom::scopeTranslationUnit
) && (name
!= NULL
) ) {
394 fGlobalSymbolTable
.add(atom
);
396 // update scope based on export list (possible that globals are downgraded to private_extern)
397 if ( (scope
== ObjectFile::Atom::scopeGlobal
) && fOptions
.hasExportRestrictList() ) {
398 bool doExport
= fOptions
.shouldExport(name
);
400 atom
.setScope(ObjectFile::Atom::scopeLinkageUnit
);
405 // record section orders so output file can have same order
406 atom
.setSection(Section::find(atom
.getSectionName(), atom
.getSegment().getName(), atom
.isZeroFill()));
408 // assign order in which this atom was originally seen
409 if ( atom
.getSortOrder() == 0 )
410 fNextSortOrder
= atom
.setSortOrder(fNextSortOrder
);
413 inline void Linker::addAtoms(std::vector
<class ObjectFile::Atom
*>& atoms
)
415 for (std::vector
<ObjectFile::Atom
*>::iterator it
=atoms
.begin(); it
!= atoms
.end(); it
++) {
420 void Linker::buildAtomList()
422 // add initial undefines from -u option
423 std::vector
<const char*>& initialUndefines
= fOptions
.initialUndefines();
424 for (std::vector
<const char*>::iterator it
=initialUndefines
.begin(); it
!= initialUndefines
.end(); it
++) {
425 fGlobalSymbolTable
.require(*it
);
428 // writer can contribute atoms
429 this->addAtoms(fOutputFile
->getAtoms());
431 // each reader contributes atoms
432 const int readerCount
= fInputFiles
.size();
433 for (int i
=0; i
< readerCount
; ++i
) {
434 this->addAtoms(fInputFiles
[i
]->getAtoms());
437 // extra command line section always at end
438 std::vector
<Options::ExtraSection
>& extraSections
= fOptions
.extraSections();
439 for( std::vector
<Options::ExtraSection
>::iterator it
=extraSections
.begin(); it
!= extraSections
.end(); ++it
) {
440 this->addAtoms(SectCreate::MakeReader(it
->segmentName
, it
->sectionName
, it
->path
, it
->data
, it
->dataLen
)->getAtoms());
444 void Linker::loadUndefines()
446 // keep looping until no more undefines were added in last loop
447 unsigned int undefineCount
= 0xFFFFFFFF;
448 while ( undefineCount
!= fGlobalSymbolTable
.getRequireCount() ) {
449 undefineCount
= fGlobalSymbolTable
.getRequireCount();
450 std::vector
<const char*> undefineNames
;
451 fGlobalSymbolTable
.getNeededNames(true, undefineNames
);
452 const int undefineCount
= undefineNames
.size();
453 for (int i
=0; i
< undefineCount
; ++i
) {
454 const char* name
= undefineNames
[i
];
455 ObjectFile::Atom
* possibleAtom
= fGlobalSymbolTable
.find(name
);
456 if ( (possibleAtom
== NULL
) || (possibleAtom
->isWeakDefinition() && (fOptions
.outputKind() != Options::kObjectFile
)) )
457 this->addJustInTimeAtoms(name
);
461 if ( fOptions
.outputKind() != Options::kObjectFile
) {
462 // error out on any remaining undefines
465 switch ( fOptions
.undefinedTreatment() ) {
466 case Options::kUndefinedError
:
468 case Options::kUndefinedDynamicLookup
:
471 case Options::kUndefinedWarning
:
474 case Options::kUndefinedSuppress
:
479 std::vector
<const char*> unresolvableUndefines
;
480 fGlobalSymbolTable
.getNeededNames(false, unresolvableUndefines
);
481 const int unresolvableCount
= unresolvableUndefines
.size();
482 if ( unresolvableCount
!= 0 ) {
484 fprintf(stderr
, "can't resolve symbols:\n");
485 for (int i
=0; i
< unresolvableCount
; ++i
) {
486 const char* name
= unresolvableUndefines
[i
];
487 const unsigned int nameLen
= strlen(name
);
488 fprintf(stderr
, " %s, referenced from:\n", name
);
489 char stubName
[nameLen
+6];
490 strcpy(stubName
, name
);
491 strcat(stubName
, "$stub");
492 char nonLazyName
[nameLen
+16];
493 strcpy(nonLazyName
, name
);
494 strcat(nonLazyName
, "$non_lazy_ptr");
495 ObjectFile::Atom
* lastStubAtomWithUnresolved
= NULL
;
496 ObjectFile::Atom
* lastNonLazyAtomWithUnresolved
= NULL
;
497 for (std::vector
<ObjectFile::Atom
*>::iterator it
=fAllAtoms
.begin(); it
!= fAllAtoms
.end(); it
++) {
498 ObjectFile::Atom
* atom
= *it
;
499 std::vector
<class ObjectFile::Reference
*>& references
= atom
->getReferences();
500 for (std::vector
<ObjectFile::Reference
*>::iterator rit
=references
.begin(); rit
!= references
.end(); rit
++) {
501 ObjectFile::Reference
* reference
= *rit
;
502 if ( reference
->isUnbound() ) {
503 if ( (atom
!= lastStubAtomWithUnresolved
) && (strcmp(reference
->getTargetName(), stubName
) == 0) ) {
504 const char* path
= atom
->getFile()->getPath();
505 const char* shortPath
= strrchr(path
, '/');
506 if ( shortPath
== NULL
)
509 shortPath
= &shortPath
[1];
510 fprintf(stderr
, " %s in %s\n", atom
->getDisplayName(), shortPath
);
511 lastStubAtomWithUnresolved
= atom
;
513 else if ( (atom
!= lastNonLazyAtomWithUnresolved
) && (strcmp(reference
->getTargetName(), nonLazyName
) == 0) ) {
514 const char* path
= atom
->getFile()->getPath();
515 const char* shortPath
= strrchr(path
, '/');
516 if ( shortPath
== NULL
)
519 shortPath
= &shortPath
[1];
520 fprintf(stderr
, " %s in %s\n", atom
->getDisplayName(), shortPath
);
521 lastNonLazyAtomWithUnresolved
= atom
;
529 throw "symbol(s) not found";
532 // now verify that -init routine exists
533 if ( fOptions
.initFunctionName() != NULL
) {
534 if ( fGlobalSymbolTable
.find(fOptions
.initFunctionName()) == NULL
)
535 throwf("symbol %s not found for -init", fOptions
.initFunctionName());
542 void Linker::addJustInTimeAtoms(const char* name
)
544 // give writer a crack at it
545 ObjectFile::Atom
* atom
= fOutputFile
->getUndefinedProxyAtom(name
);
546 if ( atom
!= NULL
) {
547 this->addAtom(*atom
);
550 // give direct readers a chance
551 const int readerCount
= fInputFiles
.size();
552 for (int i
=0; i
< readerCount
; ++i
) {
553 // if this reader is a static archive that has the symbol we need, pull in all atoms in that module
554 // if this reader is a dylib that exports the symbol we need, have it synthesize an atom for us.
555 std::vector
<class ObjectFile::Atom
*>* atoms
= fInputFiles
[i
]->getJustInTimeAtomsFor(name
);
556 if ( atoms
!= NULL
) {
557 this->addAtoms(*atoms
);
559 return; // found a definition, no need to search anymore
560 //fprintf(stderr, "addJustInTimeAtoms(%s) => found in file #%d\n", name, i);
564 // give indirect readers a chance
565 for (std::list
<IndirectLibrary
>::iterator it
=fIndirectDynamicLibraries
.begin(); it
!= fIndirectDynamicLibraries
.end(); it
++) {
566 ObjectFile::Reader
* reader
= it
->reader
;
567 if ( reader
!= NULL
) {
568 std::vector
<class ObjectFile::Atom
*>* atoms
= reader
->getJustInTimeAtomsFor(name
);
569 if ( atoms
!= NULL
) {
570 this->addAtoms(*atoms
);
573 //fprintf(stderr, "addJustInTimeAtoms(%s) => found in file #%d\n", name, i);
580 void Linker::resolve(ObjectFile::Reference
* reference
)
582 ObjectFile::Atom
* target
= NULL
;
583 const char* targetName
= reference
->getTargetName();
584 const int targetNameLen
= strlen(targetName
);
585 if ( (targetNameLen
> 5) && (strcmp(&targetName
[targetNameLen
-5], "$stub") == 0) ) {
586 // when looking up "_foo$stub", first look for "_foo"
587 char nonStubTarget
[targetNameLen
+1];
588 strcpy(nonStubTarget
, targetName
);
589 nonStubTarget
[targetNameLen
-5] = '\0';
590 // unless interposing and the symbol is exported
591 if ( !fOptions
.interposable() || !fOptions
.shouldExport(nonStubTarget
) ) {
592 target
= fGlobalSymbolTable
.find(nonStubTarget
);
593 // also need indirection to all exported weak symbols for C++ support
594 if ( (target
!= NULL
) && !target
->isImportProxy() && (!target
->isWeakDefinition() || (target
->getScope() != ObjectFile::Atom::scopeGlobal
)) ) {
595 reference
->setTarget(*target
);
596 // mark stub as no longer being needed
597 ObjectFile::Atom
* stub
= fGlobalSymbolTable
.find(targetName
);
598 if ( stub
!= NULL
) {
599 char lazySymbol
[targetNameLen
+8];
600 strcpy(lazySymbol
, nonStubTarget
);
601 strcat(lazySymbol
, "$lazy_ptr");
602 ObjectFile::Atom
* lazyPtr
= fGlobalSymbolTable
.find(lazySymbol
);
603 fDeadAtoms
.insert(stub
);
604 if ( lazyPtr
!= NULL
)
605 fDeadAtoms
.insert(lazyPtr
);
612 // look in global symbol table
613 target
= fGlobalSymbolTable
.find(targetName
);
614 if ( target
== NULL
) {
615 fprintf(stderr
, "can't resolve: %s\n", targetName
);
617 reference
->setTarget(*target
);
619 // handle weak-imports
620 if ( target
->isImportProxy() ) {
621 bool mismatch
= false;
622 if ( reference
->isWeakReference() ) {
623 switch(target
->getImportWeakness()) {
624 case ObjectFile::Atom::kWeakUnset
:
625 target
->setImportWeakness(true);
627 case ObjectFile::Atom::kWeakImport
:
629 case ObjectFile::Atom::kNonWeakImport
:
635 switch(target
->getImportWeakness()) {
636 case ObjectFile::Atom::kWeakUnset
:
637 target
->setImportWeakness(false);
639 case ObjectFile::Atom::kWeakImport
:
642 case ObjectFile::Atom::kNonWeakImport
:
647 switch ( fOptions
.weakReferenceMismatchTreatment() ) {
648 case Options::kWeakReferenceMismatchError
:
649 throwf("mismatching weak references for symbol: %s", target
->getName());
650 case Options::kWeakReferenceMismatchWeak
:
651 target
->setImportWeakness(true);
653 case Options::kWeakReferenceMismatchNonWeak
:
654 target
->setImportWeakness(false);
660 // handle references that have two (from and to) targets
661 if ( reference
->isUnbound() ) {
662 const char* fromTargetName
= reference
->getFromTargetName();
663 ObjectFile::Atom
* fromTarget
= fGlobalSymbolTable
.find(fromTargetName
);
664 if ( target
== NULL
) {
665 fprintf(stderr
, "can't resolve: %s\n", fromTargetName
);
667 reference
->setFromTarget(*fromTarget
);
672 void Linker::resolveReferences()
674 // note: the atom list may grow during this loop as libraries supply needed atoms
675 for (unsigned int j
=0; j
< fAllAtoms
.size(); ++j
) {
676 ObjectFile::Atom
* atom
= fAllAtoms
[j
];
677 std::vector
<class ObjectFile::Reference
*>& references
= atom
->getReferences();
678 for (std::vector
<ObjectFile::Reference
*>::iterator it
=references
.begin(); it
!= references
.end(); it
++) {
679 ObjectFile::Reference
* reference
= *it
;
680 if ( reference
->isUnbound() ) {
681 this->resolve(reference
);
690 InSet(std::set
<ObjectFile::Atom
*>& deadAtoms
) : fDeadAtoms(deadAtoms
) {}
692 bool operator()(ObjectFile::Atom
*& atom
) const {
693 return ( fDeadAtoms
.count(atom
) != 0 );
697 std::set
<ObjectFile::Atom
*>& fDeadAtoms
;
701 void Linker::deadStrip()
703 //printf("Stripping atoms:\n");
704 //for (std::set<ObjectFile::Atom*>::iterator it=fDeadAtoms.begin(); it != fDeadAtoms.end(); it++) {
705 // printf("\t%s\n", (*it)->getDisplayName());
708 // for now, just remove atoms weak atoms that have been overridden
709 fAllAtoms
.erase(std::remove_if(fAllAtoms
.begin(), fAllAtoms
.end(), InSet(fDeadAtoms
)), fAllAtoms
.end());
714 void Linker::sortAtoms()
716 Section::assignIndexes();
717 std::sort(fAllAtoms
.begin(), fAllAtoms
.end(), Linker::AtomSorter());
722 // make sure given addresses are within reach of branches, etc
723 void Linker::tweakLayout()
731 void Linker::writeOutput()
733 // if main executable, find entry point atom
734 ObjectFile::Atom
* entryPoint
;
735 switch ( fOptions
.outputKind() ) {
736 case Options::kDynamicExecutable
:
737 case Options::kStaticExecutable
:
739 entryPoint
= fGlobalSymbolTable
.find(fOptions
.entryName());
740 if ( entryPoint
== NULL
) {
741 throwf("could not find entry point: %s", fOptions
.entryName());
744 case Options::kDynamicLibrary
:
745 if ( fOptions
.initFunctionName() != NULL
) {
746 entryPoint
= fGlobalSymbolTable
.find(fOptions
.initFunctionName());
747 if ( entryPoint
== NULL
) {
748 throwf("could not find -init function: %s", fOptions
.initFunctionName());
756 // tell writer about each segment's atoms
757 fOutputFile
->write(fAllAtoms
, entryPoint
);
763 ObjectFile::Reader
* Linker::createReader(const Options::FileInfo
& info
)
766 uint64_t len
= info
.fileLen
;
767 int fd
= ::open(info
.path
, O_RDONLY
, 0);
769 throw "can't open file";
770 if ( info
.fileLen
< 20 )
771 throw "file too small";
772 char* p
= (char*)::mmap(NULL
, info
.fileLen
, PROT_READ
, MAP_FILE
, fd
, 0);
773 if ( p
== (char*)(-1) )
774 throw "can't map file";
777 // if fat file, skip to architecture we want
778 const mach_header
* mh
= (mach_header
*)p
;
779 if ( mh
->magic
== OSSwapBigToHostInt32(FAT_MAGIC
) ) {
780 // Fat header is always big-endian
781 const struct fat_header
* fh
= (struct fat_header
*)p
;
782 const struct fat_arch
* archs
= (struct fat_arch
*)(p
+ sizeof(struct fat_header
));
783 for (unsigned long i
=0; i
< OSSwapBigToHostInt32(fh
->nfat_arch
); ++i
) {
784 if ( OSSwapBigToHostInt32(archs
[i
].cputype
) == (uint32_t)fOptions
.architecture() ) {
785 mh
= (struct mach_header
*)((char*)p
+ OSSwapBigToHostInt32(archs
[i
].offset
));
786 len
= OSSwapBigToHostInt32(archs
[i
].size
);
792 if ( mh
->magic
== OSSwapBigToHostInt32(FAT_MAGIC
) ) {
793 const char* archName
= "unknown";
794 switch (fOptions
.architecture()) {
795 case CPU_TYPE_POWERPC
:
798 case CPU_TYPE_POWERPC64
:
805 throwf("missing required architecture %s in fat file", archName
);
808 // pull out cpu-type and file-type in endian-safe way
809 cpu_type_t cpuType
= 0;
810 uint32_t fileType
= 0;
811 if ( mh
->magic
== MH_MAGIC
) {
812 fileType
= mh
->filetype
;
813 cpuType
= mh
->cputype
;
815 else if ( mh
->magic
== OSSwapInt32(MH_MAGIC
) ) {
816 fileType
= OSSwapInt32(mh
->filetype
);
817 cpuType
= OSSwapInt32(mh
->cputype
);
819 else if ( mh
->magic
== MH_MAGIC_64
) {
820 fileType
= ((mach_header_64
*)mh
)->filetype
;
821 cpuType
= ((mach_header_64
*)mh
)->cputype
;
823 else if ( mh
->magic
== OSSwapInt32(MH_MAGIC_64
) ) {
824 fileType
= OSSwapInt32(((mach_header_64
*)mh
)->filetype
);
825 cpuType
= OSSwapInt32(((mach_header_64
*)mh
)->cputype
);
827 else if ( strncmp((const char*)mh
, "!<arch>\n", 8) == 0 ) {
829 switch ( fOptions
.architecture() ) {
830 case CPU_TYPE_POWERPC
:
831 return ppc::ObjectFileArchiveMachO::MakeReader((const uint8_t*)mh
, len
, info
.path
, fOptions
.readerOptions());
832 case CPU_TYPE_POWERPC64
:
833 return ppc64::ObjectFileArchiveMachO::MakeReader((const uint8_t*)mh
, len
, info
.path
, fOptions
.readerOptions());
835 return i386::ObjectFileArchiveMachO::MakeReader((const uint8_t*)mh
, len
, info
.path
, fOptions
.readerOptions());
837 throw "no matching archive reader";
840 throw "unknown file type";
843 // bail out if cpu-type does not match requrired architecture
844 if ( fOptions
.architecture() == cpuType
) {
845 // make appropriate reader object
846 if ( fileType
== MH_OBJECT
) {
848 case CPU_TYPE_POWERPC
:
849 return ppc::ObjectFileMachO::MakeReader((class ppc::macho_header
*)mh
, info
.path
, fOptions
.readerOptions());
850 case CPU_TYPE_POWERPC64
:
851 return ppc64::ObjectFileMachO::MakeReader((class ppc64::macho_header
*)mh
, info
.path
, fOptions
.readerOptions());
853 return i386::ObjectFileMachO::MakeReader((class i386::macho_header
*)mh
, info
.path
, fOptions
.readerOptions());
855 throw "wrong architecture in object file";
858 else if ( fileType
== MH_DYLIB
) {
859 ObjectFile::Reader
* dylibReader
= NULL
;
861 case CPU_TYPE_POWERPC
:
862 dylibReader
= ppc::ObjectFileDylibMachO::MakeReader((class ppc::macho_header
*)mh
, info
.path
, fOptions
.readerOptions());
864 case CPU_TYPE_POWERPC64
:
865 dylibReader
= ppc64::ObjectFileDylibMachO::MakeReader((class ppc64::macho_header
*)mh
, info
.path
, fOptions
.readerOptions());
868 dylibReader
= i386::ObjectFileDylibMachO::MakeReader((class i386::macho_header
*)mh
, info
.path
, fOptions
.readerOptions());
871 throw "wrong architecture in dylib";
873 this->addDylib(dylibReader
, info
);
876 throw "unknown mach-o file type";
879 throw "file does not contain requested architecture";
885 void Linker::createReaders()
887 std::vector
<Options::FileInfo
>& files
= fOptions
.getInputFiles();
888 const int count
= files
.size();
890 throw "no object files specified";
891 // add all direct object, archives, and dylibs
892 for (int i
=0; i
< count
; ++i
) {
893 Options::FileInfo
& entry
= files
[i
];
894 // ignore /usr/lib/dyld on command line in crt.o build
895 if ( strcmp(entry
.path
, "/usr/lib/dyld") != 0 ) {
897 this->addInputFile(this->createReader(entry
));
899 catch (const char* msg
) {
900 if ( strstr(msg
, "architecture") != NULL
) {
901 if ( fOptions
.ignoreOtherArchInputFiles() ) {
902 // ignore, because this is about an architecture not in use
905 fprintf(stderr
, "ld64 warning: in %s, %s\n", entry
.path
, msg
);
909 throwf("in %s, %s", entry
.path
, msg
);
915 // add first level of indirect dylibs
916 fDirectLibrariesComplete
= true;
917 for (std::vector
<ExecutableFile::DyLibUsed
>::iterator it
=fDynamicLibraries
.begin(); it
!= fDynamicLibraries
.end(); it
++) {
918 this->addIndirectLibraries(it
->reader
);
921 // indirect handling depends on namespace
922 switch ( fOptions
.nameSpace() ) {
923 case Options::kFlatNameSpace
:
924 case Options::kForceFlatNameSpace
:
925 // with flat namespace, blindly load all indirect libraries
926 // the indirect list will grow as indirect libraries are loaded
927 for (std::list
<IndirectLibrary
>::iterator it
=fIndirectDynamicLibraries
.begin(); it
!= fIndirectDynamicLibraries
.end(); it
++) {
928 struct stat statBuffer
;
929 if ( stat(it
->path
, &statBuffer
) == 0 ) {
930 Options::FileInfo info
;
931 info
.path
= it
->path
;
932 info
.fileLen
= statBuffer
.st_size
;
933 info
.options
.fWeakImport
= false;
934 info
.options
.fReExport
= false;
935 info
.options
.fInstallPathOverride
= NULL
;
936 it
->reader
= this->createReader(info
);
939 fprintf(stderr
, "ld64 warning: indirect library not found: %s\n", it
->path
);
944 case Options::kTwoLevelNameSpace
:
945 // with two-level namespace we only want to use indirect libraries that are re-exported through a library that is used
947 bool indirectAdded
= true;
948 while ( indirectAdded
) {
949 indirectAdded
= false;
950 // instantiate a reader for each indirect library and try to find parent that re-exports it
951 for (std::list
<IndirectLibrary
>::iterator it
=fIndirectDynamicLibraries
.begin(); it
!= fIndirectDynamicLibraries
.end(); it
++) {
952 if ( it
->reader
== NULL
) {
954 struct stat statBuffer
;
955 if ( stat(it
->path
, &statBuffer
) != 0 )
956 throw "file not found";
958 Options::FileInfo info
;
959 info
.path
= it
->path
;
960 info
.fileLen
= statBuffer
.st_size
;
961 info
.options
.fWeakImport
= false;
962 info
.options
.fReExport
= false;
963 info
.options
.fInstallPathOverride
= NULL
;
964 it
->reader
= this->createReader(info
);
965 indirectAdded
= true;
967 catch (const char* msg
) {
968 fprintf(stderr
, "ld64 warning: indirect library %s could not be loaded: %s\n", it
->path
, msg
);
971 // if an indirect library does not have an assigned parent, look for one
972 if ( (it
->reader
!= NULL
) && (it
->reExportParent
== NULL
) ) {
973 // ask each parent if they re-export this dylib
974 for (std::set
<ObjectFile::Reader
*>::iterator pit
=it
->parents
.begin(); pit
!= it
->parents
.end(); pit
++) {
975 if ( (*pit
)->reExports(it
->reader
) ) {
976 it
->reExportParent
= *pit
;
987 // add relevant indirect libraries to the end of fDynamicLibraries
988 for (std::list
<IndirectLibrary
>::iterator it
=fIndirectDynamicLibraries
.begin(); it
!= fIndirectDynamicLibraries
.end(); it
++) {
989 if ( (it
->reExportParent
!= NULL
) || (fOptions
.nameSpace() != Options::kTwoLevelNameSpace
) ) {
990 ExecutableFile::DyLibUsed dylibInfo
;
991 dylibInfo
.reader
= it
->reader
;
992 dylibInfo
.options
.fWeakImport
= false;
993 dylibInfo
.options
.fReExport
= false;
994 dylibInfo
.options
.fInstallPathOverride
= NULL
;
995 dylibInfo
.indirect
= true;
996 dylibInfo
.directReader
= it
->reExportParent
;
997 fDynamicLibraries
.push_back(dylibInfo
);
998 if ( fOptions
.readerOptions().fTraceIndirectDylibs
)
999 printf("[Logging for Build & Integration] Used indirect dynamic library: %s\n", it
->path
);
1006 void Linker::addDylib(ObjectFile::Reader
* reader
, const Options::FileInfo
& info
)
1008 if ( fDirectLibrariesComplete
) {
1009 this->addIndirectLibraries(reader
);
1012 if ( fOptions
.readerOptions().fTraceDylibs
)
1013 printf("[Logging for Build & Integration] Used dynamic library: %s\n", reader
->getPath());
1014 ExecutableFile::DyLibUsed dylibInfo
;
1015 dylibInfo
.reader
= reader
;
1016 dylibInfo
.options
= info
.options
;
1017 dylibInfo
.indirect
= false;
1018 dylibInfo
.directReader
= NULL
;
1019 fDynamicLibraries
.push_back(dylibInfo
);
1024 void Linker::addIndirectLibraries(ObjectFile::Reader
* reader
)
1026 std::vector
<const char*>* dependentLibs
= reader
->getDependentLibraryPaths();
1027 if ( dependentLibs
!= NULL
) {
1028 for (std::vector
<const char*>::iterator it
=dependentLibs
->begin(); it
!= dependentLibs
->end(); it
++) {
1029 if ( this->haveDirectLibrary(*it
) ) {
1030 // do nothing, direct library already exists
1032 else if ( this->haveIndirectLibrary(*it
, reader
) ) {
1033 // side effect of haveIndirectLibrary() added reader to parent list
1036 // add to list of indirect libraries
1037 IndirectLibrary indirectLib
;
1038 indirectLib
.path
= *it
;
1039 indirectLib
.fileLen
= 0;
1040 indirectLib
.reader
= NULL
;
1041 indirectLib
.parents
.insert(reader
);
1042 indirectLib
.reExportParent
= NULL
;
1043 fIndirectDynamicLibraries
.push_back(indirectLib
);
1044 //fprintf(stderr, "add indirect library: %s\n", *it);
1050 bool Linker::haveIndirectLibrary(const char* path
, ObjectFile::Reader
* parentReader
)
1052 for (std::list
<IndirectLibrary
>::iterator it
=fIndirectDynamicLibraries
.begin(); it
!= fIndirectDynamicLibraries
.end(); it
++) {
1053 if ( strcmp(path
, it
->path
) == 0 ) {
1054 it
->parents
.insert(parentReader
);
1057 if ( it
->reader
!= NULL
) {
1058 const char* installPath
= it
->reader
->getInstallPath();
1059 if ( (installPath
!= NULL
) && (strcmp(path
, installPath
) == 0) )
1066 bool Linker::haveDirectLibrary(const char* path
)
1068 for (std::vector
<ExecutableFile::DyLibUsed
>::iterator it
=fDynamicLibraries
.begin(); it
!= fDynamicLibraries
.end(); it
++) {
1069 if ( strcmp(path
, it
->reader
->getPath()) == 0 )
1071 const char* installPath
= it
->reader
->getInstallPath();
1072 if ( (installPath
!= NULL
) && (strcmp(path
, installPath
) == 0) )
1081 void Linker::createWriter()
1083 const char* path
= fOptions
.getOutputFilePath();
1084 switch ( fOptions
.architecture() ) {
1085 case CPU_TYPE_POWERPC
:
1086 this->setOutputFile(ppc::ExecutableFileMachO::MakeWriter(path
, fOptions
, fDynamicLibraries
));
1088 case CPU_TYPE_POWERPC64
:
1089 this->setOutputFile(ppc64::ExecutableFileMachO::MakeWriter(path
, fOptions
, fDynamicLibraries
));
1092 this->setOutputFile(i386::ExecutableFileMachO::MakeWriter(path
, fOptions
, fDynamicLibraries
));
1095 throw "unknown architecture";
1100 Linker::SymbolTable::SymbolTable(Linker
& owner
)
1101 : fOwner(owner
), fRequireCount(0)
1105 void Linker::SymbolTable::require(const char* name
)
1107 //fprintf(stderr, "require(%s)\n", name);
1108 Mapper::iterator pos
= fTable
.find(name
);
1109 if ( pos
== fTable
.end() ) {
1110 fTable
[name
] = NULL
;
1115 bool Linker::SymbolTable::add(ObjectFile::Atom
& atom
)
1117 const bool log
= false;
1118 const char* name
= atom
.getName();
1119 //fprintf(stderr, "map.add(%p: %s => %p)\n", &fTable, name, &atom);
1120 Mapper::iterator pos
= fTable
.find(name
);
1121 if ( pos
!= fTable
.end() ) {
1122 ObjectFile::Atom
* existingAtom
= pos
->second
;
1123 if ( existingAtom
!= NULL
) {
1124 if ( existingAtom
->isTentativeDefinition() ) {
1125 if ( atom
.isTentativeDefinition() ) {
1126 if ( atom
.getSize() > existingAtom
->getSize() ) {
1127 // replace common-symbol atom with another larger common-symbol
1128 if ( fOwner
.fOptions
.warnCommons() )
1129 fprintf(stderr
, "ld64: replacing common symbol %s size %lld from %s with larger symbol size %lld from %s\n",
1130 existingAtom
->getName(), existingAtom
->getSize(), existingAtom
->getFile()->getPath(), atom
.getSize(), atom
.getFile()->getPath());
1131 fOwner
.fDeadAtoms
.insert(existingAtom
);
1132 fTable
[name
] = &atom
;
1136 // keep existing common-symbol atom
1137 if ( fOwner
.fOptions
.warnCommons() ) {
1138 if ( atom
.getSize() == existingAtom
->getSize() )
1139 fprintf(stderr
, "ld64: ignoring common symbol %s from %s because already have common from %s with same size\n",
1140 atom
.getName(), atom
.getFile()->getPath(), existingAtom
->getFile()->getPath());
1142 fprintf(stderr
, "ld64: ignoring common symbol %s size %lld from %s because already have larger symbol size %lld from %s\n",
1143 atom
.getName(), atom
.getSize(), atom
.getFile()->getPath(), existingAtom
->getSize(), existingAtom
->getFile()->getPath());
1145 fOwner
.fDeadAtoms
.insert(&atom
);
1150 // have common symbol, now found true defintion
1151 if ( atom
.isImportProxy() ) {
1152 // definition is in a dylib, so commons-mode decides how to handle
1153 switch ( fOwner
.fOptions
.commonsMode() ) {
1154 case Options::kCommonsIgnoreDylibs
:
1155 if ( fOwner
.fOptions
.warnCommons() )
1156 fprintf(stderr
, "ld64: using common symbol %s from %s and ignoring defintion from dylib %s\n",
1157 existingAtom
->getName(), existingAtom
->getFile()->getPath(), atom
.getFile()->getPath());
1158 fOwner
.fDeadAtoms
.insert(&atom
);
1160 case Options::kCommonsOverriddenByDylibs
:
1161 if ( fOwner
.fOptions
.warnCommons() )
1162 fprintf(stderr
, "ld64: replacing common symbol %s from %s with true definition from %s\n",
1163 existingAtom
->getName(), existingAtom
->getFile()->getPath(), atom
.getFile()->getPath());
1164 fOwner
.fDeadAtoms
.insert(existingAtom
);
1165 fTable
[name
] = &atom
;
1167 case Options::kCommonsConflictsDylibsError
:
1168 throwf("common symbol %s from %s conflicts with defintion from dylib %s",
1169 existingAtom
->getName(), existingAtom
->getFile()->getPath(), atom
.getFile()->getPath());
1173 // replace common-symbol atom with true definition from .o file
1174 if ( fOwner
.fOptions
.warnCommons() ) {
1175 if ( atom
.getSize() < existingAtom
->getSize() )
1176 fprintf(stderr
, "ld64: warning: replacing common symbol %s size %lld from %s with smaller true definition size %lld from %s\n",
1177 existingAtom
->getName(), existingAtom
->getSize(), existingAtom
->getFile()->getPath(), atom
.getSize(), atom
.getFile()->getPath());
1179 fprintf(stderr
, "ld64: replacing common symbol %s from %s with true definition from %s\n",
1180 existingAtom
->getName(), existingAtom
->getFile()->getPath(), atom
.getFile()->getPath());
1182 fOwner
.fDeadAtoms
.insert(existingAtom
);
1183 fTable
[name
] = &atom
;
1188 else if ( atom
.isTentativeDefinition() ) {
1189 // keep existing true definition, ignore new tentative definition
1190 if ( fOwner
.fOptions
.warnCommons() ) {
1191 if ( atom
.getSize() > existingAtom
->getSize() )
1192 fprintf(stderr
, "ld64: warning: ignoring common symbol %s size %lld from %s because already have definition from %s size %lld, even though definition is smaller\n",
1193 atom
.getName(), atom
.getSize(), atom
.getFile()->getPath(), existingAtom
->getFile()->getPath(), existingAtom
->getSize());
1195 fprintf(stderr
, "ld64: ignoring common symbol %s from %s because already have definition from %s\n",
1196 atom
.getName(), atom
.getFile()->getPath(), existingAtom
->getFile()->getPath());
1198 fOwner
.fDeadAtoms
.insert(&atom
);
1202 // neither existing nor new atom are tentative definitions
1203 // if existing is weak, we may replace it
1204 if ( existingAtom
->isWeakDefinition() ) {
1205 if ( atom
.isImportProxy() ) {
1206 // keep weak definition even though one exists in a dylib, because coalescing means dylib's copy may not be used
1207 if ( log
) fprintf(stderr
, "keep weak atom even though also in a dylib: %s\n", atom
.getName());
1208 fOwner
.fDeadAtoms
.insert(&atom
);
1211 else if ( atom
.isWeakDefinition() ) {
1212 // have another weak atom, use existing, mark new as dead
1213 if ( log
) fprintf(stderr
, "already have weak atom: %s\n", atom
.getName());
1214 fOwner
.fDeadAtoms
.insert(&atom
);
1218 // replace weak atom with non-weak atom
1219 if ( log
) fprintf(stderr
, "replacing weak atom %p from %s with %p from %s: %s\n", existingAtom
, existingAtom
->getFile()->getPath(), &atom
, atom
.getFile()->getPath(), atom
.getName());
1220 fOwner
.fDeadAtoms
.insert(existingAtom
);
1221 fTable
[name
] = &atom
;
1226 if ( atom
.isWeakDefinition() ) {
1227 // ignore new weak atom, because we already have a non-weak one
1230 if ( atom
.isCoalesableByName() && existingAtom
->isCoalesableByName() ) {
1231 // both coalesable, so ignore duplicate
1234 fprintf(stderr
, "duplicate symbol %s in %s and %s\n", name
, atom
.getFile()->getPath(), existingAtom
->getFile()->getPath());
1237 fTable
[name
] = &atom
;
1241 ObjectFile::Atom
* Linker::SymbolTable::find(const char* name
)
1243 Mapper::iterator pos
= fTable
.find(name
);
1244 if ( pos
!= fTable
.end() ) {
1251 void Linker::SymbolTable::getNeededNames(bool andWeakDefintions
, std::vector
<const char*>& undefines
)
1253 for (Mapper::iterator it
=fTable
.begin(); it
!= fTable
.end(); it
++) {
1254 if ( (it
->second
== NULL
) || (andWeakDefintions
&& it
->second
->isWeakDefinition()) ) {
1255 undefines
.push_back(it
->first
);
1263 bool Linker::AtomSorter::operator()(ObjectFile::Atom
* left
, ObjectFile::Atom
* right
)
1265 // first sort by section order (which is already sorted by segment)
1266 unsigned int leftSectionIndex
= left
->getSection()->getIndex();
1267 unsigned int rightSectionIndex
= right
->getSection()->getIndex();
1268 if ( leftSectionIndex
!= rightSectionIndex
)
1269 return (leftSectionIndex
< rightSectionIndex
);
1271 // with a section, sort by original atom order (.o file order and atom order in .o files)
1272 return left
->getSortOrder() < right
->getSortOrder();
1276 int main(int argc
, const char* argv
[])
1279 // create linker object given command line arguments
1280 Linker
ld(argc
, argv
);
1282 // open all input files
1291 catch (const char* msg
) {
1292 fprintf(stderr
, "ld64 failed: %s\n", msg
);