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