]> git.saurik.com Git - apple/ld64.git/blob - src/ld/ld.cpp
115240e93b4745ae98e10f68c005e67f37f7850f
[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 ObjectFile::Atom* Linker::findAtom(const Options::OrderedSymbol& orderedSymbol)
2029 {
2030 ObjectFile::Atom* atom = fGlobalSymbolTable.find(orderedSymbol.symbolName);
2031 if ( atom != NULL ) {
2032 if ( matchesObjectFile(atom, orderedSymbol.objectFileName) )
2033 return atom;
2034 }
2035 else {
2036 // slow case. The requested symbol is not in symbol table, so might be static function
2037 static SymbolTable::Mapper hashTableOfTranslationUnitScopedSymbols;
2038 static bool built = false;
2039 // build a hash_map the first time
2040 if ( !built ) {
2041 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
2042 atom = *it;
2043 const char* name = atom->getName();
2044 if ( name != NULL) {
2045 if ( atom->getScope() == ObjectFile::Atom::scopeTranslationUnit ) {
2046 // static function or data
2047 SymbolTable::Mapper::iterator pos = hashTableOfTranslationUnitScopedSymbols.find(name);
2048 if ( pos == hashTableOfTranslationUnitScopedSymbols.end() )
2049 hashTableOfTranslationUnitScopedSymbols[name] = atom;
2050 else
2051 hashTableOfTranslationUnitScopedSymbols[name] = NULL; // collision, denote with NULL
2052 }
2053 }
2054 }
2055 //fprintf(stderr, "built hash table of %lu static functions\n", hashTableOfTranslationUnitScopedSymbols.size());
2056 built = true;
2057 }
2058
2059 // look for name in hashTableOfTranslationUnitScopedSymbols
2060 SymbolTable::Mapper::iterator pos = hashTableOfTranslationUnitScopedSymbols.find(orderedSymbol.symbolName);
2061 if ( pos != hashTableOfTranslationUnitScopedSymbols.end() ) {
2062 if ( (pos->second != NULL) && matchesObjectFile(pos->second, orderedSymbol.objectFileName) ) {
2063 //fprintf(stderr, "found %s in hash table\n", orderedSymbol.symbolName);
2064 return pos->second;
2065 }
2066 if ( pos->second == NULL )
2067 // name is in hash table, but atom is NULL, so that means there are duplicates, so we use super slow way
2068 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
2069 atom = *it;
2070 if ( atom->getScope() == ObjectFile::Atom::scopeTranslationUnit ) {
2071 const char* name = atom->getName();
2072 if ( (name != NULL) && (strcmp(name, orderedSymbol.symbolName) == 0) ) {
2073 if ( matchesObjectFile(atom, orderedSymbol.objectFileName) ) {
2074 if ( fOptions.printOrderFileStatistics() )
2075 warning("%s specified in order_file but it exists in multiple .o files. "
2076 "Prefix symbol with .o filename in order_file to disambiguate", orderedSymbol.symbolName);
2077 return atom;
2078 }
2079 }
2080 }
2081 }
2082 }
2083
2084 }
2085 return NULL;
2086 }
2087
2088
2089 void Linker::sortSections()
2090 {
2091 Section::assignIndexes(fOptions.outputKind() == Options::kObjectFile);
2092 }
2093
2094
2095 //
2096 // Linker::sortAtoms()
2097 //
2098 // The purpose of this method is to take the graph of all Atoms and produce an ordered
2099 // sequence of atoms. The constraints are that: 1) all Atoms of the same Segment must
2100 // be contiguous, 2) all Atoms of the same Section must be contigous, 3) Atoms specified
2101 // in an order_file are seqenced as in the order_file and before Atoms not specified,
2102 // 4) Atoms in the same section from the same .o file should be contiguous and sequenced
2103 // in the same order they were in the .o file, 5) Atoms in the same Section but which came
2104 // from different .o files should be sequenced in the same order that the .o files
2105 // were passed to the linker (i.e. command line order).
2106 //
2107 // The way this is implemented is that the linker passes a "base ordinal" to each Reader
2108 // as it is constructed. The reader should construct it Atoms so that calling getOrdinal()
2109 // on its atoms returns a contiguous range of values starting at the base ordinal. Then
2110 // sorting is just sorting by section, then by ordinal.
2111 //
2112 // If an order_file is specified, it gets more complicated. First, an override-ordinal map
2113 // is created. It causes the sort routine to ignore the value returned by getOrdinal() and
2114 // use the override value instead. Next some Atoms must be layed out consecutively
2115 // (e.g. hand written assembly that does not end with return, but rather falls into
2116 // the next label). This is modeled in Readers via a "kFollowOn" reference. The use of
2117 // kFollowOn refernces produces "clusters" of atoms that must stay together.
2118 // If an order_file tries to move one atom, it may need to move a whole cluster. The
2119 // algorithm to do this models clusters using two maps. The "starts" maps maps any
2120 // atom in a cluster to the first Atom in the cluster. The "nexts" maps an Atom in a
2121 // cluster to the next Atom in the cluster. With this in place, while processing an
2122 // order_file, if any entry is in a cluster (in "starts" map), then the entire cluster is
2123 // given ordinal overrides.
2124 //
2125 void Linker::sortAtoms()
2126 {
2127 fStartSortTime = mach_absolute_time();
2128 // if -order_file is used, build map of atom ordinal overrides
2129 std::map<const ObjectFile::Atom*, uint32_t>* ordinalOverrideMap = NULL;
2130 std::map<const ObjectFile::Atom*, uint32_t> theOrdinalOverrideMap;
2131 const bool log = false;
2132 if ( fOptions.orderedSymbols().size() != 0 ) {
2133 // first make a pass to find all follow-on references and build start/next maps
2134 // which are a way to represent clusters of atoms that must layout together
2135 std::map<const ObjectFile::Atom*, const ObjectFile::Atom*> followOnStarts;
2136 std::map<const ObjectFile::Atom*, const ObjectFile::Atom*> followOnNexts;
2137 for (std::vector<ObjectFile::Atom*>::iterator ait=fAllAtoms.begin(); ait != fAllAtoms.end(); ait++) {
2138 ObjectFile::Atom* atom = *ait;
2139 std::vector<class ObjectFile::Reference*>& references = atom->getReferences();
2140 for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
2141 ObjectFile::Reference* ref = *rit;
2142 if ( ref->getKind() == 1 ) { // FIX FIX
2143 ObjectFile::Atom* targetAtom = &ref->getTarget();
2144 if ( log ) fprintf(stderr, "ref %s -> %s", atom->getDisplayName(), targetAtom->getDisplayName());
2145 std::map<const ObjectFile::Atom*, const ObjectFile::Atom*>::iterator startFrom = followOnStarts.find(atom);
2146 std::map<const ObjectFile::Atom*, const ObjectFile::Atom*>::iterator startTo = followOnStarts.find(targetAtom);
2147 if ( (startFrom == followOnStarts.end()) && (startTo == followOnStarts.end()) ) {
2148 // this is first time we've seen either atom, make simple cluster of the two
2149 if ( log ) fprintf(stderr, " new cluster\n");
2150 followOnStarts[atom] = atom;
2151 followOnStarts[targetAtom] = atom;
2152 followOnNexts[atom] = targetAtom;
2153 followOnNexts[targetAtom] = NULL;
2154 }
2155 else if ( (startFrom != followOnStarts.end()) && (startTo == followOnStarts.end()) && (followOnNexts[atom] == NULL) ) {
2156 // atom is at end of an existing cluster, so append target to end of cluster
2157 if ( log ) fprintf(stderr, " end of cluster starting with %s\n", followOnStarts[atom]->getDisplayName());
2158 followOnNexts[atom] = targetAtom;
2159 followOnNexts[targetAtom] = NULL;
2160 followOnStarts[targetAtom] = followOnStarts[atom];
2161 }
2162 else {
2163 // gerneral case of inserting into an existing cluster
2164 if ( followOnNexts[atom] != NULL ) {
2165 // an atom with two follow-ons is illegal
2166 warning("can't order %s because both %s and %s must follow it",
2167 atom->getDisplayName(), targetAtom->getDisplayName(), followOnNexts[atom]->getDisplayName());
2168 }
2169 else {
2170 // there already exists an atom that says target must be its follow-on
2171 const ObjectFile::Atom* originalStart = startTo->second;
2172 const ObjectFile::Atom* originalPrevious = originalStart;
2173 while ( followOnNexts[originalPrevious] != targetAtom )
2174 originalPrevious = followOnNexts[originalPrevious];
2175 bool otherIsAlias = (originalPrevious->getSize() == 0);
2176 bool thisIsAlias = (atom->getSize() == 0);
2177 if ( !otherIsAlias && !thisIsAlias ) {
2178 warning("can't order %s because both %s and %s must preceed it",
2179 targetAtom->getDisplayName(), originalPrevious->getDisplayName(), atom->getDisplayName());
2180 }
2181 else if ( otherIsAlias ) {
2182 if ( originalPrevious == originalStart ) {
2183 // other is alias at start of cluster, make this the new start of cluster
2184 if ( log ) fprintf(stderr, " becomes new start of cluster previous starting with %s\n", originalStart->getDisplayName());
2185 followOnNexts[atom] = originalPrevious;
2186 for(const ObjectFile::Atom* nextAtom = atom; nextAtom != NULL; nextAtom = followOnNexts[nextAtom])
2187 followOnStarts[nextAtom] = atom;
2188 }
2189 else {
2190 // other is alias in middle of cluster, insert new atom before it
2191 if ( log ) fprintf(stderr, " insert into cluster starting with %s before alias %s\n", originalStart->getDisplayName(), originalPrevious->getDisplayName());
2192 followOnStarts[atom] = originalStart;
2193 followOnNexts[atom] = originalPrevious;
2194 for(const ObjectFile::Atom* a = originalStart; a != NULL; a = followOnNexts[a]) {
2195 if ( followOnNexts[a] == originalPrevious ) {
2196 followOnNexts[a] = atom;
2197 break;
2198 }
2199 }
2200 }
2201 }
2202 else {
2203 // this is alias, so it can go inbetween originalPrevious and targetAtom
2204 if ( log ) fprintf(stderr, " insert into cluster starting with %s after %s\n", originalStart->getDisplayName(), originalPrevious->getDisplayName());
2205 followOnStarts[atom] = originalStart;
2206 followOnNexts[atom] = followOnNexts[originalPrevious];
2207 followOnNexts[originalPrevious] = atom;
2208 }
2209 }
2210 }
2211 }
2212 }
2213 }
2214
2215 if ( log ) {
2216 for(std::map<const ObjectFile::Atom*, const ObjectFile::Atom*>::iterator it = followOnStarts.begin(); it != followOnStarts.end(); ++it)
2217 fprintf(stderr, "start %s -> %s\n", it->first->getDisplayName(), it->second->getDisplayName());
2218
2219 for(std::map<const ObjectFile::Atom*, const ObjectFile::Atom*>::iterator it = followOnNexts.begin(); it != followOnNexts.end(); ++it)
2220 fprintf(stderr, "next %s -> %s\n", it->first->getDisplayName(), (it->second != NULL) ? it->second->getDisplayName() : "null");
2221 }
2222
2223 // with the start/next maps of follow-on atoms we can process the order file and produce override ordinals
2224 ordinalOverrideMap = &theOrdinalOverrideMap;
2225 uint32_t index = 0;
2226 uint32_t matchCount = 0;
2227 std::vector<Options::OrderedSymbol>& orderedSymbols = fOptions.orderedSymbols();
2228 for(std::vector<Options::OrderedSymbol>::iterator it = orderedSymbols.begin(); it != orderedSymbols.end(); ++it) {
2229 ObjectFile::Atom* atom = this->findAtom(*it);
2230 if ( atom != NULL ) {
2231 std::map<const ObjectFile::Atom*, const ObjectFile::Atom*>::iterator start = followOnStarts.find(atom);
2232 if ( start != followOnStarts.end() ) {
2233 // this symbol for the order file corresponds to an atom that is in a cluster that must lay out together
2234 for(const ObjectFile::Atom* nextAtom = start->second; nextAtom != NULL; nextAtom = followOnNexts[nextAtom]) {
2235 std::map<const ObjectFile::Atom*, uint32_t>::iterator pos = theOrdinalOverrideMap.find(nextAtom);
2236 if ( pos == theOrdinalOverrideMap.end() ) {
2237 theOrdinalOverrideMap[nextAtom] = index++;
2238 if (log ) fprintf(stderr, "override ordinal %u assigned to %s in cluster from %s\n", index, nextAtom->getDisplayName(), nextAtom->getFile()->getPath());
2239 }
2240 else {
2241 if (log ) fprintf(stderr, "could not order %s as %u because it was already laid out earlier by %s as %u\n",
2242 atom->getDisplayName(), index, followOnStarts[atom]->getDisplayName(), theOrdinalOverrideMap[atom] );
2243 }
2244 }
2245 }
2246 else {
2247 theOrdinalOverrideMap[atom] = index;
2248 if (log ) fprintf(stderr, "override ordinal %u assigned to %s from %s\n", index, atom->getDisplayName(), atom->getFile()->getPath());
2249 }
2250 ++matchCount;
2251 }
2252 else {
2253 if ( fOptions.printOrderFileStatistics() ) {
2254 if ( it->objectFileName == NULL )
2255 warning("can't find match for order_file entry: %s", it->symbolName);
2256 else
2257 warning("can't find match for order_file entry: %s/%s", it->objectFileName, it->symbolName);
2258 }
2259 }
2260 ++index;
2261 }
2262 if ( fOptions.printOrderFileStatistics() && (fOptions.orderedSymbols().size() != matchCount) ) {
2263 warning("only %u out of %lu order_file symbols were applicable", matchCount, fOptions.orderedSymbols().size() );
2264 }
2265 }
2266
2267 // sort atoms
2268 std::sort(fAllAtoms.begin(), fAllAtoms.end(), Linker::AtomSorter(ordinalOverrideMap, fInitializerAtoms, fTerminatorAtoms));
2269
2270 //fprintf(stderr, "Sorted atoms:\n");
2271 //for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
2272 // fprintf(stderr, "\t%s, %u %s\t%s\n", (*it)->getSectionName(), (*it)->getSection()->getIndex(), (*it)->getDisplayName(), (*it)->getFile()->getPath());
2273 //}
2274 }
2275
2276
2277 // make sure given addresses are within reach of branches, etc
2278 void Linker::tweakLayout()
2279 {
2280 // > 2GB images need their large zero fill atoms sorted to the end to keep access with +/- 2GB
2281 if ( fTotalSize > 0x7F000000 ) {
2282 fBiggerThanTwoGigOutput = true;
2283
2284 if ( (fTotalSize-fTotalZeroFillSize) > 0x7F000000 )
2285 throwf("total output size exceeds 2GB (%lldMB)", (fTotalSize-fTotalZeroFillSize)/(1024*1024));
2286
2287 // move very large (>1MB) zero fill atoms to a new section at very end of __DATA segment
2288 Section* hugeZeroFills = Section::find("__huge", "__DATA", true, true);
2289 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
2290 ObjectFile::Atom* atom = *it;
2291 if ( atom->isZeroFill() && (atom->getSize() > 1024*1024) && (strcmp(atom->getSegment().getName(), "__DATA") == 0) )
2292 atom->setSection(hugeZeroFills);
2293 }
2294 }
2295
2296 // move all initializers to start of __text section
2297 if ( fOptions.readerOptions().fAutoOrderInitializers ) {
2298 // move -init function to front of __text
2299 if ( fOptions.initFunctionName() != NULL ) {
2300 ObjectFile::Atom* initAtom = fGlobalSymbolTable.find(fOptions.initFunctionName());
2301 if ( initAtom == NULL )
2302 throwf("could not find -init function: \"%s\"", fOptions.initFunctionName());
2303 moveToFrontOfSection(initAtom);
2304 }
2305
2306 // move all functions pointed to by __mod_init_func section to front of __text
2307 Section* initSection = Section::find("__mod_init_func", "__DATA", false, true, false);
2308 if ( initSection != NULL ) {
2309 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); ++it) {
2310 if ( (*it)->getSection() == initSection ) {
2311 std::vector<class ObjectFile::Reference*>& references = (*it)->getReferences();
2312 if ( references.size() == 1 )
2313 moveToFrontOfSection(&(references[0]->getTarget()));
2314 }
2315 }
2316 }
2317 }
2318
2319 // move atoms with relocations to start of __DATA,__data section
2320 // <rdar://problem/6061558> linker should order __DATA segment to reduce dyld dirtied pages
2321 if ( fOptions.orderData() ) {
2322 bool slideable = false;
2323 switch ( fOptions.outputKind() ) {
2324 case Options::kDynamicExecutable:
2325 case Options::kStaticExecutable:
2326 case Options::kDyld:
2327 case Options::kPreload:
2328 case Options::kObjectFile:
2329 case Options::kKextBundle:
2330 slideable = false;
2331 break;
2332 case Options::kDynamicLibrary:
2333 case Options::kDynamicBundle:
2334 slideable = true;
2335 break;
2336 }
2337 const bool hasPreferredLoadAddress = (fOptions.baseAddress() != 0);
2338 Section* dataSection = Section::find("__data", "__DATA", false, true, false);
2339 if ( dataSection != NULL ) {
2340 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); ++it) {
2341 ObjectFile::Atom* dataAtom = *it;
2342 if ( dataAtom->getSection() == dataSection ) {
2343 std::vector<class ObjectFile::Reference*>& references = dataAtom->getReferences();
2344 if ( references.size() > 0 ) {
2345 if ( slideable && !hasPreferredLoadAddress ) {
2346 // in a slidable image dyld will need to rebase and bind so any references will need runtime fixups
2347 // if image has preferred base address, assume it will load there and not rebase
2348 moveToFrontOfSection(dataAtom);
2349 }
2350 else {
2351 // in a non-slideable image, dyld will only do binding, so only references to
2352 // symbols in another dylib will need runtime fixups
2353 //fprintf(stderr, "reference from atom %s\n", dataAtom->getDisplayName());
2354 for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
2355 ObjectFile::Reference* reference = *rit;
2356 //fprintf(stderr, "\t%d %s\n", reference->getTarget().getDefinitionKind(), reference->getTarget().getDisplayName());
2357 if ( (reference->getTarget().getDefinitionKind() == ObjectFile::Atom::kExternalDefinition)
2358 || (reference->getTarget().getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition) ) {
2359 moveToFrontOfSection(dataAtom);
2360 break;
2361 }
2362 }
2363 }
2364 }
2365 }
2366 }
2367 }
2368 }
2369
2370 }
2371
2372
2373 void Linker::writeDotOutput()
2374 {
2375 const char* dotOutFilePath = fOptions.dotOutputFile();
2376 if ( dotOutFilePath != NULL ) {
2377 FILE* out = fopen(dotOutFilePath, "w");
2378 if ( out != NULL ) {
2379 // print header
2380 fprintf(out, "digraph dg\n{\n");
2381 fprintf(out, "\tconcentrate = true;\n");
2382 fprintf(out, "\trankdir = LR;\n");
2383
2384 // print each atom as a node
2385 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
2386 ObjectFile::Atom* atom = *it;
2387 if ( atom->getFile() != fOutputFile ) {
2388 const char* name = atom->getDisplayName();
2389 if ( (atom->getDefinitionKind() == ObjectFile::Atom::kExternalDefinition)
2390 || (atom->getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition) ) {
2391 fprintf(out, "\taddr%p [ shape = plaintext, label = \"%s\" ];\n", atom, name);
2392 }
2393 else if ( strcmp(atom->getSectionName(), "__cstring") == 0 ) {
2394 char cstring[atom->getSize()+2];
2395 atom->copyRawContent((uint8_t*)cstring);
2396 fprintf(out, "\taddr%p [ label = \"string: '", atom);
2397 for (const char* s=cstring; *s != '\0'; ++s) {
2398 if ( *s == '\n' )
2399 fprintf(out, "\\\\n");
2400 else
2401 fputc(*s, out);
2402 }
2403 fprintf(out, "'\" ];\n");
2404 }
2405 else {
2406 fprintf(out, "\taddr%p [ label = \"%s\" ];\n", atom, name);
2407 }
2408 }
2409 }
2410 fprintf(out, "\n");
2411
2412 // print each reference as an edge
2413 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
2414 ObjectFile::Atom* fromAtom = *it;
2415 if ( fromAtom->getFile() != fOutputFile ) {
2416 std::vector<ObjectFile::Reference*>& references = fromAtom->getReferences();
2417 std::set<ObjectFile::Atom*> seenTargets;
2418 for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
2419 ObjectFile::Reference* reference = *rit;
2420 ObjectFile::Atom* toAtom = &(reference->getTarget());
2421 if ( seenTargets.count(toAtom) == 0 ) {
2422 seenTargets.insert(toAtom);
2423 fprintf(out, "\taddr%p -> addr%p;\n", fromAtom, toAtom);
2424 }
2425 }
2426 }
2427 }
2428 fprintf(out, "\n");
2429
2430 // push all imports to bottom of graph
2431 fprintf(out, "{ rank = same; ");
2432 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
2433 ObjectFile::Atom* atom = *it;
2434 if ( atom->getFile() != fOutputFile )
2435 if ( (atom->getDefinitionKind() == ObjectFile::Atom::kExternalDefinition)
2436 || (atom->getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition) ) {
2437 fprintf(out, "addr%p; ", atom);
2438 }
2439 }
2440 fprintf(out, "};\n ");
2441
2442 // print footer
2443 fprintf(out, "}\n");
2444 fclose(out);
2445 }
2446 else {
2447 warning("could not write dot output file: %s", dotOutFilePath);
2448 }
2449 }
2450 }
2451
2452 ObjectFile::Atom* Linker::entryPoint(bool orInit, bool searchArchives)
2453 {
2454 // if main executable, find entry point atom
2455 ObjectFile::Atom* entryPoint = NULL;
2456 switch ( fOptions.outputKind() ) {
2457 case Options::kDynamicExecutable:
2458 case Options::kStaticExecutable:
2459 case Options::kDyld:
2460 case Options::kPreload:
2461 entryPoint = fGlobalSymbolTable.find(fOptions.entryName());
2462 if ( (entryPoint == NULL) && searchArchives ) {
2463 // <rdar://problem/7043256> ld64 can not find a -e entry point from an archive
2464 this->addJustInTimeAtoms(fOptions.entryName(), false, true, false);
2465 entryPoint = fGlobalSymbolTable.find(fOptions.entryName());
2466 }
2467 if ( entryPoint == NULL ) {
2468 throwf("could not find entry point \"%s\" (perhaps missing crt1.o)", fOptions.entryName());
2469 }
2470 break;
2471 case Options::kDynamicLibrary:
2472 if ( orInit && (fOptions.initFunctionName() != NULL) ) {
2473 entryPoint = fGlobalSymbolTable.find(fOptions.initFunctionName());
2474 if ( entryPoint == NULL ) {
2475 throwf("could not find -init function: \"%s\"", fOptions.initFunctionName());
2476 }
2477 }
2478 break;
2479 case Options::kObjectFile:
2480 case Options::kDynamicBundle:
2481 case Options::kKextBundle:
2482 entryPoint = NULL;
2483 break;
2484 }
2485 return entryPoint;
2486 }
2487
2488 ObjectFile::Atom* Linker::dyldClassicHelper()
2489 {
2490 if ( fOptions.makeClassicDyldInfo() )
2491 return fGlobalSymbolTable.find("dyld_stub_binding_helper");
2492 else
2493 return NULL;
2494 }
2495
2496 ObjectFile::Atom* Linker::dyldCompressedHelper()
2497 {
2498 if ( fOptions.makeCompressedDyldInfo() ) {
2499 // dyld_stub_binder is in libSystem.B.dylib
2500 ObjectFile::Atom* atom = fGlobalSymbolTable.find("dyld_stub_binder");
2501 if ( atom == NULL ) {
2502 this->addJustInTimeAtoms("dyld_stub_binder", true, false, true);
2503 }
2504 atom = fGlobalSymbolTable.find("dyld_stub_binder");
2505 return atom;
2506 }
2507 else
2508 return NULL;
2509 }
2510
2511 ObjectFile::Atom* Linker::dyldLazyLibraryHelper()
2512 {
2513 return fGlobalSymbolTable.find("dyld_lazy_dylib_stub_binding_helper");
2514 }
2515
2516 const char* Linker::assureFullPath(const char* path)
2517 {
2518 if ( path[0] == '/' )
2519 return path;
2520 char cwdbuff[MAXPATHLEN];
2521 if ( getcwd(cwdbuff, MAXPATHLEN) != NULL ) {
2522 char* result;
2523 asprintf(&result, "%s/%s", cwdbuff, path);
2524 if ( result != NULL )
2525 return result;
2526 }
2527 return path;
2528 }
2529
2530
2531 //
2532 // The stab strings are of the form:
2533 // <name> ':' <type-code> <number-pari>
2534 // but the <name> contain a colon.
2535 // For C++ <name> may contain a double colon (e.g. std::string:f(0,1) )
2536 // For Objective-C name may contain a colon instead square bracket (e.g. [Foo doit:]:f(0,1) )
2537 //
2538 const char* Linker::truncateStabString(const char* str)
2539 {
2540 enum { start, inObjc } state = start;
2541 for (const char* s = str; *s != 0; ++s) {
2542 char c = *s;
2543 switch (state) {
2544 case start:
2545 if ( c == '[' ) {
2546 state = inObjc;
2547 }
2548 else {
2549 if ( c == ':' ) {
2550 if ( s[1] == ':' ) {
2551 ++s;
2552 }
2553 else {
2554 // found colon
2555 // Duplicate strndup behavior here.
2556 int trunStrLen = s-str+2;
2557 char* temp = new char[trunStrLen+1];
2558 memcpy(temp, str, trunStrLen);
2559 temp[trunStrLen] = '\0';
2560 return temp;
2561 }
2562 }
2563 }
2564 break;
2565 case inObjc:
2566 if ( c == ']' ) {
2567 state = start;
2568 }
2569 break;
2570 }
2571 }
2572 // malformed
2573 return str;
2574 }
2575
2576
2577 bool Linker::minimizeStab(ObjectFile::Reader::Stab& stab)
2578 {
2579 switch(stab.type){
2580 case N_GSYM:
2581 case N_STSYM:
2582 case N_LCSYM:
2583 case N_FUN:
2584 // these all need truncated strings
2585 stab.string = truncateStabString(stab.string);
2586 return true;
2587 case N_SO:
2588 case N_OSO:
2589 case N_OPT:
2590 case N_SOL:
2591 // these are included in the minimal stabs, but they keep their full string
2592 return true;
2593 default:
2594 return false;
2595 }
2596 }
2597
2598
2599 struct HeaderRange {
2600 std::vector<ObjectFile::Reader::Stab>::iterator begin;
2601 std::vector<ObjectFile::Reader::Stab>::iterator end;
2602 int parentRangeIndex;
2603 uint32_t sum;
2604 bool sumPrecomputed;
2605 bool useEXCL;
2606 bool cannotEXCL; // because of SLINE, etc stabs
2607 };
2608
2609
2610 typedef __gnu_cxx::hash_map<const char*, std::vector<uint32_t>, __gnu_cxx::hash<const char*>, CStringEquals> PathToSums;
2611
2612 // hash table that maps header path to a vector of known checksums for that path
2613 static PathToSums sKnownBINCLs;
2614
2615
2616 void Linker::collectStabs(ObjectFile::Reader* reader, std::map<const class ObjectFile::Atom*, uint32_t>& atomOrdinals)
2617 {
2618 const bool log = false;
2619 bool minimal = ( fOptions.readerOptions().fDebugInfoStripping == ObjectFile::ReaderOptions::kDebugInfoMinimal );
2620 std::vector<class ObjectFile::Reader::Stab>* readerStabs = reader->getStabs();
2621 if ( readerStabs == NULL )
2622 return;
2623
2624 if ( log ) fprintf(stderr, "processesing %lu stabs for %s\n", readerStabs->size(), reader->getPath());
2625 std::vector<HeaderRange> ranges;
2626 int curRangeIndex = -1;
2627 int count = 0;
2628 ObjectFile::Atom* atomWithLowestOrdinal = NULL;
2629 ObjectFile::Atom* atomWithHighestOrdinal = NULL;
2630 uint32_t highestOrdinal = 0;
2631 uint32_t lowestOrdinal = UINT_MAX;
2632 std::vector<std::pair<ObjectFile::Atom*,ObjectFile::Atom*> > soRanges;
2633 // 1) find all (possibly nested) BINCL/EINCL ranges and their checksums
2634 // 2) find all SO/SO ranges and the first/last atom own by a FUN stab therein
2635 for(std::vector<class ObjectFile::Reader::Stab>::iterator it=readerStabs->begin(); it != readerStabs->end(); ++it) {
2636 ++count;
2637 switch ( it->type ) {
2638 case N_BINCL:
2639 {
2640 HeaderRange range;
2641 range.begin = it;
2642 range.end = readerStabs->end();
2643 range.parentRangeIndex = curRangeIndex;
2644 range.sum = it->value;
2645 range.sumPrecomputed = (range.sum != 0);
2646 range.useEXCL = false;
2647 range.cannotEXCL = false;
2648 curRangeIndex = ranges.size();
2649 if ( log ) fprintf(stderr, "[%d]BINCL %s\n", curRangeIndex, it->string);
2650 ranges.push_back(range);
2651 }
2652 break;
2653 case N_EINCL:
2654 if ( curRangeIndex == -1 ) {
2655 warning("EINCL missing BINCL in %s", reader->getPath());
2656 }
2657 else {
2658 ranges[curRangeIndex].end = it+1;
2659 if ( log ) fprintf(stderr, "[%d->%d]EINCL %s\n", curRangeIndex, ranges[curRangeIndex].parentRangeIndex, it->string);
2660 curRangeIndex = ranges[curRangeIndex].parentRangeIndex;
2661 }
2662 break;
2663 case N_FUN:
2664 {
2665 std::map<const class ObjectFile::Atom*, uint32_t>::iterator pos = atomOrdinals.find(it->atom);
2666 if ( pos != atomOrdinals.end() ) {
2667 uint32_t ordinal = pos->second;
2668 if ( ordinal > highestOrdinal ) {
2669 highestOrdinal = ordinal;
2670 atomWithHighestOrdinal = it->atom;
2671 }
2672 if ( ordinal < lowestOrdinal ) {
2673 lowestOrdinal = ordinal;
2674 atomWithLowestOrdinal = it->atom;
2675 }
2676 }
2677 }
2678 // fall through
2679 case N_BNSYM:
2680 case N_ENSYM:
2681 case N_LBRAC:
2682 case N_RBRAC:
2683 case N_SLINE:
2684 case N_STSYM:
2685 case N_LCSYM:
2686 if ( curRangeIndex != -1 ) {
2687 ranges[curRangeIndex].cannotEXCL = true;
2688 if ( fOptions.warnStabs() )
2689 warning("cannot do BINCL/EINCL optimzation because of stabs kinds in %s for %s\n", ranges[curRangeIndex].begin->string, reader->getPath());
2690 }
2691 break;
2692 case N_SO:
2693 if ( (it->string != NULL) && (strlen(it->string) > 0) ) {
2694 // start SO, reset hi/low FUN tracking
2695 atomWithLowestOrdinal = NULL;
2696 atomWithHighestOrdinal = NULL;
2697 highestOrdinal = 0;
2698 lowestOrdinal = UINT_MAX;
2699 }
2700 else {
2701 // end SO, record hi/low atoms for this SO range
2702 soRanges.push_back(std::make_pair<ObjectFile::Atom*,ObjectFile::Atom*>(atomWithLowestOrdinal, atomWithHighestOrdinal));
2703 }
2704 // fall through
2705 default:
2706 if ( curRangeIndex != -1 ) {
2707 if ( ! ranges[curRangeIndex].sumPrecomputed ) {
2708 uint32_t sum = 0;
2709 const char* s = it->string;
2710 char c;
2711 while ( (c = *s++) != 0 ) {
2712 sum += c;
2713 // don't checkusm first number (file index) after open paren in string
2714 if ( c == '(' ) {
2715 while(isdigit(*s))
2716 ++s;
2717 }
2718 }
2719 ranges[curRangeIndex].sum += sum;
2720 }
2721 }
2722
2723 }
2724 }
2725 if ( log ) fprintf(stderr, "processesed %d stabs for %s\n", count, reader->getPath());
2726 if ( curRangeIndex != -1 )
2727 warning("BINCL (%s) missing EINCL in %s", ranges[curRangeIndex].begin->string, reader->getPath());
2728
2729 // if no BINCLs
2730 if ( ranges.size() == 0 ) {
2731 unsigned int soIndex = 0;
2732 for(std::vector<ObjectFile::Reader::Stab>::iterator it=readerStabs->begin(); it != readerStabs->end(); ++it) {
2733 // copy minimal or all stabs
2734 ObjectFile::Reader::Stab stab = *it;
2735 if ( !minimal || minimizeStab(stab) ) {
2736 if ( stab.type == N_SO ) {
2737 if ( soIndex < soRanges.size() ) {
2738 if ( (stab.string != NULL) && (strlen(stab.string) > 0) ) {
2739 // starting SO is associated with first atom
2740 stab.atom = soRanges[soIndex].first;
2741 }
2742 else {
2743 // ending SO is associated with last atom
2744 stab.atom = soRanges[soIndex].second;
2745 ++soIndex;
2746 }
2747 }
2748 }
2749 fStabs.push_back(stab);
2750 }
2751 }
2752 return;
2753 }
2754
2755 //fprintf(stderr, "BINCL/EINCL info for %s\n", reader->getPath());
2756 //for(std::vector<HeaderRange>::iterator it=ranges.begin(); it != ranges.end(); ++it) {
2757 // fprintf(stderr, "%08X %s\n", it->sum, it->begin->string);
2758 //}
2759
2760 // see if any of these BINCL/EINCL ranges have already been seen and therefore can be replaced with EXCL
2761 for(std::vector<HeaderRange>::iterator it=ranges.begin(); it != ranges.end(); ++it) {
2762 if ( ! it->cannotEXCL ) {
2763 const char* header = it->begin->string;
2764 uint32_t sum = it->sum;
2765 PathToSums::iterator pos = sKnownBINCLs.find(header);
2766 if ( pos != sKnownBINCLs.end() ) {
2767 std::vector<uint32_t>& sums = pos->second;
2768 for(std::vector<uint32_t>::iterator sit=sums.begin(); sit != sums.end(); ++sit) {
2769 if (*sit == sum) {
2770 //fprintf(stderr, "use EXCL for %s in %s\n", header, reader->getPath());
2771 it->useEXCL = true;
2772 break;
2773 }
2774 }
2775 if ( ! it->useEXCL ) {
2776 // have seen this path, but not this checksum
2777 //fprintf(stderr, "registering another checksum %08X for %s\n", sum, header);
2778 sums.push_back(sum);
2779 }
2780 }
2781 else {
2782 // have not seen this path, so add to known BINCLs
2783 std::vector<uint32_t> empty;
2784 sKnownBINCLs[header] = empty;
2785 sKnownBINCLs[header].push_back(sum);
2786 //fprintf(stderr, "registering checksum %08X for %s\n", sum, header);
2787 }
2788 }
2789 }
2790
2791 // add a new set of stabs with BINCL/EINCL runs that have been seen before, replaced with EXCLs
2792 curRangeIndex = -1;
2793 const int maxRangeIndex = ranges.size();
2794 int soIndex = 0;
2795 for(std::vector<ObjectFile::Reader::Stab>::iterator it=readerStabs->begin(); it != readerStabs->end(); ++it) {
2796 switch ( it->type ) {
2797 case N_BINCL:
2798 for(int i=curRangeIndex+1; i < maxRangeIndex; ++i) {
2799 if ( ranges[i].begin == it ) {
2800 curRangeIndex = i;
2801 HeaderRange& range = ranges[curRangeIndex];
2802 ObjectFile::Reader::Stab stab = *it;
2803 stab.value = range.sum; // BINCL and EXCL have n_value set to checksum
2804 if ( range.useEXCL )
2805 stab.type = N_EXCL; // transform BINCL into EXCL
2806 if ( !minimal )
2807 fStabs.push_back(stab);
2808 break;
2809 }
2810 }
2811 break;
2812 case N_EINCL:
2813 if ( curRangeIndex != -1 ) {
2814 if ( !ranges[curRangeIndex].useEXCL && !minimal )
2815 fStabs.push_back(*it);
2816 curRangeIndex = ranges[curRangeIndex].parentRangeIndex;
2817 }
2818 break;
2819 default:
2820 if ( (curRangeIndex == -1) || !ranges[curRangeIndex].useEXCL ) {
2821 ObjectFile::Reader::Stab stab = *it;
2822 if ( !minimal || minimizeStab(stab) ) {
2823 if ( stab.type == N_SO ) {
2824 if ( (stab.string != NULL) && (strlen(stab.string) > 0) ) {
2825 // starting SO is associated with first atom
2826 stab.atom = soRanges[soIndex].first;
2827 }
2828 else {
2829 // ending SO is associated with last atom
2830 stab.atom = soRanges[soIndex].second;
2831 ++soIndex;
2832 }
2833 }
2834 fStabs.push_back(stab);
2835 }
2836 }
2837 }
2838 }
2839
2840 }
2841
2842
2843 // used to prune out atoms that don't need debug notes generated
2844 class NoDebugNoteAtom
2845 {
2846 public:
2847 NoDebugNoteAtom(const std::map<class ObjectFile::Reader*, uint32_t>& readersWithDwarfOrdinals)
2848 : fReadersWithDwarfOrdinals(readersWithDwarfOrdinals) {}
2849
2850 bool operator()(const ObjectFile::Atom* atom) const {
2851 if ( atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn )
2852 return true;
2853 if ( atom->getName() == NULL )
2854 return true;
2855 if ( fReadersWithDwarfOrdinals.find(atom->getFile()) == fReadersWithDwarfOrdinals.end() )
2856 return true;
2857 return false;
2858 }
2859
2860 private:
2861 const std::map<class ObjectFile::Reader*, uint32_t>& fReadersWithDwarfOrdinals;
2862 };
2863
2864 // used to sort atoms with debug notes
2865 class ReadersWithDwarfSorter
2866 {
2867 public:
2868 ReadersWithDwarfSorter(const std::map<class ObjectFile::Reader*, uint32_t>& readersWithDwarfOrdinals,
2869 const std::map<const class ObjectFile::Atom*, uint32_t>& atomOrdinals)
2870 : fReadersWithDwarfOrdinals(readersWithDwarfOrdinals), fAtomOrdinals(atomOrdinals) {}
2871
2872 bool operator()(const ObjectFile::Atom* left, const ObjectFile::Atom* right) const
2873 {
2874 // first sort by reader
2875 unsigned int leftReaderIndex = fReadersWithDwarfOrdinals.find(left->getFile())->second;
2876 unsigned int rightReaderIndex = fReadersWithDwarfOrdinals.find(right->getFile())->second;
2877 if ( leftReaderIndex != rightReaderIndex )
2878 return (leftReaderIndex < rightReaderIndex);
2879
2880 // then sort by atom ordinal
2881 unsigned int leftAtomIndex = fAtomOrdinals.find(left)->second;
2882 unsigned int rightAtomIndex = fAtomOrdinals.find(right)->second;
2883 return leftAtomIndex < rightAtomIndex;
2884 }
2885
2886 private:
2887 const std::map<class ObjectFile::Reader*, uint32_t>& fReadersWithDwarfOrdinals;
2888 const std::map<const class ObjectFile::Atom*, uint32_t>& fAtomOrdinals;
2889 };
2890
2891
2892
2893
2894
2895 void Linker::synthesizeDebugNotes(std::vector<class ObjectFile::Atom*>& allAtomsByReader)
2896 {
2897 // synthesize "debug notes" and add them to master stabs vector
2898 const char* dirPath = NULL;
2899 const char* filename = NULL;
2900 bool wroteStartSO = false;
2901 bool useZeroOSOModTime = (getenv("RC_RELEASE") != NULL);
2902 __gnu_cxx::hash_set<const char*, __gnu_cxx::hash<const char*>, CStringEquals> seenFiles;
2903 for (std::vector<ObjectFile::Atom*>::iterator it=allAtomsByReader.begin(); it != allAtomsByReader.end(); it++) {
2904 ObjectFile::Atom* atom = *it;
2905 const char* newDirPath;
2906 const char* newFilename;
2907 //fprintf(stderr, "debug note for %s\n", atom->getDisplayName());
2908 if ( atom->getTranslationUnitSource(&newDirPath, &newFilename) ) {
2909 // need SO's whenever the translation unit source file changes
2910 if ( newFilename != filename ) {
2911 // gdb like directory SO's to end in '/', but dwarf DW_AT_comp_dir usually does not have trailing '/'
2912 if ( (newDirPath != NULL) && (strlen(newDirPath) > 1 ) && (newDirPath[strlen(newDirPath)-1] != '/') )
2913 asprintf((char**)&newDirPath, "%s/", newDirPath);
2914 if ( filename != NULL ) {
2915 // translation unit change, emit ending SO
2916 ObjectFile::Reader::Stab endFileStab;
2917 endFileStab.atom = NULL;
2918 endFileStab.type = N_SO;
2919 endFileStab.other = 1;
2920 endFileStab.desc = 0;
2921 endFileStab.value = 0;
2922 endFileStab.string = "";
2923 fStabs.push_back(endFileStab);
2924 }
2925 // new translation unit, emit start SO's
2926 ObjectFile::Reader::Stab dirPathStab;
2927 dirPathStab.atom = NULL;
2928 dirPathStab.type = N_SO;
2929 dirPathStab.other = 0;
2930 dirPathStab.desc = 0;
2931 dirPathStab.value = 0;
2932 dirPathStab.string = newDirPath;
2933 fStabs.push_back(dirPathStab);
2934 ObjectFile::Reader::Stab fileStab;
2935 fileStab.atom = NULL;
2936 fileStab.type = N_SO;
2937 fileStab.other = 0;
2938 fileStab.desc = 0;
2939 fileStab.value = 0;
2940 fileStab.string = newFilename;
2941 fStabs.push_back(fileStab);
2942 // Synthesize OSO for start of file
2943 ObjectFile::Reader::Stab objStab;
2944 objStab.atom = NULL;
2945 objStab.type = N_OSO;
2946 // <rdar://problem/6337329> linker should put cpusubtype in n_sect field of nlist entry for N_OSO debug note entries
2947 objStab.other = atom->getFile()->updateCpuConstraint(0);
2948 objStab.desc = 1;
2949 objStab.value = useZeroOSOModTime ? 0 : atom->getFile()->getModificationTime();
2950 objStab.string = assureFullPath(atom->getFile()->getPath());
2951 fStabs.push_back(objStab);
2952 wroteStartSO = true;
2953 // add the source file path to seenFiles so it does not show up in SOLs
2954 seenFiles.insert(newFilename);
2955 }
2956 filename = newFilename;
2957 dirPath = newDirPath;
2958 if ( atom->getSegment().isContentExecutable() && (strncmp(atom->getSectionName(), "__text", 6) == 0) ) {
2959 // Synthesize BNSYM and start FUN stabs
2960 ObjectFile::Reader::Stab beginSym;
2961 beginSym.atom = atom;
2962 beginSym.type = N_BNSYM;
2963 beginSym.other = 1;
2964 beginSym.desc = 0;
2965 beginSym.value = 0;
2966 beginSym.string = "";
2967 fStabs.push_back(beginSym);
2968 ObjectFile::Reader::Stab startFun;
2969 startFun.atom = atom;
2970 startFun.type = N_FUN;
2971 startFun.other = 1;
2972 startFun.desc = 0;
2973 startFun.value = 0;
2974 startFun.string = atom->getName();
2975 fStabs.push_back(startFun);
2976 // Synthesize any SOL stabs needed
2977 std::vector<ObjectFile::LineInfo>* lineInfo = atom->getLineInfo();
2978 if ( lineInfo != NULL ) {
2979 const char* curFile = NULL;
2980 for (std::vector<ObjectFile::LineInfo>::iterator it = lineInfo->begin(); it != lineInfo->end(); ++it) {
2981 if ( it->fileName != curFile ) {
2982 if ( seenFiles.count(it->fileName) == 0 ) {
2983 seenFiles.insert(it->fileName);
2984 ObjectFile::Reader::Stab sol;
2985 sol.atom = 0;
2986 sol.type = N_SOL;
2987 sol.other = 0;
2988 sol.desc = 0;
2989 sol.value = 0;
2990 sol.string = it->fileName;
2991 fStabs.push_back(sol);
2992 }
2993 curFile = it->fileName;
2994 }
2995 }
2996 }
2997 // Synthesize end FUN and ENSYM stabs
2998 ObjectFile::Reader::Stab endFun;
2999 endFun.atom = atom;
3000 endFun.type = N_FUN;
3001 endFun.other = 0;
3002 endFun.desc = 0;
3003 endFun.value = 0;
3004 endFun.string = "";
3005 fStabs.push_back(endFun);
3006 ObjectFile::Reader::Stab endSym;
3007 endSym.atom = atom;
3008 endSym.type = N_ENSYM;
3009 endSym.other = 1;
3010 endSym.desc = 0;
3011 endSym.value = 0;
3012 endSym.string = "";
3013 fStabs.push_back(endSym);
3014 }
3015 else if ( atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn ) {
3016 // no stabs for atoms that would not be in the symbol table
3017 }
3018 else if ( atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableInAsAbsolute ) {
3019 // no stabs for absolute symbols
3020 }
3021 else if ( (strcmp(atom->getSectionName(), "__eh_frame") == 0) ) {
3022 // no stabs for .eh atoms
3023 }
3024 else if ( (strncmp(atom->getName(), "__dtrace_probe$", 15) == 0) ) {
3025 // no stabs for old style dtrace probes
3026 }
3027 else {
3028 ObjectFile::Reader::Stab globalsStab;
3029 const char* name = atom->getName();
3030 if ( atom->getScope() == ObjectFile::Atom::scopeTranslationUnit ) {
3031 // Synthesize STSYM stab for statics
3032 globalsStab.atom = atom;
3033 globalsStab.type = N_STSYM;
3034 globalsStab.other = 1;
3035 globalsStab.desc = 0;
3036 globalsStab.value = 0;
3037 globalsStab.string = name;
3038 fStabs.push_back(globalsStab);
3039 }
3040 else {
3041 // Synthesize GSYM stab for other globals
3042 globalsStab.atom = atom;
3043 globalsStab.type = N_GSYM;
3044 globalsStab.other = 1;
3045 globalsStab.desc = 0;
3046 globalsStab.value = 0;
3047 globalsStab.string = name;
3048 fStabs.push_back(globalsStab);
3049 }
3050 }
3051 }
3052 }
3053
3054 if ( wroteStartSO ) {
3055 // emit ending SO
3056 ObjectFile::Reader::Stab endFileStab;
3057 endFileStab.atom = NULL;
3058 endFileStab.type = N_SO;
3059 endFileStab.other = 1;
3060 endFileStab.desc = 0;
3061 endFileStab.value = 0;
3062 endFileStab.string = "";
3063 fStabs.push_back(endFileStab);
3064 }
3065 }
3066
3067
3068
3069
3070 void Linker::collectDebugInfo()
3071 {
3072 std::map<const class ObjectFile::Atom*, uint32_t> atomOrdinals;
3073 fStartDebugTime = mach_absolute_time();
3074 if ( fOptions.readerOptions().fDebugInfoStripping != ObjectFile::ReaderOptions::kDebugInfoNone ) {
3075
3076 // determine mixture of stabs and dwarf
3077 bool someStabs = false;
3078 bool someDwarf = false;
3079 for (std::vector<class ObjectFile::Reader*>::iterator it=fReadersThatHaveSuppliedAtoms.begin();
3080 it != fReadersThatHaveSuppliedAtoms.end();
3081 it++) {
3082 ObjectFile::Reader* reader = *it;
3083 if ( reader != NULL ) {
3084 switch ( reader->getDebugInfoKind() ) {
3085 case ObjectFile::Reader::kDebugInfoNone:
3086 break;
3087 case ObjectFile::Reader::kDebugInfoStabs:
3088 someStabs = true;
3089 break;
3090 case ObjectFile::Reader::kDebugInfoDwarf:
3091 someDwarf = true;
3092 fCreateUUID = true;
3093 break;
3094 case ObjectFile::Reader::kDebugInfoStabsUUID:
3095 someStabs = true;
3096 fCreateUUID = true;
3097 break;
3098 default:
3099 throw "Unhandled type of debug information";
3100 }
3101 }
3102 }
3103
3104 if ( someDwarf || someStabs ) {
3105 // try to minimize re-allocations
3106 fStabs.reserve(1024);
3107
3108 // make mapping from atoms to ordinal
3109 uint32_t ordinal = 1;
3110 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
3111 atomOrdinals[*it] = ordinal++;
3112 }
3113 }
3114
3115 // process all dwarf .o files as a batch
3116 if ( someDwarf ) {
3117 // make mapping from readers with dwarf to ordinal
3118 std::map<class ObjectFile::Reader*, uint32_t> readersWithDwarfOrdinals;
3119 uint32_t readerOrdinal = 1;
3120 for (std::vector<class ObjectFile::Reader*>::iterator it=fReadersThatHaveSuppliedAtoms.begin();
3121 it != fReadersThatHaveSuppliedAtoms.end();
3122 it++) {
3123 ObjectFile::Reader* reader = *it;
3124 if ( (reader != NULL) && (reader->getDebugInfoKind() == ObjectFile::Reader::kDebugInfoDwarf) ) {
3125 readersWithDwarfOrdinals[reader] = readerOrdinal++;
3126 }
3127 }
3128
3129 // make a vector of atoms
3130 std::vector<class ObjectFile::Atom*> allAtomsByReader(fAllAtoms.begin(), fAllAtoms.end());
3131 // remove those not from a reader that has dwarf
3132 allAtomsByReader.erase(std::remove_if(allAtomsByReader.begin(), allAtomsByReader.end(),
3133 NoDebugNoteAtom(readersWithDwarfOrdinals)), allAtomsByReader.end());
3134 // sort by reader then atom ordinal
3135 std::sort(allAtomsByReader.begin(), allAtomsByReader.end(), ReadersWithDwarfSorter(readersWithDwarfOrdinals, atomOrdinals));
3136 // add debug notes for each atom
3137 this->synthesizeDebugNotes(allAtomsByReader);
3138 }
3139
3140 // process all stabs .o files one by one
3141 if ( someStabs ) {
3142 // get stabs from each reader, in command line order
3143 for (std::vector<class ObjectFile::Reader*>::iterator it=fReadersThatHaveSuppliedAtoms.begin();
3144 it != fReadersThatHaveSuppliedAtoms.end();
3145 it++) {
3146 ObjectFile::Reader* reader = *it;
3147 if ( reader != NULL ) {
3148 switch ( reader->getDebugInfoKind() ) {
3149 case ObjectFile::Reader::kDebugInfoDwarf:
3150 case ObjectFile::Reader::kDebugInfoNone:
3151 // do nothing
3152 break;
3153 case ObjectFile::Reader::kDebugInfoStabs:
3154 case ObjectFile::Reader::kDebugInfoStabsUUID:
3155 collectStabs(reader, atomOrdinals);
3156 break;
3157 default:
3158 throw "Unhandled type of debug information";
3159 }
3160 }
3161 }
3162 // remove stabs associated with atoms that won't be in output
3163 std::set<class ObjectFile::Atom*> allAtomsSet;
3164 allAtomsSet.insert(fAllAtoms.begin(), fAllAtoms.end());
3165 fStabs.erase(std::remove_if(fStabs.begin(), fStabs.end(), NotInSet(allAtomsSet)), fStabs.end());
3166 }
3167 }
3168 }
3169
3170 void Linker::writeOutput()
3171 {
3172 // <rdar://problem/6933931> ld -r of empty .o file should preserve sub-type
3173 // <rdar://problem/7049478> empty dylib should have subtype from command line
3174 if ( fOptions.preferSubArchitecture() && (fOptions.architecture() == CPU_TYPE_ARM) ) {
3175 fCurrentCpuConstraint = (ObjectFile::Reader::CpuConstraint)fOptions.subArchitecture();
3176 }
3177
3178 if ( fOptions.forceCpuSubtypeAll() )
3179 fCurrentCpuConstraint = ObjectFile::Reader::kCpuAny;
3180
3181 fStartWriteTime = mach_absolute_time();
3182 // tell writer about each segment's atoms
3183 fOutputFileSize = fOutputFile->write(fAllAtoms, fStabs, this->entryPoint(true),
3184 fCreateUUID, fCanScatter,
3185 fCurrentCpuConstraint,
3186 fRegularDefAtomsThatOverrideADylibsWeakDef,
3187 fGlobalSymbolTable.hasExternalWeakDefinitions());
3188 }
3189
3190 const char* Linker::fileArch(const void* p)
3191 {
3192 const uint8_t* bytes = (uint8_t*)p;
3193 const char* result;
3194 result = mach_o::relocatable::Reader<ppc>::fileKind(bytes);
3195 if ( result != NULL )
3196 return result;
3197 result = mach_o::relocatable::Reader<ppc64>::fileKind(bytes);
3198 if ( result != NULL )
3199 return result;
3200 result = mach_o::relocatable::Reader<x86>::fileKind(bytes);
3201 if ( result != NULL )
3202 return result;
3203 result = mach_o::relocatable::Reader<x86_64>::fileKind(bytes);
3204 if ( result != NULL )
3205 return result;
3206 result = mach_o::relocatable::Reader<arm>::fileKind(bytes);
3207 if ( result != NULL )
3208 return result;
3209
3210 result = lto::Reader::fileKind(bytes);
3211 if ( result != NULL )
3212 return result;
3213
3214 return "unsupported file format";
3215 }
3216
3217 ObjectFile::Reader* Linker::createReader(const Options::FileInfo& info)
3218 {
3219 // map in whole file
3220 uint64_t len = info.fileLen;
3221 int fd = ::open(info.path, O_RDONLY, 0);
3222 if ( fd == -1 )
3223 throwf("can't open file, errno=%d", errno);
3224 if ( info.fileLen < 20 )
3225 throw "file too small";
3226
3227 uint8_t* p = (uint8_t*)::mmap(NULL, info.fileLen, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
3228 if ( p == (uint8_t*)(-1) )
3229 throwf("can't map file, errno=%d", errno);
3230
3231 // if fat file, skip to architecture we want
3232 // Note: fat header is always big-endian
3233 bool isFatFile = false;
3234 const fat_header* fh = (fat_header*)p;
3235 if ( fh->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) {
3236 isFatFile = true;
3237 const struct fat_arch* archs = (struct fat_arch*)(p + sizeof(struct fat_header));
3238 uint32_t sliceToUse;
3239 bool sliceFound = false;
3240 if ( fOptions.preferSubArchitecture() ) {
3241 // first try to find a slice that match cpu-type and cpu-sub-type
3242 for (uint32_t i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) {
3243 if ( (OSSwapBigToHostInt32(archs[i].cputype) == (uint32_t)fArchitecture)
3244 && (OSSwapBigToHostInt32(archs[i].cpusubtype) == (uint32_t)fOptions.subArchitecture()) ) {
3245 sliceToUse = i;
3246 sliceFound = true;
3247 break;
3248 }
3249 }
3250 }
3251 if ( !sliceFound ) {
3252 // look for any slice that matches just cpu-type
3253 for (uint32_t i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) {
3254 if ( OSSwapBigToHostInt32(archs[i].cputype) == (uint32_t)fArchitecture ) {
3255 sliceToUse = i;
3256 sliceFound = true;
3257 break;
3258 }
3259 }
3260 }
3261 if ( sliceFound ) {
3262 uint32_t fileOffset = OSSwapBigToHostInt32(archs[sliceToUse].offset);
3263 len = OSSwapBigToHostInt32(archs[sliceToUse].size);
3264 // if requested architecture is page aligned within fat file, then remap just that portion of file
3265 if ( (fileOffset & 0x00000FFF) == 0 ) {
3266 // unmap whole file
3267 munmap((caddr_t)p, info.fileLen);
3268 // re-map just part we need
3269 p = (uint8_t*)::mmap(NULL, len, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, fileOffset);
3270 if ( p == (uint8_t*)(-1) )
3271 throwf("can't re-map file, errno=%d", errno);
3272 }
3273 else {
3274 p = &p[fileOffset];
3275 }
3276 }
3277 }
3278 ::close(fd);
3279
3280 bool objSubtypeMustMatch = (fOptions.preferSubArchitecture() && !fOptions.allowSubArchitectureMismatches());
3281 switch (fArchitecture) {
3282 case CPU_TYPE_POWERPC:
3283 if ( mach_o::relocatable::Reader<ppc>::validFile(p) )
3284 return this->addObject(new mach_o::relocatable::Reader<ppc>::Reader(p, info.path, info.modTime, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3285 else if ( mach_o::dylib::Reader<ppc>::validFile(p, info.options.fBundleLoader) )
3286 return this->addDylib(new mach_o::dylib::Reader<ppc>::Reader(p, len, info.path, info.options, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3287 else if ( archive::Reader<ppc>::validFile(p, len) )
3288 return this->addArchive(new archive::Reader<ppc>::Reader(p, len, info.path, info.modTime, info.options, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3289 break;
3290 case CPU_TYPE_POWERPC64:
3291 if ( mach_o::relocatable::Reader<ppc64>::validFile(p) )
3292 return this->addObject(new mach_o::relocatable::Reader<ppc64>::Reader(p, info.path, info.modTime, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3293 else if ( mach_o::dylib::Reader<ppc64>::validFile(p, info.options.fBundleLoader) )
3294 return this->addDylib(new mach_o::dylib::Reader<ppc64>::Reader(p, len, info.path, info.options, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3295 else if ( archive::Reader<ppc64>::validFile(p, len) )
3296 return this->addArchive(new archive::Reader<ppc64>::Reader(p, len, info.path, info.modTime, info.options, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3297 break;
3298 case CPU_TYPE_I386:
3299 if ( mach_o::relocatable::Reader<x86>::validFile(p) )
3300 return this->addObject(new mach_o::relocatable::Reader<x86>::Reader(p, info.path, info.modTime, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3301 else if ( mach_o::dylib::Reader<x86>::validFile(p, info.options.fBundleLoader) )
3302 return this->addDylib(new mach_o::dylib::Reader<x86>::Reader(p, len, info.path, info.options, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3303 else if ( archive::Reader<x86>::validFile(p, len) )
3304 return this->addArchive(new archive::Reader<x86>::Reader(p, len, info.path, info.modTime, info.options, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3305 break;
3306 case CPU_TYPE_X86_64:
3307 if ( mach_o::relocatable::Reader<x86_64>::validFile(p) )
3308 return this->addObject(new mach_o::relocatable::Reader<x86_64>::Reader(p, info.path, info.modTime, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3309 else if ( mach_o::dylib::Reader<x86_64>::validFile(p, info.options.fBundleLoader) )
3310 return this->addDylib(new mach_o::dylib::Reader<x86_64>::Reader(p, len, info.path, info.options, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3311 else if ( archive::Reader<x86_64>::validFile(p, len) )
3312 return this->addArchive(new archive::Reader<x86_64>::Reader(p, len, info.path, info.modTime, info.options, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3313 case CPU_TYPE_ARM:
3314 if ( mach_o::relocatable::Reader<arm>::validFile(p, objSubtypeMustMatch, fOptions.subArchitecture()) )
3315 return this->addObject(new mach_o::relocatable::Reader<arm>::Reader(p, info.path, info.modTime, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3316 else if ( mach_o::dylib::Reader<arm>::validFile(p, info.options.fBundleLoader) )
3317 return this->addDylib(new mach_o::dylib::Reader<arm>::Reader(p, len, info.path, info.options, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3318 else if ( archive::Reader<arm>::validFile(p, len) )
3319 return this->addArchive(new archive::Reader<arm>::Reader(p, len, info.path, info.modTime, info.options, fOptions.readerOptions(), fNextInputOrdinal), info, len);
3320 break;
3321 }
3322
3323 #if LTO_SUPPORT
3324 if ( lto::Reader::validFile(p, len, fArchitecture) ) {
3325 return this->addObject(new lto::Reader(p, len, info.path, info.modTime, fOptions.readerOptions(), fArchitecture), info, len);
3326 }
3327 else if ( lto::Reader::fileKind((uint8_t*)p) != NULL ) {
3328 if ( lto::Reader::loaded() ) {
3329 throwf("file was built for %s which is not the architecture being linked (%s)", fileArch(p), fArchitectureName);
3330 }
3331 else {
3332 const char* libLTO = "libLTO.dylib";
3333 char ldPath[PATH_MAX];
3334 char tmpPath[PATH_MAX];
3335 char libLTOPath[PATH_MAX];
3336 uint32_t bufSize = PATH_MAX;
3337 if ( _NSGetExecutablePath(ldPath, &bufSize) != -1 ) {
3338 if ( realpath(ldPath, tmpPath) != NULL ) {
3339 char* lastSlash = strrchr(tmpPath, '/');
3340 if ( lastSlash != NULL )
3341 strcpy(lastSlash, "/../lib/libLTO.dylib");
3342 libLTO = tmpPath;
3343 if ( realpath(tmpPath, libLTOPath) != NULL )
3344 libLTO = libLTOPath;
3345 }
3346 }
3347 throwf("could not process llvm bitcode object file, because %s could not be loaded", libLTO);
3348 }
3349 }
3350 #endif
3351 // error handling
3352 if ( ((fat_header*)p)->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) {
3353 throwf("missing required architecture %s in file", fArchitectureName);
3354 }
3355 else {
3356 if ( isFatFile )
3357 throwf("file is universal but does not contain a(n) %s slice", fArchitectureName);
3358 else
3359 throwf("file was built for %s which is not the architecture being linked (%s)", fileArch(p), fArchitectureName);
3360 }
3361 }
3362
3363 void Linker::logDylib(ObjectFile::Reader* reader, bool indirect)
3364 {
3365 if ( fOptions.readerOptions().fTraceDylibs ) {
3366 const char* fullPath = reader->getPath();
3367 char realName[MAXPATHLEN];
3368 if ( realpath(fullPath, realName) != NULL )
3369 fullPath = realName;
3370 if ( indirect )
3371 logTraceInfo("[Logging for XBS] Used indirect dynamic library: %s\n", fullPath);
3372 else
3373 logTraceInfo("[Logging for XBS] Used dynamic library: %s\n", fullPath);
3374 }
3375 }
3376
3377
3378
3379 ObjectFile::Reader* Linker::findDylib(const char* installPath, const char* fromPath)
3380 {
3381 //fprintf(stderr, "findDylib(%s, %s)\n", installPath, fromPath);
3382 InstallNameToReader::iterator pos = fDylibMap.find(installPath);
3383 if ( pos != fDylibMap.end() ) {
3384 return pos->second;
3385 }
3386 else {
3387 // allow -dylib_path option to override indirect library to use
3388 for (std::vector<Options::DylibOverride>::iterator dit = fOptions.dylibOverrides().begin(); dit != fOptions.dylibOverrides().end(); ++dit) {
3389 if ( strcmp(dit->installName,installPath) == 0 ) {\
3390 try {
3391 Options::FileInfo info = fOptions.findFile(dit->useInstead);
3392 ObjectFile::Reader* reader = this->createReader(info);
3393 fDylibMap[strdup(installPath)] = reader;
3394 this->logDylib(reader, true);
3395 return reader;
3396 }
3397 catch (const char* msg) {
3398 warning("ignoring -dylib_file option, %s", msg);
3399 }
3400 }
3401 }
3402 char newPath[MAXPATHLEN];
3403 // handle @loader_path
3404 if ( strncmp(installPath, "@loader_path/", 13) == 0 ) {
3405 strcpy(newPath, fromPath);
3406 char* addPoint = strrchr(newPath,'/');
3407 if ( addPoint != NULL )
3408 strcpy(&addPoint[1], &installPath[13]);
3409 else
3410 strcpy(newPath, &installPath[13]);
3411 installPath = newPath;
3412 }
3413 // note: @executable_path case is handled inside findFileUsingPaths()
3414 // search for dylib using -F and -L paths
3415 Options::FileInfo info = fOptions.findFileUsingPaths(installPath);
3416 try {
3417 ObjectFile::Reader* reader = this->createReader(info);
3418 fDylibMap[strdup(installPath)] = reader;
3419 this->logDylib(reader, true);
3420 return reader;
3421 }
3422 catch (const char* msg) {
3423 throwf("in %s, %s", info.path, msg);
3424 }
3425 }
3426 }
3427
3428
3429 void Linker::processDylibs()
3430 {
3431 fAllDirectDylibsLoaded = true;
3432
3433 // mark all dylibs initially specified as required and check if they can be used
3434 for (InstallNameToReader::iterator it=fDylibMap.begin(); it != fDylibMap.end(); it++) {
3435 it->second->setExplicitlyLinked();
3436 this->checkDylibClientRestrictions(it->second);
3437 }
3438
3439 // keep processing dylibs until no more dylibs are added
3440 unsigned long lastMapSize = 0;
3441 while ( lastMapSize != fDylibMap.size() ) {
3442 lastMapSize = fDylibMap.size();
3443 // can't iterator fDylibMap while modifying it, so use temp buffer
3444 std::vector<ObjectFile::Reader*> currentUnprocessedReaders;
3445 for (InstallNameToReader::iterator it=fDylibMap.begin(); it != fDylibMap.end(); it++) {
3446 if ( fDylibsProcessed.count(it->second) == 0 )
3447 currentUnprocessedReaders.push_back(it->second);
3448 }
3449 for (std::vector<ObjectFile::Reader*>::iterator it=currentUnprocessedReaders.begin(); it != currentUnprocessedReaders.end(); it++) {
3450 fDylibsProcessed.insert(*it);
3451 (*it)->processIndirectLibraries(this);
3452 }
3453 }
3454
3455 // go back over original dylibs and mark sub frameworks as re-exported
3456 if ( fOptions.outputKind() == Options::kDynamicLibrary ) {
3457 const char* myLeaf = strrchr(fOptions.installPath(), '/');
3458 if ( myLeaf != NULL ) {
3459 for (std::vector<class ObjectFile::Reader*>::iterator it=fInputFiles.begin(); it != fInputFiles.end(); it++) {
3460 ObjectFile::Reader* reader = *it;
3461 const char* childParent = reader->parentUmbrella();
3462 if ( childParent != NULL ) {
3463 if ( strcmp(childParent, &myLeaf[1]) == 0 ) {
3464 // set re-export bit of info
3465 std::map<ObjectFile::Reader*,LibraryOptions>::iterator pos = fDylibOptionsMap.find(reader);
3466 if ( pos != fDylibOptionsMap.end() ) {
3467 pos->second.fReExport = true;
3468 }
3469 }
3470 }
3471 }
3472 }
3473 }
3474
3475 }
3476
3477
3478
3479 void Linker::createReaders()
3480 {
3481 fStartCreateReadersTime = mach_absolute_time();
3482 std::vector<Options::FileInfo>& files = fOptions.getInputFiles();
3483 const int count = files.size();
3484 if ( count == 0 )
3485 throw "no object files specified";
3486 // add all direct object, archives, and dylibs
3487 for (int i=0; i < count; ++i) {
3488 Options::FileInfo& entry = files[i];
3489 // ignore /usr/lib/dyld on command line in crt.o build
3490 if ( strcmp(entry.path, "/usr/lib/dyld") != 0 ) {
3491 try {
3492 this->addInputFile(this->createReader(entry), entry);
3493 }
3494 catch (const char* msg) {
3495 if ( (strstr(msg, "architecture") != NULL) && !fOptions.errorOnOtherArchFiles() ) {
3496 if ( fOptions.ignoreOtherArchInputFiles() ) {
3497 // ignore, because this is about an architecture not in use
3498 }
3499 else {
3500 warning("in %s, %s", entry.path, msg);
3501 }
3502 }
3503 else {
3504 throwf("in %s, %s", entry.path, msg);
3505 }
3506 }
3507 }
3508 }
3509
3510 this->processDylibs();
3511 }
3512
3513
3514
3515 ObjectFile::Reader* Linker::addArchive(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen)
3516 {
3517 fNextInputOrdinal += mappedLen;
3518 // remember which readers are archives because they are logged differently
3519 fArchiveReaders.insert(reader);
3520
3521 // update stats
3522 fTotalArchiveSize += mappedLen;
3523 ++fTotalArchivesLoaded;
3524 return reader;
3525 }
3526
3527 ObjectFile::Reader* Linker::addObject(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen)
3528 {
3529 fNextInputOrdinal += mappedLen;
3530 // any .o files that don't have MH_SUBSECTIONS_VIA_SYMBOLS, that means a generated .o file can't
3531 if ( (fOptions.outputKind() == Options::kObjectFile) && !reader->canScatterAtoms() )
3532 fCanScatter = false;
3533
3534 // update stats
3535 fTotalObjectSize += mappedLen;
3536 ++fTotalObjectLoaded;
3537 return reader;
3538 }
3539
3540
3541 void Linker::checkDylibClientRestrictions(ObjectFile::Reader* reader)
3542 {
3543 // Check for any restrictions on who can link with this dylib
3544 const char* readerParentName = reader->parentUmbrella() ;
3545 std::vector<const char*>* clients = reader->getAllowableClients();
3546 if ( (readerParentName != NULL) || (clients != NULL) ) {
3547 // only dylibs that are in an umbrella or have a client list need verification
3548 const char* installName = fOptions.installPath();
3549 const char* installNameLastSlash = strrchr(installName, '/');
3550 bool isParent = false;
3551 bool isSibling = false;
3552 bool isAllowableClient = false;
3553 // There are three cases:
3554 if ( (readerParentName != NULL) && (installNameLastSlash != NULL) ) {
3555 // case 1) The dylib has a parent umbrella, and we are creating the parent umbrella
3556 isParent = ( strcmp(&installNameLastSlash[1], readerParentName) == 0 );
3557
3558 // hack to support umbrella variants that encode the variant name in the install name
3559 // e.g. CoreServices_profile
3560 if ( !isParent ) {
3561 const char* underscore = strchr(&installNameLastSlash[1], '_');
3562 if ( underscore != NULL ) {
3563 isParent = ( strncmp(&installNameLastSlash[1], readerParentName, underscore-installNameLastSlash-1) == 0 );
3564 }
3565 }
3566
3567 // case 2) The dylib has a parent umbrella, and we are creating a sibling with the same parent
3568 isSibling = ( (fOptions.umbrellaName() != NULL) && (strcmp(fOptions.umbrellaName(), readerParentName) == 0) );
3569 }
3570
3571 if ( !isParent && !isSibling && (clients != NULL) ) {
3572 // case 3) the dylib has a list of allowable clients, and we are creating one of them
3573 const char* clientName = fOptions.clientName();
3574 int clientNameLen = 0;
3575 if ( clientName != NULL ) {
3576 // use client name as specified on command line
3577 clientNameLen = strlen(clientName);
3578 }
3579 else {
3580 // infer client name from output path (e.g. xxx/libfoo_variant.A.dylib --> foo, Bar.framework/Bar_variant --> Bar)
3581 clientName = installName;
3582 clientNameLen = strlen(clientName);
3583 // starts after last slash
3584 if ( installNameLastSlash != NULL )
3585 clientName = &installNameLastSlash[1];
3586 if ( strncmp(clientName, "lib", 3) == 0 )
3587 clientName = &clientName[3];
3588 // up to first dot
3589 const char* firstDot = strchr(clientName, '.');
3590 if ( firstDot != NULL )
3591 clientNameLen = firstDot - clientName;
3592 // up to first underscore
3593 const char* firstUnderscore = strchr(clientName, '_');
3594 if ( (firstUnderscore != NULL) && ((firstUnderscore - clientName) < clientNameLen) )
3595 clientNameLen = firstUnderscore - clientName;
3596 }
3597
3598 // Use clientName to check if this dylib is able to link against the allowable clients.
3599 for (std::vector<const char*>::iterator it = clients->begin(); it != clients->end(); it++) {
3600 if ( strncmp(*it, clientName, clientNameLen) == 0 )
3601 isAllowableClient = true;
3602 }
3603 }
3604
3605 if ( !isParent && !isSibling && !isAllowableClient ) {
3606 if ( readerParentName != NULL ) {
3607 throwf("cannot link directly with %s. Link against the umbrella framework '%s.framework' instead.",
3608 reader->getPath(), readerParentName);
3609 }
3610 else {
3611 throwf("cannot link directly with %s", reader->getPath());
3612 }
3613 }
3614 }
3615 }
3616
3617
3618 ObjectFile::Reader* Linker::addDylib(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen)
3619 {
3620 switch ( fOptions.outputKind() ) {
3621 case Options::kDynamicExecutable:
3622 case Options::kDynamicLibrary:
3623 case Options::kDynamicBundle:
3624 break;
3625 case Options::kStaticExecutable:
3626 case Options::kDyld:
3627 case Options::kPreload:
3628 case Options::kObjectFile:
3629 case Options::kKextBundle:
3630 warning("unexpected dylib (%s) on link line", reader->getPath());
3631 break;
3632 }
3633
3634 fNextInputOrdinal += mappedLen;
3635 if ( (reader->getInstallPath() == NULL) && !info.options.fBundleLoader ) {
3636 // this is a "blank" stub
3637 // silently ignore it
3638 return reader;
3639 }
3640 // add to map of loaded dylibs
3641 const char* installPath = reader->getInstallPath();
3642 if ( installPath != NULL ) {
3643 InstallNameToReader::iterator pos = fDylibMap.find(installPath);
3644 if ( pos == fDylibMap.end() ) {
3645 fDylibMap[strdup(installPath)] = reader;
3646 }
3647 else {
3648 InstallNameToReader::iterator pos2 = fDylibMap.find(reader->getPath());
3649 if ( pos2 == fDylibMap.end() )
3650 fDylibMap[strdup(reader->getPath())] = reader;
3651 else
3652 warning("duplicate dylib %s", reader->getPath());
3653 }
3654 }
3655 else if ( info.options.fBundleLoader )
3656 fBundleLoaderReader = reader;
3657
3658 // log direct readers
3659 if ( !fAllDirectDylibsLoaded )
3660 this->logDylib(reader, false);
3661
3662 // update stats
3663 ++fTotalDylibsLoaded;
3664
3665 return reader;
3666 }
3667
3668
3669 void Linker::logTraceInfo (const char* format, ...)
3670 {
3671 static int trace_file = -1;
3672 char trace_buffer[MAXPATHLEN * 2];
3673 char *buffer_ptr;
3674 int length;
3675 ssize_t amount_written;
3676 const char *trace_file_path = fOptions.readerOptions().fTraceOutputFile;
3677
3678 if(trace_file == -1) {
3679 if(trace_file_path != NULL) {
3680 trace_file = open(trace_file_path, O_WRONLY | O_APPEND | O_CREAT, 0666);
3681 if(trace_file == -1)
3682 throwf("Could not open or create trace file: %s", trace_file_path);
3683 }
3684 else {
3685 trace_file = fileno(stderr);
3686 }
3687 }
3688
3689 va_list ap;
3690 va_start(ap, format);
3691 length = vsnprintf(trace_buffer, sizeof(trace_buffer), format, ap);
3692 va_end(ap);
3693 buffer_ptr = trace_buffer;
3694
3695 while(length > 0) {
3696 amount_written = write(trace_file, buffer_ptr, length);
3697 if(amount_written == -1)
3698 /* Failure to write shouldn't fail the build. */
3699 return;
3700 buffer_ptr += amount_written;
3701 length -= amount_written;
3702 }
3703 }
3704
3705
3706
3707 void Linker::createWriter()
3708 {
3709 fStartCreateWriterTime = mach_absolute_time();
3710
3711 // make a vector out of all required dylibs in fDylibMap
3712 std::vector<ExecutableFile::DyLibUsed> dynamicLibraries;
3713 // need to preserve command line order
3714 for (std::vector<class ObjectFile::Reader*>::iterator it=fInputFiles.begin(); it != fInputFiles.end(); it++) {
3715 ObjectFile::Reader* reader = *it;
3716 for (InstallNameToReader::iterator mit=fDylibMap.begin(); mit != fDylibMap.end(); mit++) {
3717 if ( reader == mit->second ) {
3718 ExecutableFile::DyLibUsed dylibInfo;
3719 dylibInfo.reader = reader;
3720 dylibInfo.options = fDylibOptionsMap[reader];
3721 dynamicLibraries.push_back(dylibInfo);
3722 break;
3723 }
3724 }
3725 }
3726 // then add any other dylibs
3727 for (InstallNameToReader::iterator it=fDylibMap.begin(); it != fDylibMap.end(); it++) {
3728 if ( it->second->implicitlyLinked() ) {
3729 // if not already in dynamicLibraries
3730 bool alreadyInDynamicLibraries = false;
3731 for (std::vector<ExecutableFile::DyLibUsed>::iterator dit=dynamicLibraries.begin(); dit != dynamicLibraries.end(); dit++) {
3732 if ( dit->reader == it->second ) {
3733 alreadyInDynamicLibraries = true;
3734 break;
3735 }
3736 }
3737 if ( ! alreadyInDynamicLibraries ) {
3738 ExecutableFile::DyLibUsed dylibInfo;
3739 dylibInfo.reader = it->second;
3740 std::map<ObjectFile::Reader*,LibraryOptions>::iterator pos = fDylibOptionsMap.find(it->second);
3741 if ( pos != fDylibOptionsMap.end() ) {
3742 dylibInfo.options = pos->second;
3743 }
3744 else {
3745 dylibInfo.options.fWeakImport = false; // FIX ME
3746 dylibInfo.options.fReExport = false;
3747 dylibInfo.options.fBundleLoader = false;
3748 }
3749 dynamicLibraries.push_back(dylibInfo);
3750 }
3751 }
3752 }
3753 if ( fBundleLoaderReader != NULL ) {
3754 ExecutableFile::DyLibUsed dylibInfo;
3755 dylibInfo.reader = fBundleLoaderReader;
3756 dylibInfo.options.fWeakImport = false;
3757 dylibInfo.options.fReExport = false;
3758 dylibInfo.options.fBundleLoader = true;
3759 dynamicLibraries.push_back(dylibInfo);
3760 }
3761
3762 const char* path = fOptions.getOutputFilePath();
3763 switch ( fArchitecture ) {
3764 case CPU_TYPE_POWERPC:
3765 this->setOutputFile(new mach_o::executable::Writer<ppc>(path, fOptions, dynamicLibraries));
3766 break;
3767 case CPU_TYPE_POWERPC64:
3768 this->setOutputFile(new mach_o::executable::Writer<ppc64>(path, fOptions, dynamicLibraries));
3769 break;
3770 case CPU_TYPE_I386:
3771 this->setOutputFile(new mach_o::executable::Writer<x86>(path, fOptions, dynamicLibraries));
3772 break;
3773 case CPU_TYPE_X86_64:
3774 this->setOutputFile(new mach_o::executable::Writer<x86_64>(path, fOptions, dynamicLibraries));
3775 break;
3776 case CPU_TYPE_ARM:
3777 this->setOutputFile(new mach_o::executable::Writer<arm>(path, fOptions, dynamicLibraries));
3778 break;
3779 default:
3780 throw "unknown architecture";
3781 }
3782 }
3783
3784
3785 Linker::SymbolTable::SymbolTable(Linker& owner)
3786 : fOwner(owner), fRequireCount(0), fHasExternalTentativeDefinitions(false), fHasExternalWeakDefinitions(false)
3787 {
3788 }
3789
3790 void Linker::SymbolTable::require(const char* name)
3791 {
3792 //fprintf(stderr, "require(%s)\n", name);
3793 Mapper::iterator pos = fTable.find(name);
3794 if ( pos == fTable.end() ) {
3795 fTable[name] = NULL;
3796 ++fRequireCount;
3797 }
3798 }
3799
3800 // convenience labels for 2-dimensional switch statement
3801 enum AllDefinitionCombinations {
3802 kRegAndReg = (ObjectFile::Atom::kRegularDefinition << 3) | ObjectFile::Atom::kRegularDefinition,
3803 kRegAndWeak = (ObjectFile::Atom::kRegularDefinition << 3) | ObjectFile::Atom::kWeakDefinition,
3804 kRegAndTent = (ObjectFile::Atom::kRegularDefinition << 3) | ObjectFile::Atom::kTentativeDefinition,
3805 kRegAndExtern = (ObjectFile::Atom::kRegularDefinition << 3) | ObjectFile::Atom::kExternalDefinition,
3806 kRegAndExternWeak = (ObjectFile::Atom::kRegularDefinition << 3) | ObjectFile::Atom::kExternalWeakDefinition,
3807 kRegAndAbsolute = (ObjectFile::Atom::kRegularDefinition << 3) | ObjectFile::Atom::kAbsoluteSymbol,
3808 kWeakAndReg = (ObjectFile::Atom::kWeakDefinition << 3) | ObjectFile::Atom::kRegularDefinition,
3809 kWeakAndWeak = (ObjectFile::Atom::kWeakDefinition << 3) | ObjectFile::Atom::kWeakDefinition,
3810 kWeakAndTent = (ObjectFile::Atom::kWeakDefinition << 3) | ObjectFile::Atom::kTentativeDefinition,
3811 kWeakAndExtern = (ObjectFile::Atom::kWeakDefinition << 3) | ObjectFile::Atom::kExternalDefinition,
3812 kWeakAndExternWeak = (ObjectFile::Atom::kWeakDefinition << 3) | ObjectFile::Atom::kExternalWeakDefinition,
3813 kWeakAndAbsolute = (ObjectFile::Atom::kWeakDefinition << 3) | ObjectFile::Atom::kAbsoluteSymbol,
3814 kTentAndReg = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kRegularDefinition,
3815 kTentAndWeak = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kWeakDefinition,
3816 kTentAndTent = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kTentativeDefinition,
3817 kTentAndExtern = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kExternalDefinition,
3818 kTentAndExternWeak = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kExternalWeakDefinition,
3819 kTentAndAbsolute = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kAbsoluteSymbol,
3820 kExternAndReg = (ObjectFile::Atom::kExternalDefinition << 3) | ObjectFile::Atom::kRegularDefinition,
3821 kExternAndWeak = (ObjectFile::Atom::kExternalDefinition << 3) | ObjectFile::Atom::kWeakDefinition,
3822 kExternAndTent = (ObjectFile::Atom::kExternalDefinition << 3) | ObjectFile::Atom::kTentativeDefinition,
3823 kExternAndExtern = (ObjectFile::Atom::kExternalDefinition << 3) | ObjectFile::Atom::kExternalDefinition,
3824 kExternAndExternWeak = (ObjectFile::Atom::kExternalDefinition << 3) | ObjectFile::Atom::kExternalWeakDefinition,
3825 kExternAndAbsolute = (ObjectFile::Atom::kExternalDefinition << 3) | ObjectFile::Atom::kAbsoluteSymbol,
3826 kExternWeakAndReg = (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kRegularDefinition,
3827 kExternWeakAndWeak = (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kWeakDefinition,
3828 kExternWeakAndTent = (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kTentativeDefinition,
3829 kExternWeakAndExtern = (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kExternalDefinition,
3830 kExternWeakAndExternWeak= (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kExternalWeakDefinition,
3831 kExternWeakAndAbsolute = (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kAbsoluteSymbol,
3832 kAbsoluteAndReg = (ObjectFile::Atom::kAbsoluteSymbol << 3) | ObjectFile::Atom::kRegularDefinition,
3833 kAbsoluteAndWeak = (ObjectFile::Atom::kAbsoluteSymbol << 3) | ObjectFile::Atom::kWeakDefinition,
3834 kAbsoluteAndTent = (ObjectFile::Atom::kAbsoluteSymbol << 3) | ObjectFile::Atom::kTentativeDefinition,
3835 kAbsoluteAndExtern = (ObjectFile::Atom::kAbsoluteSymbol << 3) | ObjectFile::Atom::kExternalDefinition,
3836 kAbsoluteAndExternWeak = (ObjectFile::Atom::kAbsoluteSymbol << 3) | ObjectFile::Atom::kExternalWeakDefinition,
3837 kAbsoluteAndAbsolute = (ObjectFile::Atom::kAbsoluteSymbol << 3) | ObjectFile::Atom::kAbsoluteSymbol
3838 };
3839
3840 bool Linker::SymbolTable::add(ObjectFile::Atom& newAtom)
3841 {
3842 bool useNew = true;
3843 bool checkVisibilityMismatch = false;
3844 const char* name = newAtom.getName();
3845 //fprintf(stderr, "map.add(%s => %p from %s)\n", name, &newAtom, newAtom.getFile()->getPath());
3846 Mapper::iterator pos = fTable.find(name);
3847 ObjectFile::Atom* existingAtom = NULL;
3848 if ( pos != fTable.end() )
3849 existingAtom = pos->second;
3850 if ( existingAtom != NULL ) {
3851 // already have atom with same name in symbol table
3852 switch ( (AllDefinitionCombinations)((existingAtom->getDefinitionKind() << 3) | newAtom.getDefinitionKind()) ) {
3853 case kRegAndReg:
3854 throwf("duplicate symbol %s in %s and %s", name, newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
3855 case kRegAndWeak:
3856 // ignore new weak atom, because we already have a non-weak one
3857 useNew = false;
3858 break;
3859 case kRegAndTent:
3860 // ignore new tentative atom, because we already have a regular one
3861 useNew = false;
3862 checkVisibilityMismatch = true;
3863 if ( newAtom.getSize() > existingAtom->getSize() ) {
3864 warning("for symbol %s tentative definition of size %llu from %s is "
3865 "is smaller than the real definition of size %llu from %s",
3866 newAtom.getDisplayName(), newAtom.getSize(), newAtom.getFile()->getPath(),
3867 existingAtom->getSize(), existingAtom->getFile()->getPath());
3868 }
3869 break;
3870 case kRegAndExtern:
3871 // ignore external atom, because we already have a one
3872 useNew = false;
3873 break;
3874 case kRegAndExternWeak:
3875 // ignore external atom, because we already have a one
3876 useNew = false;
3877 break;
3878 case kRegAndAbsolute:
3879 throwf("duplicate symbol %s in %s and %s", name, newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
3880 break;
3881 case kWeakAndReg:
3882 // replace existing weak atom with regular one
3883 break;
3884 case kWeakAndWeak:
3885 // have another weak atom, use whichever has largest alignment requirement
3886 // because codegen of some client may require alignment
3887 useNew = ( newAtom.getAlignment().trailingZeros() > existingAtom->getAlignment().trailingZeros() );
3888 checkVisibilityMismatch = true;
3889 break;
3890 case kWeakAndTent:
3891 // replace existing weak atom with tentative one ???
3892 break;
3893 case kWeakAndExtern:
3894 // keep weak atom, at runtime external one may override
3895 useNew = false;
3896 break;
3897 case kWeakAndExternWeak:
3898 // keep weak atom, at runtime external one may override
3899 useNew = false;
3900 break;
3901 case kWeakAndAbsolute:
3902 // replace existing weak atom with absolute one
3903 break;
3904 case kTentAndReg:
3905 // replace existing tentative atom with regular one
3906 checkVisibilityMismatch = true;
3907 if ( newAtom.getSize() < existingAtom->getSize() ) {
3908 warning("for symbol %s tentative definition of size %llu from %s is "
3909 "being replaced by a real definition of size %llu from %s",
3910 newAtom.getDisplayName(), existingAtom->getSize(), existingAtom->getFile()->getPath(),
3911 newAtom.getSize(), newAtom.getFile()->getPath());
3912 }
3913 break;
3914 case kTentAndWeak:
3915 // replace existing tentative atom with weak one ???
3916 break;
3917 case kTentAndTent:
3918 // use largest
3919 checkVisibilityMismatch = true;
3920 if ( newAtom.getSize() < existingAtom->getSize() ) {
3921 useNew = false;
3922 }
3923 else {
3924 if ( newAtom.getAlignment().trailingZeros() < existingAtom->getAlignment().trailingZeros() )
3925 warning("alignment lost in merging tentative definition %s", newAtom.getDisplayName());
3926 }
3927 break;
3928 case kTentAndExtern:
3929 case kTentAndExternWeak:
3930 // a tentative definition and a dylib definition, so commons-mode decides how to handle
3931 switch ( fOwner.fOptions.commonsMode() ) {
3932 case Options::kCommonsIgnoreDylibs:
3933 if ( fOwner.fOptions.warnCommons() )
3934 warning("using common symbol %s from %s and ignoring defintion from dylib %s",
3935 existingAtom->getName(), existingAtom->getFile()->getPath(), newAtom.getFile()->getPath());
3936 useNew = false;
3937 break;
3938 case Options::kCommonsOverriddenByDylibs:
3939 if ( fOwner.fOptions.warnCommons() )
3940 warning("replacing common symbol %s from %s with true definition from dylib %s",
3941 existingAtom->getName(), existingAtom->getFile()->getPath(), newAtom.getFile()->getPath());
3942 break;
3943 case Options::kCommonsConflictsDylibsError:
3944 throwf("common symbol %s from %s conflicts with defintion from dylib %s",
3945 existingAtom->getName(), existingAtom->getFile()->getPath(), newAtom.getFile()->getPath());
3946 }
3947 break;
3948 case kTentAndAbsolute:
3949 // replace tentative with absolute (can't size check because absolutes have no size)
3950 break;
3951 case kExternAndReg:
3952 // replace external atom with regular one
3953 break;
3954 case kExternAndWeak:
3955 // replace external atom with weak one
3956 break;
3957 case kExternAndTent:
3958 // a tentative definition and a dylib definition, so commons-mode decides how to handle
3959 switch ( fOwner.fOptions.commonsMode() ) {
3960 case Options::kCommonsIgnoreDylibs:
3961 if ( fOwner.fOptions.warnCommons() )
3962 warning("using common symbol %s from %s and ignoring defintion from dylib %s",
3963 newAtom.getName(), newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
3964 break;
3965 case Options::kCommonsOverriddenByDylibs:
3966 if ( fOwner.fOptions.warnCommons() )
3967 warning("replacing defintion of %s from dylib %s with common symbol from %s",
3968 newAtom.getName(), existingAtom->getFile()->getPath(), newAtom.getFile()->getPath());
3969 useNew = false;
3970 break;
3971 case Options::kCommonsConflictsDylibsError:
3972 throwf("common symbol %s from %s conflicts with defintion from dylib %s",
3973 newAtom.getName(), newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
3974 }
3975 break;
3976 case kExternAndExtern:
3977 throwf("duplicate symbol %s in %s and %s\n", name, newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
3978 case kExternAndExternWeak:
3979 // keep strong dylib atom, ignore weak one
3980 useNew = false;
3981 break;
3982 case kExternAndAbsolute:
3983 // replace external atom with absolute one
3984 break;
3985 case kExternWeakAndReg:
3986 // replace existing weak external with regular
3987 break;
3988 case kExternWeakAndWeak:
3989 // replace existing weak external with weak (let dyld decide at runtime which to use)
3990 break;
3991 case kExternWeakAndTent:
3992 // a tentative definition and a dylib definition, so commons-mode decides how to handle
3993 switch ( fOwner.fOptions.commonsMode() ) {
3994 case Options::kCommonsIgnoreDylibs:
3995 if ( fOwner.fOptions.warnCommons() )
3996 warning("using common symbol %s from %s and ignoring defintion from dylib %s",
3997 newAtom.getName(), newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
3998 break;
3999 case Options::kCommonsOverriddenByDylibs:
4000 if ( fOwner.fOptions.warnCommons() )
4001 warning("replacing defintion of %s from dylib %s with common symbol from %s",
4002 newAtom.getName(), existingAtom->getFile()->getPath(), newAtom.getFile()->getPath());
4003 useNew = false;
4004 break;
4005 case Options::kCommonsConflictsDylibsError:
4006 throwf("common symbol %s from %s conflicts with defintion from dylib %s",
4007 newAtom.getName(), newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
4008 }
4009 break;
4010 case kExternWeakAndExtern:
4011 // replace existing weak external with external
4012 break;
4013 case kExternWeakAndExternWeak:
4014 // keep existing external weak
4015 useNew = false;
4016 break;
4017 case kExternWeakAndAbsolute:
4018 // replace existing weak external with absolute
4019 break;
4020 case kAbsoluteAndReg:
4021 throwf("duplicate symbol %s in %s and %s", name, newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
4022 case kAbsoluteAndWeak:
4023 // ignore new weak atom, because we already have a non-weak one
4024 useNew = false;
4025 break;
4026 case kAbsoluteAndTent:
4027 // ignore new tentative atom, because we already have a regular one
4028 useNew = false;
4029 break;
4030 case kAbsoluteAndExtern:
4031 // ignore external atom, because we already have a one
4032 useNew = false;
4033 break;
4034 case kAbsoluteAndExternWeak:
4035 // ignore external atom, because we already have a one
4036 useNew = false;
4037 break;
4038 case kAbsoluteAndAbsolute:
4039 throwf("duplicate symbol %s in %s and %s", name, newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
4040 break;
4041 }
4042 }
4043 if ( (existingAtom != NULL) && checkVisibilityMismatch && (newAtom.getScope() != existingAtom->getScope()) ) {
4044 warning("%s has different visibility (%s) in %s and (%s) in %s",
4045 newAtom.getDisplayName(), (newAtom.getScope() == 1 ? "hidden" : "default"), newAtom.getFile()->getPath(), (existingAtom->getScope() == 1 ? "hidden" : "default"), existingAtom->getFile()->getPath());
4046 }
4047 if ( useNew ) {
4048 fTable[name] = &newAtom;
4049 if ( existingAtom != NULL ) {
4050 fOwner.markDead(existingAtom);
4051 if ( fOwner.fInitialLoadsDone ) {
4052 //fprintf(stderr, "existing %p %s overridden by %p\n", existingAtom, existingAtom->getName(), &newAtom);
4053 fOwner.fAtomsOverriddenByLateLoads.insert(existingAtom);
4054 }
4055 }
4056 if ( newAtom.getScope() == ObjectFile::Atom::scopeGlobal ) {
4057 switch ( newAtom.getDefinitionKind() ) {
4058 case ObjectFile::Atom::kTentativeDefinition:
4059 fHasExternalTentativeDefinitions = true;
4060 ++fRequireCount; // added a tentative definition means loadUndefines() needs to continue
4061 break;
4062 case ObjectFile::Atom::kWeakDefinition:
4063 if ( newAtom.getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableIn )
4064 fHasExternalWeakDefinitions = true;
4065 break;
4066 case ObjectFile::Atom::kExternalDefinition:
4067 case ObjectFile::Atom::kExternalWeakDefinition:
4068 ++fDylibSymbolCount;
4069 break;
4070 default:
4071 break;
4072 }
4073 }
4074 }
4075 else {
4076 fOwner.markDead(&newAtom);
4077 }
4078 return useNew;
4079 }
4080
4081
4082
4083 ObjectFile::Atom* Linker::SymbolTable::find(const char* name)
4084 {
4085 Mapper::iterator pos = fTable.find(name);
4086 if ( pos != fTable.end() ) {
4087 return pos->second;
4088 }
4089 return NULL;
4090 }
4091
4092 void Linker::SymbolTable::erase(const char* name) {
4093 fTable.erase(name);
4094 }
4095
4096 void Linker::SymbolTable::getUndefinesNames(std::vector<const char*>& undefines)
4097 {
4098 for (Mapper::iterator it=fTable.begin(); it != fTable.end(); it++) {
4099 if ( it->second == NULL ) {
4100 undefines.push_back(it->first);
4101 }
4102 }
4103 }
4104
4105 void Linker::SymbolTable::getTentativesNames(std::vector<const char*>& tents)
4106 {
4107 for (Mapper::iterator it=fTable.begin(); it != fTable.end(); it++) {
4108 if ( it->second != NULL ) {
4109 if ( (it->second->getDefinitionKind() == ObjectFile::Atom::kTentativeDefinition)
4110 && (it->second->getScope() == ObjectFile::Atom::scopeGlobal) ) {
4111 tents.push_back(it->first);
4112 }
4113 }
4114 }
4115 }
4116
4117
4118
4119 bool Linker::AtomSorter::operator()(const ObjectFile::Atom* left, const ObjectFile::Atom* right)
4120 {
4121 if ( left == right )
4122 return false;
4123
4124 // first sort by section order (which is already sorted by segment)
4125 unsigned int leftSectionIndex = left->getSection()->getIndex();
4126 unsigned int rightSectionIndex = right->getSection()->getIndex();
4127 if ( leftSectionIndex != rightSectionIndex)
4128 return (leftSectionIndex < rightSectionIndex);
4129
4130 // magic section$start symbol always sorts to the start of its section
4131 if ( left->getContentType() == ObjectFile::Atom::kSectionStart )
4132 return true;
4133 if ( right->getContentType() == ObjectFile::Atom::kSectionStart )
4134 return false;
4135
4136 // if a -order_file is specified, then sorting is altered to sort those symbols first
4137 if ( fOverriddenOrdinalMap != NULL ) {
4138 std::map<const ObjectFile::Atom*, uint32_t>::iterator leftPos = fOverriddenOrdinalMap->find(left);
4139 std::map<const ObjectFile::Atom*, uint32_t>::iterator rightPos = fOverriddenOrdinalMap->find(right);
4140 std::map<const ObjectFile::Atom*, uint32_t>::iterator end = fOverriddenOrdinalMap->end();
4141 if ( leftPos != end ) {
4142 if ( rightPos != end ) {
4143 // both left and right are overridden, so compare overridden ordinals
4144 return leftPos->second < rightPos->second;
4145 }
4146 else {
4147 // left is overridden and right is not, so left < right
4148 return true;
4149 }
4150 }
4151 else {
4152 if ( rightPos != end ) {
4153 // right is overridden and left is not, so right < left
4154 return false;
4155 }
4156 else {
4157 // neither are overridden, do default sort
4158 // fall into default sorting below
4159 }
4160 }
4161 }
4162
4163 // magic section$end symbol always sorts to the end of its section
4164 if ( left->getContentType() == ObjectFile::Atom::kSectionEnd )
4165 return false;
4166 if ( right->getContentType() == ObjectFile::Atom::kSectionEnd )
4167 return true;
4168
4169 // the __common section can have real or tentative definitions
4170 // we want the real ones to sort before tentative ones
4171 bool leftIsTent = (left->getDefinitionKind() == ObjectFile::Atom::kTentativeDefinition);
4172 bool rightIsTent = (right->getDefinitionKind() == ObjectFile::Atom::kTentativeDefinition);
4173 if ( leftIsTent != rightIsTent )
4174 return rightIsTent;
4175
4176 // initializers are auto sorted to start of section
4177 if ( !fInitializerSet.empty() ) {
4178 bool leftFirst = (fInitializerSet.count(left) != 0);
4179 bool rightFirst = (fInitializerSet.count(right) != 0);
4180 if ( leftFirst != rightFirst )
4181 return leftFirst;
4182 }
4183
4184 // terminators are auto sorted to end of section
4185 if ( !fTerminatorSet.empty() ) {
4186 bool leftLast = (fTerminatorSet.count(left) != 0);
4187 bool rightLast = (fTerminatorSet.count(right) != 0);
4188 if ( leftLast != rightLast )
4189 return rightLast;
4190 }
4191
4192 // lastly sort by atom ordinal. this is already sorted by .o order
4193 return left->getOrdinal() < right->getOrdinal();
4194 }
4195
4196
4197 int main(int argc, const char* argv[])
4198 {
4199 const char* archName = NULL;
4200 bool showArch = false;
4201 bool archInferred = false;
4202 try {
4203 // create linker object given command line arguments
4204 Linker ld(argc, argv);
4205
4206 // save error message prefix
4207 archName = ld.architectureName();
4208 archInferred = ld.isInferredArchitecture();
4209 showArch = ld.showArchitectureInErrors();
4210
4211 // open all input files
4212 ld.createReaders();
4213
4214 // open output file
4215 ld.createWriter();
4216
4217 // do linking
4218 ld.link();
4219 }
4220 catch (const char* msg) {
4221 if ( archInferred )
4222 fprintf(stderr, "ld: %s for inferred architecture %s\n", msg, archName);
4223 else if ( showArch )
4224 fprintf(stderr, "ld: %s for architecture %s\n", msg, archName);
4225 else
4226 fprintf(stderr, "ld: %s\n", msg);
4227 return 1;
4228 }
4229
4230 return 0;
4231 }