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