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