]> git.saurik.com Git - apple/ld64.git/blob - src/ld/Resolver.cpp
a5405a9951057673fb0cdf1cd9c5a629acebdec2
[apple/ld64.git] / src / ld / Resolver.cpp
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-*
2 *
3 * Copyright (c) 2009-2010 Apple Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
12 * file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25
26 #include <stdlib.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <sys/mman.h>
30 #include <sys/sysctl.h>
31 #include <fcntl.h>
32 #include <errno.h>
33 #include <limits.h>
34 #include <unistd.h>
35 #include <mach/mach_time.h>
36 #include <mach/vm_statistics.h>
37 #include <mach/mach_init.h>
38 #include <mach/mach_host.h>
39 #include <dlfcn.h>
40 #include <mach-o/dyld.h>
41 #include <mach-o/fat.h>
42
43 #include <string>
44 #include <map>
45 #include <set>
46 #include <string>
47 #include <vector>
48 #include <list>
49 #include <algorithm>
50 #include <dlfcn.h>
51 #include <AvailabilityMacros.h>
52
53 #include "Options.h"
54
55 #include "ld.hpp"
56 #include "InputFiles.h"
57 #include "SymbolTable.h"
58 #include "Resolver.h"
59 #include "parsers/lto_file.h"
60
61
62 namespace ld {
63 namespace tool {
64
65
66 //
67 // An ExportAtom has no content. It exists so that the linker can track which imported
68 // symbols came from which dynamic libraries.
69 //
70 class UndefinedProxyAtom : public ld::Atom
71 {
72 public:
73 UndefinedProxyAtom(const char* nm)
74 : ld::Atom(_s_section, ld::Atom::definitionProxy,
75 ld::Atom::combineNever, ld::Atom::scopeLinkageUnit,
76 ld::Atom::typeUnclassified,
77 ld::Atom::symbolTableIn, false, false, false, ld::Atom::Alignment(0)),
78 _name(nm) {}
79 // overrides of ld::Atom
80 virtual const ld::File* file() const { return NULL; }
81 virtual const char* name() const { return _name; }
82 virtual uint64_t size() const { return 0; }
83 virtual uint64_t objectAddress() const { return 0; }
84 virtual void copyRawContent(uint8_t buffer[]) const { }
85 virtual void setScope(Scope) { }
86
87 protected:
88
89 virtual ~UndefinedProxyAtom() {}
90
91 const char* _name;
92
93 static ld::Section _s_section;
94 };
95
96 ld::Section UndefinedProxyAtom::_s_section("__TEXT", "__import", ld::Section::typeImportProxies, true);
97
98
99
100
101 class AliasAtom : public ld::Atom
102 {
103 public:
104 AliasAtom(const ld::Atom& target, const char* nm) :
105 ld::Atom(target.section(), target.definition(), ld::Atom::combineNever,
106 ld::Atom::scopeGlobal, target.contentType(),
107 target.symbolTableInclusion(), target.dontDeadStrip(),
108 target.isThumb(), true, target.alignment()),
109 _name(nm),
110 _aliasOf(target),
111 _fixup(0, ld::Fixup::k1of1, ld::Fixup::kindNoneFollowOn, &target) { }
112
113 // overrides of ld::Atom
114 virtual const ld::File* file() const { return _aliasOf.file(); }
115 virtual const char* translationUnitSource() const
116 { return _aliasOf.translationUnitSource(); }
117 virtual const char* name() const { return _name; }
118 virtual uint64_t size() const { return 0; }
119 virtual uint64_t objectAddress() const { return _aliasOf.objectAddress(); }
120 virtual void copyRawContent(uint8_t buffer[]) const { }
121 virtual const uint8_t* rawContentPointer() const { return NULL; }
122 virtual unsigned long contentHash(const class ld::IndirectBindingTable& ibt) const
123 { return _aliasOf.contentHash(ibt); }
124 virtual bool canCoalesceWith(const ld::Atom& rhs, const class ld::IndirectBindingTable& ibt) const
125 { return _aliasOf.canCoalesceWith(rhs,ibt); }
126 virtual ld::Fixup::iterator fixupsBegin() const { return (ld::Fixup*)&_fixup; }
127 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup)[1]; }
128 virtual ld::Atom::UnwindInfo::iterator beginUnwind() const { return NULL; }
129 virtual ld::Atom::UnwindInfo::iterator endUnwind() const { return NULL; }
130 virtual ld::Atom::LineInfo::iterator beginLineInfo() const { return NULL; }
131 virtual ld::Atom::LineInfo::iterator endLineInfo() const { return NULL; }
132
133 void setFinalAliasOf() const {
134 (const_cast<AliasAtom*>(this))->setAttributesFromAtom(_aliasOf);
135 (const_cast<AliasAtom*>(this))->setScope(ld::Atom::scopeGlobal);
136 }
137
138 private:
139 const char* _name;
140 const ld::Atom& _aliasOf;
141 ld::Fixup _fixup;
142 };
143
144
145
146 class SectionBoundaryAtom : public ld::Atom
147 {
148 public:
149 static SectionBoundaryAtom* makeSectionBoundaryAtom(const char* name, bool start, const char* segSectName);
150 static SectionBoundaryAtom* makeOldSectionBoundaryAtom(const char* name, bool start);
151
152 // overrides of ld::Atom
153 virtual const ld::File* file() const { return NULL; }
154 virtual const char* name() const { return _name; }
155 virtual uint64_t size() const { return 0; }
156 virtual void copyRawContent(uint8_t buffer[]) const { }
157 virtual const uint8_t* rawContentPointer() const { return NULL; }
158 virtual uint64_t objectAddress() const { return 0; }
159
160 private:
161
162 SectionBoundaryAtom(const char* nm, const ld::Section& sect,
163 ld::Atom::ContentType cont) :
164 ld::Atom(sect,
165 ld::Atom::definitionRegular,
166 ld::Atom::combineNever,
167 ld::Atom::scopeLinkageUnit,
168 cont,
169 ld::Atom::symbolTableNotIn,
170 false, false, true, ld::Atom::Alignment(0)),
171 _name(nm) { }
172
173 const char* _name;
174 };
175
176 SectionBoundaryAtom* SectionBoundaryAtom::makeSectionBoundaryAtom(const char* name, bool start, const char* segSectName)
177 {
178
179 const char* segSectDividor = strrchr(segSectName, '$');
180 if ( segSectDividor == NULL )
181 throwf("malformed section$ symbol name: %s", name);
182 const char* sectionName = segSectDividor + 1;
183 int segNameLen = segSectDividor - segSectName;
184 if ( segNameLen > 16 )
185 throwf("malformed section$ symbol name: %s", name);
186 char segName[18];
187 strlcpy(segName, segSectName, segNameLen+1);
188
189 const ld::Section* section = new ld::Section(strdup(segName), sectionName, ld::Section::typeUnclassified);
190 return new SectionBoundaryAtom(name, *section, (start ? ld::Atom::typeSectionStart : typeSectionEnd));
191 }
192
193 SectionBoundaryAtom* SectionBoundaryAtom::makeOldSectionBoundaryAtom(const char* name, bool start)
194 {
195 // e.g. __DATA__bss__begin
196 char segName[18];
197 strlcpy(segName, name, 7);
198
199 char sectName[18];
200 int nameLen = strlen(name);
201 strlcpy(sectName, &name[6], (start ? nameLen-12 : nameLen-10));
202 warning("grandfathering in old symbol '%s' as alias for 'section$%s$%s$%s'", name, start ? "start" : "end", segName, sectName);
203 const ld::Section* section = new ld::Section(strdup(segName), strdup(sectName), ld::Section::typeUnclassified);
204 return new SectionBoundaryAtom(name, *section, (start ? ld::Atom::typeSectionStart : typeSectionEnd));
205 }
206
207
208
209
210 class SegmentBoundaryAtom : public ld::Atom
211 {
212 public:
213 static SegmentBoundaryAtom* makeSegmentBoundaryAtom(const char* name, bool start, const char* segName);
214 static SegmentBoundaryAtom* makeOldSegmentBoundaryAtom(const char* name, bool start);
215
216 // overrides of ld::Atom
217 virtual const ld::File* file() const { return NULL; }
218 virtual const char* name() const { return _name; }
219 virtual uint64_t size() const { return 0; }
220 virtual void copyRawContent(uint8_t buffer[]) const { }
221 virtual const uint8_t* rawContentPointer() const { return NULL; }
222 virtual uint64_t objectAddress() const { return 0; }
223
224 private:
225
226 SegmentBoundaryAtom(const char* nm, const ld::Section& sect,
227 ld::Atom::ContentType cont) :
228 ld::Atom(sect,
229 ld::Atom::definitionRegular,
230 ld::Atom::combineNever,
231 ld::Atom::scopeLinkageUnit,
232 cont,
233 ld::Atom::symbolTableNotIn,
234 false, false, true, ld::Atom::Alignment(0)),
235 _name(nm) { }
236
237 const char* _name;
238 };
239
240 SegmentBoundaryAtom* SegmentBoundaryAtom::makeSegmentBoundaryAtom(const char* name, bool start, const char* segName)
241 {
242 if ( *segName == '\0' )
243 throwf("malformed segment$ symbol name: %s", name);
244 if ( strlen(segName) > 16 )
245 throwf("malformed segment$ symbol name: %s", name);
246
247 if ( start ) {
248 const ld::Section* section = new ld::Section(segName, "__start", ld::Section::typeFirstSection, true);
249 return new SegmentBoundaryAtom(name, *section, ld::Atom::typeSectionStart);
250 }
251 else {
252 const ld::Section* section = new ld::Section(segName, "__end", ld::Section::typeLastSection, true);
253 return new SegmentBoundaryAtom(name, *section, ld::Atom::typeSectionEnd);
254 }
255 }
256
257 SegmentBoundaryAtom* SegmentBoundaryAtom::makeOldSegmentBoundaryAtom(const char* name, bool start)
258 {
259 // e.g. __DATA__begin
260 char temp[18];
261 strlcpy(temp, name, 7);
262 char* segName = strdup(temp);
263
264 warning("grandfathering in old symbol '%s' as alias for 'segment$%s$%s'", name, start ? "start" : "end", segName);
265
266 if ( start ) {
267 const ld::Section* section = new ld::Section(segName, "__start", ld::Section::typeFirstSection, true);
268 return new SegmentBoundaryAtom(name, *section, ld::Atom::typeSectionStart);
269 }
270 else {
271 const ld::Section* section = new ld::Section(segName, "__end", ld::Section::typeLastSection, true);
272 return new SegmentBoundaryAtom(name, *section, ld::Atom::typeSectionEnd);
273 }
274 }
275
276 void Resolver::initializeState()
277 {
278 // set initial objc constraint based on command line options
279 if ( _options.objcGc() )
280 _internal.objcObjectConstraint = ld::File::objcConstraintRetainReleaseOrGC;
281 else if ( _options.objcGcOnly() )
282 _internal.objcObjectConstraint = ld::File::objcConstraintGC;
283
284 _internal.cpuSubType = _options.subArchitecture();
285
286 // In -r mode, look for -linker_option additions
287 if ( _options.outputKind() == Options::kObjectFile ) {
288 ld::relocatable::File::LinkerOptionsList lo = _options.linkerOptions();
289 for (relocatable::File::LinkerOptionsList::const_iterator it=lo.begin(); it != lo.end(); ++it) {
290 doLinkerOption(*it, "command line");
291 }
292 }
293 }
294
295 void Resolver::buildAtomList()
296 {
297 // each input files contributes initial atoms
298 _atoms.reserve(1024);
299 _inputFiles.forEachInitialAtom(*this, _internal);
300
301 _completedInitialObjectFiles = true;
302
303 //_symbolTable.printStatistics();
304 }
305
306
307 void Resolver::doLinkerOption(const std::vector<const char*>& linkerOption, const char* fileName)
308 {
309 if ( linkerOption.size() == 1 ) {
310 const char* lo1 = linkerOption.front();
311 if ( strncmp(lo1, "-l", 2) == 0 ) {
312 _internal.linkerOptionLibraries.insert(&lo1[2]);
313 }
314 else {
315 warning("unknown linker option from object file ignored: '%s' in %s", lo1, fileName);
316 }
317 }
318 else if ( linkerOption.size() == 2 ) {
319 const char* lo2a = linkerOption[0];
320 const char* lo2b = linkerOption[1];
321 if ( strcmp(lo2a, "-framework") == 0 ) {
322 _internal.linkerOptionFrameworks.insert(lo2b);
323 }
324 else {
325 warning("unknown linker option from object file ignored: '%s' '%s' from %s", lo2a, lo2b, fileName);
326 }
327 }
328 else {
329 warning("unknown linker option from object file ignored, starting with: '%s' from %s", linkerOption.front(), fileName);
330 }
331 }
332
333 static void userReadableSwiftVersion(uint8_t value, char versionString[64])
334 {
335 switch (value) {
336 case 1:
337 strcpy(versionString, "1.0");
338 break;
339 case 2:
340 strcpy(versionString, "1.1");
341 break;
342 default:
343 sprintf(versionString, "unknown ABI version 0x%02X", value);
344 }
345 }
346
347 void Resolver::doFile(const ld::File& file)
348 {
349 const ld::relocatable::File* objFile = dynamic_cast<const ld::relocatable::File*>(&file);
350 const ld::dylib::File* dylibFile = dynamic_cast<const ld::dylib::File*>(&file);
351
352 if ( objFile != NULL ) {
353 // if file has linker options, process them
354 ld::relocatable::File::LinkerOptionsList* lo = objFile->linkerOptions();
355 if ( lo != NULL ) {
356 for (relocatable::File::LinkerOptionsList::const_iterator it=lo->begin(); it != lo->end(); ++it) {
357 this->doLinkerOption(*it, file.path());
358 }
359 }
360
361 // update which form of ObjC is being used
362 switch ( file.objCConstraint() ) {
363 case ld::File::objcConstraintNone:
364 break;
365 case ld::File::objcConstraintRetainRelease:
366 if ( _internal.objcObjectConstraint == ld::File::objcConstraintGC )
367 throwf("%s built with incompatible Garbage Collection settings to link with previous .o files", file.path());
368 if ( _options.objcGcOnly() )
369 throwf("command line specified -objc_gc_only, but file is retain/release based: %s", file.path());
370 if ( _options.objcGc() )
371 throwf("command line specified -objc_gc, but file is retain/release based: %s", file.path());
372 if ( !_options.targetIOSSimulator() && (_internal.objcObjectConstraint != ld::File::objcConstraintRetainReleaseForSimulator) )
373 _internal.objcObjectConstraint = ld::File::objcConstraintRetainRelease;
374 break;
375 case ld::File::objcConstraintRetainReleaseOrGC:
376 if ( _internal.objcObjectConstraint == ld::File::objcConstraintNone )
377 _internal.objcObjectConstraint = ld::File::objcConstraintRetainReleaseOrGC;
378 if ( _options.targetIOSSimulator() )
379 warning("linking ObjC for iOS Simulator, but object file (%s) was compiled for MacOSX", file.path());
380 break;
381 case ld::File::objcConstraintGC:
382 if ( _internal.objcObjectConstraint == ld::File::objcConstraintRetainRelease )
383 throwf("%s built with incompatible Garbage Collection settings to link with previous .o files", file.path());
384 _internal.objcObjectConstraint = ld::File::objcConstraintGC;
385 if ( _options.targetIOSSimulator() )
386 warning("linking ObjC for iOS Simulator, but object file (%s) was compiled for MacOSX", file.path());
387 break;
388 case ld::File::objcConstraintRetainReleaseForSimulator:
389 if ( _internal.objcObjectConstraint == ld::File::objcConstraintNone ) {
390 if ( !_options.targetIOSSimulator() && (_options.outputKind() != Options::kObjectFile) )
391 warning("ObjC object file (%s) was compiled for iOS Simulator, but linking for MacOSX", file.path());
392 _internal.objcObjectConstraint = ld::File::objcConstraintRetainReleaseForSimulator;
393 }
394 else if ( _internal.objcObjectConstraint != ld::File::objcConstraintRetainReleaseForSimulator ) {
395 _internal.objcObjectConstraint = ld::File::objcConstraintRetainReleaseForSimulator;
396 }
397 break;
398 }
399
400 // verify all files use same version of Swift language
401 if ( file.swiftVersion() != 0 ) {
402 if ( _internal.swiftVersion == 0 ) {
403 _internal.swiftVersion = file.swiftVersion();
404 }
405 else if ( file.swiftVersion() != _internal.swiftVersion ) {
406 char fileVersion[64];
407 char otherVersion[64];
408 userReadableSwiftVersion(file.swiftVersion(), fileVersion);
409 userReadableSwiftVersion(_internal.swiftVersion, otherVersion);
410 if ( file.swiftVersion() > _internal.swiftVersion ) {
411 throwf("%s compiled with newer version of Swift language (%s) than previous files (%s)",
412 file.path(), fileVersion, otherVersion);
413 }
414 else {
415 throwf("%s compiled with older version of Swift language (%s) than previous files (%s)",
416 file.path(), fileVersion, otherVersion);
417 }
418 }
419 }
420
421 // in -r mode, if any .o files have dwarf then add UUID to output .o file
422 if ( objFile->debugInfo() == ld::relocatable::File::kDebugInfoDwarf )
423 _internal.someObjectFileHasDwarf = true;
424
425 // remember if any .o file did not have MH_SUBSECTIONS_VIA_SYMBOLS bit set
426 if ( ! objFile->canScatterAtoms() )
427 _internal.allObjectFilesScatterable = false;
428
429 // update cpu-sub-type
430 cpu_subtype_t nextObjectSubType = file.cpuSubType();
431 switch ( _options.architecture() ) {
432 case CPU_TYPE_ARM:
433 if ( _options.subArchitecture() != nextObjectSubType ) {
434 if ( (_options.subArchitecture() == CPU_SUBTYPE_ARM_ALL) && _options.forceCpuSubtypeAll() ) {
435 // hack to support gcc multillib build that tries to make sub-type-all slice
436 }
437 else if ( nextObjectSubType == CPU_SUBTYPE_ARM_ALL ) {
438 warning("CPU_SUBTYPE_ARM_ALL subtype is deprecated: %s", file.path());
439 }
440 else if ( _options.allowSubArchitectureMismatches() ) {
441 //warning("object file %s was built for different arm sub-type (%d) than link command line (%d)",
442 // file.path(), nextObjectSubType, _options.subArchitecture());
443 }
444 else {
445 throwf("object file %s was built for different arm sub-type (%d) than link command line (%d)",
446 file.path(), nextObjectSubType, _options.subArchitecture());
447 }
448 }
449 break;
450
451 case CPU_TYPE_I386:
452 _internal.cpuSubType = CPU_SUBTYPE_I386_ALL;
453 break;
454
455 case CPU_TYPE_X86_64:
456 if ( _options.subArchitecture() != nextObjectSubType ) {
457 if ( _options.allowSubArchitectureMismatches() ) {
458 warning("object file %s was built for different x86_64 sub-type (%d) than link command line (%d)",
459 file.path(), nextObjectSubType, _options.subArchitecture());
460 }
461 else {
462 throwf("object file %s was built for different x86_64 sub-type (%d) than link command line (%d)",
463 file.path(), nextObjectSubType, _options.subArchitecture());
464 }
465 }
466 break;
467 }
468 }
469 if ( dylibFile != NULL ) {
470 // update which form of ObjC dylibs are being linked
471 switch ( dylibFile->objCConstraint() ) {
472 case ld::File::objcConstraintNone:
473 break;
474 case ld::File::objcConstraintRetainRelease:
475 if ( _internal.objcDylibConstraint == ld::File::objcConstraintGC )
476 throwf("%s built with incompatible Garbage Collection settings to link with previous dylibs", file.path());
477 if ( _options.objcGcOnly() )
478 throwf("command line specified -objc_gc_only, but dylib is retain/release based: %s", file.path());
479 if ( _options.objcGc() )
480 throwf("command line specified -objc_gc, but dylib is retain/release based: %s", file.path());
481 if ( _options.targetIOSSimulator() )
482 warning("linking ObjC for iOS Simulator, but dylib (%s) was compiled for MacOSX", file.path());
483 _internal.objcDylibConstraint = ld::File::objcConstraintRetainRelease;
484 break;
485 case ld::File::objcConstraintRetainReleaseOrGC:
486 if ( _internal.objcDylibConstraint == ld::File::objcConstraintNone )
487 _internal.objcDylibConstraint = ld::File::objcConstraintRetainReleaseOrGC;
488 if ( _options.targetIOSSimulator() )
489 warning("linking ObjC for iOS Simulator, but dylib (%s) was compiled for MacOSX", file.path());
490 break;
491 case ld::File::objcConstraintGC:
492 if ( _internal.objcDylibConstraint == ld::File::objcConstraintRetainRelease )
493 throwf("%s built with incompatible Garbage Collection settings to link with previous dylibs", file.path());
494 if ( _options.targetIOSSimulator() )
495 warning("linking ObjC for iOS Simulator, but dylib (%s) was compiled for MacOSX", file.path());
496 _internal.objcDylibConstraint = ld::File::objcConstraintGC;
497 break;
498 case ld::File::objcConstraintRetainReleaseForSimulator:
499 if ( _internal.objcDylibConstraint == ld::File::objcConstraintNone )
500 _internal.objcDylibConstraint = ld::File::objcConstraintRetainReleaseForSimulator;
501 else if ( _internal.objcDylibConstraint != ld::File::objcConstraintRetainReleaseForSimulator ) {
502 warning("ObjC dylib (%s) was compiled for iOS Simulator, but dylibs others were compiled for MacOSX", file.path());
503 _internal.objcDylibConstraint = ld::File::objcConstraintRetainReleaseForSimulator;
504 }
505 break;
506 }
507 if ( _options.checkDylibsAreAppExtensionSafe() && !dylibFile->appExtensionSafe() ) {
508 warning("linking against dylib not safe for use in application extensions: %s", file.path());
509 }
510 const char* depInstallName = dylibFile->installPath();
511 // <rdar://problem/17229513> embedded frameworks are only supported on iOS 8 and later
512 if ( (depInstallName != NULL) && (depInstallName[0] != '/') ) {
513 if ( (_options.iOSVersionMin() != iOSVersionUnset) && (_options.iOSVersionMin() < iOS_8_0) ) {
514 // <rdar://problem/17598404> only warn about linking against embedded dylib if it is built for iOS 8 or later
515 if ( dylibFile->iOSMinVersion() >= iOS_8_0 )
516 throwf("embedded dylibs/frameworks are only supported on iOS 8.0 and later (%s)", depInstallName);
517 }
518 }
519 if ( _options.sharedRegionEligible() ) {
520 assert(depInstallName != NULL);
521 if ( depInstallName[0] == '@' )
522 warning("invalid -install_name (%s) in dependent dylib (%s). Dylibs/frameworks which might go in dyld shared cache "
523 "cannot link with dylib that uses @rpath, @loaderpath, etc.", depInstallName, dylibFile->path());
524 if ( (strncmp(depInstallName, "/usr/lib/", 9) != 0) && (strncmp(depInstallName, "/System/Library/", 16) != 0) )
525 warning("invalid -install_name (%s) in dependent dylib (%s). Dylibs/frameworks which might go in dyld shared cache "
526 "cannot link with dylibs that won't be in the shared cache", depInstallName, dylibFile->path());
527 }
528 }
529
530 }
531
532 void Resolver::doAtom(const ld::Atom& atom)
533 {
534 //fprintf(stderr, "Resolver::doAtom(%p), name=%s, sect=%s, scope=%d\n", &atom, atom.name(), atom.section().sectionName(), atom.scope());
535 if ( _ltoCodeGenFinished && (atom.contentType() == ld::Atom::typeLTOtemporary) && (atom.scope() != ld::Atom::scopeTranslationUnit) )
536 warning("'%s' is implemented in bitcode, but it was loaded too late", atom.name());
537
538 // add to list of known atoms
539 _atoms.push_back(&atom);
540
541 // adjust scope
542 if ( _options.hasExportRestrictList() || _options.hasReExportList() ) {
543 const char* name = atom.name();
544 switch ( atom.scope() ) {
545 case ld::Atom::scopeTranslationUnit:
546 break;
547 case ld::Atom::scopeLinkageUnit:
548 if ( _options.hasExportMaskList() && _options.shouldExport(name) ) {
549 // <rdar://problem/5062685> ld does not report error when -r is used and exported symbols are not defined.
550 if ( _options.outputKind() == Options::kObjectFile )
551 throwf("cannot export hidden symbol %s", name);
552 // .objc_class_name_* symbols are special
553 if ( atom.section().type() != ld::Section::typeObjC1Classes ) {
554 if ( atom.definition() == ld::Atom::definitionProxy ) {
555 // .exp file says to export a symbol, but that symbol is in some dylib being linked
556 if ( _options.canReExportSymbols() ) {
557 // marking proxy atom as global triggers the re-export
558 (const_cast<ld::Atom*>(&atom))->setScope(ld::Atom::scopeGlobal);
559 }
560 else if ( _options.outputKind() == Options::kDynamicLibrary ) {
561 if ( atom.file() != NULL )
562 warning("target OS does not support re-exporting symbol %s from %s\n", _options.demangleSymbol(name), atom.file()->path());
563 else
564 warning("target OS does not support re-exporting symbol %s\n", _options.demangleSymbol(name));
565 }
566 }
567 else {
568 if ( atom.file() != NULL )
569 warning("cannot export hidden symbol %s from %s", _options.demangleSymbol(name), atom.file()->path());
570 else
571 warning("cannot export hidden symbol %s", _options.demangleSymbol(name));
572 }
573 }
574 }
575 else if ( _options.shouldReExport(name) && _options.canReExportSymbols() ) {
576 if ( atom.definition() == ld::Atom::definitionProxy ) {
577 // marking proxy atom as global triggers the re-export
578 (const_cast<ld::Atom*>(&atom))->setScope(ld::Atom::scopeGlobal);
579 }
580 else {
581 throwf("requested re-export symbol %s is not from a dylib, but from %s\n", _options.demangleSymbol(name), atom.file()->path());
582 }
583 }
584 break;
585 case ld::Atom::scopeGlobal:
586 // check for globals that are downgraded to hidden
587 if ( ! _options.shouldExport(name) ) {
588 (const_cast<ld::Atom*>(&atom))->setScope(ld::Atom::scopeLinkageUnit);
589 //fprintf(stderr, "demote %s to hidden\n", name);
590 }
591 if ( _options.canReExportSymbols() && _options.shouldReExport(name) ) {
592 throwf("requested re-export symbol %s is not from a dylib, but from %s\n", _options.demangleSymbol(name), atom.file()->path());
593 }
594 break;
595 }
596 }
597
598 // work around for kernel that uses 'l' labels in assembly code
599 if ( (atom.symbolTableInclusion() == ld::Atom::symbolTableNotInFinalLinkedImages)
600 && (atom.name()[0] == 'l') && (_options.outputKind() == Options::kStaticExecutable)
601 && (strncmp(atom.name(), "ltmp", 4) != 0) )
602 (const_cast<ld::Atom*>(&atom))->setSymbolTableInclusion(ld::Atom::symbolTableIn);
603
604
605 // tell symbol table about non-static atoms
606 if ( atom.scope() != ld::Atom::scopeTranslationUnit ) {
607 _symbolTable.add(atom, _options.deadCodeStrip() && _completedInitialObjectFiles);
608
609 // add symbol aliases defined on the command line
610 if ( _options.haveCmdLineAliases() ) {
611 const std::vector<Options::AliasPair>& aliases = _options.cmdLineAliases();
612 for (std::vector<Options::AliasPair>::const_iterator it=aliases.begin(); it != aliases.end(); ++it) {
613 if ( strcmp(it->realName, atom.name()) == 0 ) {
614 const AliasAtom* alias = new AliasAtom(atom, it->alias);
615 _aliasesFromCmdLine.push_back(alias);
616 this->doAtom(*alias);
617 }
618 }
619 }
620 }
621
622 // convert references by-name or by-content to by-slot
623 this->convertReferencesToIndirect(atom);
624
625 // remember if any atoms are proxies that require LTO
626 if ( atom.contentType() == ld::Atom::typeLTOtemporary )
627 _haveLLVMObjs = true;
628
629 // remember if any atoms are aliases
630 if ( atom.section().type() == ld::Section::typeTempAlias )
631 _haveAliases = true;
632
633 if ( _options.deadCodeStrip() ) {
634 // add to set of dead-strip-roots, all symbols that the compiler marks as don't strip
635 if ( atom.dontDeadStrip() )
636 _deadStripRoots.insert(&atom);
637
638 if ( atom.scope() == ld::Atom::scopeGlobal ) {
639 // <rdar://problem/5524973> -exported_symbols_list that has wildcards and -dead_strip
640 // in dylibs, every global atom in initial .o files is a root
641 if ( _options.hasWildCardExportRestrictList() || _options.allGlobalsAreDeadStripRoots() ) {
642 if ( _options.shouldExport(atom.name()) )
643 _deadStripRoots.insert(&atom);
644 }
645 }
646 }
647 }
648
649 bool Resolver::isDtraceProbe(ld::Fixup::Kind kind)
650 {
651 switch (kind) {
652 case ld::Fixup::kindStoreX86DtraceCallSiteNop:
653 case ld::Fixup::kindStoreX86DtraceIsEnableSiteClear:
654 case ld::Fixup::kindStoreARMDtraceCallSiteNop:
655 case ld::Fixup::kindStoreARMDtraceIsEnableSiteClear:
656 case ld::Fixup::kindStoreARM64DtraceCallSiteNop:
657 case ld::Fixup::kindStoreARM64DtraceIsEnableSiteClear:
658 case ld::Fixup::kindStoreThumbDtraceCallSiteNop:
659 case ld::Fixup::kindStoreThumbDtraceIsEnableSiteClear:
660 case ld::Fixup::kindDtraceExtra:
661 return true;
662 default:
663 break;
664 }
665 return false;
666 }
667
668 void Resolver::convertReferencesToIndirect(const ld::Atom& atom)
669 {
670 // convert references by-name or by-content to by-slot
671 SymbolTable::IndirectBindingSlot slot;
672 const ld::Atom* dummy;
673 ld::Fixup::iterator end = atom.fixupsEnd();
674 for (ld::Fixup::iterator fit=atom.fixupsBegin(); fit != end; ++fit) {
675 if ( fit->kind == ld::Fixup::kindLinkerOptimizationHint )
676 _internal.someObjectHasOptimizationHints = true;
677 switch ( fit->binding ) {
678 case ld::Fixup::bindingByNameUnbound:
679 if ( isDtraceProbe(fit->kind) && (_options.outputKind() != Options::kObjectFile ) ) {
680 // in final linked images, remove reference
681 fit->binding = ld::Fixup::bindingNone;
682 }
683 else {
684 slot = _symbolTable.findSlotForName(fit->u.name);
685 fit->binding = ld::Fixup::bindingsIndirectlyBound;
686 fit->u.bindingIndex = slot;
687 }
688 break;
689 case ld::Fixup::bindingByContentBound:
690 switch ( fit->u.target->combine() ) {
691 case ld::Atom::combineNever:
692 case ld::Atom::combineByName:
693 assert(0 && "wrong combine type for bind by content");
694 break;
695 case ld::Atom::combineByNameAndContent:
696 slot = _symbolTable.findSlotForContent(fit->u.target, &dummy);
697 fit->binding = ld::Fixup::bindingsIndirectlyBound;
698 fit->u.bindingIndex = slot;
699 break;
700 case ld::Atom::combineByNameAndReferences:
701 slot = _symbolTable.findSlotForReferences(fit->u.target, &dummy);
702 fit->binding = ld::Fixup::bindingsIndirectlyBound;
703 fit->u.bindingIndex = slot;
704 break;
705 }
706 break;
707 case ld::Fixup::bindingNone:
708 case ld::Fixup::bindingDirectlyBound:
709 case ld::Fixup::bindingsIndirectlyBound:
710 break;
711 }
712 }
713 }
714
715
716 void Resolver::addInitialUndefines()
717 {
718 // add initial undefines from -u option
719 for (Options::UndefinesIterator it=_options.initialUndefinesBegin(); it != _options.initialUndefinesEnd(); ++it) {
720 _symbolTable.findSlotForName(*it);
721 }
722 }
723
724 void Resolver::resolveUndefines()
725 {
726 // keep looping until no more undefines were added in last loop
727 unsigned int undefineGenCount = 0xFFFFFFFF;
728 while ( undefineGenCount != _symbolTable.updateCount() ) {
729 undefineGenCount = _symbolTable.updateCount();
730 std::vector<const char*> undefineNames;
731 _symbolTable.undefines(undefineNames);
732 for(std::vector<const char*>::iterator it = undefineNames.begin(); it != undefineNames.end(); ++it) {
733 const char* undef = *it;
734 // load for previous undefine may also have loaded this undefine, so check again
735 if ( ! _symbolTable.hasName(undef) ) {
736 _inputFiles.searchLibraries(undef, true, true, false, *this);
737 if ( !_symbolTable.hasName(undef) && (_options.outputKind() != Options::kObjectFile) ) {
738 if ( strncmp(undef, "section$", 8) == 0 ) {
739 if ( strncmp(undef, "section$start$", 14) == 0 ) {
740 this->doAtom(*SectionBoundaryAtom::makeSectionBoundaryAtom(undef, true, &undef[14]));
741 }
742 else if ( strncmp(undef, "section$end$", 12) == 0 ) {
743 this->doAtom(*SectionBoundaryAtom::makeSectionBoundaryAtom(undef, false, &undef[12]));
744 }
745 }
746 else if ( strncmp(undef, "segment$", 8) == 0 ) {
747 if ( strncmp(undef, "segment$start$", 14) == 0 ) {
748 this->doAtom(*SegmentBoundaryAtom::makeSegmentBoundaryAtom(undef, true, &undef[14]));
749 }
750 else if ( strncmp(undef, "segment$end$", 12) == 0 ) {
751 this->doAtom(*SegmentBoundaryAtom::makeSegmentBoundaryAtom(undef, false, &undef[12]));
752 }
753 }
754 else if ( _options.outputKind() == Options::kPreload ) {
755 // for iBoot grandfather in old style section labels
756 int undefLen = strlen(undef);
757 if ( strcmp(&undef[undefLen-7], "__begin") == 0 ) {
758 if ( undefLen > 13 )
759 this->doAtom(*SectionBoundaryAtom::makeOldSectionBoundaryAtom(undef, true));
760 else
761 this->doAtom(*SegmentBoundaryAtom::makeOldSegmentBoundaryAtom(undef, true));
762 }
763 else if ( strcmp(&undef[undefLen-5], "__end") == 0 ) {
764 if ( undefLen > 11 )
765 this->doAtom(*SectionBoundaryAtom::makeOldSectionBoundaryAtom(undef, false));
766 else
767 this->doAtom(*SegmentBoundaryAtom::makeOldSegmentBoundaryAtom(undef, false));
768 }
769 }
770 }
771 }
772 }
773 // <rdar://problem/5894163> need to search archives for overrides of common symbols
774 if ( _symbolTable.hasExternalTentativeDefinitions() ) {
775 bool searchDylibs = (_options.commonsMode() == Options::kCommonsOverriddenByDylibs);
776 std::vector<const char*> tents;
777 _symbolTable.tentativeDefs(tents);
778 for(std::vector<const char*>::iterator it = tents.begin(); it != tents.end(); ++it) {
779 // load for previous tentative may also have loaded this tentative, so check again
780 const ld::Atom* curAtom = _symbolTable.atomForSlot(_symbolTable.findSlotForName(*it));
781 assert(curAtom != NULL);
782 if ( curAtom->definition() == ld::Atom::definitionTentative ) {
783 _inputFiles.searchLibraries(*it, searchDylibs, true, true, *this);
784 }
785 }
786 }
787 }
788
789 // Use linker options to resolve any remaining undefined symbols
790 if ( !_internal.linkerOptionLibraries.empty() || !_internal.linkerOptionFrameworks.empty() ) {
791 std::vector<const char*> undefineNames;
792 _symbolTable.undefines(undefineNames);
793 if ( undefineNames.size() != 0 ) {
794 for (std::vector<const char*>::iterator it = undefineNames.begin(); it != undefineNames.end(); ++it) {
795 const char* undef = *it;
796 if ( ! _symbolTable.hasName(undef) ) {
797 _inputFiles.searchLibraries(undef, true, true, false, *this);
798 }
799 }
800 }
801 }
802
803 // create proxies as needed for undefined symbols
804 if ( (_options.undefinedTreatment() != Options::kUndefinedError) || (_options.outputKind() == Options::kObjectFile) ) {
805 std::vector<const char*> undefineNames;
806 _symbolTable.undefines(undefineNames);
807 for(std::vector<const char*>::iterator it = undefineNames.begin(); it != undefineNames.end(); ++it) {
808 const char* undefName = *it;
809 // <rdar://problem/14547001> "ld -r -exported_symbol _foo" has wrong error message if _foo is undefined
810 bool makeProxy = true;
811 if ( (_options.outputKind() == Options::kObjectFile) && _options.hasExportMaskList() && _options.shouldExport(undefName) )
812 makeProxy = false;
813
814 if ( makeProxy )
815 this->doAtom(*new UndefinedProxyAtom(undefName));
816 }
817 }
818
819 // support -U option
820 if ( _options.someAllowedUndefines() ) {
821 std::vector<const char*> undefineNames;
822 _symbolTable.undefines(undefineNames);
823 for(std::vector<const char*>::iterator it = undefineNames.begin(); it != undefineNames.end(); ++it) {
824 if ( _options.allowedUndefined(*it) ) {
825 // make proxy
826 this->doAtom(*new UndefinedProxyAtom(*it));
827 }
828 }
829 }
830
831 }
832
833
834 void Resolver::markLive(const ld::Atom& atom, WhyLiveBackChain* previous)
835 {
836 //fprintf(stderr, "markLive(%p) %s\n", &atom, atom.name());
837 // if -why_live cares about this symbol, then dump chain
838 if ( (previous->referer != NULL) && _options.printWhyLive(atom.name()) ) {
839 fprintf(stderr, "%s from %s\n", atom.name(), atom.file()->path());
840 int depth = 1;
841 for(WhyLiveBackChain* p = previous; p != NULL; p = p->previous, ++depth) {
842 for(int i=depth; i > 0; --i)
843 fprintf(stderr, " ");
844 fprintf(stderr, "%s from %s\n", p->referer->name(), p->referer->file()->path());
845 }
846 }
847
848 // if already marked live, then done (stop recursion)
849 if ( atom.live() )
850 return;
851
852 // mark this atom is live
853 (const_cast<ld::Atom*>(&atom))->setLive();
854
855 // mark all atoms it references as live
856 WhyLiveBackChain thisChain;
857 thisChain.previous = previous;
858 thisChain.referer = &atom;
859 for (ld::Fixup::iterator fit = atom.fixupsBegin(), end=atom.fixupsEnd(); fit != end; ++fit) {
860 const ld::Atom* target;
861 switch ( fit->kind ) {
862 case ld::Fixup::kindNone:
863 case ld::Fixup::kindNoneFollowOn:
864 case ld::Fixup::kindNoneGroupSubordinate:
865 case ld::Fixup::kindNoneGroupSubordinateFDE:
866 case ld::Fixup::kindNoneGroupSubordinateLSDA:
867 case ld::Fixup::kindNoneGroupSubordinatePersonality:
868 case ld::Fixup::kindSetTargetAddress:
869 case ld::Fixup::kindSubtractTargetAddress:
870 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
871 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
872 case ld::Fixup::kindStoreTargetAddressBigEndian32:
873 case ld::Fixup::kindStoreTargetAddressBigEndian64:
874 case ld::Fixup::kindStoreTargetAddressX86PCRel32:
875 case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32:
876 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad:
877 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA:
878 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad:
879 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA:
880 case ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoad:
881 case ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoadNowLEA:
882 case ld::Fixup::kindStoreTargetAddressARMBranch24:
883 case ld::Fixup::kindStoreTargetAddressThumbBranch22:
884 #if SUPPORT_ARCH_arm64
885 case ld::Fixup::kindStoreTargetAddressARM64Branch26:
886 case ld::Fixup::kindStoreTargetAddressARM64Page21:
887 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
888 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21:
889 #endif
890 if ( fit->binding == ld::Fixup::bindingByContentBound ) {
891 // normally this was done in convertReferencesToIndirect()
892 // but a archive loaded .o file may have a forward reference
893 SymbolTable::IndirectBindingSlot slot;
894 const ld::Atom* dummy;
895 switch ( fit->u.target->combine() ) {
896 case ld::Atom::combineNever:
897 case ld::Atom::combineByName:
898 assert(0 && "wrong combine type for bind by content");
899 break;
900 case ld::Atom::combineByNameAndContent:
901 slot = _symbolTable.findSlotForContent(fit->u.target, &dummy);
902 fit->binding = ld::Fixup::bindingsIndirectlyBound;
903 fit->u.bindingIndex = slot;
904 break;
905 case ld::Atom::combineByNameAndReferences:
906 slot = _symbolTable.findSlotForReferences(fit->u.target, &dummy);
907 fit->binding = ld::Fixup::bindingsIndirectlyBound;
908 fit->u.bindingIndex = slot;
909 break;
910 }
911 }
912 switch ( fit->binding ) {
913 case ld::Fixup::bindingDirectlyBound:
914 markLive(*(fit->u.target), &thisChain);
915 break;
916 case ld::Fixup::bindingByNameUnbound:
917 // doAtom() did not convert to indirect in dead-strip mode, so that now
918 fit->u.bindingIndex = _symbolTable.findSlotForName(fit->u.name);
919 fit->binding = ld::Fixup::bindingsIndirectlyBound;
920 // fall into next case
921 case ld::Fixup::bindingsIndirectlyBound:
922 target = _internal.indirectBindingTable[fit->u.bindingIndex];
923 if ( target == NULL ) {
924 const char* targetName = _symbolTable.indirectName(fit->u.bindingIndex);
925 _inputFiles.searchLibraries(targetName, true, true, false, *this);
926 target = _internal.indirectBindingTable[fit->u.bindingIndex];
927 }
928 if ( target != NULL ) {
929 if ( target->definition() == ld::Atom::definitionTentative ) {
930 // <rdar://problem/5894163> need to search archives for overrides of common symbols
931 bool searchDylibs = (_options.commonsMode() == Options::kCommonsOverriddenByDylibs);
932 _inputFiles.searchLibraries(target->name(), searchDylibs, true, true, *this);
933 // recompute target since it may have been overridden by searchLibraries()
934 target = _internal.indirectBindingTable[fit->u.bindingIndex];
935 }
936 this->markLive(*target, &thisChain);
937 }
938 else {
939 _atomsWithUnresolvedReferences.push_back(&atom);
940 }
941 break;
942 default:
943 assert(0 && "bad binding during dead stripping");
944 }
945 break;
946 default:
947 break;
948 }
949 }
950
951 }
952
953 class NotLiveLTO {
954 public:
955 bool operator()(const ld::Atom* atom) const {
956 if (atom->live() || atom->dontDeadStrip() )
957 return false;
958 // don't kill combinable atoms in first pass
959 switch ( atom->combine() ) {
960 case ld::Atom::combineByNameAndContent:
961 case ld::Atom::combineByNameAndReferences:
962 return false;
963 default:
964 return true;
965 }
966 }
967 };
968
969 void Resolver::deadStripOptimize(bool force)
970 {
971 // only do this optimization with -dead_strip
972 if ( ! _options.deadCodeStrip() )
973 return;
974
975 // add entry point (main) to live roots
976 const ld::Atom* entry = this->entryPoint(true);
977 if ( entry != NULL )
978 _deadStripRoots.insert(entry);
979
980 // add -exported_symbols_list, -init, and -u entries to live roots
981 for (Options::UndefinesIterator uit=_options.initialUndefinesBegin(); uit != _options.initialUndefinesEnd(); ++uit) {
982 SymbolTable::IndirectBindingSlot slot = _symbolTable.findSlotForName(*uit);
983 if ( _internal.indirectBindingTable[slot] == NULL ) {
984 _inputFiles.searchLibraries(*uit, false, true, false, *this);
985 }
986 if ( _internal.indirectBindingTable[slot] != NULL )
987 _deadStripRoots.insert(_internal.indirectBindingTable[slot]);
988 }
989
990 // this helper is only referenced by synthesize stubs, assume it will be used
991 if ( _internal.classicBindingHelper != NULL )
992 _deadStripRoots.insert(_internal.classicBindingHelper);
993
994 // this helper is only referenced by synthesize stubs, assume it will be used
995 if ( _internal.compressedFastBinderProxy != NULL )
996 _deadStripRoots.insert(_internal.compressedFastBinderProxy);
997
998 // this helper is only referenced by synthesized lazy stubs, assume it will be used
999 if ( _internal.lazyBindingHelper != NULL )
1000 _deadStripRoots.insert(_internal.lazyBindingHelper);
1001
1002 // add all dont-dead-strip atoms as roots
1003 for (std::vector<const ld::Atom*>::const_iterator it=_atoms.begin(); it != _atoms.end(); ++it) {
1004 const ld::Atom* atom = *it;
1005 if ( atom->dontDeadStrip() ) {
1006 //fprintf(stderr, "dont dead strip: %p %s %s\n", atom, atom->section().sectionName(), atom->name());
1007 _deadStripRoots.insert(atom);
1008 // unset liveness, so markLive() will recurse
1009 (const_cast<ld::Atom*>(atom))->setLive(0);
1010 }
1011 }
1012
1013 // mark all roots as live, and all atoms they reference
1014 for (std::set<const ld::Atom*>::iterator it=_deadStripRoots.begin(); it != _deadStripRoots.end(); ++it) {
1015 WhyLiveBackChain rootChain;
1016 rootChain.previous = NULL;
1017 rootChain.referer = *it;
1018 this->markLive(**it, &rootChain);
1019 }
1020
1021 // now remove all non-live atoms from _atoms
1022 const bool log = false;
1023 if ( log ) {
1024 fprintf(stderr, "deadStripOptimize() all %ld atoms with liveness:\n", _atoms.size());
1025 for (std::vector<const ld::Atom*>::const_iterator it=_atoms.begin(); it != _atoms.end(); ++it) {
1026 const ld::File* file = (*it)->file();
1027 fprintf(stderr, " live=%d atom=%p name=%s from=%s\n", (*it)->live(), *it, (*it)->name(), (file ? file->path() : "<internal>"));
1028 }
1029 }
1030
1031 if ( _haveLLVMObjs && !force ) {
1032 // <rdar://problem/9777977> don't remove combinable atoms, they may come back in lto output
1033 _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(), NotLiveLTO()), _atoms.end());
1034 _symbolTable.removeDeadAtoms();
1035 }
1036 else {
1037 _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(), NotLive()), _atoms.end());
1038 }
1039
1040 if ( log ) {
1041 fprintf(stderr, "deadStripOptimize() %ld remaining atoms\n", _atoms.size());
1042 for (std::vector<const ld::Atom*>::const_iterator it=_atoms.begin(); it != _atoms.end(); ++it) {
1043 fprintf(stderr, " live=%d atom=%p name=%s\n", (*it)->live(), *it, (*it)->name());
1044 }
1045 }
1046 }
1047
1048
1049 // This is called when LTO is used but -dead_strip is not used.
1050 // Some undefines were eliminated by LTO, but others were not.
1051 void Resolver::remainingUndefines(std::vector<const char*>& undefs)
1052 {
1053 StringSet undefSet;
1054 // search all atoms for references that are unbound
1055 for (std::vector<const ld::Atom*>::const_iterator it=_atoms.begin(); it != _atoms.end(); ++it) {
1056 const ld::Atom* atom = *it;
1057 for (ld::Fixup::iterator fit=atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
1058 switch ( (ld::Fixup::TargetBinding)fit->binding ) {
1059 case ld::Fixup::bindingByNameUnbound:
1060 assert(0 && "should not be by-name this late");
1061 undefSet.insert(fit->u.name);
1062 break;
1063 case ld::Fixup::bindingsIndirectlyBound:
1064 if ( _internal.indirectBindingTable[fit->u.bindingIndex] == NULL ) {
1065 undefSet.insert(_symbolTable.indirectName(fit->u.bindingIndex));
1066 }
1067 break;
1068 case ld::Fixup::bindingByContentBound:
1069 case ld::Fixup::bindingNone:
1070 case ld::Fixup::bindingDirectlyBound:
1071 break;
1072 }
1073 }
1074 }
1075 // look for any initial undefines that are still undefined
1076 for (Options::UndefinesIterator uit=_options.initialUndefinesBegin(); uit != _options.initialUndefinesEnd(); ++uit) {
1077 if ( ! _symbolTable.hasName(*uit) ) {
1078 undefSet.insert(*uit);
1079 }
1080 }
1081
1082 // copy set to vector
1083 for (StringSet::const_iterator it=undefSet.begin(); it != undefSet.end(); ++it) {
1084 fprintf(stderr, "undef: %s\n", *it);
1085 undefs.push_back(*it);
1086 }
1087 }
1088
1089 void Resolver::liveUndefines(std::vector<const char*>& undefs)
1090 {
1091 StringSet undefSet;
1092 // search all live atoms for references that are unbound
1093 for (std::vector<const ld::Atom*>::const_iterator it=_atoms.begin(); it != _atoms.end(); ++it) {
1094 const ld::Atom* atom = *it;
1095 if ( ! atom->live() )
1096 continue;
1097 for (ld::Fixup::iterator fit=atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
1098 switch ( (ld::Fixup::TargetBinding)fit->binding ) {
1099 case ld::Fixup::bindingByNameUnbound:
1100 assert(0 && "should not be by-name this late");
1101 undefSet.insert(fit->u.name);
1102 break;
1103 case ld::Fixup::bindingsIndirectlyBound:
1104 if ( _internal.indirectBindingTable[fit->u.bindingIndex] == NULL ) {
1105 undefSet.insert(_symbolTable.indirectName(fit->u.bindingIndex));
1106 }
1107 break;
1108 case ld::Fixup::bindingByContentBound:
1109 case ld::Fixup::bindingNone:
1110 case ld::Fixup::bindingDirectlyBound:
1111 break;
1112 }
1113 }
1114 }
1115 // look for any initial undefines that are still undefined
1116 for (Options::UndefinesIterator uit=_options.initialUndefinesBegin(); uit != _options.initialUndefinesEnd(); ++uit) {
1117 if ( ! _symbolTable.hasName(*uit) ) {
1118 undefSet.insert(*uit);
1119 }
1120 }
1121
1122 // copy set to vector
1123 for (StringSet::const_iterator it=undefSet.begin(); it != undefSet.end(); ++it) {
1124 undefs.push_back(*it);
1125 }
1126 }
1127
1128
1129
1130 // <rdar://problem/8252819> warn when .objc_class_name_* symbol missing
1131 class ExportedObjcClass
1132 {
1133 public:
1134 ExportedObjcClass(const Options& opt) : _options(opt) {}
1135
1136 bool operator()(const char* name) const {
1137 if ( (strncmp(name, ".objc_class_name_", 17) == 0) && _options.shouldExport(name) ) {
1138 warning("ignoring undefined symbol %s from -exported_symbols_list", name);
1139 return true;
1140 }
1141 const char* s = strstr(name, "CLASS_$_");
1142 if ( s != NULL ) {
1143 char temp[strlen(name)+16];
1144 strcpy(temp, ".objc_class_name_");
1145 strcat(temp, &s[8]);
1146 if ( _options.wasRemovedExport(temp) ) {
1147 warning("ignoring undefined symbol %s from -exported_symbols_list", temp);
1148 return true;
1149 }
1150 }
1151 return false;
1152 }
1153 private:
1154 const Options& _options;
1155 };
1156
1157
1158 // temp hack for undefined aliases
1159 class UndefinedAlias
1160 {
1161 public:
1162 UndefinedAlias(const Options& opt) : _aliases(opt.cmdLineAliases()) {}
1163
1164 bool operator()(const char* name) const {
1165 for (std::vector<Options::AliasPair>::const_iterator it=_aliases.begin(); it != _aliases.end(); ++it) {
1166 if ( strcmp(it->realName, name) == 0 ) {
1167 warning("undefined base symbol '%s' for alias '%s'", name, it->alias);
1168 return true;
1169 }
1170 }
1171 return false;
1172 }
1173 private:
1174 const std::vector<Options::AliasPair>& _aliases;
1175 };
1176
1177
1178
1179 static const char* pathLeafName(const char* path)
1180 {
1181 const char* shortPath = strrchr(path, '/');
1182 if ( shortPath == NULL )
1183 return path;
1184 else
1185 return &shortPath[1];
1186 }
1187
1188 bool Resolver::printReferencedBy(const char* name, SymbolTable::IndirectBindingSlot slot)
1189 {
1190 unsigned foundReferenceCount = 0;
1191 for (std::vector<const ld::Atom*>::const_iterator it=_atoms.begin(); it != _atoms.end(); ++it) {
1192 const ld::Atom* atom = *it;
1193 for (ld::Fixup::iterator fit=atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
1194 if ( fit->binding == ld::Fixup::bindingsIndirectlyBound ) {
1195 if ( fit->u.bindingIndex == slot ) {
1196 if ( atom->contentType() == ld::Atom::typeNonLazyPointer ) {
1197 const ld::Atom* existingAtom;
1198 unsigned int nlSlot = _symbolTable.findSlotForReferences(atom, &existingAtom);
1199 if ( printReferencedBy(name, nlSlot) )
1200 ++foundReferenceCount;
1201 }
1202 else if ( atom->contentType() == ld::Atom::typeCFI ) {
1203 fprintf(stderr, " Dwarf Exception Unwind Info (__eh_frame) in %s\n", pathLeafName(atom->file()->path()));
1204 ++foundReferenceCount;
1205 }
1206 else {
1207 fprintf(stderr, " %s in %s\n", _options.demangleSymbol(atom->name()), pathLeafName(atom->file()->path()));
1208 ++foundReferenceCount;
1209 break; // if undefined used twice in a function, only show first
1210 }
1211 }
1212 }
1213 }
1214 if ( foundReferenceCount > 6 ) {
1215 fprintf(stderr, " ...\n");
1216 break; // only show first six uses of undefined symbol
1217 }
1218 }
1219 return (foundReferenceCount != 0);
1220 }
1221
1222 void Resolver::checkUndefines(bool force)
1223 {
1224 // when using LTO, undefines are checked after bitcode is optimized
1225 if ( _haveLLVMObjs && !force )
1226 return;
1227
1228 // error out on any remaining undefines
1229 bool doPrint = true;
1230 bool doError = true;
1231 switch ( _options.undefinedTreatment() ) {
1232 case Options::kUndefinedError:
1233 break;
1234 case Options::kUndefinedDynamicLookup:
1235 doError = false;
1236 break;
1237 case Options::kUndefinedWarning:
1238 doError = false;
1239 break;
1240 case Options::kUndefinedSuppress:
1241 doError = false;
1242 doPrint = false;
1243 break;
1244 }
1245 std::vector<const char*> unresolvableUndefines;
1246 if ( _options.deadCodeStrip() )
1247 this->liveUndefines(unresolvableUndefines);
1248 else if( _haveLLVMObjs )
1249 this->remainingUndefines(unresolvableUndefines); // <rdar://problem/10052396> LTO may have eliminated need for some undefines
1250 else
1251 _symbolTable.undefines(unresolvableUndefines);
1252
1253 // <rdar://problem/8252819> assert when .objc_class_name_* symbol missing
1254 if ( _options.hasExportMaskList() ) {
1255 unresolvableUndefines.erase(std::remove_if(unresolvableUndefines.begin(), unresolvableUndefines.end(), ExportedObjcClass(_options)), unresolvableUndefines.end());
1256 }
1257
1258 // hack to temporarily make missing aliases a warning
1259 if ( _options.haveCmdLineAliases() ) {
1260 unresolvableUndefines.erase(std::remove_if(unresolvableUndefines.begin(), unresolvableUndefines.end(), UndefinedAlias(_options)), unresolvableUndefines.end());
1261 }
1262
1263 const int unresolvableCount = unresolvableUndefines.size();
1264 int unresolvableExportsCount = 0;
1265 if ( unresolvableCount != 0 ) {
1266 if ( doPrint ) {
1267 if ( _options.printArchPrefix() )
1268 fprintf(stderr, "Undefined symbols for architecture %s:\n", _options.architectureName());
1269 else
1270 fprintf(stderr, "Undefined symbols:\n");
1271 for (int i=0; i < unresolvableCount; ++i) {
1272 const char* name = unresolvableUndefines[i];
1273 unsigned int slot = _symbolTable.findSlotForName(name);
1274 fprintf(stderr, " \"%s\", referenced from:\n", _options.demangleSymbol(name));
1275 // scan all atoms for references
1276 bool foundAtomReference = printReferencedBy(name, slot);
1277 // scan command line options
1278 if ( !foundAtomReference ) {
1279 // might be from -init command line option
1280 if ( (_options.initFunctionName() != NULL) && (strcmp(name, _options.initFunctionName()) == 0) ) {
1281 fprintf(stderr, " -init command line option\n");
1282 }
1283 // or might be from exported symbol option
1284 else if ( _options.hasExportMaskList() && _options.shouldExport(name) ) {
1285 fprintf(stderr, " -exported_symbol[s_list] command line option\n");
1286 }
1287 // or might be from re-exported symbol option
1288 else if ( _options.hasReExportList() && _options.shouldReExport(name) ) {
1289 fprintf(stderr, " -reexported_symbols_list command line option\n");
1290 }
1291 else if ( (_options.outputKind() == Options::kDynamicExecutable)
1292 && (_options.entryName() != NULL) && (strcmp(name, _options.entryName()) == 0) ) {
1293 fprintf(stderr, " implicit entry/start for main executable\n");
1294 }
1295 else {
1296 bool isInitialUndefine = false;
1297 for (Options::UndefinesIterator uit=_options.initialUndefinesBegin(); uit != _options.initialUndefinesEnd(); ++uit) {
1298 if ( strcmp(*uit, name) == 0 ) {
1299 isInitialUndefine = true;
1300 break;
1301 }
1302 }
1303 if ( isInitialUndefine )
1304 fprintf(stderr, " -u command line option\n");
1305 }
1306 ++unresolvableExportsCount;
1307 }
1308 // be helpful and check for typos
1309 bool printedStart = false;
1310 for (SymbolTable::byNameIterator sit=_symbolTable.begin(); sit != _symbolTable.end(); sit++) {
1311 const ld::Atom* atom = *sit;
1312 if ( (atom != NULL) && (atom->symbolTableInclusion() == ld::Atom::symbolTableIn) && (strstr(atom->name(), name) != NULL) ) {
1313 if ( ! printedStart ) {
1314 fprintf(stderr, " (maybe you meant: %s", atom->name());
1315 printedStart = true;
1316 }
1317 else {
1318 fprintf(stderr, ", %s ", atom->name());
1319 }
1320 }
1321 }
1322 if ( printedStart )
1323 fprintf(stderr, ")\n");
1324 // <rdar://problem/8989530> Add comment to error message when __ZTV symbols are undefined
1325 if ( strncmp(name, "__ZTV", 5) == 0 ) {
1326 fprintf(stderr, " NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.\n");
1327 }
1328 }
1329 }
1330 if ( doError )
1331 throw "symbol(s) not found";
1332 }
1333
1334 }
1335
1336
1337
1338 void Resolver::checkDylibSymbolCollisions()
1339 {
1340 for (SymbolTable::byNameIterator it=_symbolTable.begin(); it != _symbolTable.end(); it++) {
1341 const ld::Atom* atom = *it;
1342 if ( atom == NULL )
1343 continue;
1344 if ( atom->scope() == ld::Atom::scopeGlobal ) {
1345 // <rdar://problem/5048861> No warning about tentative definition conflicting with dylib definition
1346 // for each tentative definition in symbol table look for dylib that exports same symbol name
1347 if ( atom->definition() == ld::Atom::definitionTentative ) {
1348 _inputFiles.searchLibraries(atom->name(), true, false, false, *this);
1349 }
1350 // record any overrides of weak symbols in any linked dylib
1351 if ( (atom->definition() == ld::Atom::definitionRegular) && (atom->symbolTableInclusion() == ld::Atom::symbolTableIn) ) {
1352 if ( _inputFiles.searchWeakDefInDylib(atom->name()) )
1353 (const_cast<ld::Atom*>(atom))->setOverridesDylibsWeakDef();
1354 }
1355 }
1356 }
1357 }
1358
1359
1360 const ld::Atom* Resolver::entryPoint(bool searchArchives)
1361 {
1362 const char* symbolName = NULL;
1363 bool makingDylib = false;
1364 switch ( _options.outputKind() ) {
1365 case Options::kDynamicExecutable:
1366 case Options::kStaticExecutable:
1367 case Options::kDyld:
1368 case Options::kPreload:
1369 symbolName = _options.entryName();
1370 break;
1371 case Options::kDynamicLibrary:
1372 symbolName = _options.initFunctionName();
1373 makingDylib = true;
1374 break;
1375 case Options::kObjectFile:
1376 case Options::kDynamicBundle:
1377 case Options::kKextBundle:
1378 return NULL;
1379 break;
1380 }
1381 if ( symbolName != NULL ) {
1382 SymbolTable::IndirectBindingSlot slot = _symbolTable.findSlotForName(symbolName);
1383 if ( (_internal.indirectBindingTable[slot] == NULL) && searchArchives ) {
1384 // <rdar://problem/7043256> ld64 can not find a -e entry point from an archive
1385 _inputFiles.searchLibraries(symbolName, false, true, false, *this);
1386 }
1387 if ( _internal.indirectBindingTable[slot] == NULL ) {
1388 if ( strcmp(symbolName, "start") == 0 )
1389 throwf("entry point (%s) undefined. Usually in crt1.o", symbolName);
1390 else
1391 throwf("entry point (%s) undefined.", symbolName);
1392 }
1393 else if ( _internal.indirectBindingTable[slot]->definition() == ld::Atom::definitionProxy ) {
1394 if ( makingDylib )
1395 throwf("-init function (%s) found in linked dylib, must be in dylib being linked", symbolName);
1396 }
1397 return _internal.indirectBindingTable[slot];
1398 }
1399 return NULL;
1400 }
1401
1402
1403 void Resolver::fillInHelpersInInternalState()
1404 {
1405 // look up well known atoms
1406 bool needsStubHelper = true;
1407 switch ( _options.outputKind() ) {
1408 case Options::kDynamicExecutable:
1409 case Options::kDynamicLibrary:
1410 case Options::kDynamicBundle:
1411 needsStubHelper = true;
1412 break;
1413 case Options::kDyld:
1414 case Options::kKextBundle:
1415 case Options::kObjectFile:
1416 case Options::kStaticExecutable:
1417 case Options::kPreload:
1418 needsStubHelper = false;
1419 break;
1420 }
1421
1422 _internal.classicBindingHelper = NULL;
1423 if ( needsStubHelper && !_options.makeCompressedDyldInfo() ) {
1424 // "dyld_stub_binding_helper" comes from .o file, so should already exist in symbol table
1425 if ( _symbolTable.hasName("dyld_stub_binding_helper") ) {
1426 SymbolTable::IndirectBindingSlot slot = _symbolTable.findSlotForName("dyld_stub_binding_helper");
1427 _internal.classicBindingHelper = _internal.indirectBindingTable[slot];
1428 }
1429 }
1430
1431 _internal.lazyBindingHelper = NULL;
1432 if ( _options.usingLazyDylibLinking() ) {
1433 // "dyld_lazy_dylib_stub_binding_helper" comes from lazydylib1.o file, so should already exist in symbol table
1434 if ( _symbolTable.hasName("dyld_lazy_dylib_stub_binding_helper") ) {
1435 SymbolTable::IndirectBindingSlot slot = _symbolTable.findSlotForName("dyld_lazy_dylib_stub_binding_helper");
1436 _internal.lazyBindingHelper = _internal.indirectBindingTable[slot];
1437 }
1438 if ( _internal.lazyBindingHelper == NULL )
1439 throw "symbol dyld_lazy_dylib_stub_binding_helper not defined (usually in lazydylib1.o)";
1440 }
1441
1442 _internal.compressedFastBinderProxy = NULL;
1443 if ( needsStubHelper && _options.makeCompressedDyldInfo() ) {
1444 // "dyld_stub_binder" comes from libSystem.dylib so will need to manually resolve
1445 if ( !_symbolTable.hasName("dyld_stub_binder") ) {
1446 _inputFiles.searchLibraries("dyld_stub_binder", true, false, false, *this);
1447 }
1448 if ( _symbolTable.hasName("dyld_stub_binder") ) {
1449 SymbolTable::IndirectBindingSlot slot = _symbolTable.findSlotForName("dyld_stub_binder");
1450 _internal.compressedFastBinderProxy = _internal.indirectBindingTable[slot];
1451 }
1452 if ( _internal.compressedFastBinderProxy == NULL ) {
1453 if ( _options.undefinedTreatment() != Options::kUndefinedError ) {
1454 // make proxy
1455 _internal.compressedFastBinderProxy = new UndefinedProxyAtom("dyld_stub_binder");
1456 this->doAtom(*_internal.compressedFastBinderProxy);
1457 }
1458 }
1459 }
1460 }
1461
1462
1463 void Resolver::fillInInternalState()
1464 {
1465 // store atoms into their final section
1466 for (std::vector<const ld::Atom*>::iterator it = _atoms.begin(); it != _atoms.end(); ++it) {
1467 _internal.addAtom(**it);
1468 }
1469
1470 // <rdar://problem/7783918> make sure there is a __text section so that codesigning works
1471 if ( (_options.outputKind() == Options::kDynamicLibrary) || (_options.outputKind() == Options::kDynamicBundle) )
1472 _internal.getFinalSection(*new ld::Section("__TEXT", "__text", ld::Section::typeCode));
1473 }
1474
1475 void Resolver::fillInEntryPoint()
1476 {
1477 _internal.entryPoint = this->entryPoint(true);
1478 }
1479
1480 void Resolver::syncAliases()
1481 {
1482 if ( !_haveAliases || (_options.outputKind() == Options::kObjectFile) )
1483 return;
1484
1485 // Set attributes of alias to match its found target
1486 for (std::vector<const ld::Atom*>::iterator it = _atoms.begin(); it != _atoms.end(); ++it) {
1487 const ld::Atom* atom = *it;
1488 if ( atom->section().type() == ld::Section::typeTempAlias ) {
1489 assert(atom->fixupsBegin() != atom->fixupsEnd());
1490 for (ld::Fixup::iterator fit = atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
1491 const ld::Atom* target;
1492 ld::Atom::Scope scope;
1493 assert(fit->kind == ld::Fixup::kindNoneFollowOn);
1494 switch ( fit->binding ) {
1495 case ld::Fixup::bindingByNameUnbound:
1496 break;
1497 case ld::Fixup::bindingsIndirectlyBound:
1498 target = _internal.indirectBindingTable[fit->u.bindingIndex];
1499 assert(target != NULL);
1500 scope = atom->scope();
1501 (const_cast<Atom*>(atom))->setAttributesFromAtom(*target);
1502 // alias has same attributes as target, except for scope
1503 (const_cast<Atom*>(atom))->setScope(scope);
1504 break;
1505 default:
1506 assert(0 && "internal error: unexpected alias binding");
1507 }
1508 }
1509 }
1510 }
1511 }
1512
1513 void Resolver::removeCoalescedAwayAtoms()
1514 {
1515 const bool log = false;
1516 if ( log ) {
1517 fprintf(stderr, "removeCoalescedAwayAtoms() starts with %lu atoms\n", _atoms.size());
1518 }
1519 _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(), AtomCoalescedAway()), _atoms.end());
1520 if ( log ) {
1521 fprintf(stderr, "removeCoalescedAwayAtoms() after removing coalesced atoms, %lu remain\n", _atoms.size());
1522 for (std::vector<const ld::Atom*>::const_iterator it=_atoms.begin(); it != _atoms.end(); ++it) {
1523 fprintf(stderr, " atom=%p %s\n", *it, (*it)->name());
1524 }
1525 }
1526 }
1527
1528 void Resolver::linkTimeOptimize()
1529 {
1530 // only do work here if some llvm obj files where loaded
1531 if ( ! _haveLLVMObjs )
1532 return;
1533
1534 // <rdar://problem/15314161> LTO: Symbol multiply defined error should specify exactly where the symbol is found
1535 _symbolTable.checkDuplicateSymbols();
1536
1537 // run LLVM lto code-gen
1538 lto::OptimizeOptions optOpt;
1539 optOpt.outputFilePath = _options.outputFilePath();
1540 optOpt.tmpObjectFilePath = _options.tempLtoObjectPath();
1541 optOpt.preserveAllGlobals = _options.allGlobalsAreDeadStripRoots() || _options.hasExportRestrictList();
1542 optOpt.verbose = _options.verbose();
1543 optOpt.saveTemps = _options.saveTempFiles();
1544 optOpt.pie = _options.positionIndependentExecutable();
1545 optOpt.mainExecutable = _options.linkingMainExecutable();;
1546 optOpt.staticExecutable = (_options.outputKind() == Options::kStaticExecutable);
1547 optOpt.relocatable = (_options.outputKind() == Options::kObjectFile);
1548 optOpt.allowTextRelocs = _options.allowTextRelocs();
1549 optOpt.linkerDeadStripping = _options.deadCodeStrip();
1550 optOpt.needsUnwindInfoSection = _options.needsUnwindInfoSection();
1551 optOpt.keepDwarfUnwind = _options.keepDwarfUnwind();
1552 optOpt.verboseOptimizationHints = _options.verboseOptimizationHints();
1553 optOpt.arch = _options.architecture();
1554 optOpt.mcpu = _options.mcpuLTO();
1555 optOpt.llvmOptions = &_options.llvmOptions();
1556 optOpt.initialUndefines = &_options.initialUndefines();
1557
1558 std::vector<const ld::Atom*> newAtoms;
1559 std::vector<const char*> additionalUndefines;
1560 if ( ! lto::optimize(_atoms, _internal, optOpt, *this, newAtoms, additionalUndefines) )
1561 return; // if nothing done
1562 _ltoCodeGenFinished = true;
1563
1564 // add all newly created atoms to _atoms and update symbol table
1565 for(std::vector<const ld::Atom*>::iterator it = newAtoms.begin(); it != newAtoms.end(); ++it)
1566 this->doAtom(**it);
1567
1568 // some atoms might have been optimized way (marked coalesced), remove them
1569 this->removeCoalescedAwayAtoms();
1570
1571 // run through all atoms again and make sure newly codegened atoms have references bound
1572 for (std::vector<const ld::Atom*>::const_iterator it=_atoms.begin(); it != _atoms.end(); ++it)
1573 this->convertReferencesToIndirect(**it);
1574
1575 // adjust section of any new
1576 for (std::vector<const AliasAtom*>::const_iterator it=_aliasesFromCmdLine.begin(); it != _aliasesFromCmdLine.end(); ++it) {
1577 const AliasAtom* aliasAtom = *it;
1578 // update fields in AliasAtom to match newly constructed mach-o atom
1579 aliasAtom->setFinalAliasOf();
1580 }
1581
1582 // <rdar://problem/14609792> add any auto-link libraries requested by LTO output to dylibs to search
1583 _inputFiles.addLinkerOptionLibraries(_internal, *this);
1584 _inputFiles.createIndirectDylibs();
1585
1586 // resolve new undefines (e.g calls to _malloc and _memcpy that llvm compiler conjures up)
1587 for(std::vector<const char*>::iterator uit = additionalUndefines.begin(); uit != additionalUndefines.end(); ++uit) {
1588 const char *targetName = *uit;
1589 // these symbols may or may not already be in linker's symbol table
1590 if ( ! _symbolTable.hasName(targetName) ) {
1591 _inputFiles.searchLibraries(targetName, true, true, false, *this);
1592 }
1593 }
1594
1595 // if -dead_strip on command line
1596 if ( _options.deadCodeStrip() ) {
1597 // clear liveness bit
1598 for (std::vector<const ld::Atom*>::const_iterator it=_atoms.begin(); it != _atoms.end(); ++it) {
1599 (const_cast<ld::Atom*>(*it))->setLive((*it)->dontDeadStrip());
1600 }
1601 // and re-compute dead code
1602 this->deadStripOptimize(true);
1603 }
1604
1605 // <rdar://problem/12386559> if -exported_symbols_list on command line, re-force scope
1606 if ( _options.hasExportMaskList() ) {
1607 for (std::vector<const ld::Atom*>::const_iterator it=_atoms.begin(); it != _atoms.end(); ++it) {
1608 const ld::Atom* atom = *it;
1609 if ( atom->scope() == ld::Atom::scopeGlobal ) {
1610 if ( !_options.shouldExport(atom->name()) ) {
1611 (const_cast<ld::Atom*>(atom))->setScope(ld::Atom::scopeLinkageUnit);
1612 }
1613 }
1614 }
1615 }
1616
1617 if ( _options.outputKind() == Options::kObjectFile ) {
1618 // if -r mode, add proxies for new undefines (e.g. ___stack_chk_fail)
1619 this->resolveUndefines();
1620 }
1621 else {
1622 // last chance to check for undefines
1623 this->resolveUndefines();
1624 this->checkUndefines(true);
1625
1626 // check new code does not override some dylib
1627 this->checkDylibSymbolCollisions();
1628 }
1629 }
1630
1631
1632 void Resolver::tweakWeakness()
1633 {
1634 // <rdar://problem/7977374> Add command line options to control symbol weak-def bit on exported symbols
1635 if ( _options.hasWeakBitTweaks() ) {
1636 for (std::vector<ld::Internal::FinalSection*>::iterator sit = _internal.sections.begin(); sit != _internal.sections.end(); ++sit) {
1637 ld::Internal::FinalSection* sect = *sit;
1638 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
1639 const ld::Atom* atom = *ait;
1640 if ( atom->definition() != ld::Atom::definitionRegular )
1641 continue;
1642 const char* name = atom->name();
1643 if ( atom->scope() == ld::Atom::scopeGlobal ) {
1644 if ( atom->combine() == ld::Atom::combineNever ) {
1645 if ( _options.forceWeak(name) )
1646 (const_cast<ld::Atom*>(atom))->setCombine(ld::Atom::combineByName);
1647 }
1648 else if ( atom->combine() == ld::Atom::combineByName ) {
1649 if ( _options.forceNotWeak(name) )
1650 (const_cast<ld::Atom*>(atom))->setCombine(ld::Atom::combineNever);
1651 }
1652 }
1653 else {
1654 if ( _options.forceWeakNonWildCard(name) )
1655 warning("cannot force to be weak, non-external symbol %s", name);
1656 else if ( _options.forceNotWeakNonWildcard(name) )
1657 warning("cannot force to be not-weak, non-external symbol %s", name);
1658 }
1659 }
1660 }
1661 }
1662 }
1663
1664 void Resolver::dumpAtoms()
1665 {
1666 fprintf(stderr, "Resolver all atoms:\n");
1667 for (std::vector<const ld::Atom*>::const_iterator it=_atoms.begin(); it != _atoms.end(); ++it) {
1668 const ld::Atom* atom = *it;
1669 fprintf(stderr, " %p name=%s, def=%d\n", atom, atom->name(), atom->definition());
1670 }
1671 }
1672
1673 void Resolver::resolve()
1674 {
1675 this->initializeState();
1676 this->buildAtomList();
1677 this->addInitialUndefines();
1678 this->fillInHelpersInInternalState();
1679 this->resolveUndefines();
1680 this->deadStripOptimize();
1681 this->checkUndefines();
1682 this->checkDylibSymbolCollisions();
1683 this->syncAliases();
1684 this->removeCoalescedAwayAtoms();
1685 this->fillInEntryPoint();
1686 this->linkTimeOptimize();
1687 this->fillInInternalState();
1688 this->tweakWeakness();
1689 _symbolTable.checkDuplicateSymbols();
1690 }
1691
1692
1693
1694 } // namespace tool
1695 } // namespace ld
1696
1697
1698