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