97-2
[darwin-xtools.git] / ld64 / src / ld / ld.cpp
blob6b6d1149d1ea7742ee2e9a69e371b9c5a4974e96
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-*
2 * Copyright (c) 2005-2009 Apple 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
11 * file.
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 // start temp HACK for cross builds
25 extern "C" double log2 ( double );
26 #define __MATH__
27 // end temp HACK for cross builds
30 #include <stdlib.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <sys/mman.h>
34 #include <sys/sysctl.h>
35 #include <fcntl.h>
36 #include <errno.h>
37 #include <limits.h>
38 #include <unistd.h>
39 #include <mach/mach_time.h>
40 #include <mach/vm_statistics.h>
41 #include <mach/mach_init.h>
42 #include <mach/mach_host.h>
43 #include <dlfcn.h>
45 #include <string>
46 #include <map>
47 #include <set>
48 #include <string>
49 #include <vector>
50 #include <list>
51 #include <algorithm>
52 #include <ext/hash_map>
53 #include <dlfcn.h>
54 #include <AvailabilityMacros.h>
56 #include "configure.h"
57 #include "Options.h"
59 #include "ObjectFile.h"
61 #include "MachOReaderRelocatable.hpp"
62 #include "ArchiveReader.hpp"
63 #include "MachOReaderDylib.hpp"
64 #include "MachOWriterExecutable.hpp"
67 #if LTO_SUPPORT
68 #include "LTOReader.hpp"
69 #endif
71 #include "OpaqueSection.hpp"
74 class CStringComparor
76 public:
77 bool operator()(const char* left, const char* right) const { return (strcmp(left, right) < 0); }
80 class CStringEquals
82 public:
83 bool operator()(const char* left, const char* right) const { return (strcmp(left, right) == 0); }
86 class Section : public ObjectFile::Section
88 public:
89 static Section* find(const char* sectionName, const char* segmentName, bool zeroFill, bool untrustedZeroFill, bool createIfNeeded=true);
90 static void assignIndexes();
91 const char* getName() { return fSectionName; }
92 private:
93 Section(const char* sectionName, const char* segmentName, bool zeroFill, bool untrustedZeroFill);
95 struct Sorter {
96 static int segmentOrdinal(const char* segName);
97 bool operator()(Section* left, Section* right);
100 typedef __gnu_cxx::hash_map<const char*, uint32_t, __gnu_cxx::hash<const char*>, CStringEquals> NameToOrdinal;
101 typedef __gnu_cxx::hash_map<const char*, class Section*, __gnu_cxx::hash<const char*>, CStringEquals> NameToSection;
102 //typedef std::map<const char*, class Section*, CStringComparor> NameToSection;
104 char fSectionName[18];
105 char fSegmentName[18];
106 bool fZeroFill;
107 bool fUntrustedZeroFill;
109 static NameToSection fgMapping;
110 static std::vector<Section*> fgSections;
111 static NameToOrdinal fgSegmentDiscoverOrder;
114 Section::NameToSection Section::fgMapping;
115 std::vector<Section*> Section::fgSections;
116 Section::NameToOrdinal Section::fgSegmentDiscoverOrder;
118 Section::Section(const char* sectionName, const char* segmentName, bool zeroFill, bool untrustedZeroFill)
119 : fZeroFill(zeroFill), fUntrustedZeroFill(untrustedZeroFill)
121 strlcpy(fSectionName, sectionName, sizeof(fSectionName));
122 strlcpy(fSegmentName, segmentName, sizeof(fSegmentName));
124 this->fIndex = fgSections.size() + 20; // room for 20 standard sections
125 // special placement of some sections
126 if ( strcmp(segmentName, "__TEXT") == 0 ) {
127 // sort mach header and load commands to start of TEXT
128 if ( strcmp(sectionName, "._mach_header") == 0 )
129 this->fIndex = 1;
130 else if ( strcmp(sectionName, "._load_commands") == 0 )
131 this->fIndex = 2;
132 else if ( strcmp(sectionName, "._load_cmds_pad") == 0 )
133 this->fIndex = 3;
134 // sort __text after load commands
135 else if ( strcmp(sectionName, "__text") == 0 )
136 this->fIndex = 10;
137 // sort arm/ppc stubs after text to make branch islands feasible
138 else if ( strcmp(sectionName, "__picsymbolstub4") == 0 )
139 this->fIndex = 11;
140 else if ( strcmp(sectionName, "__symbol_stub4") == 0 )
141 this->fIndex = 11;
142 else if ( strcmp(sectionName, "__picsymbolstub1") == 0 )
143 this->fIndex = 11;
144 else if ( strcmp(sectionName, "__symbol_stub1") == 0 )
145 this->fIndex = 11;
146 // sort fast arm stubs to end of __TEXT to be close to lazy pointers
147 else if ( strcmp(sectionName, "__symbolstub1") == 0 )
148 this->fIndex = INT_MAX;
149 // sort unwind info to end of segment
150 else if ( strcmp(sectionName, "__eh_frame") == 0 )
151 this->fIndex = INT_MAX-1;
152 else if ( strcmp(sectionName, "__unwind_info") == 0 )
153 this->fIndex = INT_MAX-2;
154 else if ( strcmp(sectionName, "__gcc_except_tab") == 0 )
155 this->fIndex = INT_MAX-3;
157 else if ( strcmp(segmentName, "__DATA") == 0 ) {
158 // sort arm lazy symbol pointers that must be at start of __DATA
159 if ( strcmp(sectionName, "__lazy_symbol") == 0 )
160 this->fIndex = 0;
161 // sort sections dyld will touch to start of segment
162 else if ( strcmp(sectionName, "__dyld") == 0 )
163 this->fIndex = 1;
164 else if ( strcmp(sectionName, "__program_vars") == 0 )
165 this->fIndex = 1;
166 else if ( strcmp(sectionName, "__mod_init_func") == 0 )
167 this->fIndex = 2;
168 else if ( strcmp(sectionName, "__nl_symbol_ptr") == 0 )
169 this->fIndex = 3;
170 else if ( strcmp(sectionName, "__la_symbol_ptr") == 0 )
171 this->fIndex = 4;
172 else if ( strcmp(sectionName, "__const") == 0 )
173 this->fIndex = 5;
174 else if ( strcmp(sectionName, "__cfstring") == 0 )
175 this->fIndex = 6;
176 else if ( strcmp(sectionName, "__gcc_except_tab") == 0 )
177 this->fIndex = 7;
178 else if ( strcmp(sectionName, "__objc_data") == 0 )
179 this->fIndex = 8;
180 else if ( strcmp(sectionName, "__objc_msgrefs") == 0 )
181 this->fIndex = 9;
182 else if ( strcmp(sectionName, "__objc_protorefs") == 0 )
183 this->fIndex = 10;
184 else if ( strcmp(sectionName, "__objc_selrefs") == 0 )
185 this->fIndex = 11;
186 else if ( strcmp(sectionName, "__objc_classrefs") == 0 )
187 this->fIndex = 12;
188 else if ( strcmp(sectionName, "__objc_superrefs") == 0 )
189 this->fIndex = 13;
190 else if ( strcmp(sectionName, "__objc_const") == 0 )
191 this->fIndex = 14;
192 else if ( strcmp(sectionName, "__objc_classlist") == 0 )
193 this->fIndex = 15;
194 else if ( strcmp(sectionName, "__objc_nlclslist") == 0 )
195 this->fIndex = 16;
196 else if ( strcmp(sectionName, "__objc_catlist") == 0 )
197 this->fIndex = 17;
198 else if ( strcmp(sectionName, "__objc_protolist") == 0 )
199 this->fIndex = 18;
200 else if ( strcmp(sectionName, "__objc_imageinfo") == 0 )
201 this->fIndex = 19;
202 else if ( strcmp(sectionName, "__huge") == 0 )
203 this->fIndex = INT_MAX;
207 //fprintf(stderr, "new Section(%s, %s) => %p, %u\n", sectionName, segmentName, this, this->getIndex());
210 Section* Section::find(const char* sectionName, const char* segmentName, bool zeroFill, bool untrustedZeroFill, bool createIfNeeded)
212 NameToSection::iterator pos = fgMapping.find(sectionName);
213 if ( pos != fgMapping.end() ) {
214 if ( strcmp(pos->second->fSegmentName, segmentName) == 0 ) {
215 if ( !untrustedZeroFill && pos->second->fUntrustedZeroFill ) {
216 pos->second->fZeroFill = zeroFill;
217 pos->second->fUntrustedZeroFill = false;
219 return pos->second;
221 // otherwise same section name is used in different segments, look slow way
222 for (std::vector<Section*>::iterator it=fgSections.begin(); it != fgSections.end(); it++) {
223 if ( (strcmp((*it)->fSectionName, sectionName) == 0) && (strcmp((*it)->fSegmentName, segmentName) == 0) )
224 return *it;
228 if ( !createIfNeeded )
229 return NULL;
231 // does not exist, so make a new one
232 Section* sect = new Section(sectionName, segmentName, zeroFill, untrustedZeroFill);
233 fgMapping[sectionName] = sect;
234 fgSections.push_back(sect);
236 if ( (strcmp(sectionName, "__text") == 0) && (strcmp(segmentName, "__TEXT") == 0) ) {
237 // special case __StaticInit to be right after __text
238 find("__StaticInit", "__TEXT", false, true);
241 // remember segment discovery order
242 if ( fgSegmentDiscoverOrder.find(segmentName) == fgSegmentDiscoverOrder.end() )
243 fgSegmentDiscoverOrder[segmentName] = fgSegmentDiscoverOrder.size();
245 return sect;
248 int Section::Sorter::segmentOrdinal(const char* segName)
250 if ( strcmp(segName, "__HEADER") == 0 )
251 return 1;
252 if ( strcmp(segName, "__PAGEZERO") == 0 )
253 return 1;
254 if ( strcmp(segName, "__TEXT") == 0 )
255 return 2;
256 if ( strcmp(segName, "__DATA") == 0 )
257 return 3;
258 if ( strcmp(segName, "__OBJC") == 0 )
259 return 4;
260 if ( strcmp(segName, "__OBJC2") == 0 )
261 return 5;
262 if ( strcmp(segName, "__LINKEDIT") == 0 )
263 return INT_MAX; // linkedit segment should always sort last
264 else
265 return fgSegmentDiscoverOrder[segName]+6;
269 bool Section::Sorter::operator()(Section* left, Section* right)
271 // Segment is primary sort key
272 int leftSegOrdinal = segmentOrdinal(left->fSegmentName);
273 int rightSegOrdinal = segmentOrdinal(right->fSegmentName);
274 if ( leftSegOrdinal < rightSegOrdinal )
275 return true;
276 if ( leftSegOrdinal > rightSegOrdinal )
277 return false;
279 // zerofill section sort to the end
280 if ( !left->fZeroFill && right->fZeroFill )
281 return true;
282 if ( left->fZeroFill && !right->fZeroFill )
283 return false;
285 // section discovery order is last sort key
286 return left->fIndex < right->fIndex;
289 void Section::assignIndexes()
291 //printf("unsorted sections:\n");
292 //for (std::vector<Section*>::iterator it=fgSections.begin(); it != fgSections.end(); it++) {
293 // printf("section: name=%s, segment: name=%s, discovery order=%d\n", (*it)->fSectionName, (*it)->fSegmentName, (*it)->fIndex);
296 // sort it
297 std::sort(fgSections.begin(), fgSections.end(), Section::Sorter());
299 // assign correct section ordering to each Section object
300 unsigned int newOrder = 1;
301 for (std::vector<Section*>::iterator it=fgSections.begin(); it != fgSections.end(); it++)
302 (*it)->fIndex = newOrder++;
304 //printf("sorted sections:\n");
305 //for (std::vector<Section*>::iterator it=fgSections.begin(); it != fgSections.end(); it++) {
306 // printf("section: index=%d, obj=%p, name=%s\n", (*it)->fIndex, (*it), (*it)->fSectionName);
310 class Linker : public ObjectFile::Reader::DylibHander {
311 public:
312 Linker(int argc, const char* argv[]);
314 const char* getArchPrefix();
315 const char* architectureName();
316 bool showArchitectureInErrors();
317 bool isInferredArchitecture();
318 void createReaders();
319 void createWriter();
320 void addInputFile(ObjectFile::Reader* reader, const Options::FileInfo& );
321 void setOutputFile(ExecutableFile::Writer* writer);
322 void link();
323 void optimize();
325 // implemenation from ObjectFile::Reader::DylibHander
326 virtual ObjectFile::Reader* findDylib(const char* installPath, const char* fromPath);
328 private:
329 struct WhyLiveBackChain
331 WhyLiveBackChain* previous;
332 ObjectFile::Atom* referer;
335 ObjectFile::Reader* createReader(const Options::FileInfo&);
336 const char* fileArch(const void* p);
337 void addAtom(ObjectFile::Atom& atom);
338 void addAtoms(std::vector<class ObjectFile::Atom*>& atoms);
339 void buildAtomList();
340 void adjustScope();
341 void processDylibs();
342 void markDead(ObjectFile::Atom* atom);
343 void updateConstraints(ObjectFile::Reader* reader);
344 void loadAndResolve();
345 void processDTrace();
346 void checkObjC();
347 void addSynthesizedAtoms();
348 void loadUndefines();
349 void checkUndefines();
350 void resolveReferences();
351 void deadStripResolve();
352 void addLiveRoot(const char* name);
353 void moveToFrontOfSection(ObjectFile::Atom* atom);
354 ObjectFile::Atom* findAtom(const Options::OrderedSymbol& pair);
355 void logArchive(ObjectFile::Reader* reader);
356 void sortSections();
357 void sortAtoms();
358 void tweakLayout();
359 void writeDotOutput();
360 static bool minimizeStab(ObjectFile::Reader::Stab& stab);
361 static const char* truncateStabString(const char* str);
362 void collectDebugInfo();
363 void writeOutput();
364 ObjectFile::Atom* entryPoint(bool orInit, bool searchArchives=false);
365 ObjectFile::Atom* dyldClassicHelper();
366 ObjectFile::Atom* dyldCompressedHelper();
367 ObjectFile::Atom* dyldLazyLibraryHelper();
368 const char* assureFullPath(const char* path);
369 void markLive(ObjectFile::Atom& atom, Linker::WhyLiveBackChain* previous);
370 void collectStabs(ObjectFile::Reader* reader, std::map<const class ObjectFile::Atom*, uint32_t>& atomOrdinals);
371 void synthesizeDebugNotes(std::vector<class ObjectFile::Atom*>& allAtomsByReader);
372 void printStatistics();
373 void printTime(const char* msg, uint64_t partTime, uint64_t totalTime);
374 char* commatize(uint64_t in, char* out);
375 void getVMInfo(vm_statistics_data_t& info);
376 cpu_type_t inferArchitecture();
377 void checkDylibClientRestrictions(ObjectFile::Reader* reader);
378 void logDylib(ObjectFile::Reader* reader, bool indirect);
380 void resolve(ObjectFile::Reference* reference);
381 void resolveFrom(ObjectFile::Reference* reference);
382 std::vector<class ObjectFile::Atom*>* addJustInTimeAtoms(const char* name, bool searchDylibs, bool searchArchives, bool okToMakeProxy);
383 void addJustInTimeAtomsAndMarkLive(const char* name);
385 ObjectFile::Reader* addDylib(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen);
386 ObjectFile::Reader* addObject(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen);
387 ObjectFile::Reader* addArchive(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen);
389 void logTraceInfo(const char* format, ...);
392 class SymbolTable
394 public:
395 typedef __gnu_cxx::hash_map<const char*, ObjectFile::Atom*, __gnu_cxx::hash<const char*>, CStringEquals> Mapper;
397 SymbolTable(Linker&);
398 void require(const char* name);
399 bool add(ObjectFile::Atom& atom);
400 ObjectFile::Atom* find(const char* name);
401 void erase(const char* name);
402 unsigned int getRequireCount() { return fRequireCount; }
403 void getUndefinesNames(std::vector<const char*>& undefines);
404 void getTentativesNames(std::vector<const char*>& tents);
405 bool hasExternalTentativeDefinitions() { return fHasExternalTentativeDefinitions; }
406 bool hasExternalWeakDefinitions() { return fHasExternalWeakDefinitions; }
407 void setHasExternalWeakDefinitions(bool value) { fHasExternalWeakDefinitions = value; }
408 uint32_t dylibSymbolCount() { return fDylibSymbolCount; }
409 Mapper::iterator begin() { return fTable.begin(); }
410 Mapper::iterator end() { return fTable.end(); }
412 private:
413 Linker& fOwner;
414 Mapper fTable;
415 unsigned int fRequireCount;
416 bool fHasExternalTentativeDefinitions;
417 bool fHasExternalWeakDefinitions;
418 uint32_t fDylibSymbolCount;
421 class AtomSorter
423 public:
424 AtomSorter(std::map<const ObjectFile::Atom*, uint32_t>* map, std::set<const ObjectFile::Atom*>& inits,
425 std::set<const ObjectFile::Atom*>& terms) :
426 fOverriddenOrdinalMap(map), fInitializerSet(inits), fTerminatorSet(terms) {}
427 bool operator()(const ObjectFile::Atom* left, const ObjectFile::Atom* right);
428 private:
429 std::map<const ObjectFile::Atom*, uint32_t>* fOverriddenOrdinalMap;
430 std::set<const ObjectFile::Atom*>& fInitializerSet;
431 std::set<const ObjectFile::Atom*>& fTerminatorSet;
434 typedef std::map<const char*, uint32_t, CStringComparor> SectionOrder;
436 struct DTraceProbeInfo {
437 DTraceProbeInfo(const ObjectFile::Atom* a, uint32_t o, const char* n) : atom(a), offset(o), probeName(n) {}
438 const ObjectFile::Atom* atom;
439 uint32_t offset;
440 const char* probeName;
442 typedef __gnu_cxx::hash_map<const char*, std::vector<DTraceProbeInfo>, __gnu_cxx::hash<const char*>, CStringEquals> ProviderToProbes;
443 typedef __gnu_cxx::hash_set<const char*, __gnu_cxx::hash<const char*>, CStringEquals> CStringSet;
444 typedef __gnu_cxx::hash_map<const char*, ObjectFile::Reader*, __gnu_cxx::hash<const char*>, CStringEquals> InstallNameToReader;
446 struct IndirectLibrary {
447 const char* path;
448 uint64_t fileLen;
449 ObjectFile::Reader* reader;
450 std::set<ObjectFile::Reader*> parents;
451 ObjectFile::Reader* reExportedViaDirectLibrary;
454 ObjectFile::Reader* findDirectLibraryWhichReExports(struct IndirectLibrary& indirectLib);
456 Options fOptions;
457 SymbolTable fGlobalSymbolTable;
458 uint32_t fNextInputOrdinal;
459 std::vector<class ObjectFile::Reader*> fInputFiles;
460 ExecutableFile::Writer* fOutputFile;
461 InstallNameToReader fDylibMap;
462 std::map<ObjectFile::Reader*,LibraryOptions> fDylibOptionsMap;
463 std::set<ObjectFile::Reader*> fDylibsProcessed;
464 ObjectFile::Reader* fBundleLoaderReader;
465 std::vector<class ObjectFile::Reader*> fReadersThatHaveSuppliedAtoms;
466 std::vector<class ObjectFile::Atom*> fAllAtoms;
467 std::set<class ObjectFile::Reader*> fArchiveReaders;
468 std::set<class ObjectFile::Reader*> fArchiveReadersLogged;
469 std::set<class ObjectFile::Atom*> fDeadAtoms;
470 std::set<ObjectFile::Atom*> fLiveAtoms;
471 std::set<ObjectFile::Atom*> fLiveRootAtoms;
472 std::set<const ObjectFile::Atom*> fInitializerAtoms;
473 std::set<const ObjectFile::Atom*> fTerminatorAtoms;
474 std::set<const ObjectFile::Atom*> fRegularDefAtomsThatOverrideADylibsWeakDef;
475 std::vector<class ObjectFile::Reader::Stab> fStabs;
476 std::vector<class ObjectFile::Atom*> fAtomsWithUnresolvedReferences;
477 std::set<class ObjectFile::Atom*> fAtomsOverriddenByLateLoads;
478 bool fInitialLoadsDone;
479 bool fCreateUUID;
480 bool fCanScatter;
481 SectionOrder fSectionOrder;
482 cpu_type_t fArchitecture;
483 const char* fArchitectureName;
484 bool fArchitectureInferred;
485 bool fDirectLibrariesComplete;
486 bool fBiggerThanTwoGigOutput;
487 uint64_t fOutputFileSize;
488 uint64_t fTotalZeroFillSize;
489 uint64_t fTotalSize;
490 uint64_t fStartTime;
491 uint64_t fStartCreateReadersTime;
492 uint64_t fStartCreateWriterTime;
493 uint64_t fStartBuildAtomsTime;
494 uint64_t fStartLoadAndResolveTime;
495 uint64_t fStartSortTime;
496 uint64_t fStartDebugTime;
497 uint64_t fStartWriteTime;
498 uint64_t fEndTime;
499 uint64_t fTotalObjectSize;
500 uint64_t fTotalArchiveSize;
501 uint32_t fTotalObjectLoaded;
502 uint32_t fTotalArchivesLoaded;
503 uint32_t fTotalDylibsLoaded;
504 vm_statistics_data_t fStartVMInfo;
505 ObjectFile::Reader::ObjcConstraint fCurrentObjCConstraint;
506 ObjectFile::Reader::CpuConstraint fCurrentCpuConstraint;
507 bool fObjcReplacmentClasses;
508 bool fAllDirectDylibsLoaded;
512 Linker::Linker(int argc, const char* argv[])
513 : fOptions(argc, argv), fGlobalSymbolTable(*this), fNextInputOrdinal(1), fOutputFile(NULL), fBundleLoaderReader(NULL),
514 fInitialLoadsDone(false), fCreateUUID(fOptions.outputKind() != Options::kObjectFile), fCanScatter(true),
515 fArchitecture(0), fArchitectureInferred(false), fDirectLibrariesComplete(false), fBiggerThanTwoGigOutput(false),
516 fOutputFileSize(0), fTotalZeroFillSize(0), fTotalSize(0), fTotalObjectSize(0),
517 fTotalArchiveSize(0), fTotalObjectLoaded(0), fTotalArchivesLoaded(0), fTotalDylibsLoaded(0),
518 fCurrentObjCConstraint(ObjectFile::Reader::kObjcNone), fCurrentCpuConstraint(ObjectFile::Reader::kCpuAny),
519 fObjcReplacmentClasses(false), fAllDirectDylibsLoaded(false)
521 fStartTime = mach_absolute_time();
522 if ( fOptions.printStatistics() )
523 getVMInfo(fStartVMInfo);
525 fArchitecture = fOptions.architecture();
526 if ( fArchitecture == 0 ) {
527 // -arch not specified, scan .o files to figure out what it should be
528 fArchitecture = inferArchitecture();
529 fArchitectureInferred = true;
531 switch (fArchitecture) {
532 case CPU_TYPE_POWERPC:
533 fArchitectureName = "ppc";
534 break;
535 case CPU_TYPE_POWERPC64:
536 fArchitectureName = "ppc64";
537 break;
538 case CPU_TYPE_I386:
539 fArchitectureName = "i386";
540 break;
541 case CPU_TYPE_X86_64:
542 fArchitectureName = "x86_64";
543 break;
544 case CPU_TYPE_ARM:
545 fArchitectureName = "arm";
546 if ( fOptions.preferSubArchitecture() ) {
547 switch ( fOptions.subArchitecture() ) {
548 case CPU_SUBTYPE_ARM_V4T:
549 fArchitectureName = "armv4t";
550 break;
551 case CPU_SUBTYPE_ARM_V5TEJ:
552 fArchitectureName = "armv5";
553 break;
554 case CPU_SUBTYPE_ARM_V6:
555 fArchitectureName = "armv6";
556 break;
557 case CPU_SUBTYPE_ARM_V7:
558 fArchitectureName = "armv7";
559 break;
562 break;
563 default:
564 fArchitectureName = "unknown architecture";
565 break;
569 const char* Linker::architectureName()
571 return fArchitectureName;
574 bool Linker::showArchitectureInErrors()
576 return fOptions.printArchPrefix();
579 bool Linker::isInferredArchitecture()
581 return fArchitectureInferred;
584 cpu_type_t Linker::inferArchitecture()
586 // scan all input files, looking for a thin .o file.
587 // the first one found is presumably the architecture to link
588 uint8_t buffer[sizeof(mach_header_64)];
589 std::vector<Options::FileInfo>& files = fOptions.getInputFiles();
590 for (std::vector<Options::FileInfo>::iterator it = files.begin(); it != files.end(); ++it) {
591 int fd = ::open(it->path, O_RDONLY, 0);
592 if ( fd != -1 ) {
593 ssize_t amount = read(fd, buffer, sizeof(buffer));
594 ::close(fd);
595 if ( amount >= (ssize_t)sizeof(buffer) ) {
596 if ( mach_o::relocatable::Reader<ppc>::validFile(buffer) ) {
597 //warning("-arch not used, infering -arch ppc based on %s", it->path);
598 return CPU_TYPE_POWERPC;
600 else if ( mach_o::relocatable::Reader<ppc64>::validFile(buffer) ) {
601 //warning("-arch not used, infering -arch ppc64 based on %s", it->path);
602 return CPU_TYPE_POWERPC64;
604 else if ( mach_o::relocatable::Reader<x86>::validFile(buffer) ) {
605 //warning("-arch not used, infering -arch i386 based on %s", it->path);
606 return CPU_TYPE_I386;
608 else if ( mach_o::relocatable::Reader<x86_64>::validFile(buffer) ) {
609 //warning("-arch not used, infering -arch x86_64 based on %s", it->path);
610 return CPU_TYPE_X86_64;
612 else if ( mach_o::relocatable::Reader<arm>::validFile(buffer) ) {
613 //warning("-arch not used, infering -arch arm based on %s", it->path);
614 return CPU_TYPE_ARM;
620 // no thin .o files found, so default to same architecture this was built as
621 warning("-arch not specified");
622 #if __ppc__
623 return CPU_TYPE_POWERPC;
624 #elif __i386__
625 return CPU_TYPE_I386;
626 #elif __ppc64__
627 return CPU_TYPE_POWERPC64;
628 #elif __x86_64__
629 return CPU_TYPE_X86_64;
630 #elif __arm__
631 return CPU_TYPE_ARM;
632 #else
633 #error unknown default architecture
634 #endif
638 void Linker::addInputFile(ObjectFile::Reader* reader, const Options::FileInfo& info)
640 fInputFiles.push_back(reader);
641 fDylibOptionsMap[reader] = info.options;
644 void Linker::setOutputFile(ExecutableFile::Writer* writer)
646 fOutputFile = writer;
649 class InSet
651 public:
652 InSet(std::set<ObjectFile::Atom*>& deadAtoms) : fDeadAtoms(deadAtoms) {}
654 bool operator()(ObjectFile::Atom*& atom) const {
655 return ( fDeadAtoms.count(atom) != 0 );
658 private:
659 std::set<ObjectFile::Atom*>& fDeadAtoms;
662 void Linker::loadAndResolve()
664 fStartLoadAndResolveTime = mach_absolute_time();
665 if ( fOptions.deadStrip() == Options::kDeadStripOff ) {
666 // without dead-code-stripping:
667 // find atoms to resolve all undefines
668 this->loadUndefines();
669 // verify nothing is missing
670 this->checkUndefines();
671 // once all undefines fulfill, then bind all references
672 this->resolveReferences();
673 // remove atoms weak atoms that have been overridden
674 fAllAtoms.erase(std::remove_if(fAllAtoms.begin(), fAllAtoms.end(), InSet(fDeadAtoms)), fAllAtoms.end());
676 else {
677 // with dead code stripping:
678 // start binding references from roots,
679 this->deadStripResolve();
680 // verify nothing is missing
681 this->checkUndefines();
685 void Linker::addSynthesizedAtoms()
687 // give write a chance to synthesize stub, GOT, and lazy pointer atoms
688 std::vector<class ObjectFile::Atom*> newAtoms;
689 fOutputFile->addSynthesizedAtoms(fAllAtoms, this->dyldClassicHelper(),
690 this->dyldCompressedHelper(), this->dyldLazyLibraryHelper(),
691 fBiggerThanTwoGigOutput,
692 fGlobalSymbolTable.dylibSymbolCount(),
693 newAtoms);
695 // add all newly created atoms to fAllAtoms and update symbol table
696 this->addAtoms(newAtoms);
699 void Linker::optimize()
701 // give each reader a chance to do any optimizations
702 bool didSomething = false;
703 std::vector<class ObjectFile::Atom*> newAtoms;
704 std::vector<const char *> additionalUndefines;
705 std::vector<class ObjectFile::Atom*> newlyDeadAtoms;
706 for (std::vector<class ObjectFile::Reader*>::iterator it=fInputFiles.begin(); it != fInputFiles.end(); it++) {
707 didSomething |= (*it)->optimize(fAllAtoms, newAtoms, additionalUndefines, fDeadAtoms, newlyDeadAtoms, fNextInputOrdinal,
708 fOutputFile, entryPoint(true), fOptions.llvmOptions(),
709 fOptions.allGlobalsAreDeadStripRoots(), (int)fOptions.outputKind(), fOptions.verbose(),
710 fOptions.saveTempFiles(), fOptions.getOutputFilePath(), fOptions.positionIndependentExecutable(),
711 fOptions.allowTextRelocs());
714 // only do next steps if some optimization was actually done
715 if ( didSomething ) {
717 if ( fOptions.deadStrip() != Options::kDeadStripOff ) {
718 for(std::vector<class ObjectFile::Atom*>::iterator itr = newAtoms.begin(); itr != newAtoms.end(); ++itr) {
719 ObjectFile::Atom* atom = *itr;
720 const char* name = atom->getName();
721 if ( name != NULL ) {
722 ObjectFile::Atom* existingAtom = fGlobalSymbolTable.find(name);
723 if ( (existingAtom != NULL) && fLiveAtoms.count(existingAtom) == 0 ) {
724 // While dead code stripping, the atoms were not removed from fGlobalSymbolTable
725 // for performance reasons. Normally, libLTO will never recreate an atom
726 // that was previously dead stripped away, but if it does remove
727 // the remnents of the previous so the new one can be added
728 fGlobalSymbolTable.erase(name);
734 // add all newly created atoms to fAllAtoms and update symbol table
735 this->addAtoms(newAtoms);
737 // add dead atoms to dead list and remove from fAllAtoms
738 for(std::vector<class ObjectFile::Atom*>::iterator itr = newlyDeadAtoms.begin(); itr != newlyDeadAtoms.end(); ++itr)
739 markDead(*itr);
740 fAllAtoms.erase(std::remove_if(fAllAtoms.begin(), fAllAtoms.end(), InSet(fDeadAtoms)), fAllAtoms.end());
742 // Make sure all atoms have a section. Atoms that were not originally in a mach-o file could
743 // not have their section set until now.
744 for(std::vector<class ObjectFile::Atom*>::iterator itr = fAllAtoms.begin(); itr != fAllAtoms.end(); ++itr) {
745 ObjectFile::Atom *atom = *itr;
746 if ( atom->getSection() == NULL )
747 atom->setSection(Section::find(atom->getSectionName(), atom->getSegment().getName(), atom->isZeroFill(), true));
750 // resolve new undefines
751 for(std::vector<const char*>::iterator riter = additionalUndefines.begin(); riter != additionalUndefines.end(); ++riter) {
752 const char *targetName = *riter;
753 //fprintf(stderr, "LTO additional undefine: %s\n", targetName);
754 ObjectFile::Atom* target = fGlobalSymbolTable.find(targetName);
755 if ( target == NULL) {
756 // mark that this symbol is needed
757 fGlobalSymbolTable.require(targetName);
758 // try to find it in some library
759 this->addJustInTimeAtoms(targetName, true, true, true);
763 if ( fOptions.deadStrip() != Options::kDeadStripOff ) {
764 // LTO may optimize away some atoms, so dead stripping must be redone
765 fLiveAtoms.clear();
766 this->deadStripResolve();
767 this->checkUndefines();
769 else {
770 // LTO may require new library symbols to be loaded, so redo
771 this->checkUndefines();
772 this->resolveReferences();
778 void Linker::adjustScope()
780 // if -exported_symbols_list is used, demoted to hidden, symbols that are not in it
781 if ( fOptions.hasExportRestrictList() ) {
782 // The use of an -export file means the previous computation of fHasExternalWeakDefinitions could change
783 fGlobalSymbolTable.setHasExternalWeakDefinitions(false);
784 for(std::vector<class ObjectFile::Atom*>::iterator itr = fAllAtoms.begin(); itr != fAllAtoms.end(); ++itr) {
785 ObjectFile::Atom *atom = *itr;
786 ObjectFile::Atom::Scope scope = atom->getScope();
787 const char* name = atom->getName();
788 if ( name != NULL ) {
789 if ( scope == ObjectFile::Atom::scopeGlobal ) {
790 // check for globals that are downgraded to hidden
791 if ( !fOptions.shouldExport(name) ) {
792 atom->setScope(ObjectFile::Atom::scopeLinkageUnit);
793 //fprintf(stderr, "demote %s to hidden\n", name);
795 else if ( atom->getDefinitionKind() == ObjectFile::Atom::kWeakDefinition ) {
796 // we do have an exported weak symbol, turn WEAK_DEFINES back on
797 fGlobalSymbolTable.setHasExternalWeakDefinitions(true);
800 else if ( scope == ObjectFile::Atom::scopeLinkageUnit ) {
801 // check for hiddens that were requested to be exported
802 if ( fOptions.hasExportMaskList() && fOptions.shouldExport(name) ) {
803 warning("cannot export hidden symbol %s from %s", name, atom->getFile()->getPath());
810 // linking is done, so demote hidden symbols to static
811 if ( (fOptions.outputKind() == Options::kObjectFile) && fOptions.keepPrivateExterns() ) {
812 // ld -r -keep_private_externs does not move hidden symbols to static
814 else {
815 for(std::vector<class ObjectFile::Atom*>::iterator itr = fAllAtoms.begin(); itr != fAllAtoms.end(); ++itr) {
816 ObjectFile::Atom *atom = *itr;
817 // <rdar://problem/4637139> hidden common symbols cannot be demoted to static
818 if ( (atom->getScope() == ObjectFile::Atom::scopeLinkageUnit) && (atom->getDefinitionKind() != ObjectFile::Atom::kTentativeDefinition) ) {
819 atom->setScope(ObjectFile::Atom::scopeTranslationUnit);
820 //fprintf(stderr, "demote %s to static\n", atom->getDisplayName());
826 void Linker::link()
828 this->buildAtomList();
829 this->loadAndResolve();
830 this->optimize();
831 this->adjustScope();
832 this->checkObjC();
833 this->processDTrace();
834 this->tweakLayout();
835 this->addSynthesizedAtoms();
836 this->sortSections();
837 this->sortAtoms();
838 this->writeDotOutput();
839 this->collectDebugInfo();
840 this->writeOutput();
841 this->printStatistics();
843 if ( fOptions.pauseAtEnd() )
844 sleep(10);
847 void Linker::printTime(const char* msg, uint64_t partTime, uint64_t totalTime)
849 static uint64_t sUnitsPerSecond = 0;
850 if ( sUnitsPerSecond == 0 ) {
851 struct mach_timebase_info timeBaseInfo;
852 if ( mach_timebase_info(&timeBaseInfo) == KERN_SUCCESS ) {
853 sUnitsPerSecond = 1000000000ULL * timeBaseInfo.denom / timeBaseInfo.numer;
854 //fprintf(stderr, "sUnitsPerSecond=%llu\n", sUnitsPerSecond);
857 if ( partTime < sUnitsPerSecond ) {
858 uint32_t milliSecondsTimeTen = (partTime*10000)/sUnitsPerSecond;
859 uint32_t milliSeconds = milliSecondsTimeTen/10;
860 uint32_t percentTimesTen = (partTime*1000)/totalTime;
861 uint32_t percent = percentTimesTen/10;
862 fprintf(stderr, "%s: %u.%u milliseconds (%u.%u%%)\n", msg, milliSeconds, milliSecondsTimeTen-milliSeconds*10, percent, percentTimesTen-percent*10);
864 else {
865 uint32_t secondsTimeTen = (partTime*10)/sUnitsPerSecond;
866 uint32_t seconds = secondsTimeTen/10;
867 uint32_t percentTimesTen = (partTime*1000)/totalTime;
868 uint32_t percent = percentTimesTen/10;
869 fprintf(stderr, "%s: %u.%u seconds (%u.%u%%)\n", msg, seconds, secondsTimeTen-seconds*10, percent, percentTimesTen-percent*10);
873 char* Linker::commatize(uint64_t in, char* out)
875 char* result = out;
876 char rawNum[30];
877 sprintf(rawNum, "%llu", in);
878 const int rawNumLen = strlen(rawNum);
879 for(int i=0; i < rawNumLen-1; ++i) {
880 *out++ = rawNum[i];
881 if ( ((rawNumLen-i) % 3) == 1 )
882 *out++ = ',';
884 *out++ = rawNum[rawNumLen-1];
885 *out = '\0';
886 return result;
889 void Linker::getVMInfo(vm_statistics_data_t& info)
891 mach_msg_type_number_t count = sizeof(vm_statistics_data_t) / sizeof(natural_t);
892 kern_return_t error = host_statistics(mach_host_self(), HOST_VM_INFO,
893 (host_info_t)&info, &count);
894 if (error != KERN_SUCCESS) {
895 bzero(&info, sizeof(vm_statistics_data_t));
899 void Linker::printStatistics()
901 fEndTime = mach_absolute_time();
902 if ( fOptions.printStatistics() ) {
903 vm_statistics_data_t endVMInfo;
904 getVMInfo(endVMInfo);
906 uint64_t totalTime = fEndTime - fStartTime;
907 printTime("ld total time", totalTime, totalTime);
908 printTime(" option parsing time", fStartCreateReadersTime - fStartTime, totalTime);
909 printTime(" object file processing",fStartCreateWriterTime - fStartCreateReadersTime, totalTime);
910 printTime(" output file setup", fStartBuildAtomsTime - fStartCreateWriterTime, totalTime);
911 printTime(" build atom list", fStartLoadAndResolveTime - fStartBuildAtomsTime, totalTime);
912 printTime(" resolve references", fStartSortTime - fStartLoadAndResolveTime, totalTime);
913 printTime(" sort output", fStartDebugTime - fStartSortTime, totalTime);
914 printTime(" process debug info", fStartWriteTime - fStartDebugTime, totalTime);
915 printTime(" write output", fEndTime - fStartWriteTime, totalTime);
916 fprintf(stderr, "pageins=%u, pageouts=%u, faults=%u\n", endVMInfo.pageins-fStartVMInfo.pageins,
917 endVMInfo.pageouts-fStartVMInfo.pageouts, endVMInfo.faults-fStartVMInfo.faults);
918 char temp[40];
919 fprintf(stderr, "processed %3u object files, totaling %15s bytes\n", fTotalObjectLoaded, commatize(fTotalObjectSize, temp));
920 fprintf(stderr, "processed %3u archive files, totaling %15s bytes\n", fTotalArchivesLoaded, commatize(fTotalArchiveSize, temp));
921 fprintf(stderr, "processed %3u dylib files\n", fTotalDylibsLoaded);
922 fprintf(stderr, "wrote output file totaling %15s bytes\n", commatize(fOutputFileSize, temp));
926 inline void Linker::addAtom(ObjectFile::Atom& atom)
928 // add to list of all atoms
929 fAllAtoms.push_back(&atom);
931 if ( fOptions.deadStrip() == Options::kDeadStripOff ) {
932 // not dead-stripping code, so add atom's references's names to symbol table as to-be-resolved-later
933 std::vector<class ObjectFile::Reference*>& references = atom.getReferences();
934 for (std::vector<ObjectFile::Reference*>::iterator it=references.begin(); it != references.end(); it++) {
935 ObjectFile::Reference* reference = *it;
936 if ( reference->getTargetBinding() == ObjectFile::Reference::kUnboundByName )
937 fGlobalSymbolTable.require(reference->getTargetName());
938 if ( reference->getFromTargetBinding() == ObjectFile::Reference::kUnboundByName )
939 fGlobalSymbolTable.require(reference->getFromTargetName());
941 // update total size info (except for __ZEROPAGE atom)
942 if ( atom.getSegment().isContentReadable() ) {
943 fTotalSize += atom.getSize();
944 if ( atom.isZeroFill() )
945 fTotalZeroFillSize += atom.getSize();
948 else {
949 if ( atom.dontDeadStrip() )
950 fLiveRootAtoms.insert(&atom);
953 // if in global namespace, add atom itself to symbol table
954 ObjectFile::Atom::Scope scope = atom.getScope();
955 const char* name = atom.getName();
956 if ( (scope != ObjectFile::Atom::scopeTranslationUnit) && (name != NULL) ) {
957 // add to symbol table
958 fGlobalSymbolTable.add(atom);
961 // record section orders so output file can have same order
962 if (atom.getSectionName()) {
963 bool untrusted = false;
964 switch ( atom.getContentType() ) {
965 case ObjectFile::Atom::kSectionStart:
966 case ObjectFile::Atom::kSectionEnd:
967 untrusted = true;
968 default:
969 break;
971 atom.setSection(Section::find(atom.getSectionName(), atom.getSegment().getName(), atom.isZeroFill(), untrusted));
976 void Linker::markDead(ObjectFile::Atom* atom)
978 //fprintf(stderr, "markDead(%p) %s from %s\n", atom, atom->getDisplayName(), atom->getFile()->getPath());
979 fDeadAtoms.insert(atom);
981 // <rdar://problem/6578360> -dead_strip inhibits weak coalescing in no_dead_strip section
982 if ( fLiveRootAtoms.count(atom) != 0 ) {
983 fLiveRootAtoms.erase(atom);
987 // The kGroupSubordinate reference kind is used to model group comdat.
988 // The "signature" atom in the group has a kGroupSubordinate reference to
989 // all other members of the group. So, if the signature atom is
990 // coalesced away, all other atoms in the group should also be removed.
992 std::vector<class ObjectFile::Reference*>& references = atom->getReferences();
993 for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
994 ObjectFile::Reference* ref = *rit;
995 if ( ref->getKind() == 2 /*kGroupSubordinate*/ ) { // FIX FIX
996 ObjectFile::Atom* targetAtom = &(ref->getTarget());
997 //fprintf(stderr, " markDead(%p) subordinate %s\n", targetAtom, targetAtom->getDisplayName());
998 if ( targetAtom == NULL ) {
999 warning("%s has a group reference to %s but is not bound", atom->getDisplayName(), ref->getTargetName());
1001 else {
1002 if ( targetAtom->getScope() != ObjectFile::Atom::scopeTranslationUnit ) {
1003 // ok for .eh symbols to be not static in -r mode
1004 if ( (fOptions.outputKind() != Options::kObjectFile) || (strcmp(targetAtom->getSectionName(), "__eh_frame") != 0) )
1005 warning("%s is in a comdat group but its scope is not static", targetAtom->getDisplayName());
1007 this->markDead(targetAtom);
1013 void Linker::updateConstraints(ObjectFile::Reader* reader)
1015 // check objc objects were compiled compatibly
1016 ObjectFile::Reader::ObjcConstraint objcAddition = reader->getObjCConstraint();
1017 if ( reader->getInstallPath() == NULL ) {
1018 // adding a .o file
1019 switch ( objcAddition ) {
1020 case ObjectFile::Reader::kObjcNone:
1021 break;
1022 case ObjectFile::Reader::kObjcRetainRelease:
1023 if ( fCurrentObjCConstraint == ObjectFile::Reader::kObjcGC )
1024 throwf("%s built with incompatible Garbage Collection settings to link with previous .o files", reader->getPath());
1025 fCurrentObjCConstraint = ObjectFile::Reader::kObjcRetainRelease;
1026 break;
1027 case ObjectFile::Reader::kObjcRetainReleaseOrGC:
1028 if ( fCurrentObjCConstraint == ObjectFile::Reader::kObjcNone )
1029 fCurrentObjCConstraint = ObjectFile::Reader::kObjcRetainReleaseOrGC;
1030 break;
1031 case ObjectFile::Reader::kObjcGC:
1032 if ( fCurrentObjCConstraint == ObjectFile::Reader::kObjcRetainRelease )
1033 throwf("%s built with incompatible Garbage Collection settings to link with previous .o files", reader->getPath());
1034 fCurrentObjCConstraint = ObjectFile::Reader::kObjcGC;
1035 break;
1038 if ( reader->objcReplacementClasses() )
1039 fObjcReplacmentClasses = true;
1041 // check cpu sub-types for stricter sub-type
1042 fCurrentCpuConstraint = (ObjectFile::Reader::CpuConstraint)reader->updateCpuConstraint(fCurrentCpuConstraint);
1045 inline void Linker::addAtoms(std::vector<class ObjectFile::Atom*>& atoms)
1047 bool scanAll = fOptions.readerOptions().fFullyLoadArchives || fOptions.readerOptions().fLoadAllObjcObjectsFromArchives;
1048 bool first = true;
1049 for (std::vector<ObjectFile::Atom*>::iterator it=atoms.begin(); it != atoms.end(); it++) {
1050 // usually we only need to get the first atom's reader, but
1051 // with -all_load all atoms from all .o files come come back together
1052 // so we need to scan all atoms
1053 if ( first || scanAll ) {
1054 // update fReadersThatHaveSuppliedAtoms
1055 ObjectFile::Reader* reader = (*it)->getFile();
1056 if ( std::find(fReadersThatHaveSuppliedAtoms.begin(), fReadersThatHaveSuppliedAtoms.end(), reader)
1057 == fReadersThatHaveSuppliedAtoms.end() ) {
1058 fReadersThatHaveSuppliedAtoms.push_back(reader);
1059 updateConstraints(reader);
1062 this->addAtom(**it);
1063 first = false;
1067 void Linker::logArchive(ObjectFile::Reader* reader)
1069 if ( (fArchiveReaders.count(reader) != 0) && (fArchiveReadersLogged.count(reader) == 0) ) {
1070 fArchiveReadersLogged.insert(reader);
1071 const char* fullPath = reader->getPath();
1072 char realName[MAXPATHLEN];
1073 if ( realpath(fullPath, realName) != NULL )
1074 fullPath = realName;
1075 logTraceInfo("[Logging for XBS] Used static archive: %s\n", fullPath);
1080 void Linker::buildAtomList()
1082 fStartBuildAtomsTime = mach_absolute_time();
1083 // add initial undefines from -u option
1084 std::vector<const char*>& initialUndefines = fOptions.initialUndefines();
1085 for (std::vector<const char*>::iterator it=initialUndefines.begin(); it != initialUndefines.end(); it++) {
1086 fGlobalSymbolTable.require(*it);
1089 // writer can contribute atoms
1090 this->addAtoms(fOutputFile->getAtoms());
1092 // each reader contributes atoms
1093 for (std::vector<class ObjectFile::Reader*>::iterator it=fInputFiles.begin(); it != fInputFiles.end(); it++) {
1094 ObjectFile::Reader* reader = *it;
1095 std::vector<class ObjectFile::Atom*>& atoms = reader->getAtoms();
1096 this->addAtoms(atoms);
1097 if ( fOptions.readerOptions().fTraceArchives && (atoms.size() != 0) )
1098 logArchive(reader);
1101 // extra command line section always at end
1102 std::vector<Options::ExtraSection>& extraSections = fOptions.extraSections();
1103 for( std::vector<Options::ExtraSection>::iterator it=extraSections.begin(); it != extraSections.end(); ++it) {
1104 this->addAtoms((new opaque_section::Reader(it->segmentName, it->sectionName, it->path, it->data, it->dataLen, fNextInputOrdinal))->getAtoms());
1105 fNextInputOrdinal += it->dataLen;
1108 // done with all .o files on command line
1109 // everything loaded from now on is a just-in-time atom
1110 fInitialLoadsDone = true;
1113 static const char* pathLeafName(const char* path)
1115 const char* shortPath = strrchr(path, '/');
1116 if ( shortPath == NULL )
1117 return path;
1118 else
1119 return &shortPath[1];
1123 void Linker::loadUndefines()
1125 // keep looping until no more undefines were added in last loop
1126 unsigned int undefineCount = 0xFFFFFFFF;
1127 while ( undefineCount != fGlobalSymbolTable.getRequireCount() ) {
1128 undefineCount = fGlobalSymbolTable.getRequireCount();
1129 std::vector<const char*> undefineNames;
1130 fGlobalSymbolTable.getUndefinesNames(undefineNames);
1131 for(std::vector<const char*>::iterator it = undefineNames.begin(); it != undefineNames.end(); ++it) {
1132 // load for previous undefine may also have loaded this undefine, so check again
1133 if ( fGlobalSymbolTable.find(*it) == NULL ) {
1134 std::vector<class ObjectFile::Atom*>* atoms = this->addJustInTimeAtoms(*it, true, true, true);
1135 if ( atoms != NULL )
1136 delete atoms;
1139 // <rdar://problem/5894163> need to search archives for overrides of common symbols
1140 if ( fGlobalSymbolTable.hasExternalTentativeDefinitions() ) {
1141 bool searchDylibs = (fOptions.commonsMode() == Options::kCommonsOverriddenByDylibs);
1142 std::vector<const char*> tentativeDefinitionNames;
1143 fGlobalSymbolTable.getTentativesNames(tentativeDefinitionNames);
1144 for(std::vector<const char*>::iterator it = tentativeDefinitionNames.begin(); it != tentativeDefinitionNames.end(); ++it) {
1145 // load for previous tentative may also have overridden this tentative, so check again
1146 ObjectFile::Atom* tent = fGlobalSymbolTable.find(*it);
1147 if ( (tent != NULL) && (tent->getDefinitionKind() == ObjectFile::Atom::kTentativeDefinition) ) {
1148 std::vector<class ObjectFile::Atom*>* atoms = this->addJustInTimeAtoms(*it, searchDylibs, true, false);
1149 if ( atoms != NULL )
1150 delete atoms;
1157 // temp hack for rdar://problem/4718189 map ObjC class names to new runtime names
1158 class ExportedObjcClass
1160 public:
1161 ExportedObjcClass(Options& opt) : fOptions(opt) {}
1163 bool operator()(const char* name) const {
1164 if ( fOptions.shouldExport(name) ) {
1165 if ( strncmp(name, ".objc_class_name_", 17) == 0 )
1166 return true;
1167 if ( strncmp(name, "_OBJC_CLASS_$_", 14) == 0 )
1168 return true;
1169 if ( strncmp(name, "_OBJC_METACLASS_$_", 18) == 0 )
1170 return true;
1172 //fprintf(stderr, "%s is not exported\n", name);
1173 return false;
1175 private:
1176 Options& fOptions;
1180 void Linker::checkUndefines()
1182 // error out on any remaining undefines
1183 bool doPrint = true;
1184 bool doError = true;
1185 switch ( fOptions.undefinedTreatment() ) {
1186 case Options::kUndefinedError:
1187 break;
1188 case Options::kUndefinedDynamicLookup:
1189 doError = false;
1190 break;
1191 case Options::kUndefinedWarning:
1192 doError = false;
1193 break;
1194 case Options::kUndefinedSuppress:
1195 doError = false;
1196 doPrint = false;
1197 break;
1199 std::vector<const char*> unresolvableUndefines;
1200 fGlobalSymbolTable.getUndefinesNames(unresolvableUndefines);
1202 // temp hack for rdar://problem/4718189 map ObjC class names to new runtime names
1203 // ignore unresolved references to Objc class names that are listed in -exported_symbols_list
1204 if ( fOptions.hasExportRestrictList() )
1205 unresolvableUndefines.erase(std::remove_if(unresolvableUndefines.begin(), unresolvableUndefines.end(), ExportedObjcClass(fOptions)), unresolvableUndefines.end());
1207 const int unresolvableCount = unresolvableUndefines.size();
1208 int unresolvableExportsCount = 0;
1209 if ( unresolvableCount != 0 ) {
1210 if ( doPrint ) {
1211 if ( fOptions.printArchPrefix() )
1212 fprintf(stderr, "Undefined symbols for architecture %s:\n", fArchitectureName);
1213 else
1214 fprintf(stderr, "Undefined symbols:\n");
1215 for (int i=0; i < unresolvableCount; ++i) {
1216 const char* name = unresolvableUndefines[i];
1217 fprintf(stderr, " \"%s\", referenced from:\n", name);
1218 // scan all atoms for references
1219 bool foundAtomReference = false;
1220 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
1221 ObjectFile::Atom* atom = *it;
1222 std::vector<class ObjectFile::Reference*>& references = atom->getReferences();
1223 for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
1224 ObjectFile::Reference* reference = *rit;
1225 if ( reference->getTargetBinding() == ObjectFile::Reference::kUnboundByName ) {
1226 if ( strcmp(reference->getTargetName(), name) == 0 ) {
1227 fprintf(stderr, " %s in %s\n", atom->getDisplayName(), pathLeafName(atom->getFile()->getPath()));
1228 foundAtomReference = true;
1231 if ( reference->getFromTargetBinding() == ObjectFile::Reference::kUnboundByName ) {
1232 if ( strcmp(reference->getFromTargetName(), name) == 0 ) {
1233 fprintf(stderr, " %s in %s\n", atom->getDisplayName(), pathLeafName(atom->getFile()->getPath()));
1234 foundAtomReference = true;
1239 // scan command line options
1240 if ( !foundAtomReference ) {
1241 // might be from -init command line option
1242 if ( (fOptions.initFunctionName() != NULL) && (strcmp(name, fOptions.initFunctionName()) == 0) ) {
1243 fprintf(stderr, " -init command line option\n");
1245 // or might be from exported symbol option
1246 else if ( fOptions.hasExportMaskList() && fOptions.shouldExport(name) ) {
1247 fprintf(stderr, " -exported_symbol[s_list] command line option\n");
1249 else {
1250 bool isInitialUndefine = false;
1251 std::vector<const char*>& clundefs = fOptions.initialUndefines();
1252 for (std::vector<const char*>::iterator uit = clundefs.begin(); uit != clundefs.end(); ++uit) {
1253 if ( strcmp(*uit, name) == 0 ) {
1254 isInitialUndefine = true;
1255 break;
1258 if ( isInitialUndefine )
1259 fprintf(stderr, " -u command line option\n");
1261 ++unresolvableExportsCount;
1263 // be helpful and check for typos
1264 bool printedStart = false;
1265 for (SymbolTable::Mapper::iterator sit=fGlobalSymbolTable.begin(); sit != fGlobalSymbolTable.end(); ++sit) {
1266 if ( (sit->second != NULL) && (strstr(sit->first, name) != NULL) ) {
1267 if ( ! printedStart ) {
1268 fprintf(stderr, " (maybe you meant: %s", sit->first);
1269 printedStart = true;
1271 else {
1272 fprintf(stderr, ", %s ", sit->first);
1276 if ( printedStart )
1277 fprintf(stderr, ")\n");
1280 if ( doError )
1281 throw "symbol(s) not found";
1284 // for each tentative definition in symbol table look for dylib that exports same symbol name
1285 if ( fGlobalSymbolTable.hasExternalTentativeDefinitions() ) {
1286 for (SymbolTable::Mapper::iterator it=fGlobalSymbolTable.begin(); it != fGlobalSymbolTable.end(); ++it) {
1287 ObjectFile::Atom* atom = it->second;
1288 if ( (atom != NULL) && (atom->getDefinitionKind()==ObjectFile::Atom::kTentativeDefinition)
1289 && (atom->getScope() == ObjectFile::Atom::scopeGlobal) ) {
1290 // look for dylibs that export same name as used by global tentative definition
1291 addJustInTimeAtoms(atom->getName(), true, false, false);
1297 // record any overrides of weak symbols any linked dylib
1298 for (SymbolTable::Mapper::iterator it=fGlobalSymbolTable.begin(); it != fGlobalSymbolTable.end(); ++it) {
1299 ObjectFile::Atom* atom = it->second;
1300 if ( (atom != NULL) && (atom->getDefinitionKind()==ObjectFile::Atom::kRegularDefinition)
1301 && (atom->getScope() == ObjectFile::Atom::scopeGlobal) ) {
1302 const char* name = atom->getName();
1303 //fprintf(stderr, "looking for dylibs with a weak %s\n", name);
1304 // look for dylibs with weak exports of the same name
1305 for (InstallNameToReader::iterator it=fDylibMap.begin(); it != fDylibMap.end(); it++) {
1306 ObjectFile::Reader* reader = it->second;
1307 if ( reader->hasWeakExternals() ) {
1308 std::vector<class ObjectFile::Atom*>* dylibAtoms = reader->getJustInTimeAtomsFor(name);
1309 if ( dylibAtoms != NULL ) {
1310 //fprintf(stderr, "addJustInTimeAtoms(%s) => found in file %s\n", name, reader->getPath() );
1311 // if this is a weak definition in a dylib
1312 if ( (dylibAtoms->at(0)->getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition) ) {
1313 fRegularDefAtomsThatOverrideADylibsWeakDef.insert(atom);
1325 std::vector<class ObjectFile::Atom*>* Linker::addJustInTimeAtoms(const char* name, bool searchDylibs, bool searchArchives, bool okToMakeProxy)
1327 //fprintf(stderr, "addJustInTimeAtoms(%s, searchDylibs=%d, searchArchives=%d)\n", name, searchDylibs, searchArchives );
1328 // when creating final linked image, writer gets first chance
1329 if ( fOptions.outputKind() != Options::kObjectFile ) {
1330 std::vector<class ObjectFile::Atom*>* atoms = fOutputFile->getJustInTimeAtomsFor(name);
1331 if ( atoms != NULL ) {
1332 this->addAtoms(*atoms);
1333 //fprintf(stderr, "addJustInTimeAtoms(%s) => found in file %s\n", name, fOutputFile->getPath() );
1334 return atoms; // found a definition, no need to search anymore
1338 // give readers a chance
1339 for (std::vector<class ObjectFile::Reader*>::iterator it=fInputFiles.begin(); it != fInputFiles.end(); it++) {
1340 ObjectFile::Reader* reader = *it;
1341 if ( reader != NULL ) {
1342 // if this reader is a static archive that has the symbol we need, pull in all atoms in that module
1343 // if this reader is a dylib that exports the symbol we need, have it synthesize an atom for us.
1344 //fprintf(stderr, "addJustInTimeAtoms(%s), looking in reader %s\n", name, reader->getPath() );
1345 bool isDylibReader = (reader->getInstallPath() != NULL);
1346 if ( isDylibReader ? searchDylibs : searchArchives ) {
1347 std::vector<class ObjectFile::Atom*>* atoms = reader->getJustInTimeAtomsFor(name);
1348 if ( atoms != NULL ) {
1349 this->addAtoms(*atoms);
1350 //fprintf(stderr, "addJustInTimeAtoms(%s) => found in file %s\n", name, reader->getPath() );
1351 if ( !isDylibReader && fOptions.readerOptions().fTraceArchives ) {
1352 logArchive(reader);
1354 // if this is a weak definition in a dylib
1355 if ( isDylibReader && (atoms->size() == 1) && (atoms->at(0)->getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition) ) {
1356 // keep looking for a non-weak definition
1358 else {
1359 // found a definition, no need to search anymore
1360 return atoms;
1367 // for two level namesapce, give all implicitly link dylibs a chance
1368 if ( fOptions.nameSpace() == Options::kTwoLevelNameSpace ) {
1369 for (InstallNameToReader::iterator it=fDylibMap.begin(); it != fDylibMap.end(); it++) {
1370 if ( it->second->implicitlyLinked() ) {
1371 //fprintf(stderr, "addJustInTimeAtoms(%s), looking in implicitly linked %s\n", name, it->second->getPath() );
1372 std::vector<class ObjectFile::Atom*>* atoms = it->second->getJustInTimeAtomsFor(name);
1373 if ( atoms != NULL ) {
1374 this->addAtoms(*atoms);
1375 //fprintf(stderr, "addJustInTimeAtoms(%s) => found in file %s\n", name, reader->getPath() );
1376 // if this is a weak definition in a dylib
1377 if ( (atoms->size() == 1) && (atoms->at(0)->getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition) ) {
1378 // keep looking for a non-weak definition
1380 else {
1381 // found a definition, no need to search anymore
1382 return atoms;
1389 // for flat namespace, give indirect dylibs
1390 if ( fOptions.nameSpace() != Options::kTwoLevelNameSpace ) {
1391 for (InstallNameToReader::iterator it=fDylibMap.begin(); it != fDylibMap.end(); it++) {
1392 if ( ! it->second->explicitlyLinked() ) {
1393 std::vector<class ObjectFile::Atom*>* atoms = it->second->getJustInTimeAtomsFor(name);
1394 if ( atoms != NULL ) {
1395 this->addAtoms(*atoms);
1396 //fprintf(stderr, "addJustInTimeAtoms(%s) => found in file %s\n", name, reader->getPath() );
1397 return atoms; // found a definition, no need to search anymore
1403 // writer creates a proxy in two cases:
1404 // 1) ld -r is being used to create a .o file
1405 // 2) -undefined dynamic_lookup is being used
1406 // 3) -U _foo is being used
1407 // 4) x86_64 kext bundle is being created
1408 if ( (fOptions.outputKind() == Options::kObjectFile)
1409 || ((fOptions.undefinedTreatment() != Options::kUndefinedError) && okToMakeProxy)
1410 || (fOptions.someAllowedUndefines() && okToMakeProxy)
1411 || (fOptions.outputKind() == Options::kKextBundle) ) {
1412 ObjectFile::Atom* atom = fOutputFile->getUndefinedProxyAtom(name);
1413 if ( atom != NULL ) {
1414 this->addAtom(*atom);
1415 return NULL;
1418 //fprintf(stderr, "addJustInTimeAtoms(%s) => not found\n", name);
1419 return NULL;
1422 void Linker::resolve(ObjectFile::Reference* reference)
1424 // look in global symbol table
1425 const char* targetName = reference->getTargetName();
1426 ObjectFile::Atom* target = fGlobalSymbolTable.find(targetName);
1427 if ( target == NULL ) {
1428 throwf("unexpected undefined symbol: %s", targetName);
1430 reference->setTarget(*target, reference->getTargetOffset());
1433 void Linker::resolveFrom(ObjectFile::Reference* reference)
1435 // handle references that have two (from and to) targets
1436 const char* fromTargetName = reference->getFromTargetName();
1437 ObjectFile::Atom* fromTarget = fGlobalSymbolTable.find(fromTargetName);
1438 if ( fromTarget == NULL ) {
1439 throwf("unexpected undefined symbol: %s", fromTargetName);
1441 reference->setFromTarget(*fromTarget);
1445 void Linker::resolveReferences()
1447 // note: the atom list may grow during this loop as libraries supply needed atoms
1448 for (unsigned int j=0; j < fAllAtoms.size(); ++j) {
1449 ObjectFile::Atom* atom = fAllAtoms[j];
1450 std::vector<class ObjectFile::Reference*>& references = atom->getReferences();
1451 for (std::vector<ObjectFile::Reference*>::iterator it=references.begin(); it != references.end(); it++) {
1452 ObjectFile::Reference* reference = *it;
1453 if ( reference->getTargetBinding() == ObjectFile::Reference::kUnboundByName )
1454 this->resolve(reference);
1455 if ( reference->getFromTargetBinding() == ObjectFile::Reference::kUnboundByName )
1456 this->resolveFrom(reference);
1462 // used to remove stabs associated with atoms that won't be in output file
1463 class NotInSet
1465 public:
1466 NotInSet(std::set<ObjectFile::Atom*>& theSet) : fSet(theSet) {}
1468 bool operator()(const ObjectFile::Reader::Stab& stab) const {
1469 if ( stab.atom == NULL )
1470 return false; // leave stabs that are not associated with any atome
1471 else
1472 return ( fSet.count(stab.atom) == 0 );
1475 private:
1476 std::set<ObjectFile::Atom*>& fSet;
1480 class NotLive
1482 public:
1483 NotLive(std::set<ObjectFile::Atom*>& set) : fLiveAtoms(set) {}
1485 bool operator()(ObjectFile::Atom*& atom) const {
1486 //if ( fLiveAtoms.count(atom) == 0 )
1487 // fprintf(stderr, "dead strip %s\n", atom->getDisplayName());
1488 return ( fLiveAtoms.count(atom) == 0 );
1490 private:
1491 std::set<ObjectFile::Atom*>& fLiveAtoms;
1495 void Linker::addJustInTimeAtomsAndMarkLive(const char* name)
1497 //fprintf(stderr, "addJustInTimeAtomsAndMarkLive(%s)\n", name);
1498 std::vector<class ObjectFile::Atom*>* atoms = this->addJustInTimeAtoms(name, true, true, true);
1499 if ( atoms != NULL ) {
1500 if ( fOptions.allGlobalsAreDeadStripRoots() ) {
1501 for (std::vector<ObjectFile::Atom*>::iterator it=atoms->begin(); it != atoms->end(); it++) {
1502 ObjectFile::Atom* atom = *it;
1503 if ( atom->getScope() == ObjectFile::Atom::scopeGlobal ) {
1504 WhyLiveBackChain rootChain;
1505 rootChain.previous = NULL;
1506 rootChain.referer = atom;
1507 this->markLive(*atom, &rootChain);
1511 delete atoms;
1515 void Linker::markLive(ObjectFile::Atom& atom, struct Linker::WhyLiveBackChain* previous)
1517 //fprintf(stderr, "markLive(%p)\n", &atom);
1518 if ( fLiveAtoms.count(&atom) == 0 ) {
1519 // if -why_live cares about this symbol, then dump chain
1520 if ( (previous->referer != NULL) && fOptions.printWhyLive(previous->referer->getDisplayName()) ) {
1521 int depth = 0;
1522 for(WhyLiveBackChain* p = previous; p != NULL; p = p->previous, ++depth) {
1523 for(int i=depth; i > 0; --i)
1524 fprintf(stderr, " ");
1525 fprintf(stderr, "%p %s from %s\n", p->referer, p->referer->getDisplayName(), p->referer->getFile()->getPath());
1528 // set up next chain
1529 WhyLiveBackChain thisChain;
1530 thisChain.previous = previous;
1531 // this atom is live
1532 fLiveAtoms.insert(&atom);
1533 // update total size info (except for __ZEROPAGE atom)
1534 if ( atom.getSegment().isContentReadable() ) {
1535 fTotalSize += atom.getSize();
1536 if ( atom.isZeroFill() )
1537 fTotalZeroFillSize += atom.getSize();
1539 // and all atoms it references
1540 std::vector<class ObjectFile::Reference*>& references = atom.getReferences();
1541 for (std::vector<ObjectFile::Reference*>::iterator it=references.begin(); it != references.end(); it++) {
1542 ObjectFile::Reference* reference = *it;
1543 if ( reference->getTargetBinding() == ObjectFile::Reference::kUnboundByName ) {
1544 // look in global symbol table
1545 const char* targetName = reference->getTargetName();
1546 ObjectFile::Atom* target = fGlobalSymbolTable.find(targetName);
1547 if ( (target == NULL) || (target->getDefinitionKind() == ObjectFile::Atom::kTentativeDefinition) ) {
1548 // load archives or dylibs
1549 this->addJustInTimeAtomsAndMarkLive(targetName);
1551 // look again
1552 target = fGlobalSymbolTable.find(targetName);
1553 if ( target != NULL ) {
1554 reference->setTarget(*target, reference->getTargetOffset());
1556 else {
1557 // mark as undefined, for later error processing
1558 fAtomsWithUnresolvedReferences.push_back(&atom);
1559 fGlobalSymbolTable.require(targetName);
1562 switch ( reference->getTargetBinding() ) {
1563 case ObjectFile::Reference::kBoundDirectly:
1564 case ObjectFile::Reference::kBoundByName:
1565 thisChain.referer = &reference->getTarget();
1566 markLive(reference->getTarget(), &thisChain);
1567 break;
1568 case ObjectFile::Reference::kDontBind:
1569 case ObjectFile::Reference::kUnboundByName:
1570 // do nothing
1571 break;
1573 // do the same as above, for "from target"
1574 if ( reference->getFromTargetBinding() == ObjectFile::Reference::kUnboundByName ) {
1575 // look in global symbol table
1576 const char* targetName = reference->getFromTargetName();
1577 ObjectFile::Atom* target = fGlobalSymbolTable.find(targetName);
1578 if ( (target == NULL) || (target->getDefinitionKind() == ObjectFile::Atom::kTentativeDefinition) ) {
1579 // load archives or dylibs
1580 this->addJustInTimeAtomsAndMarkLive(targetName);
1582 // look again
1583 target = fGlobalSymbolTable.find(targetName);
1584 if ( target != NULL ) {
1585 reference->setFromTarget(*target);
1587 else {
1588 // mark as undefined, for later error processing
1589 fGlobalSymbolTable.require(targetName);
1592 switch ( reference->getFromTargetBinding() ) {
1593 case ObjectFile::Reference::kBoundDirectly:
1594 case ObjectFile::Reference::kBoundByName:
1595 thisChain.referer = &reference->getFromTarget();
1596 markLive(reference->getFromTarget(), &thisChain);
1597 break;
1598 case ObjectFile::Reference::kUnboundByName:
1599 case ObjectFile::Reference::kDontBind:
1600 // do nothing
1601 break;
1608 void Linker::addLiveRoot(const char* name)
1610 ObjectFile::Atom* target = fGlobalSymbolTable.find(name);
1611 if ( target == NULL ) {
1612 this->addJustInTimeAtomsAndMarkLive(name);
1613 target = fGlobalSymbolTable.find(name);
1615 if ( target != NULL )
1616 fLiveRootAtoms.insert(target);
1619 void Linker::moveToFrontOfSection(ObjectFile::Atom* atom)
1621 // check if already moved to front
1622 if ( fInitializerAtoms.find(atom) == fInitializerAtoms.end() ) {
1623 // don't re-order initializers from .o files without MH_SUBSECTIONS_VIA_SYMBOLS
1624 // since that could make all atoms in the file look like initializers
1625 if ( atom->getFile()->canScatterAtoms() ) {
1626 //fprintf(stdout, "marking as initializer: %s\n", atom->getDisplayName());
1627 fInitializerAtoms.insert(atom);
1628 // mark all functions that this function references
1629 std::vector<class ObjectFile::Reference*>& references = atom->getReferences();
1630 for (std::vector<ObjectFile::Reference*>::const_iterator rit=references.begin(); rit != references.end(); rit++) {
1631 ObjectFile::Atom* childAtom = &((*rit)->getTarget());
1632 if ( childAtom != NULL ) {
1633 if ( (*rit)->isBranch() ) {
1634 this->moveToFrontOfSection(childAtom);
1636 else if ( (childAtom->getName() != NULL) && (strncmp(childAtom->getName(), "___tcf_", 7) == 0) ) {
1637 //fprintf(stdout, "marking as terminator: %s\n", childAtom->getDisplayName());
1638 fTerminatorAtoms.insert(childAtom);
1646 void Linker::deadStripResolve()
1648 // add main() to live roots
1649 ObjectFile::Atom* entryPoint = this->entryPoint(false, true);
1650 if ( entryPoint != NULL )
1651 fLiveRootAtoms.insert(entryPoint);
1653 // add dyld_stub_binding_helper/dyld_stub_binder to live roots
1654 ObjectFile::Atom* dyldHelper = this->dyldClassicHelper();
1655 if ( dyldHelper != NULL )
1656 fLiveRootAtoms.insert(dyldHelper);
1657 dyldHelper = this->dyldCompressedHelper();
1658 if ( dyldHelper != NULL )
1659 fLiveRootAtoms.insert(dyldHelper);
1661 // if using lazy dylib loading, add dyld_lazy_dylib_stub_binding_helper() to live roots
1662 if ( fOptions.usingLazyDylibLinking() ) {
1663 ObjectFile::Atom* dyldLazyDylibHelper = this->dyldLazyLibraryHelper();
1664 if ( dyldLazyDylibHelper != NULL )
1665 fLiveRootAtoms.insert(dyldLazyDylibHelper);
1668 // add -exported_symbols_list, -init, and -u entries to live roots
1669 std::vector<const char*>& initialUndefines = fOptions.initialUndefines();
1670 for (std::vector<const char*>::iterator it=initialUndefines.begin(); it != initialUndefines.end(); it++)
1671 addLiveRoot(*it);
1673 // if -exported_symbols_list that has wildcards, we need to find all matches and make them the roots
1674 // <rdar://problem/5524973>
1675 if ( fOptions.hasWildCardExportRestrictList() ) {
1676 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
1677 ObjectFile::Atom* atom = *it;
1678 if ( (atom->getScope() == ObjectFile::Atom::scopeGlobal)
1679 && (fDeadAtoms.count(atom) == 0)
1680 && fOptions.shouldExport(atom->getName()) )
1681 fLiveRootAtoms.insert(atom);
1685 // in some cases, every global scope atom in initial .o files is a root
1686 if ( fOptions.allGlobalsAreDeadStripRoots() ) {
1687 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
1688 ObjectFile::Atom* atom = *it;
1689 if ( (atom->getScope() == ObjectFile::Atom::scopeGlobal) && (fDeadAtoms.count(atom) == 0) )
1690 fLiveRootAtoms.insert(atom);
1694 // mark all roots as live, and all atoms they reference
1695 for (std::set<ObjectFile::Atom*>::iterator it=fLiveRootAtoms.begin(); it != fLiveRootAtoms.end(); it++) {
1696 WhyLiveBackChain rootChain;
1697 rootChain.previous = NULL;
1698 rootChain.referer = *it;
1699 markLive(**it, &rootChain);
1702 // it is possible that there are unresolved references that can be resolved now
1703 // this can happen if the first reference to a common symbol in an archive.
1704 // common symbols are not in the archive TOC, but the .o could have been pulled in later.
1705 // <rdar://problem/4654131> ld64 while linking cc1 [ when dead_strip is ON]
1706 for (std::vector<ObjectFile::Atom*>::iterator it=fAtomsWithUnresolvedReferences.begin(); it != fAtomsWithUnresolvedReferences.end(); it++) {
1707 std::vector<class ObjectFile::Reference*>& references = (*it)->getReferences();
1708 for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
1709 ObjectFile::Reference* reference = *rit;
1710 if ( reference->getTargetBinding() == ObjectFile::Reference::kUnboundByName ) {
1711 ObjectFile::Atom* target = fGlobalSymbolTable.find(reference->getTargetName());
1712 if ( target != NULL ) {
1713 reference->setTarget(*target, reference->getTargetOffset());
1714 fLiveAtoms.insert(target);
1715 // by just adding this atom to fLiveAtoms set, we are assuming it has no
1716 // references, which is true for commons.
1717 if ( target->getDefinitionKind() != ObjectFile::Atom::kTentativeDefinition )
1718 warning("internal error %s is not a tentative definition", target->getDisplayName());
1721 if ( reference->getFromTargetBinding() == ObjectFile::Reference::kUnboundByName ) {
1722 ObjectFile::Atom* target = fGlobalSymbolTable.find(reference->getFromTargetName());
1723 if ( target != NULL ) {
1724 reference->setFromTarget(*target);
1725 fLiveAtoms.insert(target);
1726 // by just adding this atom to fLiveAtoms set, we are assuming it has no
1727 // references, which is true for commons.
1728 if ( target->getDefinitionKind() != ObjectFile::Atom::kTentativeDefinition )
1729 warning("internal error %s is not a tentative definition", target->getDisplayName());
1735 // It is possible that some weak symbols were overridden by lazily load objects from archives
1736 // and we have some atoms that still refer to the overridden ones.
1737 // In that case we need to go back and rebind
1738 if ( fAtomsOverriddenByLateLoads.size() > 0 ) {
1739 for (std::set<ObjectFile::Atom*>::iterator it=fLiveAtoms.begin(); it != fLiveAtoms.end(); ++it) {
1740 ObjectFile::Atom* atom = *it;
1741 std::vector<class ObjectFile::Reference*>& references = atom->getReferences();
1742 for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); ++rit) {
1743 ObjectFile::Reference* reference = *rit;
1744 ObjectFile::Atom* toTarget = &reference->getTarget();
1745 if ( fAtomsOverriddenByLateLoads.count(toTarget) ) {
1746 //fprintf(stderr, "change reference in %p from %p to %p\n", atom, toTarget, fGlobalSymbolTable.find(toTarget->getName()));
1747 reference->setTarget(*fGlobalSymbolTable.find(toTarget->getName()), reference->getTargetOffset());
1749 ObjectFile::Atom* fromTarget = &reference->getFromTarget();
1750 if ( (fromTarget != NULL) && fAtomsOverriddenByLateLoads.count(fromTarget) ) {
1751 //fprintf(stderr, "change from reference in %p from %p to %p\n", atom, fromTarget, fGlobalSymbolTable.find(fromTarget->getName()));
1752 reference->setTarget(*fGlobalSymbolTable.find(fromTarget->getName()), reference->getFromTargetOffset());
1757 // make sure overriders are live if the atom they overrid was live
1758 for (std::set<ObjectFile::Atom*>::iterator it=fAtomsOverriddenByLateLoads.begin(); it != fAtomsOverriddenByLateLoads.end(); ++it) {
1759 ObjectFile::Atom* overriderAtom = *it;
1760 if ( fLiveAtoms.count(overriderAtom) ) {
1761 WhyLiveBackChain rootChain;
1762 rootChain.previous = NULL;
1763 rootChain.referer = *it;
1764 markLive(*fGlobalSymbolTable.find(overriderAtom->getName()), &rootChain);
1768 // remove overridden atoms from fLiveAtoms
1769 fAllAtoms.erase(std::remove_if(fAllAtoms.begin(), fAllAtoms.end(), InSet(fAtomsOverriddenByLateLoads)), fAllAtoms.end());
1770 fAtomsOverriddenByLateLoads.clear();
1771 // remove dead atoms from fLiveAtoms
1772 fAllAtoms.erase(std::remove_if(fAllAtoms.begin(), fAllAtoms.end(), InSet(fDeadAtoms)), fAllAtoms.end());
1775 // now remove all non-live atoms from fAllAtoms
1776 fAllAtoms.erase(std::remove_if(fAllAtoms.begin(), fAllAtoms.end(), NotLive(fLiveAtoms)), fAllAtoms.end());
1779 void Linker::checkObjC()
1781 // check dylibs
1782 switch ( fCurrentObjCConstraint ) {
1783 case ObjectFile::Reader::kObjcNone:
1784 // can link against any dylib
1785 break;
1786 case ObjectFile::Reader::kObjcRetainRelease:
1787 // cannot link against GC-only dylibs
1788 for (InstallNameToReader::iterator it=fDylibMap.begin(); it != fDylibMap.end(); it++) {
1789 if ( it->second->explicitlyLinked() ) {
1790 if ( it->second->getObjCConstraint() == ObjectFile::Reader::kObjcGC )
1791 throwf("this linkage unit uses Retain/Release. It cannot link against the GC-only dylib: %s", it->second->getPath());
1794 break;
1795 case ObjectFile::Reader::kObjcRetainReleaseOrGC:
1796 // can link against GC or RR dylibs
1797 break;
1798 case ObjectFile::Reader::kObjcGC:
1799 // cannot link against RR-only dylibs
1800 for (InstallNameToReader::iterator it=fDylibMap.begin(); it != fDylibMap.end(); it++) {
1801 if ( it->second->explicitlyLinked() ) {
1802 if ( it->second->getObjCConstraint() == ObjectFile::Reader::kObjcRetainRelease )
1803 throwf("this linkage unit requires GC. It cannot link against Retain/Release dylib: %s", it->second->getPath());
1806 break;
1809 // synthesize __OBJC __image_info atom if needed
1810 if ( fCurrentObjCConstraint != ObjectFile::Reader::kObjcNone ) {
1811 this->addAtom(fOutputFile->makeObjcInfoAtom(fCurrentObjCConstraint, fObjcReplacmentClasses));
1816 static uint8_t pcRelKind(cpu_type_t arch)
1818 switch ( arch ) {
1819 case CPU_TYPE_POWERPC:
1820 return ppc::kPointerDiff32;
1821 case CPU_TYPE_POWERPC64:
1822 return ppc64::kPointerDiff32;
1823 case CPU_TYPE_I386:
1824 return x86::kPointerDiff;
1825 case CPU_TYPE_X86_64:
1826 return x86_64::kPointerDiff32;
1827 case CPU_TYPE_ARM:
1828 return arm::kPointerDiff;
1830 throw "uknown architecture";
1833 typedef uint8_t* (*oldcreatedof_func_t) (const char*, cpu_type_t, unsigned int, const char*[], const char*[], uint64_t offsetsInDOF[], size_t* size);
1834 typedef uint8_t* (*createdof_func_t)(cpu_type_t, unsigned int, const char*[], unsigned int, const char*[], const char*[], uint64_t offsetsInDOF[], size_t* size);
1837 void Linker::processDTrace()
1839 // only make __dof section in final linked images
1840 if ( fOptions.outputKind() == Options::kObjectFile )
1841 return;
1843 // scan all atoms looking for dtrace probes
1844 std::vector<DTraceProbeInfo> probeSites;
1845 std::vector<DTraceProbeInfo> isEnabledSites;
1846 std::map<const ObjectFile::Atom*,CStringSet> atomToDtraceTypes;
1847 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); ++it) {
1848 ObjectFile::Atom* atom = *it;
1849 std::vector<class ObjectFile::Reference*>& references = atom->getReferences();
1850 for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); ++rit) {
1851 ObjectFile::Reference* ref = *rit;
1852 if ( ref->getTargetBinding() == ObjectFile::Reference::kDontBind ) {
1853 const char* probeName = ref->getTargetName();
1854 if ( probeName != NULL ) {
1855 uint32_t offsetInAtom = ref->getFixUpOffset();
1856 if ( strncmp(probeName, "___dtrace_probe$", 16) == 0 )
1857 probeSites.push_back(DTraceProbeInfo(atom, offsetInAtom, probeName));
1858 else if ( strncmp(probeName, "___dtrace_isenabled$", 20) == 0 )
1859 isEnabledSites.push_back(DTraceProbeInfo(atom, offsetInAtom, probeName));
1860 else if ( strncmp(probeName, "___dtrace_", 10) == 0 )
1861 atomToDtraceTypes[atom].insert(probeName);
1867 // if no probes, we're done
1868 if ( (probeSites.size() == 0) && (isEnabledSites.size() == 0) )
1869 return;
1871 // partition probes by provider name
1872 // The symbol names looks like:
1873 // "___dtrace_probe$" provider-name "$" probe-name [ "$"... ]
1874 // "___dtrace_isenabled$" provider-name "$" probe-name [ "$"... ]
1875 ProviderToProbes providerToProbes;
1876 std::vector<DTraceProbeInfo> emptyList;
1877 for(std::vector<DTraceProbeInfo>::iterator it = probeSites.begin(); it != probeSites.end(); ++it) {
1878 // ignore probes in functions that were coalesed away rdar://problem/5628149
1879 if ( fDeadAtoms.count((ObjectFile::Atom*)(it->atom)) == 0 ) {
1880 const char* providerStart = &it->probeName[16];
1881 const char* providerEnd = strchr(providerStart, '$');
1882 if ( providerEnd != NULL ) {
1883 char providerName[providerEnd-providerStart+1];
1884 strlcpy(providerName, providerStart, providerEnd-providerStart+1);
1885 ProviderToProbes::iterator pos = providerToProbes.find(providerName);
1886 if ( pos == providerToProbes.end() ) {
1887 const char* dup = strdup(providerName);
1888 providerToProbes[dup] = emptyList;
1890 providerToProbes[providerName].push_back(*it);
1894 for(std::vector<DTraceProbeInfo>::iterator it = isEnabledSites.begin(); it != isEnabledSites.end(); ++it) {
1895 // ignore probes in functions that were coalesed away rdar://problem/5628149
1896 if ( fDeadAtoms.count((ObjectFile::Atom*)(it->atom)) == 0 ) {
1897 const char* providerStart = &it->probeName[20];
1898 const char* providerEnd = strchr(providerStart, '$');
1899 if ( providerEnd != NULL ) {
1900 char providerName[providerEnd-providerStart+1];
1901 strlcpy(providerName, providerStart, providerEnd-providerStart+1);
1902 ProviderToProbes::iterator pos = providerToProbes.find(providerName);
1903 if ( pos == providerToProbes.end() ) {
1904 const char* dup = strdup(providerName);
1905 providerToProbes[dup] = emptyList;
1907 providerToProbes[providerName].push_back(*it);
1912 // create a DOF section for each provider
1913 int dofIndex=1;
1914 CStringSet sectionNamesUsed;
1915 for(ProviderToProbes::iterator pit = providerToProbes.begin(); pit != providerToProbes.end(); ++pit, ++dofIndex) {
1916 const char* providerName = pit->first;
1917 const std::vector<DTraceProbeInfo>& probes = pit->second;
1919 // open library and find dtrace_create_dof()
1920 void* handle = dlopen("/usr/lib/libdtrace.dylib", RTLD_LAZY);
1921 if ( handle == NULL )
1922 throwf("couldn't dlopen() /usr/lib/libdtrace.dylib: %s", dlerror());
1923 createdof_func_t pCreateDOF = (createdof_func_t)dlsym(handle, "dtrace_ld_create_dof");
1924 if ( pCreateDOF == NULL )
1925 throwf("couldn't find \"dtrace_ld_create_dof\" in /usr/lib/libdtrace.dylib: %s", dlerror());
1926 // build list of typedefs/stability infos for this provider
1927 CStringSet types;
1928 for(std::vector<DTraceProbeInfo>::const_iterator it = probes.begin(); it != probes.end(); ++it) {
1929 std::map<const ObjectFile::Atom*,CStringSet>::iterator pos = atomToDtraceTypes.find(it->atom);
1930 if ( pos != atomToDtraceTypes.end() ) {
1931 for(CStringSet::iterator sit = pos->second.begin(); sit != pos->second.end(); ++sit) {
1932 const char* providerStart = strchr(*sit, '$')+1;
1933 const char* providerEnd = strchr(providerStart, '$');
1934 if ( providerEnd != NULL ) {
1935 char aProviderName[providerEnd-providerStart+1];
1936 strlcpy(aProviderName, providerStart, providerEnd-providerStart+1);
1937 if ( strcmp(aProviderName, providerName) == 0 )
1938 types.insert(*sit);
1943 int typeCount = types.size();
1944 const char* typeNames[typeCount];
1945 //fprintf(stderr, "types for %s:\n", providerName);
1946 uint32_t index = 0;
1947 for(CStringSet::iterator it = types.begin(); it != types.end(); ++it) {
1948 typeNames[index] = *it;
1949 //fprintf(stderr, "\t%s\n", *it);
1950 ++index;
1953 // build list of probe/isenabled sites
1954 const uint32_t probeCount = probes.size();
1955 const char* probeNames[probeCount];
1956 const char* funtionNames[probeCount];
1957 uint64_t offsetsInDOF[probeCount];
1958 index = 0;
1959 for(std::vector<DTraceProbeInfo>::const_iterator it = probes.begin(); it != probes.end(); ++it) {
1960 probeNames[index] = it->probeName;
1961 funtionNames[index] = it->atom->getName();
1962 offsetsInDOF[index] = 0;
1963 ++index;
1965 //fprintf(stderr, "calling libtrace to create DOF\n");
1966 //for(uint32_t i=0; i < probeCount; ++i)
1967 // fprintf(stderr, " [%u]\t %s\t%s\n", i, probeNames[i], funtionNames[i]);
1968 // call dtrace library to create DOF section
1969 size_t dofSectionSize;
1970 uint8_t* p = (*pCreateDOF)(fArchitecture, typeCount, typeNames, probeCount, probeNames, funtionNames, offsetsInDOF, &dofSectionSize);
1971 if ( p != NULL ) {
1972 char sectionName[18];
1973 strcpy(sectionName, "__dof_");
1974 strlcpy(&sectionName[6], providerName, 10);
1975 // create unique section name so each DOF is in its own section
1976 if ( sectionNamesUsed.count(sectionName) != 0 ) {
1977 sectionName[15] = '0';
1978 sectionName[16] = '\0';
1979 while ( sectionNamesUsed.count(sectionName) != 0 )
1980 ++sectionName[15];
1982 sectionNamesUsed.insert(sectionName);
1983 char symbolName[strlen(providerName)+64];
1984 sprintf(symbolName, "__dtrace_dof_for_provider_%s", providerName);
1985 opaque_section::Reader* reader = new opaque_section::Reader("__TEXT", sectionName,
1986 "dtrace", p, dofSectionSize, fNextInputOrdinal, symbolName);
1987 fNextInputOrdinal += dofSectionSize;
1988 // add references
1989 for (uint32_t i=0; i < probeCount; ++i) {
1990 uint64_t offset = offsetsInDOF[i];
1991 //fprintf(stderr, "%s offset[%d]=0x%08llX\n", providerName, i, offset);
1992 if ( offset > dofSectionSize )
1993 throwf("offsetsInDOF[%d]=%0llX > dofSectionSize=%0lX\n", i, offset, dofSectionSize);
1994 reader->addSectionReference(pcRelKind(fArchitecture), offset, probes[i].atom, probes[i].offset, reader->getAtoms()[0], 0);
1996 this->addAtoms(reader->getAtoms());
1998 else {
1999 throw "error creating dtrace DOF section";
2005 static bool matchesObjectFile(ObjectFile::Atom* atom, const char* objectFileLeafName)
2007 if ( objectFileLeafName == NULL )
2008 return true;
2009 const char* atomFullPath = atom->getFile()->getPath();
2010 const char* lastSlash = strrchr(atomFullPath, '/');
2011 if ( lastSlash != NULL ) {
2012 if ( strcmp(&lastSlash[1], objectFileLeafName) == 0 )
2013 return true;
2015 else {
2016 if ( strcmp(atomFullPath, objectFileLeafName) == 0 )
2017 return true;
2019 return false;
2023 static bool usesAnonymousNamespace(const char* symbol)
2025 return ( (strncmp(symbol, "__Z", 3) == 0) && (strstr(symbol, "_GLOBAL__N_") != NULL) );
2030 // convert:
2031 // __ZN20_GLOBAL__N__Z5main2v3barEv => _ZN-3barEv
2032 // __ZN37_GLOBAL__N_main.cxx_00000000_493A01A33barEv => _ZN-3barEv
2034 static void canonicalizeAnonymousName(const char* inSymbol, char outSymbol[])
2036 const char* globPtr = strstr(inSymbol, "_GLOBAL__N_");
2037 while ( isdigit(*(--globPtr)) )
2038 ; // loop
2039 char* endptr;
2040 unsigned long length = strtoul(globPtr+1, &endptr, 10);
2041 const char* globEndPtr = endptr + length;
2042 int startLen = globPtr-inSymbol+1;
2043 memcpy(outSymbol, inSymbol, startLen);
2044 outSymbol[startLen] = '-';
2045 strcpy(&outSymbol[startLen+1], globEndPtr);
2049 ObjectFile::Atom* Linker::findAtom(const Options::OrderedSymbol& orderedSymbol)
2051 ObjectFile::Atom* atom = fGlobalSymbolTable.find(orderedSymbol.symbolName);
2052 if ( atom != NULL ) {
2053 if ( matchesObjectFile(atom, orderedSymbol.objectFileName) )
2054 return atom;
2056 else {
2057 // slow case. The requested symbol is not in symbol table, so might be static function
2058 static SymbolTable::Mapper hashTableOfTranslationUnitScopedSymbols;
2059 static SymbolTable::Mapper hashTableOfSymbolsWithAnonymousNamespace;
2060 static bool built = false;
2061 // build a hash_map the first time
2062 if ( !built ) {
2063 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
2064 atom = *it;
2065 const char* name = atom->getName();
2066 if ( name != NULL) {
2067 if ( usesAnonymousNamespace(name) ) {
2068 // symbol that uses anonymous namespace
2069 char canonicalName[strlen(name)+2];
2070 canonicalizeAnonymousName(name, canonicalName);
2071 const char* hashName = strdup(canonicalName);
2072 SymbolTable::Mapper::iterator pos = hashTableOfSymbolsWithAnonymousNamespace.find(hashName);
2073 if ( pos == hashTableOfSymbolsWithAnonymousNamespace.end() )
2074 hashTableOfSymbolsWithAnonymousNamespace[hashName] = atom;
2075 else
2076 hashTableOfSymbolsWithAnonymousNamespace[hashName] = NULL; // collision, denote with NULL
2078 else if ( atom->getScope() == ObjectFile::Atom::scopeTranslationUnit ) {
2079 // static function or data
2080 SymbolTable::Mapper::iterator pos = hashTableOfTranslationUnitScopedSymbols.find(name);
2081 if ( pos == hashTableOfTranslationUnitScopedSymbols.end() )
2082 hashTableOfTranslationUnitScopedSymbols[name] = atom;
2083 else
2084 hashTableOfTranslationUnitScopedSymbols[name] = NULL; // collision, denote with NULL
2088 //fprintf(stderr, "built hash table of %lu static functions\n", hashTableOfTranslationUnitScopedSymbols.size());
2089 built = true;
2092 // look for name in hashTableOfTranslationUnitScopedSymbols
2093 SymbolTable::Mapper::iterator pos = hashTableOfTranslationUnitScopedSymbols.find(orderedSymbol.symbolName);
2094 if ( pos != hashTableOfTranslationUnitScopedSymbols.end() ) {
2095 if ( (pos->second != NULL) && matchesObjectFile(pos->second, orderedSymbol.objectFileName) ) {
2096 //fprintf(stderr, "found %s in hash table\n", orderedSymbol.symbolName);
2097 return pos->second;
2099 if ( pos->second == NULL )
2100 // name is in hash table, but atom is NULL, so that means there are duplicates, so we use super slow way
2101 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
2102 atom = *it;
2103 if ( atom->getScope() == ObjectFile::Atom::scopeTranslationUnit ) {
2104 const char* name = atom->getName();
2105 if ( (name != NULL) && (strcmp(name, orderedSymbol.symbolName) == 0) ) {
2106 if ( matchesObjectFile(atom, orderedSymbol.objectFileName) ) {
2107 if ( fOptions.printOrderFileStatistics() )
2108 warning("%s specified in order_file but it exists in multiple .o files. "
2109 "Prefix symbol with .o filename in order_file to disambiguate", orderedSymbol.symbolName);
2110 return atom;
2117 // look for name in hashTableOfSymbolsWithAnonymousNamespace
2118 if ( usesAnonymousNamespace(orderedSymbol.symbolName) ) {
2119 // symbol that uses anonymous namespace
2120 char canonicalName[strlen(orderedSymbol.symbolName)+2];
2121 canonicalizeAnonymousName(orderedSymbol.symbolName, canonicalName);
2122 SymbolTable::Mapper::iterator pos = hashTableOfSymbolsWithAnonymousNamespace.find(canonicalName);
2123 if ( pos != hashTableOfSymbolsWithAnonymousNamespace.end() ) {
2124 if ( (pos->second != NULL) && matchesObjectFile(pos->second, orderedSymbol.objectFileName) ) {
2125 //fprintf(stderr, "found %s in anonymous namespace hash table\n", canonicalName);
2126 return pos->second;
2128 if ( pos->second == NULL )
2129 // name is in hash table, but atom is NULL, so that means there are duplicates, so we use super slow way
2130 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
2131 atom = *it;
2132 const char* name = atom->getName();
2133 if ( (name != NULL) && usesAnonymousNamespace(name) ) {
2134 char canonicalAtomName[strlen(name)+2];
2135 canonicalizeAnonymousName(name, canonicalAtomName);
2136 if ( strcmp(canonicalAtomName, canonicalName) == 0 ) {
2137 if ( matchesObjectFile(atom, orderedSymbol.objectFileName) ) {
2138 if ( fOptions.printOrderFileStatistics() )
2139 warning("%s specified in order_file but it exists in multiple .o files. "
2140 "Prefix symbol with .o filename in order_file to disambiguate", orderedSymbol.symbolName);
2141 return atom;
2149 return NULL;
2153 void Linker::sortSections()
2155 Section::assignIndexes();
2160 // Linker::sortAtoms()
2162 // The purpose of this method is to take the graph of all Atoms and produce an ordered
2163 // sequence of atoms. The constraints are that: 1) all Atoms of the same Segment must
2164 // be contiguous, 2) all Atoms of the same Section must be contigous, 3) Atoms specified
2165 // in an order_file are seqenced as in the order_file and before Atoms not specified,
2166 // 4) Atoms in the same section from the same .o file should be contiguous and sequenced
2167 // in the same order they were in the .o file, 5) Atoms in the same Section but which came
2168 // from different .o files should be sequenced in the same order that the .o files
2169 // were passed to the linker (i.e. command line order).
2171 // The way this is implemented is that the linker passes a "base ordinal" to each Reader
2172 // as it is constructed. The reader should construct it Atoms so that calling getOrdinal()
2173 // on its atoms returns a contiguous range of values starting at the base ordinal. Then
2174 // sorting is just sorting by section, then by ordinal.
2176 // If an order_file is specified, it gets more complicated. First, an override-ordinal map
2177 // is created. It causes the sort routine to ignore the value returned by getOrdinal() and
2178 // use the override value instead. Next some Atoms must be layed out consecutively
2179 // (e.g. hand written assembly that does not end with return, but rather falls into
2180 // the next label). This is modeled in Readers via a "kFollowOn" reference. The use of
2181 // kFollowOn refernces produces "clusters" of atoms that must stay together.
2182 // If an order_file tries to move one atom, it may need to move a whole cluster. The
2183 // algorithm to do this models clusters using two maps. The "starts" maps maps any
2184 // atom in a cluster to the first Atom in the cluster. The "nexts" maps an Atom in a
2185 // cluster to the next Atom in the cluster. With this in place, while processing an
2186 // order_file, if any entry is in a cluster (in "starts" map), then the entire cluster is
2187 // given ordinal overrides.
2189 void Linker::sortAtoms()
2191 fStartSortTime = mach_absolute_time();
2192 // if -order_file is used, build map of atom ordinal overrides
2193 std::map<const ObjectFile::Atom*, uint32_t>* ordinalOverrideMap = NULL;
2194 std::map<const ObjectFile::Atom*, uint32_t> theOrdinalOverrideMap;
2195 const bool log = false;
2196 if ( fOptions.orderedSymbols().size() != 0 ) {
2197 // first make a pass to find all follow-on references and build start/next maps
2198 // which are a way to represent clusters of atoms that must layout together
2199 std::map<const ObjectFile::Atom*, const ObjectFile::Atom*> followOnStarts;
2200 std::map<const ObjectFile::Atom*, const ObjectFile::Atom*> followOnNexts;
2201 for (std::vector<ObjectFile::Atom*>::iterator ait=fAllAtoms.begin(); ait != fAllAtoms.end(); ait++) {
2202 ObjectFile::Atom* atom = *ait;
2203 std::vector<class ObjectFile::Reference*>& references = atom->getReferences();
2204 for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
2205 ObjectFile::Reference* ref = *rit;
2206 if ( ref->getKind() == 1 ) { // FIX FIX
2207 ObjectFile::Atom* targetAtom = &ref->getTarget();
2208 if ( log ) fprintf(stderr, "ref %s -> %s", atom->getDisplayName(), targetAtom->getDisplayName());
2209 std::map<const ObjectFile::Atom*, const ObjectFile::Atom*>::iterator startFrom = followOnStarts.find(atom);
2210 std::map<const ObjectFile::Atom*, const ObjectFile::Atom*>::iterator startTo = followOnStarts.find(targetAtom);
2211 if ( (startFrom == followOnStarts.end()) && (startTo == followOnStarts.end()) ) {
2212 // this is first time we've seen either atom, make simple cluster of the two
2213 if ( log ) fprintf(stderr, " new cluster\n");
2214 followOnStarts[atom] = atom;
2215 followOnStarts[targetAtom] = atom;
2216 followOnNexts[atom] = targetAtom;
2217 followOnNexts[targetAtom] = NULL;
2219 else if ( (startFrom != followOnStarts.end()) && (startTo == followOnStarts.end()) && (followOnNexts[atom] == NULL) ) {
2220 // atom is at end of an existing cluster, so append target to end of cluster
2221 if ( log ) fprintf(stderr, " end of cluster starting with %s\n", followOnStarts[atom]->getDisplayName());
2222 followOnNexts[atom] = targetAtom;
2223 followOnNexts[targetAtom] = NULL;
2224 followOnStarts[targetAtom] = followOnStarts[atom];
2226 else {
2227 // gerneral case of inserting into an existing cluster
2228 if ( followOnNexts[atom] != NULL ) {
2229 // an atom with two follow-ons is illegal
2230 warning("can't order %s because both %s and %s must follow it",
2231 atom->getDisplayName(), targetAtom->getDisplayName(), followOnNexts[atom]->getDisplayName());
2233 else {
2234 // there already exists an atom that says target must be its follow-on
2235 const ObjectFile::Atom* originalStart = startTo->second;
2236 const ObjectFile::Atom* originalPrevious = originalStart;
2237 while ( followOnNexts[originalPrevious] != targetAtom )
2238 originalPrevious = followOnNexts[originalPrevious];
2239 bool otherIsAlias = (originalPrevious->getSize() == 0);
2240 bool thisIsAlias = (atom->getSize() == 0);
2241 if ( !otherIsAlias && !thisIsAlias ) {
2242 warning("can't order %s because both %s and %s must preceed it",
2243 targetAtom->getDisplayName(), originalPrevious->getDisplayName(), atom->getDisplayName());
2245 else if ( otherIsAlias ) {
2246 if ( originalPrevious == originalStart ) {
2247 // other is alias at start of cluster, make this the new start of cluster
2248 if ( log ) fprintf(stderr, " becomes new start of cluster previous starting with %s\n", originalStart->getDisplayName());
2249 followOnNexts[atom] = originalPrevious;
2250 for(const ObjectFile::Atom* nextAtom = atom; nextAtom != NULL; nextAtom = followOnNexts[nextAtom])
2251 followOnStarts[nextAtom] = atom;
2253 else {
2254 // other is alias in middle of cluster, insert new atom before it
2255 if ( log ) fprintf(stderr, " insert into cluster starting with %s before alias %s\n", originalStart->getDisplayName(), originalPrevious->getDisplayName());
2256 followOnStarts[atom] = originalStart;
2257 followOnNexts[atom] = originalPrevious;
2258 for(const ObjectFile::Atom* a = originalStart; a != NULL; a = followOnNexts[a]) {
2259 if ( followOnNexts[a] == originalPrevious ) {
2260 followOnNexts[a] = atom;
2261 break;
2266 else {
2267 // this is alias, so it can go inbetween originalPrevious and targetAtom
2268 if ( log ) fprintf(stderr, " insert into cluster starting with %s after %s\n", originalStart->getDisplayName(), originalPrevious->getDisplayName());
2269 followOnStarts[atom] = originalStart;
2270 followOnNexts[atom] = followOnNexts[originalPrevious];
2271 followOnNexts[originalPrevious] = atom;
2279 if ( log ) {
2280 for(std::map<const ObjectFile::Atom*, const ObjectFile::Atom*>::iterator it = followOnStarts.begin(); it != followOnStarts.end(); ++it)
2281 fprintf(stderr, "start %s -> %s\n", it->first->getDisplayName(), it->second->getDisplayName());
2283 for(std::map<const ObjectFile::Atom*, const ObjectFile::Atom*>::iterator it = followOnNexts.begin(); it != followOnNexts.end(); ++it)
2284 fprintf(stderr, "next %s -> %s\n", it->first->getDisplayName(), (it->second != NULL) ? it->second->getDisplayName() : "null");
2287 // with the start/next maps of follow-on atoms we can process the order file and produce override ordinals
2288 ordinalOverrideMap = &theOrdinalOverrideMap;
2289 uint32_t index = 0;
2290 uint32_t matchCount = 0;
2291 std::vector<Options::OrderedSymbol>& orderedSymbols = fOptions.orderedSymbols();
2292 for(std::vector<Options::OrderedSymbol>::iterator it = orderedSymbols.begin(); it != orderedSymbols.end(); ++it) {
2293 ObjectFile::Atom* atom = this->findAtom(*it);
2294 if ( atom != NULL ) {
2295 std::map<const ObjectFile::Atom*, const ObjectFile::Atom*>::iterator start = followOnStarts.find(atom);
2296 if ( start != followOnStarts.end() ) {
2297 // this symbol for the order file corresponds to an atom that is in a cluster that must lay out together
2298 for(const ObjectFile::Atom* nextAtom = start->second; nextAtom != NULL; nextAtom = followOnNexts[nextAtom]) {
2299 std::map<const ObjectFile::Atom*, uint32_t>::iterator pos = theOrdinalOverrideMap.find(nextAtom);
2300 if ( pos == theOrdinalOverrideMap.end() ) {
2301 theOrdinalOverrideMap[nextAtom] = index++;
2302 if (log ) fprintf(stderr, "override ordinal %u assigned to %s in cluster from %s\n", index, nextAtom->getDisplayName(), nextAtom->getFile()->getPath());
2304 else {
2305 if (log ) fprintf(stderr, "could not order %s as %u because it was already laid out earlier by %s as %u\n",
2306 atom->getDisplayName(), index, followOnStarts[atom]->getDisplayName(), theOrdinalOverrideMap[atom] );
2310 else {
2311 theOrdinalOverrideMap[atom] = index;
2312 if (log ) fprintf(stderr, "override ordinal %u assigned to %s from %s\n", index, atom->getDisplayName(), atom->getFile()->getPath());
2314 ++matchCount;
2316 else {
2317 if ( fOptions.printOrderFileStatistics() ) {
2318 if ( it->objectFileName == NULL )
2319 warning("can't find match for order_file entry: %s", it->symbolName);
2320 else
2321 warning("can't find match for order_file entry: %s/%s", it->objectFileName, it->symbolName);
2324 ++index;
2326 if ( fOptions.printOrderFileStatistics() && (fOptions.orderedSymbols().size() != matchCount) ) {
2327 warning("only %u out of %lu order_file symbols were applicable", matchCount, fOptions.orderedSymbols().size() );
2331 // sort atoms
2332 std::sort(fAllAtoms.begin(), fAllAtoms.end(), Linker::AtomSorter(ordinalOverrideMap, fInitializerAtoms, fTerminatorAtoms));
2334 //fprintf(stderr, "Sorted atoms:\n");
2335 //for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
2336 // fprintf(stderr, "\t%s, %u %s\t%s\n", (*it)->getSectionName(), (*it)->getSection()->getIndex(), (*it)->getDisplayName(), (*it)->getFile()->getPath());
2341 // make sure given addresses are within reach of branches, etc
2342 void Linker::tweakLayout()
2344 // > 2GB images need their large zero fill atoms sorted to the end to keep access with +/- 2GB
2345 if ( fTotalSize > 0x7F000000 ) {
2346 fBiggerThanTwoGigOutput = true;
2348 if ( (fTotalSize-fTotalZeroFillSize) > 0x7F000000 )
2349 throwf("total output size exceeds 2GB (%lldMB)", (fTotalSize-fTotalZeroFillSize)/(1024*1024));
2351 // move very large (>1MB) zero fill atoms to a new section at very end of __DATA segment
2352 Section* hugeZeroFills = Section::find("__huge", "__DATA", true, true);
2353 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
2354 ObjectFile::Atom* atom = *it;
2355 if ( atom->isZeroFill() && (atom->getSize() > 1024*1024) && (strcmp(atom->getSegment().getName(), "__DATA") == 0) )
2356 atom->setSection(hugeZeroFills);
2360 // move all initializers to start of __text section
2361 if ( fOptions.readerOptions().fAutoOrderInitializers ) {
2362 // move -init function to front of __text
2363 if ( fOptions.initFunctionName() != NULL ) {
2364 ObjectFile::Atom* initAtom = fGlobalSymbolTable.find(fOptions.initFunctionName());
2365 if ( initAtom == NULL )
2366 throwf("could not find -init function: \"%s\"", fOptions.initFunctionName());
2367 moveToFrontOfSection(initAtom);
2370 // move all functions pointed to by __mod_init_func section to front of __text
2371 Section* initSection = Section::find("__mod_init_func", "__DATA", false, true, false);
2372 if ( initSection != NULL ) {
2373 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); ++it) {
2374 if ( (*it)->getSection() == initSection ) {
2375 std::vector<class ObjectFile::Reference*>& references = (*it)->getReferences();
2376 if ( references.size() == 1 )
2377 moveToFrontOfSection(&(references[0]->getTarget()));
2383 // move atoms with relocations to start of __DATA,__data section
2384 // <rdar://problem/6061558> linker should order __DATA segment to reduce dyld dirtied pages
2385 if ( fOptions.orderData() ) {
2386 bool slideable = false;
2387 switch ( fOptions.outputKind() ) {
2388 case Options::kDynamicExecutable:
2389 case Options::kStaticExecutable:
2390 case Options::kDyld:
2391 case Options::kPreload:
2392 case Options::kObjectFile:
2393 case Options::kKextBundle:
2394 slideable = false;
2395 break;
2396 case Options::kDynamicLibrary:
2397 case Options::kDynamicBundle:
2398 slideable = true;
2399 break;
2401 const bool hasPreferredLoadAddress = (fOptions.baseAddress() != 0);
2402 Section* dataSection = Section::find("__data", "__DATA", false, true, false);
2403 if ( dataSection != NULL ) {
2404 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); ++it) {
2405 ObjectFile::Atom* dataAtom = *it;
2406 if ( dataAtom->getSection() == dataSection ) {
2407 std::vector<class ObjectFile::Reference*>& references = dataAtom->getReferences();
2408 if ( references.size() > 0 ) {
2409 if ( slideable && !hasPreferredLoadAddress ) {
2410 // in a slidable image dyld will need to rebase and bind so any references will need runtime fixups
2411 // if image has preferred base address, assume it will load there and not rebase
2412 moveToFrontOfSection(dataAtom);
2414 else {
2415 // in a non-slideable image, dyld will only do binding, so only references to
2416 // symbols in another dylib will need runtime fixups
2417 //fprintf(stderr, "reference from atom %s\n", dataAtom->getDisplayName());
2418 for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
2419 ObjectFile::Reference* reference = *rit;
2420 //fprintf(stderr, "\t%d %s\n", reference->getTarget().getDefinitionKind(), reference->getTarget().getDisplayName());
2421 if ( (reference->getTarget().getDefinitionKind() == ObjectFile::Atom::kExternalDefinition)
2422 || (reference->getTarget().getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition) ) {
2423 moveToFrontOfSection(dataAtom);
2424 break;
2437 void Linker::writeDotOutput()
2439 const char* dotOutFilePath = fOptions.dotOutputFile();
2440 if ( dotOutFilePath != NULL ) {
2441 FILE* out = fopen(dotOutFilePath, "w");
2442 if ( out != NULL ) {
2443 // print header
2444 fprintf(out, "digraph dg\n{\n");
2445 fprintf(out, "\tconcentrate = true;\n");
2446 fprintf(out, "\trankdir = LR;\n");
2448 // print each atom as a node
2449 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
2450 ObjectFile::Atom* atom = *it;
2451 if ( atom->getFile() != fOutputFile ) {
2452 const char* name = atom->getDisplayName();
2453 if ( (atom->getDefinitionKind() == ObjectFile::Atom::kExternalDefinition)
2454 || (atom->getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition) ) {
2455 fprintf(out, "\taddr%p [ shape = plaintext, label = \"%s\" ];\n", atom, name);
2457 else if ( strcmp(atom->getSectionName(), "__cstring") == 0 ) {
2458 char cstring[atom->getSize()+2];
2459 atom->copyRawContent((uint8_t*)cstring);
2460 fprintf(out, "\taddr%p [ label = \"string: '", atom);
2461 for (const char* s=cstring; *s != '\0'; ++s) {
2462 if ( *s == '\n' )
2463 fprintf(out, "\\\\n");
2464 else
2465 fputc(*s, out);
2467 fprintf(out, "'\" ];\n");
2469 else {
2470 fprintf(out, "\taddr%p [ label = \"%s\" ];\n", atom, name);
2474 fprintf(out, "\n");
2476 // print each reference as an edge
2477 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
2478 ObjectFile::Atom* fromAtom = *it;
2479 if ( fromAtom->getFile() != fOutputFile ) {
2480 std::vector<ObjectFile::Reference*>& references = fromAtom->getReferences();
2481 std::set<ObjectFile::Atom*> seenTargets;
2482 for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
2483 ObjectFile::Reference* reference = *rit;
2484 ObjectFile::Atom* toAtom = &(reference->getTarget());
2485 if ( seenTargets.count(toAtom) == 0 ) {
2486 seenTargets.insert(toAtom);
2487 fprintf(out, "\taddr%p -> addr%p;\n", fromAtom, toAtom);
2492 fprintf(out, "\n");
2494 // push all imports to bottom of graph
2495 fprintf(out, "{ rank = same; ");
2496 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
2497 ObjectFile::Atom* atom = *it;
2498 if ( atom->getFile() != fOutputFile )
2499 if ( (atom->getDefinitionKind() == ObjectFile::Atom::kExternalDefinition)
2500 || (atom->getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition) ) {
2501 fprintf(out, "addr%p; ", atom);
2504 fprintf(out, "};\n ");
2506 // print footer
2507 fprintf(out, "}\n");
2508 fclose(out);
2510 else {
2511 warning("could not write dot output file: %s", dotOutFilePath);
2516 ObjectFile::Atom* Linker::entryPoint(bool orInit, bool searchArchives)
2518 // if main executable, find entry point atom
2519 ObjectFile::Atom* entryPoint = NULL;
2520 switch ( fOptions.outputKind() ) {
2521 case Options::kDynamicExecutable:
2522 case Options::kStaticExecutable:
2523 case Options::kDyld:
2524 case Options::kPreload:
2525 entryPoint = fGlobalSymbolTable.find(fOptions.entryName());
2526 if ( (entryPoint == NULL) && searchArchives ) {
2527 // <rdar://problem/7043256> ld64 can not find a -e entry point from an archive
2528 this->addJustInTimeAtoms(fOptions.entryName(), false, true, false);
2529 entryPoint = fGlobalSymbolTable.find(fOptions.entryName());
2531 if ( entryPoint == NULL ) {
2532 throwf("could not find entry point \"%s\" (perhaps missing crt1.o)", fOptions.entryName());
2534 break;
2535 case Options::kDynamicLibrary:
2536 if ( orInit && (fOptions.initFunctionName() != NULL) ) {
2537 entryPoint = fGlobalSymbolTable.find(fOptions.initFunctionName());
2538 if ( entryPoint == NULL ) {
2539 throwf("could not find -init function: \"%s\"", fOptions.initFunctionName());
2542 break;
2543 case Options::kObjectFile:
2544 case Options::kDynamicBundle:
2545 case Options::kKextBundle:
2546 entryPoint = NULL;
2547 break;
2549 return entryPoint;
2552 ObjectFile::Atom* Linker::dyldClassicHelper()
2554 if ( fOptions.makeClassicDyldInfo() )
2555 return fGlobalSymbolTable.find("dyld_stub_binding_helper");
2556 else
2557 return NULL;
2560 ObjectFile::Atom* Linker::dyldCompressedHelper()
2562 if ( fOptions.makeCompressedDyldInfo() ) {
2563 // dyld_stub_binder is in libSystem.B.dylib
2564 ObjectFile::Atom* atom = fGlobalSymbolTable.find("dyld_stub_binder");
2565 if ( atom == NULL ) {
2566 this->addJustInTimeAtoms("dyld_stub_binder", true, false, true);
2568 atom = fGlobalSymbolTable.find("dyld_stub_binder");
2569 return atom;
2571 else
2572 return NULL;
2575 ObjectFile::Atom* Linker::dyldLazyLibraryHelper()
2577 return fGlobalSymbolTable.find("dyld_lazy_dylib_stub_binding_helper");
2580 const char* Linker::assureFullPath(const char* path)
2582 if ( path[0] == '/' )
2583 return path;
2584 char cwdbuff[MAXPATHLEN];
2585 if ( getcwd(cwdbuff, MAXPATHLEN) != NULL ) {
2586 char* result;
2587 asprintf(&result, "%s/%s", cwdbuff, path);
2588 if ( result != NULL )
2589 return result;
2591 return path;
2596 // The stab strings are of the form:
2597 // <name> ':' <type-code> <number-pari>
2598 // but the <name> contain a colon.
2599 // For C++ <name> may contain a double colon (e.g. std::string:f(0,1) )
2600 // For Objective-C name may contain a colon instead square bracket (e.g. [Foo doit:]:f(0,1) )
2602 const char* Linker::truncateStabString(const char* str)
2604 enum { start, inObjc } state = start;
2605 for (const char* s = str; *s != 0; ++s) {
2606 char c = *s;
2607 switch (state) {
2608 case start:
2609 if ( c == '[' ) {
2610 state = inObjc;
2612 else {
2613 if ( c == ':' ) {
2614 if ( s[1] == ':' ) {
2615 ++s;
2617 else {
2618 // found colon
2619 // Duplicate strndup behavior here.
2620 int trunStrLen = s-str+2;
2621 char* temp = new char[trunStrLen+1];
2622 memcpy(temp, str, trunStrLen);
2623 temp[trunStrLen] = '\0';
2624 return temp;
2628 break;
2629 case inObjc:
2630 if ( c == ']' ) {
2631 state = start;
2633 break;
2636 // malformed
2637 return str;
2641 bool Linker::minimizeStab(ObjectFile::Reader::Stab& stab)
2643 switch(stab.type){
2644 case N_GSYM:
2645 case N_STSYM:
2646 case N_LCSYM:
2647 case N_FUN:
2648 // these all need truncated strings
2649 stab.string = truncateStabString(stab.string);
2650 return true;
2651 case N_SO:
2652 case N_OSO:
2653 case N_OPT:
2654 case N_SOL:
2655 // these are included in the minimal stabs, but they keep their full string
2656 return true;
2657 default:
2658 return false;
2663 struct HeaderRange {
2664 std::vector<ObjectFile::Reader::Stab>::iterator begin;
2665 std::vector<ObjectFile::Reader::Stab>::iterator end;
2666 int parentRangeIndex;
2667 uint32_t sum;
2668 bool sumPrecomputed;
2669 bool useEXCL;
2670 bool cannotEXCL; // because of SLINE, etc stabs
2674 typedef __gnu_cxx::hash_map<const char*, std::vector<uint32_t>, __gnu_cxx::hash<const char*>, CStringEquals> PathToSums;
2676 // hash table that maps header path to a vector of known checksums for that path
2677 static PathToSums sKnownBINCLs;
2680 void Linker::collectStabs(ObjectFile::Reader* reader, std::map<const class ObjectFile::Atom*, uint32_t>& atomOrdinals)
2682 const bool log = false;
2683 bool minimal = ( fOptions.readerOptions().fDebugInfoStripping == ObjectFile::ReaderOptions::kDebugInfoMinimal );
2684 std::vector<class ObjectFile::Reader::Stab>* readerStabs = reader->getStabs();
2685 if ( readerStabs == NULL )
2686 return;
2688 if ( log ) fprintf(stderr, "processesing %lu stabs for %s\n", readerStabs->size(), reader->getPath());
2689 std::vector<HeaderRange> ranges;
2690 int curRangeIndex = -1;
2691 int count = 0;
2692 ObjectFile::Atom* atomWithLowestOrdinal = NULL;
2693 ObjectFile::Atom* atomWithHighestOrdinal = NULL;
2694 uint32_t highestOrdinal = 0;
2695 uint32_t lowestOrdinal = UINT_MAX;
2696 std::vector<std::pair<ObjectFile::Atom*,ObjectFile::Atom*> > soRanges;
2697 // 1) find all (possibly nested) BINCL/EINCL ranges and their checksums
2698 // 2) find all SO/SO ranges and the first/last atom own by a FUN stab therein
2699 for(std::vector<class ObjectFile::Reader::Stab>::iterator it=readerStabs->begin(); it != readerStabs->end(); ++it) {
2700 ++count;
2701 switch ( it->type ) {
2702 case N_BINCL:
2704 HeaderRange range;
2705 range.begin = it;
2706 range.end = readerStabs->end();
2707 range.parentRangeIndex = curRangeIndex;
2708 range.sum = it->value;
2709 range.sumPrecomputed = (range.sum != 0);
2710 range.useEXCL = false;
2711 range.cannotEXCL = false;
2712 curRangeIndex = ranges.size();
2713 if ( log ) fprintf(stderr, "[%d]BINCL %s\n", curRangeIndex, it->string);
2714 ranges.push_back(range);
2716 break;
2717 case N_EINCL:
2718 if ( curRangeIndex == -1 ) {
2719 warning("EINCL missing BINCL in %s", reader->getPath());
2721 else {
2722 ranges[curRangeIndex].end = it+1;
2723 if ( log ) fprintf(stderr, "[%d->%d]EINCL %s\n", curRangeIndex, ranges[curRangeIndex].parentRangeIndex, it->string);
2724 curRangeIndex = ranges[curRangeIndex].parentRangeIndex;
2726 break;
2727 case N_FUN:
2729 std::map<const class ObjectFile::Atom*, uint32_t>::iterator pos = atomOrdinals.find(it->atom);
2730 if ( pos != atomOrdinals.end() ) {
2731 uint32_t ordinal = pos->second;
2732 if ( ordinal > highestOrdinal ) {
2733 highestOrdinal = ordinal;
2734 atomWithHighestOrdinal = it->atom;
2736 if ( ordinal < lowestOrdinal ) {
2737 lowestOrdinal = ordinal;
2738 atomWithLowestOrdinal = it->atom;
2742 // fall through
2743 case N_BNSYM:
2744 case N_ENSYM:
2745 case N_LBRAC:
2746 case N_RBRAC:
2747 case N_SLINE:
2748 case N_STSYM:
2749 case N_LCSYM:
2750 if ( curRangeIndex != -1 ) {
2751 ranges[curRangeIndex].cannotEXCL = true;
2752 if ( fOptions.warnStabs() )
2753 warning("cannot do BINCL/EINCL optimzation because of stabs kinds in %s for %s\n", ranges[curRangeIndex].begin->string, reader->getPath());
2755 break;
2756 case N_SO:
2757 if ( (it->string != NULL) && (strlen(it->string) > 0) ) {
2758 // start SO, reset hi/low FUN tracking
2759 atomWithLowestOrdinal = NULL;
2760 atomWithHighestOrdinal = NULL;
2761 highestOrdinal = 0;
2762 lowestOrdinal = UINT_MAX;
2764 else {
2765 // end SO, record hi/low atoms for this SO range
2766 soRanges.push_back(std::make_pair<ObjectFile::Atom*,ObjectFile::Atom*>(atomWithLowestOrdinal, atomWithHighestOrdinal));
2768 // fall through
2769 default:
2770 if ( curRangeIndex != -1 ) {
2771 if ( ! ranges[curRangeIndex].sumPrecomputed ) {
2772 uint32_t sum = 0;
2773 const char* s = it->string;
2774 char c;
2775 while ( (c = *s++) != 0 ) {
2776 sum += c;
2777 // don't checkusm first number (file index) after open paren in string
2778 if ( c == '(' ) {
2779 while(isdigit(*s))
2780 ++s;
2783 ranges[curRangeIndex].sum += sum;
2789 if ( log ) fprintf(stderr, "processesed %d stabs for %s\n", count, reader->getPath());
2790 if ( curRangeIndex != -1 )
2791 warning("BINCL (%s) missing EINCL in %s", ranges[curRangeIndex].begin->string, reader->getPath());
2793 // if no BINCLs
2794 if ( ranges.size() == 0 ) {
2795 unsigned int soIndex = 0;
2796 for(std::vector<ObjectFile::Reader::Stab>::iterator it=readerStabs->begin(); it != readerStabs->end(); ++it) {
2797 // copy minimal or all stabs
2798 ObjectFile::Reader::Stab stab = *it;
2799 if ( !minimal || minimizeStab(stab) ) {
2800 if ( stab.type == N_SO ) {
2801 if ( soIndex < soRanges.size() ) {
2802 if ( (stab.string != NULL) && (strlen(stab.string) > 0) ) {
2803 // starting SO is associated with first atom
2804 stab.atom = soRanges[soIndex].first;
2806 else {
2807 // ending SO is associated with last atom
2808 stab.atom = soRanges[soIndex].second;
2809 ++soIndex;
2813 fStabs.push_back(stab);
2816 return;
2819 //fprintf(stderr, "BINCL/EINCL info for %s\n", reader->getPath());
2820 //for(std::vector<HeaderRange>::iterator it=ranges.begin(); it != ranges.end(); ++it) {
2821 // fprintf(stderr, "%08X %s\n", it->sum, it->begin->string);
2824 // see if any of these BINCL/EINCL ranges have already been seen and therefore can be replaced with EXCL
2825 for(std::vector<HeaderRange>::iterator it=ranges.begin(); it != ranges.end(); ++it) {
2826 if ( ! it->cannotEXCL ) {
2827 const char* header = it->begin->string;
2828 uint32_t sum = it->sum;
2829 PathToSums::iterator pos = sKnownBINCLs.find(header);
2830 if ( pos != sKnownBINCLs.end() ) {
2831 std::vector<uint32_t>& sums = pos->second;
2832 for(std::vector<uint32_t>::iterator sit=sums.begin(); sit != sums.end(); ++sit) {
2833 if (*sit == sum) {
2834 //fprintf(stderr, "use EXCL for %s in %s\n", header, reader->getPath());
2835 it->useEXCL = true;
2836 break;
2839 if ( ! it->useEXCL ) {
2840 // have seen this path, but not this checksum
2841 //fprintf(stderr, "registering another checksum %08X for %s\n", sum, header);
2842 sums.push_back(sum);
2845 else {
2846 // have not seen this path, so add to known BINCLs
2847 std::vector<uint32_t> empty;
2848 sKnownBINCLs[header] = empty;
2849 sKnownBINCLs[header].push_back(sum);
2850 //fprintf(stderr, "registering checksum %08X for %s\n", sum, header);
2855 // add a new set of stabs with BINCL/EINCL runs that have been seen before, replaced with EXCLs
2856 curRangeIndex = -1;
2857 const int maxRangeIndex = ranges.size();
2858 int soIndex = 0;
2859 for(std::vector<ObjectFile::Reader::Stab>::iterator it=readerStabs->begin(); it != readerStabs->end(); ++it) {
2860 switch ( it->type ) {
2861 case N_BINCL:
2862 for(int i=curRangeIndex+1; i < maxRangeIndex; ++i) {
2863 if ( ranges[i].begin == it ) {
2864 curRangeIndex = i;
2865 HeaderRange& range = ranges[curRangeIndex];
2866 ObjectFile::Reader::Stab stab = *it;
2867 stab.value = range.sum; // BINCL and EXCL have n_value set to checksum
2868 if ( range.useEXCL )
2869 stab.type = N_EXCL; // transform BINCL into EXCL
2870 if ( !minimal )
2871 fStabs.push_back(stab);
2872 break;
2875 break;
2876 case N_EINCL:
2877 if ( curRangeIndex != -1 ) {
2878 if ( !ranges[curRangeIndex].useEXCL && !minimal )
2879 fStabs.push_back(*it);
2880 curRangeIndex = ranges[curRangeIndex].parentRangeIndex;
2882 break;
2883 default:
2884 if ( (curRangeIndex == -1) || !ranges[curRangeIndex].useEXCL ) {
2885 ObjectFile::Reader::Stab stab = *it;
2886 if ( !minimal || minimizeStab(stab) ) {
2887 if ( stab.type == N_SO ) {
2888 if ( (stab.string != NULL) && (strlen(stab.string) > 0) ) {
2889 // starting SO is associated with first atom
2890 stab.atom = soRanges[soIndex].first;
2892 else {
2893 // ending SO is associated with last atom
2894 stab.atom = soRanges[soIndex].second;
2895 ++soIndex;
2898 fStabs.push_back(stab);
2907 // used to prune out atoms that don't need debug notes generated
2908 class NoDebugNoteAtom
2910 public:
2911 NoDebugNoteAtom(const std::map<class ObjectFile::Reader*, uint32_t>& readersWithDwarfOrdinals)
2912 : fReadersWithDwarfOrdinals(readersWithDwarfOrdinals) {}
2914 bool operator()(const ObjectFile::Atom* atom) const {
2915 if ( atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn )
2916 return true;
2917 if ( atom->getName() == NULL )
2918 return true;
2919 if ( fReadersWithDwarfOrdinals.find(atom->getFile()) == fReadersWithDwarfOrdinals.end() )
2920 return true;
2921 return false;
2924 private:
2925 const std::map<class ObjectFile::Reader*, uint32_t>& fReadersWithDwarfOrdinals;
2928 // used to sort atoms with debug notes
2929 class ReadersWithDwarfSorter
2931 public:
2932 ReadersWithDwarfSorter(const std::map<class ObjectFile::Reader*, uint32_t>& readersWithDwarfOrdinals,
2933 const std::map<const class ObjectFile::Atom*, uint32_t>& atomOrdinals)
2934 : fReadersWithDwarfOrdinals(readersWithDwarfOrdinals), fAtomOrdinals(atomOrdinals) {}
2936 bool operator()(const ObjectFile::Atom* left, const ObjectFile::Atom* right) const
2938 // first sort by reader
2939 unsigned int leftReaderIndex = fReadersWithDwarfOrdinals.find(left->getFile())->second;
2940 unsigned int rightReaderIndex = fReadersWithDwarfOrdinals.find(right->getFile())->second;
2941 if ( leftReaderIndex != rightReaderIndex )
2942 return (leftReaderIndex < rightReaderIndex);
2944 // then sort by atom ordinal
2945 unsigned int leftAtomIndex = fAtomOrdinals.find(left)->second;
2946 unsigned int rightAtomIndex = fAtomOrdinals.find(right)->second;
2947 return leftAtomIndex < rightAtomIndex;
2950 private:
2951 const std::map<class ObjectFile::Reader*, uint32_t>& fReadersWithDwarfOrdinals;
2952 const std::map<const class ObjectFile::Atom*, uint32_t>& fAtomOrdinals;
2959 void Linker::synthesizeDebugNotes(std::vector<class ObjectFile::Atom*>& allAtomsByReader)
2961 // synthesize "debug notes" and add them to master stabs vector
2962 const char* dirPath = NULL;
2963 const char* filename = NULL;
2964 bool wroteStartSO = false;
2965 bool useZeroOSOModTime = (getenv("RC_RELEASE") != NULL);
2966 __gnu_cxx::hash_set<const char*, __gnu_cxx::hash<const char*>, CStringEquals> seenFiles;
2967 for (std::vector<ObjectFile::Atom*>::iterator it=allAtomsByReader.begin(); it != allAtomsByReader.end(); it++) {
2968 ObjectFile::Atom* atom = *it;
2969 const char* newDirPath;
2970 const char* newFilename;
2971 //fprintf(stderr, "debug note for %s\n", atom->getDisplayName());
2972 if ( atom->getTranslationUnitSource(&newDirPath, &newFilename) ) {
2973 // need SO's whenever the translation unit source file changes
2974 if ( newFilename != filename ) {
2975 // gdb like directory SO's to end in '/', but dwarf DW_AT_comp_dir usually does not have trailing '/'
2976 if ( (newDirPath != NULL) && (strlen(newDirPath) > 1 ) && (newDirPath[strlen(newDirPath)-1] != '/') )
2977 asprintf((char**)&newDirPath, "%s/", newDirPath);
2978 if ( filename != NULL ) {
2979 // translation unit change, emit ending SO
2980 ObjectFile::Reader::Stab endFileStab;
2981 endFileStab.atom = NULL;
2982 endFileStab.type = N_SO;
2983 endFileStab.other = 1;
2984 endFileStab.desc = 0;
2985 endFileStab.value = 0;
2986 endFileStab.string = "";
2987 fStabs.push_back(endFileStab);
2989 // new translation unit, emit start SO's
2990 ObjectFile::Reader::Stab dirPathStab;
2991 dirPathStab.atom = NULL;
2992 dirPathStab.type = N_SO;
2993 dirPathStab.other = 0;
2994 dirPathStab.desc = 0;
2995 dirPathStab.value = 0;
2996 dirPathStab.string = newDirPath;
2997 fStabs.push_back(dirPathStab);
2998 ObjectFile::Reader::Stab fileStab;
2999 fileStab.atom = NULL;
3000 fileStab.type = N_SO;
3001 fileStab.other = 0;
3002 fileStab.desc = 0;
3003 fileStab.value = 0;
3004 fileStab.string = newFilename;
3005 fStabs.push_back(fileStab);
3006 // Synthesize OSO for start of file
3007 ObjectFile::Reader::Stab objStab;
3008 objStab.atom = NULL;
3009 objStab.type = N_OSO;
3010 // <rdar://problem/6337329> linker should put cpusubtype in n_sect field of nlist entry for N_OSO debug note entries
3011 objStab.other = atom->getFile()->updateCpuConstraint(0);
3012 objStab.desc = 1;
3013 objStab.value = useZeroOSOModTime ? 0 : atom->getFile()->getModificationTime();
3014 objStab.string = assureFullPath(atom->getFile()->getPath());
3015 fStabs.push_back(objStab);
3016 wroteStartSO = true;
3017 // add the source file path to seenFiles so it does not show up in SOLs
3018 seenFiles.insert(newFilename);
3020 filename = newFilename;
3021 dirPath = newDirPath;
3022 if ( atom->getSegment().isContentExecutable() && (strncmp(atom->getSectionName(), "__text", 6) == 0) ) {
3023 // Synthesize BNSYM and start FUN stabs
3024 ObjectFile::Reader::Stab beginSym;
3025 beginSym.atom = atom;
3026 beginSym.type = N_BNSYM;
3027 beginSym.other = 1;
3028 beginSym.desc = 0;
3029 beginSym.value = 0;
3030 beginSym.string = "";
3031 fStabs.push_back(beginSym);
3032 ObjectFile::Reader::Stab startFun;
3033 startFun.atom = atom;
3034 startFun.type = N_FUN;
3035 startFun.other = 1;
3036 startFun.desc = 0;
3037 startFun.value = 0;
3038 startFun.string = atom->getName();
3039 fStabs.push_back(startFun);
3040 // Synthesize any SOL stabs needed
3041 std::vector<ObjectFile::LineInfo>* lineInfo = atom->getLineInfo();
3042 if ( lineInfo != NULL ) {
3043 const char* curFile = NULL;
3044 for (std::vector<ObjectFile::LineInfo>::iterator it = lineInfo->begin(); it != lineInfo->end(); ++it) {
3045 if ( it->fileName != curFile ) {
3046 if ( seenFiles.count(it->fileName) == 0 ) {
3047 seenFiles.insert(it->fileName);
3048 ObjectFile::Reader::Stab sol;
3049 sol.atom = 0;
3050 sol.type = N_SOL;
3051 sol.other = 0;
3052 sol.desc = 0;
3053 sol.value = 0;
3054 sol.string = it->fileName;
3055 fStabs.push_back(sol);
3057 curFile = it->fileName;
3061 // Synthesize end FUN and ENSYM stabs
3062 ObjectFile::Reader::Stab endFun;
3063 endFun.atom = atom;
3064 endFun.type = N_FUN;
3065 endFun.other = 0;
3066 endFun.desc = 0;
3067 endFun.value = 0;
3068 endFun.string = "";
3069 fStabs.push_back(endFun);
3070 ObjectFile::Reader::Stab endSym;
3071 endSym.atom = atom;
3072 endSym.type = N_ENSYM;
3073 endSym.other = 1;
3074 endSym.desc = 0;
3075 endSym.value = 0;
3076 endSym.string = "";
3077 fStabs.push_back(endSym);
3079 else if ( atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn ) {
3080 // no stabs for atoms that would not be in the symbol table
3082 else if ( atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableInAsAbsolute ) {
3083 // no stabs for absolute symbols
3085 else if ( (strcmp(atom->getSectionName(), "__eh_frame") == 0) ) {
3086 // no stabs for .eh atoms
3088 else if ( (strncmp(atom->getName(), "__dtrace_probe$", 15) == 0) ) {
3089 // no stabs for old style dtrace probes
3091 else {
3092 ObjectFile::Reader::Stab globalsStab;
3093 const char* name = atom->getName();
3094 if ( atom->getScope() == ObjectFile::Atom::scopeTranslationUnit ) {
3095 // Synthesize STSYM stab for statics
3096 globalsStab.atom = atom;
3097 globalsStab.type = N_STSYM;
3098 globalsStab.other = 1;
3099 globalsStab.desc = 0;
3100 globalsStab.value = 0;
3101 globalsStab.string = name;
3102 fStabs.push_back(globalsStab);
3104 else {
3105 // Synthesize GSYM stab for other globals
3106 globalsStab.atom = atom;
3107 globalsStab.type = N_GSYM;
3108 globalsStab.other = 1;
3109 globalsStab.desc = 0;
3110 globalsStab.value = 0;
3111 globalsStab.string = name;
3112 fStabs.push_back(globalsStab);
3118 if ( wroteStartSO ) {
3119 // emit ending SO
3120 ObjectFile::Reader::Stab endFileStab;
3121 endFileStab.atom = NULL;
3122 endFileStab.type = N_SO;
3123 endFileStab.other = 1;
3124 endFileStab.desc = 0;
3125 endFileStab.value = 0;
3126 endFileStab.string = "";
3127 fStabs.push_back(endFileStab);
3134 void Linker::collectDebugInfo()
3136 std::map<const class ObjectFile::Atom*, uint32_t> atomOrdinals;
3137 fStartDebugTime = mach_absolute_time();
3138 if ( fOptions.readerOptions().fDebugInfoStripping != ObjectFile::ReaderOptions::kDebugInfoNone ) {
3140 // determine mixture of stabs and dwarf
3141 bool someStabs = false;
3142 bool someDwarf = false;
3143 for (std::vector<class ObjectFile::Reader*>::iterator it=fReadersThatHaveSuppliedAtoms.begin();
3144 it != fReadersThatHaveSuppliedAtoms.end();
3145 it++) {
3146 ObjectFile::Reader* reader = *it;
3147 if ( reader != NULL ) {
3148 switch ( reader->getDebugInfoKind() ) {
3149 case ObjectFile::Reader::kDebugInfoNone:
3150 break;
3151 case ObjectFile::Reader::kDebugInfoStabs:
3152 someStabs = true;
3153 break;
3154 case ObjectFile::Reader::kDebugInfoDwarf:
3155 someDwarf = true;
3156 fCreateUUID = true;
3157 break;
3158 case ObjectFile::Reader::kDebugInfoStabsUUID:
3159 someStabs = true;
3160 fCreateUUID = true;
3161 break;
3162 default:
3163 throw "Unhandled type of debug information";
3168 if ( someDwarf || someStabs ) {
3169 // try to minimize re-allocations
3170 fStabs.reserve(1024);
3172 // make mapping from atoms to ordinal
3173 uint32_t ordinal = 1;
3174 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
3175 atomOrdinals[*it] = ordinal++;
3179 // process all dwarf .o files as a batch
3180 if ( someDwarf ) {
3181 // make mapping from readers with dwarf to ordinal
3182 std::map<class ObjectFile::Reader*, uint32_t> readersWithDwarfOrdinals;
3183 uint32_t readerOrdinal = 1;
3184 for (std::vector<class ObjectFile::Reader*>::iterator it=fReadersThatHaveSuppliedAtoms.begin();
3185 it != fReadersThatHaveSuppliedAtoms.end();
3186 it++) {
3187 ObjectFile::Reader* reader = *it;
3188 if ( (reader != NULL) && (reader->getDebugInfoKind() == ObjectFile::Reader::kDebugInfoDwarf) ) {
3189 readersWithDwarfOrdinals[reader] = readerOrdinal++;
3193 // make a vector of atoms
3194 std::vector<class ObjectFile::Atom*> allAtomsByReader(fAllAtoms.begin(), fAllAtoms.end());
3195 // remove those not from a reader that has dwarf
3196 allAtomsByReader.erase(std::remove_if(allAtomsByReader.begin(), allAtomsByReader.end(),
3197 NoDebugNoteAtom(readersWithDwarfOrdinals)), allAtomsByReader.end());
3198 // sort by reader then atom ordinal
3199 std::sort(allAtomsByReader.begin(), allAtomsByReader.end(), ReadersWithDwarfSorter(readersWithDwarfOrdinals, atomOrdinals));
3200 // add debug notes for each atom
3201 this->synthesizeDebugNotes(allAtomsByReader);
3204 // process all stabs .o files one by one
3205 if ( someStabs ) {
3206 // get stabs from each reader, in command line order
3207 for (std::vector<class ObjectFile::Reader*>::iterator it=fReadersThatHaveSuppliedAtoms.begin();
3208 it != fReadersThatHaveSuppliedAtoms.end();
3209 it++) {
3210 ObjectFile::Reader* reader = *it;
3211 if ( reader != NULL ) {
3212 switch ( reader->getDebugInfoKind() ) {
3213 case ObjectFile::Reader::kDebugInfoDwarf:
3214 case ObjectFile::Reader::kDebugInfoNone:
3215 // do nothing
3216 break;
3217 case ObjectFile::Reader::kDebugInfoStabs:
3218 case ObjectFile::Reader::kDebugInfoStabsUUID:
3219 collectStabs(reader, atomOrdinals);
3220 break;
3221 default:
3222 throw "Unhandled type of debug information";
3226 // remove stabs associated with atoms that won't be in output
3227 std::set<class ObjectFile::Atom*> allAtomsSet;
3228 allAtomsSet.insert(fAllAtoms.begin(), fAllAtoms.end());
3229 fStabs.erase(std::remove_if(fStabs.begin(), fStabs.end(), NotInSet(allAtomsSet)), fStabs.end());
3234 void Linker::writeOutput()
3236 // <rdar://problem/6933931> ld -r of empty .o file should preserve sub-type
3237 // <rdar://problem/7049478> empty dylib should have subtype from command line
3238 if ( fOptions.preferSubArchitecture() && (fOptions.architecture() == CPU_TYPE_ARM) ) {
3239 fCurrentCpuConstraint = (ObjectFile::Reader::CpuConstraint)fOptions.subArchitecture();
3242 if ( fOptions.forceCpuSubtypeAll() )
3243 fCurrentCpuConstraint = ObjectFile::Reader::kCpuAny;
3245 fStartWriteTime = mach_absolute_time();
3246 // tell writer about each segment's atoms
3247 fOutputFileSize = fOutputFile->write(fAllAtoms, fStabs, this->entryPoint(true),
3248 fCreateUUID, fCanScatter,
3249 fCurrentCpuConstraint,
3250 fRegularDefAtomsThatOverrideADylibsWeakDef,
3251 fGlobalSymbolTable.hasExternalWeakDefinitions());
3254 const char* Linker::fileArch(const void* p)
3256 const uint8_t* bytes = (uint8_t*)p;
3257 const char* result;
3258 result = mach_o::relocatable::Reader<ppc>::fileKind(bytes);
3259 if ( result != NULL )
3260 return result;
3261 result = mach_o::relocatable::Reader<ppc64>::fileKind(bytes);
3262 if ( result != NULL )
3263 return result;
3264 result = mach_o::relocatable::Reader<x86>::fileKind(bytes);
3265 if ( result != NULL )
3266 return result;
3267 result = mach_o::relocatable::Reader<x86_64>::fileKind(bytes);
3268 if ( result != NULL )
3269 return result;
3270 result = mach_o::relocatable::Reader<arm>::fileKind(bytes);
3271 if ( result != NULL )
3272 return result;
3274 result = lto::Reader::fileKind(bytes);
3275 if ( result != NULL )
3276 return result;
3278 return "unsupported file format";
3281 ObjectFile::Reader* Linker::createReader(const Options::FileInfo& info)
3283 // map in whole file
3284 uint64_t len = info.fileLen;
3285 int fd = ::open(info.path, O_RDONLY, 0);
3286 if ( fd == -1 )
3287 throwf("can't open file, errno=%d", errno);
3288 if ( info.fileLen < 20 )
3289 throw "file too small";
3291 uint8_t* p = (uint8_t*)::mmap(NULL, info.fileLen, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
3292 if ( p == (uint8_t*)(-1) )
3293 throwf("can't map file, errno=%d", errno);
3295 // if fat file, skip to architecture we want
3296 // Note: fat header is always big-endian
3297 bool isFatFile = false;
3298 const fat_header* fh = (fat_header*)p;
3299 if ( fh->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) {
3300 isFatFile = true;
3301 const struct fat_arch* archs = (struct fat_arch*)(p + sizeof(struct fat_header));
3302 uint32_t sliceToUse;
3303 bool sliceFound = false;
3304 if ( fOptions.preferSubArchitecture() ) {
3305 // first try to find a slice that match cpu-type and cpu-sub-type
3306 for (uint32_t i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) {
3307 if ( (OSSwapBigToHostInt32(archs[i].cputype) == (uint32_t)fArchitecture)
3308 && (OSSwapBigToHostInt32(archs[i].cpusubtype) == (uint32_t)fOptions.subArchitecture()) ) {
3309 sliceToUse = i;
3310 sliceFound = true;
3311 break;
3315 if ( !sliceFound ) {
3316 // look for any slice that matches just cpu-type
3317 for (uint32_t i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) {
3318 if ( OSSwapBigToHostInt32(archs[i].cputype) == (uint32_t)fArchitecture ) {
3319 sliceToUse = i;
3320 sliceFound = true;
3321 break;
3325 if ( sliceFound ) {
3326 uint32_t fileOffset = OSSwapBigToHostInt32(archs[sliceToUse].offset);
3327 len = OSSwapBigToHostInt32(archs[sliceToUse].size);
3328 // if requested architecture is page aligned within fat file, then remap just that portion of file
3329 if ( (fileOffset & 0x00000FFF) == 0 ) {
3330 // unmap whole file
3331 munmap((caddr_t)p, info.fileLen);
3332 // re-map just part we need
3333 p = (uint8_t*)::mmap(NULL, len, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, fileOffset);
3334 if ( p == (uint8_t*)(-1) )
3335 throwf("can't re-map file, errno=%d", errno);
3337 else {
3338 p = &p[fileOffset];
3342 ::close(fd);
3344 bool objSubtypeMustMatch = (fOptions.preferSubArchitecture() && !fOptions.allowSubArchitectureMismatches());
3345 switch (fArchitecture) {
3346 case CPU_TYPE_POWERPC:
3347 if ( mach_o::relocatable::Reader<ppc>::validFile(p) )
3348 return this->addObject(new mach_o::relocatable::Reader<ppc>::Reader(p, info.path, info.modTime, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3349 else if ( mach_o::dylib::Reader<ppc>::validFile(p, info.options.fBundleLoader) )
3350 return this->addDylib(new mach_o::dylib::Reader<ppc>::Reader(p, len, info.path, info.options, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3351 else if ( archive::Reader<ppc>::validFile(p, len) )
3352 return this->addArchive(new archive::Reader<ppc>::Reader(p, len, info.path, info.modTime, info.options, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3353 break;
3354 case CPU_TYPE_POWERPC64:
3355 if ( mach_o::relocatable::Reader<ppc64>::validFile(p) )
3356 return this->addObject(new mach_o::relocatable::Reader<ppc64>::Reader(p, info.path, info.modTime, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3357 else if ( mach_o::dylib::Reader<ppc64>::validFile(p, info.options.fBundleLoader) )
3358 return this->addDylib(new mach_o::dylib::Reader<ppc64>::Reader(p, len, info.path, info.options, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3359 else if ( archive::Reader<ppc64>::validFile(p, len) )
3360 return this->addArchive(new archive::Reader<ppc64>::Reader(p, len, info.path, info.modTime, info.options, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3361 break;
3362 case CPU_TYPE_I386:
3363 if ( mach_o::relocatable::Reader<x86>::validFile(p) )
3364 return this->addObject(new mach_o::relocatable::Reader<x86>::Reader(p, info.path, info.modTime, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3365 else if ( mach_o::dylib::Reader<x86>::validFile(p, info.options.fBundleLoader) )
3366 return this->addDylib(new mach_o::dylib::Reader<x86>::Reader(p, len, info.path, info.options, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3367 else if ( archive::Reader<x86>::validFile(p, len) )
3368 return this->addArchive(new archive::Reader<x86>::Reader(p, len, info.path, info.modTime, info.options, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3369 break;
3370 case CPU_TYPE_X86_64:
3371 if ( mach_o::relocatable::Reader<x86_64>::validFile(p) )
3372 return this->addObject(new mach_o::relocatable::Reader<x86_64>::Reader(p, info.path, info.modTime, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3373 else if ( mach_o::dylib::Reader<x86_64>::validFile(p, info.options.fBundleLoader) )
3374 return this->addDylib(new mach_o::dylib::Reader<x86_64>::Reader(p, len, info.path, info.options, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3375 else if ( archive::Reader<x86_64>::validFile(p, len) )
3376 return this->addArchive(new archive::Reader<x86_64>::Reader(p, len, info.path, info.modTime, info.options, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3377 case CPU_TYPE_ARM:
3378 if ( mach_o::relocatable::Reader<arm>::validFile(p, objSubtypeMustMatch, fOptions.subArchitecture()) )
3379 return this->addObject(new mach_o::relocatable::Reader<arm>::Reader(p, info.path, info.modTime, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3380 else if ( mach_o::dylib::Reader<arm>::validFile(p, info.options.fBundleLoader) )
3381 return this->addDylib(new mach_o::dylib::Reader<arm>::Reader(p, len, info.path, info.options, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3382 else if ( archive::Reader<arm>::validFile(p, len) )
3383 return this->addArchive(new archive::Reader<arm>::Reader(p, len, info.path, info.modTime, info.options, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3384 break;
3387 #if LTO_SUPPORT
3388 if ( lto::Reader::validFile(p, len, fArchitecture) ) {
3389 return this->addObject(new lto::Reader(p, len, info.path, info.modTime, fOptions.readerOptions(), fArchitecture), info, len);
3391 else if ( lto::Reader::fileKind((uint8_t*)p) != NULL ) {
3392 if ( lto::Reader::loaded() ) {
3393 throwf("file was built for %s which is not the architecture being linked (%s)", fileArch(p), fArchitectureName);
3395 else {
3396 const char* libLTO = "libLTO.dylib";
3397 char ldPath[PATH_MAX];
3398 char tmpPath[PATH_MAX];
3399 char libLTOPath[PATH_MAX];
3400 uint32_t bufSize = PATH_MAX;
3401 if ( _NSGetExecutablePath(ldPath, &bufSize) != -1 ) {
3402 if ( realpath(ldPath, tmpPath) != NULL ) {
3403 char* lastSlash = strrchr(tmpPath, '/');
3404 if ( lastSlash != NULL )
3405 strcpy(lastSlash, "/../lib/libLTO.dylib");
3406 libLTO = tmpPath;
3407 if ( realpath(tmpPath, libLTOPath) != NULL )
3408 libLTO = libLTOPath;
3411 throwf("could not process llvm bitcode object file, because %s could not be loaded", libLTO);
3414 #endif
3415 // error handling
3416 if ( ((fat_header*)p)->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) {
3417 throwf("missing required architecture %s in file", fArchitectureName);
3419 else {
3420 if ( isFatFile )
3421 throwf("file is universal but does not contain a(n) %s slice", fArchitectureName);
3422 else
3423 throwf("file was built for %s which is not the architecture being linked (%s)", fileArch(p), fArchitectureName);
3427 void Linker::logDylib(ObjectFile::Reader* reader, bool indirect)
3429 if ( fOptions.readerOptions().fTraceDylibs ) {
3430 const char* fullPath = reader->getPath();
3431 char realName[MAXPATHLEN];
3432 if ( realpath(fullPath, realName) != NULL )
3433 fullPath = realName;
3434 if ( indirect )
3435 logTraceInfo("[Logging for XBS] Used indirect dynamic library: %s\n", fullPath);
3436 else
3437 logTraceInfo("[Logging for XBS] Used dynamic library: %s\n", fullPath);
3443 ObjectFile::Reader* Linker::findDylib(const char* installPath, const char* fromPath)
3445 //fprintf(stderr, "findDylib(%s, %s)\n", installPath, fromPath);
3446 InstallNameToReader::iterator pos = fDylibMap.find(installPath);
3447 if ( pos != fDylibMap.end() ) {
3448 return pos->second;
3450 else {
3451 // allow -dylib_path option to override indirect library to use
3452 for (std::vector<Options::DylibOverride>::iterator dit = fOptions.dylibOverrides().begin(); dit != fOptions.dylibOverrides().end(); ++dit) {
3453 if ( strcmp(dit->installName,installPath) == 0 ) {\
3454 try {
3455 Options::FileInfo info = fOptions.findFile(dit->useInstead);
3456 ObjectFile::Reader* reader = this->createReader(info);
3457 fDylibMap[strdup(installPath)] = reader;
3458 this->logDylib(reader, true);
3459 return reader;
3461 catch (const char* msg) {
3462 warning("ignoring -dylib_file option, %s", msg);
3466 char newPath[MAXPATHLEN];
3467 // handle @loader_path
3468 if ( strncmp(installPath, "@loader_path/", 13) == 0 ) {
3469 strcpy(newPath, fromPath);
3470 char* addPoint = strrchr(newPath,'/');
3471 if ( addPoint != NULL )
3472 strcpy(&addPoint[1], &installPath[13]);
3473 else
3474 strcpy(newPath, &installPath[13]);
3475 installPath = newPath;
3477 // note: @executable_path case is handled inside findFileUsingPaths()
3478 // search for dylib using -F and -L paths
3479 Options::FileInfo info = fOptions.findFileUsingPaths(installPath);
3480 try {
3481 ObjectFile::Reader* reader = this->createReader(info);
3482 fDylibMap[strdup(installPath)] = reader;
3483 this->logDylib(reader, true);
3484 return reader;
3486 catch (const char* msg) {
3487 throwf("in %s, %s", info.path, msg);
3493 void Linker::processDylibs()
3495 fAllDirectDylibsLoaded = true;
3497 // mark all dylibs initially specified as required and check if they can be used
3498 for (InstallNameToReader::iterator it=fDylibMap.begin(); it != fDylibMap.end(); it++) {
3499 it->second->setExplicitlyLinked();
3500 this->checkDylibClientRestrictions(it->second);
3503 // keep processing dylibs until no more dylibs are added
3504 unsigned long lastMapSize = 0;
3505 while ( lastMapSize != fDylibMap.size() ) {
3506 lastMapSize = fDylibMap.size();
3507 // can't iterator fDylibMap while modifying it, so use temp buffer
3508 std::vector<ObjectFile::Reader*> currentUnprocessedReaders;
3509 for (InstallNameToReader::iterator it=fDylibMap.begin(); it != fDylibMap.end(); it++) {
3510 if ( fDylibsProcessed.count(it->second) == 0 )
3511 currentUnprocessedReaders.push_back(it->second);
3513 for (std::vector<ObjectFile::Reader*>::iterator it=currentUnprocessedReaders.begin(); it != currentUnprocessedReaders.end(); it++) {
3514 fDylibsProcessed.insert(*it);
3515 (*it)->processIndirectLibraries(this);
3519 // go back over original dylibs and mark sub frameworks as re-exported
3520 if ( fOptions.outputKind() == Options::kDynamicLibrary ) {
3521 const char* myLeaf = strrchr(fOptions.installPath(), '/');
3522 if ( myLeaf != NULL ) {
3523 for (std::vector<class ObjectFile::Reader*>::iterator it=fInputFiles.begin(); it != fInputFiles.end(); it++) {
3524 ObjectFile::Reader* reader = *it;
3525 const char* childParent = reader->parentUmbrella();
3526 if ( childParent != NULL ) {
3527 if ( strcmp(childParent, &myLeaf[1]) == 0 ) {
3528 // set re-export bit of info
3529 std::map<ObjectFile::Reader*,LibraryOptions>::iterator pos = fDylibOptionsMap.find(reader);
3530 if ( pos != fDylibOptionsMap.end() ) {
3531 pos->second.fReExport = true;
3543 void Linker::createReaders()
3545 fStartCreateReadersTime = mach_absolute_time();
3546 std::vector<Options::FileInfo>& files = fOptions.getInputFiles();
3547 const int count = files.size();
3548 if ( count == 0 )
3549 throw "no object files specified";
3550 // add all direct object, archives, and dylibs
3551 for (int i=0; i < count; ++i) {
3552 Options::FileInfo& entry = files[i];
3553 // ignore /usr/lib/dyld on command line in crt.o build
3554 if ( strcmp(entry.path, "/usr/lib/dyld") != 0 ) {
3555 try {
3556 this->addInputFile(this->createReader(entry), entry);
3558 catch (const char* msg) {
3559 if ( (strstr(msg, "architecture") != NULL) && !fOptions.errorOnOtherArchFiles() ) {
3560 if ( fOptions.ignoreOtherArchInputFiles() ) {
3561 // ignore, because this is about an architecture not in use
3563 else {
3564 warning("in %s, %s", entry.path, msg);
3567 else {
3568 throwf("in %s, %s", entry.path, msg);
3574 this->processDylibs();
3579 ObjectFile::Reader* Linker::addArchive(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen)
3581 fNextInputOrdinal += mappedLen;
3582 // remember which readers are archives because they are logged differently
3583 fArchiveReaders.insert(reader);
3585 // update stats
3586 fTotalArchiveSize += mappedLen;
3587 ++fTotalArchivesLoaded;
3588 return reader;
3591 ObjectFile::Reader* Linker::addObject(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen)
3593 fNextInputOrdinal += mappedLen;
3594 // any .o files that don't have MH_SUBSECTIONS_VIA_SYMBOLS, that means a generated .o file can't
3595 if ( (fOptions.outputKind() == Options::kObjectFile) && !reader->canScatterAtoms() )
3596 fCanScatter = false;
3598 // update stats
3599 fTotalObjectSize += mappedLen;
3600 ++fTotalObjectLoaded;
3601 return reader;
3605 void Linker::checkDylibClientRestrictions(ObjectFile::Reader* reader)
3607 // Check for any restrictions on who can link with this dylib
3608 const char* readerParentName = reader->parentUmbrella() ;
3609 std::vector<const char*>* clients = reader->getAllowableClients();
3610 if ( (readerParentName != NULL) || (clients != NULL) ) {
3611 // only dylibs that are in an umbrella or have a client list need verification
3612 const char* installName = fOptions.installPath();
3613 const char* installNameLastSlash = strrchr(installName, '/');
3614 bool isParent = false;
3615 bool isSibling = false;
3616 bool isAllowableClient = false;
3617 // There are three cases:
3618 if ( (readerParentName != NULL) && (installNameLastSlash != NULL) ) {
3619 // case 1) The dylib has a parent umbrella, and we are creating the parent umbrella
3620 isParent = ( strcmp(&installNameLastSlash[1], readerParentName) == 0 );
3622 // hack to support umbrella variants that encode the variant name in the install name
3623 // e.g. CoreServices_profile
3624 if ( !isParent ) {
3625 const char* underscore = strchr(&installNameLastSlash[1], '_');
3626 if ( underscore != NULL ) {
3627 isParent = ( strncmp(&installNameLastSlash[1], readerParentName, underscore-installNameLastSlash-1) == 0 );
3631 // case 2) The dylib has a parent umbrella, and we are creating a sibling with the same parent
3632 isSibling = ( (fOptions.umbrellaName() != NULL) && (strcmp(fOptions.umbrellaName(), readerParentName) == 0) );
3635 if ( !isParent && !isSibling && (clients != NULL) ) {
3636 // case 3) the dylib has a list of allowable clients, and we are creating one of them
3637 const char* clientName = fOptions.clientName();
3638 int clientNameLen = 0;
3639 if ( clientName != NULL ) {
3640 // use client name as specified on command line
3641 clientNameLen = strlen(clientName);
3643 else {
3644 // infer client name from output path (e.g. xxx/libfoo_variant.A.dylib --> foo, Bar.framework/Bar_variant --> Bar)
3645 clientName = installName;
3646 clientNameLen = strlen(clientName);
3647 // starts after last slash
3648 if ( installNameLastSlash != NULL )
3649 clientName = &installNameLastSlash[1];
3650 if ( strncmp(clientName, "lib", 3) == 0 )
3651 clientName = &clientName[3];
3652 // up to first dot
3653 const char* firstDot = strchr(clientName, '.');
3654 if ( firstDot != NULL )
3655 clientNameLen = firstDot - clientName;
3656 // up to first underscore
3657 const char* firstUnderscore = strchr(clientName, '_');
3658 if ( (firstUnderscore != NULL) && ((firstUnderscore - clientName) < clientNameLen) )
3659 clientNameLen = firstUnderscore - clientName;
3662 // Use clientName to check if this dylib is able to link against the allowable clients.
3663 for (std::vector<const char*>::iterator it = clients->begin(); it != clients->end(); it++) {
3664 if ( strncmp(*it, clientName, clientNameLen) == 0 )
3665 isAllowableClient = true;
3669 if ( !isParent && !isSibling && !isAllowableClient ) {
3670 if ( readerParentName != NULL ) {
3671 throwf("cannot link directly with %s. Link against the umbrella framework '%s.framework' instead.",
3672 reader->getPath(), readerParentName);
3674 else {
3675 throwf("cannot link directly with %s", reader->getPath());
3682 ObjectFile::Reader* Linker::addDylib(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen)
3684 switch ( fOptions.outputKind() ) {
3685 case Options::kDynamicExecutable:
3686 case Options::kDynamicLibrary:
3687 case Options::kDynamicBundle:
3688 break;
3689 case Options::kStaticExecutable:
3690 case Options::kDyld:
3691 case Options::kPreload:
3692 case Options::kObjectFile:
3693 case Options::kKextBundle:
3694 warning("unexpected dylib (%s) on link line", reader->getPath());
3695 break;
3698 fNextInputOrdinal += mappedLen;
3699 if ( (reader->getInstallPath() == NULL) && !info.options.fBundleLoader ) {
3700 // this is a "blank" stub
3701 // silently ignore it
3702 return reader;
3704 // add to map of loaded dylibs
3705 const char* installPath = reader->getInstallPath();
3706 if ( installPath != NULL ) {
3707 InstallNameToReader::iterator pos = fDylibMap.find(installPath);
3708 if ( pos == fDylibMap.end() ) {
3709 fDylibMap[strdup(installPath)] = reader;
3711 else {
3712 InstallNameToReader::iterator pos2 = fDylibMap.find(reader->getPath());
3713 if ( pos2 == fDylibMap.end() )
3714 fDylibMap[strdup(reader->getPath())] = reader;
3715 else
3716 warning("duplicate dylib %s", reader->getPath());
3719 else if ( info.options.fBundleLoader )
3720 fBundleLoaderReader = reader;
3722 // log direct readers
3723 if ( !fAllDirectDylibsLoaded )
3724 this->logDylib(reader, false);
3726 // update stats
3727 ++fTotalDylibsLoaded;
3729 return reader;
3733 void Linker::logTraceInfo (const char* format, ...)
3735 static int trace_file = -1;
3736 char trace_buffer[MAXPATHLEN * 2];
3737 char *buffer_ptr;
3738 int length;
3739 ssize_t amount_written;
3740 const char *trace_file_path = fOptions.readerOptions().fTraceOutputFile;
3742 if(trace_file == -1) {
3743 if(trace_file_path != NULL) {
3744 trace_file = open(trace_file_path, O_WRONLY | O_APPEND | O_CREAT, 0666);
3745 if(trace_file == -1)
3746 throwf("Could not open or create trace file: %s", trace_file_path);
3748 else {
3749 trace_file = fileno(stderr);
3753 va_list ap;
3754 va_start(ap, format);
3755 length = vsnprintf(trace_buffer, sizeof(trace_buffer), format, ap);
3756 va_end(ap);
3757 buffer_ptr = trace_buffer;
3759 while(length > 0) {
3760 amount_written = write(trace_file, buffer_ptr, length);
3761 if(amount_written == -1)
3762 /* Failure to write shouldn't fail the build. */
3763 return;
3764 buffer_ptr += amount_written;
3765 length -= amount_written;
3771 void Linker::createWriter()
3773 fStartCreateWriterTime = mach_absolute_time();
3775 // make a vector out of all required dylibs in fDylibMap
3776 std::vector<ExecutableFile::DyLibUsed> dynamicLibraries;
3777 // need to preserve command line order
3778 for (std::vector<class ObjectFile::Reader*>::iterator it=fInputFiles.begin(); it != fInputFiles.end(); it++) {
3779 ObjectFile::Reader* reader = *it;
3780 for (InstallNameToReader::iterator mit=fDylibMap.begin(); mit != fDylibMap.end(); mit++) {
3781 if ( reader == mit->second ) {
3782 ExecutableFile::DyLibUsed dylibInfo;
3783 dylibInfo.reader = reader;
3784 dylibInfo.options = fDylibOptionsMap[reader];
3785 dynamicLibraries.push_back(dylibInfo);
3786 break;
3790 // then add any other dylibs
3791 for (InstallNameToReader::iterator it=fDylibMap.begin(); it != fDylibMap.end(); it++) {
3792 if ( it->second->implicitlyLinked() ) {
3793 // if not already in dynamicLibraries
3794 bool alreadyInDynamicLibraries = false;
3795 for (std::vector<ExecutableFile::DyLibUsed>::iterator dit=dynamicLibraries.begin(); dit != dynamicLibraries.end(); dit++) {
3796 if ( dit->reader == it->second ) {
3797 alreadyInDynamicLibraries = true;
3798 break;
3801 if ( ! alreadyInDynamicLibraries ) {
3802 ExecutableFile::DyLibUsed dylibInfo;
3803 dylibInfo.reader = it->second;
3804 std::map<ObjectFile::Reader*,LibraryOptions>::iterator pos = fDylibOptionsMap.find(it->second);
3805 if ( pos != fDylibOptionsMap.end() ) {
3806 dylibInfo.options = pos->second;
3808 else {
3809 dylibInfo.options.fWeakImport = false; // FIX ME
3810 dylibInfo.options.fReExport = false;
3811 dylibInfo.options.fBundleLoader = false;
3813 dynamicLibraries.push_back(dylibInfo);
3817 if ( fBundleLoaderReader != NULL ) {
3818 ExecutableFile::DyLibUsed dylibInfo;
3819 dylibInfo.reader = fBundleLoaderReader;
3820 dylibInfo.options.fWeakImport = false;
3821 dylibInfo.options.fReExport = false;
3822 dylibInfo.options.fBundleLoader = true;
3823 dynamicLibraries.push_back(dylibInfo);
3826 const char* path = fOptions.getOutputFilePath();
3827 switch ( fArchitecture ) {
3828 case CPU_TYPE_POWERPC:
3829 this->setOutputFile(new mach_o::executable::Writer<ppc>(path, fOptions, dynamicLibraries));
3830 break;
3831 case CPU_TYPE_POWERPC64:
3832 this->setOutputFile(new mach_o::executable::Writer<ppc64>(path, fOptions, dynamicLibraries));
3833 break;
3834 case CPU_TYPE_I386:
3835 this->setOutputFile(new mach_o::executable::Writer<x86>(path, fOptions, dynamicLibraries));
3836 break;
3837 case CPU_TYPE_X86_64:
3838 this->setOutputFile(new mach_o::executable::Writer<x86_64>(path, fOptions, dynamicLibraries));
3839 break;
3840 case CPU_TYPE_ARM:
3841 this->setOutputFile(new mach_o::executable::Writer<arm>(path, fOptions, dynamicLibraries));
3842 break;
3843 default:
3844 throw "unknown architecture";
3849 Linker::SymbolTable::SymbolTable(Linker& owner)
3850 : fOwner(owner), fRequireCount(0), fHasExternalTentativeDefinitions(false), fHasExternalWeakDefinitions(false)
3854 void Linker::SymbolTable::require(const char* name)
3856 //fprintf(stderr, "require(%s)\n", name);
3857 Mapper::iterator pos = fTable.find(name);
3858 if ( pos == fTable.end() ) {
3859 fTable[name] = NULL;
3860 ++fRequireCount;
3864 // convenience labels for 2-dimensional switch statement
3865 enum AllDefinitionCombinations {
3866 kRegAndReg = (ObjectFile::Atom::kRegularDefinition << 3) | ObjectFile::Atom::kRegularDefinition,
3867 kRegAndWeak = (ObjectFile::Atom::kRegularDefinition << 3) | ObjectFile::Atom::kWeakDefinition,
3868 kRegAndTent = (ObjectFile::Atom::kRegularDefinition << 3) | ObjectFile::Atom::kTentativeDefinition,
3869 kRegAndExtern = (ObjectFile::Atom::kRegularDefinition << 3) | ObjectFile::Atom::kExternalDefinition,
3870 kRegAndExternWeak = (ObjectFile::Atom::kRegularDefinition << 3) | ObjectFile::Atom::kExternalWeakDefinition,
3871 kRegAndAbsolute = (ObjectFile::Atom::kRegularDefinition << 3) | ObjectFile::Atom::kAbsoluteSymbol,
3872 kWeakAndReg = (ObjectFile::Atom::kWeakDefinition << 3) | ObjectFile::Atom::kRegularDefinition,
3873 kWeakAndWeak = (ObjectFile::Atom::kWeakDefinition << 3) | ObjectFile::Atom::kWeakDefinition,
3874 kWeakAndTent = (ObjectFile::Atom::kWeakDefinition << 3) | ObjectFile::Atom::kTentativeDefinition,
3875 kWeakAndExtern = (ObjectFile::Atom::kWeakDefinition << 3) | ObjectFile::Atom::kExternalDefinition,
3876 kWeakAndExternWeak = (ObjectFile::Atom::kWeakDefinition << 3) | ObjectFile::Atom::kExternalWeakDefinition,
3877 kWeakAndAbsolute = (ObjectFile::Atom::kWeakDefinition << 3) | ObjectFile::Atom::kAbsoluteSymbol,
3878 kTentAndReg = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kRegularDefinition,
3879 kTentAndWeak = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kWeakDefinition,
3880 kTentAndTent = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kTentativeDefinition,
3881 kTentAndExtern = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kExternalDefinition,
3882 kTentAndExternWeak = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kExternalWeakDefinition,
3883 kTentAndAbsolute = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kAbsoluteSymbol,
3884 kExternAndReg = (ObjectFile::Atom::kExternalDefinition << 3) | ObjectFile::Atom::kRegularDefinition,
3885 kExternAndWeak = (ObjectFile::Atom::kExternalDefinition << 3) | ObjectFile::Atom::kWeakDefinition,
3886 kExternAndTent = (ObjectFile::Atom::kExternalDefinition << 3) | ObjectFile::Atom::kTentativeDefinition,
3887 kExternAndExtern = (ObjectFile::Atom::kExternalDefinition << 3) | ObjectFile::Atom::kExternalDefinition,
3888 kExternAndExternWeak = (ObjectFile::Atom::kExternalDefinition << 3) | ObjectFile::Atom::kExternalWeakDefinition,
3889 kExternAndAbsolute = (ObjectFile::Atom::kExternalDefinition << 3) | ObjectFile::Atom::kAbsoluteSymbol,
3890 kExternWeakAndReg = (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kRegularDefinition,
3891 kExternWeakAndWeak = (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kWeakDefinition,
3892 kExternWeakAndTent = (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kTentativeDefinition,
3893 kExternWeakAndExtern = (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kExternalDefinition,
3894 kExternWeakAndExternWeak= (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kExternalWeakDefinition,
3895 kExternWeakAndAbsolute = (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kAbsoluteSymbol,
3896 kAbsoluteAndReg = (ObjectFile::Atom::kAbsoluteSymbol << 3) | ObjectFile::Atom::kRegularDefinition,
3897 kAbsoluteAndWeak = (ObjectFile::Atom::kAbsoluteSymbol << 3) | ObjectFile::Atom::kWeakDefinition,
3898 kAbsoluteAndTent = (ObjectFile::Atom::kAbsoluteSymbol << 3) | ObjectFile::Atom::kTentativeDefinition,
3899 kAbsoluteAndExtern = (ObjectFile::Atom::kAbsoluteSymbol << 3) | ObjectFile::Atom::kExternalDefinition,
3900 kAbsoluteAndExternWeak = (ObjectFile::Atom::kAbsoluteSymbol << 3) | ObjectFile::Atom::kExternalWeakDefinition,
3901 kAbsoluteAndAbsolute = (ObjectFile::Atom::kAbsoluteSymbol << 3) | ObjectFile::Atom::kAbsoluteSymbol
3904 bool Linker::SymbolTable::add(ObjectFile::Atom& newAtom)
3906 bool useNew = true;
3907 bool checkVisibilityMismatch = false;
3908 const char* name = newAtom.getName();
3909 //fprintf(stderr, "map.add(%s => %p from %s)\n", name, &newAtom, newAtom.getFile()->getPath());
3910 Mapper::iterator pos = fTable.find(name);
3911 ObjectFile::Atom* existingAtom = NULL;
3912 if ( pos != fTable.end() )
3913 existingAtom = pos->second;
3914 if ( existingAtom != NULL ) {
3915 // already have atom with same name in symbol table
3916 switch ( (AllDefinitionCombinations)((existingAtom->getDefinitionKind() << 3) | newAtom.getDefinitionKind()) ) {
3917 case kRegAndReg:
3918 throwf("duplicate symbol %s in %s and %s", name, newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
3919 case kRegAndWeak:
3920 // ignore new weak atom, because we already have a non-weak one
3921 useNew = false;
3922 break;
3923 case kRegAndTent:
3924 // ignore new tentative atom, because we already have a regular one
3925 useNew = false;
3926 checkVisibilityMismatch = true;
3927 if ( newAtom.getSize() > existingAtom->getSize() ) {
3928 warning("for symbol %s tentative definition of size %llu from %s is "
3929 "is smaller than the real definition of size %llu from %s",
3930 newAtom.getDisplayName(), newAtom.getSize(), newAtom.getFile()->getPath(),
3931 existingAtom->getSize(), existingAtom->getFile()->getPath());
3933 break;
3934 case kRegAndExtern:
3935 // ignore external atom, because we already have a one
3936 useNew = false;
3937 break;
3938 case kRegAndExternWeak:
3939 // ignore external atom, because we already have a one
3940 useNew = false;
3941 break;
3942 case kRegAndAbsolute:
3943 throwf("duplicate symbol %s in %s and %s", name, newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
3944 break;
3945 case kWeakAndReg:
3946 // replace existing weak atom with regular one
3947 break;
3948 case kWeakAndWeak:
3949 // have another weak atom, use whichever has largest alignment requirement
3950 // because codegen of some client may require alignment
3951 useNew = ( newAtom.getAlignment().trailingZeros() > existingAtom->getAlignment().trailingZeros() );
3952 checkVisibilityMismatch = true;
3953 break;
3954 case kWeakAndTent:
3955 // replace existing weak atom with tentative one ???
3956 break;
3957 case kWeakAndExtern:
3958 // keep weak atom, at runtime external one may override
3959 useNew = false;
3960 break;
3961 case kWeakAndExternWeak:
3962 // keep weak atom, at runtime external one may override
3963 useNew = false;
3964 break;
3965 case kWeakAndAbsolute:
3966 // replace existing weak atom with absolute one
3967 break;
3968 case kTentAndReg:
3969 // replace existing tentative atom with regular one
3970 checkVisibilityMismatch = true;
3971 if ( newAtom.getSize() < existingAtom->getSize() ) {
3972 warning("for symbol %s tentative definition of size %llu from %s is "
3973 "being replaced by a real definition of size %llu from %s",
3974 newAtom.getDisplayName(), existingAtom->getSize(), existingAtom->getFile()->getPath(),
3975 newAtom.getSize(), newAtom.getFile()->getPath());
3977 break;
3978 case kTentAndWeak:
3979 // replace existing tentative atom with weak one ???
3980 break;
3981 case kTentAndTent:
3982 // use largest
3983 checkVisibilityMismatch = true;
3984 if ( newAtom.getSize() < existingAtom->getSize() ) {
3985 useNew = false;
3987 else {
3988 if ( newAtom.getAlignment().trailingZeros() < existingAtom->getAlignment().trailingZeros() )
3989 warning("alignment lost in merging tentative definition %s", newAtom.getDisplayName());
3991 break;
3992 case kTentAndExtern:
3993 case kTentAndExternWeak:
3994 // a tentative definition and a dylib definition, so commons-mode decides how to handle
3995 switch ( fOwner.fOptions.commonsMode() ) {
3996 case Options::kCommonsIgnoreDylibs:
3997 if ( fOwner.fOptions.warnCommons() )
3998 warning("using common symbol %s from %s and ignoring defintion from dylib %s",
3999 existingAtom->getName(), existingAtom->getFile()->getPath(), newAtom.getFile()->getPath());
4000 useNew = false;
4001 break;
4002 case Options::kCommonsOverriddenByDylibs:
4003 if ( fOwner.fOptions.warnCommons() )
4004 warning("replacing common symbol %s from %s with true definition from dylib %s",
4005 existingAtom->getName(), existingAtom->getFile()->getPath(), newAtom.getFile()->getPath());
4006 break;
4007 case Options::kCommonsConflictsDylibsError:
4008 throwf("common symbol %s from %s conflicts with defintion from dylib %s",
4009 existingAtom->getName(), existingAtom->getFile()->getPath(), newAtom.getFile()->getPath());
4011 break;
4012 case kTentAndAbsolute:
4013 // replace tentative with absolute (can't size check because absolutes have no size)
4014 break;
4015 case kExternAndReg:
4016 // replace external atom with regular one
4017 break;
4018 case kExternAndWeak:
4019 // replace external atom with weak one
4020 break;
4021 case kExternAndTent:
4022 // a tentative definition and a dylib definition, so commons-mode decides how to handle
4023 switch ( fOwner.fOptions.commonsMode() ) {
4024 case Options::kCommonsIgnoreDylibs:
4025 if ( fOwner.fOptions.warnCommons() )
4026 warning("using common symbol %s from %s and ignoring defintion from dylib %s",
4027 newAtom.getName(), newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
4028 break;
4029 case Options::kCommonsOverriddenByDylibs:
4030 if ( fOwner.fOptions.warnCommons() )
4031 warning("replacing defintion of %s from dylib %s with common symbol from %s",
4032 newAtom.getName(), existingAtom->getFile()->getPath(), newAtom.getFile()->getPath());
4033 useNew = false;
4034 break;
4035 case Options::kCommonsConflictsDylibsError:
4036 throwf("common symbol %s from %s conflicts with defintion from dylib %s",
4037 newAtom.getName(), newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
4039 break;
4040 case kExternAndExtern:
4041 throwf("duplicate symbol %s in %s and %s\n", name, newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
4042 case kExternAndExternWeak:
4043 // keep strong dylib atom, ignore weak one
4044 useNew = false;
4045 break;
4046 case kExternAndAbsolute:
4047 // replace external atom with absolute one
4048 break;
4049 case kExternWeakAndReg:
4050 // replace existing weak external with regular
4051 break;
4052 case kExternWeakAndWeak:
4053 // replace existing weak external with weak (let dyld decide at runtime which to use)
4054 break;
4055 case kExternWeakAndTent:
4056 // a tentative definition and a dylib definition, so commons-mode decides how to handle
4057 switch ( fOwner.fOptions.commonsMode() ) {
4058 case Options::kCommonsIgnoreDylibs:
4059 if ( fOwner.fOptions.warnCommons() )
4060 warning("using common symbol %s from %s and ignoring defintion from dylib %s",
4061 newAtom.getName(), newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
4062 break;
4063 case Options::kCommonsOverriddenByDylibs:
4064 if ( fOwner.fOptions.warnCommons() )
4065 warning("replacing defintion of %s from dylib %s with common symbol from %s",
4066 newAtom.getName(), existingAtom->getFile()->getPath(), newAtom.getFile()->getPath());
4067 useNew = false;
4068 break;
4069 case Options::kCommonsConflictsDylibsError:
4070 throwf("common symbol %s from %s conflicts with defintion from dylib %s",
4071 newAtom.getName(), newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
4073 break;
4074 case kExternWeakAndExtern:
4075 // replace existing weak external with external
4076 break;
4077 case kExternWeakAndExternWeak:
4078 // keep existing external weak
4079 useNew = false;
4080 break;
4081 case kExternWeakAndAbsolute:
4082 // replace existing weak external with absolute
4083 break;
4084 case kAbsoluteAndReg:
4085 throwf("duplicate symbol %s in %s and %s", name, newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
4086 case kAbsoluteAndWeak:
4087 // ignore new weak atom, because we already have a non-weak one
4088 useNew = false;
4089 break;
4090 case kAbsoluteAndTent:
4091 // ignore new tentative atom, because we already have a regular one
4092 useNew = false;
4093 break;
4094 case kAbsoluteAndExtern:
4095 // ignore external atom, because we already have a one
4096 useNew = false;
4097 break;
4098 case kAbsoluteAndExternWeak:
4099 // ignore external atom, because we already have a one
4100 useNew = false;
4101 break;
4102 case kAbsoluteAndAbsolute:
4103 throwf("duplicate symbol %s in %s and %s", name, newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
4104 break;
4107 if ( (existingAtom != NULL) && checkVisibilityMismatch && (newAtom.getScope() != existingAtom->getScope()) ) {
4108 warning("%s has different visibility (%s) in %s and (%s) in %s",
4109 newAtom.getDisplayName(), (newAtom.getScope() == 1 ? "hidden" : "default"), newAtom.getFile()->getPath(), (existingAtom->getScope() == 1 ? "hidden" : "default"), existingAtom->getFile()->getPath());
4111 if ( useNew ) {
4112 fTable[name] = &newAtom;
4113 if ( existingAtom != NULL ) {
4114 fOwner.markDead(existingAtom);
4115 if ( fOwner.fInitialLoadsDone ) {
4116 //fprintf(stderr, "existing %p %s overridden by %p\n", existingAtom, existingAtom->getName(), &newAtom);
4117 fOwner.fAtomsOverriddenByLateLoads.insert(existingAtom);
4120 if ( newAtom.getScope() == ObjectFile::Atom::scopeGlobal ) {
4121 switch ( newAtom.getDefinitionKind() ) {
4122 case ObjectFile::Atom::kTentativeDefinition:
4123 fHasExternalTentativeDefinitions = true;
4124 ++fRequireCount; // added a tentative definition means loadUndefines() needs to continue
4125 break;
4126 case ObjectFile::Atom::kWeakDefinition:
4127 fHasExternalWeakDefinitions = true;
4128 break;
4129 case ObjectFile::Atom::kExternalDefinition:
4130 case ObjectFile::Atom::kExternalWeakDefinition:
4131 ++fDylibSymbolCount;
4132 break;
4133 default:
4134 break;
4138 else {
4139 fOwner.markDead(&newAtom);
4141 return useNew;
4146 ObjectFile::Atom* Linker::SymbolTable::find(const char* name)
4148 Mapper::iterator pos = fTable.find(name);
4149 if ( pos != fTable.end() ) {
4150 return pos->second;
4152 return NULL;
4155 void Linker::SymbolTable::erase(const char* name) {
4156 fTable.erase(name);
4159 void Linker::SymbolTable::getUndefinesNames(std::vector<const char*>& undefines)
4161 for (Mapper::iterator it=fTable.begin(); it != fTable.end(); it++) {
4162 if ( it->second == NULL ) {
4163 undefines.push_back(it->first);
4168 void Linker::SymbolTable::getTentativesNames(std::vector<const char*>& tents)
4170 for (Mapper::iterator it=fTable.begin(); it != fTable.end(); it++) {
4171 if ( it->second != NULL ) {
4172 if ( (it->second->getDefinitionKind() == ObjectFile::Atom::kTentativeDefinition)
4173 && (it->second->getScope() == ObjectFile::Atom::scopeGlobal) ) {
4174 tents.push_back(it->first);
4182 bool Linker::AtomSorter::operator()(const ObjectFile::Atom* left, const ObjectFile::Atom* right)
4184 if ( left == right )
4185 return false;
4187 // first sort by section order (which is already sorted by segment)
4188 unsigned int leftSectionIndex = left->getSection()->getIndex();
4189 unsigned int rightSectionIndex = right->getSection()->getIndex();
4190 if ( leftSectionIndex != rightSectionIndex)
4191 return (leftSectionIndex < rightSectionIndex);
4193 // magic section$start symbol always sorts to the start of its section
4194 if ( left->getContentType() == ObjectFile::Atom::kSectionStart )
4195 return true;
4196 if ( right->getContentType() == ObjectFile::Atom::kSectionStart )
4197 return false;
4199 // if a -order_file is specified, then sorting is altered to sort those symbols first
4200 if ( fOverriddenOrdinalMap != NULL ) {
4201 std::map<const ObjectFile::Atom*, uint32_t>::iterator leftPos = fOverriddenOrdinalMap->find(left);
4202 std::map<const ObjectFile::Atom*, uint32_t>::iterator rightPos = fOverriddenOrdinalMap->find(right);
4203 std::map<const ObjectFile::Atom*, uint32_t>::iterator end = fOverriddenOrdinalMap->end();
4204 if ( leftPos != end ) {
4205 if ( rightPos != end ) {
4206 // both left and right are overridden, so compare overridden ordinals
4207 return leftPos->second < rightPos->second;
4209 else {
4210 // left is overridden and right is not, so left < right
4211 return true;
4214 else {
4215 if ( rightPos != end ) {
4216 // right is overridden and left is not, so right < left
4217 return false;
4219 else {
4220 // neither are overridden, do default sort
4221 // fall into default sorting below
4226 // magic section$end symbol always sorts to the end of its section
4227 if ( left->getContentType() == ObjectFile::Atom::kSectionEnd )
4228 return false;
4229 if ( right->getContentType() == ObjectFile::Atom::kSectionEnd )
4230 return true;
4232 // the __common section can have real or tentative definitions
4233 // we want the real ones to sort before tentative ones
4234 bool leftIsTent = (left->getDefinitionKind() == ObjectFile::Atom::kTentativeDefinition);
4235 bool rightIsTent = (right->getDefinitionKind() == ObjectFile::Atom::kTentativeDefinition);
4236 if ( leftIsTent != rightIsTent )
4237 return rightIsTent;
4239 // initializers are auto sorted to start of section
4240 if ( !fInitializerSet.empty() ) {
4241 bool leftFirst = (fInitializerSet.count(left) != 0);
4242 bool rightFirst = (fInitializerSet.count(right) != 0);
4243 if ( leftFirst != rightFirst )
4244 return leftFirst;
4247 // terminators are auto sorted to end of section
4248 if ( !fTerminatorSet.empty() ) {
4249 bool leftLast = (fTerminatorSet.count(left) != 0);
4250 bool rightLast = (fTerminatorSet.count(right) != 0);
4251 if ( leftLast != rightLast )
4252 return rightLast;
4255 // lastly sort by atom ordinal. this is already sorted by .o order
4256 return left->getOrdinal() < right->getOrdinal();
4260 int main(int argc, const char* argv[])
4262 const char* archName = NULL;
4263 bool showArch = false;
4264 bool archInferred = false;
4265 try {
4266 // create linker object given command line arguments
4267 Linker ld(argc, argv);
4269 // save error message prefix
4270 archName = ld.architectureName();
4271 archInferred = ld.isInferredArchitecture();
4272 showArch = ld.showArchitectureInErrors();
4274 // open all input files
4275 ld.createReaders();
4277 // open output file
4278 ld.createWriter();
4280 // do linking
4281 ld.link();
4283 catch (const char* msg) {
4284 if ( archInferred )
4285 fprintf(stderr, "ld: %s for inferred architecture %s\n", msg, archName);
4286 else if ( showArch )
4287 fprintf(stderr, "ld: %s for architecture %s\n", msg, archName);
4288 else
4289 fprintf(stderr, "ld: %s\n", msg);
4290 return 1;
4293 return 0;