]> git.saurik.com Git - apple/ld64.git/blob - src/ld.cpp
ld64-59.3.tar.gz
[apple/ld64.git] / src / ld.cpp
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
12 * file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 #include <stdlib.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <sys/mman.h>
28 #include <sys/sysctl.h>
29 #include <fcntl.h>
30 #include <errno.h>
31 #include <limits.h>
32 #include <unistd.h>
33 #include <mach/mach_time.h>
34 #include <mach/vm_statistics.h>
35 #include <mach/mach_init.h>
36 #include <mach/mach_host.h>
37 #include <mach-o/fat.h>
38
39
40 #include <string>
41 #include <set>
42 #include <string>
43 #include <vector>
44 #include <list>
45 #include <algorithm>
46 #include <ext/hash_map>
47
48 #include "Options.h"
49
50 #include "ObjectFile.h"
51
52 #include "MachOReaderRelocatable.hpp"
53 #include "MachOReaderArchive.hpp"
54 #include "MachOReaderDylib.hpp"
55 #include "MachOWriterExecutable.hpp"
56
57 #include "SectCreate.h"
58
59 #if 0
60 static void dumpAtom(ObjectFile::Atom* atom)
61 {
62 //printf("atom: %p\n", atom);
63
64 // name
65 printf("name: %s\n", atom->getDisplayName());
66
67 // scope
68 switch ( atom->getScope() ) {
69 case ObjectFile::Atom::scopeTranslationUnit:
70 printf("scope: translation unit\n");
71 break;
72 case ObjectFile::Atom::scopeLinkageUnit:
73 printf("scope: linkage unit\n");
74 break;
75 case ObjectFile::Atom::scopeGlobal:
76 printf("scope: global\n");
77 break;
78 default:
79 printf("scope: unknown\n");
80 }
81
82 // kind
83 switch ( atom->getDefinitinonKind() ) {
84 case ObjectFile::Atom::kRegularDefinition:
85 printf("kind: regular\n");
86 break;
87 case ObjectFile::Atom::kWeakDefinition:
88 printf("kind: weak\n");
89 break;
90 case ObjectFile::Atom::kTentativeDefinition:
91 printf("kind: tentative\n");
92 break;
93 case ObjectFile::Atom::kExternalDefinition:
94 printf("kind: import\n");
95 break;
96 case ObjectFile::Atom::kExternalWeakDefinition:
97 printf("kind: weak import\n");
98 break;
99 default:
100 printf("scope: unknown\n");
101 }
102
103 // segment and section
104 printf("section: %s,%s\n", atom->getSegment().getName(), atom->getSectionName());
105
106 // attributes
107 printf("attrs: ");
108 if ( atom->dontDeadStrip() )
109 printf("dont-dead-strip ");
110 if ( atom->isZeroFill() )
111 printf("zero-fill ");
112 printf("\n");
113
114 // size
115 printf("size: 0x%012llX\n", atom->getSize());
116
117 // content
118 uint8_t content[atom->getSize()];
119 atom->copyRawContent(content);
120 printf("content: ");
121 if ( strcmp(atom->getSectionName(), "__cstring") == 0 ) {
122 printf("\"%s\"", content);
123 }
124 else {
125 for (unsigned int i=0; i < sizeof(content); ++i)
126 printf("%02X ", content[i]);
127 }
128 printf("\n");
129
130 // references
131 std::vector<ObjectFile::Reference*>& references = atom->getReferences();
132 const int refCount = references.size();
133 printf("references: (%u)\n", refCount);
134 for (int i=0; i < refCount; ++i) {
135 ObjectFile::Reference* ref = references[i];
136 printf(" %s\n", ref->getDescription());
137 }
138
139 // attributes
140
141 }
142
143 #endif
144
145 class CStringComparor
146 {
147 public:
148 bool operator()(const char* left, const char* right) const { return (strcmp(left, right) < 0); }
149 };
150
151 class CStringEquals
152 {
153 public:
154 bool operator()(const char* left, const char* right) const { return (strcmp(left, right) == 0); }
155 };
156
157 class Section : public ObjectFile::Section
158 {
159 public:
160 static Section* find(const char* sectionName, const char* segmentName, bool zeroFill);
161 static void assignIndexes();
162
163 private:
164 Section(const char* sectionName, const char* segmentName, bool zeroFill);
165
166 struct Sorter {
167 static int segmentOrdinal(const char* segName);
168 bool operator()(Section* left, Section* right);
169 };
170
171 typedef __gnu_cxx::hash_map<const char*, class Section*, __gnu_cxx::hash<const char*>, CStringEquals> NameToSection;
172 //typedef std::map<const char*, class Section*, CStringComparor> NameToSection;
173
174 const char* fSectionName;
175 const char* fSegmentName;
176 bool fZeroFill;
177
178 static NameToSection fgMapping;
179 static std::vector<Section*> fgSections;
180 };
181
182 Section::NameToSection Section::fgMapping;
183 std::vector<Section*> Section::fgSections;
184
185 Section::Section(const char* sectionName, const char* segmentName, bool zeroFill)
186 : fSectionName(sectionName), fSegmentName(segmentName), fZeroFill(zeroFill)
187 {
188 //fprintf(stderr, "new Section(%s, %s)\n", sectionName, segmentName);
189 }
190
191 Section* Section::find(const char* sectionName, const char* segmentName, bool zeroFill)
192 {
193 NameToSection::iterator pos = fgMapping.find(sectionName);
194 if ( pos != fgMapping.end() ) {
195 if ( strcmp(pos->second->fSegmentName, segmentName) == 0 )
196 return pos->second;
197 // otherwise same section name is used in different segments, look slow way
198 for (std::vector<Section*>::iterator it=fgSections.begin(); it != fgSections.end(); it++) {
199 if ( (strcmp((*it)->fSectionName, sectionName) == 0) && (strcmp((*it)->fSegmentName, segmentName) == 0) )
200 return *it;
201 }
202 }
203
204 // does not exist, so make a new one
205 Section* sect = new Section(sectionName, segmentName, zeroFill);
206 sect->fIndex = fgMapping.size();
207 fgMapping[sectionName] = sect;
208 fgSections.push_back(sect);
209
210 if ( (strcmp(sectionName, "__text") == 0) && (strcmp(segmentName, "__TEXT") == 0) ) {
211 // special case __textcoal_nt to be right after __text
212 find("__textcoal_nt", "__TEXT", false);
213 }
214
215 return sect;
216 }
217
218 int Section::Sorter::segmentOrdinal(const char* segName)
219 {
220 if ( strcmp(segName, "__PAGEZERO") == 0 )
221 return 1;
222 if ( strcmp(segName, "__TEXT") == 0 )
223 return 2;
224 if ( strcmp(segName, "__DATA") == 0 )
225 return 3;
226 if ( strcmp(segName, "__OBJC") == 0 )
227 return 4;
228 if ( strcmp(segName, "__LINKEDIT") == 0 )
229 return INT_MAX; // linkedit segment should always sort last
230 else
231 return 5;
232 }
233
234
235 bool Section::Sorter::operator()(Section* left, Section* right)
236 {
237 // Segment is primary sort key
238 const char* leftSegName = left->fSegmentName;
239 const char* rightSegName = right->fSegmentName;
240 int segNameCmp = strcmp(leftSegName, rightSegName);
241 if ( segNameCmp != 0 )
242 {
243 int leftSegOrdinal = segmentOrdinal(leftSegName);
244 int rightSegOrdinal = segmentOrdinal(rightSegName);
245 if ( leftSegOrdinal < rightSegOrdinal )
246 return true;
247 if ( leftSegOrdinal == rightSegOrdinal )
248 return segNameCmp < 0;
249 return false;
250 }
251
252 // zerofill section sort to the end
253 if ( !left->fZeroFill && right->fZeroFill )
254 return true;
255 if ( left->fZeroFill && !right->fZeroFill )
256 return false;
257
258 // section discovery order is last sort key
259 return left->fIndex < right->fIndex;
260 }
261
262 void Section::assignIndexes()
263 {
264 //printf("unsorted:\n");
265 //for (std::vector<Section*>::iterator it=fgSections.begin(); it != fgSections.end(); it++) {
266 // printf("section: name=%s, segment: name=%s, discovery order=%d\n", (*it)->fSectionName, (*it)->fSegmentName, (*it)->fIndex);
267 //}
268
269 // sort it
270 std::sort(fgSections.begin(), fgSections.end(), Section::Sorter());
271
272 // assign correct section ordering to each Section object
273 unsigned int newOrder = 1;
274 for (std::vector<Section*>::iterator it=fgSections.begin(); it != fgSections.end(); it++)
275 (*it)->fIndex = newOrder++;
276
277 //printf("sorted:\n");
278 //for (std::vector<Section*>::iterator it=fgSections.begin(); it != fgSections.end(); it++) {
279 // printf("section: name=%s\n", (*it)->fSectionName);
280 //}
281 }
282
283 class Linker {
284 public:
285 Linker(int argc, const char* argv[]);
286
287 const char* getArchPrefix();
288 const char* architectureName();
289 bool showArchitectureInErrors();
290 bool isInferredArchitecture();
291 void createReaders();
292 void createWriter();
293 void addInputFile(ObjectFile::Reader* reader);
294 void setOutputFile(ExecutableFile::Writer* writer);
295 void link();
296
297
298 private:
299 struct WhyLiveBackChain
300 {
301 WhyLiveBackChain* previous;
302 const char* name;
303 };
304
305 ObjectFile::Reader* createReader(const Options::FileInfo&);
306 void addAtom(ObjectFile::Atom& atom);
307 void addAtoms(std::vector<class ObjectFile::Atom*>& atoms);
308 void buildAtomList();
309 void loadAndResolve();
310 void loadUndefines();
311 void checkUndefines();
312 void addWeakAtomOverrides();
313 void resolveReferences();
314 void deadStripResolve();
315 void addLiveRoot(const char* name);
316 void sortAtoms();
317 void tweakLayout();
318 void writeDotOutput();
319 static bool minimizeStab(ObjectFile::Reader::Stab& stab);
320 static const char* truncateStabString(const char* str);
321 void collectStabs();
322 void writeOutput();
323 ObjectFile::Atom* entryPoint();
324 ObjectFile::Atom* dyldHelper();
325 const char* assureFullPath(const char* path);
326 void markLive(ObjectFile::Atom& atom, Linker::WhyLiveBackChain* previous);
327 void collectStabs(ObjectFile::Reader* reader, std::map<class ObjectFile::Atom*, uint32_t>& atomOrdinals);
328 void synthesizeStabs(ObjectFile::Reader* reader);
329 void printStatistics();
330 void printTime(const char* msg, uint64_t partTime, uint64_t totalTime);
331 char* commatize(uint64_t in, char* out);
332 void getVMInfo(vm_statistics_data_t& info);
333 cpu_type_t inferArchitecture();
334
335 void resolve(ObjectFile::Reference* reference);
336 void resolveFrom(ObjectFile::Reference* reference);
337 void addJustInTimeAtoms(const char* name);
338
339 ObjectFile::Reader* addDylib(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen);
340 ObjectFile::Reader* addObject(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen);
341 ObjectFile::Reader* addArchive(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen);
342 void addIndirectLibraries(ObjectFile::Reader* reader);
343 bool haveIndirectLibrary(const char* path, ObjectFile::Reader* reader);
344 bool haveDirectLibrary(const char* path);
345
346 void logTraceInfo(const char* format, ...);
347
348
349 class SymbolTable
350 {
351 public:
352 SymbolTable(Linker&);
353 void require(const char* name);
354 bool add(ObjectFile::Atom& atom);
355 ObjectFile::Atom* find(const char* name);
356 unsigned int getRequireCount() { return fRequireCount; }
357 void getNeededNames(bool andWeakDefintions, std::vector<const char*>& undefines);
358 private:
359 typedef __gnu_cxx::hash_map<const char*, ObjectFile::Atom*, __gnu_cxx::hash<const char*>, CStringEquals> Mapper;
360 Linker& fOwner;
361 Mapper fTable;
362 unsigned int fRequireCount;
363 };
364
365 struct AtomSorter
366 {
367 bool operator()(ObjectFile::Atom* left, ObjectFile::Atom* right);
368 };
369
370 typedef std::map<const char*, uint32_t, CStringComparor> SectionOrder;
371
372 struct IndirectLibrary {
373 const char* path;
374 uint64_t fileLen;
375 ObjectFile::Reader* reader;
376 std::set<ObjectFile::Reader*> parents;
377 ObjectFile::Reader* reExportedViaDirectLibrary;
378 };
379
380 ObjectFile::Reader* findDirectLibraryWhichReExports(struct IndirectLibrary& indirectLib);
381
382 Options fOptions;
383 SymbolTable fGlobalSymbolTable;
384 unsigned int fWeakSymbolsAddedCount;
385 std::vector<class ObjectFile::Reader*> fInputFiles;
386 ExecutableFile::Writer* fOutputFile;
387 std::vector<ExecutableFile::DyLibUsed> fDynamicLibraries;
388 std::list<IndirectLibrary> fIndirectDynamicLibraries;
389 std::vector<class ObjectFile::Reader*> fReadersThatHaveSuppliedAtoms;
390 std::vector<class ObjectFile::Atom*> fAllAtoms;
391 std::set<class ObjectFile::Atom*> fDeadAtoms;
392 std::set<ObjectFile::Atom*> fLiveAtoms;
393 std::set<ObjectFile::Atom*> fLiveRootAtoms;
394 std::vector<class ObjectFile::Reader::Stab> fStabs;
395 bool fCreateUUID;
396 SectionOrder fSectionOrder;
397 unsigned int fNextSortOrder;
398 unsigned int fNextObjectFileOrder;
399 cpu_type_t fArchitecture;
400 const char* fArchitectureName;
401 bool fArchitectureInferred;
402 bool fDirectLibrariesComplete;
403 uint64_t fOutputFileSize;
404 uint64_t fStartTime;
405 uint64_t fStartCreateReadersTime;
406 uint64_t fStartCreateWriterTime;
407 uint64_t fStartBuildAtomsTime;
408 uint64_t fStartLoadUndefinesTime;
409 uint64_t fStartResolveTime;
410 uint64_t fStartSortTime;
411 uint64_t fStartWriteTime;
412 uint64_t fEndTime;
413 uint64_t fTotalObjectSize;
414 uint64_t fTotalArchiveSize;
415 uint32_t fTotalObjectLoaded;
416 uint32_t fTotalArchivesLoaded;
417 uint32_t fTotalDylibsLoaded;
418 vm_statistics_data_t fStartVMInfo;
419 };
420
421
422 Linker::Linker(int argc, const char* argv[])
423 : fOptions(argc, argv), fGlobalSymbolTable(*this), fOutputFile(NULL), fCreateUUID(false), fNextSortOrder(1),
424 fNextObjectFileOrder(1), fArchitecture(0), fArchitectureInferred(false), fDirectLibrariesComplete(false),
425 fOutputFileSize(0), fTotalObjectSize(0),
426 fTotalArchiveSize(0), fTotalObjectLoaded(0), fTotalArchivesLoaded(0), fTotalDylibsLoaded(0)
427 {
428 fStartTime = mach_absolute_time();
429 if ( fOptions.printStatistics() )
430 getVMInfo(fStartVMInfo);
431
432 fArchitecture = fOptions.architecture();
433 if ( fArchitecture == 0 ) {
434 // -arch not specified, scan .o files to figure out what it should be
435 fArchitecture = inferArchitecture();
436 fArchitectureInferred = true;
437 }
438 switch (fArchitecture) {
439 case CPU_TYPE_POWERPC:
440 fArchitectureName = "ppc";
441 break;
442 case CPU_TYPE_POWERPC64:
443 fArchitectureName = "ppc64";
444 break;
445 case CPU_TYPE_I386:
446 fArchitectureName = "i386";
447 break;
448 case CPU_TYPE_X86_64:
449 fArchitectureName = "x86_64";
450 break;
451 default:
452 fArchitectureName = "unknown architecture";
453 break;
454 }
455 }
456
457 const char* Linker::architectureName()
458 {
459 return fArchitectureName;
460 }
461
462 bool Linker::showArchitectureInErrors()
463 {
464 return fOptions.printArchPrefix();
465 }
466
467 bool Linker::isInferredArchitecture()
468 {
469 return fArchitectureInferred;
470 }
471
472 cpu_type_t Linker::inferArchitecture()
473 {
474 // scan all input files, looking for a thin .o file.
475 // the first one found is presumably the architecture to link
476 uint8_t buffer[sizeof(mach_header_64)];
477 std::vector<Options::FileInfo>& files = fOptions.getInputFiles();
478 for (std::vector<Options::FileInfo>::iterator it = files.begin(); it != files.end(); ++it) {
479 int fd = ::open(it->path, O_RDONLY, 0);
480 if ( fd != -1 ) {
481 ssize_t amount = read(fd, buffer, sizeof(buffer));
482 ::close(fd);
483 if ( amount >= (ssize_t)sizeof(buffer) ) {
484 if ( mach_o::relocatable::Reader<ppc>::validFile(buffer) ) {
485 //fprintf(stderr, "ld64 warning: -arch not used, infering -arch ppc based on %s\n", it->path);
486 return CPU_TYPE_POWERPC;
487 }
488 else if ( mach_o::relocatable::Reader<ppc64>::validFile(buffer) ) {
489 //fprintf(stderr, "ld64 warning: -arch not used, infering -arch ppc64 based on %s\n", it->path);
490 return CPU_TYPE_POWERPC64;
491 }
492 else if ( mach_o::relocatable::Reader<x86>::validFile(buffer) ) {
493 //fprintf(stderr, "ld64 warning: -arch not used, infering -arch i386 based on %s\n", it->path);
494 return CPU_TYPE_I386;
495 }
496 else if ( mach_o::relocatable::Reader<x86_64>::validFile(buffer) ) {
497 //fprintf(stderr, "ld64 warning: -arch not used, infering -arch x86_64 based on %s\n", it->path);
498 return CPU_TYPE_X86_64;
499 }
500 }
501 }
502 }
503
504 // no thin .o files found, so default to same architecture this was built as
505 fprintf(stderr, "ld64 warning: -arch not specified\n");
506 #if __ppc__
507 return CPU_TYPE_POWERPC;
508 #elif __i386__
509 return CPU_TYPE_I386;
510 #elif __ppc64__
511 return CPU_TYPE_POWERPC64;
512 #elif __x86_64__
513 return CPU_TYPE_X86_64;
514 #else
515 #error unknown default architecture
516 #endif
517 }
518
519
520 void Linker::addInputFile(ObjectFile::Reader* reader)
521 {
522 reader->setSortOrder(fNextObjectFileOrder++);
523 fInputFiles.push_back(reader);
524 }
525
526 void Linker::setOutputFile(ExecutableFile::Writer* writer)
527 {
528 fOutputFile = writer;
529 }
530
531 class InSet
532 {
533 public:
534 InSet(std::set<ObjectFile::Atom*>& deadAtoms) : fDeadAtoms(deadAtoms) {}
535
536 bool operator()(ObjectFile::Atom*& atom) const {
537 return ( fDeadAtoms.count(atom) != 0 );
538 }
539
540 private:
541 std::set<ObjectFile::Atom*>& fDeadAtoms;
542 };
543
544 void Linker::loadAndResolve()
545 {
546 if ( fOptions.deadStrip() == Options::kDeadStripOff ) {
547 // without dead-code-stripping:
548 // find atoms to resolve all undefines
549 this->loadUndefines();
550 // verify nothing is missing
551 this->checkUndefines();
552 // once all undefines fulfill, then bind all references
553 this->resolveReferences();
554 // remove atoms weak atoms that have been overridden
555 fAllAtoms.erase(std::remove_if(fAllAtoms.begin(), fAllAtoms.end(), InSet(fDeadAtoms)), fAllAtoms.end());
556 }
557 else {
558 // with dead code stripping:
559 // start binding references from roots,
560 this->deadStripResolve();
561 // verify nothing is missing
562 this->checkUndefines();
563 }
564 }
565
566 void Linker::link()
567 {
568 this->buildAtomList();
569 this->loadAndResolve();
570 this->sortAtoms();
571 this->tweakLayout();
572 this->writeDotOutput();
573 this->collectStabs();
574 this->writeOutput();
575 this->printStatistics();
576
577 if ( fOptions.pauseAtEnd() )
578 sleep(10);
579 }
580
581 void Linker::printTime(const char* msg, uint64_t partTime, uint64_t totalTime)
582 {
583 static uint64_t sUnitsPerSecond = 0;
584 if ( sUnitsPerSecond == 0 ) {
585 struct mach_timebase_info timeBaseInfo;
586 if ( mach_timebase_info(&timeBaseInfo) == KERN_SUCCESS ) {
587 sUnitsPerSecond = 1000000000LL * timeBaseInfo.denom / timeBaseInfo.numer;
588 //fprintf(stderr, "sUnitsPerSecond=%llu\n", sUnitsPerSecond);
589 }
590 }
591 if ( partTime < sUnitsPerSecond ) {
592 uint32_t milliSecondsTimeTen = (partTime*10000)/sUnitsPerSecond;
593 uint32_t milliSeconds = milliSecondsTimeTen/10;
594 uint32_t percentTimesTen = (partTime*1000)/totalTime;
595 uint32_t percent = percentTimesTen/10;
596 fprintf(stderr, "%s: %u.%u milliseconds (%u.%u%%)\n", msg, milliSeconds, milliSecondsTimeTen-milliSeconds*10, percent, percentTimesTen-percent*10);
597 }
598 else {
599 uint32_t secondsTimeTen = (partTime*10)/sUnitsPerSecond;
600 uint32_t seconds = secondsTimeTen/10;
601 uint32_t percentTimesTen = (partTime*1000)/totalTime;
602 uint32_t percent = percentTimesTen/10;
603 fprintf(stderr, "%s: %u.%u seconds (%u.%u%%)\n", msg, seconds, secondsTimeTen-seconds*10, percent, percentTimesTen-percent*10);
604 }
605 }
606
607 char* Linker::commatize(uint64_t in, char* out)
608 {
609 char* result = out;
610 char rawNum[30];
611 sprintf(rawNum, "%llu", in);
612 const int rawNumLen = strlen(rawNum);
613 for(int i=0; i < rawNumLen-1; ++i) {
614 *out++ = rawNum[i];
615 if ( ((rawNumLen-i) % 3) == 1 )
616 *out++ = ',';
617 }
618 *out++ = rawNum[rawNumLen-1];
619 *out = '\0';
620 return result;
621 }
622
623 void Linker::getVMInfo(vm_statistics_data_t& info)
624 {
625 mach_msg_type_number_t count = sizeof(vm_statistics_data_t) / sizeof(natural_t);
626 kern_return_t error = host_statistics(mach_host_self(), HOST_VM_INFO,
627 (host_info_t)&info, &count);
628 if (error != KERN_SUCCESS) {
629 bzero(&info, sizeof(vm_statistics_data_t));
630 }
631 }
632
633 void Linker::printStatistics()
634 {
635 fEndTime = mach_absolute_time();
636 if ( fOptions.printStatistics() ) {
637 vm_statistics_data_t endVMInfo;
638 getVMInfo(endVMInfo);
639
640 uint64_t totalTime = fEndTime - fStartTime;
641 printTime("ld64 total time", totalTime, totalTime);
642 printTime(" option parsing time", fStartCreateReadersTime - fStartTime, totalTime);
643 printTime(" object file processing",fStartCreateWriterTime - fStartCreateReadersTime, totalTime);
644 printTime(" output file setup", fStartBuildAtomsTime - fStartCreateWriterTime, totalTime);
645 printTime(" build atom list", fStartLoadUndefinesTime - fStartBuildAtomsTime, totalTime);
646 printTime(" load undefines", fStartResolveTime - fStartLoadUndefinesTime, totalTime);
647 printTime(" resolve references", fStartSortTime - fStartResolveTime, totalTime);
648 printTime(" sort output", fStartWriteTime - fStartSortTime, totalTime);
649 printTime(" write output", fEndTime - fStartWriteTime, totalTime);
650 fprintf(stderr, "pageins=%u, pageouts=%u, faults=%u\n", endVMInfo.pageins-fStartVMInfo.pageins,
651 endVMInfo.pageouts-fStartVMInfo.pageouts, endVMInfo.faults-fStartVMInfo.faults);
652 char temp[40];
653 fprintf(stderr, "processed %3u object files, totaling %15s bytes\n", fTotalObjectLoaded, commatize(fTotalObjectSize, temp));
654 fprintf(stderr, "processed %3u archive files, totaling %15s bytes\n", fTotalArchivesLoaded, commatize(fTotalArchiveSize, temp));
655 fprintf(stderr, "processed %3u dylib files\n", fTotalDylibsLoaded);
656 fprintf(stderr, "wrote output file totaling %15s bytes\n", commatize(fOutputFileSize, temp));
657 }
658 }
659
660 inline void Linker::addAtom(ObjectFile::Atom& atom)
661 {
662 // add to list of all atoms
663 fAllAtoms.push_back(&atom);
664
665 if ( fOptions.deadStrip() == Options::kDeadStripOff ) {
666 // not dead-stripping code, so add atom's references's names to symbol table as to-be-resolved-later
667 std::vector<class ObjectFile::Reference*>& references = atom.getReferences();
668 for (std::vector<ObjectFile::Reference*>::iterator it=references.begin(); it != references.end(); it++) {
669 ObjectFile::Reference* reference = *it;
670 if ( reference->isTargetUnbound() ) {
671 fGlobalSymbolTable.require(reference->getTargetName());
672 }
673 if ( reference->hasFromTarget() && reference->isFromTargetUnbound() )
674 fGlobalSymbolTable.require(reference->getFromTargetName());
675 }
676 }
677 else {
678 if ( atom.dontDeadStrip() )
679 fLiveRootAtoms.insert(&atom);
680 }
681
682 // if in global namespace, add atom itself to symbol table
683 ObjectFile::Atom::Scope scope = atom.getScope();
684 const char* name = atom.getName();
685 if ( (scope != ObjectFile::Atom::scopeTranslationUnit) && (name != NULL) ) {
686 fGlobalSymbolTable.add(atom);
687
688 // update scope based on export list (possible that globals are downgraded to private_extern)
689 if ( (scope == ObjectFile::Atom::scopeGlobal) && fOptions.hasExportRestrictList() ) {
690 bool doExport = fOptions.shouldExport(name);
691 if ( !doExport ) {
692 atom.setScope(ObjectFile::Atom::scopeLinkageUnit);
693 }
694 }
695 }
696
697 // record section orders so output file can have same order
698 atom.setSection(Section::find(atom.getSectionName(), atom.getSegment().getName(), atom.isZeroFill()));
699
700 // assign order in which this atom was originally seen
701 if ( atom.getSortOrder() == 0 )
702 fNextSortOrder = atom.setSortOrder(fNextSortOrder);
703 }
704
705 inline void Linker::addAtoms(std::vector<class ObjectFile::Atom*>& atoms)
706 {
707 bool first = true; // assume all atoms are from same reader
708 for (std::vector<ObjectFile::Atom*>::iterator it=atoms.begin(); it != atoms.end(); it++) {
709 if ( first ) {
710 // update fReadersThatHaveSuppliedAtoms
711 ObjectFile::Reader* reader = (*it)->getFile();
712 if ( std::find(fReadersThatHaveSuppliedAtoms.begin(), fReadersThatHaveSuppliedAtoms.end(), reader)
713 == fReadersThatHaveSuppliedAtoms.end() ) {
714 fReadersThatHaveSuppliedAtoms.push_back(reader);
715 }
716 }
717 this->addAtom(**it);
718 first = false;
719 }
720 }
721
722 void Linker::buildAtomList()
723 {
724 fStartBuildAtomsTime = mach_absolute_time();
725 // add initial undefines from -u option
726 std::vector<const char*>& initialUndefines = fOptions.initialUndefines();
727 for (std::vector<const char*>::iterator it=initialUndefines.begin(); it != initialUndefines.end(); it++) {
728 fGlobalSymbolTable.require(*it);
729 }
730
731 // writer can contribute atoms
732 this->addAtoms(fOutputFile->getAtoms());
733
734 // each reader contributes atoms
735 const int readerCount = fInputFiles.size();
736 for (int i=0; i < readerCount; ++i) {
737 this->addAtoms(fInputFiles[i]->getAtoms());
738 }
739
740 // extra command line section always at end
741 std::vector<Options::ExtraSection>& extraSections = fOptions.extraSections();
742 for( std::vector<Options::ExtraSection>::iterator it=extraSections.begin(); it != extraSections.end(); ++it) {
743 this->addAtoms(SectCreate::MakeReader(it->segmentName, it->sectionName, it->path, it->data, it->dataLen)->getAtoms());
744 }
745 }
746
747 static const char* pathLeafName(const char* path)
748 {
749 const char* shortPath = strrchr(path, '/');
750 if ( shortPath == NULL )
751 return path;
752 else
753 return &shortPath[1];
754 }
755
756 void Linker::loadUndefines()
757 {
758 fStartLoadUndefinesTime = mach_absolute_time();
759 // keep looping until no more undefines were added in last loop
760 unsigned int undefineCount = 0xFFFFFFFF;
761 while ( undefineCount != fGlobalSymbolTable.getRequireCount() ) {
762 undefineCount = fGlobalSymbolTable.getRequireCount();
763 std::vector<const char*> undefineNames;
764 fGlobalSymbolTable.getNeededNames(false, undefineNames);
765 for(std::vector<const char*>::iterator it = undefineNames.begin(); it != undefineNames.end(); ++it) {
766 const char* name = *it;
767 ObjectFile::Atom* possibleAtom = fGlobalSymbolTable.find(name);
768 if ( (possibleAtom == NULL)
769 || ((possibleAtom->getDefinitionKind()==ObjectFile::Atom::kWeakDefinition) && (fOptions.outputKind() != Options::kObjectFile) && (possibleAtom->getScope() == ObjectFile::Atom::scopeGlobal)) )
770 this->addJustInTimeAtoms(name);
771 }
772 }
773 }
774
775 void Linker::checkUndefines()
776 {
777 if ( fOptions.outputKind() != Options::kObjectFile ) {
778 // error out on any remaining undefines
779 bool doPrint = true;
780 bool doError = true;
781 switch ( fOptions.undefinedTreatment() ) {
782 case Options::kUndefinedError:
783 break;
784 case Options::kUndefinedDynamicLookup:
785 doError = false;
786 break;
787 case Options::kUndefinedWarning:
788 doError = false;
789 break;
790 case Options::kUndefinedSuppress:
791 doError = false;
792 doPrint = false;
793 break;
794 }
795 std::vector<const char*> unresolvableUndefines;
796 fGlobalSymbolTable.getNeededNames(false, unresolvableUndefines);
797 const int unresolvableCount = unresolvableUndefines.size();
798 int unresolvableExportsCount = 0;
799 if ( unresolvableCount != 0 ) {
800 if ( doPrint ) {
801 if ( fOptions.printArchPrefix() )
802 fprintf(stderr, "Undefined symbols for architecture %s:\n", fArchitectureName);
803 else
804 fprintf(stderr, "Undefined symbols:\n");
805 for (int i=0; i < unresolvableCount; ++i) {
806 const char* name = unresolvableUndefines[i];
807 fprintf(stderr, " %s, referenced from:\n", name);
808 // scan all atoms for references
809 bool foundAtomReference = false;
810 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
811 ObjectFile::Atom* atom = *it;
812 std::vector<class ObjectFile::Reference*>& references = atom->getReferences();
813 for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
814 ObjectFile::Reference* reference = *rit;
815 if ( reference->isTargetUnbound() ) {
816 if ( strcmp(reference->getTargetName(), name) == 0 ) {
817 fprintf(stderr, " %s in %s\n", atom->getDisplayName(), pathLeafName(atom->getFile()->getPath()));
818 foundAtomReference = true;
819 }
820 }
821 if ( reference->hasFromTarget() && reference->isFromTargetUnbound() ) {
822 if ( strcmp(reference->getFromTargetName(), name) == 0 ) {
823 fprintf(stderr, " %s in %s\n", atom->getDisplayName(), pathLeafName(atom->getFile()->getPath()));
824 foundAtomReference = true;
825 }
826 }
827 }
828 }
829 // scan command line options
830 if ( !foundAtomReference && fOptions.hasExportRestrictList() && fOptions.shouldExport(name) ) {
831 fprintf(stderr, " -exported_symbols_list command line option\n");
832 ++unresolvableExportsCount;
833 }
834 }
835 }
836 if ( doError && (unresolvableCount > unresolvableExportsCount) ) // last check should be removed. It exists so broken projects still build
837 throw "symbol(s) not found";
838 }
839 }
840 }
841
842
843
844 void Linker::addJustInTimeAtoms(const char* name)
845 {
846 // when creating final linked image, writer gets first chance
847 if ( fOptions.outputKind() != Options::kObjectFile ) {
848 std::vector<class ObjectFile::Atom*>* atoms = fOutputFile->getJustInTimeAtomsFor(name);
849 if ( atoms != NULL ) {
850 this->addAtoms(*atoms);
851 delete atoms;
852 //fprintf(stderr, "addJustInTimeAtoms(%s) => found in file %s\n", name, fOutputFile->getPath() );
853 return; // found a definition, no need to search anymore
854 }
855 }
856
857 // give direct readers a chance
858 for (std::vector<class ObjectFile::Reader*>::iterator it=fInputFiles.begin(); it != fInputFiles.end(); it++) {
859 ObjectFile::Reader* reader = *it;
860 if ( reader != NULL ) {
861 // if this reader is a static archive that has the symbol we need, pull in all atoms in that module
862 // if this reader is a dylib that exports the symbol we need, have it synthesize an atom for us.
863 std::vector<class ObjectFile::Atom*>* atoms = reader->getJustInTimeAtomsFor(name);
864 if ( atoms != NULL ) {
865 this->addAtoms(*atoms);
866 delete atoms;
867 //fprintf(stderr, "addJustInTimeAtoms(%s) => found in file %s\n", name, fInputFiles[i]->getPath() );
868 return; // found a definition, no need to search anymore
869 }
870 }
871 }
872
873 // give indirect readers a chance
874 for (std::list<IndirectLibrary>::iterator it=fIndirectDynamicLibraries.begin(); it != fIndirectDynamicLibraries.end(); it++) {
875 ObjectFile::Reader* reader = it->reader;
876 if ( reader != NULL ) {
877 std::vector<class ObjectFile::Atom*>* atoms = reader->getJustInTimeAtomsFor(name);
878 if ( atoms != NULL ) {
879 this->addAtoms(*atoms);
880 //fprintf(stderr, "addJustInTimeAtoms(%s) => found in file %s\n", name, reader->getPath() );
881 delete atoms;
882 return; // found a definition, no need to search anymore
883 }
884 }
885 }
886
887 // when creating .o file, writer goes last (this is so any static archives will be searched above)
888 if ( (fOptions.outputKind() == Options::kObjectFile) || (fOptions.undefinedTreatment() != Options::kUndefinedError) ) {
889 ObjectFile::Atom* atom = fOutputFile->getUndefinedProxyAtom(name);
890 if ( atom != NULL ) {
891 this->addAtom(*atom);
892 return;
893 }
894 }
895 //fprintf(stderr, "addJustInTimeAtoms(%s) => not found\n", name);
896 }
897
898 void Linker::resolve(ObjectFile::Reference* reference)
899 {
900 // look in global symbol table
901 const char* targetName = reference->getTargetName();
902 ObjectFile::Atom* target = fGlobalSymbolTable.find(targetName);
903 if ( target == NULL ) {
904 fprintf(stderr, "Undefined symbol: %s\n", targetName);
905 }
906 reference->setTarget(*target, reference->getTargetOffset());
907 }
908
909 void Linker::resolveFrom(ObjectFile::Reference* reference)
910 {
911 // handle references that have two (from and to) targets
912 const char* fromTargetName = reference->getFromTargetName();
913 ObjectFile::Atom* fromTarget = fGlobalSymbolTable.find(fromTargetName);
914 if ( fromTarget == NULL ) {
915 fprintf(stderr, "Undefined symbol: %s\n", fromTargetName);
916 }
917 reference->setFromTarget(*fromTarget);
918 }
919
920
921 void Linker::resolveReferences()
922 {
923 fStartResolveTime = mach_absolute_time();
924 // note: the atom list may grow during this loop as libraries supply needed atoms
925 for (unsigned int j=0; j < fAllAtoms.size(); ++j) {
926 ObjectFile::Atom* atom = fAllAtoms[j];
927 std::vector<class ObjectFile::Reference*>& references = atom->getReferences();
928 for (std::vector<ObjectFile::Reference*>::iterator it=references.begin(); it != references.end(); it++) {
929 ObjectFile::Reference* reference = *it;
930 if ( reference->isTargetUnbound() )
931 this->resolve(reference);
932 if ( reference->hasFromTarget() && reference->isFromTargetUnbound() )
933 this->resolveFrom(reference);
934 }
935 }
936 }
937
938
939 // used to remove stabs associated with atoms that won't be in output file
940 class NotInSet
941 {
942 public:
943 NotInSet(std::set<ObjectFile::Atom*>& theSet) : fSet(theSet) {}
944
945 bool operator()(const ObjectFile::Reader::Stab& stab) const {
946 if ( stab.atom == NULL )
947 return false; // leave stabs that are not associated with any atome
948 else
949 return ( fSet.count(stab.atom) == 0 );
950 }
951
952 private:
953 std::set<ObjectFile::Atom*>& fSet;
954 };
955
956
957 class NotLive
958 {
959 public:
960 NotLive(std::set<ObjectFile::Atom*>& set) : fLiveAtoms(set) {}
961
962 bool operator()(ObjectFile::Atom*& atom) const {
963 //if ( fLiveAtoms.count(atom) == 0 )
964 // fprintf(stderr, "dead strip %s\n", atom->getDisplayName());
965 return ( fLiveAtoms.count(atom) == 0 );
966 }
967 private:
968 std::set<ObjectFile::Atom*>& fLiveAtoms;
969 };
970
971
972
973 void Linker::markLive(ObjectFile::Atom& atom, struct Linker::WhyLiveBackChain* previous)
974 {
975 if ( fLiveAtoms.count(&atom) == 0 ) {
976 // if -whylive cares about this symbol, then dump chain
977 if ( (previous->name != NULL) && fOptions.printWhyLive(previous->name) ) {
978 int depth = 0;
979 for(WhyLiveBackChain* p = previous; p != NULL; p = p->previous, ++depth) {
980 for(int i=depth; i > 0; --i)
981 fprintf(stderr, " ");
982 fprintf(stderr, "%s\n", p->name);
983 }
984 }
985 // set up next chain
986 WhyLiveBackChain thisChain;
987 thisChain.previous = previous;
988 // this atom is live
989 fLiveAtoms.insert(&atom);
990 // and all atoms it references
991 std::vector<class ObjectFile::Reference*>& references = atom.getReferences();
992 for (std::vector<ObjectFile::Reference*>::iterator it=references.begin(); it != references.end(); it++) {
993 ObjectFile::Reference* reference = *it;
994 if ( reference->isTargetUnbound() ) {
995 // look in global symbol table
996 const char* targetName = reference->getTargetName();
997 ObjectFile::Atom* target = fGlobalSymbolTable.find(targetName);
998 if ( target == NULL ) {
999 // load archives or dylibs
1000 this->addJustInTimeAtoms(targetName);
1001 }
1002 // look again
1003 target = fGlobalSymbolTable.find(targetName);
1004 if ( target != NULL ) {
1005 reference->setTarget(*target, reference->getTargetOffset());
1006 }
1007 else {
1008 // mark as undefined, for later error processing
1009 fGlobalSymbolTable.require(targetName);
1010 }
1011 }
1012 if ( ! reference->isTargetUnbound() ) {
1013 thisChain.name = reference->getTargetName();
1014 markLive(reference->getTarget(), &thisChain);
1015 }
1016 if ( reference->hasFromTarget() ) {
1017 // do the same as above, for from target
1018 if ( reference->isFromTargetUnbound() ) {
1019 // look in global symbol table
1020 const char* targetName = reference->getFromTargetName();
1021 ObjectFile::Atom* target = fGlobalSymbolTable.find(targetName);
1022 if ( target == NULL ) {
1023 // load archives or dylibs
1024 this->addJustInTimeAtoms(targetName);
1025 }
1026 // look again
1027 target = fGlobalSymbolTable.find(targetName);
1028 if ( target != NULL ) {
1029 reference->setFromTarget(*target);
1030 }
1031 else {
1032 // mark as undefined, for later error processing
1033 fGlobalSymbolTable.require(targetName);
1034 }
1035 }
1036 if ( ! reference->isFromTargetUnbound() ) {
1037 thisChain.name = reference->getFromTargetName();
1038 markLive(reference->getFromTarget(), &thisChain);
1039 }
1040 }
1041 }
1042 }
1043 }
1044
1045
1046 void Linker::addLiveRoot(const char* name)
1047 {
1048 ObjectFile::Atom* target = fGlobalSymbolTable.find(name);
1049 if ( target == NULL ) {
1050 this->addJustInTimeAtoms(name);
1051 target = fGlobalSymbolTable.find(name);
1052 }
1053 if ( target != NULL )
1054 fLiveRootAtoms.insert(target);
1055 }
1056
1057
1058 void Linker::deadStripResolve()
1059 {
1060 // add main() to live roots
1061 ObjectFile::Atom* entryPoint = this->entryPoint();
1062 if ( entryPoint != NULL )
1063 fLiveRootAtoms.insert(entryPoint);
1064
1065 // add dyld_stub_binding_helper() to live roots
1066 ObjectFile::Atom* dyldHelper = this->dyldHelper();
1067 if ( dyldHelper != NULL )
1068 fLiveRootAtoms.insert(dyldHelper);
1069
1070 // add -exported_symbols_list, -init, and -u entries to live roots
1071 std::vector<const char*>& initialUndefines = fOptions.initialUndefines();
1072 for (std::vector<const char*>::iterator it=initialUndefines.begin(); it != initialUndefines.end(); it++)
1073 addLiveRoot(*it);
1074
1075 // in some cases, every global scope atom in initial .o files is a root
1076 if ( fOptions.allGlobalsAreDeadStripRoots() ) {
1077 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
1078 ObjectFile::Atom* atom = *it;
1079 if ( atom->getScope() == ObjectFile::Atom::scopeGlobal )
1080 fLiveRootAtoms.insert(atom);
1081 }
1082 }
1083
1084 // mark all roots as live, and all atoms they reference
1085 for (std::set<ObjectFile::Atom*>::iterator it=fLiveRootAtoms.begin(); it != fLiveRootAtoms.end(); it++) {
1086 WhyLiveBackChain rootChain;
1087 rootChain.previous = NULL;
1088 rootChain.name = (*it)->getDisplayName();
1089 markLive(**it, &rootChain);
1090 }
1091
1092 // now remove all non-live atoms from fAllAtoms
1093 fAllAtoms.erase(std::remove_if(fAllAtoms.begin(), fAllAtoms.end(), NotLive(fLiveAtoms)), fAllAtoms.end());
1094 }
1095
1096 void Linker::sortAtoms()
1097 {
1098 fStartSortTime = mach_absolute_time();
1099 Section::assignIndexes();
1100 std::sort(fAllAtoms.begin(), fAllAtoms.end(), Linker::AtomSorter());
1101 //fprintf(stderr, "Sorted atoms:\n");
1102 //for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
1103 // fprintf(stderr, "\t%s\n", (*it)->getDisplayName());
1104 //}
1105 }
1106
1107
1108
1109 // make sure given addresses are within reach of branches, etc
1110 void Linker::tweakLayout()
1111 {
1112 }
1113
1114
1115 void Linker::writeDotOutput()
1116 {
1117 const char* dotOutFilePath = fOptions.dotOutputFile();
1118 if ( dotOutFilePath != NULL ) {
1119 FILE* out = fopen(dotOutFilePath, "w");
1120 if ( out != NULL ) {
1121 // print header
1122 fprintf(out, "digraph dg\n{\n");
1123 fprintf(out, "\tconcentrate = true;\n");
1124 fprintf(out, "\trankdir = LR;\n");
1125
1126 // print each atom as a node
1127 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
1128 ObjectFile::Atom* atom = *it;
1129 if ( atom->getFile() != fOutputFile ) {
1130 const char* name = atom->getDisplayName();
1131 if ( (atom->getDefinitionKind() == ObjectFile::Atom::kExternalDefinition)
1132 || (atom->getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition) ) {
1133 fprintf(out, "\taddr%p [ shape = plaintext, label = \"%s\" ];\n", atom, name);
1134 }
1135 else if ( strcmp(atom->getSectionName(), "__cstring") == 0 ) {
1136 char cstring[atom->getSize()+2];
1137 atom->copyRawContent((uint8_t*)cstring);
1138 fprintf(out, "\taddr%p [ label = \"string: '", atom);
1139 for (const char* s=cstring; *s != '\0'; ++s) {
1140 if ( *s == '\n' )
1141 fprintf(out, "\\\\n");
1142 else
1143 fputc(*s, out);
1144 }
1145 fprintf(out, "'\" ];\n");
1146 }
1147 else {
1148 fprintf(out, "\taddr%p [ label = \"%s\" ];\n", atom, name);
1149 }
1150 }
1151 }
1152 fprintf(out, "\n");
1153
1154 // print each reference as an edge
1155 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
1156 ObjectFile::Atom* fromAtom = *it;
1157 if ( fromAtom->getFile() != fOutputFile ) {
1158 std::vector<ObjectFile::Reference*>& references = fromAtom->getReferences();
1159 std::set<ObjectFile::Atom*> seenTargets;
1160 for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
1161 ObjectFile::Reference* reference = *rit;
1162 ObjectFile::Atom* toAtom = &(reference->getTarget());
1163 if ( seenTargets.count(toAtom) == 0 ) {
1164 seenTargets.insert(toAtom);
1165 fprintf(out, "\taddr%p -> addr%p;\n", fromAtom, toAtom);
1166 }
1167 }
1168 }
1169 }
1170 fprintf(out, "\n");
1171
1172 // push all imports to bottom of graph
1173 fprintf(out, "{ rank = same; ");
1174 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
1175 ObjectFile::Atom* atom = *it;
1176 if ( atom->getFile() != fOutputFile )
1177 if ( (atom->getDefinitionKind() == ObjectFile::Atom::kExternalDefinition)
1178 || (atom->getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition) ) {
1179 fprintf(out, "addr%p; ", atom);
1180 }
1181 }
1182 fprintf(out, "};\n ");
1183
1184 // print footer
1185 fprintf(out, "}\n");
1186 fclose(out);
1187 }
1188 else {
1189 fprintf(stderr, "ld64 warning: could not write dot output file: %s\n", dotOutFilePath);
1190 }
1191 }
1192 }
1193
1194 ObjectFile::Atom* Linker::entryPoint()
1195 {
1196 // if main executable, find entry point atom
1197 ObjectFile::Atom* entryPoint = NULL;
1198 switch ( fOptions.outputKind() ) {
1199 case Options::kDynamicExecutable:
1200 case Options::kStaticExecutable:
1201 case Options::kDyld:
1202 entryPoint = fGlobalSymbolTable.find(fOptions.entryName());
1203 if ( entryPoint == NULL ) {
1204 throwf("could not find entry point \"%s\" (perhaps missing crt1.o)", fOptions.entryName());
1205 }
1206 break;
1207 case Options::kDynamicLibrary:
1208 if ( fOptions.initFunctionName() != NULL ) {
1209 entryPoint = fGlobalSymbolTable.find(fOptions.initFunctionName());
1210 if ( entryPoint == NULL ) {
1211 throwf("could not find -init function: \"%s\"", fOptions.initFunctionName());
1212 }
1213 }
1214 break;
1215 case Options::kObjectFile:
1216 case Options::kDynamicBundle:
1217 entryPoint = NULL;
1218 break;
1219 }
1220 return entryPoint;
1221 }
1222
1223 ObjectFile::Atom* Linker::dyldHelper()
1224 {
1225 return fGlobalSymbolTable.find("dyld_stub_binding_helper");
1226 }
1227
1228 const char* Linker::assureFullPath(const char* path)
1229 {
1230 if ( path[0] == '/' )
1231 return path;
1232 char cwdbuff[MAXPATHLEN];
1233 if ( getcwd(cwdbuff, MAXPATHLEN) != NULL ) {
1234 char* result;
1235 asprintf(&result, "%s/%s", cwdbuff, path);
1236 if ( result != NULL )
1237 return result;
1238 }
1239 return path;
1240 }
1241
1242
1243 //
1244 // The stab strings are of the form:
1245 // <name> ':' <type-code> <number-pari>
1246 // but the <name> contain a colon.
1247 // For C++ <name> may contain a double colon (e.g. std::string:f(0,1) )
1248 // For Objective-C name may contain a colon instead square bracket (e.g. [Foo doit:]:f(0,1) )
1249 //
1250 const char* Linker::truncateStabString(const char* str)
1251 {
1252 enum { start, inObjc } state = start;
1253 for (const char* s = str; *s != 0; ++s) {
1254 char c = *s;
1255 switch (state) {
1256 case start:
1257 if ( c == '[' ) {
1258 state = inObjc;
1259 }
1260 else {
1261 if ( c == ':' ) {
1262 if ( s[1] == ':' ) {
1263 ++s;
1264 }
1265 else {
1266 // found colon
1267 // Duplicate strndup behavior here.
1268 int trunStrLen = s-str+2;
1269 char* temp = new char[trunStrLen+1];
1270 memcpy(temp, str, trunStrLen);
1271 temp[trunStrLen] = '\0';
1272 return temp;
1273 }
1274 }
1275 }
1276 break;
1277 case inObjc:
1278 if ( c == ']' ) {
1279 state = start;
1280 }
1281 break;
1282 }
1283 }
1284 // malformed
1285 return str;
1286 }
1287
1288
1289 bool Linker::minimizeStab(ObjectFile::Reader::Stab& stab)
1290 {
1291 switch(stab.type){
1292 case N_GSYM:
1293 case N_STSYM:
1294 case N_LCSYM:
1295 case N_FUN:
1296 // these all need truncated strings
1297 stab.string = truncateStabString(stab.string);
1298 return true;
1299 case N_SO:
1300 case N_OSO:
1301 case N_OPT:
1302 case N_SOL:
1303 // these are included in the minimal stabs, but they keep their full string
1304 return true;
1305 default:
1306 return false;
1307 }
1308 }
1309
1310
1311 struct HeaderRange {
1312 std::vector<ObjectFile::Reader::Stab>::iterator begin;
1313 std::vector<ObjectFile::Reader::Stab>::iterator end;
1314 int parentRangeIndex;
1315 uint32_t sum;
1316 bool sumPrecomputed;
1317 bool useEXCL;
1318 bool cannotEXCL; // because of SLINE, etc stabs
1319 };
1320
1321
1322 typedef __gnu_cxx::hash_map<const char*, std::vector<uint32_t>, __gnu_cxx::hash<const char*>, CStringEquals> PathToSums;
1323
1324 // hash table that maps header path to a vector of known checksums for that path
1325 static PathToSums sKnownBINCLs;
1326
1327
1328 void Linker::collectStabs(ObjectFile::Reader* reader, std::map<class ObjectFile::Atom*, uint32_t>& atomOrdinals)
1329 {
1330 bool log = false;
1331 bool minimal = ( fOptions.readerOptions().fDebugInfoStripping == ObjectFile::ReaderOptions::kDebugInfoMinimal );
1332 std::vector<class ObjectFile::Reader::Stab>* readerStabs = reader->getStabs();
1333 if ( readerStabs == NULL )
1334 return;
1335
1336 if ( log ) fprintf(stderr, "processesing %lu stabs for %s\n", readerStabs->size(), reader->getPath());
1337 std::vector<HeaderRange> ranges;
1338 int curRangeIndex = -1;
1339 int count = 0;
1340 ObjectFile::Atom* atomWithLowestOrdinal = NULL;
1341 ObjectFile::Atom* atomWithHighestOrdinal = NULL;
1342 uint32_t highestOrdinal = 0;
1343 uint32_t lowestOrdinal = UINT_MAX;
1344 std::vector<std::pair<ObjectFile::Atom*,ObjectFile::Atom*> > soRanges;
1345 // 1) find all (possibly nested) BINCL/EINCL ranges and their checksums
1346 // 2) find all SO/SO ranges and the first/last atom own by a FUN stab therein
1347 for(std::vector<class ObjectFile::Reader::Stab>::iterator it=readerStabs->begin(); it != readerStabs->end(); ++it) {
1348 ++count;
1349 switch ( it->type ) {
1350 case N_BINCL:
1351 {
1352 HeaderRange range;
1353 range.begin = it;
1354 range.end = readerStabs->end();
1355 range.parentRangeIndex = curRangeIndex;
1356 range.sum = it->value;
1357 range.sumPrecomputed = (range.sum != 0);
1358 range.useEXCL = false;
1359 range.cannotEXCL = false;
1360 curRangeIndex = ranges.size();
1361 if ( log ) fprintf(stderr, "[%d]BINCL %s\n", curRangeIndex, it->string);
1362 ranges.push_back(range);
1363 }
1364 break;
1365 case N_EINCL:
1366 if ( curRangeIndex == -1 ) {
1367 fprintf(stderr, "ld64 warning: EINCL missing BINCL in %s\n", reader->getPath());
1368 }
1369 else {
1370 ranges[curRangeIndex].end = it+1;
1371 if ( log ) fprintf(stderr, "[%d->%d]EINCL %s\n", curRangeIndex, ranges[curRangeIndex].parentRangeIndex, it->string);
1372 curRangeIndex = ranges[curRangeIndex].parentRangeIndex;
1373 }
1374 break;
1375 case N_FUN:
1376 {
1377 std::map<class ObjectFile::Atom*, uint32_t>::iterator pos = atomOrdinals.find(it->atom);
1378 if ( pos != atomOrdinals.end() ) {
1379 uint32_t ordinal = pos->second;
1380 if ( ordinal > highestOrdinal ) {
1381 highestOrdinal = ordinal;
1382 atomWithHighestOrdinal = it->atom;
1383 }
1384 if ( ordinal < lowestOrdinal ) {
1385 lowestOrdinal = ordinal;
1386 atomWithLowestOrdinal = it->atom;
1387 }
1388 }
1389 }
1390 // fall through
1391 case N_BNSYM:
1392 case N_ENSYM:
1393 case N_LBRAC:
1394 case N_RBRAC:
1395 case N_SLINE:
1396 case N_STSYM:
1397 case N_LCSYM:
1398 if ( curRangeIndex != -1 ) {
1399 ranges[curRangeIndex].cannotEXCL = true;
1400 if ( fOptions.warnStabs() )
1401 fprintf(stderr, "ld64: cannot do BINCL/EINCL optimzation because of stabs kinds in %s for %s\n", ranges[curRangeIndex].begin->string, reader->getPath());
1402 }
1403 break;
1404 case N_SO:
1405 if ( (it->string != NULL) && (strlen(it->string) > 0) ) {
1406 // start SO, reset hi/low FUN tracking
1407 atomWithLowestOrdinal = NULL;
1408 atomWithHighestOrdinal = NULL;
1409 highestOrdinal = 0;
1410 lowestOrdinal = UINT_MAX;
1411 }
1412 else {
1413 // end SO, record hi/low atoms for this SO range
1414 soRanges.push_back(std::make_pair<ObjectFile::Atom*,ObjectFile::Atom*>(atomWithLowestOrdinal, atomWithHighestOrdinal));
1415 }
1416 // fall through
1417 default:
1418 if ( curRangeIndex != -1 ) {
1419 if ( ! ranges[curRangeIndex].sumPrecomputed ) {
1420 uint32_t sum = 0;
1421 const char* s = it->string;
1422 char c;
1423 while ( (c = *s++) != 0 ) {
1424 sum += c;
1425 // don't checkusm first number (file index) after open paren in string
1426 if ( c == '(' ) {
1427 while(isdigit(*s))
1428 ++s;
1429 }
1430 }
1431 ranges[curRangeIndex].sum += sum;
1432 }
1433 }
1434
1435 }
1436 }
1437 if ( log ) fprintf(stderr, "processesed %d stabs for %s\n", count, reader->getPath());
1438 if ( curRangeIndex != -1 )
1439 fprintf(stderr, "ld64 warning: BINCL (%s) missing EINCL in %s\n", ranges[curRangeIndex].begin->string, reader->getPath());
1440
1441 // if no BINCLs
1442 if ( ranges.size() == 0 ) {
1443 int soIndex = 0;
1444 for(std::vector<ObjectFile::Reader::Stab>::iterator it=readerStabs->begin(); it != readerStabs->end(); ++it) {
1445 // copy minimal or all stabs
1446 ObjectFile::Reader::Stab stab = *it;
1447 if ( !minimal || minimizeStab(stab) ) {
1448 if ( stab.type == N_SO ) {
1449 if ( (stab.string != NULL) && (strlen(stab.string) > 0) ) {
1450 // starting SO is associated with first atom
1451 stab.atom = soRanges[soIndex].first;
1452 }
1453 else {
1454 // ending SO is associated with last atom
1455 stab.atom = soRanges[soIndex].second;
1456 ++soIndex;
1457 }
1458 }
1459 fStabs.push_back(stab);
1460 }
1461 }
1462 return;
1463 }
1464
1465 //fprintf(stderr, "BINCL/EINCL info for %s\n", reader->getPath());
1466 //for(std::vector<HeaderRange>::iterator it=ranges.begin(); it != ranges.end(); ++it) {
1467 // fprintf(stderr, "%08X %s\n", it->sum, it->begin->string);
1468 //}
1469
1470 // see if any of these BINCL/EINCL ranges have already been seen and therefore can be replaced with EXCL
1471 for(std::vector<HeaderRange>::iterator it=ranges.begin(); it != ranges.end(); ++it) {
1472 if ( ! it->cannotEXCL ) {
1473 const char* header = it->begin->string;
1474 uint32_t sum = it->sum;
1475 PathToSums::iterator pos = sKnownBINCLs.find(header);
1476 if ( pos != sKnownBINCLs.end() ) {
1477 std::vector<uint32_t>& sums = pos->second;
1478 for(std::vector<uint32_t>::iterator sit=sums.begin(); sit != sums.end(); ++sit) {
1479 if (*sit == sum) {
1480 //fprintf(stderr, "use EXCL for %s in %s\n", header, reader->getPath());
1481 it->useEXCL = true;
1482 break;
1483 }
1484 }
1485 if ( ! it->useEXCL ) {
1486 // have seen this path, but not this checksum
1487 //fprintf(stderr, "registering another checksum %08X for %s\n", sum, header);
1488 sums.push_back(sum);
1489 }
1490 }
1491 else {
1492 // have not seen this path, so add to known BINCLs
1493 std::vector<uint32_t> empty;
1494 sKnownBINCLs[header] = empty;
1495 sKnownBINCLs[header].push_back(sum);
1496 //fprintf(stderr, "registering checksum %08X for %s\n", sum, header);
1497 }
1498 }
1499 }
1500
1501 // add a new set of stabs with BINCL/EINCL runs that have been seen before, replaced with EXCLs
1502 curRangeIndex = -1;
1503 const int maxRangeIndex = ranges.size();
1504 int soIndex = 0;
1505 for(std::vector<ObjectFile::Reader::Stab>::iterator it=readerStabs->begin(); it != readerStabs->end(); ++it) {
1506 switch ( it->type ) {
1507 case N_BINCL:
1508 for(int i=curRangeIndex+1; i < maxRangeIndex; ++i) {
1509 if ( ranges[i].begin == it ) {
1510 curRangeIndex = i;
1511 HeaderRange& range = ranges[curRangeIndex];
1512 ObjectFile::Reader::Stab stab = *it;
1513 stab.value = range.sum; // BINCL and EXCL have n_value set to checksum
1514 if ( range.useEXCL )
1515 stab.type = N_EXCL; // transform BINCL into EXCL
1516 if ( !minimal )
1517 fStabs.push_back(stab);
1518 break;
1519 }
1520 }
1521 break;
1522 case N_EINCL:
1523 if ( curRangeIndex != -1 ) {
1524 if ( !ranges[curRangeIndex].useEXCL && !minimal )
1525 fStabs.push_back(*it);
1526 curRangeIndex = ranges[curRangeIndex].parentRangeIndex;
1527 }
1528 break;
1529 default:
1530 if ( (curRangeIndex == -1) || !ranges[curRangeIndex].useEXCL ) {
1531 ObjectFile::Reader::Stab stab = *it;
1532 if ( !minimal || minimizeStab(stab) ) {
1533 if ( stab.type == N_SO ) {
1534 if ( (stab.string != NULL) || (strlen(stab.string) > 0) ) {
1535 // starting SO is associated with first atom
1536 stab.atom = soRanges[soIndex].first;
1537 }
1538 else {
1539 // ending SO is associated with last atom
1540 stab.atom = soRanges[soIndex].second;
1541 ++soIndex;
1542 }
1543 }
1544 fStabs.push_back(stab);
1545 }
1546 }
1547 }
1548 }
1549
1550 }
1551
1552
1553 void Linker::synthesizeStabs(ObjectFile::Reader* reader)
1554 {
1555 // synthesize "debug notes" and add them to master stabs vector
1556 const char* dirPath = NULL;
1557 const char* filename = NULL;
1558 bool wroteStartSO = false;
1559 std::vector<const char*> seenFiles;
1560 for (std::vector<class ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); ++it) {
1561 ObjectFile::Atom* atom = *it;
1562 if ( atom->getFile() == reader ) {
1563 const char* name = atom->getName();
1564 if ( (name != NULL) && (atom->getSymbolTableInclusion() != ObjectFile::Atom::kSymbolTableNotIn) ) {
1565 const char* newDirPath;
1566 const char* newFilename;
1567 if ( atom->getTranslationUnitSource(&newDirPath, &newFilename) ) {
1568 // gdb like directory SO's to end in '/', but dwarf DW_AT_comp_dir usually does not have trailing '/'
1569 if ( (newDirPath != NULL) && (strlen(newDirPath) > 1 ) && (newDirPath[strlen(newDirPath)-1] != '/') )
1570 asprintf((char**)&newDirPath, "%s/", newDirPath);
1571 // need SO's whenever the translation unit source file changes
1572 if ( newFilename != filename ) {
1573 if ( filename != NULL ) {
1574 // translation unit change, emit ending SO
1575 ObjectFile::Reader::Stab endFileStab;
1576 endFileStab.atom = NULL;
1577 endFileStab.type = N_SO;
1578 endFileStab.other = 1;
1579 endFileStab.desc = 0;
1580 endFileStab.value = 0;
1581 endFileStab.string = "";
1582 fStabs.push_back(endFileStab);
1583 }
1584 // new translation unit, emit start SO's
1585 ObjectFile::Reader::Stab dirPathStab;
1586 dirPathStab.atom = NULL;
1587 dirPathStab.type = N_SO;
1588 dirPathStab.other = 0;
1589 dirPathStab.desc = 0;
1590 dirPathStab.value = 0;
1591 dirPathStab.string = newDirPath;
1592 fStabs.push_back(dirPathStab);
1593 ObjectFile::Reader::Stab fileStab;
1594 fileStab.atom = NULL;
1595 fileStab.type = N_SO;
1596 fileStab.other = 0;
1597 fileStab.desc = 0;
1598 fileStab.value = 0;
1599 fileStab.string = newFilename;
1600 fStabs.push_back(fileStab);
1601 // Synthesize OSO for start of file
1602 ObjectFile::Reader::Stab objStab;
1603 objStab.atom = NULL;
1604 objStab.type = N_OSO;
1605 objStab.other = 0;
1606 objStab.desc = 1;
1607 objStab.value = reader->getModificationTime();
1608 objStab.string = assureFullPath(reader->getPath());
1609 fStabs.push_back(objStab);
1610 wroteStartSO = true;
1611 }
1612 filename = newFilename;
1613 dirPath = newDirPath;
1614 seenFiles.push_back(filename);
1615 if ( atom->getSegment().isContentExecutable() && (strncmp(atom->getSectionName(), "__text", 6) == 0) ) {
1616 // Synthesize BNSYM and start FUN stabs
1617 ObjectFile::Reader::Stab beginSym;
1618 beginSym.atom = atom;
1619 beginSym.type = N_BNSYM;
1620 beginSym.other = 1;
1621 beginSym.desc = 0;
1622 beginSym.value = 0;
1623 beginSym.string = "";
1624 fStabs.push_back(beginSym);
1625 ObjectFile::Reader::Stab startFun;
1626 startFun.atom = atom;
1627 startFun.type = N_FUN;
1628 startFun.other = 1;
1629 startFun.desc = 0;
1630 startFun.value = 0;
1631 startFun.string = name;
1632 fStabs.push_back(startFun);
1633 // Synthesize any SOL stabs needed
1634 std::vector<ObjectFile::LineInfo>* lineInfo = atom->getLineInfo();
1635 if ( lineInfo != NULL ) {
1636 // might be nice to set the source file path to seenFiles so it does not show up in SOLs
1637 const char* curFile = NULL;
1638 for (std::vector<ObjectFile::LineInfo>::iterator it = lineInfo->begin(); it != lineInfo->end(); ++it) {
1639 if ( it->fileName != curFile ) {
1640 bool alreadySeen = false;
1641 for (std::vector<const char*>::iterator sit = seenFiles.begin(); sit != seenFiles.end(); ++sit) {
1642 if ( strcmp(it->fileName, *sit) == 0 ) {
1643 alreadySeen = true;
1644 break;
1645 }
1646 }
1647 if ( ! alreadySeen ) {
1648 seenFiles.push_back(it->fileName);
1649 ObjectFile::Reader::Stab sol;
1650 sol.atom = 0;
1651 sol.type = N_SOL;
1652 sol.other = 0;
1653 sol.desc = 0;
1654 sol.value = 0;
1655 sol.string = it->fileName;
1656 fStabs.push_back(sol);
1657 }
1658 curFile = it->fileName;
1659 }
1660 }
1661 }
1662 // Synthesize end FUN and ENSYM stabs
1663 ObjectFile::Reader::Stab endFun;
1664 endFun.atom = atom;
1665 endFun.type = N_FUN;
1666 endFun.other = 0;
1667 endFun.desc = 0;
1668 endFun.value = 0;
1669 endFun.string = "";
1670 fStabs.push_back(endFun);
1671 ObjectFile::Reader::Stab endSym;
1672 endSym.atom = atom;
1673 endSym.type = N_ENSYM;
1674 endSym.other = 1;
1675 endSym.desc = 0;
1676 endSym.value = 0;
1677 endSym.string = "";
1678 fStabs.push_back(endSym);
1679 }
1680 else {
1681 ObjectFile::Reader::Stab globalsStab;
1682 if ( atom->getScope() == ObjectFile::Atom::scopeTranslationUnit ) {
1683 // Synthesize STSYM stab for statics
1684 const char* name = atom->getName();
1685 if ( name[0] == '_' ) {
1686 globalsStab.atom = atom;
1687 globalsStab.type = N_STSYM;
1688 globalsStab.other = 1;
1689 globalsStab.desc = 0;
1690 globalsStab.value = 0;
1691 globalsStab.string = name;
1692 fStabs.push_back(globalsStab);
1693 }
1694 }
1695 else {
1696 // Synthesize GSYM stab for other globals (but not .eh exception frame symbols)
1697 const char* name = atom->getName();
1698 if ( (name[0] == '_') && (strcmp(atom->getSectionName(), "__eh_frame") != 0) ) {
1699 globalsStab.atom = atom;
1700 globalsStab.type = N_GSYM;
1701 globalsStab.other = 1;
1702 globalsStab.desc = 0;
1703 globalsStab.value = 0;
1704 globalsStab.string = name;
1705 fStabs.push_back(globalsStab);
1706 }
1707 }
1708 }
1709 }
1710 }
1711 }
1712 }
1713 if ( wroteStartSO ) {
1714 // emit ending SO
1715 ObjectFile::Reader::Stab endFileStab;
1716 endFileStab.atom = NULL;
1717 endFileStab.type = N_SO;
1718 endFileStab.other = 1;
1719 endFileStab.desc = 0;
1720 endFileStab.value = 0;
1721 endFileStab.string = "";
1722 fStabs.push_back(endFileStab);
1723 }
1724 }
1725
1726 void Linker::collectStabs()
1727 {
1728 if ( fOptions.readerOptions().fDebugInfoStripping != ObjectFile::ReaderOptions::kDebugInfoNone ) {
1729
1730 // make mapping from atoms to ordinal
1731 std::map<class ObjectFile::Atom*, uint32_t> atomOrdinals;
1732 uint32_t ordinal = 1;
1733 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms.begin(); it != fAllAtoms.end(); it++) {
1734 atomOrdinals[*it] = ordinal++;
1735 }
1736
1737 fStabs.reserve(1024); // try to minimize re-allocations
1738 // get stabs from each reader, in command line order
1739 for (std::vector<class ObjectFile::Reader*>::iterator it=fReadersThatHaveSuppliedAtoms.begin();
1740 it != fReadersThatHaveSuppliedAtoms.end();
1741 it++) {
1742 ObjectFile::Reader* reader = *it;
1743 if ( reader != NULL ) {
1744 switch ( reader->getDebugInfoKind() ) {
1745 case ObjectFile::Reader::kDebugInfoNone:
1746 // do nothing
1747 break;
1748 case ObjectFile::Reader::kDebugInfoStabs:
1749 collectStabs(reader, atomOrdinals);
1750 break;
1751 case ObjectFile::Reader::kDebugInfoDwarf:
1752 synthesizeStabs(reader);
1753 fCreateUUID = true;
1754 break;
1755 case ObjectFile::Reader::kDebugInfoStabsUUID:
1756 collectStabs(reader, atomOrdinals);
1757 fCreateUUID = true;
1758 break;
1759 default:
1760 throw "Unhandled type of debug information";
1761 }
1762 }
1763 }
1764 // remove stabs associated with atoms that won't be in output
1765 std::set<class ObjectFile::Atom*> allAtomsSet;
1766 allAtomsSet.insert(fAllAtoms.begin(), fAllAtoms.end());
1767 fStabs.erase(std::remove_if(fStabs.begin(), fStabs.end(), NotInSet(allAtomsSet)), fStabs.end());
1768 }
1769 }
1770
1771 void Linker::writeOutput()
1772 {
1773 fStartWriteTime = mach_absolute_time();
1774 // tell writer about each segment's atoms
1775 fOutputFileSize = fOutputFile->write(fAllAtoms, fStabs, this->entryPoint(), this->dyldHelper(), (fCreateUUID && fOptions.emitUUID()));
1776 }
1777
1778 ObjectFile::Reader* Linker::createReader(const Options::FileInfo& info)
1779 {
1780 // map in whole file
1781 uint64_t len = info.fileLen;
1782 int fd = ::open(info.path, O_RDONLY, 0);
1783 if ( fd == -1 )
1784 throwf("can't open file, errno=%d", errno);
1785 if ( info.fileLen < 20 )
1786 throw "file too small";
1787
1788 uint8_t* p = (uint8_t*)::mmap(NULL, info.fileLen, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
1789 if ( p == (uint8_t*)(-1) )
1790 throwf("can't map file, errno=%d", errno);
1791
1792 // if fat file, skip to architecture we want
1793 const fat_header* fh = (fat_header*)p;
1794 if ( fh->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) {
1795 // Fat header is always big-endian
1796 const struct fat_arch* archs = (struct fat_arch*)(p + sizeof(struct fat_header));
1797 for (unsigned long i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) {
1798 if ( OSSwapBigToHostInt32(archs[i].cputype) == (uint32_t)fArchitecture ) {
1799 uint32_t fileOffset = OSSwapBigToHostInt32(archs[i].offset);
1800 len = OSSwapBigToHostInt32(archs[i].size);
1801 // if requested architecture is page aligned within fat file, then remap just that portion of file
1802 if ( (fileOffset && 0x00000FFF) == 0 ) {
1803 // unmap whole file
1804 munmap((caddr_t)p, info.fileLen);
1805 // re-map just part we need
1806 p = (uint8_t*)::mmap(NULL, len, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, fileOffset);
1807 if ( p == (uint8_t*)(-1) )
1808 throwf("can't re-map file, errno=%d", errno);
1809 }
1810 else {
1811 p = &p[fileOffset];
1812 }
1813 break;
1814 }
1815 }
1816 }
1817 ::close(fd);
1818
1819 switch (fArchitecture) {
1820 case CPU_TYPE_POWERPC:
1821 if ( mach_o::relocatable::Reader<ppc>::validFile(p) )
1822 return this->addObject(mach_o::relocatable::Reader<ppc>::make(p, info.path, info.modTime, fOptions.readerOptions()), info, len);
1823 else if ( mach_o::dylib::Reader<ppc>::validFile(p, info.options.fBundleLoader) )
1824 return this->addDylib(mach_o::dylib::Reader<ppc>::make(p, len, info.path, info.options.fBundleLoader, fOptions.readerOptions()), info, len);
1825 else if ( mach_o::archive::Reader<ppc>::validFile(p, len) )
1826 return this->addArchive(mach_o::archive::Reader<ppc>::make(p, len, info.path, info.modTime, fOptions.readerOptions()), info, len);
1827 break;
1828 case CPU_TYPE_POWERPC64:
1829 if ( mach_o::relocatable::Reader<ppc64>::validFile(p) )
1830 return this->addObject(mach_o::relocatable::Reader<ppc64>::make(p, info.path, info.modTime, fOptions.readerOptions()), info, len);
1831 else if ( mach_o::dylib::Reader<ppc64>::validFile(p, info.options.fBundleLoader) )
1832 return this->addDylib(mach_o::dylib::Reader<ppc64>::make(p, len, info.path, info.options.fBundleLoader, fOptions.readerOptions()), info, len);
1833 else if ( mach_o::archive::Reader<ppc64>::validFile(p, len) )
1834 return this->addArchive(mach_o::archive::Reader<ppc64>::make(p, len, info.path, info.modTime, fOptions.readerOptions()), info, len);
1835 break;
1836 case CPU_TYPE_I386:
1837 if ( mach_o::relocatable::Reader<x86>::validFile(p) )
1838 return this->addObject(mach_o::relocatable::Reader<x86>::make(p, info.path, info.modTime, fOptions.readerOptions()), info, len);
1839 else if ( mach_o::dylib::Reader<x86>::validFile(p, info.options.fBundleLoader) )
1840 return this->addDylib(mach_o::dylib::Reader<x86>::make(p, len, info.path, info.options.fBundleLoader, fOptions.readerOptions()), info, len);
1841 else if ( mach_o::archive::Reader<x86>::validFile(p, len) )
1842 return this->addArchive(mach_o::archive::Reader<x86>::make(p, len, info.path, info.modTime, fOptions.readerOptions()), info, len);
1843 break;
1844 case CPU_TYPE_X86_64:
1845 if ( mach_o::relocatable::Reader<x86_64>::validFile(p) )
1846 return this->addObject(mach_o::relocatable::Reader<x86_64>::make(p, info.path, info.modTime, fOptions.readerOptions()), info, len);
1847 else if ( mach_o::dylib::Reader<x86_64>::validFile(p, info.options.fBundleLoader) )
1848 return this->addDylib(mach_o::dylib::Reader<x86_64>::make(p, len, info.path, info.options.fBundleLoader, fOptions.readerOptions()), info, len);
1849 else if ( mach_o::archive::Reader<x86_64>::validFile(p, len) )
1850 return this->addArchive(mach_o::archive::Reader<x86_64>::make(p, len, info.path, info.modTime, fOptions.readerOptions()), info, len);
1851 break;
1852 }
1853
1854 // error handling
1855 if ( ((fat_header*)p)->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) {
1856 throwf("missing required architecture %s in file", fArchitectureName);
1857 }
1858 else {
1859 throw "file is not of required architecture";
1860 }
1861 }
1862
1863
1864 void Linker::createReaders()
1865 {
1866 fStartCreateReadersTime = mach_absolute_time();
1867 std::vector<Options::FileInfo>& files = fOptions.getInputFiles();
1868 const int count = files.size();
1869 if ( count == 0 )
1870 throw "no object files specified";
1871 // add all direct object, archives, and dylibs
1872 for (int i=0; i < count; ++i) {
1873 Options::FileInfo& entry = files[i];
1874 // ignore /usr/lib/dyld on command line in crt.o build
1875 if ( strcmp(entry.path, "/usr/lib/dyld") != 0 ) {
1876 try {
1877 this->addInputFile(this->createReader(entry));
1878 }
1879 catch (const char* msg) {
1880 if ( strstr(msg, "architecture") != NULL ) {
1881 if ( fOptions.ignoreOtherArchInputFiles() ) {
1882 // ignore, because this is about an architecture not in use
1883 }
1884 else {
1885 fprintf(stderr, "ld64 warning: in %s, %s\n", entry.path, msg);
1886 }
1887 }
1888 else {
1889 throwf("in %s, %s", entry.path, msg);
1890 }
1891 }
1892 }
1893 }
1894
1895 // add first level of indirect dylibs
1896 fDirectLibrariesComplete = true;
1897 for (std::vector<ExecutableFile::DyLibUsed>::iterator it=fDynamicLibraries.begin(); it != fDynamicLibraries.end(); it++) {
1898 this->addIndirectLibraries(it->reader);
1899 }
1900
1901 // indirect handling depends on namespace
1902 switch ( fOptions.nameSpace() ) {
1903 case Options::kFlatNameSpace:
1904 case Options::kForceFlatNameSpace:
1905 // with flat namespace, blindly load all indirect libraries
1906 // the indirect list will grow as indirect libraries are loaded
1907 for (std::list<IndirectLibrary>::iterator it=fIndirectDynamicLibraries.begin(); it != fIndirectDynamicLibraries.end(); it++) {
1908 try {
1909 it->reader = this->createReader(fOptions.findFile(it->path));
1910 it->reader->setSortOrder(fNextObjectFileOrder++);
1911 }
1912 catch (const char* msg) {
1913 fprintf(stderr, "ld64 warning: indirect library %s could not be loaded: %s\n", it->path, msg);
1914 }
1915 }
1916 break;
1917
1918 case Options::kTwoLevelNameSpace:
1919 // with two-level namespace we only want to use indirect libraries that are re-exported through a library that is used
1920 {
1921 bool indirectAdded = true;
1922 while ( indirectAdded ) {
1923 indirectAdded = false;
1924 // instantiate a reader for each indirect library and try to find parent that re-exports it
1925 for (std::list<IndirectLibrary>::iterator it=fIndirectDynamicLibraries.begin(); it != fIndirectDynamicLibraries.end(); it++) {
1926 if ( it->reader == NULL ) {
1927 try {
1928 it->reader = this->createReader(fOptions.findFile(it->path));
1929 it->reader->setSortOrder(fNextObjectFileOrder++);
1930 indirectAdded = true;
1931 }
1932 catch (const char* msg) {
1933 fprintf(stderr, "ld64 warning: indirect library %s could not be loaded: %s\n", it->path, msg);
1934 }
1935 }
1936 // if an indirect library does not have an assigned parent, look for one
1937 if ( (it->reader != NULL) && (it->reExportedViaDirectLibrary == NULL) ) {
1938 it->reExportedViaDirectLibrary = this->findDirectLibraryWhichReExports(*it);
1939 }
1940 }
1941 }
1942 }
1943 break;
1944 }
1945
1946 // add relevant indirect libraries to the end of fDynamicLibraries
1947 for (std::list<IndirectLibrary>::iterator it=fIndirectDynamicLibraries.begin(); it != fIndirectDynamicLibraries.end(); it++) {
1948 if ( (it->reader != NULL) && (it->reExportedViaDirectLibrary != NULL) || (fOptions.nameSpace() != Options::kTwoLevelNameSpace) ) {
1949 ExecutableFile::DyLibUsed dylibInfo;
1950 dylibInfo.reader = it->reader;
1951 dylibInfo.options.fWeakImport = false;
1952 dylibInfo.options.fReExport = false;
1953 dylibInfo.options.fInstallPathOverride = NULL;
1954 dylibInfo.indirect = true;
1955 dylibInfo.directReader = it->reExportedViaDirectLibrary;
1956 fDynamicLibraries.push_back(dylibInfo);
1957 if ( fOptions.readerOptions().fTraceIndirectDylibs ) {
1958 const char* fullPath = it->reader->getPath();
1959 char realName[MAXPATHLEN];
1960 if ( realpath(fullPath, realName) != NULL )
1961 fullPath = realName;
1962 logTraceInfo("[Logging for XBS] Used indirect dynamic library: %s\n", fullPath);
1963 }
1964 }
1965 }
1966 }
1967
1968
1969 ObjectFile::Reader* Linker::findDirectLibraryWhichReExports(IndirectLibrary& indirectLib)
1970 {
1971 // ask each parent if they re-export this dylib
1972 for (std::set<ObjectFile::Reader*>::iterator pit=indirectLib.parents.begin(); pit != indirectLib.parents.end(); pit++) {
1973 if ( (*pit)->reExports(indirectLib.reader) ) {
1974 ObjectFile::Reader* lib = *pit;
1975 // first check if we found a direct library, if so return it
1976 for (std::vector<ExecutableFile::DyLibUsed>::iterator dit=fDynamicLibraries.begin(); dit != fDynamicLibraries.end(); dit++) {
1977 if ( dit->reader == lib && dit->indirect == false )
1978 return lib;
1979 }
1980 // otherwise search indirects for parent and see how it is reexported
1981 for (std::list<IndirectLibrary>::iterator iit=fIndirectDynamicLibraries.begin(); iit != fIndirectDynamicLibraries.end(); iit++) {
1982 if ( iit->reader == lib ) {
1983 ObjectFile::Reader* lib2 = this->findDirectLibraryWhichReExports(*iit);
1984 if ( lib2 != NULL )
1985 return lib2;
1986 }
1987 }
1988 }
1989 }
1990 return NULL;
1991 }
1992
1993
1994
1995 ObjectFile::Reader* Linker::addArchive(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen)
1996 {
1997 if (fOptions.readerOptions().fTraceArchives) {
1998 const char* fullPath = reader->getPath();
1999 char realName[MAXPATHLEN];
2000 if ( realpath(fullPath, realName) != NULL )
2001 fullPath = realName;
2002 logTraceInfo("[Logging for XBS] Used static archive: %s\n", fullPath);
2003 }
2004
2005 // update stats
2006 fTotalArchiveSize += mappedLen;
2007 ++fTotalArchivesLoaded;
2008 return reader;
2009 }
2010
2011 ObjectFile::Reader* Linker::addObject(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen)
2012 {
2013 // update stats
2014 fTotalObjectSize += mappedLen;
2015 ++fTotalObjectLoaded;
2016 return reader;
2017 }
2018
2019 ObjectFile::Reader* Linker::addDylib(ObjectFile::Reader* reader, const Options::FileInfo& info, uint64_t mappedLen)
2020 {
2021 if ( (reader->getInstallPath() == NULL) && !info.options.fBundleLoader ) {
2022 // this is a "blank" stub
2023 // silently ignore it
2024 return reader;
2025 }
2026
2027 if ( fDirectLibrariesComplete ) {
2028 this->addIndirectLibraries(reader);
2029 }
2030 else {
2031 if ( fOptions.readerOptions().fTraceDylibs ) {
2032 const char* fullPath = reader->getPath();
2033 char realName[MAXPATHLEN];
2034 if ( realpath(fullPath, realName) != NULL )
2035 fullPath = realName;
2036 logTraceInfo("[Logging for XBS] Used dynamic library: %s\n", fullPath);
2037 }
2038 ExecutableFile::DyLibUsed dylibInfo;
2039 dylibInfo.reader = reader;
2040 dylibInfo.options = info.options;
2041 dylibInfo.indirect = false;
2042 dylibInfo.directReader = NULL;
2043 fDynamicLibraries.push_back(dylibInfo);
2044
2045
2046 // Verify that a client is allowed to link to this dylib. There are three cases.
2047 bool okToLink = true;
2048 const char* outputFilePath = fOptions.installPath();
2049 const char* outputFilePathLastSlash = strrchr(outputFilePath, '/');
2050 if ( reader->parentUmbrella() != NULL ) {
2051 // case 1) The dylib has a parent umbrella, and we are creating the parent umbrella
2052 okToLink = ( (outputFilePathLastSlash != NULL) && (strcmp(&outputFilePathLastSlash[1], reader->parentUmbrella()) == 0) );
2053 }
2054
2055 if ( !okToLink && (reader->parentUmbrella() != NULL) ) {
2056 // case 2) The dylib has a parent umbrella, and we are creating a sibling with the same parent
2057 okToLink = ( (outputFilePathLastSlash != NULL)
2058 && (fOptions.umbrellaName() != NULL)
2059 && (strcmp(fOptions.umbrellaName(), reader->parentUmbrella()) == 0) );
2060 }
2061
2062 std::vector<const char*>* clients = reader->getAllowableClients();
2063 if ( !okToLink && (clients != NULL) ) {
2064 // case 3) the dylib has a list of allowable clients, and we are creating one of them
2065 const char* clientName = fOptions.clientName();
2066 int clientNameLen = 0;
2067 if ( clientName != NULL ) {
2068 // use client name as specified on command line
2069 clientNameLen = strlen(clientName);
2070 }
2071 else {
2072 // infer client name from output path (e.g. xxx/libfoo.A.dylib --> foo, Bar.framework/Bar --> Bar)
2073 clientName = outputFilePath;
2074 // starts after last slash
2075 if ( outputFilePathLastSlash != NULL )
2076 clientName = &outputFilePathLastSlash[1];
2077 if ( strncmp(clientName, "lib", 3) == 0 )
2078 clientName = &clientName[3];
2079 // up to first dot
2080 const char* firstDot = strchr(clientName, '.');
2081 if ( firstDot == NULL )
2082 clientNameLen = strlen(clientName);
2083 else
2084 clientNameLen = firstDot - clientName;
2085 }
2086
2087 // Use clientName to check if this dylib is able to link against the allowable clients.
2088 for (std::vector<const char*>::iterator it = clients->begin(); it != clients->end(); it++) {
2089 if ( strncmp(*it, clientName, clientNameLen) == 0 )
2090 okToLink = true;
2091 }
2092 }
2093
2094 // error out if we are not allowed to link
2095 if ( ! okToLink )
2096 //throwf("'%s' is a subframework. Link against the umbrella framework '%s.framework' instead.",
2097 fprintf(stderr, "'%s' is a subframework. Link against the umbrella framework '%s.framework' instead.",
2098 reader->getPath(), reader->parentUmbrella());
2099 }
2100
2101 // update stats
2102 ++fTotalDylibsLoaded;
2103
2104 return reader;
2105 }
2106
2107
2108 void Linker::addIndirectLibraries(ObjectFile::Reader* reader)
2109 {
2110 std::vector<const char*>* dependentLibs = reader->getDependentLibraryPaths();
2111 if ( dependentLibs != NULL ) {
2112 for (std::vector<const char*>::iterator it=dependentLibs->begin(); it != dependentLibs->end(); it++) {
2113 if ( this->haveDirectLibrary(*it) ) {
2114 // do nothing, direct library already exists
2115 }
2116 else if ( this->haveIndirectLibrary(*it, reader) ) {
2117 // side effect of haveIndirectLibrary() added reader to parent list
2118 }
2119 else {
2120 // add to list of indirect libraries
2121 IndirectLibrary indirectLib;
2122 indirectLib.path = *it;
2123 indirectLib.fileLen = 0;
2124 indirectLib.reader = NULL;
2125 indirectLib.parents.insert(reader);
2126 indirectLib.reExportedViaDirectLibrary = NULL;
2127 fIndirectDynamicLibraries.push_back(indirectLib);
2128 //fprintf(stderr, "add indirect library: %s\n", *it);
2129 }
2130 }
2131 }
2132 }
2133
2134 bool Linker::haveIndirectLibrary(const char* path, ObjectFile::Reader* parentReader)
2135 {
2136 for (std::list<IndirectLibrary>::iterator it=fIndirectDynamicLibraries.begin(); it != fIndirectDynamicLibraries.end(); it++) {
2137 if ( strcmp(path, it->path) == 0 ) {
2138 it->parents.insert(parentReader);
2139 return true;
2140 }
2141 if ( it->reader != NULL ) {
2142 const char* installPath = it->reader->getInstallPath();
2143 if ( (installPath != NULL) && (strcmp(path, installPath) == 0) )
2144 return true;
2145 }
2146 }
2147 return false;
2148 }
2149
2150 bool Linker::haveDirectLibrary(const char* path)
2151 {
2152 for (std::vector<ExecutableFile::DyLibUsed>::iterator it=fDynamicLibraries.begin(); it != fDynamicLibraries.end(); it++) {
2153 if ( strcmp(path, it->reader->getPath()) == 0 )
2154 return true;
2155 const char* installPath = it->reader->getInstallPath();
2156 if ( (installPath != NULL) && (strcmp(path, installPath) == 0) )
2157 return true;
2158 }
2159 return false;
2160 }
2161
2162 void Linker::logTraceInfo (const char* format, ...)
2163 {
2164 static int trace_file = -1;
2165 char trace_buffer[MAXPATHLEN * 2];
2166 char *buffer_ptr;
2167 int length;
2168 ssize_t amount_written;
2169 const char *trace_file_path = fOptions.readerOptions().fTraceOutputFile;
2170
2171 if(trace_file == -1) {
2172 if(trace_file_path != NULL) {
2173 trace_file = open(trace_file_path, O_WRONLY | O_APPEND | O_CREAT, 0666);
2174 if(trace_file == -1)
2175 throwf("Could not open or create trace file: %s\n", trace_file_path);
2176 }
2177 else {
2178 trace_file = fileno(stderr);
2179 }
2180 }
2181
2182 va_list ap;
2183 va_start(ap, format);
2184 length = vsnprintf(trace_buffer, sizeof(trace_buffer), format, ap);
2185 va_end(ap);
2186 buffer_ptr = trace_buffer;
2187
2188 while(length > 0) {
2189 amount_written = write(trace_file, buffer_ptr, length);
2190 if(amount_written == -1)
2191 /* Failure to write shouldn't fail the build. */
2192 return;
2193 buffer_ptr += amount_written;
2194 length -= amount_written;
2195 }
2196 }
2197
2198
2199
2200 void Linker::createWriter()
2201 {
2202 fStartCreateWriterTime = mach_absolute_time();
2203 const char* path = fOptions.getOutputFilePath();
2204 switch ( fArchitecture ) {
2205 case CPU_TYPE_POWERPC:
2206 this->setOutputFile(new mach_o::executable::Writer<ppc>(path, fOptions, fDynamicLibraries));
2207 break;
2208 case CPU_TYPE_POWERPC64:
2209 this->setOutputFile(new mach_o::executable::Writer<ppc64>(path, fOptions, fDynamicLibraries));
2210 break;
2211 case CPU_TYPE_I386:
2212 this->setOutputFile(new mach_o::executable::Writer<x86>(path, fOptions, fDynamicLibraries));
2213 break;
2214 case CPU_TYPE_X86_64:
2215 this->setOutputFile(new mach_o::executable::Writer<x86_64>(path, fOptions, fDynamicLibraries));
2216 break;
2217 default:
2218 throw "unknown architecture";
2219 }
2220 }
2221
2222
2223 Linker::SymbolTable::SymbolTable(Linker& owner)
2224 : fOwner(owner), fRequireCount(0)
2225 {
2226 }
2227
2228 void Linker::SymbolTable::require(const char* name)
2229 {
2230 //fprintf(stderr, "require(%s)\n", name);
2231 Mapper::iterator pos = fTable.find(name);
2232 if ( pos == fTable.end() ) {
2233 fTable[name] = NULL;
2234 ++fRequireCount;
2235 }
2236 }
2237
2238 // convenience labels for 2-dimensional switch statement
2239 enum {
2240 kRegAndReg = (ObjectFile::Atom::kRegularDefinition << 3) | ObjectFile::Atom::kRegularDefinition,
2241 kRegAndWeak = (ObjectFile::Atom::kRegularDefinition << 3) | ObjectFile::Atom::kWeakDefinition,
2242 kRegAndTent = (ObjectFile::Atom::kRegularDefinition << 3) | ObjectFile::Atom::kTentativeDefinition,
2243 kRegAndExtern = (ObjectFile::Atom::kRegularDefinition << 3) | ObjectFile::Atom::kExternalDefinition,
2244 kRegAndExternWeak = (ObjectFile::Atom::kRegularDefinition << 3) | ObjectFile::Atom::kExternalWeakDefinition,
2245 kWeakAndReg = (ObjectFile::Atom::kWeakDefinition << 3) | ObjectFile::Atom::kRegularDefinition,
2246 kWeakAndWeak = (ObjectFile::Atom::kWeakDefinition << 3) | ObjectFile::Atom::kWeakDefinition,
2247 kWeakAndTent = (ObjectFile::Atom::kWeakDefinition << 3) | ObjectFile::Atom::kTentativeDefinition,
2248 kWeakAndExtern = (ObjectFile::Atom::kWeakDefinition << 3) | ObjectFile::Atom::kExternalDefinition,
2249 kWeakAndExternWeak = (ObjectFile::Atom::kWeakDefinition << 3) | ObjectFile::Atom::kExternalWeakDefinition,
2250 kTentAndReg = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kRegularDefinition,
2251 kTentAndWeak = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kWeakDefinition,
2252 kTentAndTent = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kTentativeDefinition,
2253 kTentAndExtern = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kExternalDefinition,
2254 kTentAndExternWeak = (ObjectFile::Atom::kTentativeDefinition << 3) | ObjectFile::Atom::kExternalWeakDefinition,
2255 kExternAndReg = (ObjectFile::Atom::kExternalDefinition << 3) | ObjectFile::Atom::kRegularDefinition,
2256 kExternAndWeak = (ObjectFile::Atom::kExternalDefinition << 3) | ObjectFile::Atom::kWeakDefinition,
2257 kExternAndTent = (ObjectFile::Atom::kExternalDefinition << 3) | ObjectFile::Atom::kTentativeDefinition,
2258 kExternAndExtern = (ObjectFile::Atom::kExternalDefinition << 3) | ObjectFile::Atom::kExternalDefinition,
2259 kExternAndExternWeak = (ObjectFile::Atom::kExternalDefinition << 3) | ObjectFile::Atom::kExternalWeakDefinition,
2260 kExternWeakAndReg = (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kRegularDefinition,
2261 kExternWeakAndWeak = (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kWeakDefinition,
2262 kExternWeakAndTent = (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kTentativeDefinition,
2263 kExternWeakAndExtern = (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kExternalDefinition,
2264 kExternWeakAndExternWeak= (ObjectFile::Atom::kExternalWeakDefinition << 3) | ObjectFile::Atom::kExternalWeakDefinition
2265 };
2266
2267 bool Linker::SymbolTable::add(ObjectFile::Atom& newAtom)
2268 {
2269 bool useNew = true;
2270 const char* name = newAtom.getName();
2271 //fprintf(stderr, "map.add(%s => %p from %s)\n", name, &newAtom, newAtom.getFile()->getPath());
2272 Mapper::iterator pos = fTable.find(name);
2273 ObjectFile::Atom* existingAtom = NULL;
2274 if ( pos != fTable.end() )
2275 existingAtom = pos->second;
2276 if ( existingAtom != NULL ) {
2277 // already have atom with same name in symbol table
2278 switch ( (existingAtom->getDefinitionKind() << 3) | newAtom.getDefinitionKind() ) {
2279 case kRegAndReg:
2280 throwf("duplicate symbol %s in %s and %s\n", name, newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
2281 case kRegAndWeak:
2282 // ignore new weak atom, because we already have a non-weak one
2283 useNew = false;
2284 break;
2285 case kRegAndTent:
2286 // ignore new tentative atom, because we already have a regular one
2287 useNew = false;
2288 break;
2289 case kRegAndExtern:
2290 // ignore external atom, because we already have a one
2291 useNew = false;
2292 break;
2293 case kRegAndExternWeak:
2294 // ignore external atom, because we already have a one
2295 useNew = false;
2296 break;
2297 case kWeakAndReg:
2298 // replace existing weak atom with regular one
2299 break;
2300 case kWeakAndWeak:
2301 // have another weak atom, use whichever has largest alignment requirement
2302 // because codegen of some client may require alignment
2303 useNew = ( newAtom.getAlignment() > existingAtom->getAlignment() );
2304 break;
2305 case kWeakAndTent:
2306 // replace existing weak atom with tentative one ???
2307 break;
2308 case kWeakAndExtern:
2309 // keep weak atom, at runtime external one may override
2310 useNew = false;
2311 break;
2312 case kWeakAndExternWeak:
2313 // keep weak atom, at runtime external one may override
2314 useNew = false;
2315 break;
2316 case kTentAndReg:
2317 // replace existing tentative atom with regular one
2318 break;
2319 case kTentAndWeak:
2320 // replace existing tentative atom with weak one ???
2321 break;
2322 case kTentAndTent:
2323 // use largest
2324 if ( newAtom.getSize() < existingAtom->getSize() ) {
2325 useNew = false;
2326 }
2327 break;
2328 case kTentAndExtern:
2329 case kTentAndExternWeak:
2330 // a tentative definition and a dylib definition, so commons-mode decides how to handle
2331 switch ( fOwner.fOptions.commonsMode() ) {
2332 case Options::kCommonsIgnoreDylibs:
2333 if ( fOwner.fOptions.warnCommons() )
2334 fprintf(stderr, "ld64: using common symbol %s from %s and ignoring defintion from dylib %s\n",
2335 existingAtom->getName(), existingAtom->getFile()->getPath(), newAtom.getFile()->getPath());
2336 useNew = false;
2337 break;
2338 case Options::kCommonsOverriddenByDylibs:
2339 if ( fOwner.fOptions.warnCommons() )
2340 fprintf(stderr, "ld64: replacing common symbol %s from %s with true definition from dylib %s\n",
2341 existingAtom->getName(), existingAtom->getFile()->getPath(), newAtom.getFile()->getPath());
2342 break;
2343 case Options::kCommonsConflictsDylibsError:
2344 throwf("common symbol %s from %s conflicts with defintion from dylib %s",
2345 existingAtom->getName(), existingAtom->getFile()->getPath(), newAtom.getFile()->getPath());
2346 }
2347 break;
2348 case kExternAndReg:
2349 // replace external atom with regular one
2350 break;
2351 case kExternAndWeak:
2352 // replace external atom with weak one
2353 break;
2354 case kExternAndTent:
2355 // a tentative definition and a dylib definition, so commons-mode decides how to handle
2356 switch ( fOwner.fOptions.commonsMode() ) {
2357 case Options::kCommonsIgnoreDylibs:
2358 if ( fOwner.fOptions.warnCommons() )
2359 fprintf(stderr, "ld64: using common symbol %s from %s and ignoring defintion from dylib %s\n",
2360 newAtom.getName(), newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
2361 break;
2362 case Options::kCommonsOverriddenByDylibs:
2363 if ( fOwner.fOptions.warnCommons() )
2364 fprintf(stderr, "ld64: replacing defintion of %s from dylib %s with common symbol from %s\n",
2365 newAtom.getName(), existingAtom->getFile()->getPath(), newAtom.getFile()->getPath());
2366 useNew = false;
2367 break;
2368 case Options::kCommonsConflictsDylibsError:
2369 throwf("common symbol %s from %s conflicts with defintion from dylib %s",
2370 newAtom.getName(), newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
2371 }
2372 break;
2373 case kExternAndExtern:
2374 throwf("duplicate symbol %s in %s and %s\n", name, newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
2375 case kExternAndExternWeak:
2376 // keep strong dylib atom, ignore weak one
2377 useNew = false;
2378 break;
2379 case kExternWeakAndReg:
2380 // replace existing weak external with regular
2381 break;
2382 case kExternWeakAndWeak:
2383 // replace existing weak external with weak (let dyld decide at runtime which to use)
2384 break;
2385 case kExternWeakAndTent:
2386 // a tentative definition and a dylib definition, so commons-mode decides how to handle
2387 switch ( fOwner.fOptions.commonsMode() ) {
2388 case Options::kCommonsIgnoreDylibs:
2389 if ( fOwner.fOptions.warnCommons() )
2390 fprintf(stderr, "ld64: using common symbol %s from %s and ignoring defintion from dylib %s\n",
2391 newAtom.getName(), newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
2392 break;
2393 case Options::kCommonsOverriddenByDylibs:
2394 if ( fOwner.fOptions.warnCommons() )
2395 fprintf(stderr, "ld64: replacing defintion of %s from dylib %s with common symbol from %s\n",
2396 newAtom.getName(), existingAtom->getFile()->getPath(), newAtom.getFile()->getPath());
2397 useNew = false;
2398 break;
2399 case Options::kCommonsConflictsDylibsError:
2400 throwf("common symbol %s from %s conflicts with defintion from dylib %s",
2401 newAtom.getName(), newAtom.getFile()->getPath(), existingAtom->getFile()->getPath());
2402 }
2403 break;
2404 case kExternWeakAndExtern:
2405 // replace existing weak external with external
2406 break;
2407 case kExternWeakAndExternWeak:
2408 // keep existing external weak
2409 useNew = false;
2410 break;
2411 }
2412 }
2413 if ( useNew ) {
2414 fTable[name] = &newAtom;
2415 if ( existingAtom != NULL )
2416 fOwner.fDeadAtoms.insert(existingAtom);
2417 }
2418 else {
2419 fOwner.fDeadAtoms.insert(&newAtom);
2420 }
2421 return useNew;
2422 }
2423
2424
2425
2426 ObjectFile::Atom* Linker::SymbolTable::find(const char* name)
2427 {
2428 Mapper::iterator pos = fTable.find(name);
2429 if ( pos != fTable.end() ) {
2430 return pos->second;
2431 }
2432 return NULL;
2433 }
2434
2435
2436 void Linker::SymbolTable::getNeededNames(bool andWeakDefintions, std::vector<const char*>& undefines)
2437 {
2438 for (Mapper::iterator it=fTable.begin(); it != fTable.end(); it++) {
2439 if ( (it->second == NULL) || (andWeakDefintions && (it->second->getDefinitionKind()==ObjectFile::Atom::kWeakDefinition)) ) {
2440 undefines.push_back(it->first);
2441 }
2442 }
2443 }
2444
2445
2446
2447
2448 bool Linker::AtomSorter::operator()(ObjectFile::Atom* left, ObjectFile::Atom* right)
2449 {
2450 // first sort by section order (which is already sorted by segment)
2451 unsigned int leftSectionIndex = left->getSection()->getIndex();
2452 unsigned int rightSectionIndex = right->getSection()->getIndex();
2453 if ( leftSectionIndex != rightSectionIndex)
2454 return (leftSectionIndex < rightSectionIndex);
2455
2456 // then sort by .o file order
2457 ObjectFile::Reader* leftReader = left->getFile();
2458 ObjectFile::Reader* rightReader = right->getFile();
2459 if ( leftReader != rightReader )
2460 return leftReader->getSortOrder() < rightReader->getSortOrder();
2461
2462 // lastly sort by atom within a .o file
2463 return left->getSortOrder() < right->getSortOrder();
2464 }
2465
2466
2467 int main(int argc, const char* argv[])
2468 {
2469 const char* archName = NULL;
2470 bool showArch = false;
2471 bool archInferred = false;
2472 try {
2473 // create linker object given command line arguments
2474 Linker ld(argc, argv);
2475
2476 // save error message prefix
2477 archName = ld.architectureName();
2478 archInferred = ld.isInferredArchitecture();
2479 showArch = ld.showArchitectureInErrors();
2480
2481 // open all input files
2482 ld.createReaders();
2483
2484 // open output file
2485 ld.createWriter();
2486
2487 // do linking
2488 ld.link();
2489 }
2490 catch (const char* msg) {
2491 extern const double ld64VersionNumber;
2492 if ( archInferred )
2493 fprintf(stderr, "ld64-%g failed: %s for inferred architecture %s\n", ld64VersionNumber, msg, archName);
2494 else if ( showArch )
2495 fprintf(stderr, "ld64-%g failed: %s for architecture %s\n", ld64VersionNumber, msg, archName);
2496 else
2497 fprintf(stderr, "ld64-%g failed: %s\n", ld64VersionNumber, msg);
2498 return 1;
2499 }
2500
2501 return 0;
2502 }