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