]> git.saurik.com Git - apple/ld64.git/blame - src/ld/OutputFile.cpp
ld64-236.3.tar.gz
[apple/ld64.git] / src / ld / OutputFile.cpp
CommitLineData
a645023d
A
1/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-*
2 *
afe874b1 3 * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
a645023d
A
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>
d425e388
A
31#include <sys/param.h>
32#include <sys/mount.h>
a645023d
A
33#include <fcntl.h>
34#include <errno.h>
35#include <limits.h>
36#include <unistd.h>
37#include <mach/mach_time.h>
38#include <mach/vm_statistics.h>
39#include <mach/mach_init.h>
40#include <mach/mach_host.h>
41#include <uuid/uuid.h>
42#include <dlfcn.h>
43#include <mach-o/dyld.h>
44#include <mach-o/fat.h>
45
46#include <string>
47#include <map>
48#include <set>
49#include <string>
50#include <vector>
51#include <list>
52#include <algorithm>
d425e388 53#include <unordered_set>
a645023d
A
54
55#include <CommonCrypto/CommonDigest.h>
56#include <AvailabilityMacros.h>
57
58#include "MachOTrie.hpp"
59
60#include "Options.h"
61
62#include "OutputFile.h"
63#include "Architectures.hpp"
64#include "HeaderAndLoadCommands.hpp"
65#include "LinkEdit.hpp"
66#include "LinkEditClassic.hpp"
67
68
69namespace ld {
70namespace tool {
71
9543cb2f
A
72uint32_t sAdrpNA = 0;
73uint32_t sAdrpNoped = 0;
74uint32_t sAdrpNotNoped = 0;
75
a645023d
A
76
77OutputFile::OutputFile(const Options& opts)
78 :
9543cb2f
A
79 usesWeakExternalSymbols(false), overridesWeakExternalSymbols(false),
80 _noReExportedDylibs(false), pieDisabled(false), hasDataInCode(false),
a645023d
A
81 headerAndLoadCommandsSection(NULL),
82 rebaseSection(NULL), bindingSection(NULL), weakBindingSection(NULL),
83 lazyBindingSection(NULL), exportSection(NULL),
84 splitSegInfoSection(NULL), functionStartsSection(NULL),
9543cb2f 85 dataInCodeSection(NULL), optimizationHintsSection(NULL), dependentDRsSection(NULL),
a645023d
A
86 symbolTableSection(NULL), stringPoolSection(NULL),
87 localRelocationsSection(NULL), externalRelocationsSection(NULL),
88 sectionRelocationsSection(NULL),
89 indirectSymbolTableSection(NULL),
90 _options(opts),
91 _hasDyldInfo(opts.makeCompressedDyldInfo()),
92 _hasSymbolTable(true),
93 _hasSectionRelocations(opts.outputKind() == Options::kObjectFile),
94 _hasSplitSegInfo(opts.sharedRegionEligible()),
95 _hasFunctionStartsInfo(opts.addFunctionStarts()),
ebf6f434
A
96 _hasDataInCodeInfo(opts.addDataInCodeInfo()),
97 _hasDependentDRInfo(opts.needsDependentDRInfo()),
a645023d
A
98 _hasDynamicSymbolTable(true),
99 _hasLocalRelocations(!opts.makeCompressedDyldInfo()),
100 _hasExternalRelocations(!opts.makeCompressedDyldInfo()),
9543cb2f 101 _hasOptimizationHints(opts.outputKind() == Options::kObjectFile),
a645023d
A
102 _encryptedTEXTstartOffset(0),
103 _encryptedTEXTendOffset(0),
104 _localSymbolsStartIndex(0),
105 _localSymbolsCount(0),
106 _globalSymbolsStartIndex(0),
107 _globalSymbolsCount(0),
108 _importSymbolsStartIndex(0),
109 _importSymbolsCount(0),
110 _sectionsRelocationsAtom(NULL),
111 _localRelocsAtom(NULL),
112 _externalRelocsAtom(NULL),
113 _symbolTableAtom(NULL),
114 _indirectSymbolTableAtom(NULL),
115 _rebasingInfoAtom(NULL),
116 _bindingInfoAtom(NULL),
117 _lazyBindingInfoAtom(NULL),
118 _weakBindingInfoAtom(NULL),
119 _exportInfoAtom(NULL),
120 _splitSegInfoAtom(NULL),
ebf6f434
A
121 _functionStartsAtom(NULL),
122 _dataInCodeAtom(NULL),
9543cb2f
A
123 _dependentDRInfoAtom(NULL),
124 _optimizationHintsAtom(NULL)
a645023d
A
125{
126}
127
128void OutputFile::dumpAtomsBySection(ld::Internal& state, bool printAtoms)
129{
130 fprintf(stderr, "SORTED:\n");
131 for (std::vector<ld::Internal::FinalSection*>::iterator it = state.sections.begin(); it != state.sections.end(); ++it) {
132 fprintf(stderr, "final section %p %s/%s %s start addr=0x%08llX, size=0x%08llX, alignment=%02d, fileOffset=0x%08llX\n",
133 (*it), (*it)->segmentName(), (*it)->sectionName(), (*it)->isSectionHidden() ? "(hidden)" : "",
134 (*it)->address, (*it)->size, (*it)->alignment, (*it)->fileOffset);
135 if ( printAtoms ) {
136 std::vector<const ld::Atom*>& atoms = (*it)->atoms;
137 for (std::vector<const ld::Atom*>::iterator ait = atoms.begin(); ait != atoms.end(); ++ait) {
138 fprintf(stderr, " %p (0x%04llX) %s\n", *ait, (*ait)->size(), (*ait)->name());
139 }
140 }
141 }
142 fprintf(stderr, "DYLIBS:\n");
143 for (std::vector<ld::dylib::File*>::iterator it=state.dylibs.begin(); it != state.dylibs.end(); ++it )
144 fprintf(stderr, " %s\n", (*it)->installPath());
145}
146
147void OutputFile::write(ld::Internal& state)
148{
149 this->buildDylibOrdinalMapping(state);
150 this->addLoadCommands(state);
151 this->addLinkEdit(state);
9543cb2f 152 state.setSectionSizesAndAlignments();
a645023d 153 this->setLoadCommandsPadding(state);
9543cb2f 154 _fileSize = state.assignFileOffsets();
a645023d
A
155 this->assignAtomAddresses(state);
156 this->synthesizeDebugNotes(state);
157 this->buildSymbolTable(state);
158 this->generateLinkEditInfo(state);
159 this->makeSplitSegInfo(state);
160 this->updateLINKEDITAddresses(state);
161 //this->dumpAtomsBySection(state, false);
162 this->writeOutputFile(state);
163 this->writeMapFile(state);
164}
165
166bool OutputFile::findSegment(ld::Internal& state, uint64_t addr, uint64_t* start, uint64_t* end, uint32_t* index)
167{
168 uint32_t segIndex = 0;
169 ld::Internal::FinalSection* segFirstSection = NULL;
170 ld::Internal::FinalSection* lastSection = NULL;
171 for (std::vector<ld::Internal::FinalSection*>::iterator it = state.sections.begin(); it != state.sections.end(); ++it) {
172 ld::Internal::FinalSection* sect = *it;
173 if ( (segFirstSection == NULL ) || strcmp(segFirstSection->segmentName(), sect->segmentName()) != 0 ) {
174 if ( segFirstSection != NULL ) {
175 //fprintf(stderr, "findSegment(0x%llX) seg changed to %s\n", addr, sect->segmentName());
176 if ( (addr >= segFirstSection->address) && (addr < lastSection->address+lastSection->size) ) {
177 *start = segFirstSection->address;
178 *end = lastSection->address+lastSection->size;
179 *index = segIndex;
180 return true;
181 }
182 ++segIndex;
183 }
184 segFirstSection = sect;
185 }
186 lastSection = sect;
187 }
188 return false;
189}
190
191
192void OutputFile::assignAtomAddresses(ld::Internal& state)
193{
ebf6f434
A
194 const bool log = false;
195 if ( log ) fprintf(stderr, "assignAtomAddresses()\n");
a645023d
A
196 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
197 ld::Internal::FinalSection* sect = *sit;
ebf6f434 198 if ( log ) fprintf(stderr, " section=%s/%s\n", sect->segmentName(), sect->sectionName());
a645023d
A
199 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
200 const ld::Atom* atom = *ait;
201 switch ( sect-> type() ) {
202 case ld::Section::typeImportProxies:
203 // want finalAddress() of all proxy atoms to be zero
204 (const_cast<ld::Atom*>(atom))->setSectionStartAddress(0);
205 break;
206 case ld::Section::typeAbsoluteSymbols:
207 // want finalAddress() of all absolute atoms to be value of abs symbol
208 (const_cast<ld::Atom*>(atom))->setSectionStartAddress(0);
209 break;
210 case ld::Section::typeLinkEdit:
211 // linkedit layout is assigned later
212 break;
213 default:
214 (const_cast<ld::Atom*>(atom))->setSectionStartAddress(sect->address);
9543cb2f 215 if ( log ) fprintf(stderr, " atom=%p, addr=0x%08llX, name=%s\n", atom, atom->finalAddress(), atom->name());
a645023d
A
216 break;
217 }
218 }
219 }
220}
221
222void OutputFile::updateLINKEDITAddresses(ld::Internal& state)
223{
224 if ( _options.makeCompressedDyldInfo() ) {
225 // build dylb rebasing info
226 assert(_rebasingInfoAtom != NULL);
227 _rebasingInfoAtom->encode();
228
229 // build dyld binding info
230 assert(_bindingInfoAtom != NULL);
231 _bindingInfoAtom->encode();
232
233 // build dyld lazy binding info
234 assert(_lazyBindingInfoAtom != NULL);
235 _lazyBindingInfoAtom->encode();
236
237 // build dyld weak binding info
238 assert(_weakBindingInfoAtom != NULL);
239 _weakBindingInfoAtom->encode();
240
241 // build dyld export info
242 assert(_exportInfoAtom != NULL);
243 _exportInfoAtom->encode();
244 }
245
246 if ( _options.sharedRegionEligible() ) {
247 // build split seg info
248 assert(_splitSegInfoAtom != NULL);
249 _splitSegInfoAtom->encode();
250 }
251
252 if ( _options.addFunctionStarts() ) {
253 // build function starts info
254 assert(_functionStartsAtom != NULL);
255 _functionStartsAtom->encode();
256 }
257
ebf6f434
A
258 if ( _options.addDataInCodeInfo() ) {
259 // build data-in-code info
260 assert(_dataInCodeAtom != NULL);
261 _dataInCodeAtom->encode();
262 }
263
9543cb2f
A
264 if ( _hasOptimizationHints ) {
265 // build linker-optimization-hint info
266 assert(_optimizationHintsAtom != NULL);
267 _optimizationHintsAtom->encode();
268 }
269
ebf6f434
A
270 if ( _options.needsDependentDRInfo() ) {
271 // build dependent dylib DR info
272 assert(_dependentDRInfoAtom != NULL);
273 _dependentDRInfoAtom->encode();
274 }
275
a645023d
A
276 // build classic symbol table
277 assert(_symbolTableAtom != NULL);
278 _symbolTableAtom->encode();
279 assert(_indirectSymbolTableAtom != NULL);
280 _indirectSymbolTableAtom->encode();
281
282 // add relocations to .o files
283 if ( _options.outputKind() == Options::kObjectFile ) {
284 assert(_sectionsRelocationsAtom != NULL);
285 _sectionsRelocationsAtom->encode();
286 }
287
288 if ( ! _options.makeCompressedDyldInfo() ) {
289 // build external relocations
290 assert(_externalRelocsAtom != NULL);
291 _externalRelocsAtom->encode();
292 // build local relocations
293 assert(_localRelocsAtom != NULL);
294 _localRelocsAtom->encode();
295 }
296
297 // update address and file offsets now that linkedit content has been generated
298 uint64_t curLinkEditAddress = 0;
299 uint64_t curLinkEditfileOffset = 0;
300 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
301 ld::Internal::FinalSection* sect = *sit;
302 if ( sect->type() != ld::Section::typeLinkEdit )
303 continue;
304 if ( curLinkEditAddress == 0 ) {
305 curLinkEditAddress = sect->address;
306 curLinkEditfileOffset = sect->fileOffset;
307 }
308 uint16_t maxAlignment = 0;
309 uint64_t offset = 0;
310 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
311 const ld::Atom* atom = *ait;
312 //fprintf(stderr, "setting linkedit atom offset for %s\n", atom->name());
313 if ( atom->alignment().powerOf2 > maxAlignment )
314 maxAlignment = atom->alignment().powerOf2;
315 // calculate section offset for this atom
316 uint64_t alignment = 1 << atom->alignment().powerOf2;
317 uint64_t currentModulus = (offset % alignment);
318 uint64_t requiredModulus = atom->alignment().modulus;
319 if ( currentModulus != requiredModulus ) {
320 if ( requiredModulus > currentModulus )
321 offset += requiredModulus-currentModulus;
322 else
323 offset += requiredModulus+alignment-currentModulus;
324 }
325 (const_cast<ld::Atom*>(atom))->setSectionOffset(offset);
326 (const_cast<ld::Atom*>(atom))->setSectionStartAddress(curLinkEditAddress);
327 offset += atom->size();
328 }
329 sect->size = offset;
330 // section alignment is that of a contained atom with the greatest alignment
331 sect->alignment = maxAlignment;
332 sect->address = curLinkEditAddress;
333 sect->fileOffset = curLinkEditfileOffset;
334 curLinkEditAddress += sect->size;
335 curLinkEditfileOffset += sect->size;
336 }
337
338 _fileSize = state.sections.back()->fileOffset + state.sections.back()->size;
339}
340
a645023d
A
341
342void OutputFile::setLoadCommandsPadding(ld::Internal& state)
343{
344 // In other sections, any extra space is put and end of segment.
345 // In __TEXT segment, any extra space is put after load commands to allow post-processing of load commands
346 // Do a reverse layout of __TEXT segment to determine padding size and adjust section size
347 uint64_t paddingSize = 0;
348 switch ( _options.outputKind() ) {
349 case Options::kDyld:
350 // dyld itself has special padding requirements. We want the beginning __text section to start at a stable address
351 assert(strcmp(state.sections[1]->sectionName(),"__text") == 0);
352 state.sections[1]->alignment = 12; // page align __text
353 break;
354 case Options::kObjectFile:
355 // mach-o .o files need no padding between load commands and first section
356 // but leave enough room that the object file could be signed
357 paddingSize = 32;
358 break;
359 case Options::kPreload:
360 // mach-o MH_PRELOAD files need no padding between load commands and first section
361 paddingSize = 0;
362 default:
363 // work backwards from end of segment and lay out sections so that extra room goes to padding atom
364 uint64_t addr = 0;
9543cb2f 365 uint64_t textSegPageSize = _options.segPageSize("__TEXT");
a645023d
A
366 for (std::vector<ld::Internal::FinalSection*>::reverse_iterator it = state.sections.rbegin(); it != state.sections.rend(); ++it) {
367 ld::Internal::FinalSection* sect = *it;
368 if ( strcmp(sect->segmentName(), "__TEXT") != 0 )
369 continue;
370 if ( sect == headerAndLoadCommandsSection ) {
371 addr -= headerAndLoadCommandsSection->size;
9543cb2f 372 paddingSize = addr % textSegPageSize;
a645023d
A
373 break;
374 }
375 addr -= sect->size;
376 addr = addr & (0 - (1 << sect->alignment));
377 }
378
379 // if command line requires more padding than this
380 uint32_t minPad = _options.minimumHeaderPad();
381 if ( _options.maxMminimumHeaderPad() ) {
382 // -headerpad_max_install_names means there should be room for every path load command to grow to 1204 bytes
383 uint32_t altMin = _dylibsToLoad.size() * MAXPATHLEN;
384 if ( _options.outputKind() == Options::kDynamicLibrary )
385 altMin += MAXPATHLEN;
386 if ( altMin > minPad )
387 minPad = altMin;
388 }
389 if ( paddingSize < minPad ) {
390 int extraPages = (minPad - paddingSize + _options.segmentAlignment() - 1)/_options.segmentAlignment();
391 paddingSize += extraPages * _options.segmentAlignment();
392 }
393
394 if ( _options.makeEncryptable() ) {
395 // load commands must be on a separate non-encrypted page
396 int loadCommandsPage = (headerAndLoadCommandsSection->size + minPad)/_options.segmentAlignment();
397 int textPage = (headerAndLoadCommandsSection->size + paddingSize)/_options.segmentAlignment();
398 if ( loadCommandsPage == textPage ) {
399 paddingSize += _options.segmentAlignment();
400 textPage += 1;
401 }
402 // remember start for later use by load command
403 _encryptedTEXTstartOffset = textPage*_options.segmentAlignment();
404 }
405 break;
406 }
407 // add padding to size of section
408 headerAndLoadCommandsSection->size += paddingSize;
409}
410
411
412uint64_t OutputFile::pageAlign(uint64_t addr)
413{
414 const uint64_t alignment = _options.segmentAlignment();
415 return ((addr+alignment-1) & (-alignment));
416}
417
418uint64_t OutputFile::pageAlign(uint64_t addr, uint64_t pageSize)
419{
420 return ((addr+pageSize-1) & (-pageSize));
421}
422
a645023d
A
423static const char* makeName(const ld::Atom& atom)
424{
425 static char buffer[4096];
426 switch ( atom.symbolTableInclusion() ) {
427 case ld::Atom::symbolTableNotIn:
428 case ld::Atom::symbolTableNotInFinalLinkedImages:
429 sprintf(buffer, "%s@0x%08llX", atom.name(), atom.objectAddress());
430 break;
431 case ld::Atom::symbolTableIn:
432 case ld::Atom::symbolTableInAndNeverStrip:
433 case ld::Atom::symbolTableInAsAbsolute:
434 case ld::Atom::symbolTableInWithRandomAutoStripLabel:
435 strlcpy(buffer, atom.name(), 4096);
436 break;
437 }
438 return buffer;
439}
440
441static const char* referenceTargetAtomName(ld::Internal& state, const ld::Fixup* ref)
442{
443 switch ( ref->binding ) {
444 case ld::Fixup::bindingNone:
445 return "NO BINDING";
446 case ld::Fixup::bindingByNameUnbound:
447 return (char*)(ref->u.target);
448 case ld::Fixup::bindingByContentBound:
449 case ld::Fixup::bindingDirectlyBound:
450 return makeName(*((ld::Atom*)(ref->u.target)));
451 case ld::Fixup::bindingsIndirectlyBound:
452 return makeName(*state.indirectBindingTable[ref->u.bindingIndex]);
453 }
454 return "BAD BINDING";
455}
456
457bool OutputFile::targetIsThumb(ld::Internal& state, const ld::Fixup* fixup)
458{
459 switch ( fixup->binding ) {
460 case ld::Fixup::bindingByContentBound:
461 case ld::Fixup::bindingDirectlyBound:
462 return fixup->u.target->isThumb();
463 case ld::Fixup::bindingsIndirectlyBound:
464 return state.indirectBindingTable[fixup->u.bindingIndex]->isThumb();
465 default:
466 break;
467 }
468 throw "unexpected binding";
469}
470
471uint64_t OutputFile::addressOf(const ld::Internal& state, const ld::Fixup* fixup, const ld::Atom** target)
472{
473 if ( !_options.makeCompressedDyldInfo() ) {
474 // For external relocations the classic mach-o format
475 // has addend only stored in the content. That means
476 // that the address of the target is not used.
477 if ( fixup->contentAddendOnly )
478 return 0;
479 }
480 switch ( fixup->binding ) {
481 case ld::Fixup::bindingNone:
482 throw "unexpected bindingNone";
483 case ld::Fixup::bindingByNameUnbound:
484 throw "unexpected bindingByNameUnbound";
485 case ld::Fixup::bindingByContentBound:
486 case ld::Fixup::bindingDirectlyBound:
487 *target = fixup->u.target;
488 return (*target)->finalAddress();
489 case ld::Fixup::bindingsIndirectlyBound:
490 *target = state.indirectBindingTable[fixup->u.bindingIndex];
ebf6f434
A
491 #ifndef NDEBUG
492 if ( ! (*target)->finalAddressMode() ) {
493 throwf("reference to symbol (which has not been assigned an address) %s", (*target)->name());
494 }
495 #endif
a645023d
A
496 return (*target)->finalAddress();
497 }
498 throw "unexpected binding";
499}
500
501uint64_t OutputFile::sectionOffsetOf(const ld::Internal& state, const ld::Fixup* fixup)
502{
503 const ld::Atom* target = NULL;
504 switch ( fixup->binding ) {
505 case ld::Fixup::bindingNone:
506 throw "unexpected bindingNone";
507 case ld::Fixup::bindingByNameUnbound:
508 throw "unexpected bindingByNameUnbound";
509 case ld::Fixup::bindingByContentBound:
510 case ld::Fixup::bindingDirectlyBound:
511 target = fixup->u.target;
512 break;
513 case ld::Fixup::bindingsIndirectlyBound:
514 target = state.indirectBindingTable[fixup->u.bindingIndex];
515 break;
516 }
517 assert(target != NULL);
518
519 uint64_t targetAddress = target->finalAddress();
520 for (std::vector<ld::Internal::FinalSection*>::const_iterator it = state.sections.begin(); it != state.sections.end(); ++it) {
521 const ld::Internal::FinalSection* sect = *it;
522 if ( (sect->address <= targetAddress) && (targetAddress < (sect->address+sect->size)) )
523 return targetAddress - sect->address;
524 }
525 throw "section not found for section offset";
526}
527
528
529
530uint64_t OutputFile::tlvTemplateOffsetOf(const ld::Internal& state, const ld::Fixup* fixup)
531{
532 const ld::Atom* target = NULL;
533 switch ( fixup->binding ) {
534 case ld::Fixup::bindingNone:
535 throw "unexpected bindingNone";
536 case ld::Fixup::bindingByNameUnbound:
537 throw "unexpected bindingByNameUnbound";
538 case ld::Fixup::bindingByContentBound:
539 case ld::Fixup::bindingDirectlyBound:
540 target = fixup->u.target;
541 break;
542 case ld::Fixup::bindingsIndirectlyBound:
543 target = state.indirectBindingTable[fixup->u.bindingIndex];
544 break;
545 }
546 assert(target != NULL);
547
548 for (std::vector<ld::Internal::FinalSection*>::const_iterator it = state.sections.begin(); it != state.sections.end(); ++it) {
549 const ld::Internal::FinalSection* sect = *it;
550 switch ( sect->type() ) {
551 case ld::Section::typeTLVInitialValues:
552 case ld::Section::typeTLVZeroFill:
553 return target->finalAddress() - sect->address;
554 default:
555 break;
556 }
557 }
558 throw "section not found for tlvTemplateOffsetOf";
559}
560
561void OutputFile::printSectionLayout(ld::Internal& state)
562{
563 // show layout of final image
564 fprintf(stderr, "final section layout:\n");
565 for (std::vector<ld::Internal::FinalSection*>::iterator it = state.sections.begin(); it != state.sections.end(); ++it) {
566 if ( (*it)->isSectionHidden() )
567 continue;
568 fprintf(stderr, " %s/%s addr=0x%08llX, size=0x%08llX, fileOffset=0x%08llX, type=%d\n",
569 (*it)->segmentName(), (*it)->sectionName(),
570 (*it)->address, (*it)->size, (*it)->fileOffset, (*it)->type());
571 }
572}
573
574
575void OutputFile::rangeCheck8(int64_t displacement, ld::Internal& state, const ld::Atom* atom, const ld::Fixup* fixup)
576{
577 if ( (displacement > 127) || (displacement < -128) ) {
578 // show layout of final image
579 printSectionLayout(state);
580
581 const ld::Atom* target;
582 throwf("8-bit reference out of range (%lld max is +/-127B): from %s (0x%08llX) to %s (0x%08llX)",
583 displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup),
584 addressOf(state, fixup, &target));
585 }
586}
587
588void OutputFile::rangeCheck16(int64_t displacement, ld::Internal& state, const ld::Atom* atom, const ld::Fixup* fixup)
589{
590 const int64_t thirtyTwoKLimit = 0x00007FFF;
591 if ( (displacement > thirtyTwoKLimit) || (displacement < (-thirtyTwoKLimit)) ) {
592 // show layout of final image
593 printSectionLayout(state);
594
595 const ld::Atom* target;
596 throwf("16-bit reference out of range (%lld max is +/-32KB): from %s (0x%08llX) to %s (0x%08llX)",
597 displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup),
598 addressOf(state, fixup, &target));
599 }
600}
601
602void OutputFile::rangeCheckBranch32(int64_t displacement, ld::Internal& state, const ld::Atom* atom, const ld::Fixup* fixup)
603{
604 const int64_t twoGigLimit = 0x7FFFFFFF;
605 if ( (displacement > twoGigLimit) || (displacement < (-twoGigLimit)) ) {
606 // show layout of final image
607 printSectionLayout(state);
608
609 const ld::Atom* target;
b1f7435d 610 throwf("32-bit branch out of range (%lld max is +/-2GB): from %s (0x%08llX) to %s (0x%08llX)",
a645023d
A
611 displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup),
612 addressOf(state, fixup, &target));
613 }
614}
615
afe874b1
A
616
617void OutputFile::rangeCheckAbsolute32(int64_t displacement, ld::Internal& state, const ld::Atom* atom, const ld::Fixup* fixup)
618{
619 const int64_t fourGigLimit = 0xFFFFFFFF;
620 if ( displacement > fourGigLimit ) {
621 // <rdar://problem/9610466> cannot enforce 32-bit range checks on 32-bit archs because assembler loses sign information
622 // .long _foo - 0xC0000000
623 // is encoded in mach-o the same as:
624 // .long _foo + 0x40000000
625 // so if _foo lays out to 0xC0000100, the first is ok, but the second is not.
626 if ( (_options.architecture() == CPU_TYPE_ARM) || (_options.architecture() == CPU_TYPE_I386) ) {
d425e388
A
627 // Unlikely userland code does funky stuff like this, so warn for them, but not warn for -preload or -static
628 if ( (_options.outputKind() != Options::kPreload) && (_options.outputKind() != Options::kStaticExecutable) ) {
afe874b1
A
629 warning("32-bit absolute address out of range (0x%08llX max is 4GB): from %s + 0x%08X (0x%08llX) to 0x%08llX",
630 displacement, atom->name(), fixup->offsetInAtom, atom->finalAddress(), displacement);
631 }
632 return;
633 }
634 // show layout of final image
635 printSectionLayout(state);
636
637 const ld::Atom* target;
638 if ( fixup->binding == ld::Fixup::bindingNone )
639 throwf("32-bit absolute address out of range (0x%08llX max is 4GB): from %s + 0x%08X (0x%08llX) to 0x%08llX",
640 displacement, atom->name(), fixup->offsetInAtom, atom->finalAddress(), displacement);
641 else
642 throwf("32-bit absolute address out of range (0x%08llX max is 4GB): from %s + 0x%08X (0x%08llX) to %s (0x%08llX)",
643 displacement, atom->name(), fixup->offsetInAtom, atom->finalAddress(), referenceTargetAtomName(state, fixup),
644 addressOf(state, fixup, &target));
645 }
646}
647
648
a645023d
A
649void OutputFile::rangeCheckRIP32(int64_t displacement, ld::Internal& state, const ld::Atom* atom, const ld::Fixup* fixup)
650{
651 const int64_t twoGigLimit = 0x7FFFFFFF;
afe874b1 652 if ( (displacement > twoGigLimit) || (displacement < (-twoGigLimit)) ) {
a645023d
A
653 // show layout of final image
654 printSectionLayout(state);
655
656 const ld::Atom* target;
657 throwf("32-bit RIP relative reference out of range (%lld max is +/-4GB): from %s (0x%08llX) to %s (0x%08llX)",
658 displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup),
659 addressOf(state, fixup, &target));
660 }
661}
662
663void OutputFile::rangeCheckARM12(int64_t displacement, ld::Internal& state, const ld::Atom* atom, const ld::Fixup* fixup)
664{
665 if ( (displacement > 4092LL) || (displacement < (-4092LL)) ) {
666 // show layout of final image
667 printSectionLayout(state);
668
669 const ld::Atom* target;
670 throwf("ARM ldr 12-bit displacement out of range (%lld max is +/-4096B): from %s (0x%08llX) to %s (0x%08llX)",
671 displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup),
672 addressOf(state, fixup, &target));
673 }
674}
675
9543cb2f
A
676bool OutputFile::checkArmBranch24Displacement(int64_t displacement)
677{
678 return ( (displacement < 33554428LL) && (displacement > (-33554432LL)) );
679}
a645023d
A
680
681void OutputFile::rangeCheckARMBranch24(int64_t displacement, ld::Internal& state, const ld::Atom* atom, const ld::Fixup* fixup)
682{
9543cb2f
A
683 if ( checkArmBranch24Displacement(displacement) )
684 return;
a645023d 685
9543cb2f
A
686 // show layout of final image
687 printSectionLayout(state);
688
689 const ld::Atom* target;
690 throwf("b/bl/blx ARM branch out of range (%lld max is +/-32MB): from %s (0x%08llX) to %s (0x%08llX)",
691 displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup),
692 addressOf(state, fixup, &target));
a645023d
A
693}
694
9543cb2f 695bool OutputFile::checkThumbBranch22Displacement(int64_t displacement)
a645023d 696{
9543cb2f 697 // thumb2 supports +/- 16MB displacement
afe874b1 698 if ( _options.preferSubArchitecture() && _options.archSupportsThumb2() ) {
a645023d 699 if ( (displacement > 16777214LL) || (displacement < (-16777216LL)) ) {
9543cb2f 700 return false;
a645023d
A
701 }
702 }
703 else {
9543cb2f 704 // thumb1 supports +/- 4MB displacement
a645023d 705 if ( (displacement > 4194302LL) || (displacement < (-4194304LL)) ) {
9543cb2f 706 return false;
a645023d
A
707 }
708 }
9543cb2f
A
709 return true;
710}
711
712void OutputFile::rangeCheckThumbBranch22(int64_t displacement, ld::Internal& state, const ld::Atom* atom, const ld::Fixup* fixup)
713{
714 if ( checkThumbBranch22Displacement(displacement) )
715 return;
716
717 // show layout of final image
718 printSectionLayout(state);
719
720 const ld::Atom* target;
721 if ( _options.preferSubArchitecture() && _options.archSupportsThumb2() ) {
722 throwf("b/bl/blx thumb2 branch out of range (%lld max is +/-16MB): from %s (0x%08llX) to %s (0x%08llX)",
723 displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup),
724 addressOf(state, fixup, &target));
725 }
726 else {
727 throwf("b/bl/blx thumb1 branch out of range (%lld max is +/-4MB): from %s (0x%08llX) to %s (0x%08llX)",
728 displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup),
729 addressOf(state, fixup, &target));
730 }
a645023d
A
731}
732
a645023d 733
f80fe69f
A
734void OutputFile::rangeCheckARM64Branch26(int64_t displacement, ld::Internal& state, const ld::Atom* atom, const ld::Fixup* fixup)
735{
736 const int64_t bl_128MegLimit = 0x07FFFFFF;
737 if ( (displacement > bl_128MegLimit) || (displacement < (-bl_128MegLimit)) ) {
738 // show layout of final image
739 printSectionLayout(state);
740
741 const ld::Atom* target;
742 throwf("b(l) ARM64 branch out of range (%lld max is +/-128MB): from %s (0x%08llX) to %s (0x%08llX)",
743 displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup),
744 addressOf(state, fixup, &target));
745 }
746}
a645023d 747
f80fe69f
A
748void OutputFile::rangeCheckARM64Page21(int64_t displacement, ld::Internal& state, const ld::Atom* atom, const ld::Fixup* fixup)
749{
750 const int64_t adrp_4GigLimit = 0x100000000ULL;
751 if ( (displacement > adrp_4GigLimit) || (displacement < (-adrp_4GigLimit)) ) {
752 // show layout of final image
753 printSectionLayout(state);
754
755 const ld::Atom* target;
756 throwf("ARM64 ADRP out of range (%lld max is +/-4GB): from %s (0x%08llX) to %s (0x%08llX)",
757 displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup),
758 addressOf(state, fixup, &target));
759 }
760}
a645023d
A
761
762
763uint16_t OutputFile::get16LE(uint8_t* loc) { return LittleEndian::get16(*(uint16_t*)loc); }
764void OutputFile::set16LE(uint8_t* loc, uint16_t value) { LittleEndian::set16(*(uint16_t*)loc, value); }
765
766uint32_t OutputFile::get32LE(uint8_t* loc) { return LittleEndian::get32(*(uint32_t*)loc); }
767void OutputFile::set32LE(uint8_t* loc, uint32_t value) { LittleEndian::set32(*(uint32_t*)loc, value); }
768
769uint64_t OutputFile::get64LE(uint8_t* loc) { return LittleEndian::get64(*(uint64_t*)loc); }
770void OutputFile::set64LE(uint8_t* loc, uint64_t value) { LittleEndian::set64(*(uint64_t*)loc, value); }
771
772uint16_t OutputFile::get16BE(uint8_t* loc) { return BigEndian::get16(*(uint16_t*)loc); }
773void OutputFile::set16BE(uint8_t* loc, uint16_t value) { BigEndian::set16(*(uint16_t*)loc, value); }
774
775uint32_t OutputFile::get32BE(uint8_t* loc) { return BigEndian::get32(*(uint32_t*)loc); }
776void OutputFile::set32BE(uint8_t* loc, uint32_t value) { BigEndian::set32(*(uint32_t*)loc, value); }
777
778uint64_t OutputFile::get64BE(uint8_t* loc) { return BigEndian::get64(*(uint64_t*)loc); }
779void OutputFile::set64BE(uint8_t* loc, uint64_t value) { BigEndian::set64(*(uint64_t*)loc, value); }
780
9543cb2f
A
781static uint32_t makeNOP() {
782 return 0xD503201F;
783}
784
785enum SignExtension { signedNot, signed32, signed64 };
786struct LoadStoreInfo {
787 uint32_t reg;
788 uint32_t baseReg;
789 uint32_t offset; // after scaling
790 uint32_t size; // 1,2,4,8, or 16
791 bool isStore;
792 bool isFloat; // if destReg is FP/SIMD
793 SignExtension signEx; // if load is sign extended
794};
795
796static uint32_t makeLDR_literal(const LoadStoreInfo& info, uint64_t targetAddress, uint64_t instructionAddress)
797{
798 int64_t delta = targetAddress - instructionAddress;
799 assert(delta < 1024*1024);
800 assert(delta > -1024*1024);
801 assert((info.reg & 0xFFFFFFE0) == 0);
802 assert((targetAddress & 0x3) == 0);
803 assert((instructionAddress & 0x3) == 0);
804 assert(!info.isStore);
805 uint32_t imm19 = (delta << 3) & 0x00FFFFE0;
806 uint32_t instruction = 0;
807 switch ( info.size ) {
808 case 4:
809 if ( info.isFloat ) {
810 assert(info.signEx == signedNot);
811 instruction = 0x1C000000;
812 }
813 else {
814 if ( info.signEx == signed64 )
815 instruction = 0x98000000;
816 else
817 instruction = 0x18000000;
818 }
819 break;
820 case 8:
821 assert(info.signEx == signedNot);
822 instruction = info.isFloat ? 0x5C000000 : 0x58000000;
823 break;
824 case 16:
825 assert(info.signEx == signedNot);
826 instruction = 0x9C000000;
827 break;
828 default:
829 assert(0 && "invalid load size for literal");
830 }
831 return (instruction | imm19 | info.reg);
832}
833
834static uint32_t makeADR(uint32_t destReg, uint64_t targetAddress, uint64_t instructionAddress)
835{
836 assert((destReg & 0xFFFFFFE0) == 0);
837 assert((instructionAddress & 0x3) == 0);
838 uint32_t instruction = 0x10000000;
839 int64_t delta = targetAddress - instructionAddress;
840 assert(delta < 1024*1024);
841 assert(delta > -1024*1024);
842 uint32_t immhi = (delta & 0x001FFFFC) << 3;
843 uint32_t immlo = (delta & 0x00000003) << 29;
844 return (instruction | immhi | immlo | destReg);
845}
846
847static uint32_t makeLoadOrStore(const LoadStoreInfo& info)
848{
849 uint32_t instruction = 0x39000000;
850 if ( info.isFloat )
851 instruction |= 0x04000000;
852 instruction |= info.reg;
853 instruction |= (info.baseReg << 5);
854 uint32_t sizeBits = 0;
855 uint32_t opcBits = 0;
856 uint32_t imm12Bits = 0;
857 switch ( info.size ) {
858 case 1:
859 sizeBits = 0;
860 imm12Bits = info.offset;
861 if ( info.isStore ) {
862 opcBits = 0;
863 }
864 else {
865 switch ( info.signEx ) {
866 case signedNot:
867 opcBits = 1;
868 break;
869 case signed32:
870 opcBits = 3;
871 break;
872 case signed64:
873 opcBits = 2;
874 break;
875 }
876 }
877 break;
878 case 2:
879 sizeBits = 1;
880 assert((info.offset % 2) == 0);
881 imm12Bits = info.offset/2;
882 if ( info.isStore ) {
883 opcBits = 0;
884 }
885 else {
886 switch ( info.signEx ) {
887 case signedNot:
888 opcBits = 1;
889 break;
890 case signed32:
891 opcBits = 3;
892 break;
893 case signed64:
894 opcBits = 2;
895 break;
896 }
897 }
898 break;
899 case 4:
900 sizeBits = 2;
901 assert((info.offset % 4) == 0);
902 imm12Bits = info.offset/4;
903 if ( info.isStore ) {
904 opcBits = 0;
905 }
906 else {
907 switch ( info.signEx ) {
908 case signedNot:
909 opcBits = 1;
910 break;
911 case signed32:
912 assert(0 && "cannot use signed32 with 32-bit load/store");
913 break;
914 case signed64:
915 opcBits = 2;
916 break;
917 }
918 }
919 break;
920 case 8:
921 sizeBits = 3;
922 assert((info.offset % 8) == 0);
923 imm12Bits = info.offset/8;
924 if ( info.isStore ) {
925 opcBits = 0;
926 }
927 else {
928 opcBits = 1;
929 assert(info.signEx == signedNot);
930 }
931 break;
932 case 16:
933 sizeBits = 0;
934 assert((info.offset % 16) == 0);
935 imm12Bits = info.offset/16;
936 assert(info.isFloat);
937 if ( info.isStore ) {
938 opcBits = 2;
939 }
940 else {
941 opcBits = 3;
942 }
943 break;
944 default:
945 assert(0 && "bad load/store size");
946 break;
947 }
948 assert(imm12Bits < 4096);
949 return (instruction | (sizeBits << 30) | (opcBits << 22) | (imm12Bits << 10));
950}
951
952static bool parseLoadOrStore(uint32_t instruction, LoadStoreInfo& info)
953{
954 if ( (instruction & 0x3B000000) != 0x39000000 )
955 return false;
956 info.isFloat = ( (instruction & 0x04000000) != 0 );
957 info.reg = (instruction & 0x1F);
958 info.baseReg = ((instruction>>5) & 0x1F);
959 switch (instruction & 0xC0C00000) {
960 case 0x00000000:
961 info.size = 1;
962 info.isStore = true;
963 info.signEx = signedNot;
964 break;
965 case 0x00400000:
966 info.size = 1;
967 info.isStore = false;
968 info.signEx = signedNot;
969 break;
970 case 0x00800000:
971 if ( info.isFloat ) {
972 info.size = 16;
973 info.isStore = true;
974 info.signEx = signedNot;
975 }
976 else {
977 info.size = 1;
978 info.isStore = false;
979 info.signEx = signed64;
980 }
981 break;
982 case 0x00C00000:
983 if ( info.isFloat ) {
984 info.size = 16;
985 info.isStore = false;
986 info.signEx = signedNot;
987 }
988 else {
989 info.size = 1;
990 info.isStore = false;
991 info.signEx = signed32;
992 }
993 break;
994 case 0x40000000:
995 info.size = 2;
996 info.isStore = true;
997 info.signEx = signedNot;
998 break;
999 case 0x40400000:
1000 info.size = 2;
1001 info.isStore = false;
1002 info.signEx = signedNot;
1003 break;
1004 case 0x40800000:
1005 info.size = 2;
1006 info.isStore = false;
1007 info.signEx = signed64;
1008 break;
1009 case 0x40C00000:
1010 info.size = 2;
1011 info.isStore = false;
1012 info.signEx = signed32;
1013 break;
1014 case 0x80000000:
1015 info.size = 4;
1016 info.isStore = true;
1017 info.signEx = signedNot;
1018 break;
1019 case 0x80400000:
1020 info.size = 4;
1021 info.isStore = false;
1022 info.signEx = signedNot;
1023 break;
1024 case 0x80800000:
1025 info.size = 4;
1026 info.isStore = false;
1027 info.signEx = signed64;
1028 break;
1029 case 0xC0000000:
1030 info.size = 8;
1031 info.isStore = true;
1032 info.signEx = signedNot;
1033 break;
1034 case 0xC0400000:
1035 info.size = 8;
1036 info.isStore = false;
1037 info.signEx = signedNot;
1038 break;
1039 default:
1040 return false;
1041 }
1042 info.offset = ((instruction >> 10) & 0x0FFF) * info.size;
1043 return true;
1044}
1045
1046struct AdrpInfo {
1047 uint32_t destReg;
1048};
1049
1050static bool parseADRP(uint32_t instruction, AdrpInfo& info)
1051{
1052 if ( (instruction & 0x9F000000) != 0x90000000 )
1053 return false;
1054 info.destReg = (instruction & 0x1F);
1055 return true;
1056}
1057
1058struct AddInfo {
1059 uint32_t destReg;
1060 uint32_t srcReg;
1061 uint32_t addend;
1062};
1063
1064static bool parseADD(uint32_t instruction, AddInfo& info)
1065{
1066 if ( (instruction & 0xFFC00000) != 0x91000000 )
1067 return false;
1068 info.destReg = (instruction & 0x1F);
1069 info.srcReg = ((instruction>>5) & 0x1F);
1070 info.addend = ((instruction>>10) & 0xFFF);
1071 return true;
1072}
1073
1074
1075
1076#if 0
1077static uint32_t makeLDR_scaledOffset(const LoadStoreInfo& info)
1078{
1079 assert((info.reg & 0xFFFFFFE0) == 0);
1080 assert((info.baseReg & 0xFFFFFFE0) == 0);
1081 assert(!info.isFloat || (info.signEx != signedNot));
1082 uint32_t sizeBits = 0;
1083 uint32_t opcBits = 1;
1084 uint32_t vBit = info.isFloat;
1085 switch ( info.signEx ) {
1086 case signedNot:
1087 opcBits = 1;
1088 break;
1089 case signed32:
1090 opcBits = 3;
1091 break;
1092 case signed64:
1093 opcBits = 2;
1094 break;
1095 default:
1096 assert(0 && "bad SignExtension runtime value");
1097 }
1098 switch ( info.size ) {
1099 case 1:
1100 sizeBits = 0;
1101 break;
1102 case 2:
1103 sizeBits = 1;
1104 break;
1105 case 4:
1106 sizeBits = 2;
1107 break;
1108 case 8:
1109 sizeBits = 3;
1110 break;
1111 case 16:
1112 sizeBits = 0;
1113 vBit = 1;
1114 opcBits = 3;
1115 break;
1116 default:
1117 assert(0 && "invalid load size for literal");
1118 }
1119 assert((info.offset % info.size) == 0);
1120 uint32_t scaledOffset = info.offset/info.size;
1121 assert(scaledOffset < 4096);
1122 return (0x39000000 | (sizeBits<<30) | (vBit<<26) | (opcBits<<22) | (scaledOffset<<10) | (info.baseReg<<5) | info.reg);
1123}
1124
1125static uint32_t makeLDR_literal(uint32_t destReg, uint32_t loadSize, bool isFloat, uint64_t targetAddress, uint64_t instructionAddress)
1126{
1127 int64_t delta = targetAddress - instructionAddress;
1128 assert(delta < 1024*1024);
1129 assert(delta > -1024*1024);
1130 assert((destReg & 0xFFFFFFE0) == 0);
1131 assert((targetAddress & 0x3) == 0);
1132 assert((instructionAddress & 0x3) == 0);
1133 uint32_t imm19 = (delta << 3) & 0x00FFFFE0;
1134 uint32_t instruction = 0;
1135 switch ( loadSize ) {
1136 case 4:
1137 instruction = isFloat ? 0x1C000000 : 0x18000000;
1138 break;
1139 case 8:
1140 instruction = isFloat ? 0x5C000000 : 0x58000000;
1141 break;
1142 case 16:
1143 instruction = 0x9C000000;
1144 break;
1145 default:
1146 assert(0 && "invalid load size for literal");
1147 }
1148 return (instruction | imm19 | destReg);
1149}
1150
1151
1152static bool ldrInfo(uint32_t instruction, uint8_t* size, uint8_t* destReg, bool* v, uint32_t* scaledOffset)
1153{
1154 *v = ( (instruction & 0x04000000) != 0 );
1155 *destReg = (instruction & 0x1F);
1156 uint32_t imm12 = ((instruction >> 10) & 0x00000FFF);
1157 switch ( (instruction & 0xC0000000) >> 30 ) {
1158 case 0:
1159 // vector and byte LDR have same "size" bits, need to check other bits to differenciate
1160 if ( (instruction & 0x00800000) == 0 ) {
1161 *size = 1;
1162 *scaledOffset = imm12;
1163 }
1164 else {
1165 *size = 16;
1166 *scaledOffset = imm12 * 16;
1167 }
1168 break;
1169 case 1:
1170 *size = 2;
1171 *scaledOffset = imm12 * 2;
1172 break;
1173 case 2:
1174 *size = 4;
1175 *scaledOffset = imm12 * 4;
1176 break;
1177 case 3:
1178 *size = 8;
1179 *scaledOffset = imm12 * 8;
1180 break;
1181 }
1182 return ((instruction & 0x3B400000) == 0x39400000);
1183}
1184#endif
1185
1186static bool withinOneMeg(uint64_t addr1, uint64_t addr2) {
1187 int64_t delta = (addr2 - addr1);
1188 return ( (delta < 1024*1024) && (delta > -1024*1024) );
1189}
1190
1191void OutputFile::setInfo(ld::Internal& state, const ld::Atom* atom, uint8_t* buffer, const std::map<uint32_t, const Fixup*>& usedByHints,
1192 uint32_t offsetInAtom, uint32_t delta, InstructionInfo* info)
1193{
1194 info->offsetInAtom = offsetInAtom + delta;
1195 std::map<uint32_t, const Fixup*>::const_iterator pos = usedByHints.find(info->offsetInAtom);
1196 if ( (pos != usedByHints.end()) && (pos->second != NULL) ) {
1197 info->fixup = pos->second;
1198 info->targetAddress = addressOf(state, info->fixup, &info->target);
1199 if ( info->fixup->clusterSize != ld::Fixup::k1of1 ) {
1200 assert(info->fixup->firstInCluster());
1201 const ld::Fixup* nextFixup = info->fixup + 1;
1202 if ( nextFixup->kind == ld::Fixup::kindAddAddend ) {
1203 info->targetAddress += nextFixup->u.addend;
1204 }
1205 else {
1206 assert(0 && "expected addend");
1207 }
1208 }
1209 }
1210 else {
1211 info->fixup = NULL;
1212 info->targetAddress = 0;
1213 info->target = NULL;
1214 }
1215 info->instructionContent = &buffer[info->offsetInAtom];
1216 info->instructionAddress = atom->finalAddress() + info->offsetInAtom;
1217 info->instruction = get32LE(info->instructionContent);
1218}
1219
1220static bool isPageKind(const ld::Fixup* fixup, bool mustBeGOT=false)
1221{
1222 if ( fixup == NULL )
1223 return false;
1224 const ld::Fixup* f;
1225 switch ( fixup->kind ) {
1226 case ld::Fixup::kindStoreTargetAddressARM64Page21:
1227 return !mustBeGOT;
1228 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
1229 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21:
1230 return true;
1231 case ld::Fixup::kindSetTargetAddress:
1232 f = fixup;
1233 do {
1234 ++f;
1235 } while ( ! f->lastInCluster() );
1236 switch (f->kind ) {
1237 case ld::Fixup::kindStoreARM64Page21:
1238 return !mustBeGOT;
1239 case ld::Fixup::kindStoreARM64GOTLoadPage21:
1240 case ld::Fixup::kindStoreARM64GOTLeaPage21:
1241 return true;
1242 default:
1243 break;
1244 }
1245 break;
1246 default:
1247 break;
1248 }
1249 return false;
1250}
1251
1252static bool isPageOffsetKind(const ld::Fixup* fixup, bool mustBeGOT=false)
1253{
1254 if ( fixup == NULL )
1255 return false;
1256 const ld::Fixup* f;
1257 switch ( fixup->kind ) {
1258 case ld::Fixup::kindStoreTargetAddressARM64PageOff12:
1259 return !mustBeGOT;
1260 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12:
1261 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPageOff12:
1262 return true;
1263 case ld::Fixup::kindSetTargetAddress:
1264 f = fixup;
1265 do {
1266 ++f;
1267 } while ( ! f->lastInCluster() );
1268 switch (f->kind ) {
1269 case ld::Fixup::kindStoreARM64PageOff12:
1270 return !mustBeGOT;
1271 case ld::Fixup::kindStoreARM64GOTLoadPageOff12:
1272 case ld::Fixup::kindStoreARM64GOTLeaPageOff12:
1273 return true;
1274 default:
1275 break;
1276 }
1277 break;
1278 default:
1279 break;
1280 }
1281 return false;
1282}
1283
1284
1285#define LOH_ASSERT(cond) \
1286 if ( !(cond) ) { \
1287 warning("ignoring linker optimzation hint at %s+0x%X because " #cond, atom->name(), fit->offsetInAtom); \
1288 break; \
1289 }
1290
1291
a645023d
A
1292void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld::Atom* atom, uint8_t* buffer)
1293{
1294 //fprintf(stderr, "applyFixUps() on %s\n", atom->name());
1295 int64_t accumulator = 0;
1296 const ld::Atom* toTarget = NULL;
1297 const ld::Atom* fromTarget;
1298 int64_t delta;
1299 uint32_t instruction;
1300 uint32_t newInstruction;
a645023d
A
1301 bool is_bl;
1302 bool is_blx;
1303 bool is_b;
1304 bool thumbTarget = false;
9543cb2f 1305 std::map<uint32_t, const Fixup*> usedByHints;
a645023d
A
1306 for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
1307 uint8_t* fixUpLocation = &buffer[fit->offsetInAtom];
9543cb2f 1308 ld::Fixup::LOH_arm64 lohExtra;
a645023d
A
1309 switch ( (ld::Fixup::Kind)(fit->kind) ) {
1310 case ld::Fixup::kindNone:
1311 case ld::Fixup::kindNoneFollowOn:
1312 case ld::Fixup::kindNoneGroupSubordinate:
1313 case ld::Fixup::kindNoneGroupSubordinateFDE:
1314 case ld::Fixup::kindNoneGroupSubordinateLSDA:
1315 case ld::Fixup::kindNoneGroupSubordinatePersonality:
1316 break;
1317 case ld::Fixup::kindSetTargetAddress:
1318 accumulator = addressOf(state, fit, &toTarget);
1319 thumbTarget = targetIsThumb(state, fit);
1320 if ( thumbTarget )
1321 accumulator |= 1;
1322 if ( fit->contentAddendOnly || fit->contentDetlaToAddendOnly )
1323 accumulator = 0;
1324 break;
1325 case ld::Fixup::kindSubtractTargetAddress:
1326 delta = addressOf(state, fit, &fromTarget);
1327 if ( ! fit->contentAddendOnly )
1328 accumulator -= delta;
1329 break;
1330 case ld::Fixup::kindAddAddend:
f80fe69f
A
1331 if ( ! fit->contentIgnoresAddend ) {
1332 // <rdar://problem/8342028> ARM main executables main contain .long constants pointing
1333 // into themselves such as jump tables. These .long should not have thumb bit set
1334 // even though the target is a thumb instruction. We can tell it is an interior pointer
1335 // because we are processing an addend.
1336 if ( thumbTarget && (toTarget == atom) && ((int32_t)fit->u.addend > 0) ) {
1337 accumulator &= (-2);
1338 //warning("removing thumb bit from intra-atom pointer in %s %s+0x%0X",
1339 // atom->section().sectionName(), atom->name(), fit->offsetInAtom);
1340 }
1341 accumulator += fit->u.addend;
a645023d 1342 }
a645023d
A
1343 break;
1344 case ld::Fixup::kindSubtractAddend:
1345 accumulator -= fit->u.addend;
1346 break;
1347 case ld::Fixup::kindSetTargetImageOffset:
1348 accumulator = addressOf(state, fit, &toTarget) - mhAddress;
1349 break;
1350 case ld::Fixup::kindSetTargetSectionOffset:
1351 accumulator = sectionOffsetOf(state, fit);
1352 break;
1353 case ld::Fixup::kindSetTargetTLVTemplateOffset:
1354 accumulator = tlvTemplateOffsetOf(state, fit);
1355 break;
1356 case ld::Fixup::kindStore8:
1357 *fixUpLocation += accumulator;
1358 break;
1359 case ld::Fixup::kindStoreLittleEndian16:
1360 set16LE(fixUpLocation, accumulator);
1361 break;
1362 case ld::Fixup::kindStoreLittleEndianLow24of32:
1363 set32LE(fixUpLocation, (get32LE(fixUpLocation) & 0xFF000000) | (accumulator & 0x00FFFFFF) );
1364 break;
1365 case ld::Fixup::kindStoreLittleEndian32:
afe874b1 1366 rangeCheckAbsolute32(accumulator, state, atom, fit);
a645023d
A
1367 set32LE(fixUpLocation, accumulator);
1368 break;
1369 case ld::Fixup::kindStoreLittleEndian64:
1370 set64LE(fixUpLocation, accumulator);
1371 break;
1372 case ld::Fixup::kindStoreBigEndian16:
1373 set16BE(fixUpLocation, accumulator);
1374 break;
1375 case ld::Fixup::kindStoreBigEndianLow24of32:
1376 set32BE(fixUpLocation, (get32BE(fixUpLocation) & 0xFF000000) | (accumulator & 0x00FFFFFF) );
1377 break;
1378 case ld::Fixup::kindStoreBigEndian32:
afe874b1 1379 rangeCheckAbsolute32(accumulator, state, atom, fit);
a645023d
A
1380 set32BE(fixUpLocation, accumulator);
1381 break;
1382 case ld::Fixup::kindStoreBigEndian64:
1383 set64BE(fixUpLocation, accumulator);
1384 break;
1385 case ld::Fixup::kindStoreX86PCRel8:
1386 case ld::Fixup::kindStoreX86BranchPCRel8:
1387 if ( fit->contentAddendOnly )
1388 delta = accumulator;
1389 else
1390 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 1);
1391 rangeCheck8(delta, state, atom, fit);
1392 *fixUpLocation = delta;
1393 break;
1394 case ld::Fixup::kindStoreX86PCRel16:
1395 if ( fit->contentAddendOnly )
1396 delta = accumulator;
1397 else
1398 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 2);
1399 rangeCheck16(delta, state, atom, fit);
1400 set16LE(fixUpLocation, delta);
1401 break;
1402 case ld::Fixup::kindStoreX86BranchPCRel32:
1403 if ( fit->contentAddendOnly )
1404 delta = accumulator;
1405 else
1406 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 4);
1407 rangeCheckBranch32(delta, state, atom, fit);
1408 set32LE(fixUpLocation, delta);
1409 break;
1410 case ld::Fixup::kindStoreX86PCRel32GOTLoad:
1411 case ld::Fixup::kindStoreX86PCRel32GOT:
1412 case ld::Fixup::kindStoreX86PCRel32:
1413 case ld::Fixup::kindStoreX86PCRel32TLVLoad:
1414 if ( fit->contentAddendOnly )
1415 delta = accumulator;
1416 else
1417 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 4);
1418 rangeCheckRIP32(delta, state, atom, fit);
1419 set32LE(fixUpLocation, delta);
1420 break;
1421 case ld::Fixup::kindStoreX86PCRel32_1:
1422 if ( fit->contentAddendOnly )
1423 delta = accumulator - 1;
1424 else
1425 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 5);
1426 rangeCheckRIP32(delta, state, atom, fit);
1427 set32LE(fixUpLocation, delta);
1428 break;
1429 case ld::Fixup::kindStoreX86PCRel32_2:
1430 if ( fit->contentAddendOnly )
1431 delta = accumulator - 2;
1432 else
1433 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 6);
1434 rangeCheckRIP32(delta, state, atom, fit);
1435 set32LE(fixUpLocation, delta);
1436 break;
1437 case ld::Fixup::kindStoreX86PCRel32_4:
1438 if ( fit->contentAddendOnly )
1439 delta = accumulator - 4;
1440 else
1441 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 8);
1442 rangeCheckRIP32(delta, state, atom, fit);
1443 set32LE(fixUpLocation, delta);
1444 break;
1445 case ld::Fixup::kindStoreX86Abs32TLVLoad:
1446 set32LE(fixUpLocation, accumulator);
1447 break;
1448 case ld::Fixup::kindStoreX86Abs32TLVLoadNowLEA:
1449 assert(_options.outputKind() != Options::kObjectFile);
1450 // TLV entry was optimized away, change movl instruction to a leal
1451 if ( fixUpLocation[-1] != 0xA1 )
1452 throw "TLV load reloc does not point to a movl instruction";
1453 fixUpLocation[-1] = 0xB8;
1454 set32LE(fixUpLocation, accumulator);
1455 break;
1456 case ld::Fixup::kindStoreX86PCRel32GOTLoadNowLEA:
1457 assert(_options.outputKind() != Options::kObjectFile);
1458 // GOT entry was optimized away, change movq instruction to a leaq
1459 if ( fixUpLocation[-2] != 0x8B )
1460 throw "GOT load reloc does not point to a movq instruction";
1461 fixUpLocation[-2] = 0x8D;
1462 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 4);
1463 rangeCheckRIP32(delta, state, atom, fit);
1464 set32LE(fixUpLocation, delta);
1465 break;
1466 case ld::Fixup::kindStoreX86PCRel32TLVLoadNowLEA:
1467 assert(_options.outputKind() != Options::kObjectFile);
1468 // TLV entry was optimized away, change movq instruction to a leaq
1469 if ( fixUpLocation[-2] != 0x8B )
1470 throw "TLV load reloc does not point to a movq instruction";
1471 fixUpLocation[-2] = 0x8D;
1472 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 4);
1473 rangeCheckRIP32(delta, state, atom, fit);
1474 set32LE(fixUpLocation, delta);
1475 break;
1476 case ld::Fixup::kindStoreTargetAddressARMLoad12:
1477 accumulator = addressOf(state, fit, &toTarget);
1478 // fall into kindStoreARMLoad12 case
1479 case ld::Fixup::kindStoreARMLoad12:
1480 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 8);
1481 rangeCheckARM12(delta, state, atom, fit);
1482 instruction = get32LE(fixUpLocation);
1483 if ( delta >= 0 ) {
1484 newInstruction = instruction & 0xFFFFF000;
1485 newInstruction |= ((uint32_t)delta & 0xFFF);
1486 }
1487 else {
1488 newInstruction = instruction & 0xFF7FF000;
1489 newInstruction |= ((uint32_t)(-delta) & 0xFFF);
1490 }
1491 set32LE(fixUpLocation, newInstruction);
1492 break;
a645023d
A
1493 case ld::Fixup::kindDtraceExtra:
1494 break;
1495 case ld::Fixup::kindStoreX86DtraceCallSiteNop:
1496 if ( _options.outputKind() != Options::kObjectFile ) {
1497 // change call site to a NOP
1498 fixUpLocation[-1] = 0x90; // 1-byte nop
1499 fixUpLocation[0] = 0x0F; // 4-byte nop
1500 fixUpLocation[1] = 0x1F;
1501 fixUpLocation[2] = 0x40;
1502 fixUpLocation[3] = 0x00;
1503 }
1504 break;
1505 case ld::Fixup::kindStoreX86DtraceIsEnableSiteClear:
1506 if ( _options.outputKind() != Options::kObjectFile ) {
1507 // change call site to a clear eax
1508 fixUpLocation[-1] = 0x33; // xorl eax,eax
1509 fixUpLocation[0] = 0xC0;
1510 fixUpLocation[1] = 0x90; // 1-byte nop
1511 fixUpLocation[2] = 0x90; // 1-byte nop
1512 fixUpLocation[3] = 0x90; // 1-byte nop
1513 }
1514 break;
a645023d
A
1515 case ld::Fixup::kindStoreARMDtraceCallSiteNop:
1516 if ( _options.outputKind() != Options::kObjectFile ) {
1517 // change call site to a NOP
1518 set32LE(fixUpLocation, 0xE1A00000);
1519 }
1520 break;
1521 case ld::Fixup::kindStoreARMDtraceIsEnableSiteClear:
1522 if ( _options.outputKind() != Options::kObjectFile ) {
1523 // change call site to 'eor r0, r0, r0'
1524 set32LE(fixUpLocation, 0xE0200000);
1525 }
1526 break;
1527 case ld::Fixup::kindStoreThumbDtraceCallSiteNop:
1528 if ( _options.outputKind() != Options::kObjectFile ) {
1529 // change 32-bit blx call site to two thumb NOPs
1530 set32LE(fixUpLocation, 0x46C046C0);
1531 }
1532 break;
1533 case ld::Fixup::kindStoreThumbDtraceIsEnableSiteClear:
1534 if ( _options.outputKind() != Options::kObjectFile ) {
1535 // change 32-bit blx call site to 'nop', 'eor r0, r0'
1536 set32LE(fixUpLocation, 0x46C04040);
1537 }
1538 break;
f80fe69f
A
1539 case ld::Fixup::kindStoreARM64DtraceCallSiteNop:
1540 if ( _options.outputKind() != Options::kObjectFile ) {
1541 // change call site to a NOP
1542 set32LE(fixUpLocation, 0xD503201F);
1543 }
1544 break;
1545 case ld::Fixup::kindStoreARM64DtraceIsEnableSiteClear:
1546 if ( _options.outputKind() != Options::kObjectFile ) {
1547 // change call site to 'MOVZ X0,0'
1548 set32LE(fixUpLocation, 0xD2800000);
1549 }
1550 break;
a645023d 1551 case ld::Fixup::kindLazyTarget:
9543cb2f 1552 case ld::Fixup::kindIslandTarget:
a645023d
A
1553 break;
1554 case ld::Fixup::kindSetLazyOffset:
1555 assert(fit->binding == ld::Fixup::bindingDirectlyBound);
1556 accumulator = this->lazyBindingInfoOffsetForLazyPointerAddress(fit->u.target->finalAddress());
1557 break;
ebf6f434
A
1558 case ld::Fixup::kindDataInCodeStartData:
1559 case ld::Fixup::kindDataInCodeStartJT8:
1560 case ld::Fixup::kindDataInCodeStartJT16:
1561 case ld::Fixup::kindDataInCodeStartJT32:
1562 case ld::Fixup::kindDataInCodeStartJTA32:
1563 case ld::Fixup::kindDataInCodeEnd:
1564 break;
9543cb2f
A
1565 case ld::Fixup::kindLinkerOptimizationHint:
1566 // expand table of address/offsets used by hints
1567 lohExtra.addend = fit->u.addend;
1568 usedByHints[fit->offsetInAtom + (lohExtra.info.delta1 << 2)] = NULL;
1569 if ( lohExtra.info.count > 0 )
1570 usedByHints[fit->offsetInAtom + (lohExtra.info.delta2 << 2)] = NULL;
1571 if ( lohExtra.info.count > 1 )
1572 usedByHints[fit->offsetInAtom + (lohExtra.info.delta3 << 2)] = NULL;
1573 if ( lohExtra.info.count > 2 )
1574 usedByHints[fit->offsetInAtom + (lohExtra.info.delta4 << 2)] = NULL;
1575 break;
a645023d
A
1576 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
1577 accumulator = addressOf(state, fit, &toTarget);
1578 thumbTarget = targetIsThumb(state, fit);
1579 if ( thumbTarget )
1580 accumulator |= 1;
1581 if ( fit->contentAddendOnly )
1582 accumulator = 0;
afe874b1 1583 rangeCheckAbsolute32(accumulator, state, atom, fit);
a645023d
A
1584 set32LE(fixUpLocation, accumulator);
1585 break;
1586 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
1587 accumulator = addressOf(state, fit, &toTarget);
1588 if ( fit->contentAddendOnly )
1589 accumulator = 0;
1590 set64LE(fixUpLocation, accumulator);
1591 break;
1592 case ld::Fixup::kindStoreTargetAddressBigEndian32:
1593 accumulator = addressOf(state, fit, &toTarget);
1594 if ( fit->contentAddendOnly )
1595 accumulator = 0;
1596 set32BE(fixUpLocation, accumulator);
1597 break;
1598 case ld::Fixup::kindStoreTargetAddressBigEndian64:
1599 accumulator = addressOf(state, fit, &toTarget);
1600 if ( fit->contentAddendOnly )
1601 accumulator = 0;
1602 set64BE(fixUpLocation, accumulator);
1603 break;
1604 case ld::Fixup::kindSetTargetTLVTemplateOffsetLittleEndian32:
1605 accumulator = tlvTemplateOffsetOf(state, fit);
1606 set32LE(fixUpLocation, accumulator);
1607 break;
1608 case ld::Fixup::kindSetTargetTLVTemplateOffsetLittleEndian64:
1609 accumulator = tlvTemplateOffsetOf(state, fit);
1610 set64LE(fixUpLocation, accumulator);
1611 break;
1612 case ld::Fixup::kindStoreTargetAddressX86PCRel32:
1613 case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32:
1614 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad:
1615 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad:
1616 accumulator = addressOf(state, fit, &toTarget);
1617 if ( fit->contentDetlaToAddendOnly )
1618 accumulator = 0;
1619 if ( fit->contentAddendOnly )
1620 delta = 0;
1621 else
1622 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 4);
1623 rangeCheckRIP32(delta, state, atom, fit);
1624 set32LE(fixUpLocation, delta);
1625 break;
1626 case ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoad:
1627 set32LE(fixUpLocation, accumulator);
1628 break;
1629 case ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoadNowLEA:
1630 // TLV entry was optimized away, change movl instruction to a leal
1631 if ( fixUpLocation[-1] != 0xA1 )
1632 throw "TLV load reloc does not point to a movl <abs-address>,<reg> instruction";
1633 fixUpLocation[-1] = 0xB8;
1634 accumulator = addressOf(state, fit, &toTarget);
1635 set32LE(fixUpLocation, accumulator);
1636 break;
1637 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA:
1638 // GOT entry was optimized away, change movq instruction to a leaq
1639 if ( fixUpLocation[-2] != 0x8B )
1640 throw "GOT load reloc does not point to a movq instruction";
1641 fixUpLocation[-2] = 0x8D;
1642 accumulator = addressOf(state, fit, &toTarget);
1643 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 4);
1644 rangeCheckRIP32(delta, state, atom, fit);
1645 set32LE(fixUpLocation, delta);
1646 break;
1647 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA:
1648 // TLV entry was optimized away, change movq instruction to a leaq
1649 if ( fixUpLocation[-2] != 0x8B )
1650 throw "TLV load reloc does not point to a movq instruction";
1651 fixUpLocation[-2] = 0x8D;
1652 accumulator = addressOf(state, fit, &toTarget);
1653 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 4);
1654 rangeCheckRIP32(delta, state, atom, fit);
1655 set32LE(fixUpLocation, delta);
1656 break;
1657 case ld::Fixup::kindStoreTargetAddressARMBranch24:
1658 accumulator = addressOf(state, fit, &toTarget);
1659 thumbTarget = targetIsThumb(state, fit);
9543cb2f
A
1660 if ( toTarget->contentType() == ld::Atom::typeBranchIsland ) {
1661 // Branching to island. If ultimate target is in range, branch there directly.
1662 for (ld::Fixup::iterator islandfit = toTarget->fixupsBegin(), end=toTarget->fixupsEnd(); islandfit != end; ++islandfit) {
1663 if ( islandfit->kind == ld::Fixup::kindIslandTarget ) {
1664 const ld::Atom* islandTarget = NULL;
1665 uint64_t islandTargetAddress = addressOf(state, islandfit, &islandTarget);
1666 delta = islandTargetAddress - (atom->finalAddress() + fit->offsetInAtom + 4);
1667 if ( checkArmBranch24Displacement(delta) ) {
1668 toTarget = islandTarget;
1669 accumulator = islandTargetAddress;
1670 thumbTarget = targetIsThumb(state, islandfit);
1671 }
1672 break;
1673 }
1674 }
1675 }
a645023d
A
1676 if ( thumbTarget )
1677 accumulator |= 1;
1678 if ( fit->contentDetlaToAddendOnly )
1679 accumulator = 0;
1680 // fall into kindStoreARMBranch24 case
1681 case ld::Fixup::kindStoreARMBranch24:
1682 // The pc added will be +8 from the pc
1683 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 8);
1684 rangeCheckARMBranch24(delta, state, atom, fit);
1685 instruction = get32LE(fixUpLocation);
9543cb2f 1686 // Make sure we are calling arm with bl, thumb with blx
a645023d
A
1687 is_bl = ((instruction & 0xFF000000) == 0xEB000000);
1688 is_blx = ((instruction & 0xFE000000) == 0xFA000000);
afe874b1 1689 is_b = !is_blx && ((instruction & 0x0F000000) == 0x0A000000);
9543cb2f
A
1690 if ( (is_bl | is_blx) && thumbTarget ) {
1691 uint32_t opcode = 0xFA000000; // force to be blx
a645023d
A
1692 uint32_t disp = (uint32_t)(delta >> 2) & 0x00FFFFFF;
1693 uint32_t h_bit = (uint32_t)(delta << 23) & 0x01000000;
1694 newInstruction = opcode | h_bit | disp;
1695 }
9543cb2f
A
1696 else if ( (is_bl | is_blx) && !thumbTarget ) {
1697 uint32_t opcode = 0xEB000000; // force to be bl
a645023d
A
1698 uint32_t disp = (uint32_t)(delta >> 2) & 0x00FFFFFF;
1699 newInstruction = opcode | disp;
1700 }
afe874b1
A
1701 else if ( is_b && thumbTarget ) {
1702 if ( fit->contentDetlaToAddendOnly )
1703 newInstruction = (instruction & 0xFF000000) | ((uint32_t)(delta >> 2) & 0x00FFFFFF);
1704 else
1705 throwf("no pc-rel bx arm instruction. Can't fix up branch to %s in %s",
1706 referenceTargetAtomName(state, fit), atom->name());
1707 }
a645023d
A
1708 else if ( !is_bl && !is_blx && thumbTarget ) {
1709 throwf("don't know how to convert instruction %x referencing %s to thumb",
1710 instruction, referenceTargetAtomName(state, fit));
1711 }
1712 else {
1713 newInstruction = (instruction & 0xFF000000) | ((uint32_t)(delta >> 2) & 0x00FFFFFF);
1714 }
1715 set32LE(fixUpLocation, newInstruction);
1716 break;
1717 case ld::Fixup::kindStoreTargetAddressThumbBranch22:
1718 accumulator = addressOf(state, fit, &toTarget);
1719 thumbTarget = targetIsThumb(state, fit);
9543cb2f
A
1720 if ( toTarget->contentType() == ld::Atom::typeBranchIsland ) {
1721 // branching to island, so see if ultimate target is in range
1722 // and if so branch to ultimate target instead.
1723 for (ld::Fixup::iterator islandfit = toTarget->fixupsBegin(), end=toTarget->fixupsEnd(); islandfit != end; ++islandfit) {
1724 if ( islandfit->kind == ld::Fixup::kindIslandTarget ) {
1725 const ld::Atom* islandTarget = NULL;
1726 uint64_t islandTargetAddress = addressOf(state, islandfit, &islandTarget);
1727 delta = islandTargetAddress - (atom->finalAddress() + fit->offsetInAtom + 4);
1728 if ( checkThumbBranch22Displacement(delta) ) {
1729 toTarget = islandTarget;
1730 accumulator = islandTargetAddress;
1731 thumbTarget = targetIsThumb(state, islandfit);
1732 }
1733 break;
1734 }
1735 }
1736 }
a645023d
A
1737 if ( thumbTarget )
1738 accumulator |= 1;
1739 if ( fit->contentDetlaToAddendOnly )
1740 accumulator = 0;
1741 // fall into kindStoreThumbBranch22 case
1742 case ld::Fixup::kindStoreThumbBranch22:
1743 instruction = get32LE(fixUpLocation);
1744 is_bl = ((instruction & 0xD000F800) == 0xD000F000);
1745 is_blx = ((instruction & 0xD000F800) == 0xC000F000);
1746 is_b = ((instruction & 0xD000F800) == 0x9000F000);
1747 // If the target is not thumb, we will be generating a blx instruction
1748 // Since blx cannot have the low bit set, set bit[1] of the target to
1749 // bit[1] of the base address, so that the difference is a multiple of
1750 // 4 bytes.
afe874b1 1751 if ( !thumbTarget && !fit->contentDetlaToAddendOnly ) {
a645023d
A
1752 accumulator &= -3ULL;
1753 accumulator |= ((atom->finalAddress() + fit->offsetInAtom ) & 2LL);
1754 }
1755 // The pc added will be +4 from the pc
1756 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 4);
1757 rangeCheckThumbBranch22(delta, state, atom, fit);
afe874b1 1758 if ( _options.preferSubArchitecture() && _options.archSupportsThumb2() ) {
a645023d
A
1759 // The instruction is really two instructions:
1760 // The lower 16 bits are the first instruction, which contains the high
1761 // 11 bits of the displacement.
1762 // The upper 16 bits are the second instruction, which contains the low
1763 // 11 bits of the displacement, as well as differentiating bl and blx.
1764 uint32_t s = (uint32_t)(delta >> 24) & 0x1;
1765 uint32_t i1 = (uint32_t)(delta >> 23) & 0x1;
1766 uint32_t i2 = (uint32_t)(delta >> 22) & 0x1;
1767 uint32_t imm10 = (uint32_t)(delta >> 12) & 0x3FF;
1768 uint32_t imm11 = (uint32_t)(delta >> 1) & 0x7FF;
1769 uint32_t j1 = (i1 == s);
1770 uint32_t j2 = (i2 == s);
1771 if ( is_bl ) {
1772 if ( thumbTarget )
1773 instruction = 0xD000F000; // keep bl
1774 else
1775 instruction = 0xC000F000; // change to blx
1776 }
1777 else if ( is_blx ) {
1778 if ( thumbTarget )
1779 instruction = 0xD000F000; // change to bl
1780 else
1781 instruction = 0xC000F000; // keep blx
1782 }
1783 else if ( is_b ) {
a645023d 1784 instruction = 0x9000F000; // keep b
afe874b1
A
1785 if ( !thumbTarget && !fit->contentDetlaToAddendOnly ) {
1786 throwf("armv7 has no pc-rel bx thumb instruction. Can't fix up branch to %s in %s",
1787 referenceTargetAtomName(state, fit), atom->name());
1788 }
a645023d 1789 }
afe874b1 1790 else {
a645023d
A
1791 if ( !thumbTarget )
1792 throwf("don't know how to convert branch instruction %x referencing %s to bx",
1793 instruction, referenceTargetAtomName(state, fit));
1794 instruction = 0x9000F000; // keep b
1795 }
1796 uint32_t nextDisp = (j1 << 13) | (j2 << 11) | imm11;
1797 uint32_t firstDisp = (s << 10) | imm10;
1798 newInstruction = instruction | (nextDisp << 16) | firstDisp;
d425e388
A
1799 //warning("s=%d, j1=%d, j2=%d, imm10=0x%0X, imm11=0x%0X, instruction=0x%08X, first=0x%04X, next=0x%04X, new=0x%08X, disp=0x%llX for %s to %s\n",
1800 // s, j1, j2, imm10, imm11, instruction, firstDisp, nextDisp, newInstruction, delta, atom->name(), toTarget->name());
a645023d
A
1801 set32LE(fixUpLocation, newInstruction);
1802 }
1803 else {
1804 // The instruction is really two instructions:
1805 // The lower 16 bits are the first instruction, which contains the high
1806 // 11 bits of the displacement.
1807 // The upper 16 bits are the second instruction, which contains the low
1808 // 11 bits of the displacement, as well as differentiating bl and blx.
1809 uint32_t firstDisp = (uint32_t)(delta >> 12) & 0x7FF;
1810 uint32_t nextDisp = (uint32_t)(delta >> 1) & 0x7FF;
1811 if ( is_bl && !thumbTarget ) {
1812 instruction = 0xE800F000;
1813 }
1814 else if ( is_blx && thumbTarget ) {
1815 instruction = 0xF800F000;
1816 }
afe874b1
A
1817 else if ( is_b ) {
1818 instruction = 0x9000F000; // keep b
1819 if ( !thumbTarget && !fit->contentDetlaToAddendOnly ) {
1820 throwf("armv6 has no pc-rel bx thumb instruction. Can't fix up branch to %s in %s",
1821 referenceTargetAtomName(state, fit), atom->name());
1822 }
1823 }
a645023d
A
1824 else {
1825 instruction = instruction & 0xF800F800;
1826 }
1827 newInstruction = instruction | (nextDisp << 16) | firstDisp;
1828 set32LE(fixUpLocation, newInstruction);
1829 }
1830 break;
1831 case ld::Fixup::kindStoreARMLow16:
1832 {
1833 uint32_t imm4 = (accumulator & 0x0000F000) >> 12;
1834 uint32_t imm12 = accumulator & 0x00000FFF;
1835 instruction = get32LE(fixUpLocation);
1836 newInstruction = (instruction & 0xFFF0F000) | (imm4 << 16) | imm12;
1837 set32LE(fixUpLocation, newInstruction);
1838 }
1839 break;
1840 case ld::Fixup::kindStoreARMHigh16:
1841 {
1842 uint32_t imm4 = (accumulator & 0xF0000000) >> 28;
1843 uint32_t imm12 = (accumulator & 0x0FFF0000) >> 16;
1844 instruction = get32LE(fixUpLocation);
1845 newInstruction = (instruction & 0xFFF0F000) | (imm4 << 16) | imm12;
1846 set32LE(fixUpLocation, newInstruction);
1847 }
1848 break;
1849 case ld::Fixup::kindStoreThumbLow16:
1850 {
1851 uint32_t imm4 = (accumulator & 0x0000F000) >> 12;
1852 uint32_t i = (accumulator & 0x00000800) >> 11;
1853 uint32_t imm3 = (accumulator & 0x00000700) >> 8;
1854 uint32_t imm8 = accumulator & 0x000000FF;
1855 instruction = get32LE(fixUpLocation);
1856 newInstruction = (instruction & 0x8F00FBF0) | imm4 | (i << 10) | (imm3 << 28) | (imm8 << 16);
1857 set32LE(fixUpLocation, newInstruction);
1858 }
1859 break;
1860 case ld::Fixup::kindStoreThumbHigh16:
1861 {
1862 uint32_t imm4 = (accumulator & 0xF0000000) >> 28;
1863 uint32_t i = (accumulator & 0x08000000) >> 27;
1864 uint32_t imm3 = (accumulator & 0x07000000) >> 24;
1865 uint32_t imm8 = (accumulator & 0x00FF0000) >> 16;
1866 instruction = get32LE(fixUpLocation);
1867 newInstruction = (instruction & 0x8F00FBF0) | imm4 | (i << 10) | (imm3 << 28) | (imm8 << 16);
1868 set32LE(fixUpLocation, newInstruction);
1869 }
1870 break;
f80fe69f
A
1871#if SUPPORT_ARCH_arm64
1872 case ld::Fixup::kindStoreTargetAddressARM64Branch26:
1873 accumulator = addressOf(state, fit, &toTarget);
1874 // fall into kindStoreARM64Branch26 case
1875 case ld::Fixup::kindStoreARM64Branch26:
1876 if ( fit->contentAddendOnly )
1877 delta = accumulator;
1878 else
1879 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom);
1880 rangeCheckARM64Branch26(delta, state, atom, fit);
1881 instruction = get32LE(fixUpLocation);
1882 newInstruction = (instruction & 0xFC000000) | ((uint32_t)(delta >> 2) & 0x03FFFFFF);
1883 set32LE(fixUpLocation, newInstruction);
1884 break;
1885 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21:
1886 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
1887 case ld::Fixup::kindStoreTargetAddressARM64Page21:
9543cb2f
A
1888 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21:
1889 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPage21:
f80fe69f
A
1890 accumulator = addressOf(state, fit, &toTarget);
1891 // fall into kindStoreARM64Branch26 case
1892 case ld::Fixup::kindStoreARM64GOTLeaPage21:
1893 case ld::Fixup::kindStoreARM64GOTLoadPage21:
1894 case ld::Fixup::kindStoreARM64TLVPLoadPage21:
9543cb2f 1895 case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPage21:
f80fe69f
A
1896 case ld::Fixup::kindStoreARM64Page21:
1897 {
1898 // the ADRP instruction adds the imm << 12 to the page that the pc is on
1899 if ( fit->contentAddendOnly )
1900 delta = 0;
1901 else
1902 delta = (accumulator & (-4096)) - ((atom->finalAddress() + fit->offsetInAtom) & (-4096));
1903 rangeCheckARM64Page21(delta, state, atom, fit);
1904 instruction = get32LE(fixUpLocation);
1905 uint32_t immhi = (delta >> 9) & (0x00FFFFE0);
1906 uint32_t immlo = (delta << 17) & (0x60000000);
1907 newInstruction = (instruction & 0x9F00001F) | immlo | immhi;
1908 set32LE(fixUpLocation, newInstruction);
1909 }
1910 break;
1911 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12:
1912 case ld::Fixup::kindStoreTargetAddressARM64PageOff12:
9543cb2f 1913 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12:
f80fe69f
A
1914 accumulator = addressOf(state, fit, &toTarget);
1915 // fall into kindAddressARM64PageOff12 case
1916 case ld::Fixup::kindStoreARM64TLVPLoadPageOff12:
1917 case ld::Fixup::kindStoreARM64GOTLoadPageOff12:
1918 case ld::Fixup::kindStoreARM64PageOff12:
1919 {
1920 uint32_t offset = accumulator & 0x00000FFF;
1921 instruction = get32LE(fixUpLocation);
1922 // LDR/STR instruction have implicit scale factor, need to compensate for that
1923 if ( instruction & 0x08000000 ) {
1924 uint32_t implictShift = ((instruction >> 30) & 0x3);
1925 switch ( implictShift ) {
1926 case 0:
1927 if ( (instruction & 0x04800000) == 0x04800000 ) {
1928 // vector and byte LDR/STR have same "size" bits, need to check other bits to differenciate
1929 implictShift = 4;
1930 if ( (offset & 0xF) != 0 ) {
1931 throwf("128-bit LDR/STR not 16-byte aligned: from %s (0x%08llX) to %s (0x%08llX)",
1932 atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fit),
1933 addressOf(state, fit, &toTarget));
1934 }
1935 }
1936 break;
1937 case 1:
1938 if ( (offset & 0x1) != 0 ) {
1939 throwf("16-bit LDR/STR not 2-byte aligned: from %s (0x%08llX) to %s (0x%08llX)",
1940 atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fit),
1941 addressOf(state, fit, &toTarget));
1942 }
1943 break;
1944 case 2:
1945 if ( (offset & 0x3) != 0 ) {
1946 throwf("32-bit LDR/STR not 4-byte aligned: from %s (0x%08llX) to %s (0x%08llX)",
1947 atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fit),
1948 addressOf(state, fit, &toTarget));
1949 }
1950 break;
1951 case 3:
1952 if ( (offset & 0x7) != 0 ) {
1953 throwf("64-bit LDR/STR not 8-byte aligned: from %s (0x%08llX) to %s (0x%08llX)",
1954 atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fit),
1955 addressOf(state, fit, &toTarget));
1956 }
1957 break;
1958 }
1959 // compensate for implicit scale
1960 offset >>= implictShift;
1961 }
1962 if ( fit->contentAddendOnly )
1963 offset = 0;
1964 uint32_t imm12 = offset << 10;
1965 newInstruction = (instruction & 0xFFC003FF) | imm12;
1966 set32LE(fixUpLocation, newInstruction);
1967 }
1968 break;
1969 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPageOff12:
1970 accumulator = addressOf(state, fit, &toTarget);
1971 // fall into kindStoreARM64GOTLoadPage21 case
1972 case ld::Fixup::kindStoreARM64GOTLeaPageOff12:
1973 {
1974 // GOT entry was optimized away, change LDR instruction to a ADD
1975 instruction = get32LE(fixUpLocation);
1976 if ( (instruction & 0xFFC00000) != 0xF9400000 )
1977 throwf("GOT load reloc does not point to a LDR instruction in %s", atom->name());
1978 uint32_t offset = accumulator & 0x00000FFF;
1979 uint32_t imm12 = offset << 10;
1980 newInstruction = 0x91000000 | imm12 | (instruction & 0x000003FF);
1981 set32LE(fixUpLocation, newInstruction);
1982 }
1983 break;
9543cb2f
A
1984 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12:
1985 accumulator = addressOf(state, fit, &toTarget);
1986 // fall into kindStoreARM64TLVPLeaPageOff12 case
1987 case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPageOff12:
1988 {
1989 // TLV thunk in same linkage unit, so LEA it directly, changing LDR instruction to a ADD
1990 instruction = get32LE(fixUpLocation);
1991 if ( (instruction & 0xFFC00000) != 0xF9400000 )
1992 throwf("TLV load reloc does not point to a LDR instruction in %s", atom->name());
1993 uint32_t offset = accumulator & 0x00000FFF;
1994 uint32_t imm12 = offset << 10;
1995 newInstruction = 0x91000000 | imm12 | (instruction & 0x000003FF);
1996 set32LE(fixUpLocation, newInstruction);
1997 }
1998 break;
f80fe69f
A
1999 case ld::Fixup::kindStoreARM64PointerToGOT:
2000 set64LE(fixUpLocation, accumulator);
2001 break;
2002 case ld::Fixup::kindStoreARM64PCRelToGOT:
2003 if ( fit->contentAddendOnly )
2004 delta = accumulator;
2005 else
2006 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom);
2007 set32LE(fixUpLocation, delta);
2008 break;
2009#endif
a645023d
A
2010 }
2011 }
9543cb2f
A
2012
2013 // after all fixups are done on atom, if there are potential optimizations, do those
2014 if ( (usedByHints.size() != 0) && (_options.outputKind() != Options::kObjectFile) && !_options.ignoreOptimizationHints() ) {
2015 // fill in second part of usedByHints map, so we can see the target of fixups that might be optimized
2016 for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
2017 switch ( fit->kind ) {
2018 case ld::Fixup::kindLinkerOptimizationHint:
2019 case ld::Fixup::kindNoneFollowOn:
2020 case ld::Fixup::kindNoneGroupSubordinate:
2021 case ld::Fixup::kindNoneGroupSubordinateFDE:
2022 case ld::Fixup::kindNoneGroupSubordinateLSDA:
2023 case ld::Fixup::kindNoneGroupSubordinatePersonality:
2024 break;
2025 default:
2026 if ( fit->firstInCluster() ) {
2027 std::map<uint32_t, const Fixup*>::iterator pos = usedByHints.find(fit->offsetInAtom);
2028 if ( pos != usedByHints.end() ) {
2029 assert(pos->second == NULL && "two fixups in same hint location");
2030 pos->second = fit;
2031 //fprintf(stderr, "setting %s usedByHints[0x%04X], kind = %d\n", atom->name(), fit->offsetInAtom, fit->kind);
2032 }
2033 }
2034 }
2035 }
2036
2037 // apply hints pass 1
2038 for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
2039 if ( fit->kind != ld::Fixup::kindLinkerOptimizationHint )
2040 continue;
2041 InstructionInfo infoA;
2042 InstructionInfo infoB;
2043 InstructionInfo infoC;
2044 InstructionInfo infoD;
2045 LoadStoreInfo ldrInfoB, ldrInfoC;
2046 AddInfo addInfoB;
2047 AdrpInfo adrpInfoA;
2048 bool usableSegment;
2049 bool targetFourByteAligned;
2050 bool literalableSize, isADRP, isADD, isLDR, isSTR;
2051 //uint8_t loadSize, destReg;
2052 //uint32_t scaledOffset;
2053 //uint32_t imm12;
2054 ld::Fixup::LOH_arm64 alt;
2055 alt.addend = fit->u.addend;
2056 setInfo(state, atom, buffer, usedByHints, fit->offsetInAtom, (alt.info.delta1 << 2), &infoA);
2057 if ( alt.info.count > 0 )
2058 setInfo(state, atom, buffer, usedByHints, fit->offsetInAtom, (alt.info.delta2 << 2), &infoB);
2059 if ( alt.info.count > 1 )
2060 setInfo(state, atom, buffer, usedByHints, fit->offsetInAtom, (alt.info.delta3 << 2), &infoC);
2061 if ( alt.info.count > 2 )
2062 setInfo(state, atom, buffer, usedByHints, fit->offsetInAtom, (alt.info.delta4 << 2), &infoD);
2063
2064 switch ( alt.info.kind ) {
2065 case LOH_ARM64_ADRP_ADRP:
2066 // processed in pass 2 beacuse some ADRP may have been removed
2067 break;
2068 case LOH_ARM64_ADRP_LDR:
2069 LOH_ASSERT(alt.info.count == 1);
2070 LOH_ASSERT(isPageKind(infoA.fixup));
2071 LOH_ASSERT(isPageOffsetKind(infoB.fixup));
2072 LOH_ASSERT(infoA.target == infoB.target);
2073 LOH_ASSERT(infoA.targetAddress == infoB.targetAddress);
2074 usableSegment = ( !_options.sharedRegionEligible() || (strcmp(atom->section().segmentName(), infoB.target->section().segmentName()) == 0) );
2075 isADRP = parseADRP(infoA.instruction, adrpInfoA);
2076 LOH_ASSERT(isADRP);
2077 isLDR = parseLoadOrStore(infoB.instruction, ldrInfoB);
2078 LOH_ASSERT(isLDR);
2079 LOH_ASSERT(ldrInfoB.baseReg == adrpInfoA.destReg);
2080 LOH_ASSERT(ldrInfoB.offset == (infoA.targetAddress & 0x00000FFF));
2081 literalableSize = ( (ldrInfoB.size != 1) && (ldrInfoB.size != 2) );
2082 targetFourByteAligned = ( (infoA.targetAddress & 0x3) == 0 );
2083 if ( literalableSize && usableSegment && targetFourByteAligned && withinOneMeg(infoB.instructionAddress, infoA.targetAddress) ) {
2084 set32LE(infoA.instructionContent, makeNOP());
2085 set32LE(infoB.instructionContent, makeLDR_literal(ldrInfoB, infoA.targetAddress, infoB.instructionAddress));
2086 if ( _options.verboseOptimizationHints() )
2087 fprintf(stderr, "adrp-ldr at 0x%08llX transformed to LDR literal\n", infoB.instructionAddress);
2088 }
2089 else {
2090 if ( _options.verboseOptimizationHints() )
2091 fprintf(stderr, "adrp-ldr at 0x%08llX not transformed, isLDR=%d, literalableSize=%d, inRange=%d, usableSegment=%d, scaledOffset=%d\n",
2092 infoB.instructionAddress, isLDR, literalableSize, withinOneMeg(infoB.instructionAddress, infoA.targetAddress), usableSegment, ldrInfoB.offset);
2093 }
2094 break;
2095 case LOH_ARM64_ADRP_ADD_LDR:
2096 LOH_ASSERT(alt.info.count == 2);
2097 LOH_ASSERT(isPageKind(infoA.fixup));
2098 LOH_ASSERT(isPageOffsetKind(infoB.fixup));
2099 LOH_ASSERT(infoC.fixup == NULL);
2100 LOH_ASSERT(infoA.target == infoB.target);
2101 LOH_ASSERT(infoA.targetAddress == infoB.targetAddress);
2102 usableSegment = ( !_options.sharedRegionEligible() || (strcmp(atom->section().segmentName(), infoB.target->section().segmentName()) == 0) );
2103 isADRP = parseADRP(infoA.instruction, adrpInfoA);
2104 LOH_ASSERT(isADRP);
2105 isADD = parseADD(infoB.instruction, addInfoB);
2106 LOH_ASSERT(isADD);
2107 LOH_ASSERT(adrpInfoA.destReg == addInfoB.srcReg);
2108 isLDR = parseLoadOrStore(infoC.instruction, ldrInfoC);
2109 LOH_ASSERT(isLDR);
2110 LOH_ASSERT(addInfoB.destReg == ldrInfoC.baseReg);
2111 targetFourByteAligned = ( ((infoB.targetAddress+ldrInfoC.offset) & 0x3) == 0 );
2112 literalableSize = ( (ldrInfoC.size != 1) && (ldrInfoC.size != 2) );
2113 if ( literalableSize && usableSegment && targetFourByteAligned && withinOneMeg(infoC.instructionAddress, infoA.targetAddress+ldrInfoC.offset) ) {
2114 // can do T1 transformation to LDR literal
2115 set32LE(infoA.instructionContent, makeNOP());
2116 set32LE(infoB.instructionContent, makeNOP());
2117 set32LE(infoC.instructionContent, makeLDR_literal(ldrInfoC, infoA.targetAddress+ldrInfoC.offset, infoC.instructionAddress));
2118 if ( _options.verboseOptimizationHints() ) {
2119 fprintf(stderr, "adrp-add-ldr at 0x%08llX T1 transformed to LDR literal\n", infoC.instructionAddress);
2120 }
2121 }
2122 else if ( usableSegment && withinOneMeg(infoA.instructionAddress, infoA.targetAddress+ldrInfoC.offset) ) {
2123 // can to T4 transformation and turn ADRP/ADD into ADR
2124 set32LE(infoA.instructionContent, makeADR(ldrInfoC.baseReg, infoA.targetAddress+ldrInfoC.offset, infoA.instructionAddress));
2125 set32LE(infoB.instructionContent, makeNOP());
2126 ldrInfoC.offset = 0; // offset is now in ADR instead of ADD or LDR
2127 set32LE(infoC.instructionContent, makeLoadOrStore(ldrInfoC));
2128 set32LE(infoC.instructionContent, infoC.instruction & 0xFFC003FF);
2129 if ( _options.verboseOptimizationHints() )
2130 fprintf(stderr, "adrp-add-ldr at 0x%08llX T4 transformed to ADR/LDR\n", infoB.instructionAddress);
2131 }
2132 else if ( ((infoB.targetAddress % ldrInfoC.size) == 0) && (ldrInfoC.offset == 0) ) {
2133 // can do T2 transformation by merging ADD into LD
2134 // Leave ADRP as-is
2135 set32LE(infoB.instructionContent, makeNOP());
2136 ldrInfoC.offset += addInfoB.addend;
2137 set32LE(infoC.instructionContent, makeLoadOrStore(ldrInfoC));
2138 if ( _options.verboseOptimizationHints() )
2139 fprintf(stderr, "adrp-add-ldr at 0x%08llX T2 transformed to ADRP/LDR \n", infoC.instructionAddress);
2140 }
2141 else {
2142 if ( _options.verboseOptimizationHints() )
2143 fprintf(stderr, "adrp-add-ldr at 0x%08llX could not be transformed, loadSize=%d, literalableSize=%d, inRange=%d, usableSegment=%d, targetFourByteAligned=%d, imm12=%d\n",
2144 infoC.instructionAddress, ldrInfoC.size, literalableSize, withinOneMeg(infoC.instructionAddress, infoA.targetAddress+ldrInfoC.offset), usableSegment, targetFourByteAligned, ldrInfoC.offset);
2145 }
2146 break;
2147 case LOH_ARM64_ADRP_ADD:
2148 LOH_ASSERT(alt.info.count == 1);
2149 LOH_ASSERT(isPageKind(infoA.fixup));
2150 LOH_ASSERT(isPageOffsetKind(infoB.fixup));
2151 LOH_ASSERT(infoA.target == infoB.target);
2152 LOH_ASSERT(infoA.targetAddress == infoB.targetAddress);
2153 isADRP = parseADRP(infoA.instruction, adrpInfoA);
2154 LOH_ASSERT(isADRP);
2155 isADD = parseADD(infoB.instruction, addInfoB);
2156 LOH_ASSERT(isADD);
2157 LOH_ASSERT(adrpInfoA.destReg == addInfoB.srcReg);
2158 usableSegment = ( !_options.sharedRegionEligible() || (strcmp(atom->section().segmentName(), infoB.target->section().segmentName()) == 0) );
2159 if ( usableSegment && withinOneMeg(infoA.targetAddress, infoA.instructionAddress) ) {
2160 // can do T4 transformation and use ADR
2161 set32LE(infoA.instructionContent, makeADR(addInfoB.destReg, infoA.targetAddress, infoA.instructionAddress));
2162 set32LE(infoB.instructionContent, makeNOP());
2163 if ( _options.verboseOptimizationHints() )
2164 fprintf(stderr, "adrp-add at 0x%08llX transformed to ADR\n", infoB.instructionAddress);
2165 }
2166 else {
2167 if ( _options.verboseOptimizationHints() )
2168 fprintf(stderr, "adrp-add at 0x%08llX not transformed, isAdd=%d, inRange=%d, usableSegment=%d\n",
2169 infoB.instructionAddress, isADD, withinOneMeg(infoA.targetAddress, infoA.instructionAddress), usableSegment);
2170 }
2171 break;
2172 case LOH_ARM64_ADRP_LDR_GOT_LDR:
2173 LOH_ASSERT(alt.info.count == 2);
2174 LOH_ASSERT(isPageKind(infoA.fixup, true));
2175 LOH_ASSERT(isPageOffsetKind(infoB.fixup, true));
2176 LOH_ASSERT(infoC.fixup == NULL);
2177 LOH_ASSERT(infoA.target == infoB.target);
2178 LOH_ASSERT(infoA.targetAddress == infoB.targetAddress);
2179 isADRP = parseADRP(infoA.instruction, adrpInfoA);
2180 LOH_ASSERT(isADRP);
2181 isLDR = parseLoadOrStore(infoC.instruction, ldrInfoC);
2182 LOH_ASSERT(isLDR);
2183 LOH_ASSERT(ldrInfoC.offset == 0);
2184 isADD = parseADD(infoB.instruction, addInfoB);
2185 isLDR = parseLoadOrStore(infoB.instruction, ldrInfoB);
2186 if ( isLDR ) {
2187 // target of GOT is external
2188 LOH_ASSERT(ldrInfoB.size == 8);
2189 LOH_ASSERT(!ldrInfoB.isFloat);
2190 LOH_ASSERT(ldrInfoC.baseReg == ldrInfoB.reg);
2191 //fprintf(stderr, "infoA.target=%p, %s, infoA.targetAddress=0x%08llX\n", infoA.target, infoA.target->name(), infoA.targetAddress);
2192 usableSegment = ( !_options.sharedRegionEligible() || (strcmp(atom->section().segmentName(), infoB.target->section().segmentName()) == 0) );
2193 targetFourByteAligned = ( ((infoA.targetAddress) & 0x3) == 0 );
2194 if ( usableSegment && targetFourByteAligned && withinOneMeg(infoB.instructionAddress, infoA.targetAddress) ) {
2195 // can do T5 transform
2196 set32LE(infoA.instructionContent, makeNOP());
2197 set32LE(infoB.instructionContent, makeLDR_literal(ldrInfoB, infoA.targetAddress, infoB.instructionAddress));
2198 if ( _options.verboseOptimizationHints() ) {
2199 fprintf(stderr, "adrp-ldr-got-ldr at 0x%08llX T5 transformed to LDR literal of GOT plus LDR\n", infoC.instructionAddress);
2200 }
2201 }
2202 else {
2203 if ( _options.verboseOptimizationHints() )
2204 fprintf(stderr, "adrp-ldr-got-ldr at 0x%08llX no optimization done\n", infoC.instructionAddress);
2205 }
2206 }
2207 else if ( isADD ) {
2208 // target of GOT is in same linkage unit and B instruction was changed to ADD to compute LEA of target
2209 LOH_ASSERT(addInfoB.srcReg == adrpInfoA.destReg);
2210 LOH_ASSERT(addInfoB.destReg == ldrInfoC.baseReg);
2211 usableSegment = ( !_options.sharedRegionEligible() || (strcmp(atom->section().segmentName(), infoB.target->section().segmentName()) == 0) );
2212 targetFourByteAligned = ( ((infoA.targetAddress) & 0x3) == 0 );
2213 literalableSize = ( (ldrInfoC.size != 1) && (ldrInfoC.size != 2) );
2214 if ( usableSegment && literalableSize && targetFourByteAligned && withinOneMeg(infoC.instructionAddress, infoA.targetAddress) ) {
2215 // can do T1 transform
2216 set32LE(infoA.instructionContent, makeNOP());
2217 set32LE(infoB.instructionContent, makeNOP());
2218 set32LE(infoC.instructionContent, makeLDR_literal(ldrInfoC, infoA.targetAddress, infoC.instructionAddress));
2219 if ( _options.verboseOptimizationHints() )
2220 fprintf(stderr, "adrp-ldr-got-ldr at 0x%08llX T1 transformed to LDR literal\n", infoC.instructionAddress);
2221 }
2222 else if ( usableSegment && withinOneMeg(infoA.instructionAddress, infoA.targetAddress) ) {
2223 // can do T4 transform
2224 set32LE(infoA.instructionContent, makeADR(ldrInfoC.baseReg, infoA.targetAddress, infoA.instructionAddress));
2225 set32LE(infoB.instructionContent, makeNOP());
2226 set32LE(infoC.instructionContent, makeLoadOrStore(ldrInfoC));
2227 if ( _options.verboseOptimizationHints() ) {
2228 fprintf(stderr, "adrp-ldr-got-ldr at 0x%08llX T4 transformed to ADR/LDR\n", infoC.instructionAddress);
2229 }
2230 }
2231 else if ( (infoA.targetAddress % ldrInfoC.size) == 0 ) {
2232 // can do T2 transform
2233 set32LE(infoB.instructionContent, makeNOP());
2234 ldrInfoC.baseReg = adrpInfoA.destReg;
2235 ldrInfoC.offset = addInfoB.addend;
2236 set32LE(infoC.instructionContent, makeLoadOrStore(ldrInfoC));
2237 if ( _options.verboseOptimizationHints() ) {
2238 fprintf(stderr, "adrp-ldr-got-ldr at 0x%08llX T4 transformed to ADRP/NOP/LDR\n", infoC.instructionAddress);
2239 }
2240 }
2241 else {
2242 // T3 transform already done by ld::passes:got:doPass()
2243 if ( _options.verboseOptimizationHints() ) {
2244 fprintf(stderr, "adrp-ldr-got-ldr at 0x%08llX T3 transformed to ADRP/ADD/LDR\n", infoC.instructionAddress);
2245 }
2246 }
2247 }
2248 else {
2249 if ( _options.verboseOptimizationHints() )
2250 fprintf(stderr, "adrp-ldr-got-ldr at 0x%08llX not ADD or LDR\n", infoC.instructionAddress);
2251 }
2252 break;
2253 case LOH_ARM64_ADRP_ADD_STR:
2254 LOH_ASSERT(alt.info.count == 2);
2255 LOH_ASSERT(isPageKind(infoA.fixup));
2256 LOH_ASSERT(isPageOffsetKind(infoB.fixup));
2257 LOH_ASSERT(infoC.fixup == NULL);
2258 LOH_ASSERT(infoA.target == infoB.target);
2259 LOH_ASSERT(infoA.targetAddress == infoB.targetAddress);
2260 usableSegment = ( !_options.sharedRegionEligible() || (strcmp(atom->section().segmentName(), infoB.target->section().segmentName()) == 0) );
2261 isADRP = parseADRP(infoA.instruction, adrpInfoA);
2262 LOH_ASSERT(isADRP);
2263 isADD = parseADD(infoB.instruction, addInfoB);
2264 LOH_ASSERT(isADD);
2265 LOH_ASSERT(adrpInfoA.destReg == addInfoB.srcReg);
2266 isSTR = (parseLoadOrStore(infoC.instruction, ldrInfoC) && ldrInfoC.isStore);
2267 LOH_ASSERT(isSTR);
2268 LOH_ASSERT(addInfoB.destReg == ldrInfoC.baseReg);
2269 if ( usableSegment && withinOneMeg(infoA.instructionAddress, infoA.targetAddress+ldrInfoC.offset) ) {
2270 // can to T4 transformation and turn ADRP/ADD into ADR
2271 set32LE(infoA.instructionContent, makeADR(ldrInfoC.baseReg, infoA.targetAddress+ldrInfoC.offset, infoA.instructionAddress));
2272 set32LE(infoB.instructionContent, makeNOP());
2273 ldrInfoC.offset = 0; // offset is now in ADR instead of ADD or LDR
2274 set32LE(infoC.instructionContent, makeLoadOrStore(ldrInfoC));
2275 set32LE(infoC.instructionContent, infoC.instruction & 0xFFC003FF);
2276 if ( _options.verboseOptimizationHints() )
2277 fprintf(stderr, "adrp-add-str at 0x%08llX T4 transformed to ADR/STR\n", infoB.instructionAddress);
2278 }
2279 else if ( ((infoB.targetAddress % ldrInfoC.size) == 0) && (ldrInfoC.offset == 0) ) {
2280 // can do T2 transformation by merging ADD into STR
2281 // Leave ADRP as-is
2282 set32LE(infoB.instructionContent, makeNOP());
2283 ldrInfoC.offset += addInfoB.addend;
2284 set32LE(infoC.instructionContent, makeLoadOrStore(ldrInfoC));
2285 if ( _options.verboseOptimizationHints() )
2286 fprintf(stderr, "adrp-add-str at 0x%08llX T2 transformed to ADRP/STR \n", infoC.instructionAddress);
2287 }
2288 else {
2289 if ( _options.verboseOptimizationHints() )
2290 fprintf(stderr, "adrp-add-str at 0x%08llX could not be transformed, loadSize=%d, inRange=%d, usableSegment=%d, imm12=%d\n",
2291 infoC.instructionAddress, ldrInfoC.size, withinOneMeg(infoC.instructionAddress, infoA.targetAddress+ldrInfoC.offset), usableSegment, ldrInfoC.offset);
2292 }
2293 break;
2294 case LOH_ARM64_ADRP_LDR_GOT_STR:
2295 LOH_ASSERT(alt.info.count == 2);
2296 LOH_ASSERT(isPageKind(infoA.fixup, true));
2297 LOH_ASSERT(isPageOffsetKind(infoB.fixup, true));
2298 LOH_ASSERT(infoC.fixup == NULL);
2299 LOH_ASSERT(infoA.target == infoB.target);
2300 LOH_ASSERT(infoA.targetAddress == infoB.targetAddress);
2301 isADRP = parseADRP(infoA.instruction, adrpInfoA);
2302 LOH_ASSERT(isADRP);
2303 isSTR = (parseLoadOrStore(infoC.instruction, ldrInfoC) && ldrInfoC.isStore);
2304 LOH_ASSERT(isSTR);
2305 LOH_ASSERT(ldrInfoC.offset == 0);
2306 isADD = parseADD(infoB.instruction, addInfoB);
2307 isLDR = parseLoadOrStore(infoB.instruction, ldrInfoB);
2308 if ( isLDR ) {
2309 // target of GOT is external
2310 LOH_ASSERT(ldrInfoB.size == 8);
2311 LOH_ASSERT(!ldrInfoB.isFloat);
2312 LOH_ASSERT(ldrInfoC.baseReg == ldrInfoB.reg);
2313 usableSegment = ( !_options.sharedRegionEligible() || (strcmp(atom->section().segmentName(), infoB.target->section().segmentName()) == 0) );
2314 targetFourByteAligned = ( ((infoA.targetAddress) & 0x3) == 0 );
2315 if ( usableSegment && targetFourByteAligned && withinOneMeg(infoB.instructionAddress, infoA.targetAddress) ) {
2316 // can do T5 transform
2317 set32LE(infoA.instructionContent, makeNOP());
2318 set32LE(infoB.instructionContent, makeLDR_literal(ldrInfoB, infoA.targetAddress, infoB.instructionAddress));
2319 if ( _options.verboseOptimizationHints() ) {
2320 fprintf(stderr, "adrp-ldr-got-str at 0x%08llX T5 transformed to LDR literal of GOT plus STR\n", infoC.instructionAddress);
2321 }
2322 }
2323 else {
2324 if ( _options.verboseOptimizationHints() )
2325 fprintf(stderr, "adrp-ldr-got-str at 0x%08llX no optimization done\n", infoC.instructionAddress);
2326 }
2327 }
2328 else if ( isADD ) {
2329 // target of GOT is in same linkage unit and B instruction was changed to ADD to compute LEA of target
2330 LOH_ASSERT(addInfoB.srcReg == adrpInfoA.destReg);
2331 LOH_ASSERT(addInfoB.destReg == ldrInfoC.baseReg);
2332 usableSegment = ( !_options.sharedRegionEligible() || (strcmp(atom->section().segmentName(), infoB.target->section().segmentName()) == 0) );
2333 targetFourByteAligned = ( ((infoA.targetAddress) & 0x3) == 0 );
2334 literalableSize = ( (ldrInfoC.size != 1) && (ldrInfoC.size != 2) );
2335 if ( usableSegment && withinOneMeg(infoA.instructionAddress, infoA.targetAddress) ) {
2336 // can do T4 transform
2337 set32LE(infoA.instructionContent, makeADR(ldrInfoC.baseReg, infoA.targetAddress, infoA.instructionAddress));
2338 set32LE(infoB.instructionContent, makeNOP());
2339 set32LE(infoC.instructionContent, makeLoadOrStore(ldrInfoC));
2340 if ( _options.verboseOptimizationHints() ) {
2341 fprintf(stderr, "adrp-ldr-got-str at 0x%08llX T4 transformed to ADR/STR\n", infoC.instructionAddress);
2342 }
2343 }
2344 else if ( ((infoA.targetAddress % ldrInfoC.size) == 0) && (ldrInfoC.offset == 0) ) {
2345 // can do T2 transform
2346 set32LE(infoB.instructionContent, makeNOP());
2347 ldrInfoC.baseReg = adrpInfoA.destReg;
2348 ldrInfoC.offset = addInfoB.addend;
2349 set32LE(infoC.instructionContent, makeLoadOrStore(ldrInfoC));
2350 if ( _options.verboseOptimizationHints() ) {
2351 fprintf(stderr, "adrp-ldr-got-str at 0x%08llX T4 transformed to ADRP/NOP/STR\n", infoC.instructionAddress);
2352 }
2353 }
2354 else {
2355 // T3 transform already done by ld::passes:got:doPass()
2356 if ( _options.verboseOptimizationHints() ) {
2357 fprintf(stderr, "adrp-ldr-got-str at 0x%08llX T3 transformed to ADRP/ADD/STR\n", infoC.instructionAddress);
2358 }
2359 }
2360 }
2361 else {
2362 if ( _options.verboseOptimizationHints() )
2363 fprintf(stderr, "adrp-ldr-got-str at 0x%08llX not ADD or LDR\n", infoC.instructionAddress);
2364 }
2365 break;
2366 case LOH_ARM64_ADRP_LDR_GOT:
2367 LOH_ASSERT(alt.info.count == 1);
2368 LOH_ASSERT(isPageKind(infoA.fixup, true));
2369 LOH_ASSERT(isPageOffsetKind(infoB.fixup, true));
2370 LOH_ASSERT(infoA.target == infoB.target);
2371 LOH_ASSERT(infoA.targetAddress == infoB.targetAddress);
2372 isADRP = parseADRP(infoA.instruction, adrpInfoA);
2373 isADD = parseADD(infoB.instruction, addInfoB);
2374 isLDR = parseLoadOrStore(infoB.instruction, ldrInfoB);
2375 usableSegment = ( !_options.sharedRegionEligible() || (strcmp(atom->section().segmentName(), infoB.target->section().segmentName()) == 0) );
2376 if ( isADRP ) {
2377 if ( isLDR ) {
2378 if ( usableSegment && withinOneMeg(infoB.instructionAddress, infoA.targetAddress) ) {
2379 // can do T5 transform (LDR literal load of GOT)
2380 set32LE(infoA.instructionContent, makeNOP());
2381 set32LE(infoB.instructionContent, makeLDR_literal(ldrInfoB, infoA.targetAddress, infoB.instructionAddress));
2382 if ( _options.verboseOptimizationHints() ) {
2383 fprintf(stderr, "adrp-ldr-got at 0x%08llX T5 transformed to NOP/LDR\n", infoC.instructionAddress);
2384 }
2385 }
2386 }
2387 else if ( isADD ) {
2388 if ( usableSegment && withinOneMeg(infoA.instructionAddress, infoA.targetAddress) ) {
2389 // can do T4 transform (ADR to compute local address)
2390 set32LE(infoA.instructionContent, makeADR(addInfoB.destReg, infoA.targetAddress, infoA.instructionAddress));
2391 set32LE(infoB.instructionContent, makeNOP());
2392 if ( _options.verboseOptimizationHints() ) {
2393 fprintf(stderr, "adrp-ldr-got at 0x%08llX T4 transformed to ADR/STR\n", infoC.instructionAddress);
2394 }
2395 }
2396 }
2397 else {
2398 if ( _options.verboseOptimizationHints() )
2399 fprintf(stderr, "adrp-ldr-got at 0x%08llX not LDR or ADD\n", infoB.instructionAddress);
2400 }
2401 }
2402 else {
2403 if ( _options.verboseOptimizationHints() )
2404 fprintf(stderr, "adrp-ldr-got at 0x%08llX not ADRP\n", infoA.instructionAddress);
2405 }
2406 break;
2407 default:
2408 if ( _options.verboseOptimizationHints() )
2409 fprintf(stderr, "unknown hint kind %d alt.info.kind at 0x%08llX\n", alt.info.kind, infoA.instructionAddress);
2410 break;
2411 }
2412 }
2413 // apply hints pass 2
2414 for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
2415 if ( fit->kind != ld::Fixup::kindLinkerOptimizationHint )
2416 continue;
2417 InstructionInfo infoA;
2418 InstructionInfo infoB;
2419 ld::Fixup::LOH_arm64 alt;
2420 alt.addend = fit->u.addend;
2421 setInfo(state, atom, buffer, usedByHints, fit->offsetInAtom, (alt.info.delta1 << 2), &infoA);
2422 if ( alt.info.count > 0 )
2423 setInfo(state, atom, buffer, usedByHints, fit->offsetInAtom, (alt.info.delta2 << 2), &infoB);
2424
2425 switch ( alt.info.kind ) {
2426 case LOH_ARM64_ADRP_ADRP:
2427 LOH_ASSERT(isPageKind(infoA.fixup));
2428 LOH_ASSERT(isPageKind(infoB.fixup));
2429 if ( (infoA.instruction & 0x9F000000) != 0x90000000 ) {
2430 if ( _options.verboseOptimizationHints() )
2431 fprintf(stderr, "may-reused-adrp at 0x%08llX no longer an ADRP, now 0x%08X\n", infoA.instructionAddress, infoA.instruction);
2432 sAdrpNA++;
2433 break;
2434 }
2435 if ( (infoB.instruction & 0x9F000000) != 0x90000000 ) {
2436 if ( _options.verboseOptimizationHints() )
2437 fprintf(stderr, "may-reused-adrp at 0x%08llX no longer an ADRP, now 0x%08X\n", infoB.instructionAddress, infoA.instruction);
2438 sAdrpNA++;
2439 break;
2440 }
2441 if ( (infoA.targetAddress & (-4096)) == (infoB.targetAddress & (-4096)) ) {
2442 set32LE(infoB.instructionContent, 0xD503201F);
2443 sAdrpNoped++;
2444 }
2445 else {
2446 sAdrpNotNoped++;
2447 }
2448 break;
2449 }
2450 }
2451 }
2452
2453
2454
2455
a645023d
A
2456}
2457
afe874b1 2458void OutputFile::copyNoOps(uint8_t* from, uint8_t* to, bool thumb)
a645023d
A
2459{
2460 switch ( _options.architecture() ) {
a645023d
A
2461 case CPU_TYPE_I386:
2462 case CPU_TYPE_X86_64:
2463 for (uint8_t* p=from; p < to; ++p)
2464 *p = 0x90;
2465 break;
2466 case CPU_TYPE_ARM:
afe874b1
A
2467 if ( thumb ) {
2468 for (uint8_t* p=from; p < to; p += 2)
2469 OSWriteLittleInt16((uint16_t*)p, 0, 0x46c0);
2470 }
2471 else {
2472 for (uint8_t* p=from; p < to; p += 4)
2473 OSWriteLittleInt32((uint32_t*)p, 0, 0xe1a00000);
2474 }
a645023d
A
2475 break;
2476 default:
2477 for (uint8_t* p=from; p < to; ++p)
2478 *p = 0x00;
2479 break;
2480 }
2481}
2482
2483bool OutputFile::takesNoDiskSpace(const ld::Section* sect)
2484{
2485 switch ( sect->type() ) {
2486 case ld::Section::typeZeroFill:
2487 case ld::Section::typeTLVZeroFill:
2488 return _options.optimizeZeroFill();
2489 case ld::Section::typePageZero:
2490 case ld::Section::typeStack:
2491 case ld::Section::typeAbsoluteSymbols:
2492 case ld::Section::typeTentativeDefs:
2493 return true;
2494 default:
2495 break;
2496 }
2497 return false;
2498}
2499
2500bool OutputFile::hasZeroForFileOffset(const ld::Section* sect)
2501{
2502 switch ( sect->type() ) {
2503 case ld::Section::typeZeroFill:
2504 case ld::Section::typeTLVZeroFill:
2505 return _options.optimizeZeroFill();
2506 case ld::Section::typePageZero:
2507 case ld::Section::typeStack:
2508 case ld::Section::typeTentativeDefs:
2509 return true;
2510 default:
2511 break;
2512 }
2513 return false;
2514}
2515
ebf6f434 2516void OutputFile::writeAtoms(ld::Internal& state, uint8_t* wholeBuffer)
a645023d 2517{
a645023d
A
2518 // have each atom write itself
2519 uint64_t fileOffsetOfEndOfLastAtom = 0;
2520 uint64_t mhAddress = 0;
2521 bool lastAtomUsesNoOps = false;
2522 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
2523 ld::Internal::FinalSection* sect = *sit;
2524 if ( sect->type() == ld::Section::typeMachHeader )
2525 mhAddress = sect->address;
2526 if ( takesNoDiskSpace(sect) )
2527 continue;
2528 const bool sectionUsesNops = (sect->type() == ld::Section::typeCode);
2529 //fprintf(stderr, "file offset=0x%08llX, section %s\n", sect->fileOffset, sect->sectionName());
2530 std::vector<const ld::Atom*>& atoms = sect->atoms;
afe874b1 2531 bool lastAtomWasThumb = false;
a645023d
A
2532 for (std::vector<const ld::Atom*>::iterator ait = atoms.begin(); ait != atoms.end(); ++ait) {
2533 const ld::Atom* atom = *ait;
2534 if ( atom->definition() == ld::Atom::definitionProxy )
2535 continue;
2536 try {
2537 uint64_t fileOffset = atom->finalAddress() - sect->address + sect->fileOffset;
2538 // check for alignment padding between atoms
2539 if ( (fileOffset != fileOffsetOfEndOfLastAtom) && lastAtomUsesNoOps ) {
afe874b1 2540 this->copyNoOps(&wholeBuffer[fileOffsetOfEndOfLastAtom], &wholeBuffer[fileOffset], lastAtomWasThumb);
a645023d
A
2541 }
2542 // copy atom content
2543 atom->copyRawContent(&wholeBuffer[fileOffset]);
2544 // apply fix ups
2545 this->applyFixUps(state, mhAddress, atom, &wholeBuffer[fileOffset]);
2546 fileOffsetOfEndOfLastAtom = fileOffset+atom->size();
2547 lastAtomUsesNoOps = sectionUsesNops;
afe874b1 2548 lastAtomWasThumb = atom->isThumb();
a645023d
A
2549 }
2550 catch (const char* msg) {
2551 if ( atom->file() != NULL )
d425e388 2552 throwf("%s in '%s' from %s", msg, atom->name(), atom->file()->path());
a645023d 2553 else
d425e388 2554 throwf("%s in '%s'", msg, atom->name());
a645023d
A
2555 }
2556 }
2557 }
9543cb2f
A
2558
2559 if ( _options.verboseOptimizationHints() ) {
2560 //fprintf(stderr, "ADRP optimized away: %d\n", sAdrpNA);
2561 //fprintf(stderr, "ADRPs changed to NOPs: %d\n", sAdrpNoped);
2562 //fprintf(stderr, "ADRPs unchanged: %d\n", sAdrpNotNoped);
2563 }
ebf6f434
A
2564}
2565
2566
2567void OutputFile::computeContentUUID(ld::Internal& state, uint8_t* wholeBuffer)
2568{
2569 const bool log = false;
2570 if ( (_options.outputKind() != Options::kObjectFile) || state.someObjectFileHasDwarf ) {
2571 uint8_t digest[CC_MD5_DIGEST_LENGTH];
2572 uint32_t stabsStringsOffsetStart;
2573 uint32_t tabsStringsOffsetEnd;
2574 uint32_t stabsOffsetStart;
2575 uint32_t stabsOffsetEnd;
2576 if ( _symbolTableAtom->hasStabs(stabsStringsOffsetStart, tabsStringsOffsetEnd, stabsOffsetStart, stabsOffsetEnd) ) {
2577 // find two areas of file that are stabs info and should not contribute to checksum
2578 uint64_t stringPoolFileOffset = 0;
2579 uint64_t symbolTableFileOffset = 0;
2580 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
2581 ld::Internal::FinalSection* sect = *sit;
2582 if ( sect->type() == ld::Section::typeLinkEdit ) {
2583 if ( strcmp(sect->sectionName(), "__string_pool") == 0 )
2584 stringPoolFileOffset = sect->fileOffset;
2585 else if ( strcmp(sect->sectionName(), "__symbol_table") == 0 )
2586 symbolTableFileOffset = sect->fileOffset;
a645023d 2587 }
a645023d 2588 }
ebf6f434
A
2589 uint64_t firstStabNlistFileOffset = symbolTableFileOffset + stabsOffsetStart;
2590 uint64_t lastStabNlistFileOffset = symbolTableFileOffset + stabsOffsetEnd;
2591 uint64_t firstStabStringFileOffset = stringPoolFileOffset + stabsStringsOffsetStart;
2592 uint64_t lastStabStringFileOffset = stringPoolFileOffset + tabsStringsOffsetEnd;
2593 if ( log ) fprintf(stderr, "firstStabNlistFileOffset=0x%08llX\n", firstStabNlistFileOffset);
2594 if ( log ) fprintf(stderr, "lastStabNlistFileOffset=0x%08llX\n", lastStabNlistFileOffset);
2595 if ( log ) fprintf(stderr, "firstStabStringFileOffset=0x%08llX\n", firstStabStringFileOffset);
2596 if ( log ) fprintf(stderr, "lastStabStringFileOffset=0x%08llX\n", lastStabStringFileOffset);
2597 assert(firstStabNlistFileOffset <= firstStabStringFileOffset);
2598
2599 CC_MD5_CTX md5state;
2600 CC_MD5_Init(&md5state);
2601 // checksum everything up to first stabs nlist
2602 if ( log ) fprintf(stderr, "checksum 0x%08X -> 0x%08llX\n", 0, firstStabNlistFileOffset);
2603 CC_MD5_Update(&md5state, &wholeBuffer[0], firstStabNlistFileOffset);
2604 // checkusm everything after last stabs nlist and up to first stabs string
2605 if ( log ) fprintf(stderr, "checksum 0x%08llX -> 0x%08llX\n", lastStabNlistFileOffset, firstStabStringFileOffset);
2606 CC_MD5_Update(&md5state, &wholeBuffer[lastStabNlistFileOffset], firstStabStringFileOffset-lastStabNlistFileOffset);
2607 // checksum everything after last stabs string to end of file
2608 if ( log ) fprintf(stderr, "checksum 0x%08llX -> 0x%08llX\n", lastStabStringFileOffset, _fileSize);
2609 CC_MD5_Update(&md5state, &wholeBuffer[lastStabStringFileOffset], _fileSize-lastStabStringFileOffset);
2610 CC_MD5_Final(digest, &md5state);
2611 if ( log ) fprintf(stderr, "uuid=%02X, %02X, %02X, %02X, %02X, %02X, %02X, %02X\n", digest[0], digest[1], digest[2],
2612 digest[3], digest[4], digest[5], digest[6], digest[7]);
2613 }
2614 else {
2615 CC_MD5(wholeBuffer, _fileSize, digest);
a645023d 2616 }
ebf6f434
A
2617 // <rdar://problem/6723729> LC_UUID uuids should conform to RFC 4122 UUID version 4 & UUID version 5 formats
2618 digest[6] = ( digest[6] & 0x0F ) | ( 3 << 4 );
2619 digest[8] = ( digest[8] & 0x3F ) | 0x80;
2620 // update buffer with new UUID
2621 _headersAndLoadCommandAtom->setUUID(digest);
2622 _headersAndLoadCommandAtom->recopyUUIDCommand();
a645023d 2623 }
ebf6f434
A
2624}
2625
2626
2627void OutputFile::writeOutputFile(ld::Internal& state)
2628{
2629 // for UNIX conformance, error if file exists and is not writable
2630 if ( (access(_options.outputFilePath(), F_OK) == 0) && (access(_options.outputFilePath(), W_OK) == -1) )
2631 throwf("can't write output file: %s", _options.outputFilePath());
a645023d 2632
ebf6f434
A
2633 mode_t permissions = 0777;
2634 if ( _options.outputKind() == Options::kObjectFile )
2635 permissions = 0666;
2636 mode_t umask = ::umask(0);
2637 ::umask(umask); // put back the original umask
2638 permissions &= ~umask;
2639 // Calling unlink first assures the file is gone so that open creates it with correct permissions
2640 // It also handles the case where __options.outputFilePath() file is not writable but its directory is
2641 // And it means we don't have to truncate the file when done writing (in case new is smaller than old)
2642 // Lastly, only delete existing file if it is a normal file (e.g. not /dev/null).
2643 struct stat stat_buf;
d425e388
A
2644 bool outputIsRegularFile = false;
2645 bool outputIsMappableFile = false;
ebf6f434
A
2646 if ( stat(_options.outputFilePath(), &stat_buf) != -1 ) {
2647 if (stat_buf.st_mode & S_IFREG) {
d425e388
A
2648 outputIsRegularFile = true;
2649 // <rdar://problem/12264302> Don't use mmap on non-hfs volumes
2650 struct statfs fsInfo;
2651 if ( statfs(_options.outputFilePath(), &fsInfo) != -1 ) {
2652 if ( strcmp(fsInfo.f_fstypename, "hfs") == 0) {
2653 (void)unlink(_options.outputFilePath());
2654 outputIsMappableFile = true;
2655 }
2656 }
2657 else {
2658 outputIsMappableFile = false;
2659 }
2660 }
2661 else {
ebf6f434
A
2662 outputIsRegularFile = false;
2663 }
2664 }
d425e388
A
2665 else {
2666 // special files (pipes, devices, etc) must already exist
2667 outputIsRegularFile = true;
2668 // output file does not exist yet
2669 char dirPath[PATH_MAX];
2670 strcpy(dirPath, _options.outputFilePath());
2671 char* end = strrchr(dirPath, '/');
2672 if ( end != NULL ) {
2673 end[1] = '\0';
2674 struct statfs fsInfo;
2675 if ( statfs(dirPath, &fsInfo) != -1 ) {
2676 if ( strcmp(fsInfo.f_fstypename, "hfs") == 0) {
2677 outputIsMappableFile = true;
2678 }
2679 }
2680 }
2681 }
2682
2683 //fprintf(stderr, "outputIsMappableFile=%d, outputIsRegularFile=%d, path=%s\n", outputIsMappableFile, outputIsRegularFile, _options.outputFilePath());
2684
ebf6f434
A
2685 int fd;
2686 // Construct a temporary path of the form {outputFilePath}.ld_XXXXXX
2687 const char filenameTemplate[] = ".ld_XXXXXX";
2688 char tmpOutput[PATH_MAX];
2689 uint8_t *wholeBuffer;
d425e388 2690 if ( outputIsRegularFile && outputIsMappableFile ) {
ebf6f434
A
2691 strcpy(tmpOutput, _options.outputFilePath());
2692 // If the path is too long to add a suffix for a temporary name then
2693 // just fall back to using the output path.
2694 if (strlen(tmpOutput)+strlen(filenameTemplate) < PATH_MAX) {
2695 strcat(tmpOutput, filenameTemplate);
2696 fd = mkstemp(tmpOutput);
d425e388
A
2697 }
2698 else {
ebf6f434
A
2699 fd = open(tmpOutput, O_RDWR|O_CREAT, permissions);
2700 }
2701 if ( fd == -1 )
f80fe69f
A
2702 throwf("can't open output file for writing '%s', errno=%d", tmpOutput, errno);
2703 if ( ftruncate(fd, _fileSize) == -1 ) {
2704 int err = errno;
2705 unlink(tmpOutput);
2706 if ( err == ENOSPC )
2707 throwf("not enough disk space for writing '%s'", _options.outputFilePath());
2708 else
2709 throwf("can't grow file for writing '%s', errno=%d", _options.outputFilePath(), err);
2710 }
ebf6f434
A
2711
2712 wholeBuffer = (uint8_t *)mmap(NULL, _fileSize, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
2713 if ( wholeBuffer == MAP_FAILED )
2714 throwf("can't create buffer of %llu bytes for output", _fileSize);
d425e388
A
2715 }
2716 else {
2717 if ( outputIsRegularFile )
2718 fd = open(_options.outputFilePath(), O_RDWR|O_CREAT, permissions);
2719 else
2720 fd = open(_options.outputFilePath(), O_WRONLY);
ebf6f434
A
2721 if ( fd == -1 )
2722 throwf("can't open output file for writing: %s, errno=%d", _options.outputFilePath(), errno);
2723 // try to allocate buffer for entire output file content
2724 wholeBuffer = (uint8_t*)calloc(_fileSize, 1);
2725 if ( wholeBuffer == NULL )
2726 throwf("can't create buffer of %llu bytes for output", _fileSize);
2727 }
2728
2729 if ( _options.UUIDMode() == Options::kUUIDRandom ) {
2730 uint8_t bits[16];
2731 ::uuid_generate_random(bits);
2732 _headersAndLoadCommandAtom->setUUID(bits);
2733 }
2734
2735 writeAtoms(state, wholeBuffer);
2736
2737 // compute UUID
2738 if ( _options.UUIDMode() == Options::kUUIDContent )
2739 computeContentUUID(state, wholeBuffer);
2740
d425e388 2741 if ( outputIsRegularFile && outputIsMappableFile ) {
ebf6f434
A
2742 if ( ::chmod(tmpOutput, permissions) == -1 ) {
2743 unlink(tmpOutput);
2744 throwf("can't set permissions on output file: %s, errno=%d", tmpOutput, errno);
2745 }
2746 if ( ::rename(tmpOutput, _options.outputFilePath()) == -1 && strcmp(tmpOutput, _options.outputFilePath()) != 0) {
2747 unlink(tmpOutput);
2748 throwf("can't move output file in place, errno=%d", errno);
2749 }
d425e388
A
2750 }
2751 else {
ebf6f434
A
2752 if ( ::write(fd, wholeBuffer, _fileSize) == -1 ) {
2753 throwf("can't write to output file: %s, errno=%d", _options.outputFilePath(), errno);
2754 }
f80fe69f
A
2755 ::close(fd);
2756 // <rdar://problem/13118223> NFS: iOS incremental builds in Xcode 4.6 fail with codesign error
2757 // NFS seems to pad the end of the file sometimes. Calling trunc seems to correct it...
2758 ::truncate(_options.outputFilePath(), _fileSize);
ebf6f434 2759 }
a645023d
A
2760}
2761
2762struct AtomByNameSorter
2763{
2764 bool operator()(const ld::Atom* left, const ld::Atom* right)
2765 {
2766 return (strcmp(left->name(), right->name()) < 0);
2767 }
2768};
2769
afe874b1
A
2770class NotInSet
2771{
2772public:
2773 NotInSet(const std::set<const ld::Atom*>& theSet) : _set(theSet) {}
2774
2775 bool operator()(const ld::Atom* atom) const {
2776 return ( _set.count(atom) == 0 );
2777 }
2778private:
2779 const std::set<const ld::Atom*>& _set;
2780};
2781
2782
a645023d
A
2783void OutputFile::buildSymbolTable(ld::Internal& state)
2784{
2785 unsigned int machoSectionIndex = 0;
2786 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
2787 ld::Internal::FinalSection* sect = *sit;
2788 bool setMachoSectionIndex = !sect->isSectionHidden() && (sect->type() != ld::Section::typeTentativeDefs);
2789 if ( setMachoSectionIndex )
2790 ++machoSectionIndex;
2791 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
2792 const ld::Atom* atom = *ait;
2793 if ( setMachoSectionIndex )
2794 (const_cast<ld::Atom*>(atom))->setMachoSection(machoSectionIndex);
2795 else if ( sect->type() == ld::Section::typeMachHeader )
2796 (const_cast<ld::Atom*>(atom))->setMachoSection(1); // __mh_execute_header is not in any section by needs n_sect==1
2797 else if ( sect->type() == ld::Section::typeLastSection )
2798 (const_cast<ld::Atom*>(atom))->setMachoSection(machoSectionIndex); // use section index of previous section
2799 else if ( sect->type() == ld::Section::typeFirstSection )
2800 (const_cast<ld::Atom*>(atom))->setMachoSection(machoSectionIndex+1); // use section index of next section
2801
2802 // in -r mode, clarify symbolTableNotInFinalLinkedImages
2803 if ( _options.outputKind() == Options::kObjectFile ) {
f80fe69f 2804 if ( (_options.architecture() == CPU_TYPE_X86_64) || (_options.architecture() == CPU_TYPE_ARM64) ) {
a645023d
A
2805 // x86_64 .o files need labels on anonymous literal strings
2806 if ( (sect->type() == ld::Section::typeCString) && (atom->combine() == ld::Atom::combineByNameAndContent) ) {
2807 (const_cast<ld::Atom*>(atom))->setSymbolTableInclusion(ld::Atom::symbolTableIn);
2808 _localAtoms.push_back(atom);
2809 continue;
2810 }
2811 }
2812 if ( sect->type() == ld::Section::typeCFI ) {
2813 if ( _options.removeEHLabels() )
2814 (const_cast<ld::Atom*>(atom))->setSymbolTableInclusion(ld::Atom::symbolTableNotIn);
2815 else
2816 (const_cast<ld::Atom*>(atom))->setSymbolTableInclusion(ld::Atom::symbolTableIn);
2817 }
2818 if ( atom->symbolTableInclusion() == ld::Atom::symbolTableNotInFinalLinkedImages )
2819 (const_cast<ld::Atom*>(atom))->setSymbolTableInclusion(ld::Atom::symbolTableIn);
2820 }
2821
2822 // TEMP work around until <rdar://problem/7702923> goes in
2823 if ( (atom->symbolTableInclusion() == ld::Atom::symbolTableInAndNeverStrip)
2824 && (atom->scope() == ld::Atom::scopeLinkageUnit)
2825 && (_options.outputKind() == Options::kDynamicLibrary) ) {
2826 (const_cast<ld::Atom*>(atom))->setScope(ld::Atom::scopeGlobal);
2827 }
2828
2829 // <rdar://problem/6783167> support auto hidden weak symbols: .weak_def_can_be_hidden
2830 if ( atom->autoHide() && (_options.outputKind() != Options::kObjectFile) ) {
2831 // adding auto-hide symbol to .exp file should keep it global
2832 if ( !_options.hasExportMaskList() || !_options.shouldExport(atom->name()) )
2833 (const_cast<ld::Atom*>(atom))->setScope(ld::Atom::scopeLinkageUnit);
2834 }
2835
2836 // <rdar://problem/8626058> ld should consistently warn when resolvers are not exported
2837 if ( (atom->contentType() == ld::Atom::typeResolver) && (atom->scope() == ld::Atom::scopeLinkageUnit) )
2838 warning("resolver functions should be external, but '%s' is hidden", atom->name());
2839
2840 if ( sect->type() == ld::Section::typeImportProxies ) {
2841 if ( atom->combine() == ld::Atom::combineByName )
2842 this->usesWeakExternalSymbols = true;
2843 // alias proxy is a re-export with a name change, don't import changed name
2844 if ( ! atom->isAlias() )
2845 _importedAtoms.push_back(atom);
2846 // scope of proxies are usually linkage unit, so done
2847 // if scope is global, we need to re-export it too
2848 if ( atom->scope() == ld::Atom::scopeGlobal )
2849 _exportedAtoms.push_back(atom);
2850 continue;
2851 }
2852 if ( atom->symbolTableInclusion() == ld::Atom::symbolTableNotInFinalLinkedImages ) {
2853 assert(_options.outputKind() != Options::kObjectFile);
2854 continue; // don't add to symbol table
2855 }
2856 if ( atom->symbolTableInclusion() == ld::Atom::symbolTableNotIn ) {
2857 continue; // don't add to symbol table
2858 }
d425e388
A
2859 if ( (atom->symbolTableInclusion() == ld::Atom::symbolTableInWithRandomAutoStripLabel)
2860 && (_options.outputKind() != Options::kObjectFile) ) {
2861 continue; // don't add to symbol table
2862 }
a645023d
A
2863
2864 if ( (atom->definition() == ld::Atom::definitionTentative) && (_options.outputKind() == Options::kObjectFile) ) {
2865 if ( _options.makeTentativeDefinitionsReal() ) {
2866 // -r -d turns tentative defintions into real def
2867 _exportedAtoms.push_back(atom);
2868 }
2869 else {
2870 // in mach-o object files tentative defintions are stored like undefined symbols
2871 _importedAtoms.push_back(atom);
2872 }
2873 continue;
2874 }
d425e388 2875
a645023d
A
2876 switch ( atom->scope() ) {
2877 case ld::Atom::scopeTranslationUnit:
2878 if ( _options.keepLocalSymbol(atom->name()) ) {
2879 _localAtoms.push_back(atom);
2880 }
2881 else {
2882 if ( _options.outputKind() == Options::kObjectFile ) {
2883 (const_cast<ld::Atom*>(atom))->setSymbolTableInclusion(ld::Atom::symbolTableInWithRandomAutoStripLabel);
2884 _localAtoms.push_back(atom);
2885 }
2886 else
2887 (const_cast<ld::Atom*>(atom))->setSymbolTableInclusion(ld::Atom::symbolTableNotIn);
2888 }
2889 break;
2890 case ld::Atom::scopeGlobal:
2891 _exportedAtoms.push_back(atom);
2892 break;
2893 case ld::Atom::scopeLinkageUnit:
2894 if ( _options.outputKind() == Options::kObjectFile ) {
2895 if ( _options.keepPrivateExterns() ) {
a645023d
A
2896 _exportedAtoms.push_back(atom);
2897 }
2898 else if ( _options.keepLocalSymbol(atom->name()) ) {
2899 _localAtoms.push_back(atom);
2900 }
2901 else {
2902 (const_cast<ld::Atom*>(atom))->setSymbolTableInclusion(ld::Atom::symbolTableInWithRandomAutoStripLabel);
2903 _localAtoms.push_back(atom);
2904 }
2905 }
2906 else {
afe874b1
A
2907 if ( _options.keepLocalSymbol(atom->name()) )
2908 _localAtoms.push_back(atom);
2909 // <rdar://problem/5804214> ld should never have a symbol in the non-lazy indirect symbol table with index 0
2910 // this works by making __mh_execute_header be a local symbol which takes symbol index 0
2911 else if ( (atom->symbolTableInclusion() == ld::Atom::symbolTableInAndNeverStrip) && !_options.makeCompressedDyldInfo() )
a645023d
A
2912 _localAtoms.push_back(atom);
2913 else
2914 (const_cast<ld::Atom*>(atom))->setSymbolTableInclusion(ld::Atom::symbolTableNotIn);
2915 }
2916 break;
2917 }
2918 }
2919 }
2920
afe874b1
A
2921 // <rdar://problem/6978069> ld adds undefined symbol from .exp file to binary
2922 if ( (_options.outputKind() == Options::kKextBundle) && _options.hasExportRestrictList() ) {
2923 // search for referenced undefines
2924 std::set<const ld::Atom*> referencedProxyAtoms;
2925 for (std::vector<ld::Internal::FinalSection*>::iterator sit=state.sections.begin(); sit != state.sections.end(); ++sit) {
2926 ld::Internal::FinalSection* sect = *sit;
2927 for (std::vector<const ld::Atom*>::iterator ait=sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
2928 const ld::Atom* atom = *ait;
2929 for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
2930 switch ( fit->binding ) {
2931 case ld::Fixup::bindingsIndirectlyBound:
2932 referencedProxyAtoms.insert(state.indirectBindingTable[fit->u.bindingIndex]);
2933 break;
2934 case ld::Fixup::bindingDirectlyBound:
2935 referencedProxyAtoms.insert(fit->u.target);
2936 break;
2937 default:
2938 break;
2939 }
2940 }
2941 }
2942 }
2943 // remove any unreferenced _importedAtoms
2944 _importedAtoms.erase(std::remove_if(_importedAtoms.begin(), _importedAtoms.end(), NotInSet(referencedProxyAtoms)), _importedAtoms.end());
2945 }
2946
a645023d
A
2947 // sort by name
2948 std::sort(_exportedAtoms.begin(), _exportedAtoms.end(), AtomByNameSorter());
2949 std::sort(_importedAtoms.begin(), _importedAtoms.end(), AtomByNameSorter());
a645023d
A
2950}
2951
2952void OutputFile::addPreloadLinkEdit(ld::Internal& state)
2953{
2954 switch ( _options.architecture() ) {
ebf6f434 2955#if SUPPORT_ARCH_i386
a645023d
A
2956 case CPU_TYPE_I386:
2957 if ( _hasLocalRelocations ) {
2958 _localRelocsAtom = new LocalRelocationsAtom<x86>(_options, state, *this);
2959 localRelocationsSection = state.addAtom(*_localRelocsAtom);
2960 }
2961 if ( _hasExternalRelocations ) {
2962 _externalRelocsAtom = new ExternalRelocationsAtom<x86>(_options, state, *this);
2963 externalRelocationsSection = state.addAtom(*_externalRelocsAtom);
2964 }
2965 if ( _hasSymbolTable ) {
2966 _indirectSymbolTableAtom = new IndirectSymbolTableAtom<x86>(_options, state, *this);
2967 indirectSymbolTableSection = state.addAtom(*_indirectSymbolTableAtom);
2968 _symbolTableAtom = new SymbolTableAtom<x86>(_options, state, *this);
2969 symbolTableSection = state.addAtom(*_symbolTableAtom);
2970 _stringPoolAtom = new StringPoolAtom(_options, state, *this, 4);
2971 stringPoolSection = state.addAtom(*_stringPoolAtom);
2972 }
2973 break;
ebf6f434
A
2974#endif
2975#if SUPPORT_ARCH_x86_64
a645023d
A
2976 case CPU_TYPE_X86_64:
2977 if ( _hasLocalRelocations ) {
2978 _localRelocsAtom = new LocalRelocationsAtom<x86_64>(_options, state, *this);
2979 localRelocationsSection = state.addAtom(*_localRelocsAtom);
2980 }
2981 if ( _hasExternalRelocations ) {
2982 _externalRelocsAtom = new ExternalRelocationsAtom<x86_64>(_options, state, *this);
2983 externalRelocationsSection = state.addAtom(*_externalRelocsAtom);
2984 }
2985 if ( _hasSymbolTable ) {
2986 _indirectSymbolTableAtom = new IndirectSymbolTableAtom<x86_64>(_options, state, *this);
2987 indirectSymbolTableSection = state.addAtom(*_indirectSymbolTableAtom);
2988 _symbolTableAtom = new SymbolTableAtom<x86_64>(_options, state, *this);
2989 symbolTableSection = state.addAtom(*_symbolTableAtom);
2990 _stringPoolAtom = new StringPoolAtom(_options, state, *this, 4);
2991 stringPoolSection = state.addAtom(*_stringPoolAtom);
2992 }
2993 break;
ebf6f434
A
2994#endif
2995#if SUPPORT_ARCH_arm_any
a645023d
A
2996 case CPU_TYPE_ARM:
2997 if ( _hasLocalRelocations ) {
2998 _localRelocsAtom = new LocalRelocationsAtom<arm>(_options, state, *this);
2999 localRelocationsSection = state.addAtom(*_localRelocsAtom);
3000 }
3001 if ( _hasExternalRelocations ) {
3002 _externalRelocsAtom = new ExternalRelocationsAtom<arm>(_options, state, *this);
3003 externalRelocationsSection = state.addAtom(*_externalRelocsAtom);
3004 }
3005 if ( _hasSymbolTable ) {
3006 _indirectSymbolTableAtom = new IndirectSymbolTableAtom<arm>(_options, state, *this);
3007 indirectSymbolTableSection = state.addAtom(*_indirectSymbolTableAtom);
3008 _symbolTableAtom = new SymbolTableAtom<arm>(_options, state, *this);
3009 symbolTableSection = state.addAtom(*_symbolTableAtom);
3010 _stringPoolAtom = new StringPoolAtom(_options, state, *this, 4);
3011 stringPoolSection = state.addAtom(*_stringPoolAtom);
3012 }
3013 break;
f80fe69f
A
3014#endif
3015#if SUPPORT_ARCH_arm64
3016 case CPU_TYPE_ARM64:
3017 if ( _hasLocalRelocations ) {
3018 _localRelocsAtom = new LocalRelocationsAtom<arm64>(_options, state, *this);
3019 localRelocationsSection = state.addAtom(*_localRelocsAtom);
3020 }
3021 if ( _hasExternalRelocations ) {
3022 _externalRelocsAtom = new ExternalRelocationsAtom<arm64>(_options, state, *this);
3023 externalRelocationsSection = state.addAtom(*_externalRelocsAtom);
3024 }
3025 if ( _hasSymbolTable ) {
3026 _indirectSymbolTableAtom = new IndirectSymbolTableAtom<arm64>(_options, state, *this);
3027 indirectSymbolTableSection = state.addAtom(*_indirectSymbolTableAtom);
3028 _symbolTableAtom = new SymbolTableAtom<arm64>(_options, state, *this);
3029 symbolTableSection = state.addAtom(*_symbolTableAtom);
3030 _stringPoolAtom = new StringPoolAtom(_options, state, *this, 4);
3031 stringPoolSection = state.addAtom(*_stringPoolAtom);
3032 }
3033 break;
ebf6f434 3034#endif
a645023d 3035 default:
f80fe69f 3036 throw "-preload not supported";
a645023d
A
3037 }
3038
3039}
3040
3041
3042void OutputFile::addLinkEdit(ld::Internal& state)
3043{
3044 // for historical reasons, -preload orders LINKEDIT content differently
3045 if ( _options.outputKind() == Options::kPreload )
3046 return addPreloadLinkEdit(state);
3047
3048 switch ( _options.architecture() ) {
ebf6f434 3049#if SUPPORT_ARCH_i386
a645023d
A
3050 case CPU_TYPE_I386:
3051 if ( _hasSectionRelocations ) {
3052 _sectionsRelocationsAtom = new SectionRelocationsAtom<x86>(_options, state, *this);
3053 sectionRelocationsSection = state.addAtom(*_sectionsRelocationsAtom);
3054 }
3055 if ( _hasDyldInfo ) {
3056 _rebasingInfoAtom = new RebaseInfoAtom<x86>(_options, state, *this);
3057 rebaseSection = state.addAtom(*_rebasingInfoAtom);
3058
3059 _bindingInfoAtom = new BindingInfoAtom<x86>(_options, state, *this);
3060 bindingSection = state.addAtom(*_bindingInfoAtom);
3061
3062 _weakBindingInfoAtom = new WeakBindingInfoAtom<x86>(_options, state, *this);
3063 weakBindingSection = state.addAtom(*_weakBindingInfoAtom);
3064
3065 _lazyBindingInfoAtom = new LazyBindingInfoAtom<x86>(_options, state, *this);
3066 lazyBindingSection = state.addAtom(*_lazyBindingInfoAtom);
3067
3068 _exportInfoAtom = new ExportInfoAtom<x86>(_options, state, *this);
3069 exportSection = state.addAtom(*_exportInfoAtom);
3070 }
3071 if ( _hasLocalRelocations ) {
3072 _localRelocsAtom = new LocalRelocationsAtom<x86>(_options, state, *this);
3073 localRelocationsSection = state.addAtom(*_localRelocsAtom);
3074 }
3075 if ( _hasSplitSegInfo ) {
3076 _splitSegInfoAtom = new SplitSegInfoAtom<x86>(_options, state, *this);
3077 splitSegInfoSection = state.addAtom(*_splitSegInfoAtom);
3078 }
3079 if ( _hasFunctionStartsInfo ) {
3080 _functionStartsAtom = new FunctionStartsAtom<x86>(_options, state, *this);
3081 functionStartsSection = state.addAtom(*_functionStartsAtom);
3082 }
ebf6f434
A
3083 if ( _hasDataInCodeInfo ) {
3084 _dataInCodeAtom = new DataInCodeAtom<x86>(_options, state, *this);
3085 dataInCodeSection = state.addAtom(*_dataInCodeAtom);
3086 }
9543cb2f
A
3087 if ( _hasOptimizationHints ) {
3088 _optimizationHintsAtom = new OptimizationHintsAtom<x86>(_options, state, *this);
3089 optimizationHintsSection = state.addAtom(*_optimizationHintsAtom);
3090 }
ebf6f434
A
3091 if ( _hasDependentDRInfo ) {
3092 _dependentDRInfoAtom = new DependentDRAtom<x86>(_options, state, *this);
3093 dependentDRsSection = state.addAtom(*_dependentDRInfoAtom);
3094 }
a645023d
A
3095 if ( _hasSymbolTable ) {
3096 _symbolTableAtom = new SymbolTableAtom<x86>(_options, state, *this);
3097 symbolTableSection = state.addAtom(*_symbolTableAtom);
3098 }
3099 if ( _hasExternalRelocations ) {
3100 _externalRelocsAtom = new ExternalRelocationsAtom<x86>(_options, state, *this);
3101 externalRelocationsSection = state.addAtom(*_externalRelocsAtom);
3102 }
3103 if ( _hasSymbolTable ) {
3104 _indirectSymbolTableAtom = new IndirectSymbolTableAtom<x86>(_options, state, *this);
3105 indirectSymbolTableSection = state.addAtom(*_indirectSymbolTableAtom);
3106 _stringPoolAtom = new StringPoolAtom(_options, state, *this, 4);
3107 stringPoolSection = state.addAtom(*_stringPoolAtom);
3108 }
3109 break;
ebf6f434
A
3110#endif
3111#if SUPPORT_ARCH_x86_64
a645023d
A
3112 case CPU_TYPE_X86_64:
3113 if ( _hasSectionRelocations ) {
3114 _sectionsRelocationsAtom = new SectionRelocationsAtom<x86_64>(_options, state, *this);
3115 sectionRelocationsSection = state.addAtom(*_sectionsRelocationsAtom);
3116 }
3117 if ( _hasDyldInfo ) {
3118 _rebasingInfoAtom = new RebaseInfoAtom<x86_64>(_options, state, *this);
3119 rebaseSection = state.addAtom(*_rebasingInfoAtom);
3120
3121 _bindingInfoAtom = new BindingInfoAtom<x86_64>(_options, state, *this);
3122 bindingSection = state.addAtom(*_bindingInfoAtom);
3123
3124 _weakBindingInfoAtom = new WeakBindingInfoAtom<x86_64>(_options, state, *this);
3125 weakBindingSection = state.addAtom(*_weakBindingInfoAtom);
3126
3127 _lazyBindingInfoAtom = new LazyBindingInfoAtom<x86_64>(_options, state, *this);
3128 lazyBindingSection = state.addAtom(*_lazyBindingInfoAtom);
3129
3130 _exportInfoAtom = new ExportInfoAtom<x86_64>(_options, state, *this);
3131 exportSection = state.addAtom(*_exportInfoAtom);
3132 }
3133 if ( _hasLocalRelocations ) {
3134 _localRelocsAtom = new LocalRelocationsAtom<x86_64>(_options, state, *this);
3135 localRelocationsSection = state.addAtom(*_localRelocsAtom);
3136 }
3137 if ( _hasSplitSegInfo ) {
3138 _splitSegInfoAtom = new SplitSegInfoAtom<x86_64>(_options, state, *this);
3139 splitSegInfoSection = state.addAtom(*_splitSegInfoAtom);
3140 }
3141 if ( _hasFunctionStartsInfo ) {
3142 _functionStartsAtom = new FunctionStartsAtom<x86_64>(_options, state, *this);
3143 functionStartsSection = state.addAtom(*_functionStartsAtom);
3144 }
ebf6f434
A
3145 if ( _hasDataInCodeInfo ) {
3146 _dataInCodeAtom = new DataInCodeAtom<x86_64>(_options, state, *this);
3147 dataInCodeSection = state.addAtom(*_dataInCodeAtom);
3148 }
9543cb2f
A
3149 if ( _hasOptimizationHints ) {
3150 _optimizationHintsAtom = new OptimizationHintsAtom<x86_64>(_options, state, *this);
3151 optimizationHintsSection = state.addAtom(*_optimizationHintsAtom);
3152 }
ebf6f434
A
3153 if ( _hasDependentDRInfo ) {
3154 _dependentDRInfoAtom = new DependentDRAtom<x86_64>(_options, state, *this);
3155 dependentDRsSection = state.addAtom(*_dependentDRInfoAtom);
3156 }
a645023d
A
3157 if ( _hasSymbolTable ) {
3158 _symbolTableAtom = new SymbolTableAtom<x86_64>(_options, state, *this);
3159 symbolTableSection = state.addAtom(*_symbolTableAtom);
3160 }
3161 if ( _hasExternalRelocations ) {
3162 _externalRelocsAtom = new ExternalRelocationsAtom<x86_64>(_options, state, *this);
3163 externalRelocationsSection = state.addAtom(*_externalRelocsAtom);
3164 }
3165 if ( _hasSymbolTable ) {
3166 _indirectSymbolTableAtom = new IndirectSymbolTableAtom<x86_64>(_options, state, *this);
3167 indirectSymbolTableSection = state.addAtom(*_indirectSymbolTableAtom);
3168 _stringPoolAtom = new StringPoolAtom(_options, state, *this, 8);
3169 stringPoolSection = state.addAtom(*_stringPoolAtom);
3170 }
3171 break;
ebf6f434
A
3172#endif
3173#if SUPPORT_ARCH_arm_any
a645023d
A
3174 case CPU_TYPE_ARM:
3175 if ( _hasSectionRelocations ) {
3176 _sectionsRelocationsAtom = new SectionRelocationsAtom<arm>(_options, state, *this);
3177 sectionRelocationsSection = state.addAtom(*_sectionsRelocationsAtom);
3178 }
3179 if ( _hasDyldInfo ) {
3180 _rebasingInfoAtom = new RebaseInfoAtom<arm>(_options, state, *this);
3181 rebaseSection = state.addAtom(*_rebasingInfoAtom);
3182
3183 _bindingInfoAtom = new BindingInfoAtom<arm>(_options, state, *this);
3184 bindingSection = state.addAtom(*_bindingInfoAtom);
3185
3186 _weakBindingInfoAtom = new WeakBindingInfoAtom<arm>(_options, state, *this);
3187 weakBindingSection = state.addAtom(*_weakBindingInfoAtom);
3188
3189 _lazyBindingInfoAtom = new LazyBindingInfoAtom<arm>(_options, state, *this);
3190 lazyBindingSection = state.addAtom(*_lazyBindingInfoAtom);
3191
3192 _exportInfoAtom = new ExportInfoAtom<arm>(_options, state, *this);
3193 exportSection = state.addAtom(*_exportInfoAtom);
3194 }
3195 if ( _hasLocalRelocations ) {
3196 _localRelocsAtom = new LocalRelocationsAtom<arm>(_options, state, *this);
3197 localRelocationsSection = state.addAtom(*_localRelocsAtom);
3198 }
3199 if ( _hasSplitSegInfo ) {
3200 _splitSegInfoAtom = new SplitSegInfoAtom<arm>(_options, state, *this);
3201 splitSegInfoSection = state.addAtom(*_splitSegInfoAtom);
3202 }
3203 if ( _hasFunctionStartsInfo ) {
3204 _functionStartsAtom = new FunctionStartsAtom<arm>(_options, state, *this);
3205 functionStartsSection = state.addAtom(*_functionStartsAtom);
3206 }
ebf6f434
A
3207 if ( _hasDataInCodeInfo ) {
3208 _dataInCodeAtom = new DataInCodeAtom<arm>(_options, state, *this);
3209 dataInCodeSection = state.addAtom(*_dataInCodeAtom);
3210 }
9543cb2f
A
3211 if ( _hasOptimizationHints ) {
3212 _optimizationHintsAtom = new OptimizationHintsAtom<arm>(_options, state, *this);
3213 optimizationHintsSection = state.addAtom(*_optimizationHintsAtom);
3214 }
ebf6f434
A
3215 if ( _hasDependentDRInfo ) {
3216 _dependentDRInfoAtom = new DependentDRAtom<arm>(_options, state, *this);
3217 dependentDRsSection = state.addAtom(*_dependentDRInfoAtom);
3218 }
a645023d
A
3219 if ( _hasSymbolTable ) {
3220 _symbolTableAtom = new SymbolTableAtom<arm>(_options, state, *this);
3221 symbolTableSection = state.addAtom(*_symbolTableAtom);
3222 }
3223 if ( _hasExternalRelocations ) {
3224 _externalRelocsAtom = new ExternalRelocationsAtom<arm>(_options, state, *this);
3225 externalRelocationsSection = state.addAtom(*_externalRelocsAtom);
3226 }
3227 if ( _hasSymbolTable ) {
3228 _indirectSymbolTableAtom = new IndirectSymbolTableAtom<arm>(_options, state, *this);
3229 indirectSymbolTableSection = state.addAtom(*_indirectSymbolTableAtom);
3230 _stringPoolAtom = new StringPoolAtom(_options, state, *this, 4);
3231 stringPoolSection = state.addAtom(*_stringPoolAtom);
3232 }
3233 break;
f80fe69f
A
3234#endif
3235#if SUPPORT_ARCH_arm64
3236 case CPU_TYPE_ARM64:
3237 if ( _hasSectionRelocations ) {
3238 _sectionsRelocationsAtom = new SectionRelocationsAtom<arm64>(_options, state, *this);
3239 sectionRelocationsSection = state.addAtom(*_sectionsRelocationsAtom);
3240 }
3241 if ( _hasDyldInfo ) {
3242 _rebasingInfoAtom = new RebaseInfoAtom<arm64>(_options, state, *this);
3243 rebaseSection = state.addAtom(*_rebasingInfoAtom);
3244
3245 _bindingInfoAtom = new BindingInfoAtom<arm64>(_options, state, *this);
3246 bindingSection = state.addAtom(*_bindingInfoAtom);
3247
3248 _weakBindingInfoAtom = new WeakBindingInfoAtom<arm64>(_options, state, *this);
3249 weakBindingSection = state.addAtom(*_weakBindingInfoAtom);
3250
3251 _lazyBindingInfoAtom = new LazyBindingInfoAtom<arm64>(_options, state, *this);
3252 lazyBindingSection = state.addAtom(*_lazyBindingInfoAtom);
3253
3254 _exportInfoAtom = new ExportInfoAtom<arm64>(_options, state, *this);
3255 exportSection = state.addAtom(*_exportInfoAtom);
3256 }
3257 if ( _hasLocalRelocations ) {
3258 _localRelocsAtom = new LocalRelocationsAtom<arm64>(_options, state, *this);
3259 localRelocationsSection = state.addAtom(*_localRelocsAtom);
3260 }
3261 if ( _hasSplitSegInfo ) {
3262 _splitSegInfoAtom = new SplitSegInfoAtom<arm64>(_options, state, *this);
3263 splitSegInfoSection = state.addAtom(*_splitSegInfoAtom);
3264 }
3265 if ( _hasFunctionStartsInfo ) {
3266 _functionStartsAtom = new FunctionStartsAtom<arm64>(_options, state, *this);
3267 functionStartsSection = state.addAtom(*_functionStartsAtom);
3268 }
3269 if ( _hasDataInCodeInfo ) {
3270 _dataInCodeAtom = new DataInCodeAtom<arm64>(_options, state, *this);
3271 dataInCodeSection = state.addAtom(*_dataInCodeAtom);
3272 }
9543cb2f
A
3273 if ( _hasOptimizationHints ) {
3274 _optimizationHintsAtom = new OptimizationHintsAtom<arm64>(_options, state, *this);
3275 optimizationHintsSection = state.addAtom(*_optimizationHintsAtom);
3276 }
f80fe69f
A
3277 if ( _hasDependentDRInfo ) {
3278 _dependentDRInfoAtom = new DependentDRAtom<arm64>(_options, state, *this);
3279 dependentDRsSection = state.addAtom(*_dependentDRInfoAtom);
3280 }
3281 if ( _hasSymbolTable ) {
3282 _symbolTableAtom = new SymbolTableAtom<arm64>(_options, state, *this);
3283 symbolTableSection = state.addAtom(*_symbolTableAtom);
3284 }
3285 if ( _hasExternalRelocations ) {
3286 _externalRelocsAtom = new ExternalRelocationsAtom<arm64>(_options, state, *this);
3287 externalRelocationsSection = state.addAtom(*_externalRelocsAtom);
3288 }
3289 if ( _hasSymbolTable ) {
3290 _indirectSymbolTableAtom = new IndirectSymbolTableAtom<arm64>(_options, state, *this);
3291 indirectSymbolTableSection = state.addAtom(*_indirectSymbolTableAtom);
3292 _stringPoolAtom = new StringPoolAtom(_options, state, *this, 4);
3293 stringPoolSection = state.addAtom(*_stringPoolAtom);
3294 }
3295 break;
ebf6f434 3296#endif
a645023d
A
3297 default:
3298 throw "unknown architecture";
3299 }
3300}
3301
3302void OutputFile::addLoadCommands(ld::Internal& state)
3303{
3304 switch ( _options.architecture() ) {
ebf6f434 3305#if SUPPORT_ARCH_x86_64
a645023d
A
3306 case CPU_TYPE_X86_64:
3307 _headersAndLoadCommandAtom = new HeaderAndLoadCommandsAtom<x86_64>(_options, state, *this);
3308 headerAndLoadCommandsSection = state.addAtom(*_headersAndLoadCommandAtom);
3309 break;
ebf6f434
A
3310#endif
3311#if SUPPORT_ARCH_arm_any
a645023d
A
3312 case CPU_TYPE_ARM:
3313 _headersAndLoadCommandAtom = new HeaderAndLoadCommandsAtom<arm>(_options, state, *this);
3314 headerAndLoadCommandsSection = state.addAtom(*_headersAndLoadCommandAtom);
3315 break;
ebf6f434 3316#endif
f80fe69f
A
3317#if SUPPORT_ARCH_arm64
3318 case CPU_TYPE_ARM64:
3319 _headersAndLoadCommandAtom = new HeaderAndLoadCommandsAtom<arm64>(_options, state, *this);
3320 headerAndLoadCommandsSection = state.addAtom(*_headersAndLoadCommandAtom);
3321 break;
3322#endif
ebf6f434 3323#if SUPPORT_ARCH_i386
a645023d
A
3324 case CPU_TYPE_I386:
3325 _headersAndLoadCommandAtom = new HeaderAndLoadCommandsAtom<x86>(_options, state, *this);
3326 headerAndLoadCommandsSection = state.addAtom(*_headersAndLoadCommandAtom);
3327 break;
ebf6f434 3328#endif
a645023d
A
3329 default:
3330 throw "unknown architecture";
3331 }
3332}
3333
3334uint32_t OutputFile::dylibCount()
3335{
3336 return _dylibsToLoad.size();
3337}
3338
3339const ld::dylib::File* OutputFile::dylibByOrdinal(unsigned int ordinal)
3340{
3341 assert( ordinal > 0 );
3342 assert( ordinal <= _dylibsToLoad.size() );
3343 return _dylibsToLoad[ordinal-1];
3344}
3345
3346bool OutputFile::hasOrdinalForInstallPath(const char* path, int* ordinal)
3347{
3348 for (std::map<const ld::dylib::File*, int>::const_iterator it = _dylibToOrdinal.begin(); it != _dylibToOrdinal.end(); ++it) {
3349 const char* installPath = it->first->installPath();
3350 if ( (installPath != NULL) && (strcmp(path, installPath) == 0) ) {
3351 *ordinal = it->second;
3352 return true;
3353 }
3354 }
3355 return false;
3356}
3357
3358uint32_t OutputFile::dylibToOrdinal(const ld::dylib::File* dylib)
3359{
3360 return _dylibToOrdinal[dylib];
3361}
3362
3363
3364void OutputFile::buildDylibOrdinalMapping(ld::Internal& state)
3365{
3366 // count non-public re-exported dylibs
3367 unsigned int nonPublicReExportCount = 0;
3368 for (std::vector<ld::dylib::File*>::iterator it = state.dylibs.begin(); it != state.dylibs.end(); ++it) {
3369 ld::dylib::File* aDylib = *it;
3370 if ( aDylib->willBeReExported() && ! aDylib->hasPublicInstallName() )
3371 ++nonPublicReExportCount;
3372 }
3373
3374 // look at each dylib supplied in state
3375 bool hasReExports = false;
3376 bool haveLazyDylibs = false;
3377 for (std::vector<ld::dylib::File*>::iterator it = state.dylibs.begin(); it != state.dylibs.end(); ++it) {
3378 ld::dylib::File* aDylib = *it;
3379 int ordinal;
3380 if ( aDylib == state.bundleLoader ) {
3381 _dylibToOrdinal[aDylib] = BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE;
3382 }
3383 else if ( this->hasOrdinalForInstallPath(aDylib->installPath(), &ordinal) ) {
3384 // already have a dylib with that install path, map all uses to that ordinal
3385 _dylibToOrdinal[aDylib] = ordinal;
3386 }
3387 else if ( aDylib->willBeLazyLoadedDylib() ) {
3388 // all lazy dylib need to be at end of ordinals
3389 haveLazyDylibs = true;
3390 }
3391 else if ( aDylib->willBeReExported() && ! aDylib->hasPublicInstallName() && (nonPublicReExportCount >= 2) ) {
3392 _dylibsToLoad.push_back(aDylib);
3393 _dylibToOrdinal[aDylib] = BIND_SPECIAL_DYLIB_SELF;
3394 }
3395 else {
3396 // first time this install path seen, create new ordinal
3397 _dylibsToLoad.push_back(aDylib);
3398 _dylibToOrdinal[aDylib] = _dylibsToLoad.size();
3399 }
3400 if ( aDylib->explicitlyLinked() && aDylib->willBeReExported() )
3401 hasReExports = true;
3402 }
3403 if ( haveLazyDylibs ) {
3404 // second pass to determine ordinals for lazy loaded dylibs
3405 for (std::vector<ld::dylib::File*>::iterator it = state.dylibs.begin(); it != state.dylibs.end(); ++it) {
3406 ld::dylib::File* aDylib = *it;
3407 if ( aDylib->willBeLazyLoadedDylib() ) {
3408 int ordinal;
3409 if ( this->hasOrdinalForInstallPath(aDylib->installPath(), &ordinal) ) {
3410 // already have a dylib with that install path, map all uses to that ordinal
3411 _dylibToOrdinal[aDylib] = ordinal;
3412 }
3413 else {
3414 // first time this install path seen, create new ordinal
3415 _dylibsToLoad.push_back(aDylib);
3416 _dylibToOrdinal[aDylib] = _dylibsToLoad.size();
3417 }
3418 }
3419 }
3420 }
3421 _noReExportedDylibs = !hasReExports;
3422 //fprintf(stderr, "dylibs:\n");
3423 //for (std::map<const ld::dylib::File*, int>::const_iterator it = _dylibToOrdinal.begin(); it != _dylibToOrdinal.end(); ++it) {
3424 // fprintf(stderr, " %p ord=%u, install_name=%s\n",it->first, it->second, it->first->installPath());
3425 //}
3426}
3427
3428uint32_t OutputFile::lazyBindingInfoOffsetForLazyPointerAddress(uint64_t lpAddress)
3429{
3430 return _lazyPointerAddressToInfoOffset[lpAddress];
3431}
3432
3433void OutputFile::setLazyBindingInfoOffset(uint64_t lpAddress, uint32_t lpInfoOffset)
3434{
3435 _lazyPointerAddressToInfoOffset[lpAddress] = lpInfoOffset;
3436}
3437
3438int OutputFile::compressedOrdinalForAtom(const ld::Atom* target)
3439{
3440 // flat namespace images use zero for all ordinals
3441 if ( _options.nameSpace() != Options::kTwoLevelNameSpace )
3442 return BIND_SPECIAL_DYLIB_FLAT_LOOKUP;
3443
3444 // handle -interposable
3445 if ( target->definition() == ld::Atom::definitionRegular )
3446 return BIND_SPECIAL_DYLIB_SELF;
3447
3448 // regular ordinal
3449 const ld::dylib::File* dylib = dynamic_cast<const ld::dylib::File*>(target->file());
d425e388
A
3450 if ( dylib != NULL ) {
3451 std::map<const ld::dylib::File*, int>::iterator pos = _dylibToOrdinal.find(dylib);
3452 if ( pos != _dylibToOrdinal.end() )
3453 return pos->second;
3454 assert(0 && "dylib not assigned ordinal");
3455 }
3456
a645023d
A
3457 // handle undefined dynamic_lookup
3458 if ( _options.undefinedTreatment() == Options::kUndefinedDynamicLookup )
3459 return BIND_SPECIAL_DYLIB_FLAT_LOOKUP;
3460
3461 // handle -U _foo
3462 if ( _options.allowedUndefined(target->name()) )
3463 return BIND_SPECIAL_DYLIB_FLAT_LOOKUP;
3464
3465 throw "can't find ordinal for imported symbol";
3466}
3467
3468
3469bool OutputFile::isPcRelStore(ld::Fixup::Kind kind)
3470{
3471 switch ( kind ) {
3472 case ld::Fixup::kindStoreX86BranchPCRel8:
3473 case ld::Fixup::kindStoreX86BranchPCRel32:
3474 case ld::Fixup::kindStoreX86PCRel8:
3475 case ld::Fixup::kindStoreX86PCRel16:
3476 case ld::Fixup::kindStoreX86PCRel32:
3477 case ld::Fixup::kindStoreX86PCRel32_1:
3478 case ld::Fixup::kindStoreX86PCRel32_2:
3479 case ld::Fixup::kindStoreX86PCRel32_4:
3480 case ld::Fixup::kindStoreX86PCRel32GOTLoad:
3481 case ld::Fixup::kindStoreX86PCRel32GOTLoadNowLEA:
3482 case ld::Fixup::kindStoreX86PCRel32GOT:
3483 case ld::Fixup::kindStoreX86PCRel32TLVLoad:
3484 case ld::Fixup::kindStoreX86PCRel32TLVLoadNowLEA:
3485 case ld::Fixup::kindStoreARMBranch24:
3486 case ld::Fixup::kindStoreThumbBranch22:
3487 case ld::Fixup::kindStoreARMLoad12:
a645023d
A
3488 case ld::Fixup::kindStoreTargetAddressX86PCRel32:
3489 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad:
3490 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA:
d425e388
A
3491 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad:
3492 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA:
a645023d
A
3493 case ld::Fixup::kindStoreTargetAddressARMBranch24:
3494 case ld::Fixup::kindStoreTargetAddressThumbBranch22:
3495 case ld::Fixup::kindStoreTargetAddressARMLoad12:
f80fe69f
A
3496#if SUPPORT_ARCH_arm64
3497 case ld::Fixup::kindStoreARM64Page21:
3498 case ld::Fixup::kindStoreARM64PageOff12:
3499 case ld::Fixup::kindStoreARM64GOTLoadPage21:
3500 case ld::Fixup::kindStoreARM64GOTLoadPageOff12:
3501 case ld::Fixup::kindStoreARM64GOTLeaPage21:
3502 case ld::Fixup::kindStoreARM64GOTLeaPageOff12:
3503 case ld::Fixup::kindStoreARM64PCRelToGOT:
3504 case ld::Fixup::kindStoreTargetAddressARM64Page21:
3505 case ld::Fixup::kindStoreTargetAddressARM64PageOff12:
3506 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
3507 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12:
3508 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21:
3509 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPageOff12:
3510#endif
a645023d
A
3511 return true;
3512 case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32:
f80fe69f
A
3513#if SUPPORT_ARCH_arm64
3514 case ld::Fixup::kindStoreTargetAddressARM64Branch26:
3515#endif
a645023d
A
3516 return (_options.outputKind() != Options::kKextBundle);
3517 default:
3518 break;
3519 }
3520 return false;
3521}
3522
3523bool OutputFile::isStore(ld::Fixup::Kind kind)
3524{
3525 switch ( kind ) {
3526 case ld::Fixup::kindNone:
3527 case ld::Fixup::kindNoneFollowOn:
3528 case ld::Fixup::kindNoneGroupSubordinate:
3529 case ld::Fixup::kindNoneGroupSubordinateFDE:
3530 case ld::Fixup::kindNoneGroupSubordinateLSDA:
3531 case ld::Fixup::kindNoneGroupSubordinatePersonality:
3532 case ld::Fixup::kindSetTargetAddress:
3533 case ld::Fixup::kindSubtractTargetAddress:
3534 case ld::Fixup::kindAddAddend:
3535 case ld::Fixup::kindSubtractAddend:
3536 case ld::Fixup::kindSetTargetImageOffset:
3537 case ld::Fixup::kindSetTargetSectionOffset:
3538 return false;
3539 default:
3540 break;
3541 }
3542 return true;
3543}
3544
3545
3546bool OutputFile::setsTarget(ld::Fixup::Kind kind)
3547{
3548 switch ( kind ) {
3549 case ld::Fixup::kindSetTargetAddress:
3550 case ld::Fixup::kindLazyTarget:
3551 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
3552 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
3553 case ld::Fixup::kindStoreTargetAddressBigEndian32:
3554 case ld::Fixup::kindStoreTargetAddressBigEndian64:
3555 case ld::Fixup::kindStoreTargetAddressX86PCRel32:
3556 case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32:
3557 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad:
3558 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA:
b1f7435d 3559 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad:
f80fe69f 3560 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA:
b1f7435d 3561 case ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoad:
a645023d
A
3562 case ld::Fixup::kindStoreTargetAddressARMBranch24:
3563 case ld::Fixup::kindStoreTargetAddressThumbBranch22:
3564 case ld::Fixup::kindStoreTargetAddressARMLoad12:
f80fe69f
A
3565#if SUPPORT_ARCH_arm64
3566 case ld::Fixup::kindStoreTargetAddressARM64Branch26:
3567 case ld::Fixup::kindStoreTargetAddressARM64Page21:
3568 case ld::Fixup::kindStoreTargetAddressARM64PageOff12:
3569 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
3570 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12:
3571 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21:
3572 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPageOff12:
3573#endif
a645023d
A
3574 return true;
3575 case ld::Fixup::kindStoreX86DtraceCallSiteNop:
3576 case ld::Fixup::kindStoreX86DtraceIsEnableSiteClear:
3577 case ld::Fixup::kindStoreARMDtraceCallSiteNop:
3578 case ld::Fixup::kindStoreARMDtraceIsEnableSiteClear:
f80fe69f
A
3579 case ld::Fixup::kindStoreARM64DtraceCallSiteNop:
3580 case ld::Fixup::kindStoreARM64DtraceIsEnableSiteClear:
a645023d
A
3581 case ld::Fixup::kindStoreThumbDtraceCallSiteNop:
3582 case ld::Fixup::kindStoreThumbDtraceIsEnableSiteClear:
a645023d
A
3583 return (_options.outputKind() == Options::kObjectFile);
3584 default:
3585 break;
3586 }
3587 return false;
3588}
3589
3590bool OutputFile::isPointerToTarget(ld::Fixup::Kind kind)
3591{
3592 switch ( kind ) {
3593 case ld::Fixup::kindSetTargetAddress:
3594 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
3595 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
3596 case ld::Fixup::kindStoreTargetAddressBigEndian32:
3597 case ld::Fixup::kindStoreTargetAddressBigEndian64:
3598 case ld::Fixup::kindLazyTarget:
3599 return true;
3600 default:
3601 break;
3602 }
3603 return false;
3604}
3605bool OutputFile::isPointerFromTarget(ld::Fixup::Kind kind)
3606{
3607 switch ( kind ) {
3608 case ld::Fixup::kindSubtractTargetAddress:
3609 return true;
3610 default:
3611 break;
3612 }
3613 return false;
3614}
3615
3616
3617uint64_t OutputFile::lookBackAddend(ld::Fixup::iterator fit)
3618{
3619 uint64_t addend = 0;
3620 switch ( fit->clusterSize ) {
3621 case ld::Fixup::k1of1:
3622 case ld::Fixup::k1of2:
3623 case ld::Fixup::k2of2:
3624 break;
3625 case ld::Fixup::k2of3:
3626 --fit;
3627 switch ( fit->kind ) {
3628 case ld::Fixup::kindAddAddend:
3629 addend += fit->u.addend;
3630 break;
3631 case ld::Fixup::kindSubtractAddend:
3632 addend -= fit->u.addend;
3633 break;
3634 default:
3635 throw "unexpected fixup kind for binding";
3636 }
3637 break;
3638 case ld::Fixup::k1of3:
3639 ++fit;
3640 switch ( fit->kind ) {
3641 case ld::Fixup::kindAddAddend:
3642 addend += fit->u.addend;
3643 break;
3644 case ld::Fixup::kindSubtractAddend:
3645 addend -= fit->u.addend;
3646 break;
3647 default:
3648 throw "unexpected fixup kind for binding";
3649 }
3650 break;
3651 default:
3652 throw "unexpected fixup cluster size for binding";
3653 }
3654 return addend;
3655}
3656
3657
a645023d
A
3658void OutputFile::generateLinkEditInfo(ld::Internal& state)
3659{
3660 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
3661 ld::Internal::FinalSection* sect = *sit;
9543cb2f
A
3662 // record end of last __TEXT section encrypted iPhoneOS apps.
3663 if ( _options.makeEncryptable() && (strcmp(sect->segmentName(), "__TEXT") == 0) ) {
3664 _encryptedTEXTendOffset = pageAlign(sect->fileOffset + sect->size);
3665 }
a645023d
A
3666 bool objc1ClassRefSection = ( (sect->type() == ld::Section::typeCStringPointer)
3667 && (strcmp(sect->sectionName(), "__cls_refs") == 0)
3668 && (strcmp(sect->segmentName(), "__OBJC") == 0) );
3669 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
3670 const ld::Atom* atom = *ait;
3671
3672 // Record regular atoms that override a dylib's weak definitions
3673 if ( (atom->scope() == ld::Atom::scopeGlobal) && atom->overridesDylibsWeakDef() ) {
3674 if ( _options.makeCompressedDyldInfo() ) {
3675 uint8_t wtype = BIND_TYPE_OVERRIDE_OF_WEAKDEF_IN_DYLIB;
3676 bool nonWeakDef = (atom->combine() == ld::Atom::combineNever);
3677 _weakBindingInfo.push_back(BindingInfo(wtype, atom->name(), nonWeakDef, atom->finalAddress(), 0));
3678 }
3679 this->overridesWeakExternalSymbols = true;
3680 if ( _options.warnWeakExports() )
3681 warning("overrides weak external symbol: %s", atom->name());
3682 }
3683
3684 ld::Fixup* fixupWithTarget = NULL;
3685 ld::Fixup* fixupWithMinusTarget = NULL;
3686 ld::Fixup* fixupWithStore = NULL;
f80fe69f 3687 ld::Fixup* fixupWithAddend = NULL;
a645023d
A
3688 const ld::Atom* target = NULL;
3689 const ld::Atom* minusTarget = NULL;
3690 uint64_t targetAddend = 0;
3691 uint64_t minusTargetAddend = 0;
3692 for (ld::Fixup::iterator fit = atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
3693 if ( fit->firstInCluster() ) {
3694 fixupWithTarget = NULL;
3695 fixupWithMinusTarget = NULL;
3696 fixupWithStore = NULL;
3697 target = NULL;
3698 minusTarget = NULL;
3699 targetAddend = 0;
3700 minusTargetAddend = 0;
3701 }
3702 if ( this->setsTarget(fit->kind) ) {
3703 switch ( fit->binding ) {
3704 case ld::Fixup::bindingNone:
3705 case ld::Fixup::bindingByNameUnbound:
3706 break;
3707 case ld::Fixup::bindingByContentBound:
3708 case ld::Fixup::bindingDirectlyBound:
3709 fixupWithTarget = fit;
3710 target = fit->u.target;
3711 break;
3712 case ld::Fixup::bindingsIndirectlyBound:
3713 fixupWithTarget = fit;
3714 target = state.indirectBindingTable[fit->u.bindingIndex];
3715 break;
3716 }
3717 assert(target != NULL);
3718 }
3719 switch ( fit->kind ) {
3720 case ld::Fixup::kindAddAddend:
3721 targetAddend = fit->u.addend;
f80fe69f 3722 fixupWithAddend = fit;
a645023d
A
3723 break;
3724 case ld::Fixup::kindSubtractAddend:
3725 minusTargetAddend = fit->u.addend;
f80fe69f 3726 fixupWithAddend = fit;
a645023d
A
3727 break;
3728 case ld::Fixup::kindSubtractTargetAddress:
3729 switch ( fit->binding ) {
3730 case ld::Fixup::bindingNone:
3731 case ld::Fixup::bindingByNameUnbound:
3732 break;
3733 case ld::Fixup::bindingByContentBound:
3734 case ld::Fixup::bindingDirectlyBound:
3735 fixupWithMinusTarget = fit;
3736 minusTarget = fit->u.target;
3737 break;
3738 case ld::Fixup::bindingsIndirectlyBound:
3739 fixupWithMinusTarget = fit;
3740 minusTarget = state.indirectBindingTable[fit->u.bindingIndex];
3741 break;
3742 }
3743 assert(minusTarget != NULL);
3744 break;
ebf6f434
A
3745 case ld::Fixup::kindDataInCodeStartData:
3746 case ld::Fixup::kindDataInCodeStartJT8:
3747 case ld::Fixup::kindDataInCodeStartJT16:
3748 case ld::Fixup::kindDataInCodeStartJT32:
3749 case ld::Fixup::kindDataInCodeStartJTA32:
3750 case ld::Fixup::kindDataInCodeEnd:
3751 hasDataInCode = true;
3752 break;
3753 default:
a645023d
A
3754 break;
3755 }
3756 if ( this->isStore(fit->kind) ) {
3757 fixupWithStore = fit;
3758 }
3759 if ( fit->lastInCluster() ) {
3760 if ( (fixupWithStore != NULL) && (target != NULL) ) {
3761 if ( _options.outputKind() == Options::kObjectFile ) {
f80fe69f 3762 this->addSectionRelocs(state, sect, atom, fixupWithTarget, fixupWithMinusTarget, fixupWithAddend, fixupWithStore,
a645023d
A
3763 target, minusTarget, targetAddend, minusTargetAddend);
3764 }
3765 else {
3766 if ( _options.makeCompressedDyldInfo() ) {
3767 this->addDyldInfo(state, sect, atom, fixupWithTarget, fixupWithMinusTarget, fixupWithStore,
3768 target, minusTarget, targetAddend, minusTargetAddend);
3769 }
3770 else {
3771 this->addClassicRelocs(state, sect, atom, fixupWithTarget, fixupWithMinusTarget, fixupWithStore,
3772 target, minusTarget, targetAddend, minusTargetAddend);
3773 }
3774 }
3775 }
3776 else if ( objc1ClassRefSection && (target != NULL) && (fixupWithStore == NULL) ) {
3777 // check for class refs to lazy loaded dylibs
3778 const ld::dylib::File* dylib = dynamic_cast<const ld::dylib::File*>(target->file());
3779 if ( (dylib != NULL) && dylib->willBeLazyLoadedDylib() )
3780 throwf("illegal class reference to %s in lazy loaded dylib %s", target->name(), dylib->path());
3781 }
3782 }
3783 }
3784 }
3785 }
3786}
3787
3788
3789void OutputFile::noteTextReloc(const ld::Atom* atom, const ld::Atom* target)
3790{
3791 if ( (atom->contentType() == ld::Atom::typeStub) || (atom->contentType() == ld::Atom::typeStubHelper) ) {
3792 // silently let stubs (synthesized by linker) use text relocs
3793 }
3794 else if ( _options.allowTextRelocs() ) {
3795 if ( _options.warnAboutTextRelocs() )
3796 warning("text reloc in %s to %s", atom->name(), target->name());
3797 }
ebf6f434
A
3798 else if ( _options.positionIndependentExecutable() && (_options.outputKind() == Options::kDynamicExecutable)
3799 && ((_options.iOSVersionMin() >= ld::iOS_4_3) || (_options.macosxVersionMin() >= ld::mac10_7)) ) {
a645023d 3800 if ( ! this->pieDisabled ) {
f80fe69f
A
3801#if SUPPORT_ARCH_arm64
3802 if ( _options.architecture() == CPU_TYPE_ARM64 ) {
3803 const char* demangledName = strdup(_options.demangleSymbol(atom->name()));
3804 throwf("Absolute addressing not allowed in arm64 code but used in '%s' referencing '%s'", demangledName, _options.demangleSymbol(target->name()));
3805 }
3806 else
3807#endif
3808 {
3809 warning("PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) not allowed in code signed PIE, "
a645023d
A
3810 "but used in %s from %s. "
3811 "To fix this warning, don't compile with -mdynamic-no-pic or link with -Wl,-no_pie",
3812 atom->name(), atom->file()->path());
f80fe69f 3813 }
a645023d
A
3814 }
3815 this->pieDisabled = true;
3816 }
afe874b1
A
3817 else if ( (target->scope() == ld::Atom::scopeGlobal) && (target->combine() == ld::Atom::combineByName) ) {
3818 throwf("illegal text-relocoation (direct reference) to (global,weak) %s in %s from %s in %s", target->name(), target->file()->path(), atom->name(), atom->file()->path());
3819 }
a645023d 3820 else {
f80fe69f
A
3821 if ( (target->file() != NULL) && (atom->file() != NULL) )
3822 throwf("illegal text-relocation to '%s' in %s from '%s' in %s", target->name(), target->file()->path(), atom->name(), atom->file()->path());
3823 else
3824 throwf("illegal text reloc in '%s' to '%s'", atom->name(), target->name());
a645023d
A
3825 }
3826}
3827
3828void OutputFile::addDyldInfo(ld::Internal& state, ld::Internal::FinalSection* sect, const ld::Atom* atom,
3829 ld::Fixup* fixupWithTarget, ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithStore,
3830 const ld::Atom* target, const ld::Atom* minusTarget,
3831 uint64_t targetAddend, uint64_t minusTargetAddend)
3832{
3833 if ( sect->isSectionHidden() )
3834 return;
3835
3836 // no need to rebase or bind PCRel stores
3837 if ( this->isPcRelStore(fixupWithStore->kind) ) {
3838 // as long as target is in same linkage unit
afe874b1
A
3839 if ( (target == NULL) || (target->definition() != ld::Atom::definitionProxy) ) {
3840 // make sure target is not global and weak
3841 if ( (target->scope() == ld::Atom::scopeGlobal) && (target->combine() == ld::Atom::combineByName) && (target->definition() == ld::Atom::definitionRegular)) {
3842 if ( (atom->section().type() == ld::Section::typeCFI)
3843 || (atom->section().type() == ld::Section::typeDtraceDOF)
3844 || (atom->section().type() == ld::Section::typeUnwindInfo) ) {
3845 // ok for __eh_frame and __uwind_info to use pointer diffs to global weak symbols
3846 return;
3847 }
f80fe69f
A
3848 // <rdar://problem/13700961> spurious warning when weak function has reference to itself
3849 if ( fixupWithTarget->binding == ld::Fixup::bindingDirectlyBound ) {
3850 // ok to ignore pc-rel references within a weak function to itself
3851 return;
3852 }
afe874b1 3853 // Have direct reference to weak-global. This should be an indrect reference
ebf6f434 3854 const char* demangledName = strdup(_options.demangleSymbol(atom->name()));
afe874b1
A
3855 warning("direct access in %s to global weak symbol %s means the weak symbol cannot be overridden at runtime. "
3856 "This was likely caused by different translation units being compiled with different visibility settings.",
ebf6f434 3857 demangledName, _options.demangleSymbol(target->name()));
afe874b1 3858 }
a645023d 3859 return;
afe874b1 3860 }
a645023d
A
3861 }
3862
3863 // no need to rebase or bind PIC internal pointer diff
3864 if ( minusTarget != NULL ) {
3865 // with pointer diffs, both need to be in same linkage unit
3866 assert(minusTarget->definition() != ld::Atom::definitionProxy);
3867 assert(target != NULL);
3868 assert(target->definition() != ld::Atom::definitionProxy);
3869 if ( target == minusTarget ) {
3870 // This is a compile time constant and could have been optimized away by compiler
3871 return;
3872 }
3873
afe874b1
A
3874 // check if target of pointer-diff is global and weak
3875 if ( (target->scope() == ld::Atom::scopeGlobal) && (target->combine() == ld::Atom::combineByName) && (target->definition() == ld::Atom::definitionRegular) ) {
3876 if ( (atom->section().type() == ld::Section::typeCFI)
3877 || (atom->section().type() == ld::Section::typeDtraceDOF)
3878 || (atom->section().type() == ld::Section::typeUnwindInfo) ) {
3879 // ok for __eh_frame and __uwind_info to use pointer diffs to global weak symbols
3880 return;
3881 }
3882 // Have direct reference to weak-global. This should be an indrect reference
ebf6f434 3883 const char* demangledName = strdup(_options.demangleSymbol(atom->name()));
afe874b1
A
3884 warning("direct access in %s to global weak symbol %s means the weak symbol cannot be overridden at runtime. "
3885 "This was likely caused by different translation units being compiled with different visibility settings.",
ebf6f434 3886 demangledName, _options.demangleSymbol(target->name()));
a645023d
A
3887 }
3888 return;
3889 }
3890
3891 // no need to rebase or bind an atom's references to itself if the output is not slidable
3892 if ( (atom == target) && !_options.outputSlidable() )
3893 return;
3894
3895 // cluster has no target, so needs no rebasing or binding
3896 if ( target == NULL )
3897 return;
3898
9543cb2f 3899 bool inReadOnlySeg = ((_options.initialSegProtection(sect->segmentName()) & VM_PROT_WRITE) == 0);
a645023d
A
3900 bool needsRebase = false;
3901 bool needsBinding = false;
3902 bool needsLazyBinding = false;
3903 bool needsWeakBinding = false;
3904
3905 uint8_t rebaseType = REBASE_TYPE_POINTER;
3906 uint8_t type = BIND_TYPE_POINTER;
3907 const ld::dylib::File* dylib = dynamic_cast<const ld::dylib::File*>(target->file());
ebf6f434 3908 bool weak_import = (fixupWithTarget->weakImport || ((dylib != NULL) && dylib->forcedWeakLinked()));
a645023d
A
3909 uint64_t address = atom->finalAddress() + fixupWithTarget->offsetInAtom;
3910 uint64_t addend = targetAddend - minusTargetAddend;
3911
3912 // special case lazy pointers
3913 if ( fixupWithTarget->kind == ld::Fixup::kindLazyTarget ) {
3914 assert(fixupWithTarget->u.target == target);
3915 assert(addend == 0);
3916 // lazy dylib lazy pointers do not have any dyld info
3917 if ( atom->section().type() == ld::Section::typeLazyDylibPointer )
3918 return;
3919 // lazy binding to weak definitions are done differently
3920 // they are directly bound to target, then have a weak bind in case of a collision
3921 if ( target->combine() == ld::Atom::combineByName ) {
3922 if ( target->definition() == ld::Atom::definitionProxy ) {
3923 // weak def exported from another dylib
3924 // must non-lazy bind to it plus have weak binding info in case of collision
3925 needsBinding = true;
3926 needsWeakBinding = true;
3927 }
3928 else {
3929 // weak def in this linkage unit.
3930 // just rebase, plus have weak binding info in case of collision
3931 // this will be done by other cluster on lazy pointer atom
3932 }
3933 }
f80fe69f 3934 else if ( target->contentType() == ld::Atom::typeResolver ) {
a645023d 3935 // <rdar://problem/8553647> Hidden resolver functions should not have lazy binding info
f80fe69f
A
3936 // <rdar://problem/12629331> Resolver function run before initializers when overriding the dyld shared cache
3937 // The lazy pointers used by stubs used when non-lazy binding to a resolver are not normal lazy pointers
3938 // and should not be in lazy binding info.
a645023d
A
3939 needsLazyBinding = false;
3940 }
3941 else {
3942 // normal case of a pointer to non-weak-def symbol, so can lazily bind
3943 needsLazyBinding = true;
3944 }
3945 }
3946 else {
3947 // everything except lazy pointers
3948 switch ( target->definition() ) {
3949 case ld::Atom::definitionProxy:
3950 if ( (dylib != NULL) && dylib->willBeLazyLoadedDylib() )
3951 throwf("illegal data reference to %s in lazy loaded dylib %s", target->name(), dylib->path());
3952 if ( target->contentType() == ld::Atom::typeTLV ) {
3953 if ( sect->type() != ld::Section::typeTLVPointers )
3954 throwf("illegal data reference in %s to thread local variable %s in dylib %s",
3955 atom->name(), target->name(), dylib->path());
3956 }
3957 if ( inReadOnlySeg )
3958 type = BIND_TYPE_TEXT_ABSOLUTE32;
3959 needsBinding = true;
3960 if ( target->combine() == ld::Atom::combineByName )
3961 needsWeakBinding = true;
3962 break;
3963 case ld::Atom::definitionRegular:
3964 case ld::Atom::definitionTentative:
3965 // only slideable images need rebasing info
3966 if ( _options.outputSlidable() ) {
3967 needsRebase = true;
3968 }
3969 // references to internal symbol never need binding
3970 if ( target->scope() != ld::Atom::scopeGlobal )
3971 break;
3972 // reference to global weak def needs weak binding
3973 if ( (target->combine() == ld::Atom::combineByName) && (target->definition() == ld::Atom::definitionRegular) )
3974 needsWeakBinding = true;
3975 else if ( _options.outputKind() == Options::kDynamicExecutable ) {
3976 // in main executables, the only way regular symbols are indirected is if -interposable is used
3977 if ( _options.interposable(target->name()) ) {
3978 needsRebase = false;
3979 needsBinding = true;
3980 }
3981 }
3982 else {
3983 // for flat-namespace or interposable two-level-namespace
3984 // all references to exported symbols get indirected
3985 if ( (_options.nameSpace() != Options::kTwoLevelNameSpace) || _options.interposable(target->name()) ) {
3986 // <rdar://problem/5254468> no external relocs for flat objc classes
3987 if ( strncmp(target->name(), ".objc_class_", 12) == 0 )
3988 break;
3989 // no rebase info for references to global symbols that will have binding info
3990 needsRebase = false;
3991 needsBinding = true;
3992 }
f80fe69f
A
3993 else if ( _options.forceCoalesce(target->name()) ) {
3994 needsWeakBinding = true;
3995 }
a645023d
A
3996 }
3997 break;
3998 case ld::Atom::definitionAbsolute:
3999 break;
4000 }
4001 }
4002
f80fe69f
A
4003 // <rdar://problem/13828711> if target is an import alias, use base of alias
4004 if ( target->isAlias() && (target->definition() == ld::Atom::definitionProxy) ) {
4005 for (ld::Fixup::iterator fit = target->fixupsBegin(), end=target->fixupsEnd(); fit != end; ++fit) {
4006 if ( fit->firstInCluster() ) {
4007 if ( fit->kind == ld::Fixup::kindNoneFollowOn ) {
4008 if ( fit->binding == ld::Fixup::bindingDirectlyBound ) {
4009 //fprintf(stderr, "switching import of %s to import of %s\n", target->name(), fit->u.target->name());
4010 target = fit->u.target;
4011 }
4012 }
4013 }
4014 }
4015 }
4016
a645023d
A
4017 // record dyld info for this cluster
4018 if ( needsRebase ) {
4019 if ( inReadOnlySeg ) {
4020 noteTextReloc(atom, target);
4021 sect->hasLocalRelocs = true; // so dyld knows to change permissions on __TEXT segment
4022 rebaseType = REBASE_TYPE_TEXT_ABSOLUTE32;
4023 }
f80fe69f
A
4024 if ( _options.sharedRegionEligible() ) {
4025 // <rdar://problem/13287063> when range checking, ignore high byte of arm64 addends
4026 uint64_t checkAddend = addend;
4027 if ( _options.architecture() == CPU_TYPE_ARM64 )
4028 checkAddend &= 0x0FFFFFFFFFFFFFFFULL;
4029 if ( checkAddend != 0 ) {
4030 // make sure the addend does not cause the pointer to point outside the target's segment
4031 // if it does, update_dyld_shared_cache will not be able to put this dylib into the shared cache
4032 uint64_t targetAddress = target->finalAddress();
4033 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
4034 ld::Internal::FinalSection* sct = *sit;
4035 uint64_t sctEnd = (sct->address+sct->size);
4036 if ( (sct->address <= targetAddress) && (targetAddress < sctEnd) ) {
4037 if ( (targetAddress+checkAddend) > sctEnd ) {
4038 warning("data symbol %s from %s has pointer to %s + 0x%08llX. "
4039 "That large of an addend may disable %s from being put in the dyld shared cache.",
4040 atom->name(), atom->file()->path(), target->name(), addend, _options.installPath() );
4041 }
ebf6f434
A
4042 }
4043 }
4044 }
4045 }
a645023d
A
4046 _rebaseInfo.push_back(RebaseInfo(rebaseType, address));
4047 }
4048 if ( needsBinding ) {
4049 if ( inReadOnlySeg ) {
4050 noteTextReloc(atom, target);
4051 sect->hasExternalRelocs = true; // so dyld knows to change permissions on __TEXT segment
4052 }
4053 _bindingInfo.push_back(BindingInfo(type, this->compressedOrdinalForAtom(target), target->name(), weak_import, address, addend));
4054 }
4055 if ( needsLazyBinding ) {
4056 if ( _options.bindAtLoad() )
4057 _bindingInfo.push_back(BindingInfo(type, this->compressedOrdinalForAtom(target), target->name(), weak_import, address, addend));
4058 else
4059 _lazyBindingInfo.push_back(BindingInfo(type, this->compressedOrdinalForAtom(target), target->name(), weak_import, address, addend));
4060 }
4061 if ( needsWeakBinding )
4062 _weakBindingInfo.push_back(BindingInfo(type, 0, target->name(), false, address, addend));
a645023d
A
4063}
4064
4065
4066void OutputFile::addClassicRelocs(ld::Internal& state, ld::Internal::FinalSection* sect, const ld::Atom* atom,
4067 ld::Fixup* fixupWithTarget, ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithStore,
4068 const ld::Atom* target, const ld::Atom* minusTarget,
4069 uint64_t targetAddend, uint64_t minusTargetAddend)
4070{
4071 if ( sect->isSectionHidden() )
4072 return;
4073
4074 // non-lazy-pointer section is encoded in indirect symbol table - not using relocations
ebf6f434
A
4075 if ( sect->type() == ld::Section::typeNonLazyPointer ) {
4076 // except kexts and static pie which *do* use relocations
4077 switch (_options.outputKind()) {
4078 case Options::kKextBundle:
4079 break;
4080 case Options::kStaticExecutable:
4081 if ( _options.positionIndependentExecutable() )
4082 break;
4083 // else fall into default case
4084 default:
4085 assert(target != NULL);
4086 assert(fixupWithTarget != NULL);
4087 return;
4088 }
a645023d
A
4089 }
4090
4091 // no need to rebase or bind PCRel stores
4092 if ( this->isPcRelStore(fixupWithStore->kind) ) {
4093 // as long as target is in same linkage unit
4094 if ( (target == NULL) || (target->definition() != ld::Atom::definitionProxy) )
4095 return;
4096 }
4097
4098 // no need to rebase or bind PIC internal pointer diff
4099 if ( minusTarget != NULL ) {
4100 // with pointer diffs, both need to be in same linkage unit
4101 assert(minusTarget->definition() != ld::Atom::definitionProxy);
4102 assert(target != NULL);
4103 assert(target->definition() != ld::Atom::definitionProxy);
4104 // make sure target is not global and weak
4105 if ( (target->scope() == ld::Atom::scopeGlobal) && (target->combine() == ld::Atom::combineByName)
4106 && (atom->section().type() != ld::Section::typeCFI)
4107 && (atom->section().type() != ld::Section::typeDtraceDOF)
4108 && (atom->section().type() != ld::Section::typeUnwindInfo)
4109 && (minusTarget != target) ) {
4110 // ok for __eh_frame and __uwind_info to use pointer diffs to global weak symbols
4111 throwf("bad codegen, pointer diff in %s to global weak symbol %s", atom->name(), target->name());
4112 }
4113 return;
4114 }
4115
4116 // cluster has no target, so needs no rebasing or binding
4117 if ( target == NULL )
4118 return;
4119
4120 assert(_localRelocsAtom != NULL);
4121 uint64_t relocAddress = atom->finalAddress() + fixupWithTarget->offsetInAtom - _localRelocsAtom->relocBaseAddress(state);
4122
4123 bool inReadOnlySeg = ( strcmp(sect->segmentName(), "__TEXT") == 0 );
4124 bool needsLocalReloc = false;
4125 bool needsExternReloc = false;
4126
4127 switch ( fixupWithStore->kind ) {
4128 case ld::Fixup::kindLazyTarget:
afe874b1 4129 // lazy pointers don't need relocs
a645023d
A
4130 break;
4131 case ld::Fixup::kindStoreLittleEndian32:
4132 case ld::Fixup::kindStoreLittleEndian64:
4133 case ld::Fixup::kindStoreBigEndian32:
4134 case ld::Fixup::kindStoreBigEndian64:
4135 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
4136 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
4137 case ld::Fixup::kindStoreTargetAddressBigEndian32:
4138 case ld::Fixup::kindStoreTargetAddressBigEndian64:
4139 // is pointer
4140 switch ( target->definition() ) {
4141 case ld::Atom::definitionProxy:
4142 needsExternReloc = true;
4143 break;
4144 case ld::Atom::definitionRegular:
4145 case ld::Atom::definitionTentative:
4146 // only slideable images need local relocs
4147 if ( _options.outputSlidable() )
4148 needsLocalReloc = true;
4149 // references to internal symbol never need binding
4150 if ( target->scope() != ld::Atom::scopeGlobal )
4151 break;
4152 // reference to global weak def needs weak binding in dynamic images
4153 if ( (target->combine() == ld::Atom::combineByName)
4154 && (target->definition() == ld::Atom::definitionRegular)
d425e388 4155 && (_options.outputKind() != Options::kStaticExecutable)
f80fe69f
A
4156 && (_options.outputKind() != Options::kPreload)
4157 && (atom != target) ) {
a645023d
A
4158 needsExternReloc = true;
4159 }
4160 else if ( _options.outputKind() == Options::kDynamicExecutable ) {
4161 // in main executables, the only way regular symbols are indirected is if -interposable is used
4162 if ( _options.interposable(target->name()) )
4163 needsExternReloc = true;
4164 }
4165 else {
4166 // for flat-namespace or interposable two-level-namespace
4167 // all references to exported symbols get indirected
4168 if ( (_options.nameSpace() != Options::kTwoLevelNameSpace) || _options.interposable(target->name()) ) {
4169 // <rdar://problem/5254468> no external relocs for flat objc classes
4170 if ( strncmp(target->name(), ".objc_class_", 12) == 0 )
4171 break;
4172 // no rebase info for references to global symbols that will have binding info
4173 needsExternReloc = true;
4174 }
4175 }
4176 if ( needsExternReloc )
4177 needsLocalReloc = false;
4178 break;
4179 case ld::Atom::definitionAbsolute:
4180 break;
4181 }
4182 if ( needsExternReloc ) {
4183 if ( inReadOnlySeg )
4184 noteTextReloc(atom, target);
4185 const ld::dylib::File* dylib = dynamic_cast<const ld::dylib::File*>(target->file());
4186 if ( (dylib != NULL) && dylib->willBeLazyLoadedDylib() )
4187 throwf("illegal data reference to %s in lazy loaded dylib %s", target->name(), dylib->path());
4188 _externalRelocsAtom->addExternalPointerReloc(relocAddress, target);
4189 sect->hasExternalRelocs = true;
4190 fixupWithTarget->contentAddendOnly = true;
a645023d
A
4191 }
4192 else if ( needsLocalReloc ) {
4193 assert(target != NULL);
4194 if ( inReadOnlySeg )
4195 noteTextReloc(atom, target);
4196 _localRelocsAtom->addPointerReloc(relocAddress, target->machoSection());
4197 sect->hasLocalRelocs = true;
4198 }
4199 break;
a645023d 4200 case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32:
f80fe69f
A
4201#if SUPPORT_ARCH_arm64
4202 case ld::Fixup::kindStoreTargetAddressARM64Branch26:
4203#endif
a645023d
A
4204 if ( _options.outputKind() == Options::kKextBundle ) {
4205 assert(target != NULL);
4206 if ( target->definition() == ld::Atom::definitionProxy ) {
4207 _externalRelocsAtom->addExternalCallSiteReloc(relocAddress, target);
4208 fixupWithStore->contentAddendOnly = true;
4209 }
4210 }
4211 break;
afe874b1
A
4212
4213 case ld::Fixup::kindStoreARMLow16:
4214 case ld::Fixup::kindStoreThumbLow16:
4215 // no way to encode rebasing of binding for these instructions
4216 if ( _options.outputSlidable() || (target->definition() == ld::Atom::definitionProxy) )
4217 throwf("no supported runtime lo16 relocation in %s from %s to %s", atom->name(), atom->file()->path(), target->name());
4218 break;
4219
4220 case ld::Fixup::kindStoreARMHigh16:
4221 case ld::Fixup::kindStoreThumbHigh16:
4222 // no way to encode rebasing of binding for these instructions
4223 if ( _options.outputSlidable() || (target->definition() == ld::Atom::definitionProxy) )
4224 throwf("no supported runtime hi16 relocation in %s from %s to %s", atom->name(), atom->file()->path(), target->name());
4225 break;
4226
a645023d
A
4227 default:
4228 break;
4229 }
4230}
4231
4232
4233bool OutputFile::useExternalSectionReloc(const ld::Atom* atom, const ld::Atom* target, ld::Fixup* fixupWithTarget)
4234{
f80fe69f
A
4235 if ( (_options.architecture() == CPU_TYPE_X86_64) || (_options.architecture() == CPU_TYPE_ARM64) ) {
4236 // x86_64 and ARM64 use external relocations for everthing that has a symbol
a645023d
A
4237 return ( target->symbolTableInclusion() != ld::Atom::symbolTableNotIn );
4238 }
afe874b1
A
4239
4240 // <rdar://problem/9513487> support arm branch interworking in -r mode
4241 if ( (_options.architecture() == CPU_TYPE_ARM) && (_options.outputKind() == Options::kObjectFile) ) {
4242 if ( atom->isThumb() != target->isThumb() ) {
4243 switch ( fixupWithTarget->kind ) {
4244 // have branch that switches mode, then might be 'b' not 'bl'
4245 // Force external relocation, since no way to do local reloc for 'b'
4246 case ld::Fixup::kindStoreTargetAddressThumbBranch22 :
4247 case ld::Fixup::kindStoreTargetAddressARMBranch24:
4248 return true;
4249 default:
4250 break;
4251 }
4252 }
4253 }
b1f7435d
A
4254
4255 if ( (_options.architecture() == CPU_TYPE_I386) && (_options.outputKind() == Options::kObjectFile) ) {
4256 if ( target->contentType() == ld::Atom::typeTLV )
4257 return true;
4258 }
afe874b1 4259
a645023d
A
4260 // most architectures use external relocations only for references
4261 // to a symbol in another translation unit or for references to "weak symbols" or tentative definitions
4262 assert(target != NULL);
4263 if ( target->definition() == ld::Atom::definitionProxy )
4264 return true;
4265 if ( (target->definition() == ld::Atom::definitionTentative) && ! _options.makeTentativeDefinitionsReal() )
4266 return true;
4267 if ( target->scope() != ld::Atom::scopeGlobal )
4268 return false;
4269 if ( (target->combine() == ld::Atom::combineByName) && (target->definition() == ld::Atom::definitionRegular) )
4270 return true;
4271 return false;
4272}
4273
f80fe69f
A
4274bool OutputFile::useSectionRelocAddend(ld::Fixup* fixupWithTarget)
4275{
4276#if SUPPORT_ARCH_arm64
4277 if ( _options.architecture() == CPU_TYPE_ARM64 ) {
4278 switch ( fixupWithTarget->kind ) {
4279 case ld::Fixup::kindStoreARM64Branch26:
4280 case ld::Fixup::kindStoreARM64Page21:
4281 case ld::Fixup::kindStoreARM64PageOff12:
4282 return true;
4283 default:
4284 return false;
4285 }
4286 }
4287#endif
4288 return false;
4289}
4290
a645023d
A
4291
4292
4293
4294void OutputFile::addSectionRelocs(ld::Internal& state, ld::Internal::FinalSection* sect, const ld::Atom* atom,
f80fe69f
A
4295 ld::Fixup* fixupWithTarget, ld::Fixup* fixupWithMinusTarget,
4296 ld::Fixup* fixupWithAddend, ld::Fixup* fixupWithStore,
a645023d
A
4297 const ld::Atom* target, const ld::Atom* minusTarget,
4298 uint64_t targetAddend, uint64_t minusTargetAddend)
4299{
4300 if ( sect->isSectionHidden() )
4301 return;
4302
4303 // in -r mode where there will be no labels on __eh_frame section, there is no need for relocations
4304 if ( (sect->type() == ld::Section::typeCFI) && _options.removeEHLabels() )
4305 return;
4306
4307 // non-lazy-pointer section is encoded in indirect symbol table - not using relocations
4308 if ( sect->type() == ld::Section::typeNonLazyPointer )
4309 return;
4310
4311 // tentative defs don't have any relocations
4312 if ( sect->type() == ld::Section::typeTentativeDefs )
4313 return;
4314
4315 assert(target != NULL);
4316 assert(fixupWithTarget != NULL);
4317 bool targetUsesExternalReloc = this->useExternalSectionReloc(atom, target, fixupWithTarget);
4318 bool minusTargetUsesExternalReloc = (minusTarget != NULL) && this->useExternalSectionReloc(atom, minusTarget, fixupWithMinusTarget);
4319
f80fe69f
A
4320 // in x86_64 and arm64 .o files an external reloc means the content contains just the addend
4321 if ( (_options.architecture() == CPU_TYPE_X86_64) ||(_options.architecture() == CPU_TYPE_ARM64) ) {
a645023d
A
4322 if ( targetUsesExternalReloc ) {
4323 fixupWithTarget->contentAddendOnly = true;
4324 fixupWithStore->contentAddendOnly = true;
f80fe69f
A
4325 if ( this->useSectionRelocAddend(fixupWithStore) && (fixupWithAddend != NULL) )
4326 fixupWithAddend->contentIgnoresAddend = true;
a645023d
A
4327 }
4328 if ( minusTargetUsesExternalReloc )
4329 fixupWithMinusTarget->contentAddendOnly = true;
4330 }
4331 else {
4332 // for other archs, content is addend only with (non pc-rel) pointers
4333 // pc-rel instructions are funny. If the target is _foo+8 and _foo is
4334 // external, then the pc-rel instruction *evalutates* to the address 8.
4335 if ( targetUsesExternalReloc ) {
b1f7435d
A
4336 // TLV support for i386 acts like RIP relative addressing
4337 // The addend is the offset from the PICBase to the end of the instruction
4338 if ( (_options.architecture() == CPU_TYPE_I386)
4339 && (_options.outputKind() == Options::kObjectFile)
4340 && (fixupWithStore->kind == ld::Fixup::kindStoreX86PCRel32TLVLoad) ) {
4341 fixupWithTarget->contentAddendOnly = true;
4342 fixupWithStore->contentAddendOnly = true;
4343 }
4344 else if ( isPcRelStore(fixupWithStore->kind) ) {
a645023d
A
4345 fixupWithTarget->contentDetlaToAddendOnly = true;
4346 fixupWithStore->contentDetlaToAddendOnly = true;
4347 }
4348 else if ( minusTarget == NULL ){
4349 fixupWithTarget->contentAddendOnly = true;
4350 fixupWithStore->contentAddendOnly = true;
4351 }
4352 }
4353 }
4354
4355 if ( fixupWithStore != NULL ) {
4356 _sectionsRelocationsAtom->addSectionReloc(sect, fixupWithStore->kind, atom, fixupWithStore->offsetInAtom,
4357 targetUsesExternalReloc, minusTargetUsesExternalReloc,
4358 target, targetAddend, minusTarget, minusTargetAddend);
4359 }
4360
4361}
4362
4363
4364void OutputFile::makeSplitSegInfo(ld::Internal& state)
4365{
4366 if ( !_options.sharedRegionEligible() )
4367 return;
4368
4369 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
4370 ld::Internal::FinalSection* sect = *sit;
4371 if ( sect->isSectionHidden() )
4372 continue;
4373 if ( strcmp(sect->segmentName(), "__TEXT") != 0 )
4374 continue;
4375 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
4376 const ld::Atom* atom = *ait;
4377 const ld::Atom* target = NULL;
afe874b1
A
4378 const ld::Atom* fromTarget = NULL;
4379 uint64_t accumulator = 0;
4380 bool thumbTarget;
a645023d
A
4381 bool hadSubtract = false;
4382 for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
4383 if ( fit->firstInCluster() )
4384 target = NULL;
afe874b1
A
4385 if ( this->setsTarget(fit->kind) ) {
4386 accumulator = addressOf(state, fit, &target);
4387 thumbTarget = targetIsThumb(state, fit);
4388 if ( thumbTarget )
4389 accumulator |= 1;
a645023d 4390 }
afe874b1
A
4391 switch ( fit->kind ) {
4392 case ld::Fixup::kindSubtractTargetAddress:
4393 accumulator -= addressOf(state, fit, &fromTarget);
4394 hadSubtract = true;
a645023d 4395 break;
afe874b1
A
4396 case ld::Fixup::kindAddAddend:
4397 accumulator += fit->u.addend;
a645023d 4398 break;
afe874b1
A
4399 case ld::Fixup::kindSubtractAddend:
4400 accumulator -= fit->u.addend;
a645023d 4401 break;
a645023d
A
4402 case ld::Fixup::kindStoreBigEndian32:
4403 case ld::Fixup::kindStoreLittleEndian32:
4404 case ld::Fixup::kindStoreLittleEndian64:
4405 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
4406 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
4407 // if no subtract, then this is an absolute pointer which means
4408 // there is also a text reloc which update_dyld_shared_cache will use.
4409 if ( ! hadSubtract )
4410 break;
afe874b1 4411 // fall through
a645023d
A
4412 case ld::Fixup::kindStoreX86PCRel32:
4413 case ld::Fixup::kindStoreX86PCRel32_1:
4414 case ld::Fixup::kindStoreX86PCRel32_2:
4415 case ld::Fixup::kindStoreX86PCRel32_4:
4416 case ld::Fixup::kindStoreX86PCRel32GOTLoad:
4417 case ld::Fixup::kindStoreX86PCRel32GOTLoadNowLEA:
4418 case ld::Fixup::kindStoreX86PCRel32GOT:
f80fe69f
A
4419 case ld::Fixup::kindStoreX86PCRel32TLVLoad:
4420 case ld::Fixup::kindStoreX86PCRel32TLVLoadNowLEA:
a645023d
A
4421 case ld::Fixup::kindStoreTargetAddressX86PCRel32:
4422 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad:
4423 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA:
f80fe69f
A
4424 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad:
4425 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA:
afe874b1
A
4426 case ld::Fixup::kindStoreARMLow16:
4427 case ld::Fixup::kindStoreThumbLow16:
f80fe69f
A
4428#if SUPPORT_ARCH_arm64
4429 case ld::Fixup::kindStoreARM64Page21:
4430 case ld::Fixup::kindStoreARM64GOTLoadPage21:
4431 case ld::Fixup::kindStoreARM64GOTLeaPage21:
4432 case ld::Fixup::kindStoreARM64TLVPLoadPage21:
4433 case ld::Fixup::kindStoreTargetAddressARM64Page21:
4434 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
4435 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21:
4436 case ld::Fixup::kindStoreARM64PCRelToGOT:
4437#endif
a645023d
A
4438 assert(target != NULL);
4439 if ( strcmp(sect->segmentName(), target->section().segmentName()) != 0 ) {
4440 _splitSegInfos.push_back(SplitSegInfoEntry(atom->finalAddress()+fit->offsetInAtom,fit->kind));
4441 }
4442 break;
afe874b1
A
4443 case ld::Fixup::kindStoreARMHigh16:
4444 case ld::Fixup::kindStoreThumbHigh16:
4445 assert(target != NULL);
4446 if ( strcmp(sect->segmentName(), target->section().segmentName()) != 0 ) {
4447 // hi16 needs to know upper 4-bits of low16 to compute carry
4448 uint32_t extra = (accumulator >> 12) & 0xF;
4449 _splitSegInfos.push_back(SplitSegInfoEntry(atom->finalAddress()+fit->offsetInAtom,fit->kind, extra));
4450 }
4451 break;
4452 case ld::Fixup::kindSetTargetImageOffset:
4453 accumulator = addressOf(state, fit, &target);
4454 assert(target != NULL);
4455 hadSubtract = true;
4456 break;
a645023d
A
4457 default:
4458 break;
4459 }
4460 }
4461 }
4462 }
4463}
4464
4465
4466void OutputFile::writeMapFile(ld::Internal& state)
4467{
4468 if ( _options.generatedMapPath() != NULL ) {
4469 FILE* mapFile = fopen(_options.generatedMapPath(), "w");
4470 if ( mapFile != NULL ) {
4471 // write output path
4472 fprintf(mapFile, "# Path: %s\n", _options.outputFilePath());
4473 // write output architecure
4474 fprintf(mapFile, "# Arch: %s\n", _options.architectureName());
4475 // write UUID
4476 //if ( fUUIDAtom != NULL ) {
4477 // const uint8_t* uuid = fUUIDAtom->getUUID();
4478 // fprintf(mapFile, "# UUID: %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X \n",
4479 // uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
4480 // uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
4481 //}
4482 // write table of object files
ebf6f434
A
4483 std::map<const ld::File*, ld::File::Ordinal> readerToOrdinal;
4484 std::map<ld::File::Ordinal, const ld::File*> ordinalToReader;
a645023d
A
4485 std::map<const ld::File*, uint32_t> readerToFileOrdinal;
4486 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
4487 ld::Internal::FinalSection* sect = *sit;
4488 if ( sect->isSectionHidden() )
4489 continue;
4490 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
4491 const ld::Atom* atom = *ait;
4492 const ld::File* reader = atom->file();
4493 if ( reader == NULL )
4494 continue;
ebf6f434
A
4495 ld::File::Ordinal readerOrdinal = reader->ordinal();
4496 std::map<const ld::File*, ld::File::Ordinal>::iterator pos = readerToOrdinal.find(reader);
a645023d
A
4497 if ( pos == readerToOrdinal.end() ) {
4498 readerToOrdinal[reader] = readerOrdinal;
4499 ordinalToReader[readerOrdinal] = reader;
4500 }
4501 }
4502 }
4503 fprintf(mapFile, "# Object files:\n");
4504 fprintf(mapFile, "[%3u] %s\n", 0, "linker synthesized");
ebf6f434
A
4505 uint32_t fileIndex = 1;
4506 for(std::map<ld::File::Ordinal, const ld::File*>::iterator it = ordinalToReader.begin(); it != ordinalToReader.end(); ++it) {
4507 fprintf(mapFile, "[%3u] %s\n", fileIndex, it->second->path());
4508 readerToFileOrdinal[it->second] = fileIndex++;
a645023d
A
4509 }
4510 // write table of sections
4511 fprintf(mapFile, "# Sections:\n");
4512 fprintf(mapFile, "# Address\tSize \tSegment\tSection\n");
4513 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
4514 ld::Internal::FinalSection* sect = *sit;
4515 if ( sect->isSectionHidden() )
4516 continue;
4517 fprintf(mapFile, "0x%08llX\t0x%08llX\t%s\t%s\n", sect->address, sect->size,
4518 sect->segmentName(), sect->sectionName());
4519 }
4520 // write table of symbols
4521 fprintf(mapFile, "# Symbols:\n");
4522 fprintf(mapFile, "# Address\tSize \tFile Name\n");
4523 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
4524 ld::Internal::FinalSection* sect = *sit;
4525 if ( sect->isSectionHidden() )
4526 continue;
4527 //bool isCstring = (sect->type() == ld::Section::typeCString);
4528 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
4529 char buffer[4096];
4530 const ld::Atom* atom = *ait;
4531 const char* name = atom->name();
d425e388
A
4532 // don't add auto-stripped aliases to .map file
4533 if ( (atom->size() == 0) && (atom->symbolTableInclusion() == ld::Atom::symbolTableNotInFinalLinkedImages) )
4534 continue;
a645023d
A
4535 if ( atom->contentType() == ld::Atom::typeCString ) {
4536 strcpy(buffer, "literal string: ");
4537 strlcat(buffer, (char*)atom->rawContentPointer(), 4096);
4538 name = buffer;
4539 }
4540 else if ( (atom->contentType() == ld::Atom::typeCFI) && (strcmp(name, "FDE") == 0) ) {
4541 for (ld::Fixup::iterator fit = atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
4542 if ( (fit->kind == ld::Fixup::kindSetTargetAddress) && (fit->clusterSize == ld::Fixup::k1of4) ) {
4543 assert(fit->binding == ld::Fixup::bindingDirectlyBound);
4544 if ( fit->u.target->section().type() == ld::Section::typeCode) {
4545 strcpy(buffer, "FDE for: ");
4546 strlcat(buffer, fit->u.target->name(), 4096);
4547 name = buffer;
4548 }
4549 }
4550 }
4551 }
4552 else if ( atom->contentType() == ld::Atom::typeNonLazyPointer ) {
4553 strcpy(buffer, "non-lazy-pointer");
4554 for (ld::Fixup::iterator fit = atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
4555 if ( fit->binding == ld::Fixup::bindingsIndirectlyBound ) {
4556 strcpy(buffer, "non-lazy-pointer-to: ");
4557 strlcat(buffer, state.indirectBindingTable[fit->u.bindingIndex]->name(), 4096);
4558 break;
4559 }
4560 else if ( fit->binding == ld::Fixup::bindingDirectlyBound ) {
4561 strcpy(buffer, "non-lazy-pointer-to-local: ");
4562 strlcat(buffer, fit->u.target->name(), 4096);
4563 break;
4564 }
4565 }
4566 name = buffer;
4567 }
4568 fprintf(mapFile, "0x%08llX\t0x%08llX\t[%3u] %s\n", atom->finalAddress(), atom->size(),
4569 readerToFileOrdinal[atom->file()], name);
4570 }
4571 }
4572 fclose(mapFile);
4573 }
4574 else {
4575 warning("could not write map file: %s\n", _options.generatedMapPath());
4576 }
4577 }
4578}
4579
4580
4581// used to sort atoms with debug notes
4582class DebugNoteSorter
4583{
4584public:
4585 bool operator()(const ld::Atom* left, const ld::Atom* right) const
4586 {
4587 // first sort by reader
ebf6f434
A
4588 ld::File::Ordinal leftFileOrdinal = left->file()->ordinal();
4589 ld::File::Ordinal rightFileOrdinal = right->file()->ordinal();
a645023d
A
4590 if ( leftFileOrdinal!= rightFileOrdinal)
4591 return (leftFileOrdinal < rightFileOrdinal);
4592
4593 // then sort by atom objectAddress
afe874b1
A
4594 uint64_t leftAddr = left->finalAddress();
4595 uint64_t rightAddr = right->finalAddress();
a645023d
A
4596 return leftAddr < rightAddr;
4597 }
4598};
4599
4600
a645023d
A
4601const char* OutputFile::assureFullPath(const char* path)
4602{
4603 if ( path[0] == '/' )
4604 return path;
4605 char cwdbuff[MAXPATHLEN];
4606 if ( getcwd(cwdbuff, MAXPATHLEN) != NULL ) {
4607 char* result;
4608 asprintf(&result, "%s/%s", cwdbuff, path);
4609 if ( result != NULL )
4610 return result;
4611 }
4612 return path;
4613}
4614
4615void OutputFile::synthesizeDebugNotes(ld::Internal& state)
4616{
4617 // -S means don't synthesize debug map
4618 if ( _options.debugInfoStripping() == Options::kDebugInfoNone )
4619 return;
4620 // make a vector of atoms that come from files compiled with dwarf debug info
4621 std::vector<const ld::Atom*> atomsNeedingDebugNotes;
4622 std::set<const ld::Atom*> atomsWithStabs;
4623 atomsNeedingDebugNotes.reserve(1024);
4624 const ld::relocatable::File* objFile = NULL;
4625 bool objFileHasDwarf = false;
4626 bool objFileHasStabs = false;
4627 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
4628 ld::Internal::FinalSection* sect = *sit;
4629 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
4630 const ld::Atom* atom = *ait;
4631 // no stabs for atoms that would not be in the symbol table
4632 if ( atom->symbolTableInclusion() == ld::Atom::symbolTableNotIn )
4633 continue;
4634 if ( atom->symbolTableInclusion() == ld::Atom::symbolTableNotInFinalLinkedImages )
4635 continue;
d425e388
A
4636 if ( atom->symbolTableInclusion() == ld::Atom::symbolTableInWithRandomAutoStripLabel )
4637 continue;
a645023d
A
4638 // no stabs for absolute symbols
4639 if ( atom->definition() == ld::Atom::definitionAbsolute )
4640 continue;
4641 // no stabs for .eh atoms
4642 if ( atom->contentType() == ld::Atom::typeCFI )
4643 continue;
d425e388
A
4644 // no stabs for string literal atoms
4645 if ( atom->contentType() == ld::Atom::typeCString )
4646 continue;
4647 // no stabs for kernel dtrace probes
4648 if ( (_options.outputKind() == Options::kStaticExecutable) && (strncmp(atom->name(), "__dtrace_probe$", 15) == 0) )
4649 continue;
a645023d
A
4650 const ld::File* file = atom->file();
4651 if ( file != NULL ) {
4652 if ( file != objFile ) {
4653 objFileHasDwarf = false;
4654 objFileHasStabs = false;
4655 objFile = dynamic_cast<const ld::relocatable::File*>(file);
4656 if ( objFile != NULL ) {
4657 switch ( objFile->debugInfo() ) {
4658 case ld::relocatable::File::kDebugInfoNone:
4659 break;
4660 case ld::relocatable::File::kDebugInfoDwarf:
4661 objFileHasDwarf = true;
4662 break;
4663 case ld::relocatable::File::kDebugInfoStabs:
4664 case ld::relocatable::File::kDebugInfoStabsUUID:
4665 objFileHasStabs = true;
4666 break;
4667 }
4668 }
4669 }
4670 if ( objFileHasDwarf )
4671 atomsNeedingDebugNotes.push_back(atom);
4672 if ( objFileHasStabs )
4673 atomsWithStabs.insert(atom);
4674 }
4675 }
4676 }
4677
4678 // sort by file ordinal then atom ordinal
4679 std::sort(atomsNeedingDebugNotes.begin(), atomsNeedingDebugNotes.end(), DebugNoteSorter());
4680
4681 // synthesize "debug notes" and add them to master stabs vector
4682 const char* dirPath = NULL;
4683 const char* filename = NULL;
4684 bool wroteStartSO = false;
4685 state.stabs.reserve(atomsNeedingDebugNotes.size()*4);
d425e388 4686 std::unordered_set<const char*, CStringHash, CStringEquals> seenFiles;
a645023d
A
4687 for (std::vector<const ld::Atom*>::iterator it=atomsNeedingDebugNotes.begin(); it != atomsNeedingDebugNotes.end(); it++) {
4688 const ld::Atom* atom = *it;
4689 const ld::File* atomFile = atom->file();
4690 const ld::relocatable::File* atomObjFile = dynamic_cast<const ld::relocatable::File*>(atomFile);
afe874b1 4691 //fprintf(stderr, "debug note for %s\n", atom->name());
b1f7435d
A
4692 const char* newPath = atom->translationUnitSource();
4693 if ( newPath != NULL ) {
4694 const char* newDirPath;
4695 const char* newFilename;
4696 const char* lastSlash = strrchr(newPath, '/');
4697 if ( lastSlash == NULL )
4698 continue;
4699 newFilename = lastSlash+1;
4700 char* temp = strdup(newPath);
4701 newDirPath = temp;
4702 // gdb like directory SO's to end in '/', but dwarf DW_AT_comp_dir usually does not have trailing '/'
4703 temp[lastSlash-newPath+1] = '\0';
a645023d 4704 // need SO's whenever the translation unit source file changes
b1f7435d 4705 if ( (filename == NULL) || (strcmp(newFilename,filename) != 0) ) {
a645023d
A
4706 if ( filename != NULL ) {
4707 // translation unit change, emit ending SO
4708 ld::relocatable::File::Stab endFileStab;
4709 endFileStab.atom = NULL;
4710 endFileStab.type = N_SO;
4711 endFileStab.other = 1;
4712 endFileStab.desc = 0;
4713 endFileStab.value = 0;
4714 endFileStab.string = "";
4715 state.stabs.push_back(endFileStab);
4716 }
4717 // new translation unit, emit start SO's
4718 ld::relocatable::File::Stab dirPathStab;
4719 dirPathStab.atom = NULL;
4720 dirPathStab.type = N_SO;
4721 dirPathStab.other = 0;
4722 dirPathStab.desc = 0;
4723 dirPathStab.value = 0;
4724 dirPathStab.string = newDirPath;
4725 state.stabs.push_back(dirPathStab);
4726 ld::relocatable::File::Stab fileStab;
4727 fileStab.atom = NULL;
4728 fileStab.type = N_SO;
4729 fileStab.other = 0;
4730 fileStab.desc = 0;
4731 fileStab.value = 0;
4732 fileStab.string = newFilename;
4733 state.stabs.push_back(fileStab);
4734 // Synthesize OSO for start of file
4735 ld::relocatable::File::Stab objStab;
4736 objStab.atom = NULL;
4737 objStab.type = N_OSO;
4738 // <rdar://problem/6337329> linker should put cpusubtype in n_sect field of nlist entry for N_OSO debug note entries
4739 objStab.other = atomFile->cpuSubType();
4740 objStab.desc = 1;
4741 if ( atomObjFile != NULL ) {
4742 objStab.string = assureFullPath(atomObjFile->debugInfoPath());
4743 objStab.value = atomObjFile->debugInfoModificationTime();
4744 }
4745 else {
4746 objStab.string = assureFullPath(atomFile->path());
4747 objStab.value = atomFile->modificationTime();
4748 }
4749 state.stabs.push_back(objStab);
4750 wroteStartSO = true;
4751 // add the source file path to seenFiles so it does not show up in SOLs
4752 seenFiles.insert(newFilename);
4753 char* fullFilePath;
afe874b1 4754 asprintf(&fullFilePath, "%s%s", newDirPath, newFilename);
a645023d
A
4755 // add both leaf path and full path
4756 seenFiles.insert(fullFilePath);
4757 }
4758 filename = newFilename;
4759 dirPath = newDirPath;
4760 if ( atom->section().type() == ld::Section::typeCode ) {
4761 // Synthesize BNSYM and start FUN stabs
4762 ld::relocatable::File::Stab beginSym;
4763 beginSym.atom = atom;
4764 beginSym.type = N_BNSYM;
4765 beginSym.other = 1;
4766 beginSym.desc = 0;
4767 beginSym.value = 0;
4768 beginSym.string = "";
4769 state.stabs.push_back(beginSym);
4770 ld::relocatable::File::Stab startFun;
4771 startFun.atom = atom;
4772 startFun.type = N_FUN;
4773 startFun.other = 1;
4774 startFun.desc = 0;
4775 startFun.value = 0;
4776 startFun.string = atom->name();
4777 state.stabs.push_back(startFun);
4778 // Synthesize any SOL stabs needed
4779 const char* curFile = NULL;
4780 for (ld::Atom::LineInfo::iterator lit = atom->beginLineInfo(); lit != atom->endLineInfo(); ++lit) {
4781 if ( lit->fileName != curFile ) {
4782 if ( seenFiles.count(lit->fileName) == 0 ) {
4783 seenFiles.insert(lit->fileName);
4784 ld::relocatable::File::Stab sol;
4785 sol.atom = 0;
4786 sol.type = N_SOL;
4787 sol.other = 0;
4788 sol.desc = 0;
4789 sol.value = 0;
4790 sol.string = lit->fileName;
4791 state.stabs.push_back(sol);
4792 }
4793 curFile = lit->fileName;
4794 }
4795 }
4796 // Synthesize end FUN and ENSYM stabs
4797 ld::relocatable::File::Stab endFun;
4798 endFun.atom = atom;
4799 endFun.type = N_FUN;
4800 endFun.other = 0;
4801 endFun.desc = 0;
4802 endFun.value = 0;
4803 endFun.string = "";
4804 state.stabs.push_back(endFun);
4805 ld::relocatable::File::Stab endSym;
4806 endSym.atom = atom;
4807 endSym.type = N_ENSYM;
4808 endSym.other = 1;
4809 endSym.desc = 0;
4810 endSym.value = 0;
4811 endSym.string = "";
4812 state.stabs.push_back(endSym);
4813 }
4814 else {
4815 ld::relocatable::File::Stab globalsStab;
4816 const char* name = atom->name();
4817 if ( atom->scope() == ld::Atom::scopeTranslationUnit ) {
4818 // Synthesize STSYM stab for statics
4819 globalsStab.atom = atom;
4820 globalsStab.type = N_STSYM;
4821 globalsStab.other = 1;
4822 globalsStab.desc = 0;
4823 globalsStab.value = 0;
4824 globalsStab.string = name;
4825 state.stabs.push_back(globalsStab);
4826 }
4827 else {
4828 // Synthesize GSYM stab for other globals
4829 globalsStab.atom = atom;
4830 globalsStab.type = N_GSYM;
4831 globalsStab.other = 1;
4832 globalsStab.desc = 0;
4833 globalsStab.value = 0;
4834 globalsStab.string = name;
4835 state.stabs.push_back(globalsStab);
4836 }
4837 }
4838 }
4839 }
4840
4841 if ( wroteStartSO ) {
4842 // emit ending SO
4843 ld::relocatable::File::Stab endFileStab;
4844 endFileStab.atom = NULL;
4845 endFileStab.type = N_SO;
4846 endFileStab.other = 1;
4847 endFileStab.desc = 0;
4848 endFileStab.value = 0;
4849 endFileStab.string = "";
4850 state.stabs.push_back(endFileStab);
4851 }
4852
4853 // copy any stabs from .o file
4854 std::set<const ld::File*> filesSeenWithStabs;
4855 for (std::set<const ld::Atom*>::iterator it=atomsWithStabs.begin(); it != atomsWithStabs.end(); it++) {
4856 const ld::Atom* atom = *it;
4857 objFile = dynamic_cast<const ld::relocatable::File*>(atom->file());
4858 if ( objFile != NULL ) {
4859 if ( filesSeenWithStabs.count(objFile) == 0 ) {
4860 filesSeenWithStabs.insert(objFile);
4861 const std::vector<ld::relocatable::File::Stab>* stabs = objFile->stabs();
4862 if ( stabs != NULL ) {
4863 for(std::vector<ld::relocatable::File::Stab>::const_iterator sit = stabs->begin(); sit != stabs->end(); ++sit) {
4864 ld::relocatable::File::Stab stab = *sit;
4865 // ignore stabs associated with atoms that were dead stripped or coalesced away
4866 if ( (sit->atom != NULL) && (atomsWithStabs.count(sit->atom) == 0) )
4867 continue;
4868 // <rdar://problem/8284718> Value of N_SO stabs should be address of first atom from translation unit
4869 if ( (stab.type == N_SO) && (stab.string != NULL) && (stab.string[0] != '\0') ) {
4870 stab.atom = atom;
4871 }
4872 state.stabs.push_back(stab);
4873 }
4874 }
4875 }
4876 }
4877 }
4878
4879}
4880
4881
4882} // namespace tool
4883} // namespace ld
4884