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