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