]> git.saurik.com Git - apple/ld64.git/blame - src/ld/OutputFile.cpp
ld64-409.12.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>
eaf282aa 54#include <utility>
0a8dc3df
A
55#include <iostream>
56#include <fstream>
a645023d
A
57
58#include <CommonCrypto/CommonDigest.h>
59#include <AvailabilityMacros.h>
60
61#include "MachOTrie.hpp"
62
63#include "Options.h"
64
65#include "OutputFile.h"
66#include "Architectures.hpp"
67#include "HeaderAndLoadCommands.hpp"
68#include "LinkEdit.hpp"
69#include "LinkEditClassic.hpp"
70
a645023d
A
71namespace ld {
72namespace tool {
73
9543cb2f
A
74uint32_t sAdrpNA = 0;
75uint32_t sAdrpNoped = 0;
76uint32_t sAdrpNotNoped = 0;
77
a645023d
A
78
79OutputFile::OutputFile(const Options& opts)
80 :
9543cb2f
A
81 usesWeakExternalSymbols(false), overridesWeakExternalSymbols(false),
82 _noReExportedDylibs(false), pieDisabled(false), hasDataInCode(false),
a645023d
A
83 headerAndLoadCommandsSection(NULL),
84 rebaseSection(NULL), bindingSection(NULL), weakBindingSection(NULL),
85 lazyBindingSection(NULL), exportSection(NULL),
86 splitSegInfoSection(NULL), functionStartsSection(NULL),
eaf282aa 87 dataInCodeSection(NULL), optimizationHintsSection(NULL),
a645023d
A
88 symbolTableSection(NULL), stringPoolSection(NULL),
89 localRelocationsSection(NULL), externalRelocationsSection(NULL),
90 sectionRelocationsSection(NULL),
e456bf10
A
91 indirectSymbolTableSection(NULL),
92 threadedPageStartsSection(NULL),
a645023d
A
93 _options(opts),
94 _hasDyldInfo(opts.makeCompressedDyldInfo()),
e456bf10 95 _hasThreadedPageStarts(opts.makeThreadedStartsSection()),
a645023d
A
96 _hasSymbolTable(true),
97 _hasSectionRelocations(opts.outputKind() == Options::kObjectFile),
98 _hasSplitSegInfo(opts.sharedRegionEligible()),
99 _hasFunctionStartsInfo(opts.addFunctionStarts()),
ebf6f434 100 _hasDataInCodeInfo(opts.addDataInCodeInfo()),
a645023d 101 _hasDynamicSymbolTable(true),
e456bf10
A
102 _hasLocalRelocations(!opts.makeCompressedDyldInfo() && !opts.makeThreadedStartsSection()),
103 _hasExternalRelocations(!opts.makeCompressedDyldInfo() && !opts.makeThreadedStartsSection()),
9543cb2f 104 _hasOptimizationHints(opts.outputKind() == Options::kObjectFile),
a645023d
A
105 _encryptedTEXTstartOffset(0),
106 _encryptedTEXTendOffset(0),
107 _localSymbolsStartIndex(0),
108 _localSymbolsCount(0),
109 _globalSymbolsStartIndex(0),
110 _globalSymbolsCount(0),
111 _importSymbolsStartIndex(0),
112 _importSymbolsCount(0),
113 _sectionsRelocationsAtom(NULL),
114 _localRelocsAtom(NULL),
115 _externalRelocsAtom(NULL),
116 _symbolTableAtom(NULL),
117 _indirectSymbolTableAtom(NULL),
118 _rebasingInfoAtom(NULL),
119 _bindingInfoAtom(NULL),
120 _lazyBindingInfoAtom(NULL),
121 _weakBindingInfoAtom(NULL),
122 _exportInfoAtom(NULL),
123 _splitSegInfoAtom(NULL),
ebf6f434
A
124 _functionStartsAtom(NULL),
125 _dataInCodeAtom(NULL),
9543cb2f 126 _optimizationHintsAtom(NULL)
a645023d
A
127{
128}
129
130void OutputFile::dumpAtomsBySection(ld::Internal& state, bool printAtoms)
131{
132 fprintf(stderr, "SORTED:\n");
133 for (std::vector<ld::Internal::FinalSection*>::iterator it = state.sections.begin(); it != state.sections.end(); ++it) {
134 fprintf(stderr, "final section %p %s/%s %s start addr=0x%08llX, size=0x%08llX, alignment=%02d, fileOffset=0x%08llX\n",
135 (*it), (*it)->segmentName(), (*it)->sectionName(), (*it)->isSectionHidden() ? "(hidden)" : "",
136 (*it)->address, (*it)->size, (*it)->alignment, (*it)->fileOffset);
137 if ( printAtoms ) {
138 std::vector<const ld::Atom*>& atoms = (*it)->atoms;
139 for (std::vector<const ld::Atom*>::iterator ait = atoms.begin(); ait != atoms.end(); ++ait) {
140 fprintf(stderr, " %p (0x%04llX) %s\n", *ait, (*ait)->size(), (*ait)->name());
141 }
142 }
143 }
144 fprintf(stderr, "DYLIBS:\n");
145 for (std::vector<ld::dylib::File*>::iterator it=state.dylibs.begin(); it != state.dylibs.end(); ++it )
146 fprintf(stderr, " %s\n", (*it)->installPath());
147}
148
149void OutputFile::write(ld::Internal& state)
150{
151 this->buildDylibOrdinalMapping(state);
152 this->addLoadCommands(state);
153 this->addLinkEdit(state);
9543cb2f 154 state.setSectionSizesAndAlignments();
a645023d 155 this->setLoadCommandsPadding(state);
9543cb2f 156 _fileSize = state.assignFileOffsets();
a645023d
A
157 this->assignAtomAddresses(state);
158 this->synthesizeDebugNotes(state);
159 this->buildSymbolTable(state);
160 this->generateLinkEditInfo(state);
eaf282aa
A
161 if ( _options.sharedRegionEncodingV2() )
162 this->makeSplitSegInfoV2(state);
163 else
164 this->makeSplitSegInfo(state);
a645023d
A
165 this->updateLINKEDITAddresses(state);
166 //this->dumpAtomsBySection(state, false);
167 this->writeOutputFile(state);
168 this->writeMapFile(state);
0a8dc3df 169 this->writeJSONEntry(state);
a645023d
A
170}
171
172bool OutputFile::findSegment(ld::Internal& state, uint64_t addr, uint64_t* start, uint64_t* end, uint32_t* index)
173{
174 uint32_t segIndex = 0;
175 ld::Internal::FinalSection* segFirstSection = NULL;
176 ld::Internal::FinalSection* lastSection = NULL;
177 for (std::vector<ld::Internal::FinalSection*>::iterator it = state.sections.begin(); it != state.sections.end(); ++it) {
178 ld::Internal::FinalSection* sect = *it;
179 if ( (segFirstSection == NULL ) || strcmp(segFirstSection->segmentName(), sect->segmentName()) != 0 ) {
180 if ( segFirstSection != NULL ) {
181 //fprintf(stderr, "findSegment(0x%llX) seg changed to %s\n", addr, sect->segmentName());
182 if ( (addr >= segFirstSection->address) && (addr < lastSection->address+lastSection->size) ) {
183 *start = segFirstSection->address;
184 *end = lastSection->address+lastSection->size;
185 *index = segIndex;
186 return true;
187 }
188 ++segIndex;
189 }
190 segFirstSection = sect;
191 }
192 lastSection = sect;
193 }
194 return false;
195}
196
197
198void OutputFile::assignAtomAddresses(ld::Internal& state)
199{
ebf6f434
A
200 const bool log = false;
201 if ( log ) fprintf(stderr, "assignAtomAddresses()\n");
a645023d
A
202 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
203 ld::Internal::FinalSection* sect = *sit;
ebf6f434 204 if ( log ) fprintf(stderr, " section=%s/%s\n", sect->segmentName(), sect->sectionName());
a645023d
A
205 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
206 const ld::Atom* atom = *ait;
207 switch ( sect-> type() ) {
208 case ld::Section::typeImportProxies:
209 // want finalAddress() of all proxy atoms to be zero
210 (const_cast<ld::Atom*>(atom))->setSectionStartAddress(0);
211 break;
212 case ld::Section::typeAbsoluteSymbols:
213 // want finalAddress() of all absolute atoms to be value of abs symbol
214 (const_cast<ld::Atom*>(atom))->setSectionStartAddress(0);
215 break;
216 case ld::Section::typeLinkEdit:
217 // linkedit layout is assigned later
218 break;
219 default:
220 (const_cast<ld::Atom*>(atom))->setSectionStartAddress(sect->address);
9543cb2f 221 if ( log ) fprintf(stderr, " atom=%p, addr=0x%08llX, name=%s\n", atom, atom->finalAddress(), atom->name());
a645023d
A
222 break;
223 }
224 }
225 }
226}
227
228void OutputFile::updateLINKEDITAddresses(ld::Internal& state)
229{
230 if ( _options.makeCompressedDyldInfo() ) {
231 // build dylb rebasing info
232 assert(_rebasingInfoAtom != NULL);
233 _rebasingInfoAtom->encode();
234
235 // build dyld binding info
236 assert(_bindingInfoAtom != NULL);
237 _bindingInfoAtom->encode();
238
239 // build dyld lazy binding info
240 assert(_lazyBindingInfoAtom != NULL);
241 _lazyBindingInfoAtom->encode();
242
243 // build dyld weak binding info
244 assert(_weakBindingInfoAtom != NULL);
245 _weakBindingInfoAtom->encode();
246
247 // build dyld export info
248 assert(_exportInfoAtom != NULL);
249 _exportInfoAtom->encode();
250 }
251
252 if ( _options.sharedRegionEligible() ) {
253 // build split seg info
254 assert(_splitSegInfoAtom != NULL);
255 _splitSegInfoAtom->encode();
256 }
257
258 if ( _options.addFunctionStarts() ) {
259 // build function starts info
260 assert(_functionStartsAtom != NULL);
261 _functionStartsAtom->encode();
262 }
263
ebf6f434
A
264 if ( _options.addDataInCodeInfo() ) {
265 // build data-in-code info
266 assert(_dataInCodeAtom != NULL);
267 _dataInCodeAtom->encode();
268 }
269
9543cb2f
A
270 if ( _hasOptimizationHints ) {
271 // build linker-optimization-hint info
272 assert(_optimizationHintsAtom != NULL);
273 _optimizationHintsAtom->encode();
274 }
275
eaf282aa 276 // build classic symbol table
a645023d
A
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
e456bf10 288 if ( !_options.makeCompressedDyldInfo() && !_options.makeThreadedStartsSection() ) {
a645023d
A
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;
0a8dc3df
A
362 case Options::kKextBundle:
363 if ( _options.useTextExecSegment() ) {
364 paddingSize = 32;
365 break;
366 }
367 // else fall into default case
a645023d
A
368 default:
369 // work backwards from end of segment and lay out sections so that extra room goes to padding atom
370 uint64_t addr = 0;
9543cb2f 371 uint64_t textSegPageSize = _options.segPageSize("__TEXT");
e456bf10 372 if ( _options.sharedRegionEligible() && _options.platforms().minOS(ld::iOS_8_0) && (textSegPageSize == 0x4000) )
599556ff 373 textSegPageSize = 0x1000;
a645023d
A
374 for (std::vector<ld::Internal::FinalSection*>::reverse_iterator it = state.sections.rbegin(); it != state.sections.rend(); ++it) {
375 ld::Internal::FinalSection* sect = *it;
376 if ( strcmp(sect->segmentName(), "__TEXT") != 0 )
377 continue;
378 if ( sect == headerAndLoadCommandsSection ) {
379 addr -= headerAndLoadCommandsSection->size;
9543cb2f 380 paddingSize = addr % textSegPageSize;
a645023d
A
381 break;
382 }
383 addr -= sect->size;
384 addr = addr & (0 - (1 << sect->alignment));
385 }
386
387 // if command line requires more padding than this
388 uint32_t minPad = _options.minimumHeaderPad();
389 if ( _options.maxMminimumHeaderPad() ) {
390 // -headerpad_max_install_names means there should be room for every path load command to grow to 1204 bytes
391 uint32_t altMin = _dylibsToLoad.size() * MAXPATHLEN;
392 if ( _options.outputKind() == Options::kDynamicLibrary )
393 altMin += MAXPATHLEN;
394 if ( altMin > minPad )
395 minPad = altMin;
396 }
397 if ( paddingSize < minPad ) {
398 int extraPages = (minPad - paddingSize + _options.segmentAlignment() - 1)/_options.segmentAlignment();
399 paddingSize += extraPages * _options.segmentAlignment();
400 }
401
402 if ( _options.makeEncryptable() ) {
403 // load commands must be on a separate non-encrypted page
404 int loadCommandsPage = (headerAndLoadCommandsSection->size + minPad)/_options.segmentAlignment();
405 int textPage = (headerAndLoadCommandsSection->size + paddingSize)/_options.segmentAlignment();
406 if ( loadCommandsPage == textPage ) {
407 paddingSize += _options.segmentAlignment();
408 textPage += 1;
409 }
410 // remember start for later use by load command
411 _encryptedTEXTstartOffset = textPage*_options.segmentAlignment();
412 }
413 break;
414 }
415 // add padding to size of section
416 headerAndLoadCommandsSection->size += paddingSize;
417}
418
419
420uint64_t OutputFile::pageAlign(uint64_t addr)
421{
422 const uint64_t alignment = _options.segmentAlignment();
423 return ((addr+alignment-1) & (-alignment));
424}
425
426uint64_t OutputFile::pageAlign(uint64_t addr, uint64_t pageSize)
427{
428 return ((addr+pageSize-1) & (-pageSize));
429}
430
a645023d
A
431static const char* makeName(const ld::Atom& atom)
432{
433 static char buffer[4096];
434 switch ( atom.symbolTableInclusion() ) {
435 case ld::Atom::symbolTableNotIn:
436 case ld::Atom::symbolTableNotInFinalLinkedImages:
437 sprintf(buffer, "%s@0x%08llX", atom.name(), atom.objectAddress());
438 break;
439 case ld::Atom::symbolTableIn:
440 case ld::Atom::symbolTableInAndNeverStrip:
441 case ld::Atom::symbolTableInAsAbsolute:
442 case ld::Atom::symbolTableInWithRandomAutoStripLabel:
443 strlcpy(buffer, atom.name(), 4096);
444 break;
445 }
446 return buffer;
447}
448
449static const char* referenceTargetAtomName(ld::Internal& state, const ld::Fixup* ref)
450{
451 switch ( ref->binding ) {
452 case ld::Fixup::bindingNone:
453 return "NO BINDING";
454 case ld::Fixup::bindingByNameUnbound:
455 return (char*)(ref->u.target);
456 case ld::Fixup::bindingByContentBound:
457 case ld::Fixup::bindingDirectlyBound:
458 return makeName(*((ld::Atom*)(ref->u.target)));
459 case ld::Fixup::bindingsIndirectlyBound:
460 return makeName(*state.indirectBindingTable[ref->u.bindingIndex]);
461 }
462 return "BAD BINDING";
463}
464
465bool OutputFile::targetIsThumb(ld::Internal& state, const ld::Fixup* fixup)
466{
467 switch ( fixup->binding ) {
468 case ld::Fixup::bindingByContentBound:
469 case ld::Fixup::bindingDirectlyBound:
470 return fixup->u.target->isThumb();
471 case ld::Fixup::bindingsIndirectlyBound:
472 return state.indirectBindingTable[fixup->u.bindingIndex]->isThumb();
473 default:
474 break;
475 }
476 throw "unexpected binding";
477}
478
479uint64_t OutputFile::addressOf(const ld::Internal& state, const ld::Fixup* fixup, const ld::Atom** target)
480{
e456bf10
A
481 // FIXME: Is this right for makeThreadedStartsSection?
482 if ( !_options.makeCompressedDyldInfo() && !_options.makeThreadedStartsSection() ) {
a645023d
A
483 // For external relocations the classic mach-o format
484 // has addend only stored in the content. That means
485 // that the address of the target is not used.
486 if ( fixup->contentAddendOnly )
487 return 0;
488 }
489 switch ( fixup->binding ) {
490 case ld::Fixup::bindingNone:
491 throw "unexpected bindingNone";
492 case ld::Fixup::bindingByNameUnbound:
493 throw "unexpected bindingByNameUnbound";
494 case ld::Fixup::bindingByContentBound:
495 case ld::Fixup::bindingDirectlyBound:
496 *target = fixup->u.target;
497 return (*target)->finalAddress();
498 case ld::Fixup::bindingsIndirectlyBound:
499 *target = state.indirectBindingTable[fixup->u.bindingIndex];
ebf6f434
A
500 #ifndef NDEBUG
501 if ( ! (*target)->finalAddressMode() ) {
502 throwf("reference to symbol (which has not been assigned an address) %s", (*target)->name());
503 }
504 #endif
a645023d
A
505 return (*target)->finalAddress();
506 }
507 throw "unexpected binding";
508}
509
0a8dc3df
A
510uint64_t OutputFile::addressAndTarget(const ld::Internal& state, const ld::Fixup* fixup, const ld::Atom** target)
511{
512 switch ( fixup->binding ) {
513 case ld::Fixup::bindingNone:
514 throw "unexpected bindingNone";
515 case ld::Fixup::bindingByNameUnbound:
516 throw "unexpected bindingByNameUnbound";
517 case ld::Fixup::bindingByContentBound:
518 case ld::Fixup::bindingDirectlyBound:
519 *target = fixup->u.target;
520 return (*target)->finalAddress();
521 case ld::Fixup::bindingsIndirectlyBound:
522 *target = state.indirectBindingTable[fixup->u.bindingIndex];
523 #ifndef NDEBUG
524 if ( ! (*target)->finalAddressMode() ) {
525 throwf("reference to symbol (which has not been assigned an address) %s", (*target)->name());
526 }
527 #endif
528 return (*target)->finalAddress();
529 }
530 throw "unexpected binding";
531}
532
533
a645023d
A
534uint64_t OutputFile::sectionOffsetOf(const ld::Internal& state, const ld::Fixup* fixup)
535{
536 const ld::Atom* target = NULL;
537 switch ( fixup->binding ) {
538 case ld::Fixup::bindingNone:
539 throw "unexpected bindingNone";
540 case ld::Fixup::bindingByNameUnbound:
541 throw "unexpected bindingByNameUnbound";
542 case ld::Fixup::bindingByContentBound:
543 case ld::Fixup::bindingDirectlyBound:
544 target = fixup->u.target;
545 break;
546 case ld::Fixup::bindingsIndirectlyBound:
547 target = state.indirectBindingTable[fixup->u.bindingIndex];
548 break;
549 }
550 assert(target != NULL);
551
552 uint64_t targetAddress = target->finalAddress();
553 for (std::vector<ld::Internal::FinalSection*>::const_iterator it = state.sections.begin(); it != state.sections.end(); ++it) {
554 const ld::Internal::FinalSection* sect = *it;
555 if ( (sect->address <= targetAddress) && (targetAddress < (sect->address+sect->size)) )
556 return targetAddress - sect->address;
557 }
558 throw "section not found for section offset";
559}
560
561
562
563uint64_t OutputFile::tlvTemplateOffsetOf(const ld::Internal& state, const ld::Fixup* fixup)
564{
565 const ld::Atom* target = NULL;
566 switch ( fixup->binding ) {
567 case ld::Fixup::bindingNone:
568 throw "unexpected bindingNone";
569 case ld::Fixup::bindingByNameUnbound:
570 throw "unexpected bindingByNameUnbound";
571 case ld::Fixup::bindingByContentBound:
572 case ld::Fixup::bindingDirectlyBound:
573 target = fixup->u.target;
574 break;
575 case ld::Fixup::bindingsIndirectlyBound:
576 target = state.indirectBindingTable[fixup->u.bindingIndex];
577 break;
578 }
579 assert(target != NULL);
580
581 for (std::vector<ld::Internal::FinalSection*>::const_iterator it = state.sections.begin(); it != state.sections.end(); ++it) {
582 const ld::Internal::FinalSection* sect = *it;
583 switch ( sect->type() ) {
584 case ld::Section::typeTLVInitialValues:
585 case ld::Section::typeTLVZeroFill:
586 return target->finalAddress() - sect->address;
587 default:
588 break;
589 }
590 }
591 throw "section not found for tlvTemplateOffsetOf";
592}
593
594void OutputFile::printSectionLayout(ld::Internal& state)
595{
596 // show layout of final image
597 fprintf(stderr, "final section layout:\n");
598 for (std::vector<ld::Internal::FinalSection*>::iterator it = state.sections.begin(); it != state.sections.end(); ++it) {
599 if ( (*it)->isSectionHidden() )
600 continue;
601 fprintf(stderr, " %s/%s addr=0x%08llX, size=0x%08llX, fileOffset=0x%08llX, type=%d\n",
602 (*it)->segmentName(), (*it)->sectionName(),
603 (*it)->address, (*it)->size, (*it)->fileOffset, (*it)->type());
604 }
605}
606
607
608void OutputFile::rangeCheck8(int64_t displacement, ld::Internal& state, const ld::Atom* atom, const ld::Fixup* fixup)
609{
610 if ( (displacement > 127) || (displacement < -128) ) {
611 // show layout of final image
612 printSectionLayout(state);
613
614 const ld::Atom* target;
615 throwf("8-bit reference out of range (%lld max is +/-127B): from %s (0x%08llX) to %s (0x%08llX)",
616 displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup),
617 addressOf(state, fixup, &target));
618 }
619}
620
621void OutputFile::rangeCheck16(int64_t displacement, ld::Internal& state, const ld::Atom* atom, const ld::Fixup* fixup)
622{
623 const int64_t thirtyTwoKLimit = 0x00007FFF;
624 if ( (displacement > thirtyTwoKLimit) || (displacement < (-thirtyTwoKLimit)) ) {
625 // show layout of final image
626 printSectionLayout(state);
627
628 const ld::Atom* target;
629 throwf("16-bit reference out of range (%lld max is +/-32KB): from %s (0x%08llX) to %s (0x%08llX)",
630 displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup),
631 addressOf(state, fixup, &target));
632 }
633}
634
635void OutputFile::rangeCheckBranch32(int64_t displacement, ld::Internal& state, const ld::Atom* atom, const ld::Fixup* fixup)
636{
637 const int64_t twoGigLimit = 0x7FFFFFFF;
638 if ( (displacement > twoGigLimit) || (displacement < (-twoGigLimit)) ) {
639 // show layout of final image
640 printSectionLayout(state);
641
642 const ld::Atom* target;
b1f7435d 643 throwf("32-bit branch out of range (%lld max is +/-2GB): from %s (0x%08llX) to %s (0x%08llX)",
a645023d
A
644 displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup),
645 addressOf(state, fixup, &target));
646 }
647}
648
afe874b1
A
649
650void OutputFile::rangeCheckAbsolute32(int64_t displacement, ld::Internal& state, const ld::Atom* atom, const ld::Fixup* fixup)
651{
652 const int64_t fourGigLimit = 0xFFFFFFFF;
653 if ( displacement > fourGigLimit ) {
654 // <rdar://problem/9610466> cannot enforce 32-bit range checks on 32-bit archs because assembler loses sign information
655 // .long _foo - 0xC0000000
656 // is encoded in mach-o the same as:
657 // .long _foo + 0x40000000
658 // so if _foo lays out to 0xC0000100, the first is ok, but the second is not.
659 if ( (_options.architecture() == CPU_TYPE_ARM) || (_options.architecture() == CPU_TYPE_I386) ) {
d425e388
A
660 // Unlikely userland code does funky stuff like this, so warn for them, but not warn for -preload or -static
661 if ( (_options.outputKind() != Options::kPreload) && (_options.outputKind() != Options::kStaticExecutable) ) {
afe874b1
A
662 warning("32-bit absolute address out of range (0x%08llX max is 4GB): from %s + 0x%08X (0x%08llX) to 0x%08llX",
663 displacement, atom->name(), fixup->offsetInAtom, atom->finalAddress(), displacement);
664 }
665 return;
666 }
667 // show layout of final image
668 printSectionLayout(state);
669
670 const ld::Atom* target;
671 if ( fixup->binding == ld::Fixup::bindingNone )
672 throwf("32-bit absolute address out of range (0x%08llX max is 4GB): from %s + 0x%08X (0x%08llX) to 0x%08llX",
673 displacement, atom->name(), fixup->offsetInAtom, atom->finalAddress(), displacement);
674 else
675 throwf("32-bit absolute address out of range (0x%08llX max is 4GB): from %s + 0x%08X (0x%08llX) to %s (0x%08llX)",
676 displacement, atom->name(), fixup->offsetInAtom, atom->finalAddress(), referenceTargetAtomName(state, fixup),
677 addressOf(state, fixup, &target));
678 }
679}
680
681
a645023d
A
682void OutputFile::rangeCheckRIP32(int64_t displacement, ld::Internal& state, const ld::Atom* atom, const ld::Fixup* fixup)
683{
684 const int64_t twoGigLimit = 0x7FFFFFFF;
afe874b1 685 if ( (displacement > twoGigLimit) || (displacement < (-twoGigLimit)) ) {
a645023d
A
686 // show layout of final image
687 printSectionLayout(state);
688
689 const ld::Atom* target;
bee7e226 690 throwf("32-bit RIP relative reference out of range (%lld max is +/-2GB): from %s (0x%08llX) to %s (0x%08llX)",
a645023d
A
691 displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup),
692 addressOf(state, fixup, &target));
693 }
694}
695
696void OutputFile::rangeCheckARM12(int64_t displacement, ld::Internal& state, const ld::Atom* atom, const ld::Fixup* fixup)
697{
698 if ( (displacement > 4092LL) || (displacement < (-4092LL)) ) {
699 // show layout of final image
700 printSectionLayout(state);
701
702 const ld::Atom* target;
703 throwf("ARM ldr 12-bit displacement out of range (%lld max is +/-4096B): from %s (0x%08llX) to %s (0x%08llX)",
704 displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup),
705 addressOf(state, fixup, &target));
706 }
707}
708
9543cb2f
A
709bool OutputFile::checkArmBranch24Displacement(int64_t displacement)
710{
711 return ( (displacement < 33554428LL) && (displacement > (-33554432LL)) );
712}
a645023d
A
713
714void OutputFile::rangeCheckARMBranch24(int64_t displacement, ld::Internal& state, const ld::Atom* atom, const ld::Fixup* fixup)
715{
9543cb2f
A
716 if ( checkArmBranch24Displacement(displacement) )
717 return;
a645023d 718
9543cb2f
A
719 // show layout of final image
720 printSectionLayout(state);
721
722 const ld::Atom* target;
723 throwf("b/bl/blx ARM branch out of range (%lld max is +/-32MB): from %s (0x%08llX) to %s (0x%08llX)",
724 displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup),
725 addressOf(state, fixup, &target));
a645023d
A
726}
727
9543cb2f 728bool OutputFile::checkThumbBranch22Displacement(int64_t displacement)
a645023d 729{
9543cb2f 730 // thumb2 supports +/- 16MB displacement
afe874b1 731 if ( _options.preferSubArchitecture() && _options.archSupportsThumb2() ) {
a645023d 732 if ( (displacement > 16777214LL) || (displacement < (-16777216LL)) ) {
9543cb2f 733 return false;
a645023d
A
734 }
735 }
736 else {
9543cb2f 737 // thumb1 supports +/- 4MB displacement
a645023d 738 if ( (displacement > 4194302LL) || (displacement < (-4194304LL)) ) {
9543cb2f 739 return false;
a645023d
A
740 }
741 }
9543cb2f
A
742 return true;
743}
744
745void OutputFile::rangeCheckThumbBranch22(int64_t displacement, ld::Internal& state, const ld::Atom* atom, const ld::Fixup* fixup)
746{
747 if ( checkThumbBranch22Displacement(displacement) )
748 return;
749
750 // show layout of final image
751 printSectionLayout(state);
752
753 const ld::Atom* target;
754 if ( _options.preferSubArchitecture() && _options.archSupportsThumb2() ) {
755 throwf("b/bl/blx thumb2 branch out of range (%lld max is +/-16MB): from %s (0x%08llX) to %s (0x%08llX)",
756 displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup),
757 addressOf(state, fixup, &target));
758 }
759 else {
760 throwf("b/bl/blx thumb1 branch out of range (%lld max is +/-4MB): from %s (0x%08llX) to %s (0x%08llX)",
761 displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup),
762 addressOf(state, fixup, &target));
763 }
a645023d
A
764}
765
a645023d 766
f80fe69f
A
767void OutputFile::rangeCheckARM64Branch26(int64_t displacement, ld::Internal& state, const ld::Atom* atom, const ld::Fixup* fixup)
768{
769 const int64_t bl_128MegLimit = 0x07FFFFFF;
770 if ( (displacement > bl_128MegLimit) || (displacement < (-bl_128MegLimit)) ) {
771 // show layout of final image
772 printSectionLayout(state);
773
774 const ld::Atom* target;
775 throwf("b(l) ARM64 branch out of range (%lld max is +/-128MB): from %s (0x%08llX) to %s (0x%08llX)",
776 displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup),
777 addressOf(state, fixup, &target));
778 }
779}
a645023d 780
f80fe69f
A
781void OutputFile::rangeCheckARM64Page21(int64_t displacement, ld::Internal& state, const ld::Atom* atom, const ld::Fixup* fixup)
782{
783 const int64_t adrp_4GigLimit = 0x100000000ULL;
784 if ( (displacement > adrp_4GigLimit) || (displacement < (-adrp_4GigLimit)) ) {
785 // show layout of final image
786 printSectionLayout(state);
787
788 const ld::Atom* target;
789 throwf("ARM64 ADRP out of range (%lld max is +/-4GB): from %s (0x%08llX) to %s (0x%08llX)",
790 displacement, atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fixup),
791 addressOf(state, fixup, &target));
792 }
793}
a645023d
A
794
795
796uint16_t OutputFile::get16LE(uint8_t* loc) { return LittleEndian::get16(*(uint16_t*)loc); }
797void OutputFile::set16LE(uint8_t* loc, uint16_t value) { LittleEndian::set16(*(uint16_t*)loc, value); }
798
799uint32_t OutputFile::get32LE(uint8_t* loc) { return LittleEndian::get32(*(uint32_t*)loc); }
800void OutputFile::set32LE(uint8_t* loc, uint32_t value) { LittleEndian::set32(*(uint32_t*)loc, value); }
801
802uint64_t OutputFile::get64LE(uint8_t* loc) { return LittleEndian::get64(*(uint64_t*)loc); }
803void OutputFile::set64LE(uint8_t* loc, uint64_t value) { LittleEndian::set64(*(uint64_t*)loc, value); }
804
805uint16_t OutputFile::get16BE(uint8_t* loc) { return BigEndian::get16(*(uint16_t*)loc); }
806void OutputFile::set16BE(uint8_t* loc, uint16_t value) { BigEndian::set16(*(uint16_t*)loc, value); }
807
808uint32_t OutputFile::get32BE(uint8_t* loc) { return BigEndian::get32(*(uint32_t*)loc); }
809void OutputFile::set32BE(uint8_t* loc, uint32_t value) { BigEndian::set32(*(uint32_t*)loc, value); }
810
811uint64_t OutputFile::get64BE(uint8_t* loc) { return BigEndian::get64(*(uint64_t*)loc); }
812void OutputFile::set64BE(uint8_t* loc, uint64_t value) { BigEndian::set64(*(uint64_t*)loc, value); }
813
599556ff
A
814#if SUPPORT_ARCH_arm64
815
9543cb2f
A
816static uint32_t makeNOP() {
817 return 0xD503201F;
818}
819
820enum SignExtension { signedNot, signed32, signed64 };
821struct LoadStoreInfo {
822 uint32_t reg;
823 uint32_t baseReg;
824 uint32_t offset; // after scaling
825 uint32_t size; // 1,2,4,8, or 16
826 bool isStore;
827 bool isFloat; // if destReg is FP/SIMD
828 SignExtension signEx; // if load is sign extended
829};
830
831static uint32_t makeLDR_literal(const LoadStoreInfo& info, uint64_t targetAddress, uint64_t instructionAddress)
832{
833 int64_t delta = targetAddress - instructionAddress;
834 assert(delta < 1024*1024);
835 assert(delta > -1024*1024);
836 assert((info.reg & 0xFFFFFFE0) == 0);
837 assert((targetAddress & 0x3) == 0);
838 assert((instructionAddress & 0x3) == 0);
839 assert(!info.isStore);
840 uint32_t imm19 = (delta << 3) & 0x00FFFFE0;
841 uint32_t instruction = 0;
842 switch ( info.size ) {
843 case 4:
844 if ( info.isFloat ) {
845 assert(info.signEx == signedNot);
846 instruction = 0x1C000000;
847 }
848 else {
849 if ( info.signEx == signed64 )
850 instruction = 0x98000000;
851 else
852 instruction = 0x18000000;
853 }
854 break;
855 case 8:
856 assert(info.signEx == signedNot);
857 instruction = info.isFloat ? 0x5C000000 : 0x58000000;
858 break;
859 case 16:
860 assert(info.signEx == signedNot);
861 instruction = 0x9C000000;
862 break;
863 default:
864 assert(0 && "invalid load size for literal");
865 }
866 return (instruction | imm19 | info.reg);
867}
868
869static uint32_t makeADR(uint32_t destReg, uint64_t targetAddress, uint64_t instructionAddress)
870{
871 assert((destReg & 0xFFFFFFE0) == 0);
872 assert((instructionAddress & 0x3) == 0);
873 uint32_t instruction = 0x10000000;
874 int64_t delta = targetAddress - instructionAddress;
875 assert(delta < 1024*1024);
876 assert(delta > -1024*1024);
877 uint32_t immhi = (delta & 0x001FFFFC) << 3;
878 uint32_t immlo = (delta & 0x00000003) << 29;
879 return (instruction | immhi | immlo | destReg);
880}
881
882static uint32_t makeLoadOrStore(const LoadStoreInfo& info)
883{
884 uint32_t instruction = 0x39000000;
885 if ( info.isFloat )
886 instruction |= 0x04000000;
887 instruction |= info.reg;
888 instruction |= (info.baseReg << 5);
889 uint32_t sizeBits = 0;
890 uint32_t opcBits = 0;
891 uint32_t imm12Bits = 0;
892 switch ( info.size ) {
893 case 1:
894 sizeBits = 0;
895 imm12Bits = info.offset;
896 if ( info.isStore ) {
897 opcBits = 0;
898 }
899 else {
900 switch ( info.signEx ) {
901 case signedNot:
902 opcBits = 1;
903 break;
904 case signed32:
905 opcBits = 3;
906 break;
907 case signed64:
908 opcBits = 2;
909 break;
910 }
911 }
912 break;
913 case 2:
914 sizeBits = 1;
915 assert((info.offset % 2) == 0);
916 imm12Bits = info.offset/2;
917 if ( info.isStore ) {
918 opcBits = 0;
919 }
920 else {
921 switch ( info.signEx ) {
922 case signedNot:
923 opcBits = 1;
924 break;
925 case signed32:
926 opcBits = 3;
927 break;
928 case signed64:
929 opcBits = 2;
930 break;
931 }
932 }
933 break;
934 case 4:
935 sizeBits = 2;
936 assert((info.offset % 4) == 0);
937 imm12Bits = info.offset/4;
938 if ( info.isStore ) {
939 opcBits = 0;
940 }
941 else {
942 switch ( info.signEx ) {
943 case signedNot:
944 opcBits = 1;
945 break;
946 case signed32:
947 assert(0 && "cannot use signed32 with 32-bit load/store");
948 break;
949 case signed64:
950 opcBits = 2;
951 break;
952 }
953 }
954 break;
955 case 8:
956 sizeBits = 3;
957 assert((info.offset % 8) == 0);
958 imm12Bits = info.offset/8;
959 if ( info.isStore ) {
960 opcBits = 0;
961 }
962 else {
963 opcBits = 1;
964 assert(info.signEx == signedNot);
965 }
966 break;
967 case 16:
968 sizeBits = 0;
969 assert((info.offset % 16) == 0);
970 imm12Bits = info.offset/16;
971 assert(info.isFloat);
972 if ( info.isStore ) {
973 opcBits = 2;
974 }
975 else {
976 opcBits = 3;
977 }
978 break;
979 default:
980 assert(0 && "bad load/store size");
981 break;
982 }
983 assert(imm12Bits < 4096);
984 return (instruction | (sizeBits << 30) | (opcBits << 22) | (imm12Bits << 10));
985}
986
987static bool parseLoadOrStore(uint32_t instruction, LoadStoreInfo& info)
988{
989 if ( (instruction & 0x3B000000) != 0x39000000 )
990 return false;
991 info.isFloat = ( (instruction & 0x04000000) != 0 );
992 info.reg = (instruction & 0x1F);
993 info.baseReg = ((instruction>>5) & 0x1F);
994 switch (instruction & 0xC0C00000) {
995 case 0x00000000:
996 info.size = 1;
997 info.isStore = true;
998 info.signEx = signedNot;
999 break;
1000 case 0x00400000:
1001 info.size = 1;
1002 info.isStore = false;
1003 info.signEx = signedNot;
1004 break;
1005 case 0x00800000:
1006 if ( info.isFloat ) {
1007 info.size = 16;
1008 info.isStore = true;
1009 info.signEx = signedNot;
1010 }
1011 else {
1012 info.size = 1;
1013 info.isStore = false;
1014 info.signEx = signed64;
1015 }
1016 break;
1017 case 0x00C00000:
1018 if ( info.isFloat ) {
1019 info.size = 16;
1020 info.isStore = false;
1021 info.signEx = signedNot;
1022 }
1023 else {
1024 info.size = 1;
1025 info.isStore = false;
1026 info.signEx = signed32;
1027 }
1028 break;
1029 case 0x40000000:
1030 info.size = 2;
1031 info.isStore = true;
1032 info.signEx = signedNot;
1033 break;
1034 case 0x40400000:
1035 info.size = 2;
1036 info.isStore = false;
1037 info.signEx = signedNot;
1038 break;
1039 case 0x40800000:
1040 info.size = 2;
1041 info.isStore = false;
1042 info.signEx = signed64;
1043 break;
1044 case 0x40C00000:
1045 info.size = 2;
1046 info.isStore = false;
1047 info.signEx = signed32;
1048 break;
1049 case 0x80000000:
1050 info.size = 4;
1051 info.isStore = true;
1052 info.signEx = signedNot;
1053 break;
1054 case 0x80400000:
1055 info.size = 4;
1056 info.isStore = false;
1057 info.signEx = signedNot;
1058 break;
1059 case 0x80800000:
1060 info.size = 4;
1061 info.isStore = false;
1062 info.signEx = signed64;
1063 break;
1064 case 0xC0000000:
1065 info.size = 8;
1066 info.isStore = true;
1067 info.signEx = signedNot;
1068 break;
1069 case 0xC0400000:
1070 info.size = 8;
1071 info.isStore = false;
1072 info.signEx = signedNot;
1073 break;
1074 default:
1075 return false;
1076 }
1077 info.offset = ((instruction >> 10) & 0x0FFF) * info.size;
1078 return true;
1079}
1080
1081struct AdrpInfo {
1082 uint32_t destReg;
1083};
1084
1085static bool parseADRP(uint32_t instruction, AdrpInfo& info)
1086{
1087 if ( (instruction & 0x9F000000) != 0x90000000 )
1088 return false;
1089 info.destReg = (instruction & 0x1F);
1090 return true;
1091}
1092
1093struct AddInfo {
1094 uint32_t destReg;
1095 uint32_t srcReg;
1096 uint32_t addend;
1097};
1098
1099static bool parseADD(uint32_t instruction, AddInfo& info)
1100{
1101 if ( (instruction & 0xFFC00000) != 0x91000000 )
1102 return false;
1103 info.destReg = (instruction & 0x1F);
1104 info.srcReg = ((instruction>>5) & 0x1F);
1105 info.addend = ((instruction>>10) & 0xFFF);
1106 return true;
1107}
1108
1109
1110
1111#if 0
1112static uint32_t makeLDR_scaledOffset(const LoadStoreInfo& info)
1113{
1114 assert((info.reg & 0xFFFFFFE0) == 0);
1115 assert((info.baseReg & 0xFFFFFFE0) == 0);
1116 assert(!info.isFloat || (info.signEx != signedNot));
1117 uint32_t sizeBits = 0;
1118 uint32_t opcBits = 1;
1119 uint32_t vBit = info.isFloat;
1120 switch ( info.signEx ) {
1121 case signedNot:
1122 opcBits = 1;
1123 break;
1124 case signed32:
1125 opcBits = 3;
1126 break;
1127 case signed64:
1128 opcBits = 2;
1129 break;
1130 default:
1131 assert(0 && "bad SignExtension runtime value");
1132 }
1133 switch ( info.size ) {
1134 case 1:
1135 sizeBits = 0;
1136 break;
1137 case 2:
1138 sizeBits = 1;
1139 break;
1140 case 4:
1141 sizeBits = 2;
1142 break;
1143 case 8:
1144 sizeBits = 3;
1145 break;
1146 case 16:
1147 sizeBits = 0;
1148 vBit = 1;
1149 opcBits = 3;
1150 break;
1151 default:
1152 assert(0 && "invalid load size for literal");
1153 }
1154 assert((info.offset % info.size) == 0);
1155 uint32_t scaledOffset = info.offset/info.size;
1156 assert(scaledOffset < 4096);
1157 return (0x39000000 | (sizeBits<<30) | (vBit<<26) | (opcBits<<22) | (scaledOffset<<10) | (info.baseReg<<5) | info.reg);
1158}
1159
1160static uint32_t makeLDR_literal(uint32_t destReg, uint32_t loadSize, bool isFloat, uint64_t targetAddress, uint64_t instructionAddress)
1161{
1162 int64_t delta = targetAddress - instructionAddress;
1163 assert(delta < 1024*1024);
1164 assert(delta > -1024*1024);
1165 assert((destReg & 0xFFFFFFE0) == 0);
1166 assert((targetAddress & 0x3) == 0);
1167 assert((instructionAddress & 0x3) == 0);
1168 uint32_t imm19 = (delta << 3) & 0x00FFFFE0;
1169 uint32_t instruction = 0;
1170 switch ( loadSize ) {
1171 case 4:
1172 instruction = isFloat ? 0x1C000000 : 0x18000000;
1173 break;
1174 case 8:
1175 instruction = isFloat ? 0x5C000000 : 0x58000000;
1176 break;
1177 case 16:
1178 instruction = 0x9C000000;
1179 break;
1180 default:
1181 assert(0 && "invalid load size for literal");
1182 }
1183 return (instruction | imm19 | destReg);
1184}
1185
1186
1187static bool ldrInfo(uint32_t instruction, uint8_t* size, uint8_t* destReg, bool* v, uint32_t* scaledOffset)
1188{
1189 *v = ( (instruction & 0x04000000) != 0 );
1190 *destReg = (instruction & 0x1F);
1191 uint32_t imm12 = ((instruction >> 10) & 0x00000FFF);
1192 switch ( (instruction & 0xC0000000) >> 30 ) {
1193 case 0:
1194 // vector and byte LDR have same "size" bits, need to check other bits to differenciate
1195 if ( (instruction & 0x00800000) == 0 ) {
1196 *size = 1;
1197 *scaledOffset = imm12;
1198 }
1199 else {
1200 *size = 16;
1201 *scaledOffset = imm12 * 16;
1202 }
1203 break;
1204 case 1:
1205 *size = 2;
1206 *scaledOffset = imm12 * 2;
1207 break;
1208 case 2:
1209 *size = 4;
1210 *scaledOffset = imm12 * 4;
1211 break;
1212 case 3:
1213 *size = 8;
1214 *scaledOffset = imm12 * 8;
1215 break;
1216 }
1217 return ((instruction & 0x3B400000) == 0x39400000);
1218}
1219#endif
1220
1221static bool withinOneMeg(uint64_t addr1, uint64_t addr2) {
1222 int64_t delta = (addr2 - addr1);
1223 return ( (delta < 1024*1024) && (delta > -1024*1024) );
1224}
599556ff 1225#endif // SUPPORT_ARCH_arm64
9543cb2f
A
1226
1227void OutputFile::setInfo(ld::Internal& state, const ld::Atom* atom, uint8_t* buffer, const std::map<uint32_t, const Fixup*>& usedByHints,
1228 uint32_t offsetInAtom, uint32_t delta, InstructionInfo* info)
1229{
1230 info->offsetInAtom = offsetInAtom + delta;
1231 std::map<uint32_t, const Fixup*>::const_iterator pos = usedByHints.find(info->offsetInAtom);
1232 if ( (pos != usedByHints.end()) && (pos->second != NULL) ) {
1233 info->fixup = pos->second;
1234 info->targetAddress = addressOf(state, info->fixup, &info->target);
1235 if ( info->fixup->clusterSize != ld::Fixup::k1of1 ) {
1236 assert(info->fixup->firstInCluster());
1237 const ld::Fixup* nextFixup = info->fixup + 1;
1238 if ( nextFixup->kind == ld::Fixup::kindAddAddend ) {
1239 info->targetAddress += nextFixup->u.addend;
1240 }
1241 else {
1242 assert(0 && "expected addend");
1243 }
1244 }
1245 }
1246 else {
1247 info->fixup = NULL;
1248 info->targetAddress = 0;
1249 info->target = NULL;
1250 }
1251 info->instructionContent = &buffer[info->offsetInAtom];
1252 info->instructionAddress = atom->finalAddress() + info->offsetInAtom;
1253 info->instruction = get32LE(info->instructionContent);
1254}
1255
599556ff 1256#if SUPPORT_ARCH_arm64
9543cb2f
A
1257static bool isPageKind(const ld::Fixup* fixup, bool mustBeGOT=false)
1258{
1259 if ( fixup == NULL )
1260 return false;
1261 const ld::Fixup* f;
1262 switch ( fixup->kind ) {
1263 case ld::Fixup::kindStoreTargetAddressARM64Page21:
1264 return !mustBeGOT;
1265 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
1266 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21:
eaf282aa
A
1267 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21:
1268 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPage21:
9543cb2f
A
1269 return true;
1270 case ld::Fixup::kindSetTargetAddress:
1271 f = fixup;
1272 do {
1273 ++f;
1274 } while ( ! f->lastInCluster() );
1275 switch (f->kind ) {
1276 case ld::Fixup::kindStoreARM64Page21:
1277 return !mustBeGOT;
1278 case ld::Fixup::kindStoreARM64GOTLoadPage21:
1279 case ld::Fixup::kindStoreARM64GOTLeaPage21:
eaf282aa
A
1280 case ld::Fixup::kindStoreARM64TLVPLoadPage21:
1281 case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPage21:
9543cb2f
A
1282 return true;
1283 default:
1284 break;
1285 }
1286 break;
1287 default:
1288 break;
1289 }
1290 return false;
1291}
1292
1293static bool isPageOffsetKind(const ld::Fixup* fixup, bool mustBeGOT=false)
1294{
1295 if ( fixup == NULL )
1296 return false;
1297 const ld::Fixup* f;
1298 switch ( fixup->kind ) {
1299 case ld::Fixup::kindStoreTargetAddressARM64PageOff12:
1300 return !mustBeGOT;
1301 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12:
1302 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPageOff12:
eaf282aa
A
1303 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12:
1304 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12:
9543cb2f
A
1305 return true;
1306 case ld::Fixup::kindSetTargetAddress:
1307 f = fixup;
1308 do {
1309 ++f;
1310 } while ( ! f->lastInCluster() );
1311 switch (f->kind ) {
1312 case ld::Fixup::kindStoreARM64PageOff12:
1313 return !mustBeGOT;
1314 case ld::Fixup::kindStoreARM64GOTLoadPageOff12:
1315 case ld::Fixup::kindStoreARM64GOTLeaPageOff12:
eaf282aa
A
1316 case ld::Fixup::kindStoreARM64TLVPLoadPageOff12:
1317 case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPageOff12:
9543cb2f
A
1318 return true;
1319 default:
1320 break;
1321 }
1322 break;
1323 default:
1324 break;
1325 }
1326 return false;
1327}
599556ff 1328#endif // SUPPORT_ARCH_arm64
9543cb2f
A
1329
1330
1331#define LOH_ASSERT(cond) \
1332 if ( !(cond) ) { \
ec29ba20 1333 warning("ignoring linker optimization hint at %s+0x%X because " #cond, atom->name(), fit->offsetInAtom); \
9543cb2f
A
1334 break; \
1335 }
1336
a645023d
A
1337void OutputFile::applyFixUps(ld::Internal& state, uint64_t mhAddress, const ld::Atom* atom, uint8_t* buffer)
1338{
1339 //fprintf(stderr, "applyFixUps() on %s\n", atom->name());
1340 int64_t accumulator = 0;
1341 const ld::Atom* toTarget = NULL;
1342 const ld::Atom* fromTarget;
1343 int64_t delta;
1344 uint32_t instruction;
1345 uint32_t newInstruction;
a645023d
A
1346 bool is_bl;
1347 bool is_blx;
1348 bool is_b;
1349 bool thumbTarget = false;
9543cb2f 1350 std::map<uint32_t, const Fixup*> usedByHints;
e456bf10
A
1351#if SUPPORT_ARCH_arm64e
1352 Fixup::AuthData authData;
1353#endif
a645023d
A
1354 for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
1355 uint8_t* fixUpLocation = &buffer[fit->offsetInAtom];
9543cb2f 1356 ld::Fixup::LOH_arm64 lohExtra;
a645023d
A
1357 switch ( (ld::Fixup::Kind)(fit->kind) ) {
1358 case ld::Fixup::kindNone:
1359 case ld::Fixup::kindNoneFollowOn:
1360 case ld::Fixup::kindNoneGroupSubordinate:
1361 case ld::Fixup::kindNoneGroupSubordinateFDE:
1362 case ld::Fixup::kindNoneGroupSubordinateLSDA:
1363 case ld::Fixup::kindNoneGroupSubordinatePersonality:
1364 break;
1365 case ld::Fixup::kindSetTargetAddress:
1366 accumulator = addressOf(state, fit, &toTarget);
1367 thumbTarget = targetIsThumb(state, fit);
1368 if ( thumbTarget )
1369 accumulator |= 1;
1370 if ( fit->contentAddendOnly || fit->contentDetlaToAddendOnly )
1371 accumulator = 0;
1372 break;
1373 case ld::Fixup::kindSubtractTargetAddress:
1374 delta = addressOf(state, fit, &fromTarget);
1375 if ( ! fit->contentAddendOnly )
1376 accumulator -= delta;
1377 break;
1378 case ld::Fixup::kindAddAddend:
f80fe69f
A
1379 if ( ! fit->contentIgnoresAddend ) {
1380 // <rdar://problem/8342028> ARM main executables main contain .long constants pointing
1381 // into themselves such as jump tables. These .long should not have thumb bit set
1382 // even though the target is a thumb instruction. We can tell it is an interior pointer
1383 // because we are processing an addend.
1384 if ( thumbTarget && (toTarget == atom) && ((int32_t)fit->u.addend > 0) ) {
1385 accumulator &= (-2);
1386 //warning("removing thumb bit from intra-atom pointer in %s %s+0x%0X",
1387 // atom->section().sectionName(), atom->name(), fit->offsetInAtom);
1388 }
1389 accumulator += fit->u.addend;
a645023d 1390 }
a645023d
A
1391 break;
1392 case ld::Fixup::kindSubtractAddend:
1393 accumulator -= fit->u.addend;
1394 break;
1395 case ld::Fixup::kindSetTargetImageOffset:
1396 accumulator = addressOf(state, fit, &toTarget) - mhAddress;
599556ff
A
1397 thumbTarget = targetIsThumb(state, fit);
1398 if ( thumbTarget )
1399 accumulator |= 1;
a645023d
A
1400 break;
1401 case ld::Fixup::kindSetTargetSectionOffset:
1402 accumulator = sectionOffsetOf(state, fit);
1403 break;
1404 case ld::Fixup::kindSetTargetTLVTemplateOffset:
1405 accumulator = tlvTemplateOffsetOf(state, fit);
1406 break;
1407 case ld::Fixup::kindStore8:
1408 *fixUpLocation += accumulator;
1409 break;
1410 case ld::Fixup::kindStoreLittleEndian16:
1411 set16LE(fixUpLocation, accumulator);
1412 break;
1413 case ld::Fixup::kindStoreLittleEndianLow24of32:
1414 set32LE(fixUpLocation, (get32LE(fixUpLocation) & 0xFF000000) | (accumulator & 0x00FFFFFF) );
1415 break;
1416 case ld::Fixup::kindStoreLittleEndian32:
afe874b1 1417 rangeCheckAbsolute32(accumulator, state, atom, fit);
a645023d
A
1418 set32LE(fixUpLocation, accumulator);
1419 break;
1420 case ld::Fixup::kindStoreLittleEndian64:
1421 set64LE(fixUpLocation, accumulator);
1422 break;
1423 case ld::Fixup::kindStoreBigEndian16:
1424 set16BE(fixUpLocation, accumulator);
1425 break;
1426 case ld::Fixup::kindStoreBigEndianLow24of32:
1427 set32BE(fixUpLocation, (get32BE(fixUpLocation) & 0xFF000000) | (accumulator & 0x00FFFFFF) );
1428 break;
1429 case ld::Fixup::kindStoreBigEndian32:
afe874b1 1430 rangeCheckAbsolute32(accumulator, state, atom, fit);
a645023d
A
1431 set32BE(fixUpLocation, accumulator);
1432 break;
1433 case ld::Fixup::kindStoreBigEndian64:
1434 set64BE(fixUpLocation, accumulator);
1435 break;
1436 case ld::Fixup::kindStoreX86PCRel8:
1437 case ld::Fixup::kindStoreX86BranchPCRel8:
1438 if ( fit->contentAddendOnly )
1439 delta = accumulator;
1440 else
1441 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 1);
1442 rangeCheck8(delta, state, atom, fit);
1443 *fixUpLocation = delta;
1444 break;
1445 case ld::Fixup::kindStoreX86PCRel16:
1446 if ( fit->contentAddendOnly )
1447 delta = accumulator;
1448 else
1449 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 2);
1450 rangeCheck16(delta, state, atom, fit);
1451 set16LE(fixUpLocation, delta);
1452 break;
1453 case ld::Fixup::kindStoreX86BranchPCRel32:
1454 if ( fit->contentAddendOnly )
1455 delta = accumulator;
1456 else
1457 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 4);
1458 rangeCheckBranch32(delta, state, atom, fit);
1459 set32LE(fixUpLocation, delta);
1460 break;
1461 case ld::Fixup::kindStoreX86PCRel32GOTLoad:
1462 case ld::Fixup::kindStoreX86PCRel32GOT:
1463 case ld::Fixup::kindStoreX86PCRel32:
1464 case ld::Fixup::kindStoreX86PCRel32TLVLoad:
1465 if ( fit->contentAddendOnly )
1466 delta = accumulator;
1467 else
1468 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 4);
1469 rangeCheckRIP32(delta, state, atom, fit);
1470 set32LE(fixUpLocation, delta);
1471 break;
1472 case ld::Fixup::kindStoreX86PCRel32_1:
1473 if ( fit->contentAddendOnly )
1474 delta = accumulator - 1;
1475 else
1476 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 5);
1477 rangeCheckRIP32(delta, state, atom, fit);
1478 set32LE(fixUpLocation, delta);
1479 break;
1480 case ld::Fixup::kindStoreX86PCRel32_2:
1481 if ( fit->contentAddendOnly )
1482 delta = accumulator - 2;
1483 else
1484 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 6);
1485 rangeCheckRIP32(delta, state, atom, fit);
1486 set32LE(fixUpLocation, delta);
1487 break;
1488 case ld::Fixup::kindStoreX86PCRel32_4:
1489 if ( fit->contentAddendOnly )
1490 delta = accumulator - 4;
1491 else
1492 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 8);
1493 rangeCheckRIP32(delta, state, atom, fit);
1494 set32LE(fixUpLocation, delta);
1495 break;
1496 case ld::Fixup::kindStoreX86Abs32TLVLoad:
1497 set32LE(fixUpLocation, accumulator);
1498 break;
1499 case ld::Fixup::kindStoreX86Abs32TLVLoadNowLEA:
1500 assert(_options.outputKind() != Options::kObjectFile);
1501 // TLV entry was optimized away, change movl instruction to a leal
1502 if ( fixUpLocation[-1] != 0xA1 )
1503 throw "TLV load reloc does not point to a movl instruction";
1504 fixUpLocation[-1] = 0xB8;
1505 set32LE(fixUpLocation, accumulator);
1506 break;
1507 case ld::Fixup::kindStoreX86PCRel32GOTLoadNowLEA:
1508 assert(_options.outputKind() != Options::kObjectFile);
1509 // GOT entry was optimized away, change movq instruction to a leaq
1510 if ( fixUpLocation[-2] != 0x8B )
1511 throw "GOT load reloc does not point to a movq instruction";
1512 fixUpLocation[-2] = 0x8D;
1513 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 4);
1514 rangeCheckRIP32(delta, state, atom, fit);
1515 set32LE(fixUpLocation, delta);
1516 break;
1517 case ld::Fixup::kindStoreX86PCRel32TLVLoadNowLEA:
1518 assert(_options.outputKind() != Options::kObjectFile);
1519 // TLV entry was optimized away, change movq instruction to a leaq
1520 if ( fixUpLocation[-2] != 0x8B )
1521 throw "TLV load reloc does not point to a movq instruction";
1522 fixUpLocation[-2] = 0x8D;
1523 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 4);
1524 rangeCheckRIP32(delta, state, atom, fit);
1525 set32LE(fixUpLocation, delta);
1526 break;
1527 case ld::Fixup::kindStoreTargetAddressARMLoad12:
1528 accumulator = addressOf(state, fit, &toTarget);
1529 // fall into kindStoreARMLoad12 case
1530 case ld::Fixup::kindStoreARMLoad12:
1531 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 8);
1532 rangeCheckARM12(delta, state, atom, fit);
1533 instruction = get32LE(fixUpLocation);
1534 if ( delta >= 0 ) {
1535 newInstruction = instruction & 0xFFFFF000;
1536 newInstruction |= ((uint32_t)delta & 0xFFF);
1537 }
1538 else {
1539 newInstruction = instruction & 0xFF7FF000;
1540 newInstruction |= ((uint32_t)(-delta) & 0xFFF);
1541 }
1542 set32LE(fixUpLocation, newInstruction);
1543 break;
a645023d
A
1544 case ld::Fixup::kindDtraceExtra:
1545 break;
1546 case ld::Fixup::kindStoreX86DtraceCallSiteNop:
1547 if ( _options.outputKind() != Options::kObjectFile ) {
1548 // change call site to a NOP
1549 fixUpLocation[-1] = 0x90; // 1-byte nop
1550 fixUpLocation[0] = 0x0F; // 4-byte nop
1551 fixUpLocation[1] = 0x1F;
1552 fixUpLocation[2] = 0x40;
1553 fixUpLocation[3] = 0x00;
1554 }
1555 break;
1556 case ld::Fixup::kindStoreX86DtraceIsEnableSiteClear:
1557 if ( _options.outputKind() != Options::kObjectFile ) {
1558 // change call site to a clear eax
1559 fixUpLocation[-1] = 0x33; // xorl eax,eax
1560 fixUpLocation[0] = 0xC0;
1561 fixUpLocation[1] = 0x90; // 1-byte nop
1562 fixUpLocation[2] = 0x90; // 1-byte nop
1563 fixUpLocation[3] = 0x90; // 1-byte nop
1564 }
1565 break;
a645023d
A
1566 case ld::Fixup::kindStoreARMDtraceCallSiteNop:
1567 if ( _options.outputKind() != Options::kObjectFile ) {
1568 // change call site to a NOP
1569 set32LE(fixUpLocation, 0xE1A00000);
1570 }
1571 break;
1572 case ld::Fixup::kindStoreARMDtraceIsEnableSiteClear:
1573 if ( _options.outputKind() != Options::kObjectFile ) {
1574 // change call site to 'eor r0, r0, r0'
1575 set32LE(fixUpLocation, 0xE0200000);
1576 }
1577 break;
1578 case ld::Fixup::kindStoreThumbDtraceCallSiteNop:
1579 if ( _options.outputKind() != Options::kObjectFile ) {
1580 // change 32-bit blx call site to two thumb NOPs
1581 set32LE(fixUpLocation, 0x46C046C0);
1582 }
1583 break;
1584 case ld::Fixup::kindStoreThumbDtraceIsEnableSiteClear:
1585 if ( _options.outputKind() != Options::kObjectFile ) {
1586 // change 32-bit blx call site to 'nop', 'eor r0, r0'
1587 set32LE(fixUpLocation, 0x46C04040);
1588 }
1589 break;
f80fe69f
A
1590 case ld::Fixup::kindStoreARM64DtraceCallSiteNop:
1591 if ( _options.outputKind() != Options::kObjectFile ) {
1592 // change call site to a NOP
1593 set32LE(fixUpLocation, 0xD503201F);
1594 }
1595 break;
1596 case ld::Fixup::kindStoreARM64DtraceIsEnableSiteClear:
1597 if ( _options.outputKind() != Options::kObjectFile ) {
1598 // change call site to 'MOVZ X0,0'
1599 set32LE(fixUpLocation, 0xD2800000);
1600 }
1601 break;
a645023d 1602 case ld::Fixup::kindLazyTarget:
9543cb2f 1603 case ld::Fixup::kindIslandTarget:
a645023d
A
1604 break;
1605 case ld::Fixup::kindSetLazyOffset:
1606 assert(fit->binding == ld::Fixup::bindingDirectlyBound);
1607 accumulator = this->lazyBindingInfoOffsetForLazyPointerAddress(fit->u.target->finalAddress());
1608 break;
ebf6f434
A
1609 case ld::Fixup::kindDataInCodeStartData:
1610 case ld::Fixup::kindDataInCodeStartJT8:
1611 case ld::Fixup::kindDataInCodeStartJT16:
1612 case ld::Fixup::kindDataInCodeStartJT32:
1613 case ld::Fixup::kindDataInCodeStartJTA32:
1614 case ld::Fixup::kindDataInCodeEnd:
1615 break;
9543cb2f
A
1616 case ld::Fixup::kindLinkerOptimizationHint:
1617 // expand table of address/offsets used by hints
1618 lohExtra.addend = fit->u.addend;
1619 usedByHints[fit->offsetInAtom + (lohExtra.info.delta1 << 2)] = NULL;
1620 if ( lohExtra.info.count > 0 )
1621 usedByHints[fit->offsetInAtom + (lohExtra.info.delta2 << 2)] = NULL;
1622 if ( lohExtra.info.count > 1 )
1623 usedByHints[fit->offsetInAtom + (lohExtra.info.delta3 << 2)] = NULL;
1624 if ( lohExtra.info.count > 2 )
1625 usedByHints[fit->offsetInAtom + (lohExtra.info.delta4 << 2)] = NULL;
1626 break;
a645023d
A
1627 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
1628 accumulator = addressOf(state, fit, &toTarget);
1629 thumbTarget = targetIsThumb(state, fit);
1630 if ( thumbTarget )
1631 accumulator |= 1;
1632 if ( fit->contentAddendOnly )
1633 accumulator = 0;
afe874b1 1634 rangeCheckAbsolute32(accumulator, state, atom, fit);
a645023d
A
1635 set32LE(fixUpLocation, accumulator);
1636 break;
1637 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
1638 accumulator = addressOf(state, fit, &toTarget);
1639 if ( fit->contentAddendOnly )
1640 accumulator = 0;
1641 set64LE(fixUpLocation, accumulator);
1642 break;
e456bf10
A
1643#if SUPPORT_ARCH_arm64e
1644 case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64: {
1645 accumulator = addressOf(state, fit, &toTarget);
1646 if ( fit->contentAddendOnly ) {
1647 // ld -r mode. We want to write out the original relocation again
1648
1649 // FIXME: Should we zero out the accumulator here as done in kindStoreTargetAddressLittleEndian64?
1650 // Make sure the high bits aren't set. The low-32-bits should be the addend.
1651 assert((accumulator & 0xFFFFFFFF00000000ULL) == 0);
1652 accumulator |= ((uint64_t)authData.discriminator) << 32;
1653 accumulator |= ((uint64_t)authData.hasAddressDiversity) << 48;
1654 accumulator |= ((uint64_t)authData.key) << 49;
1655 // Set the high bit as we are authenticated
1656 accumulator |= 1ULL << 63;
1657 set64LE(fixUpLocation, accumulator);
1658 }
1659 else if (_options.outputKind() == Options::kKextBundle ) {
1660 // kexts dont' handle auth pointers, write unauth pointer
1661 set64LE(fixUpLocation, accumulator);
1662 }
1663 else {
1664 auto fixupOffset = (uintptr_t)(fixUpLocation - mhAddress);
1665 assert(_authenticatedFixupData.find(fixupOffset) == _authenticatedFixupData.end());
1666 auto authneticatedData = std::make_pair(authData, accumulator);
1667 _authenticatedFixupData[fixupOffset] = authneticatedData;
1668 // Zero out this entry which we will expect later.
1669 set64LE(fixUpLocation, 0);
1670 }
1671 break;
1672 }
1673 case ld::Fixup::kindStoreLittleEndianAuth64: {
1674 if ( fit->contentAddendOnly ) {
1675 // ld -r mode. We want to write out the original relocation again
1676
1677 // FIXME: Should we zero out the accumulator here as done in kindStoreTargetAddressLittleEndian64?
1678 // Make sure the high bits aren't set. The low-32-bits should be the addend.
1679 assert((accumulator & 0xFFFFFFFF00000000ULL) == 0);
1680 accumulator |= ((uint64_t)authData.discriminator) << 32;
1681 accumulator |= ((uint64_t)authData.hasAddressDiversity) << 48;
1682 accumulator |= ((uint64_t)authData.key) << 49;
1683 // Set the high bit as we are authenticated
1684 accumulator |= 1ULL << 63;
1685 set64LE(fixUpLocation, accumulator);
1686 }
1687 else if (_options.outputKind() == Options::kKextBundle ) {
1688 // kexts dont' handle auth pointers, write unauth pointer
1689 set64LE(fixUpLocation, accumulator);
1690 }
1691 else {
1692 auto fixupOffset = (uintptr_t)(fixUpLocation - mhAddress);
1693 assert(_authenticatedFixupData.find(fixupOffset) == _authenticatedFixupData.end());
1694 auto authneticatedData = std::make_pair(authData, accumulator);
1695 _authenticatedFixupData[fixupOffset] = authneticatedData;
1696 // Zero out this entry which we will expect later.
1697 set64LE(fixUpLocation, 0);
1698 }
1699 break;
1700 }
1701 case ld::Fixup::kindSetAuthData:
1702 authData = fit->u.authData;
1703 break;
1704#endif
a645023d
A
1705 case ld::Fixup::kindStoreTargetAddressBigEndian32:
1706 accumulator = addressOf(state, fit, &toTarget);
1707 if ( fit->contentAddendOnly )
1708 accumulator = 0;
1709 set32BE(fixUpLocation, accumulator);
1710 break;
1711 case ld::Fixup::kindStoreTargetAddressBigEndian64:
1712 accumulator = addressOf(state, fit, &toTarget);
1713 if ( fit->contentAddendOnly )
1714 accumulator = 0;
1715 set64BE(fixUpLocation, accumulator);
1716 break;
1717 case ld::Fixup::kindSetTargetTLVTemplateOffsetLittleEndian32:
1718 accumulator = tlvTemplateOffsetOf(state, fit);
1719 set32LE(fixUpLocation, accumulator);
1720 break;
1721 case ld::Fixup::kindSetTargetTLVTemplateOffsetLittleEndian64:
1722 accumulator = tlvTemplateOffsetOf(state, fit);
1723 set64LE(fixUpLocation, accumulator);
1724 break;
1725 case ld::Fixup::kindStoreTargetAddressX86PCRel32:
1726 case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32:
1727 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad:
1728 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad:
1729 accumulator = addressOf(state, fit, &toTarget);
1730 if ( fit->contentDetlaToAddendOnly )
1731 accumulator = 0;
1732 if ( fit->contentAddendOnly )
1733 delta = 0;
1734 else
1735 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 4);
1736 rangeCheckRIP32(delta, state, atom, fit);
1737 set32LE(fixUpLocation, delta);
1738 break;
1739 case ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoad:
1740 set32LE(fixUpLocation, accumulator);
1741 break;
1742 case ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoadNowLEA:
1743 // TLV entry was optimized away, change movl instruction to a leal
1744 if ( fixUpLocation[-1] != 0xA1 )
1745 throw "TLV load reloc does not point to a movl <abs-address>,<reg> instruction";
1746 fixUpLocation[-1] = 0xB8;
1747 accumulator = addressOf(state, fit, &toTarget);
1748 set32LE(fixUpLocation, accumulator);
1749 break;
1750 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA:
1751 // GOT entry was optimized away, change movq instruction to a leaq
1752 if ( fixUpLocation[-2] != 0x8B )
1753 throw "GOT load reloc does not point to a movq instruction";
1754 fixUpLocation[-2] = 0x8D;
1755 accumulator = addressOf(state, fit, &toTarget);
1756 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 4);
1757 rangeCheckRIP32(delta, state, atom, fit);
1758 set32LE(fixUpLocation, delta);
1759 break;
1760 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA:
1761 // TLV entry was optimized away, change movq instruction to a leaq
1762 if ( fixUpLocation[-2] != 0x8B )
1763 throw "TLV load reloc does not point to a movq instruction";
1764 fixUpLocation[-2] = 0x8D;
1765 accumulator = addressOf(state, fit, &toTarget);
1766 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 4);
1767 rangeCheckRIP32(delta, state, atom, fit);
1768 set32LE(fixUpLocation, delta);
1769 break;
1770 case ld::Fixup::kindStoreTargetAddressARMBranch24:
1771 accumulator = addressOf(state, fit, &toTarget);
1772 thumbTarget = targetIsThumb(state, fit);
9543cb2f
A
1773 if ( toTarget->contentType() == ld::Atom::typeBranchIsland ) {
1774 // Branching to island. If ultimate target is in range, branch there directly.
1775 for (ld::Fixup::iterator islandfit = toTarget->fixupsBegin(), end=toTarget->fixupsEnd(); islandfit != end; ++islandfit) {
1776 if ( islandfit->kind == ld::Fixup::kindIslandTarget ) {
1777 const ld::Atom* islandTarget = NULL;
1778 uint64_t islandTargetAddress = addressOf(state, islandfit, &islandTarget);
c1f6aec5 1779 delta = islandTargetAddress - (atom->finalAddress() + fit->offsetInAtom + 8);
9543cb2f
A
1780 if ( checkArmBranch24Displacement(delta) ) {
1781 toTarget = islandTarget;
1782 accumulator = islandTargetAddress;
1783 thumbTarget = targetIsThumb(state, islandfit);
1784 }
1785 break;
1786 }
1787 }
1788 }
a645023d
A
1789 if ( thumbTarget )
1790 accumulator |= 1;
1791 if ( fit->contentDetlaToAddendOnly )
1792 accumulator = 0;
1793 // fall into kindStoreARMBranch24 case
1794 case ld::Fixup::kindStoreARMBranch24:
1795 // The pc added will be +8 from the pc
1796 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 8);
1797 rangeCheckARMBranch24(delta, state, atom, fit);
1798 instruction = get32LE(fixUpLocation);
9543cb2f 1799 // Make sure we are calling arm with bl, thumb with blx
a645023d
A
1800 is_bl = ((instruction & 0xFF000000) == 0xEB000000);
1801 is_blx = ((instruction & 0xFE000000) == 0xFA000000);
afe874b1 1802 is_b = !is_blx && ((instruction & 0x0F000000) == 0x0A000000);
9543cb2f
A
1803 if ( (is_bl | is_blx) && thumbTarget ) {
1804 uint32_t opcode = 0xFA000000; // force to be blx
a645023d
A
1805 uint32_t disp = (uint32_t)(delta >> 2) & 0x00FFFFFF;
1806 uint32_t h_bit = (uint32_t)(delta << 23) & 0x01000000;
1807 newInstruction = opcode | h_bit | disp;
1808 }
9543cb2f
A
1809 else if ( (is_bl | is_blx) && !thumbTarget ) {
1810 uint32_t opcode = 0xEB000000; // force to be bl
a645023d
A
1811 uint32_t disp = (uint32_t)(delta >> 2) & 0x00FFFFFF;
1812 newInstruction = opcode | disp;
1813 }
afe874b1
A
1814 else if ( is_b && thumbTarget ) {
1815 if ( fit->contentDetlaToAddendOnly )
1816 newInstruction = (instruction & 0xFF000000) | ((uint32_t)(delta >> 2) & 0x00FFFFFF);
1817 else
1818 throwf("no pc-rel bx arm instruction. Can't fix up branch to %s in %s",
1819 referenceTargetAtomName(state, fit), atom->name());
1820 }
a645023d
A
1821 else if ( !is_bl && !is_blx && thumbTarget ) {
1822 throwf("don't know how to convert instruction %x referencing %s to thumb",
1823 instruction, referenceTargetAtomName(state, fit));
1824 }
1825 else {
1826 newInstruction = (instruction & 0xFF000000) | ((uint32_t)(delta >> 2) & 0x00FFFFFF);
1827 }
1828 set32LE(fixUpLocation, newInstruction);
1829 break;
1830 case ld::Fixup::kindStoreTargetAddressThumbBranch22:
1831 accumulator = addressOf(state, fit, &toTarget);
1832 thumbTarget = targetIsThumb(state, fit);
9543cb2f
A
1833 if ( toTarget->contentType() == ld::Atom::typeBranchIsland ) {
1834 // branching to island, so see if ultimate target is in range
1835 // and if so branch to ultimate target instead.
1836 for (ld::Fixup::iterator islandfit = toTarget->fixupsBegin(), end=toTarget->fixupsEnd(); islandfit != end; ++islandfit) {
1837 if ( islandfit->kind == ld::Fixup::kindIslandTarget ) {
1838 const ld::Atom* islandTarget = NULL;
1839 uint64_t islandTargetAddress = addressOf(state, islandfit, &islandTarget);
599556ff
A
1840 if ( !fit->contentDetlaToAddendOnly ) {
1841 if ( targetIsThumb(state, islandfit) ) {
1842 // Thumb to thumb branch, we will be generating a bl instruction.
1843 // Delta is always even, so mask out thumb bit in target.
1844 islandTargetAddress &= -2ULL;
1845 }
1846 else {
1847 // Target is not thumb, we will be generating a blx instruction
1848 // Since blx cannot have the low bit set, set bit[1] of the target to
1849 // bit[1] of the base address, so that the difference is a multiple of
1850 // 4 bytes.
1851 islandTargetAddress &= -3ULL;
1852 islandTargetAddress |= ((atom->finalAddress() + fit->offsetInAtom ) & 2LL);
1853 }
1854 }
9543cb2f
A
1855 delta = islandTargetAddress - (atom->finalAddress() + fit->offsetInAtom + 4);
1856 if ( checkThumbBranch22Displacement(delta) ) {
1857 toTarget = islandTarget;
1858 accumulator = islandTargetAddress;
1859 thumbTarget = targetIsThumb(state, islandfit);
1860 }
1861 break;
1862 }
1863 }
1864 }
a645023d
A
1865 if ( thumbTarget )
1866 accumulator |= 1;
1867 if ( fit->contentDetlaToAddendOnly )
1868 accumulator = 0;
1869 // fall into kindStoreThumbBranch22 case
1870 case ld::Fixup::kindStoreThumbBranch22:
1871 instruction = get32LE(fixUpLocation);
1872 is_bl = ((instruction & 0xD000F800) == 0xD000F000);
1873 is_blx = ((instruction & 0xD000F800) == 0xC000F000);
1874 is_b = ((instruction & 0xD000F800) == 0x9000F000);
599556ff
A
1875 if ( !fit->contentDetlaToAddendOnly ) {
1876 if ( thumbTarget ) {
1877 // Thumb to thumb branch, we will be generating a bl instruction.
1878 // Delta is always even, so mask out thumb bit in target.
1879 accumulator &= -2ULL;
1880 }
1881 else {
1882 // Target is not thumb, we will be generating a blx instruction
1883 // Since blx cannot have the low bit set, set bit[1] of the target to
1884 // bit[1] of the base address, so that the difference is a multiple of
1885 // 4 bytes.
1886 accumulator &= -3ULL;
1887 accumulator |= ((atom->finalAddress() + fit->offsetInAtom ) & 2LL);
1888 }
a645023d
A
1889 }
1890 // The pc added will be +4 from the pc
1891 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom + 4);
599556ff
A
1892 // <rdar://problem/16652542> support bl in very large .o files
1893 if ( fit->contentDetlaToAddendOnly ) {
1894 while ( delta < (-16777216LL) )
1895 delta += 0x2000000;
1896 }
a645023d 1897 rangeCheckThumbBranch22(delta, state, atom, fit);
afe874b1 1898 if ( _options.preferSubArchitecture() && _options.archSupportsThumb2() ) {
a645023d
A
1899 // The instruction is really two instructions:
1900 // The lower 16 bits are the first instruction, which contains the high
1901 // 11 bits of the displacement.
1902 // The upper 16 bits are the second instruction, which contains the low
1903 // 11 bits of the displacement, as well as differentiating bl and blx.
1904 uint32_t s = (uint32_t)(delta >> 24) & 0x1;
1905 uint32_t i1 = (uint32_t)(delta >> 23) & 0x1;
1906 uint32_t i2 = (uint32_t)(delta >> 22) & 0x1;
1907 uint32_t imm10 = (uint32_t)(delta >> 12) & 0x3FF;
1908 uint32_t imm11 = (uint32_t)(delta >> 1) & 0x7FF;
1909 uint32_t j1 = (i1 == s);
1910 uint32_t j2 = (i2 == s);
1911 if ( is_bl ) {
1912 if ( thumbTarget )
1913 instruction = 0xD000F000; // keep bl
1914 else
1915 instruction = 0xC000F000; // change to blx
1916 }
1917 else if ( is_blx ) {
1918 if ( thumbTarget )
1919 instruction = 0xD000F000; // change to bl
1920 else
1921 instruction = 0xC000F000; // keep blx
1922 }
1923 else if ( is_b ) {
a645023d 1924 instruction = 0x9000F000; // keep b
afe874b1
A
1925 if ( !thumbTarget && !fit->contentDetlaToAddendOnly ) {
1926 throwf("armv7 has no pc-rel bx thumb instruction. Can't fix up branch to %s in %s",
1927 referenceTargetAtomName(state, fit), atom->name());
1928 }
a645023d 1929 }
afe874b1 1930 else {
a645023d
A
1931 if ( !thumbTarget )
1932 throwf("don't know how to convert branch instruction %x referencing %s to bx",
1933 instruction, referenceTargetAtomName(state, fit));
1934 instruction = 0x9000F000; // keep b
1935 }
1936 uint32_t nextDisp = (j1 << 13) | (j2 << 11) | imm11;
1937 uint32_t firstDisp = (s << 10) | imm10;
1938 newInstruction = instruction | (nextDisp << 16) | firstDisp;
d425e388
A
1939 //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",
1940 // s, j1, j2, imm10, imm11, instruction, firstDisp, nextDisp, newInstruction, delta, atom->name(), toTarget->name());
a645023d
A
1941 set32LE(fixUpLocation, newInstruction);
1942 }
1943 else {
1944 // The instruction is really two instructions:
1945 // The lower 16 bits are the first instruction, which contains the high
1946 // 11 bits of the displacement.
1947 // The upper 16 bits are the second instruction, which contains the low
1948 // 11 bits of the displacement, as well as differentiating bl and blx.
1949 uint32_t firstDisp = (uint32_t)(delta >> 12) & 0x7FF;
1950 uint32_t nextDisp = (uint32_t)(delta >> 1) & 0x7FF;
1951 if ( is_bl && !thumbTarget ) {
1952 instruction = 0xE800F000;
1953 }
1954 else if ( is_blx && thumbTarget ) {
1955 instruction = 0xF800F000;
1956 }
afe874b1
A
1957 else if ( is_b ) {
1958 instruction = 0x9000F000; // keep b
1959 if ( !thumbTarget && !fit->contentDetlaToAddendOnly ) {
1960 throwf("armv6 has no pc-rel bx thumb instruction. Can't fix up branch to %s in %s",
1961 referenceTargetAtomName(state, fit), atom->name());
1962 }
1963 }
a645023d
A
1964 else {
1965 instruction = instruction & 0xF800F800;
1966 }
1967 newInstruction = instruction | (nextDisp << 16) | firstDisp;
1968 set32LE(fixUpLocation, newInstruction);
1969 }
1970 break;
1971 case ld::Fixup::kindStoreARMLow16:
1972 {
1973 uint32_t imm4 = (accumulator & 0x0000F000) >> 12;
1974 uint32_t imm12 = accumulator & 0x00000FFF;
1975 instruction = get32LE(fixUpLocation);
1976 newInstruction = (instruction & 0xFFF0F000) | (imm4 << 16) | imm12;
1977 set32LE(fixUpLocation, newInstruction);
1978 }
1979 break;
1980 case ld::Fixup::kindStoreARMHigh16:
1981 {
1982 uint32_t imm4 = (accumulator & 0xF0000000) >> 28;
1983 uint32_t imm12 = (accumulator & 0x0FFF0000) >> 16;
1984 instruction = get32LE(fixUpLocation);
1985 newInstruction = (instruction & 0xFFF0F000) | (imm4 << 16) | imm12;
1986 set32LE(fixUpLocation, newInstruction);
1987 }
1988 break;
1989 case ld::Fixup::kindStoreThumbLow16:
1990 {
1991 uint32_t imm4 = (accumulator & 0x0000F000) >> 12;
1992 uint32_t i = (accumulator & 0x00000800) >> 11;
1993 uint32_t imm3 = (accumulator & 0x00000700) >> 8;
1994 uint32_t imm8 = accumulator & 0x000000FF;
1995 instruction = get32LE(fixUpLocation);
1996 newInstruction = (instruction & 0x8F00FBF0) | imm4 | (i << 10) | (imm3 << 28) | (imm8 << 16);
1997 set32LE(fixUpLocation, newInstruction);
1998 }
1999 break;
2000 case ld::Fixup::kindStoreThumbHigh16:
2001 {
2002 uint32_t imm4 = (accumulator & 0xF0000000) >> 28;
2003 uint32_t i = (accumulator & 0x08000000) >> 27;
2004 uint32_t imm3 = (accumulator & 0x07000000) >> 24;
2005 uint32_t imm8 = (accumulator & 0x00FF0000) >> 16;
2006 instruction = get32LE(fixUpLocation);
2007 newInstruction = (instruction & 0x8F00FBF0) | imm4 | (i << 10) | (imm3 << 28) | (imm8 << 16);
2008 set32LE(fixUpLocation, newInstruction);
2009 }
2010 break;
f80fe69f
A
2011#if SUPPORT_ARCH_arm64
2012 case ld::Fixup::kindStoreTargetAddressARM64Branch26:
2013 accumulator = addressOf(state, fit, &toTarget);
2014 // fall into kindStoreARM64Branch26 case
2015 case ld::Fixup::kindStoreARM64Branch26:
2016 if ( fit->contentAddendOnly )
2017 delta = accumulator;
2018 else
2019 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom);
2020 rangeCheckARM64Branch26(delta, state, atom, fit);
2021 instruction = get32LE(fixUpLocation);
2022 newInstruction = (instruction & 0xFC000000) | ((uint32_t)(delta >> 2) & 0x03FFFFFF);
2023 set32LE(fixUpLocation, newInstruction);
2024 break;
2025 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21:
2026 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
2027 case ld::Fixup::kindStoreTargetAddressARM64Page21:
9543cb2f
A
2028 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21:
2029 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPage21:
f80fe69f
A
2030 accumulator = addressOf(state, fit, &toTarget);
2031 // fall into kindStoreARM64Branch26 case
2032 case ld::Fixup::kindStoreARM64GOTLeaPage21:
2033 case ld::Fixup::kindStoreARM64GOTLoadPage21:
2034 case ld::Fixup::kindStoreARM64TLVPLoadPage21:
9543cb2f 2035 case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPage21:
f80fe69f
A
2036 case ld::Fixup::kindStoreARM64Page21:
2037 {
2038 // the ADRP instruction adds the imm << 12 to the page that the pc is on
2039 if ( fit->contentAddendOnly )
2040 delta = 0;
2041 else
2042 delta = (accumulator & (-4096)) - ((atom->finalAddress() + fit->offsetInAtom) & (-4096));
2043 rangeCheckARM64Page21(delta, state, atom, fit);
2044 instruction = get32LE(fixUpLocation);
2045 uint32_t immhi = (delta >> 9) & (0x00FFFFE0);
2046 uint32_t immlo = (delta << 17) & (0x60000000);
2047 newInstruction = (instruction & 0x9F00001F) | immlo | immhi;
2048 set32LE(fixUpLocation, newInstruction);
2049 }
2050 break;
2051 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12:
e456bf10
A
2052 // In -r mode, the GOT doesn't exist but the relocations track it
2053 // so the address doesn't need to be aligned.
2054 if ( _options.outputKind() == Options::kObjectFile )
2055 break;
f80fe69f 2056 case ld::Fixup::kindStoreTargetAddressARM64PageOff12:
9543cb2f 2057 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12:
f80fe69f
A
2058 accumulator = addressOf(state, fit, &toTarget);
2059 // fall into kindAddressARM64PageOff12 case
2060 case ld::Fixup::kindStoreARM64TLVPLoadPageOff12:
2061 case ld::Fixup::kindStoreARM64GOTLoadPageOff12:
2062 case ld::Fixup::kindStoreARM64PageOff12:
2063 {
2064 uint32_t offset = accumulator & 0x00000FFF;
2065 instruction = get32LE(fixUpLocation);
2066 // LDR/STR instruction have implicit scale factor, need to compensate for that
2067 if ( instruction & 0x08000000 ) {
2068 uint32_t implictShift = ((instruction >> 30) & 0x3);
2069 switch ( implictShift ) {
2070 case 0:
2071 if ( (instruction & 0x04800000) == 0x04800000 ) {
2072 // vector and byte LDR/STR have same "size" bits, need to check other bits to differenciate
2073 implictShift = 4;
2074 if ( (offset & 0xF) != 0 ) {
2075 throwf("128-bit LDR/STR not 16-byte aligned: from %s (0x%08llX) to %s (0x%08llX)",
2076 atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fit),
2077 addressOf(state, fit, &toTarget));
2078 }
2079 }
2080 break;
2081 case 1:
2082 if ( (offset & 0x1) != 0 ) {
2083 throwf("16-bit LDR/STR not 2-byte aligned: from %s (0x%08llX) to %s (0x%08llX)",
2084 atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fit),
2085 addressOf(state, fit, &toTarget));
2086 }
2087 break;
2088 case 2:
2089 if ( (offset & 0x3) != 0 ) {
2090 throwf("32-bit LDR/STR not 4-byte aligned: from %s (0x%08llX) to %s (0x%08llX)",
2091 atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fit),
2092 addressOf(state, fit, &toTarget));
2093 }
2094 break;
2095 case 3:
2096 if ( (offset & 0x7) != 0 ) {
2097 throwf("64-bit LDR/STR not 8-byte aligned: from %s (0x%08llX) to %s (0x%08llX)",
2098 atom->name(), atom->finalAddress(), referenceTargetAtomName(state, fit),
2099 addressOf(state, fit, &toTarget));
2100 }
2101 break;
2102 }
2103 // compensate for implicit scale
2104 offset >>= implictShift;
2105 }
2106 if ( fit->contentAddendOnly )
2107 offset = 0;
2108 uint32_t imm12 = offset << 10;
2109 newInstruction = (instruction & 0xFFC003FF) | imm12;
2110 set32LE(fixUpLocation, newInstruction);
2111 }
2112 break;
2113 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPageOff12:
2114 accumulator = addressOf(state, fit, &toTarget);
2115 // fall into kindStoreARM64GOTLoadPage21 case
2116 case ld::Fixup::kindStoreARM64GOTLeaPageOff12:
2117 {
2118 // GOT entry was optimized away, change LDR instruction to a ADD
2119 instruction = get32LE(fixUpLocation);
0a8dc3df 2120 if ( (instruction & 0xBFC00000) != 0xB9400000 )
f80fe69f
A
2121 throwf("GOT load reloc does not point to a LDR instruction in %s", atom->name());
2122 uint32_t offset = accumulator & 0x00000FFF;
2123 uint32_t imm12 = offset << 10;
2124 newInstruction = 0x91000000 | imm12 | (instruction & 0x000003FF);
2125 set32LE(fixUpLocation, newInstruction);
2126 }
2127 break;
9543cb2f
A
2128 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12:
2129 accumulator = addressOf(state, fit, &toTarget);
2130 // fall into kindStoreARM64TLVPLeaPageOff12 case
2131 case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPageOff12:
2132 {
2133 // TLV thunk in same linkage unit, so LEA it directly, changing LDR instruction to a ADD
2134 instruction = get32LE(fixUpLocation);
0a8dc3df 2135 if ( (instruction & 0xBFC00000) != 0xB9400000 )
9543cb2f
A
2136 throwf("TLV load reloc does not point to a LDR instruction in %s", atom->name());
2137 uint32_t offset = accumulator & 0x00000FFF;
2138 uint32_t imm12 = offset << 10;
2139 newInstruction = 0x91000000 | imm12 | (instruction & 0x000003FF);
2140 set32LE(fixUpLocation, newInstruction);
2141 }
2142 break;
f80fe69f
A
2143 case ld::Fixup::kindStoreARM64PointerToGOT:
2144 set64LE(fixUpLocation, accumulator);
2145 break;
0a8dc3df 2146 case ld::Fixup::kindStoreARM64PCRelToGOT:
f80fe69f
A
2147 if ( fit->contentAddendOnly )
2148 delta = accumulator;
2149 else
2150 delta = accumulator - (atom->finalAddress() + fit->offsetInAtom);
2151 set32LE(fixUpLocation, delta);
2152 break;
2153#endif
a645023d
A
2154 }
2155 }
9543cb2f 2156
599556ff 2157#if SUPPORT_ARCH_arm64
9543cb2f
A
2158 // after all fixups are done on atom, if there are potential optimizations, do those
2159 if ( (usedByHints.size() != 0) && (_options.outputKind() != Options::kObjectFile) && !_options.ignoreOptimizationHints() ) {
2160 // fill in second part of usedByHints map, so we can see the target of fixups that might be optimized
2161 for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
2162 switch ( fit->kind ) {
2163 case ld::Fixup::kindLinkerOptimizationHint:
2164 case ld::Fixup::kindNoneFollowOn:
2165 case ld::Fixup::kindNoneGroupSubordinate:
2166 case ld::Fixup::kindNoneGroupSubordinateFDE:
2167 case ld::Fixup::kindNoneGroupSubordinateLSDA:
2168 case ld::Fixup::kindNoneGroupSubordinatePersonality:
2169 break;
2170 default:
2171 if ( fit->firstInCluster() ) {
2172 std::map<uint32_t, const Fixup*>::iterator pos = usedByHints.find(fit->offsetInAtom);
2173 if ( pos != usedByHints.end() ) {
2174 assert(pos->second == NULL && "two fixups in same hint location");
2175 pos->second = fit;
2176 //fprintf(stderr, "setting %s usedByHints[0x%04X], kind = %d\n", atom->name(), fit->offsetInAtom, fit->kind);
2177 }
2178 }
2179 }
2180 }
2181
2182 // apply hints pass 1
2183 for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
2184 if ( fit->kind != ld::Fixup::kindLinkerOptimizationHint )
2185 continue;
2186 InstructionInfo infoA;
2187 InstructionInfo infoB;
2188 InstructionInfo infoC;
2189 InstructionInfo infoD;
2190 LoadStoreInfo ldrInfoB, ldrInfoC;
2191 AddInfo addInfoB;
2192 AdrpInfo adrpInfoA;
2193 bool usableSegment;
2194 bool targetFourByteAligned;
2195 bool literalableSize, isADRP, isADD, isLDR, isSTR;
2196 //uint8_t loadSize, destReg;
2197 //uint32_t scaledOffset;
2198 //uint32_t imm12;
2199 ld::Fixup::LOH_arm64 alt;
2200 alt.addend = fit->u.addend;
2201 setInfo(state, atom, buffer, usedByHints, fit->offsetInAtom, (alt.info.delta1 << 2), &infoA);
2202 if ( alt.info.count > 0 )
2203 setInfo(state, atom, buffer, usedByHints, fit->offsetInAtom, (alt.info.delta2 << 2), &infoB);
2204 if ( alt.info.count > 1 )
2205 setInfo(state, atom, buffer, usedByHints, fit->offsetInAtom, (alt.info.delta3 << 2), &infoC);
2206 if ( alt.info.count > 2 )
2207 setInfo(state, atom, buffer, usedByHints, fit->offsetInAtom, (alt.info.delta4 << 2), &infoD);
eaf282aa
A
2208
2209 if ( _options.sharedRegionEligible() ) {
2210 if ( _options.sharedRegionEncodingV2() ) {
2211 // In v2 format, all references might be move at dyld shared cache creation time
2212 usableSegment = false;
2213 }
2214 else {
2215 // In v1 format, only references to something in __TEXT segment could be optimized
2216 usableSegment = (strcmp(atom->section().segmentName(), infoB.target->section().segmentName()) == 0);
2217 }
2218 }
2219 else {
2220 // main executables can optimize any reference
2221 usableSegment = true;
2222 }
2223
9543cb2f
A
2224 switch ( alt.info.kind ) {
2225 case LOH_ARM64_ADRP_ADRP:
eaf282aa 2226 // processed in pass 2 because some ADRP may have been removed
9543cb2f
A
2227 break;
2228 case LOH_ARM64_ADRP_LDR:
2229 LOH_ASSERT(alt.info.count == 1);
2230 LOH_ASSERT(isPageKind(infoA.fixup));
2231 LOH_ASSERT(isPageOffsetKind(infoB.fixup));
2232 LOH_ASSERT(infoA.target == infoB.target);
2233 LOH_ASSERT(infoA.targetAddress == infoB.targetAddress);
9543cb2f
A
2234 isADRP = parseADRP(infoA.instruction, adrpInfoA);
2235 LOH_ASSERT(isADRP);
2236 isLDR = parseLoadOrStore(infoB.instruction, ldrInfoB);
eaf282aa
A
2237 // silently ignore LDRs transformed to ADD by TLV pass
2238 if ( !isLDR && infoB.fixup->kind == ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12 )
2239 break;
9543cb2f
A
2240 LOH_ASSERT(isLDR);
2241 LOH_ASSERT(ldrInfoB.baseReg == adrpInfoA.destReg);
2242 LOH_ASSERT(ldrInfoB.offset == (infoA.targetAddress & 0x00000FFF));
2243 literalableSize = ( (ldrInfoB.size != 1) && (ldrInfoB.size != 2) );
2244 targetFourByteAligned = ( (infoA.targetAddress & 0x3) == 0 );
2245 if ( literalableSize && usableSegment && targetFourByteAligned && withinOneMeg(infoB.instructionAddress, infoA.targetAddress) ) {
2246 set32LE(infoA.instructionContent, makeNOP());
2247 set32LE(infoB.instructionContent, makeLDR_literal(ldrInfoB, infoA.targetAddress, infoB.instructionAddress));
2248 if ( _options.verboseOptimizationHints() )
eaf282aa 2249 fprintf(stderr, "adrp-ldr at 0x%08llX transformed to LDR literal, usableSegment=%d usableSegment\n", infoB.instructionAddress, usableSegment);
9543cb2f
A
2250 }
2251 else {
2252 if ( _options.verboseOptimizationHints() )
2253 fprintf(stderr, "adrp-ldr at 0x%08llX not transformed, isLDR=%d, literalableSize=%d, inRange=%d, usableSegment=%d, scaledOffset=%d\n",
2254 infoB.instructionAddress, isLDR, literalableSize, withinOneMeg(infoB.instructionAddress, infoA.targetAddress), usableSegment, ldrInfoB.offset);
2255 }
2256 break;
2257 case LOH_ARM64_ADRP_ADD_LDR:
2258 LOH_ASSERT(alt.info.count == 2);
2259 LOH_ASSERT(isPageKind(infoA.fixup));
2260 LOH_ASSERT(isPageOffsetKind(infoB.fixup));
2261 LOH_ASSERT(infoC.fixup == NULL);
2262 LOH_ASSERT(infoA.target == infoB.target);
2263 LOH_ASSERT(infoA.targetAddress == infoB.targetAddress);
9543cb2f
A
2264 isADRP = parseADRP(infoA.instruction, adrpInfoA);
2265 LOH_ASSERT(isADRP);
2266 isADD = parseADD(infoB.instruction, addInfoB);
2267 LOH_ASSERT(isADD);
2268 LOH_ASSERT(adrpInfoA.destReg == addInfoB.srcReg);
2269 isLDR = parseLoadOrStore(infoC.instruction, ldrInfoC);
2270 LOH_ASSERT(isLDR);
2271 LOH_ASSERT(addInfoB.destReg == ldrInfoC.baseReg);
2272 targetFourByteAligned = ( ((infoB.targetAddress+ldrInfoC.offset) & 0x3) == 0 );
2273 literalableSize = ( (ldrInfoC.size != 1) && (ldrInfoC.size != 2) );
2274 if ( literalableSize && usableSegment && targetFourByteAligned && withinOneMeg(infoC.instructionAddress, infoA.targetAddress+ldrInfoC.offset) ) {
2275 // can do T1 transformation to LDR literal
2276 set32LE(infoA.instructionContent, makeNOP());
2277 set32LE(infoB.instructionContent, makeNOP());
2278 set32LE(infoC.instructionContent, makeLDR_literal(ldrInfoC, infoA.targetAddress+ldrInfoC.offset, infoC.instructionAddress));
2279 if ( _options.verboseOptimizationHints() ) {
2280 fprintf(stderr, "adrp-add-ldr at 0x%08llX T1 transformed to LDR literal\n", infoC.instructionAddress);
2281 }
2282 }
2283 else if ( usableSegment && withinOneMeg(infoA.instructionAddress, infoA.targetAddress+ldrInfoC.offset) ) {
2284 // can to T4 transformation and turn ADRP/ADD into ADR
2285 set32LE(infoA.instructionContent, makeADR(ldrInfoC.baseReg, infoA.targetAddress+ldrInfoC.offset, infoA.instructionAddress));
2286 set32LE(infoB.instructionContent, makeNOP());
2287 ldrInfoC.offset = 0; // offset is now in ADR instead of ADD or LDR
2288 set32LE(infoC.instructionContent, makeLoadOrStore(ldrInfoC));
2289 set32LE(infoC.instructionContent, infoC.instruction & 0xFFC003FF);
2290 if ( _options.verboseOptimizationHints() )
2291 fprintf(stderr, "adrp-add-ldr at 0x%08llX T4 transformed to ADR/LDR\n", infoB.instructionAddress);
2292 }
2293 else if ( ((infoB.targetAddress % ldrInfoC.size) == 0) && (ldrInfoC.offset == 0) ) {
2294 // can do T2 transformation by merging ADD into LD
2295 // Leave ADRP as-is
2296 set32LE(infoB.instructionContent, makeNOP());
2297 ldrInfoC.offset += addInfoB.addend;
82b4b32b 2298 ldrInfoC.baseReg = adrpInfoA.destReg;
9543cb2f
A
2299 set32LE(infoC.instructionContent, makeLoadOrStore(ldrInfoC));
2300 if ( _options.verboseOptimizationHints() )
2301 fprintf(stderr, "adrp-add-ldr at 0x%08llX T2 transformed to ADRP/LDR \n", infoC.instructionAddress);
2302 }
2303 else {
2304 if ( _options.verboseOptimizationHints() )
2305 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",
2306 infoC.instructionAddress, ldrInfoC.size, literalableSize, withinOneMeg(infoC.instructionAddress, infoA.targetAddress+ldrInfoC.offset), usableSegment, targetFourByteAligned, ldrInfoC.offset);
2307 }
2308 break;
2309 case LOH_ARM64_ADRP_ADD:
2310 LOH_ASSERT(alt.info.count == 1);
2311 LOH_ASSERT(isPageKind(infoA.fixup));
2312 LOH_ASSERT(isPageOffsetKind(infoB.fixup));
2313 LOH_ASSERT(infoA.target == infoB.target);
2314 LOH_ASSERT(infoA.targetAddress == infoB.targetAddress);
2315 isADRP = parseADRP(infoA.instruction, adrpInfoA);
2316 LOH_ASSERT(isADRP);
2317 isADD = parseADD(infoB.instruction, addInfoB);
2318 LOH_ASSERT(isADD);
2319 LOH_ASSERT(adrpInfoA.destReg == addInfoB.srcReg);
9543cb2f
A
2320 if ( usableSegment && withinOneMeg(infoA.targetAddress, infoA.instructionAddress) ) {
2321 // can do T4 transformation and use ADR
2322 set32LE(infoA.instructionContent, makeADR(addInfoB.destReg, infoA.targetAddress, infoA.instructionAddress));
2323 set32LE(infoB.instructionContent, makeNOP());
2324 if ( _options.verboseOptimizationHints() )
2325 fprintf(stderr, "adrp-add at 0x%08llX transformed to ADR\n", infoB.instructionAddress);
2326 }
2327 else {
2328 if ( _options.verboseOptimizationHints() )
2329 fprintf(stderr, "adrp-add at 0x%08llX not transformed, isAdd=%d, inRange=%d, usableSegment=%d\n",
2330 infoB.instructionAddress, isADD, withinOneMeg(infoA.targetAddress, infoA.instructionAddress), usableSegment);
2331 }
2332 break;
2333 case LOH_ARM64_ADRP_LDR_GOT_LDR:
2334 LOH_ASSERT(alt.info.count == 2);
2335 LOH_ASSERT(isPageKind(infoA.fixup, true));
2336 LOH_ASSERT(isPageOffsetKind(infoB.fixup, true));
2337 LOH_ASSERT(infoC.fixup == NULL);
2338 LOH_ASSERT(infoA.target == infoB.target);
2339 LOH_ASSERT(infoA.targetAddress == infoB.targetAddress);
2340 isADRP = parseADRP(infoA.instruction, adrpInfoA);
2341 LOH_ASSERT(isADRP);
2342 isLDR = parseLoadOrStore(infoC.instruction, ldrInfoC);
2343 LOH_ASSERT(isLDR);
9543cb2f
A
2344 isADD = parseADD(infoB.instruction, addInfoB);
2345 isLDR = parseLoadOrStore(infoB.instruction, ldrInfoB);
2346 if ( isLDR ) {
2347 // target of GOT is external
2348 LOH_ASSERT(ldrInfoB.size == 8);
2349 LOH_ASSERT(!ldrInfoB.isFloat);
2350 LOH_ASSERT(ldrInfoC.baseReg == ldrInfoB.reg);
2351 //fprintf(stderr, "infoA.target=%p, %s, infoA.targetAddress=0x%08llX\n", infoA.target, infoA.target->name(), infoA.targetAddress);
ec29ba20
A
2352 targetFourByteAligned = ( ((infoA.targetAddress + ldrInfoC.offset) & 0x3) == 0 );
2353 if ( usableSegment && targetFourByteAligned && withinOneMeg(infoB.instructionAddress, infoA.targetAddress + ldrInfoC.offset) ) {
9543cb2f
A
2354 // can do T5 transform
2355 set32LE(infoA.instructionContent, makeNOP());
2356 set32LE(infoB.instructionContent, makeLDR_literal(ldrInfoB, infoA.targetAddress, infoB.instructionAddress));
2357 if ( _options.verboseOptimizationHints() ) {
2358 fprintf(stderr, "adrp-ldr-got-ldr at 0x%08llX T5 transformed to LDR literal of GOT plus LDR\n", infoC.instructionAddress);
2359 }
2360 }
2361 else {
2362 if ( _options.verboseOptimizationHints() )
2363 fprintf(stderr, "adrp-ldr-got-ldr at 0x%08llX no optimization done\n", infoC.instructionAddress);
2364 }
2365 }
2366 else if ( isADD ) {
2367 // target of GOT is in same linkage unit and B instruction was changed to ADD to compute LEA of target
2368 LOH_ASSERT(addInfoB.srcReg == adrpInfoA.destReg);
2369 LOH_ASSERT(addInfoB.destReg == ldrInfoC.baseReg);
9543cb2f
A
2370 targetFourByteAligned = ( ((infoA.targetAddress) & 0x3) == 0 );
2371 literalableSize = ( (ldrInfoC.size != 1) && (ldrInfoC.size != 2) );
ec29ba20 2372 if ( usableSegment && literalableSize && targetFourByteAligned && withinOneMeg(infoC.instructionAddress, infoA.targetAddress + ldrInfoC.offset) ) {
9543cb2f
A
2373 // can do T1 transform
2374 set32LE(infoA.instructionContent, makeNOP());
2375 set32LE(infoB.instructionContent, makeNOP());
ec29ba20 2376 set32LE(infoC.instructionContent, makeLDR_literal(ldrInfoC, infoA.targetAddress + ldrInfoC.offset, infoC.instructionAddress));
9543cb2f
A
2377 if ( _options.verboseOptimizationHints() )
2378 fprintf(stderr, "adrp-ldr-got-ldr at 0x%08llX T1 transformed to LDR literal\n", infoC.instructionAddress);
2379 }
2380 else if ( usableSegment && withinOneMeg(infoA.instructionAddress, infoA.targetAddress) ) {
2381 // can do T4 transform
2382 set32LE(infoA.instructionContent, makeADR(ldrInfoC.baseReg, infoA.targetAddress, infoA.instructionAddress));
2383 set32LE(infoB.instructionContent, makeNOP());
2384 set32LE(infoC.instructionContent, makeLoadOrStore(ldrInfoC));
2385 if ( _options.verboseOptimizationHints() ) {
2386 fprintf(stderr, "adrp-ldr-got-ldr at 0x%08llX T4 transformed to ADR/LDR\n", infoC.instructionAddress);
2387 }
2388 }
ec29ba20 2389 else if ( ((infoA.targetAddress % ldrInfoC.size) == 0) && ((addInfoB.addend + ldrInfoC.offset) < 4096) ) {
9543cb2f
A
2390 // can do T2 transform
2391 set32LE(infoB.instructionContent, makeNOP());
2392 ldrInfoC.baseReg = adrpInfoA.destReg;
ec29ba20 2393 ldrInfoC.offset += addInfoB.addend;
9543cb2f
A
2394 set32LE(infoC.instructionContent, makeLoadOrStore(ldrInfoC));
2395 if ( _options.verboseOptimizationHints() ) {
ec29ba20 2396 fprintf(stderr, "adrp-ldr-got-ldr at 0x%08llX T2 transformed to ADRP/NOP/LDR\n", infoC.instructionAddress);
9543cb2f
A
2397 }
2398 }
2399 else {
2400 // T3 transform already done by ld::passes:got:doPass()
2401 if ( _options.verboseOptimizationHints() ) {
2402 fprintf(stderr, "adrp-ldr-got-ldr at 0x%08llX T3 transformed to ADRP/ADD/LDR\n", infoC.instructionAddress);
2403 }
2404 }
2405 }
2406 else {
2407 if ( _options.verboseOptimizationHints() )
2408 fprintf(stderr, "adrp-ldr-got-ldr at 0x%08llX not ADD or LDR\n", infoC.instructionAddress);
2409 }
2410 break;
2411 case LOH_ARM64_ADRP_ADD_STR:
2412 LOH_ASSERT(alt.info.count == 2);
2413 LOH_ASSERT(isPageKind(infoA.fixup));
2414 LOH_ASSERT(isPageOffsetKind(infoB.fixup));
2415 LOH_ASSERT(infoC.fixup == NULL);
2416 LOH_ASSERT(infoA.target == infoB.target);
2417 LOH_ASSERT(infoA.targetAddress == infoB.targetAddress);
9543cb2f
A
2418 isADRP = parseADRP(infoA.instruction, adrpInfoA);
2419 LOH_ASSERT(isADRP);
2420 isADD = parseADD(infoB.instruction, addInfoB);
2421 LOH_ASSERT(isADD);
2422 LOH_ASSERT(adrpInfoA.destReg == addInfoB.srcReg);
2423 isSTR = (parseLoadOrStore(infoC.instruction, ldrInfoC) && ldrInfoC.isStore);
2424 LOH_ASSERT(isSTR);
2425 LOH_ASSERT(addInfoB.destReg == ldrInfoC.baseReg);
2426 if ( usableSegment && withinOneMeg(infoA.instructionAddress, infoA.targetAddress+ldrInfoC.offset) ) {
2427 // can to T4 transformation and turn ADRP/ADD into ADR
2428 set32LE(infoA.instructionContent, makeADR(ldrInfoC.baseReg, infoA.targetAddress+ldrInfoC.offset, infoA.instructionAddress));
2429 set32LE(infoB.instructionContent, makeNOP());
2430 ldrInfoC.offset = 0; // offset is now in ADR instead of ADD or LDR
2431 set32LE(infoC.instructionContent, makeLoadOrStore(ldrInfoC));
2432 set32LE(infoC.instructionContent, infoC.instruction & 0xFFC003FF);
2433 if ( _options.verboseOptimizationHints() )
2434 fprintf(stderr, "adrp-add-str at 0x%08llX T4 transformed to ADR/STR\n", infoB.instructionAddress);
2435 }
2436 else if ( ((infoB.targetAddress % ldrInfoC.size) == 0) && (ldrInfoC.offset == 0) ) {
2437 // can do T2 transformation by merging ADD into STR
2438 // Leave ADRP as-is
2439 set32LE(infoB.instructionContent, makeNOP());
2440 ldrInfoC.offset += addInfoB.addend;
2441 set32LE(infoC.instructionContent, makeLoadOrStore(ldrInfoC));
2442 if ( _options.verboseOptimizationHints() )
2443 fprintf(stderr, "adrp-add-str at 0x%08llX T2 transformed to ADRP/STR \n", infoC.instructionAddress);
2444 }
2445 else {
2446 if ( _options.verboseOptimizationHints() )
2447 fprintf(stderr, "adrp-add-str at 0x%08llX could not be transformed, loadSize=%d, inRange=%d, usableSegment=%d, imm12=%d\n",
2448 infoC.instructionAddress, ldrInfoC.size, withinOneMeg(infoC.instructionAddress, infoA.targetAddress+ldrInfoC.offset), usableSegment, ldrInfoC.offset);
2449 }
2450 break;
2451 case LOH_ARM64_ADRP_LDR_GOT_STR:
2452 LOH_ASSERT(alt.info.count == 2);
2453 LOH_ASSERT(isPageKind(infoA.fixup, true));
2454 LOH_ASSERT(isPageOffsetKind(infoB.fixup, true));
2455 LOH_ASSERT(infoC.fixup == NULL);
2456 LOH_ASSERT(infoA.target == infoB.target);
2457 LOH_ASSERT(infoA.targetAddress == infoB.targetAddress);
2458 isADRP = parseADRP(infoA.instruction, adrpInfoA);
2459 LOH_ASSERT(isADRP);
2460 isSTR = (parseLoadOrStore(infoC.instruction, ldrInfoC) && ldrInfoC.isStore);
2461 LOH_ASSERT(isSTR);
9543cb2f
A
2462 isADD = parseADD(infoB.instruction, addInfoB);
2463 isLDR = parseLoadOrStore(infoB.instruction, ldrInfoB);
2464 if ( isLDR ) {
2465 // target of GOT is external
2466 LOH_ASSERT(ldrInfoB.size == 8);
2467 LOH_ASSERT(!ldrInfoB.isFloat);
2468 LOH_ASSERT(ldrInfoC.baseReg == ldrInfoB.reg);
ec29ba20
A
2469 targetFourByteAligned = ( ((infoA.targetAddress + ldrInfoC.offset) & 0x3) == 0 );
2470 if ( usableSegment && targetFourByteAligned && withinOneMeg(infoB.instructionAddress, infoA.targetAddress + ldrInfoC.offset) ) {
9543cb2f
A
2471 // can do T5 transform
2472 set32LE(infoA.instructionContent, makeNOP());
2473 set32LE(infoB.instructionContent, makeLDR_literal(ldrInfoB, infoA.targetAddress, infoB.instructionAddress));
2474 if ( _options.verboseOptimizationHints() ) {
2475 fprintf(stderr, "adrp-ldr-got-str at 0x%08llX T5 transformed to LDR literal of GOT plus STR\n", infoC.instructionAddress);
2476 }
2477 }
2478 else {
2479 if ( _options.verboseOptimizationHints() )
2480 fprintf(stderr, "adrp-ldr-got-str at 0x%08llX no optimization done\n", infoC.instructionAddress);
2481 }
2482 }
2483 else if ( isADD ) {
2484 // target of GOT is in same linkage unit and B instruction was changed to ADD to compute LEA of target
2485 LOH_ASSERT(addInfoB.srcReg == adrpInfoA.destReg);
2486 LOH_ASSERT(addInfoB.destReg == ldrInfoC.baseReg);
9543cb2f
A
2487 targetFourByteAligned = ( ((infoA.targetAddress) & 0x3) == 0 );
2488 literalableSize = ( (ldrInfoC.size != 1) && (ldrInfoC.size != 2) );
2489 if ( usableSegment && withinOneMeg(infoA.instructionAddress, infoA.targetAddress) ) {
2490 // can do T4 transform
2491 set32LE(infoA.instructionContent, makeADR(ldrInfoC.baseReg, infoA.targetAddress, infoA.instructionAddress));
2492 set32LE(infoB.instructionContent, makeNOP());
2493 set32LE(infoC.instructionContent, makeLoadOrStore(ldrInfoC));
2494 if ( _options.verboseOptimizationHints() ) {
2495 fprintf(stderr, "adrp-ldr-got-str at 0x%08llX T4 transformed to ADR/STR\n", infoC.instructionAddress);
2496 }
2497 }
2498 else if ( ((infoA.targetAddress % ldrInfoC.size) == 0) && (ldrInfoC.offset == 0) ) {
2499 // can do T2 transform
2500 set32LE(infoB.instructionContent, makeNOP());
2501 ldrInfoC.baseReg = adrpInfoA.destReg;
ec29ba20 2502 ldrInfoC.offset += addInfoB.addend;
9543cb2f
A
2503 set32LE(infoC.instructionContent, makeLoadOrStore(ldrInfoC));
2504 if ( _options.verboseOptimizationHints() ) {
2505 fprintf(stderr, "adrp-ldr-got-str at 0x%08llX T4 transformed to ADRP/NOP/STR\n", infoC.instructionAddress);
2506 }
2507 }
2508 else {
2509 // T3 transform already done by ld::passes:got:doPass()
2510 if ( _options.verboseOptimizationHints() ) {
2511 fprintf(stderr, "adrp-ldr-got-str at 0x%08llX T3 transformed to ADRP/ADD/STR\n", infoC.instructionAddress);
2512 }
2513 }
2514 }
2515 else {
2516 if ( _options.verboseOptimizationHints() )
2517 fprintf(stderr, "adrp-ldr-got-str at 0x%08llX not ADD or LDR\n", infoC.instructionAddress);
2518 }
2519 break;
2520 case LOH_ARM64_ADRP_LDR_GOT:
2521 LOH_ASSERT(alt.info.count == 1);
2522 LOH_ASSERT(isPageKind(infoA.fixup, true));
2523 LOH_ASSERT(isPageOffsetKind(infoB.fixup, true));
2524 LOH_ASSERT(infoA.target == infoB.target);
2525 LOH_ASSERT(infoA.targetAddress == infoB.targetAddress);
2526 isADRP = parseADRP(infoA.instruction, adrpInfoA);
2527 isADD = parseADD(infoB.instruction, addInfoB);
2528 isLDR = parseLoadOrStore(infoB.instruction, ldrInfoB);
9543cb2f
A
2529 if ( isADRP ) {
2530 if ( isLDR ) {
2531 if ( usableSegment && withinOneMeg(infoB.instructionAddress, infoA.targetAddress) ) {
2532 // can do T5 transform (LDR literal load of GOT)
2533 set32LE(infoA.instructionContent, makeNOP());
2534 set32LE(infoB.instructionContent, makeLDR_literal(ldrInfoB, infoA.targetAddress, infoB.instructionAddress));
2535 if ( _options.verboseOptimizationHints() ) {
2536 fprintf(stderr, "adrp-ldr-got at 0x%08llX T5 transformed to NOP/LDR\n", infoC.instructionAddress);
2537 }
2538 }
2539 }
2540 else if ( isADD ) {
2541 if ( usableSegment && withinOneMeg(infoA.instructionAddress, infoA.targetAddress) ) {
2542 // can do T4 transform (ADR to compute local address)
2543 set32LE(infoA.instructionContent, makeADR(addInfoB.destReg, infoA.targetAddress, infoA.instructionAddress));
2544 set32LE(infoB.instructionContent, makeNOP());
2545 if ( _options.verboseOptimizationHints() ) {
2546 fprintf(stderr, "adrp-ldr-got at 0x%08llX T4 transformed to ADR/STR\n", infoC.instructionAddress);
2547 }
2548 }
2549 }
2550 else {
2551 if ( _options.verboseOptimizationHints() )
2552 fprintf(stderr, "adrp-ldr-got at 0x%08llX not LDR or ADD\n", infoB.instructionAddress);
2553 }
2554 }
2555 else {
2556 if ( _options.verboseOptimizationHints() )
2557 fprintf(stderr, "adrp-ldr-got at 0x%08llX not ADRP\n", infoA.instructionAddress);
2558 }
2559 break;
2560 default:
2561 if ( _options.verboseOptimizationHints() )
2562 fprintf(stderr, "unknown hint kind %d alt.info.kind at 0x%08llX\n", alt.info.kind, infoA.instructionAddress);
2563 break;
2564 }
2565 }
2566 // apply hints pass 2
2567 for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
2568 if ( fit->kind != ld::Fixup::kindLinkerOptimizationHint )
2569 continue;
2570 InstructionInfo infoA;
2571 InstructionInfo infoB;
2572 ld::Fixup::LOH_arm64 alt;
2573 alt.addend = fit->u.addend;
2574 setInfo(state, atom, buffer, usedByHints, fit->offsetInAtom, (alt.info.delta1 << 2), &infoA);
2575 if ( alt.info.count > 0 )
2576 setInfo(state, atom, buffer, usedByHints, fit->offsetInAtom, (alt.info.delta2 << 2), &infoB);
2577
2578 switch ( alt.info.kind ) {
2579 case LOH_ARM64_ADRP_ADRP:
2580 LOH_ASSERT(isPageKind(infoA.fixup));
2581 LOH_ASSERT(isPageKind(infoB.fixup));
2582 if ( (infoA.instruction & 0x9F000000) != 0x90000000 ) {
2583 if ( _options.verboseOptimizationHints() )
2584 fprintf(stderr, "may-reused-adrp at 0x%08llX no longer an ADRP, now 0x%08X\n", infoA.instructionAddress, infoA.instruction);
2585 sAdrpNA++;
2586 break;
2587 }
2588 if ( (infoB.instruction & 0x9F000000) != 0x90000000 ) {
2589 if ( _options.verboseOptimizationHints() )
2590 fprintf(stderr, "may-reused-adrp at 0x%08llX no longer an ADRP, now 0x%08X\n", infoB.instructionAddress, infoA.instruction);
2591 sAdrpNA++;
2592 break;
2593 }
2594 if ( (infoA.targetAddress & (-4096)) == (infoB.targetAddress & (-4096)) ) {
2595 set32LE(infoB.instructionContent, 0xD503201F);
2596 sAdrpNoped++;
2597 }
2598 else {
2599 sAdrpNotNoped++;
2600 }
2601 break;
2602 }
2603 }
2604 }
599556ff 2605#endif // SUPPORT_ARCH_arm64
9543cb2f 2606
a645023d
A
2607}
2608
afe874b1 2609void OutputFile::copyNoOps(uint8_t* from, uint8_t* to, bool thumb)
a645023d
A
2610{
2611 switch ( _options.architecture() ) {
a645023d
A
2612 case CPU_TYPE_I386:
2613 case CPU_TYPE_X86_64:
2614 for (uint8_t* p=from; p < to; ++p)
2615 *p = 0x90;
2616 break;
2617 case CPU_TYPE_ARM:
afe874b1
A
2618 if ( thumb ) {
2619 for (uint8_t* p=from; p < to; p += 2)
2620 OSWriteLittleInt16((uint16_t*)p, 0, 0x46c0);
2621 }
2622 else {
2623 for (uint8_t* p=from; p < to; p += 4)
2624 OSWriteLittleInt32((uint32_t*)p, 0, 0xe1a00000);
2625 }
a645023d
A
2626 break;
2627 default:
2628 for (uint8_t* p=from; p < to; ++p)
2629 *p = 0x00;
2630 break;
2631 }
2632}
2633
2634bool OutputFile::takesNoDiskSpace(const ld::Section* sect)
2635{
2636 switch ( sect->type() ) {
2637 case ld::Section::typeZeroFill:
2638 case ld::Section::typeTLVZeroFill:
2639 return _options.optimizeZeroFill();
2640 case ld::Section::typePageZero:
2641 case ld::Section::typeStack:
2642 case ld::Section::typeAbsoluteSymbols:
2643 case ld::Section::typeTentativeDefs:
2644 return true;
2645 default:
2646 break;
2647 }
2648 return false;
2649}
2650
2651bool OutputFile::hasZeroForFileOffset(const ld::Section* sect)
2652{
2653 switch ( sect->type() ) {
2654 case ld::Section::typeZeroFill:
2655 case ld::Section::typeTLVZeroFill:
2656 return _options.optimizeZeroFill();
2657 case ld::Section::typePageZero:
2658 case ld::Section::typeStack:
2659 case ld::Section::typeTentativeDefs:
2660 return true;
2661 default:
2662 break;
2663 }
2664 return false;
2665}
2666
ebf6f434 2667void OutputFile::writeAtoms(ld::Internal& state, uint8_t* wholeBuffer)
a645023d 2668{
a645023d
A
2669 // have each atom write itself
2670 uint64_t fileOffsetOfEndOfLastAtom = 0;
2671 uint64_t mhAddress = 0;
2672 bool lastAtomUsesNoOps = false;
2673 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
2674 ld::Internal::FinalSection* sect = *sit;
2675 if ( sect->type() == ld::Section::typeMachHeader )
2676 mhAddress = sect->address;
2677 if ( takesNoDiskSpace(sect) )
2678 continue;
2679 const bool sectionUsesNops = (sect->type() == ld::Section::typeCode);
2680 //fprintf(stderr, "file offset=0x%08llX, section %s\n", sect->fileOffset, sect->sectionName());
2681 std::vector<const ld::Atom*>& atoms = sect->atoms;
afe874b1 2682 bool lastAtomWasThumb = false;
a645023d
A
2683 for (std::vector<const ld::Atom*>::iterator ait = atoms.begin(); ait != atoms.end(); ++ait) {
2684 const ld::Atom* atom = *ait;
2685 if ( atom->definition() == ld::Atom::definitionProxy )
2686 continue;
2687 try {
2688 uint64_t fileOffset = atom->finalAddress() - sect->address + sect->fileOffset;
2689 // check for alignment padding between atoms
2690 if ( (fileOffset != fileOffsetOfEndOfLastAtom) && lastAtomUsesNoOps ) {
afe874b1 2691 this->copyNoOps(&wholeBuffer[fileOffsetOfEndOfLastAtom], &wholeBuffer[fileOffset], lastAtomWasThumb);
a645023d
A
2692 }
2693 // copy atom content
2694 atom->copyRawContent(&wholeBuffer[fileOffset]);
2695 // apply fix ups
2696 this->applyFixUps(state, mhAddress, atom, &wholeBuffer[fileOffset]);
2697 fileOffsetOfEndOfLastAtom = fileOffset+atom->size();
2698 lastAtomUsesNoOps = sectionUsesNops;
afe874b1 2699 lastAtomWasThumb = atom->isThumb();
a645023d
A
2700 }
2701 catch (const char* msg) {
2702 if ( atom->file() != NULL )
82b4b32b 2703 throwf("%s in '%s' from %s", msg, atom->name(), atom->safeFilePath());
a645023d 2704 else
d425e388 2705 throwf("%s in '%s'", msg, atom->name());
a645023d
A
2706 }
2707 }
2708 }
9543cb2f
A
2709
2710 if ( _options.verboseOptimizationHints() ) {
2711 //fprintf(stderr, "ADRP optimized away: %d\n", sAdrpNA);
2712 //fprintf(stderr, "ADRPs changed to NOPs: %d\n", sAdrpNoped);
2713 //fprintf(stderr, "ADRPs unchanged: %d\n", sAdrpNotNoped);
2714 }
e456bf10
A
2715
2716 if ( _options.makeThreadedStartsSection() ) {
2717 assert(_threadedRebaseBindIndices.empty());
2718
2719 std::vector<OutputFile::BindingInfo>& bindInfo = _bindingInfo;
2720 std::vector<OutputFile::RebaseInfo>& rebaseInfo = _rebaseInfo;
2721
2722 std::vector<int64_t>& threadedRebaseBindIndices = _threadedRebaseBindIndices;
2723 threadedRebaseBindIndices.reserve(bindInfo.size() + rebaseInfo.size());
2724
2725 for (int64_t i = 0, e = rebaseInfo.size(); i != e; ++i)
2726 threadedRebaseBindIndices.push_back(-i);
2727
2728 for (int64_t i = 0, e = bindInfo.size(); i != e; ++i)
2729 threadedRebaseBindIndices.push_back(i + 1);
2730
2731 // Now sort the entries by address.
2732 std::sort(threadedRebaseBindIndices.begin(), threadedRebaseBindIndices.end(),
2733 [&rebaseInfo, &bindInfo](int64_t indexA, int64_t indexB) {
2734 if (indexA == indexB)
2735 return false;
2736 uint64_t addressA = indexA <= 0 ? rebaseInfo[-indexA]._address : bindInfo[indexA - 1]._address;
2737 uint64_t addressB = indexB <= 0 ? rebaseInfo[-indexB]._address : bindInfo[indexB - 1]._address;
2738 assert(addressA != addressB);
2739 return addressA < addressB;
2740 });
2741 }
2742
2743 // new rebasing/binding scheme requires making another pass at DATA
2744 // segment and building linked list of rebase locations
2745 if ( _options.useLinkedListBinding() && !_threadedRebaseBindIndices.empty() ) {
2746 uint64_t curSegStart = 0;
2747 uint64_t curSegEnd = 0;
2748 uint32_t curSegIndex = 0;
2749 ld::Internal::FinalSection* curSection = NULL;
2750
2751 const uint64_t deltaBits = 11;
2752 const uint32_t fixupAlignment = _options.makeThreadedStartsSection() ? 4 : 8;
2753 const bool allowThreadsToCrossPages = _options.makeThreadedStartsSection();
2754 std::vector<uint64_t> threadStarts;
2755
2756 // Find the thread starts section
2757 ld::Internal::FinalSection* threadStartsSection = nullptr;
2758 uint64_t threadStartsReservedSpace = 0;
2759 if ( _options.makeThreadedStartsSection() ) {
2760 for (ld::Internal::FinalSection* sect : state.sections) {
2761 if ( sect->type() == ld::Section::typeThreadStarts ) {
2762 threadStartsSection = sect;
2763 break;
2764 }
2765 }
2766 assert(threadStartsSection);
2767 threadStartsReservedSpace = (threadStartsSection->size - 4) / 4;
2768 threadStarts.reserve(threadStartsReservedSpace);
2769 }
2770
2771 auto getAddress = [this](int64_t index) {
2772 if (index <= 0)
2773 return _rebaseInfo[-index]._address;
2774 else
2775 return _bindingInfo[index - 1]._address;
2776 };
2777
2778 if ( (_bindingInfo.size() > 1)
2779 && ! findSegment(state, getAddress(_threadedRebaseBindIndices.front()),
2780 &curSegStart, &curSegEnd, &curSegIndex) )
2781 throw "binding address outside range of any segment";
2782
2783 auto applyBind = [&](int64_t currentIndex, int64_t nextIndex) {
2784 uint64_t currentAddress = getAddress(currentIndex);
2785 uint64_t nextAddress = getAddress(nextIndex);
2786
2787 // The very first pointer we see must be a new chain
2788 if ( _options.makeThreadedStartsSection() && curSection == NULL )
2789 threadStarts.push_back(currentAddress);
2790
2791 if ( (curSection == NULL)
2792 || (currentAddress < curSection->address)
2793 || (currentAddress >= curSection->address+curSection->size) ) {
2794 for (ld::Internal::FinalSection* sect : state.sections) {
2795 if ( (sect->address <= currentAddress)
2796 && (currentAddress < sect->address+sect->size) ) {
2797 curSection = sect;
2798 break;
2799 }
2800 }
2801 }
2802
2803 bool makeChainToNextAddress = true;
2804 if ( allowThreadsToCrossPages ) {
2805 // Even if we allow threads to cross pages, we still need to have the same section.
2806 if ( (nextAddress < curSection->address) || (nextAddress >= curSection->address+curSection->size) )
2807 makeChainToNextAddress = false;
2808 } else {
2809 // If threads can't cross pages then make sure they are on the same page.
2810 uint64_t currentPageIndex = ( currentAddress - curSegStart) / 4096;
2811 uint64_t nextPageIndex = ( nextAddress - curSegStart) / 4096;
2812 if ( currentPageIndex != nextPageIndex )
2813 makeChainToNextAddress = false;
2814 }
2815
2816 uint64_t delta = 0;
2817 if (makeChainToNextAddress) {
2818 delta = nextAddress - currentAddress;
2819
2820 // The value should already be aligned to 4 or 8, so make sure the low bits are zeroes
2821 assert( (delta & (fixupAlignment - 1)) == 0 );
2822 delta /= fixupAlignment;
2823 if ( delta >= (1 << deltaBits) ) {
2824 // Current and next are both in the same segment, so see if they are
2825 // on the same page. If so, patch current to point to next.
2826 makeChainToNextAddress = false;
2827 }
2828 }
2829
2830 if (!makeChainToNextAddress) {
2831 delta = 0;
2832 if (_options.makeThreadedStartsSection())
2833 threadStarts.push_back(nextAddress);
2834 }
2835
2836 uint8_t* lastBindLocation = wholeBuffer + curSection->fileOffset + currentAddress - curSection->address;
2837 switch ( _options.architecture() ) {
2838 case CPU_TYPE_X86_64:
2839 case CPU_TYPE_ARM64:
2840 uint64_t value = 0;
2841 if (currentIndex <= 0) {
2842 // For rebases, bits [0..50] is the mh offset which is already set
2843 // Bit 62 is a 0 to say this is a rebase
2844 value = get64LE(lastBindLocation);
2845#if SUPPORT_ARCH_arm64e
2846 auto fixupOffset = (uintptr_t)(lastBindLocation - mhAddress);
2847 auto it = _authenticatedFixupData.find(fixupOffset);
2848 if (it != _authenticatedFixupData.end()) {
2849 // For authenticated data, we zeroed out the location
2850 assert(value == 0);
2851 const auto &authData = it->second.first;
2852 uint64_t accumulator = it->second.second;
2853 assert(accumulator >= mhAddress);
2854 accumulator -= mhAddress;
2855
2856 // Make sure the high bits aren't set. The low 32-bits may
2857 // be the target value.
2858 assert((accumulator & 0xFFFFFFFF00000000ULL) == 0);
2859 accumulator |= ((uint64_t)authData.discriminator) << 32;
2860 accumulator |= ((uint64_t)authData.hasAddressDiversity) << 48;
2861 accumulator |= ((uint64_t)authData.key) << 49;
2862 // Set the high bit as we are authenticated
2863 accumulator |= 1ULL << 63;
2864
2865 value = accumulator;
2866 } else
2867#endif
2868 {
2869 // Regular pointer which needs to fit in 51-bits of value.
2870 // C++ RTTI uses the top bit, so we'll allow the whole top-byte
2871 // and the bottom 43-bits with sign-extension to be fit in to 51-bits.
2872 uint64_t top8Bits = value & 0xFF00000000000000ULL;
2873 uint64_t bottom43Bits = value & 0x000007FFFFFFFFFFULL;
2874 // Ensure that the sign-extended bottom 43-bits is equivalent in sign to the gap bits
2875 assert( ((value & ~0xFF0003FFFFFFFFFF) == 0) || ((value & ~0xFF0003FFFFFFFFFF) == ~0xFF0003FFFFFFFFFF) );
2876 value = ( top8Bits >> 13 ) | bottom43Bits;
2877 }
2878 } else {
2879 // The ordinal in [0..15]
2880 // Bit 62 is a 1 to say this is a bind
2881 value = get64LE(lastBindLocation);
2882#if SUPPORT_ARCH_arm64e
2883 auto fixupOffset = (uintptr_t)(lastBindLocation - mhAddress);
2884 auto it = _authenticatedFixupData.find(fixupOffset);
2885 if (it != _authenticatedFixupData.end()) {
2886 // For authenticated data, we zeroed out the location
2887 assert(value == 0);
2888 const auto &authData = it->second.first;
2889 uint64_t accumulator = it->second.second;
2890
2891 // Make sure the high bits aren't set. The low 32-bits may
2892 // be the target value.
2893 // Note, this doesn't work for binds to a weak def as we actually
2894 // manage to resolve their address to an address in this binary so
2895 // its not 0.
2896 if (_bindingInfo[currentIndex - 1]._libraryOrdinal == BIND_SPECIAL_DYLIB_WEAK_LOOKUP)
2897 accumulator = 0;
2898 assert((accumulator & 0xFFFFFFFF00000000ULL) == 0);
2899 accumulator |= ((uint64_t)authData.discriminator) << 32;
2900 accumulator |= ((uint64_t)authData.hasAddressDiversity) << 48;
2901 accumulator |= ((uint64_t)authData.key) << 49;
2902 // Set the high bit as we are authenticated
2903 accumulator |= 1ULL << 63;
2904
2905 value = accumulator;
2906 } else
2907#endif
2908 {
2909 // Regular pointer
2910 // The current data is unused as we get a new address from the bind table.
2911 // So zero it out to avoid the bits interfering with the authentication bits.
2912 value = 0;
2913 }
2914 value &= 0xFFFFFFFFFFFF0000;
2915 value |= _bindingInfo[currentIndex - 1]._threadedBindOrdinal;
2916 value |= 1ULL << 62;
2917 }
2918
2919 // The delta is bits [51..61]
2920 value |= ( delta << 51 );
2921 set64LE(lastBindLocation, value);
2922 break;
2923 }
2924 };
2925
2926 // Loop over every value and see if it needs to point to its successor.
2927 // Note that on every iteration, info[i] is already known to be in the current
2928 // segment.
2929 for (int64_t i = 0, e = _threadedRebaseBindIndices.size() - 1; i != e; ++i) {
2930 int64_t currentIndex = _threadedRebaseBindIndices[i];
2931 int64_t nextIndex = _threadedRebaseBindIndices[i + 1];
2932 uint64_t nextAddress = getAddress(nextIndex);
2933 if ( (nextAddress < curSegStart) || ( nextAddress >= curSegEnd) ) {
2934 // The next pointer is in a new segment.
2935 // This means current is the end of a chain, and we need to move
2936 // the segment addresses on to be the next ones.
2937 if ( ! findSegment(state, nextAddress, &curSegStart, &curSegEnd, &curSegIndex) )
2938 throw "binding address outside range of any segment";
2939 }
2940
2941 applyBind(currentIndex, nextIndex);
2942 }
2943
2944 applyBind(_threadedRebaseBindIndices.back(), _threadedRebaseBindIndices.back());
2945
2946 if ( _options.makeThreadedStartsSection() ) {
2947 if ( threadStarts.size() > threadStartsReservedSpace )
2948 throw "overflow in thread starts section";
2949
2950 // Now write over this section content with the new array.
2951 const ld::Atom *threadStartsAtom = nullptr;
2952 for (const ld::Atom *atom : threadStartsSection->atoms) {
2953 if ( (atom->contentType() == ld::Atom::typeSectionStart) || (atom->contentType() == ld::Atom::typeSectionEnd) ) {
2954 assert(atom->size() == 0);
2955 continue;
2956 }
2957 assert(threadStartsAtom == nullptr);
2958 threadStartsAtom = atom;
2959 }
2960 uint64_t threadStartsFileOffset = threadStartsAtom->finalAddress() - threadStartsSection->address + threadStartsSection->fileOffset;
2961 // Skip the header
2962 threadStartsFileOffset += sizeof(uint32_t);
2963 for (uint64_t threadStart : threadStarts) {
2964 uint64_t offset = threadStart - mhAddress;
2965 assert(offset < 0x100000000);
2966 set32LE(&wholeBuffer[threadStartsFileOffset], offset);
2967 threadStartsFileOffset += sizeof(uint32_t);
2968 }
2969 }
2970 }
ebf6f434
A
2971}
2972
ebf6f434
A
2973void OutputFile::computeContentUUID(ld::Internal& state, uint8_t* wholeBuffer)
2974{
2975 const bool log = false;
2976 if ( (_options.outputKind() != Options::kObjectFile) || state.someObjectFileHasDwarf ) {
2977 uint8_t digest[CC_MD5_DIGEST_LENGTH];
eaf282aa
A
2978 std::vector<std::pair<uint64_t, uint64_t>> excludeRegions;
2979 uint64_t bitcodeCmdOffset;
2980 uint64_t bitcodeCmdEnd;
2981 uint64_t bitcodeSectOffset;
2982 uint64_t bitcodePaddingEnd;
2983 if ( _headersAndLoadCommandAtom->bitcodeBundleCommand(bitcodeCmdOffset, bitcodeCmdEnd,
2984 bitcodeSectOffset, bitcodePaddingEnd) ) {
2985 // Exclude embedded bitcode bundle section which contains timestamps in XAR header
2986 // Note the timestamp is in the compressed XML header which means it might change the size of
2987 // bitcode section. The load command which include the size of the section and the padding after
2988 // the bitcode section should also be excluded in the UUID computation.
2989 // Bitcode section should appears before LINKEDIT
2990 // Exclude section cmd
2991 if ( log ) fprintf(stderr, "bundle cmd start=0x%08llX, bundle cmd end=0x%08llX\n",
2992 bitcodeCmdOffset, bitcodeCmdEnd);
2993 excludeRegions.emplace_back(std::pair<uint64_t, uint64_t>(bitcodeCmdOffset, bitcodeCmdEnd));
2994 // Exclude section content
2995 if ( log ) fprintf(stderr, "bundle start=0x%08llX, bundle end=0x%08llX\n",
2996 bitcodeSectOffset, bitcodePaddingEnd);
2997 excludeRegions.emplace_back(std::pair<uint64_t, uint64_t>(bitcodeSectOffset, bitcodePaddingEnd));
2998 }
ebf6f434
A
2999 uint32_t stabsStringsOffsetStart;
3000 uint32_t tabsStringsOffsetEnd;
3001 uint32_t stabsOffsetStart;
3002 uint32_t stabsOffsetEnd;
3003 if ( _symbolTableAtom->hasStabs(stabsStringsOffsetStart, tabsStringsOffsetEnd, stabsOffsetStart, stabsOffsetEnd) ) {
3004 // find two areas of file that are stabs info and should not contribute to checksum
3005 uint64_t stringPoolFileOffset = 0;
3006 uint64_t symbolTableFileOffset = 0;
3007 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
3008 ld::Internal::FinalSection* sect = *sit;
3009 if ( sect->type() == ld::Section::typeLinkEdit ) {
3010 if ( strcmp(sect->sectionName(), "__string_pool") == 0 )
3011 stringPoolFileOffset = sect->fileOffset;
3012 else if ( strcmp(sect->sectionName(), "__symbol_table") == 0 )
3013 symbolTableFileOffset = sect->fileOffset;
a645023d 3014 }
a645023d 3015 }
ebf6f434
A
3016 uint64_t firstStabNlistFileOffset = symbolTableFileOffset + stabsOffsetStart;
3017 uint64_t lastStabNlistFileOffset = symbolTableFileOffset + stabsOffsetEnd;
3018 uint64_t firstStabStringFileOffset = stringPoolFileOffset + stabsStringsOffsetStart;
3019 uint64_t lastStabStringFileOffset = stringPoolFileOffset + tabsStringsOffsetEnd;
0a8dc3df
A
3020 if ( log ) fprintf(stderr, "stabNlist offset=0x%08llX, size=0x%08llX\n", firstStabNlistFileOffset, lastStabNlistFileOffset-firstStabNlistFileOffset);
3021 if ( log ) fprintf(stderr, "stabString offset=0x%08llX, size=0x%08llX\n", firstStabStringFileOffset, lastStabStringFileOffset-firstStabStringFileOffset);
ebf6f434 3022 assert(firstStabNlistFileOffset <= firstStabStringFileOffset);
eaf282aa
A
3023 excludeRegions.emplace_back(std::pair<uint64_t, uint64_t>(firstStabNlistFileOffset, lastStabNlistFileOffset));
3024 excludeRegions.emplace_back(std::pair<uint64_t, uint64_t>(firstStabStringFileOffset, lastStabStringFileOffset));
0a8dc3df
A
3025 // exclude LINKEDIT LC_SEGMENT (size field depends on stabs size)
3026 uint64_t linkeditSegCmdOffset;
3027 uint64_t linkeditSegCmdSize;
3028 _headersAndLoadCommandAtom->linkeditCmdInfo(linkeditSegCmdOffset, linkeditSegCmdSize);
3029 excludeRegions.emplace_back(std::pair<uint64_t, uint64_t>(linkeditSegCmdOffset, linkeditSegCmdOffset+linkeditSegCmdSize));
3030 if ( log ) fprintf(stderr, "linkedit SegCmdOffset=0x%08llX, size=0x%08llX\n", linkeditSegCmdOffset, linkeditSegCmdSize);
3031 uint64_t symbolTableCmdOffset;
3032 uint64_t symbolTableCmdSize;
3033 _headersAndLoadCommandAtom->symbolTableCmdInfo(symbolTableCmdOffset, symbolTableCmdSize);
3034 excludeRegions.emplace_back(std::pair<uint64_t, uint64_t>(symbolTableCmdOffset, symbolTableCmdOffset+symbolTableCmdSize));
3035 if ( log ) fprintf(stderr, "linkedit SegCmdOffset=0x%08llX, size=0x%08llX\n", symbolTableCmdOffset, symbolTableCmdSize);
eaf282aa
A
3036 }
3037 if ( !excludeRegions.empty() ) {
ebf6f434
A
3038 CC_MD5_CTX md5state;
3039 CC_MD5_Init(&md5state);
eaf282aa
A
3040 // rdar://problem/19487042 include the output leaf file name in the hash
3041 const char* lastSlash = strrchr(_options.outputFilePath(), '/');
3042 if ( lastSlash != NULL ) {
3043 CC_MD5_Update(&md5state, lastSlash, strlen(lastSlash));
3044 }
e456bf10
A
3045 // <rdar://problem/38679559> use train name when calculating a binary's UUID
3046 const char* buildName = _options.buildContextName();
3047 if ( buildName != NULL ) {
3048 CC_MD5_Update(&md5state, buildName, strlen(buildName));
3049 }
0a8dc3df 3050 std::sort(excludeRegions.begin(), excludeRegions.end());
eaf282aa
A
3051 uint64_t checksumStart = 0;
3052 for ( auto& region : excludeRegions ) {
3053 uint64_t regionStart = region.first;
3054 uint64_t regionEnd = region.second;
3055 assert(checksumStart <= regionStart && regionStart <= regionEnd && "Region overlapped");
3056 if ( log ) fprintf(stderr, "checksum 0x%08llX -> 0x%08llX\n", checksumStart, regionStart);
3057 CC_MD5_Update(&md5state, &wholeBuffer[checksumStart], regionStart - checksumStart);
3058 checksumStart = regionEnd;
3059 }
3060 if ( log ) fprintf(stderr, "checksum 0x%08llX -> 0x%08llX\n", checksumStart, _fileSize);
3061 CC_MD5_Update(&md5state, &wholeBuffer[checksumStart], _fileSize-checksumStart);
ebf6f434 3062 CC_MD5_Final(digest, &md5state);
eaf282aa 3063 if ( log ) fprintf(stderr, "uuid=%02X, %02X, %02X, %02X, %02X, %02X, %02X, %02X\n", digest[0], digest[1], digest[2],
ebf6f434
A
3064 digest[3], digest[4], digest[5], digest[6], digest[7]);
3065 }
3066 else {
3067 CC_MD5(wholeBuffer, _fileSize, digest);
a645023d 3068 }
ebf6f434
A
3069 // <rdar://problem/6723729> LC_UUID uuids should conform to RFC 4122 UUID version 4 & UUID version 5 formats
3070 digest[6] = ( digest[6] & 0x0F ) | ( 3 << 4 );
3071 digest[8] = ( digest[8] & 0x3F ) | 0x80;
3072 // update buffer with new UUID
3073 _headersAndLoadCommandAtom->setUUID(digest);
3074 _headersAndLoadCommandAtom->recopyUUIDCommand();
a645023d 3075 }
ebf6f434 3076}
eaf282aa
A
3077
3078static int sDescriptorOfPathToRemove = -1;
3079static void removePathAndExit(int sig)
3080{
3081 if ( sDescriptorOfPathToRemove != -1 ) {
3082 char path[MAXPATHLEN];
3083 if ( ::fcntl(sDescriptorOfPathToRemove, F_GETPATH, path) == 0 )
3084 ::unlink(path);
3085 }
3086 fprintf(stderr, "ld: interrupted\n");
3087 exit(1);
3088}
ebf6f434
A
3089
3090void OutputFile::writeOutputFile(ld::Internal& state)
3091{
3092 // for UNIX conformance, error if file exists and is not writable
3093 if ( (access(_options.outputFilePath(), F_OK) == 0) && (access(_options.outputFilePath(), W_OK) == -1) )
3094 throwf("can't write output file: %s", _options.outputFilePath());
a645023d 3095
ebf6f434
A
3096 mode_t permissions = 0777;
3097 if ( _options.outputKind() == Options::kObjectFile )
3098 permissions = 0666;
3099 mode_t umask = ::umask(0);
3100 ::umask(umask); // put back the original umask
3101 permissions &= ~umask;
3102 // Calling unlink first assures the file is gone so that open creates it with correct permissions
3103 // It also handles the case where __options.outputFilePath() file is not writable but its directory is
3104 // And it means we don't have to truncate the file when done writing (in case new is smaller than old)
3105 // Lastly, only delete existing file if it is a normal file (e.g. not /dev/null).
3106 struct stat stat_buf;
d425e388
A
3107 bool outputIsRegularFile = false;
3108 bool outputIsMappableFile = false;
ebf6f434
A
3109 if ( stat(_options.outputFilePath(), &stat_buf) != -1 ) {
3110 if (stat_buf.st_mode & S_IFREG) {
d425e388
A
3111 outputIsRegularFile = true;
3112 // <rdar://problem/12264302> Don't use mmap on non-hfs volumes
3113 struct statfs fsInfo;
3114 if ( statfs(_options.outputFilePath(), &fsInfo) != -1 ) {
82b4b32b 3115 if ( (strcmp(fsInfo.f_fstypename, "hfs") == 0) || (strcmp(fsInfo.f_fstypename, "apfs") == 0) ) {
d425e388
A
3116 (void)unlink(_options.outputFilePath());
3117 outputIsMappableFile = true;
3118 }
3119 }
3120 else {
3121 outputIsMappableFile = false;
3122 }
3123 }
3124 else {
ebf6f434
A
3125 outputIsRegularFile = false;
3126 }
3127 }
d425e388
A
3128 else {
3129 // special files (pipes, devices, etc) must already exist
3130 outputIsRegularFile = true;
3131 // output file does not exist yet
3132 char dirPath[PATH_MAX];
3133 strcpy(dirPath, _options.outputFilePath());
3134 char* end = strrchr(dirPath, '/');
3135 if ( end != NULL ) {
3136 end[1] = '\0';
3137 struct statfs fsInfo;
3138 if ( statfs(dirPath, &fsInfo) != -1 ) {
82b4b32b 3139 if ( (strcmp(fsInfo.f_fstypename, "hfs") == 0) || (strcmp(fsInfo.f_fstypename, "apfs") == 0) ) {
d425e388
A
3140 outputIsMappableFile = true;
3141 }
3142 }
3143 }
3144 }
3145
3146 //fprintf(stderr, "outputIsMappableFile=%d, outputIsRegularFile=%d, path=%s\n", outputIsMappableFile, outputIsRegularFile, _options.outputFilePath());
3147
ebf6f434
A
3148 int fd;
3149 // Construct a temporary path of the form {outputFilePath}.ld_XXXXXX
3150 const char filenameTemplate[] = ".ld_XXXXXX";
3151 char tmpOutput[PATH_MAX];
3152 uint8_t *wholeBuffer;
d425e388 3153 if ( outputIsRegularFile && outputIsMappableFile ) {
eaf282aa
A
3154 // <rdar://problem/20959031> ld64 should clean up temporary files on SIGINT
3155 ::signal(SIGINT, removePathAndExit);
3156
ebf6f434
A
3157 strcpy(tmpOutput, _options.outputFilePath());
3158 // If the path is too long to add a suffix for a temporary name then
3159 // just fall back to using the output path.
3160 if (strlen(tmpOutput)+strlen(filenameTemplate) < PATH_MAX) {
3161 strcat(tmpOutput, filenameTemplate);
3162 fd = mkstemp(tmpOutput);
eaf282aa 3163 sDescriptorOfPathToRemove = fd;
d425e388
A
3164 }
3165 else {
ebf6f434
A
3166 fd = open(tmpOutput, O_RDWR|O_CREAT, permissions);
3167 }
3168 if ( fd == -1 )
f80fe69f
A
3169 throwf("can't open output file for writing '%s', errno=%d", tmpOutput, errno);
3170 if ( ftruncate(fd, _fileSize) == -1 ) {
3171 int err = errno;
3172 unlink(tmpOutput);
3173 if ( err == ENOSPC )
3174 throwf("not enough disk space for writing '%s'", _options.outputFilePath());
3175 else
3176 throwf("can't grow file for writing '%s', errno=%d", _options.outputFilePath(), err);
3177 }
ebf6f434
A
3178
3179 wholeBuffer = (uint8_t *)mmap(NULL, _fileSize, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
3180 if ( wholeBuffer == MAP_FAILED )
3181 throwf("can't create buffer of %llu bytes for output", _fileSize);
d425e388
A
3182 }
3183 else {
3184 if ( outputIsRegularFile )
3185 fd = open(_options.outputFilePath(), O_RDWR|O_CREAT, permissions);
3186 else
3187 fd = open(_options.outputFilePath(), O_WRONLY);
ebf6f434
A
3188 if ( fd == -1 )
3189 throwf("can't open output file for writing: %s, errno=%d", _options.outputFilePath(), errno);
3190 // try to allocate buffer for entire output file content
3191 wholeBuffer = (uint8_t*)calloc(_fileSize, 1);
3192 if ( wholeBuffer == NULL )
3193 throwf("can't create buffer of %llu bytes for output", _fileSize);
3194 }
3195
3196 if ( _options.UUIDMode() == Options::kUUIDRandom ) {
3197 uint8_t bits[16];
3198 ::uuid_generate_random(bits);
3199 _headersAndLoadCommandAtom->setUUID(bits);
3200 }
3201
3202 writeAtoms(state, wholeBuffer);
3203
3204 // compute UUID
3205 if ( _options.UUIDMode() == Options::kUUIDContent )
3206 computeContentUUID(state, wholeBuffer);
3207
d425e388 3208 if ( outputIsRegularFile && outputIsMappableFile ) {
ebf6f434
A
3209 if ( ::chmod(tmpOutput, permissions) == -1 ) {
3210 unlink(tmpOutput);
3211 throwf("can't set permissions on output file: %s, errno=%d", tmpOutput, errno);
3212 }
3213 if ( ::rename(tmpOutput, _options.outputFilePath()) == -1 && strcmp(tmpOutput, _options.outputFilePath()) != 0) {
3214 unlink(tmpOutput);
3215 throwf("can't move output file in place, errno=%d", errno);
3216 }
d425e388
A
3217 }
3218 else {
ebf6f434
A
3219 if ( ::write(fd, wholeBuffer, _fileSize) == -1 ) {
3220 throwf("can't write to output file: %s, errno=%d", _options.outputFilePath(), errno);
3221 }
eaf282aa 3222 sDescriptorOfPathToRemove = -1;
f80fe69f
A
3223 ::close(fd);
3224 // <rdar://problem/13118223> NFS: iOS incremental builds in Xcode 4.6 fail with codesign error
3225 // NFS seems to pad the end of the file sometimes. Calling trunc seems to correct it...
3226 ::truncate(_options.outputFilePath(), _fileSize);
ebf6f434 3227 }
eaf282aa
A
3228
3229 // Rename symbol map file if needed
3230 if ( _options.renameReverseSymbolMap() ) {
3231 assert(_options.hideSymbols() && _options.reverseSymbolMapPath() != NULL && "Must hide symbol and specify a path");
3232 uuid_string_t UUIDString;
3233 const uint8_t* rawUUID = _headersAndLoadCommandAtom->getUUID();
3234 uuid_unparse_upper(rawUUID, UUIDString);
3235 char outputMapPath[PATH_MAX];
3236 sprintf(outputMapPath, "%s/%s.bcsymbolmap", _options.reverseSymbolMapPath(), UUIDString);
3237 if ( ::rename(_options.reverseMapTempPath().c_str(), outputMapPath) != 0 )
3238 throwf("could not create bcsymbolmap file: %s", outputMapPath);
3239 }
a645023d
A
3240}
3241
3242struct AtomByNameSorter
0a8dc3df
A
3243{
3244 bool operator()(const ld::Atom* left, const ld::Atom* right) const
3245 {
3246 return (strcmp(left->name(), right->name()) < 0);
3247 }
3248
3249 bool operator()(const ld::Atom* left, const char* right) const
3250 {
3251 return (strcmp(left->name(), right) < 0);
3252 }
3253
3254 bool operator()(const char* left, const ld::Atom* right) const
3255 {
3256 return (strcmp(left, right->name()) < 0);
3257 }
a645023d
A
3258};
3259
0a8dc3df 3260
afe874b1
A
3261class NotInSet
3262{
3263public:
3264 NotInSet(const std::set<const ld::Atom*>& theSet) : _set(theSet) {}
3265
3266 bool operator()(const ld::Atom* atom) const {
3267 return ( _set.count(atom) == 0 );
3268 }
3269private:
3270 const std::set<const ld::Atom*>& _set;
3271};
3272
3273
a645023d
A
3274void OutputFile::buildSymbolTable(ld::Internal& state)
3275{
3276 unsigned int machoSectionIndex = 0;
3277 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
3278 ld::Internal::FinalSection* sect = *sit;
3279 bool setMachoSectionIndex = !sect->isSectionHidden() && (sect->type() != ld::Section::typeTentativeDefs);
3280 if ( setMachoSectionIndex )
3281 ++machoSectionIndex;
3282 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
3283 const ld::Atom* atom = *ait;
bee7e226 3284 if ( setMachoSectionIndex )
a645023d
A
3285 (const_cast<ld::Atom*>(atom))->setMachoSection(machoSectionIndex);
3286 else if ( sect->type() == ld::Section::typeMachHeader )
3287 (const_cast<ld::Atom*>(atom))->setMachoSection(1); // __mh_execute_header is not in any section by needs n_sect==1
3288 else if ( sect->type() == ld::Section::typeLastSection )
3289 (const_cast<ld::Atom*>(atom))->setMachoSection(machoSectionIndex); // use section index of previous section
3290 else if ( sect->type() == ld::Section::typeFirstSection )
3291 (const_cast<ld::Atom*>(atom))->setMachoSection(machoSectionIndex+1); // use section index of next section
3292
3293 // in -r mode, clarify symbolTableNotInFinalLinkedImages
3294 if ( _options.outputKind() == Options::kObjectFile ) {
0a8dc3df
A
3295 if ( (_options.architecture() == CPU_TYPE_X86_64)
3296 || (_options.architecture() == CPU_TYPE_ARM64)
3297 ) {
a645023d
A
3298 // x86_64 .o files need labels on anonymous literal strings
3299 if ( (sect->type() == ld::Section::typeCString) && (atom->combine() == ld::Atom::combineByNameAndContent) ) {
3300 (const_cast<ld::Atom*>(atom))->setSymbolTableInclusion(ld::Atom::symbolTableIn);
3301 _localAtoms.push_back(atom);
3302 continue;
3303 }
3304 }
3305 if ( sect->type() == ld::Section::typeCFI ) {
3306 if ( _options.removeEHLabels() )
3307 (const_cast<ld::Atom*>(atom))->setSymbolTableInclusion(ld::Atom::symbolTableNotIn);
3308 else
3309 (const_cast<ld::Atom*>(atom))->setSymbolTableInclusion(ld::Atom::symbolTableIn);
3310 }
599556ff
A
3311 else if ( sect->type() == ld::Section::typeTempAlias ) {
3312 assert(_options.outputKind() == Options::kObjectFile);
3313 _importedAtoms.push_back(atom);
3314 continue;
3315 }
a645023d
A
3316 if ( atom->symbolTableInclusion() == ld::Atom::symbolTableNotInFinalLinkedImages )
3317 (const_cast<ld::Atom*>(atom))->setSymbolTableInclusion(ld::Atom::symbolTableIn);
3318 }
3319
3320 // TEMP work around until <rdar://problem/7702923> goes in
3321 if ( (atom->symbolTableInclusion() == ld::Atom::symbolTableInAndNeverStrip)
3322 && (atom->scope() == ld::Atom::scopeLinkageUnit)
3323 && (_options.outputKind() == Options::kDynamicLibrary) ) {
3324 (const_cast<ld::Atom*>(atom))->setScope(ld::Atom::scopeGlobal);
3325 }
3326
3327 // <rdar://problem/6783167> support auto hidden weak symbols: .weak_def_can_be_hidden
3328 if ( atom->autoHide() && (_options.outputKind() != Options::kObjectFile) ) {
3329 // adding auto-hide symbol to .exp file should keep it global
3330 if ( !_options.hasExportMaskList() || !_options.shouldExport(atom->name()) )
3331 (const_cast<ld::Atom*>(atom))->setScope(ld::Atom::scopeLinkageUnit);
3332 }
3333
3334 // <rdar://problem/8626058> ld should consistently warn when resolvers are not exported
3335 if ( (atom->contentType() == ld::Atom::typeResolver) && (atom->scope() == ld::Atom::scopeLinkageUnit) )
3336 warning("resolver functions should be external, but '%s' is hidden", atom->name());
3337
3338 if ( sect->type() == ld::Section::typeImportProxies ) {
3339 if ( atom->combine() == ld::Atom::combineByName )
3340 this->usesWeakExternalSymbols = true;
3341 // alias proxy is a re-export with a name change, don't import changed name
3342 if ( ! atom->isAlias() )
3343 _importedAtoms.push_back(atom);
3344 // scope of proxies are usually linkage unit, so done
3345 // if scope is global, we need to re-export it too
3346 if ( atom->scope() == ld::Atom::scopeGlobal )
3347 _exportedAtoms.push_back(atom);
3348 continue;
3349 }
3350 if ( atom->symbolTableInclusion() == ld::Atom::symbolTableNotInFinalLinkedImages ) {
3351 assert(_options.outputKind() != Options::kObjectFile);
3352 continue; // don't add to symbol table
3353 }
3354 if ( atom->symbolTableInclusion() == ld::Atom::symbolTableNotIn ) {
3355 continue; // don't add to symbol table
3356 }
d425e388
A
3357 if ( (atom->symbolTableInclusion() == ld::Atom::symbolTableInWithRandomAutoStripLabel)
3358 && (_options.outputKind() != Options::kObjectFile) ) {
3359 continue; // don't add to symbol table
3360 }
a645023d
A
3361
3362 if ( (atom->definition() == ld::Atom::definitionTentative) && (_options.outputKind() == Options::kObjectFile) ) {
3363 if ( _options.makeTentativeDefinitionsReal() ) {
3364 // -r -d turns tentative defintions into real def
3365 _exportedAtoms.push_back(atom);
3366 }
3367 else {
3368 // in mach-o object files tentative defintions are stored like undefined symbols
3369 _importedAtoms.push_back(atom);
3370 }
3371 continue;
3372 }
d425e388 3373
a645023d
A
3374 switch ( atom->scope() ) {
3375 case ld::Atom::scopeTranslationUnit:
3376 if ( _options.keepLocalSymbol(atom->name()) ) {
3377 _localAtoms.push_back(atom);
3378 }
3379 else {
3380 if ( _options.outputKind() == Options::kObjectFile ) {
3381 (const_cast<ld::Atom*>(atom))->setSymbolTableInclusion(ld::Atom::symbolTableInWithRandomAutoStripLabel);
3382 _localAtoms.push_back(atom);
3383 }
3384 else
3385 (const_cast<ld::Atom*>(atom))->setSymbolTableInclusion(ld::Atom::symbolTableNotIn);
3386 }
3387 break;
3388 case ld::Atom::scopeGlobal:
3389 _exportedAtoms.push_back(atom);
3390 break;
3391 case ld::Atom::scopeLinkageUnit:
3392 if ( _options.outputKind() == Options::kObjectFile ) {
3393 if ( _options.keepPrivateExterns() ) {
e456bf10
A
3394 if ( atom->symbolTableInclusion() == ld::Atom::symbolTableInWithRandomAutoStripLabel ) {
3395 // <rdar://problem/42150005> ld -r should not promote static 'l' labels to hidden
3396 (const_cast<ld::Atom*>(atom))->setScope(ld::Atom::scopeTranslationUnit);
3397 _localAtoms.push_back(atom);
3398 }
3399 else {
3400 _exportedAtoms.push_back(atom);
3401 }
a645023d
A
3402 }
3403 else if ( _options.keepLocalSymbol(atom->name()) ) {
3404 _localAtoms.push_back(atom);
3405 }
3406 else {
3407 (const_cast<ld::Atom*>(atom))->setSymbolTableInclusion(ld::Atom::symbolTableInWithRandomAutoStripLabel);
3408 _localAtoms.push_back(atom);
3409 }
3410 }
3411 else {
afe874b1
A
3412 if ( _options.keepLocalSymbol(atom->name()) )
3413 _localAtoms.push_back(atom);
3414 // <rdar://problem/5804214> ld should never have a symbol in the non-lazy indirect symbol table with index 0
3415 // this works by making __mh_execute_header be a local symbol which takes symbol index 0
e456bf10 3416 else if ( (atom->symbolTableInclusion() == ld::Atom::symbolTableInAndNeverStrip) && !_options.makeCompressedDyldInfo() && !_options.makeThreadedStartsSection() )
a645023d
A
3417 _localAtoms.push_back(atom);
3418 else
3419 (const_cast<ld::Atom*>(atom))->setSymbolTableInclusion(ld::Atom::symbolTableNotIn);
3420 }
3421 break;
3422 }
3423 }
3424 }
3425
afe874b1
A
3426 // <rdar://problem/6978069> ld adds undefined symbol from .exp file to binary
3427 if ( (_options.outputKind() == Options::kKextBundle) && _options.hasExportRestrictList() ) {
3428 // search for referenced undefines
3429 std::set<const ld::Atom*> referencedProxyAtoms;
3430 for (std::vector<ld::Internal::FinalSection*>::iterator sit=state.sections.begin(); sit != state.sections.end(); ++sit) {
3431 ld::Internal::FinalSection* sect = *sit;
3432 for (std::vector<const ld::Atom*>::iterator ait=sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
3433 const ld::Atom* atom = *ait;
3434 for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
3435 switch ( fit->binding ) {
3436 case ld::Fixup::bindingsIndirectlyBound:
3437 referencedProxyAtoms.insert(state.indirectBindingTable[fit->u.bindingIndex]);
3438 break;
3439 case ld::Fixup::bindingDirectlyBound:
3440 referencedProxyAtoms.insert(fit->u.target);
3441 break;
3442 default:
3443 break;
3444 }
3445 }
3446 }
3447 }
3448 // remove any unreferenced _importedAtoms
3449 _importedAtoms.erase(std::remove_if(_importedAtoms.begin(), _importedAtoms.end(), NotInSet(referencedProxyAtoms)), _importedAtoms.end());
3450 }
3451
a645023d
A
3452 // sort by name
3453 std::sort(_exportedAtoms.begin(), _exportedAtoms.end(), AtomByNameSorter());
3454 std::sort(_importedAtoms.begin(), _importedAtoms.end(), AtomByNameSorter());
0a8dc3df
A
3455
3456 std::map<std::string, std::vector<std::string>> addedSymbols;
3457 std::map<std::string, std::vector<std::string>> hiddenSymbols;
3458 for (const auto *atom : _exportedAtoms) {
3459 // The exported symbols have already been sorted. Early exit the loop
3460 // once we see a symbol that is lexicographically past the special
3461 // linker symbol.
3462 if (atom->name()[0] > '$')
3463 break;
3464
3465 std::string name(atom->name());
3466 if (name.rfind("$ld$add$", 7) == 0) {
3467 auto pos = name.find_first_of('$', 10);
3468 if (pos == std::string::npos) {
3469 warning("bad special linker symbol '%s'", atom->name());
3470 continue;
3471 }
3472 auto &&symbolName = name.substr(pos+1);
3473 auto it = addedSymbols.emplace(symbolName, std::initializer_list<std::string>{name});
3474 if (!it.second)
3475 it.first->second.emplace_back(name);
3476 } else if (name.rfind("$ld$hide$", 8) == 0) {
3477 auto pos = name.find_first_of('$', 11);
3478 if (pos == std::string::npos) {
3479 warning("bad special linker symbol '%s'", atom->name());
3480 continue;
3481 }
3482 auto &&symbolName = name.substr(pos+1);
3483 auto it = hiddenSymbols.emplace(symbolName, std::initializer_list<std::string>{name});
3484 if (!it.second)
3485 it.first->second.emplace_back(name);
3486 }
3487 }
3488
3489 for (const auto &it : addedSymbols) {
3490 if (!std::binary_search(_exportedAtoms.begin(), _exportedAtoms.end(), it.first.c_str(), AtomByNameSorter()))
3491 continue;
3492 for (const auto &symbol : it.second)
3493 warning("linker symbol '%s' adds already existing symbol '%s'", symbol.c_str(), it.first.c_str());
3494 }
3495
3496 auto it = hiddenSymbols.begin();
3497 while (it != hiddenSymbols.end()) {
3498 if (std::binary_search(_exportedAtoms.begin(), _exportedAtoms.end(), it->first.c_str(), AtomByNameSorter()))
3499 it = hiddenSymbols.erase(it);
3500 else
3501 ++it;
3502 }
3503
3504 for (const auto &it : hiddenSymbols) {
3505 for (const auto &symbol : it.second)
3506 warning("linker symbol '%s' hides a non-existent symbol '%s'", symbol.c_str(), it.first.c_str());
3507 }
a645023d
A
3508}
3509
3510void OutputFile::addPreloadLinkEdit(ld::Internal& state)
3511{
3512 switch ( _options.architecture() ) {
ebf6f434 3513#if SUPPORT_ARCH_i386
a645023d
A
3514 case CPU_TYPE_I386:
3515 if ( _hasLocalRelocations ) {
3516 _localRelocsAtom = new LocalRelocationsAtom<x86>(_options, state, *this);
3517 localRelocationsSection = state.addAtom(*_localRelocsAtom);
3518 }
3519 if ( _hasExternalRelocations ) {
3520 _externalRelocsAtom = new ExternalRelocationsAtom<x86>(_options, state, *this);
3521 externalRelocationsSection = state.addAtom(*_externalRelocsAtom);
3522 }
e456bf10
A
3523 if ( _hasDataInCodeInfo ) {
3524 _dataInCodeAtom = new DataInCodeAtom<x86_64>(_options, state, *this);
3525 dataInCodeSection = state.addAtom(*_dataInCodeAtom);
3526 }
a645023d
A
3527 if ( _hasSymbolTable ) {
3528 _indirectSymbolTableAtom = new IndirectSymbolTableAtom<x86>(_options, state, *this);
3529 indirectSymbolTableSection = state.addAtom(*_indirectSymbolTableAtom);
3530 _symbolTableAtom = new SymbolTableAtom<x86>(_options, state, *this);
3531 symbolTableSection = state.addAtom(*_symbolTableAtom);
3532 _stringPoolAtom = new StringPoolAtom(_options, state, *this, 4);
3533 stringPoolSection = state.addAtom(*_stringPoolAtom);
3534 }
3535 break;
ebf6f434
A
3536#endif
3537#if SUPPORT_ARCH_x86_64
a645023d
A
3538 case CPU_TYPE_X86_64:
3539 if ( _hasLocalRelocations ) {
3540 _localRelocsAtom = new LocalRelocationsAtom<x86_64>(_options, state, *this);
3541 localRelocationsSection = state.addAtom(*_localRelocsAtom);
3542 }
3543 if ( _hasExternalRelocations ) {
3544 _externalRelocsAtom = new ExternalRelocationsAtom<x86_64>(_options, state, *this);
3545 externalRelocationsSection = state.addAtom(*_externalRelocsAtom);
3546 }
e456bf10
A
3547 if ( _hasDataInCodeInfo ) {
3548 _dataInCodeAtom = new DataInCodeAtom<x86_64>(_options, state, *this);
3549 dataInCodeSection = state.addAtom(*_dataInCodeAtom);
3550 }
a645023d
A
3551 if ( _hasSymbolTable ) {
3552 _indirectSymbolTableAtom = new IndirectSymbolTableAtom<x86_64>(_options, state, *this);
3553 indirectSymbolTableSection = state.addAtom(*_indirectSymbolTableAtom);
3554 _symbolTableAtom = new SymbolTableAtom<x86_64>(_options, state, *this);
3555 symbolTableSection = state.addAtom(*_symbolTableAtom);
3556 _stringPoolAtom = new StringPoolAtom(_options, state, *this, 4);
3557 stringPoolSection = state.addAtom(*_stringPoolAtom);
3558 }
3559 break;
ebf6f434
A
3560#endif
3561#if SUPPORT_ARCH_arm_any
a645023d
A
3562 case CPU_TYPE_ARM:
3563 if ( _hasLocalRelocations ) {
3564 _localRelocsAtom = new LocalRelocationsAtom<arm>(_options, state, *this);
3565 localRelocationsSection = state.addAtom(*_localRelocsAtom);
3566 }
3567 if ( _hasExternalRelocations ) {
3568 _externalRelocsAtom = new ExternalRelocationsAtom<arm>(_options, state, *this);
3569 externalRelocationsSection = state.addAtom(*_externalRelocsAtom);
3570 }
e456bf10
A
3571 if ( _hasDataInCodeInfo ) {
3572 _dataInCodeAtom = new DataInCodeAtom<x86_64>(_options, state, *this);
3573 dataInCodeSection = state.addAtom(*_dataInCodeAtom);
3574 }
a645023d
A
3575 if ( _hasSymbolTable ) {
3576 _indirectSymbolTableAtom = new IndirectSymbolTableAtom<arm>(_options, state, *this);
3577 indirectSymbolTableSection = state.addAtom(*_indirectSymbolTableAtom);
3578 _symbolTableAtom = new SymbolTableAtom<arm>(_options, state, *this);
3579 symbolTableSection = state.addAtom(*_symbolTableAtom);
3580 _stringPoolAtom = new StringPoolAtom(_options, state, *this, 4);
3581 stringPoolSection = state.addAtom(*_stringPoolAtom);
3582 }
3583 break;
f80fe69f
A
3584#endif
3585#if SUPPORT_ARCH_arm64
3586 case CPU_TYPE_ARM64:
3587 if ( _hasLocalRelocations ) {
3588 _localRelocsAtom = new LocalRelocationsAtom<arm64>(_options, state, *this);
3589 localRelocationsSection = state.addAtom(*_localRelocsAtom);
3590 }
3591 if ( _hasExternalRelocations ) {
3592 _externalRelocsAtom = new ExternalRelocationsAtom<arm64>(_options, state, *this);
3593 externalRelocationsSection = state.addAtom(*_externalRelocsAtom);
3594 }
e456bf10
A
3595 if ( _hasDataInCodeInfo ) {
3596 _dataInCodeAtom = new DataInCodeAtom<x86_64>(_options, state, *this);
3597 dataInCodeSection = state.addAtom(*_dataInCodeAtom);
3598 }
f80fe69f
A
3599 if ( _hasSymbolTable ) {
3600 _indirectSymbolTableAtom = new IndirectSymbolTableAtom<arm64>(_options, state, *this);
3601 indirectSymbolTableSection = state.addAtom(*_indirectSymbolTableAtom);
3602 _symbolTableAtom = new SymbolTableAtom<arm64>(_options, state, *this);
3603 symbolTableSection = state.addAtom(*_symbolTableAtom);
3604 _stringPoolAtom = new StringPoolAtom(_options, state, *this, 4);
3605 stringPoolSection = state.addAtom(*_stringPoolAtom);
3606 }
3607 break;
ebf6f434 3608#endif
a645023d 3609 default:
f80fe69f 3610 throw "-preload not supported";
a645023d
A
3611 }
3612
3613}
3614
3615
3616void OutputFile::addLinkEdit(ld::Internal& state)
3617{
3618 // for historical reasons, -preload orders LINKEDIT content differently
3619 if ( _options.outputKind() == Options::kPreload )
3620 return addPreloadLinkEdit(state);
3621
3622 switch ( _options.architecture() ) {
ebf6f434 3623#if SUPPORT_ARCH_i386
a645023d
A
3624 case CPU_TYPE_I386:
3625 if ( _hasSectionRelocations ) {
3626 _sectionsRelocationsAtom = new SectionRelocationsAtom<x86>(_options, state, *this);
3627 sectionRelocationsSection = state.addAtom(*_sectionsRelocationsAtom);
3628 }
3629 if ( _hasDyldInfo ) {
3630 _rebasingInfoAtom = new RebaseInfoAtom<x86>(_options, state, *this);
3631 rebaseSection = state.addAtom(*_rebasingInfoAtom);
3632
3633 _bindingInfoAtom = new BindingInfoAtom<x86>(_options, state, *this);
3634 bindingSection = state.addAtom(*_bindingInfoAtom);
3635
3636 _weakBindingInfoAtom = new WeakBindingInfoAtom<x86>(_options, state, *this);
3637 weakBindingSection = state.addAtom(*_weakBindingInfoAtom);
3638
3639 _lazyBindingInfoAtom = new LazyBindingInfoAtom<x86>(_options, state, *this);
3640 lazyBindingSection = state.addAtom(*_lazyBindingInfoAtom);
3641
3642 _exportInfoAtom = new ExportInfoAtom<x86>(_options, state, *this);
3643 exportSection = state.addAtom(*_exportInfoAtom);
3644 }
3645 if ( _hasLocalRelocations ) {
3646 _localRelocsAtom = new LocalRelocationsAtom<x86>(_options, state, *this);
3647 localRelocationsSection = state.addAtom(*_localRelocsAtom);
3648 }
3649 if ( _hasSplitSegInfo ) {
0a8dc3df
A
3650 if ( _options.sharedRegionEncodingV2() )
3651 _splitSegInfoAtom = new SplitSegInfoV2Atom<x86>(_options, state, *this);
3652 else
3653 _splitSegInfoAtom = new SplitSegInfoV1Atom<x86>(_options, state, *this);
a645023d
A
3654 splitSegInfoSection = state.addAtom(*_splitSegInfoAtom);
3655 }
3656 if ( _hasFunctionStartsInfo ) {
3657 _functionStartsAtom = new FunctionStartsAtom<x86>(_options, state, *this);
3658 functionStartsSection = state.addAtom(*_functionStartsAtom);
3659 }
ebf6f434
A
3660 if ( _hasDataInCodeInfo ) {
3661 _dataInCodeAtom = new DataInCodeAtom<x86>(_options, state, *this);
3662 dataInCodeSection = state.addAtom(*_dataInCodeAtom);
3663 }
9543cb2f
A
3664 if ( _hasOptimizationHints ) {
3665 _optimizationHintsAtom = new OptimizationHintsAtom<x86>(_options, state, *this);
3666 optimizationHintsSection = state.addAtom(*_optimizationHintsAtom);
3667 }
a645023d
A
3668 if ( _hasSymbolTable ) {
3669 _symbolTableAtom = new SymbolTableAtom<x86>(_options, state, *this);
3670 symbolTableSection = state.addAtom(*_symbolTableAtom);
3671 }
3672 if ( _hasExternalRelocations ) {
3673 _externalRelocsAtom = new ExternalRelocationsAtom<x86>(_options, state, *this);
3674 externalRelocationsSection = state.addAtom(*_externalRelocsAtom);
3675 }
3676 if ( _hasSymbolTable ) {
3677 _indirectSymbolTableAtom = new IndirectSymbolTableAtom<x86>(_options, state, *this);
3678 indirectSymbolTableSection = state.addAtom(*_indirectSymbolTableAtom);
3679 _stringPoolAtom = new StringPoolAtom(_options, state, *this, 4);
3680 stringPoolSection = state.addAtom(*_stringPoolAtom);
3681 }
3682 break;
ebf6f434
A
3683#endif
3684#if SUPPORT_ARCH_x86_64
a645023d
A
3685 case CPU_TYPE_X86_64:
3686 if ( _hasSectionRelocations ) {
3687 _sectionsRelocationsAtom = new SectionRelocationsAtom<x86_64>(_options, state, *this);
3688 sectionRelocationsSection = state.addAtom(*_sectionsRelocationsAtom);
3689 }
3690 if ( _hasDyldInfo ) {
3691 _rebasingInfoAtom = new RebaseInfoAtom<x86_64>(_options, state, *this);
3692 rebaseSection = state.addAtom(*_rebasingInfoAtom);
3693
3694 _bindingInfoAtom = new BindingInfoAtom<x86_64>(_options, state, *this);
3695 bindingSection = state.addAtom(*_bindingInfoAtom);
3696
3697 _weakBindingInfoAtom = new WeakBindingInfoAtom<x86_64>(_options, state, *this);
3698 weakBindingSection = state.addAtom(*_weakBindingInfoAtom);
3699
3700 _lazyBindingInfoAtom = new LazyBindingInfoAtom<x86_64>(_options, state, *this);
3701 lazyBindingSection = state.addAtom(*_lazyBindingInfoAtom);
3702
3703 _exportInfoAtom = new ExportInfoAtom<x86_64>(_options, state, *this);
3704 exportSection = state.addAtom(*_exportInfoAtom);
3705 }
3706 if ( _hasLocalRelocations ) {
3707 _localRelocsAtom = new LocalRelocationsAtom<x86_64>(_options, state, *this);
3708 localRelocationsSection = state.addAtom(*_localRelocsAtom);
3709 }
3710 if ( _hasSplitSegInfo ) {
0a8dc3df
A
3711 if ( _options.sharedRegionEncodingV2() )
3712 _splitSegInfoAtom = new SplitSegInfoV2Atom<x86_64>(_options, state, *this);
3713 else
3714 _splitSegInfoAtom = new SplitSegInfoV1Atom<x86_64>(_options, state, *this);
a645023d
A
3715 splitSegInfoSection = state.addAtom(*_splitSegInfoAtom);
3716 }
3717 if ( _hasFunctionStartsInfo ) {
3718 _functionStartsAtom = new FunctionStartsAtom<x86_64>(_options, state, *this);
3719 functionStartsSection = state.addAtom(*_functionStartsAtom);
3720 }
ebf6f434
A
3721 if ( _hasDataInCodeInfo ) {
3722 _dataInCodeAtom = new DataInCodeAtom<x86_64>(_options, state, *this);
3723 dataInCodeSection = state.addAtom(*_dataInCodeAtom);
3724 }
9543cb2f
A
3725 if ( _hasOptimizationHints ) {
3726 _optimizationHintsAtom = new OptimizationHintsAtom<x86_64>(_options, state, *this);
3727 optimizationHintsSection = state.addAtom(*_optimizationHintsAtom);
3728 }
a645023d
A
3729 if ( _hasSymbolTable ) {
3730 _symbolTableAtom = new SymbolTableAtom<x86_64>(_options, state, *this);
3731 symbolTableSection = state.addAtom(*_symbolTableAtom);
3732 }
3733 if ( _hasExternalRelocations ) {
3734 _externalRelocsAtom = new ExternalRelocationsAtom<x86_64>(_options, state, *this);
3735 externalRelocationsSection = state.addAtom(*_externalRelocsAtom);
3736 }
3737 if ( _hasSymbolTable ) {
3738 _indirectSymbolTableAtom = new IndirectSymbolTableAtom<x86_64>(_options, state, *this);
3739 indirectSymbolTableSection = state.addAtom(*_indirectSymbolTableAtom);
3740 _stringPoolAtom = new StringPoolAtom(_options, state, *this, 8);
3741 stringPoolSection = state.addAtom(*_stringPoolAtom);
3742 }
3743 break;
ebf6f434
A
3744#endif
3745#if SUPPORT_ARCH_arm_any
a645023d
A
3746 case CPU_TYPE_ARM:
3747 if ( _hasSectionRelocations ) {
3748 _sectionsRelocationsAtom = new SectionRelocationsAtom<arm>(_options, state, *this);
3749 sectionRelocationsSection = state.addAtom(*_sectionsRelocationsAtom);
3750 }
3751 if ( _hasDyldInfo ) {
3752 _rebasingInfoAtom = new RebaseInfoAtom<arm>(_options, state, *this);
3753 rebaseSection = state.addAtom(*_rebasingInfoAtom);
3754
3755 _bindingInfoAtom = new BindingInfoAtom<arm>(_options, state, *this);
3756 bindingSection = state.addAtom(*_bindingInfoAtom);
3757
3758 _weakBindingInfoAtom = new WeakBindingInfoAtom<arm>(_options, state, *this);
3759 weakBindingSection = state.addAtom(*_weakBindingInfoAtom);
3760
3761 _lazyBindingInfoAtom = new LazyBindingInfoAtom<arm>(_options, state, *this);
3762 lazyBindingSection = state.addAtom(*_lazyBindingInfoAtom);
3763
3764 _exportInfoAtom = new ExportInfoAtom<arm>(_options, state, *this);
3765 exportSection = state.addAtom(*_exportInfoAtom);
3766 }
3767 if ( _hasLocalRelocations ) {
3768 _localRelocsAtom = new LocalRelocationsAtom<arm>(_options, state, *this);
3769 localRelocationsSection = state.addAtom(*_localRelocsAtom);
3770 }
3771 if ( _hasSplitSegInfo ) {
eaf282aa
A
3772 if ( _options.sharedRegionEncodingV2() )
3773 _splitSegInfoAtom = new SplitSegInfoV2Atom<arm>(_options, state, *this);
3774 else
3775 _splitSegInfoAtom = new SplitSegInfoV1Atom<arm>(_options, state, *this);
a645023d
A
3776 splitSegInfoSection = state.addAtom(*_splitSegInfoAtom);
3777 }
3778 if ( _hasFunctionStartsInfo ) {
3779 _functionStartsAtom = new FunctionStartsAtom<arm>(_options, state, *this);
3780 functionStartsSection = state.addAtom(*_functionStartsAtom);
3781 }
ebf6f434
A
3782 if ( _hasDataInCodeInfo ) {
3783 _dataInCodeAtom = new DataInCodeAtom<arm>(_options, state, *this);
3784 dataInCodeSection = state.addAtom(*_dataInCodeAtom);
3785 }
9543cb2f
A
3786 if ( _hasOptimizationHints ) {
3787 _optimizationHintsAtom = new OptimizationHintsAtom<arm>(_options, state, *this);
3788 optimizationHintsSection = state.addAtom(*_optimizationHintsAtom);
3789 }
a645023d
A
3790 if ( _hasSymbolTable ) {
3791 _symbolTableAtom = new SymbolTableAtom<arm>(_options, state, *this);
3792 symbolTableSection = state.addAtom(*_symbolTableAtom);
3793 }
3794 if ( _hasExternalRelocations ) {
3795 _externalRelocsAtom = new ExternalRelocationsAtom<arm>(_options, state, *this);
3796 externalRelocationsSection = state.addAtom(*_externalRelocsAtom);
3797 }
3798 if ( _hasSymbolTable ) {
3799 _indirectSymbolTableAtom = new IndirectSymbolTableAtom<arm>(_options, state, *this);
3800 indirectSymbolTableSection = state.addAtom(*_indirectSymbolTableAtom);
3801 _stringPoolAtom = new StringPoolAtom(_options, state, *this, 4);
3802 stringPoolSection = state.addAtom(*_stringPoolAtom);
3803 }
3804 break;
f80fe69f
A
3805#endif
3806#if SUPPORT_ARCH_arm64
3807 case CPU_TYPE_ARM64:
3808 if ( _hasSectionRelocations ) {
3809 _sectionsRelocationsAtom = new SectionRelocationsAtom<arm64>(_options, state, *this);
3810 sectionRelocationsSection = state.addAtom(*_sectionsRelocationsAtom);
3811 }
3812 if ( _hasDyldInfo ) {
3813 _rebasingInfoAtom = new RebaseInfoAtom<arm64>(_options, state, *this);
3814 rebaseSection = state.addAtom(*_rebasingInfoAtom);
3815
3816 _bindingInfoAtom = new BindingInfoAtom<arm64>(_options, state, *this);
3817 bindingSection = state.addAtom(*_bindingInfoAtom);
3818
3819 _weakBindingInfoAtom = new WeakBindingInfoAtom<arm64>(_options, state, *this);
3820 weakBindingSection = state.addAtom(*_weakBindingInfoAtom);
3821
3822 _lazyBindingInfoAtom = new LazyBindingInfoAtom<arm64>(_options, state, *this);
3823 lazyBindingSection = state.addAtom(*_lazyBindingInfoAtom);
3824
3825 _exportInfoAtom = new ExportInfoAtom<arm64>(_options, state, *this);
3826 exportSection = state.addAtom(*_exportInfoAtom);
3827 }
3828 if ( _hasLocalRelocations ) {
3829 _localRelocsAtom = new LocalRelocationsAtom<arm64>(_options, state, *this);
3830 localRelocationsSection = state.addAtom(*_localRelocsAtom);
3831 }
3832 if ( _hasSplitSegInfo ) {
eaf282aa
A
3833 if ( _options.sharedRegionEncodingV2() )
3834 _splitSegInfoAtom = new SplitSegInfoV2Atom<arm64>(_options, state, *this);
3835 else
3836 _splitSegInfoAtom = new SplitSegInfoV1Atom<arm64>(_options, state, *this);
f80fe69f
A
3837 splitSegInfoSection = state.addAtom(*_splitSegInfoAtom);
3838 }
3839 if ( _hasFunctionStartsInfo ) {
3840 _functionStartsAtom = new FunctionStartsAtom<arm64>(_options, state, *this);
3841 functionStartsSection = state.addAtom(*_functionStartsAtom);
3842 }
3843 if ( _hasDataInCodeInfo ) {
3844 _dataInCodeAtom = new DataInCodeAtom<arm64>(_options, state, *this);
3845 dataInCodeSection = state.addAtom(*_dataInCodeAtom);
3846 }
9543cb2f
A
3847 if ( _hasOptimizationHints ) {
3848 _optimizationHintsAtom = new OptimizationHintsAtom<arm64>(_options, state, *this);
3849 optimizationHintsSection = state.addAtom(*_optimizationHintsAtom);
3850 }
f80fe69f
A
3851 if ( _hasSymbolTable ) {
3852 _symbolTableAtom = new SymbolTableAtom<arm64>(_options, state, *this);
3853 symbolTableSection = state.addAtom(*_symbolTableAtom);
3854 }
3855 if ( _hasExternalRelocations ) {
3856 _externalRelocsAtom = new ExternalRelocationsAtom<arm64>(_options, state, *this);
3857 externalRelocationsSection = state.addAtom(*_externalRelocsAtom);
3858 }
3859 if ( _hasSymbolTable ) {
3860 _indirectSymbolTableAtom = new IndirectSymbolTableAtom<arm64>(_options, state, *this);
3861 indirectSymbolTableSection = state.addAtom(*_indirectSymbolTableAtom);
3862 _stringPoolAtom = new StringPoolAtom(_options, state, *this, 4);
3863 stringPoolSection = state.addAtom(*_stringPoolAtom);
3864 }
3865 break;
ebf6f434 3866#endif
a645023d
A
3867 default:
3868 throw "unknown architecture";
3869 }
3870}
3871
3872void OutputFile::addLoadCommands(ld::Internal& state)
3873{
3874 switch ( _options.architecture() ) {
ebf6f434 3875#if SUPPORT_ARCH_x86_64
a645023d
A
3876 case CPU_TYPE_X86_64:
3877 _headersAndLoadCommandAtom = new HeaderAndLoadCommandsAtom<x86_64>(_options, state, *this);
3878 headerAndLoadCommandsSection = state.addAtom(*_headersAndLoadCommandAtom);
3879 break;
ebf6f434
A
3880#endif
3881#if SUPPORT_ARCH_arm_any
a645023d
A
3882 case CPU_TYPE_ARM:
3883 _headersAndLoadCommandAtom = new HeaderAndLoadCommandsAtom<arm>(_options, state, *this);
3884 headerAndLoadCommandsSection = state.addAtom(*_headersAndLoadCommandAtom);
3885 break;
ebf6f434 3886#endif
f80fe69f
A
3887#if SUPPORT_ARCH_arm64
3888 case CPU_TYPE_ARM64:
3889 _headersAndLoadCommandAtom = new HeaderAndLoadCommandsAtom<arm64>(_options, state, *this);
3890 headerAndLoadCommandsSection = state.addAtom(*_headersAndLoadCommandAtom);
3891 break;
3892#endif
ebf6f434 3893#if SUPPORT_ARCH_i386
a645023d
A
3894 case CPU_TYPE_I386:
3895 _headersAndLoadCommandAtom = new HeaderAndLoadCommandsAtom<x86>(_options, state, *this);
3896 headerAndLoadCommandsSection = state.addAtom(*_headersAndLoadCommandAtom);
3897 break;
ebf6f434 3898#endif
a645023d
A
3899 default:
3900 throw "unknown architecture";
3901 }
3902}
3903
3904uint32_t OutputFile::dylibCount()
3905{
3906 return _dylibsToLoad.size();
3907}
3908
3909const ld::dylib::File* OutputFile::dylibByOrdinal(unsigned int ordinal)
3910{
3911 assert( ordinal > 0 );
3912 assert( ordinal <= _dylibsToLoad.size() );
3913 return _dylibsToLoad[ordinal-1];
3914}
3915
3916bool OutputFile::hasOrdinalForInstallPath(const char* path, int* ordinal)
3917{
3918 for (std::map<const ld::dylib::File*, int>::const_iterator it = _dylibToOrdinal.begin(); it != _dylibToOrdinal.end(); ++it) {
3919 const char* installPath = it->first->installPath();
3920 if ( (installPath != NULL) && (strcmp(path, installPath) == 0) ) {
3921 *ordinal = it->second;
3922 return true;
3923 }
3924 }
3925 return false;
3926}
3927
3928uint32_t OutputFile::dylibToOrdinal(const ld::dylib::File* dylib)
3929{
3930 return _dylibToOrdinal[dylib];
3931}
3932
3933
3934void OutputFile::buildDylibOrdinalMapping(ld::Internal& state)
3935{
3936 // count non-public re-exported dylibs
3937 unsigned int nonPublicReExportCount = 0;
3938 for (std::vector<ld::dylib::File*>::iterator it = state.dylibs.begin(); it != state.dylibs.end(); ++it) {
3939 ld::dylib::File* aDylib = *it;
3940 if ( aDylib->willBeReExported() && ! aDylib->hasPublicInstallName() )
3941 ++nonPublicReExportCount;
3942 }
3943
3944 // look at each dylib supplied in state
3945 bool hasReExports = false;
3946 bool haveLazyDylibs = false;
3947 for (std::vector<ld::dylib::File*>::iterator it = state.dylibs.begin(); it != state.dylibs.end(); ++it) {
3948 ld::dylib::File* aDylib = *it;
3949 int ordinal;
3950 if ( aDylib == state.bundleLoader ) {
3951 _dylibToOrdinal[aDylib] = BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE;
3952 }
3953 else if ( this->hasOrdinalForInstallPath(aDylib->installPath(), &ordinal) ) {
3954 // already have a dylib with that install path, map all uses to that ordinal
3955 _dylibToOrdinal[aDylib] = ordinal;
3956 }
3957 else if ( aDylib->willBeLazyLoadedDylib() ) {
3958 // all lazy dylib need to be at end of ordinals
3959 haveLazyDylibs = true;
3960 }
3961 else if ( aDylib->willBeReExported() && ! aDylib->hasPublicInstallName() && (nonPublicReExportCount >= 2) ) {
3962 _dylibsToLoad.push_back(aDylib);
3963 _dylibToOrdinal[aDylib] = BIND_SPECIAL_DYLIB_SELF;
3964 }
3965 else {
3966 // first time this install path seen, create new ordinal
3967 _dylibsToLoad.push_back(aDylib);
3968 _dylibToOrdinal[aDylib] = _dylibsToLoad.size();
3969 }
3970 if ( aDylib->explicitlyLinked() && aDylib->willBeReExported() )
3971 hasReExports = true;
3972 }
3973 if ( haveLazyDylibs ) {
3974 // second pass to determine ordinals for lazy loaded dylibs
3975 for (std::vector<ld::dylib::File*>::iterator it = state.dylibs.begin(); it != state.dylibs.end(); ++it) {
3976 ld::dylib::File* aDylib = *it;
3977 if ( aDylib->willBeLazyLoadedDylib() ) {
3978 int ordinal;
3979 if ( this->hasOrdinalForInstallPath(aDylib->installPath(), &ordinal) ) {
3980 // already have a dylib with that install path, map all uses to that ordinal
3981 _dylibToOrdinal[aDylib] = ordinal;
3982 }
3983 else {
3984 // first time this install path seen, create new ordinal
3985 _dylibsToLoad.push_back(aDylib);
3986 _dylibToOrdinal[aDylib] = _dylibsToLoad.size();
3987 }
3988 }
3989 }
3990 }
3991 _noReExportedDylibs = !hasReExports;
3992 //fprintf(stderr, "dylibs:\n");
3993 //for (std::map<const ld::dylib::File*, int>::const_iterator it = _dylibToOrdinal.begin(); it != _dylibToOrdinal.end(); ++it) {
3994 // fprintf(stderr, " %p ord=%u, install_name=%s\n",it->first, it->second, it->first->installPath());
3995 //}
3996}
3997
3998uint32_t OutputFile::lazyBindingInfoOffsetForLazyPointerAddress(uint64_t lpAddress)
3999{
4000 return _lazyPointerAddressToInfoOffset[lpAddress];
4001}
4002
4003void OutputFile::setLazyBindingInfoOffset(uint64_t lpAddress, uint32_t lpInfoOffset)
4004{
4005 _lazyPointerAddressToInfoOffset[lpAddress] = lpInfoOffset;
4006}
4007
4008int OutputFile::compressedOrdinalForAtom(const ld::Atom* target)
4009{
4010 // flat namespace images use zero for all ordinals
4011 if ( _options.nameSpace() != Options::kTwoLevelNameSpace )
4012 return BIND_SPECIAL_DYLIB_FLAT_LOOKUP;
4013
4014 // handle -interposable
4015 if ( target->definition() == ld::Atom::definitionRegular )
4016 return BIND_SPECIAL_DYLIB_SELF;
4017
4018 // regular ordinal
4019 const ld::dylib::File* dylib = dynamic_cast<const ld::dylib::File*>(target->file());
d425e388
A
4020 if ( dylib != NULL ) {
4021 std::map<const ld::dylib::File*, int>::iterator pos = _dylibToOrdinal.find(dylib);
4022 if ( pos != _dylibToOrdinal.end() )
4023 return pos->second;
4024 assert(0 && "dylib not assigned ordinal");
4025 }
4026
a645023d
A
4027 // handle undefined dynamic_lookup
4028 if ( _options.undefinedTreatment() == Options::kUndefinedDynamicLookup )
4029 return BIND_SPECIAL_DYLIB_FLAT_LOOKUP;
4030
4031 // handle -U _foo
4032 if ( _options.allowedUndefined(target->name()) )
4033 return BIND_SPECIAL_DYLIB_FLAT_LOOKUP;
4034
4035 throw "can't find ordinal for imported symbol";
4036}
4037
4038
e456bf10 4039bool OutputFile::isPcRelStore(const ld::Fixup* fixup)
a645023d 4040{
e456bf10 4041 return fixup->isPcRelStore(_options.outputKind() == Options::kKextBundle);
a645023d
A
4042}
4043
4044bool OutputFile::isStore(ld::Fixup::Kind kind)
4045{
4046 switch ( kind ) {
4047 case ld::Fixup::kindNone:
4048 case ld::Fixup::kindNoneFollowOn:
4049 case ld::Fixup::kindNoneGroupSubordinate:
4050 case ld::Fixup::kindNoneGroupSubordinateFDE:
4051 case ld::Fixup::kindNoneGroupSubordinateLSDA:
4052 case ld::Fixup::kindNoneGroupSubordinatePersonality:
4053 case ld::Fixup::kindSetTargetAddress:
4054 case ld::Fixup::kindSubtractTargetAddress:
4055 case ld::Fixup::kindAddAddend:
4056 case ld::Fixup::kindSubtractAddend:
4057 case ld::Fixup::kindSetTargetImageOffset:
4058 case ld::Fixup::kindSetTargetSectionOffset:
e456bf10
A
4059#if SUPPORT_ARCH_arm64e
4060 case ld::Fixup::kindSetAuthData:
4061#endif
a645023d
A
4062 return false;
4063 default:
4064 break;
4065 }
4066 return true;
4067}
4068
4069
e456bf10 4070bool OutputFile::setsTarget(const ld::Fixup &fixup)
a645023d 4071{
e456bf10 4072 return fixup.setsTarget(_options.outputKind() == Options::kObjectFile);
a645023d
A
4073}
4074
4075bool OutputFile::isPointerToTarget(ld::Fixup::Kind kind)
4076{
4077 switch ( kind ) {
4078 case ld::Fixup::kindSetTargetAddress:
4079 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
4080 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
e456bf10
A
4081#if SUPPORT_ARCH_arm64e
4082 case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64:
4083#endif
a645023d
A
4084 case ld::Fixup::kindStoreTargetAddressBigEndian32:
4085 case ld::Fixup::kindStoreTargetAddressBigEndian64:
4086 case ld::Fixup::kindLazyTarget:
4087 return true;
4088 default:
4089 break;
4090 }
4091 return false;
4092}
4093bool OutputFile::isPointerFromTarget(ld::Fixup::Kind kind)
4094{
4095 switch ( kind ) {
4096 case ld::Fixup::kindSubtractTargetAddress:
4097 return true;
4098 default:
4099 break;
4100 }
4101 return false;
4102}
4103
4104
4105uint64_t OutputFile::lookBackAddend(ld::Fixup::iterator fit)
4106{
4107 uint64_t addend = 0;
4108 switch ( fit->clusterSize ) {
4109 case ld::Fixup::k1of1:
4110 case ld::Fixup::k1of2:
4111 case ld::Fixup::k2of2:
4112 break;
4113 case ld::Fixup::k2of3:
4114 --fit;
4115 switch ( fit->kind ) {
4116 case ld::Fixup::kindAddAddend:
4117 addend += fit->u.addend;
4118 break;
4119 case ld::Fixup::kindSubtractAddend:
4120 addend -= fit->u.addend;
4121 break;
4122 default:
4123 throw "unexpected fixup kind for binding";
4124 }
4125 break;
4126 case ld::Fixup::k1of3:
4127 ++fit;
4128 switch ( fit->kind ) {
4129 case ld::Fixup::kindAddAddend:
4130 addend += fit->u.addend;
4131 break;
4132 case ld::Fixup::kindSubtractAddend:
4133 addend -= fit->u.addend;
4134 break;
4135 default:
4136 throw "unexpected fixup kind for binding";
4137 }
4138 break;
4139 default:
4140 throw "unexpected fixup cluster size for binding";
4141 }
4142 return addend;
4143}
4144
4145
a645023d
A
4146void OutputFile::generateLinkEditInfo(ld::Internal& state)
4147{
4148 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
4149 ld::Internal::FinalSection* sect = *sit;
9543cb2f 4150 // record end of last __TEXT section encrypted iPhoneOS apps.
0a8dc3df 4151 if ( _options.makeEncryptable() && (strcmp(sect->segmentName(), "__TEXT") == 0) && (strcmp(sect->sectionName(), "__oslogstring") != 0) ) {
9543cb2f
A
4152 _encryptedTEXTendOffset = pageAlign(sect->fileOffset + sect->size);
4153 }
a645023d
A
4154 bool objc1ClassRefSection = ( (sect->type() == ld::Section::typeCStringPointer)
4155 && (strcmp(sect->sectionName(), "__cls_refs") == 0)
4156 && (strcmp(sect->segmentName(), "__OBJC") == 0) );
4157 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
4158 const ld::Atom* atom = *ait;
4159
4160 // Record regular atoms that override a dylib's weak definitions
4161 if ( (atom->scope() == ld::Atom::scopeGlobal) && atom->overridesDylibsWeakDef() ) {
4162 if ( _options.makeCompressedDyldInfo() ) {
4163 uint8_t wtype = BIND_TYPE_OVERRIDE_OF_WEAKDEF_IN_DYLIB;
4164 bool nonWeakDef = (atom->combine() == ld::Atom::combineNever);
e456bf10
A
4165 // Don't push weak binding info for threaded bind.
4166 // Instead we use a special ordinal in the regular bind info
4167 if ( !_options.useLinkedListBinding() )
4168 _weakBindingInfo.push_back(BindingInfo(wtype, atom->name(), nonWeakDef, atom->finalAddress(), 0));
a645023d
A
4169 }
4170 this->overridesWeakExternalSymbols = true;
4171 if ( _options.warnWeakExports() )
4172 warning("overrides weak external symbol: %s", atom->name());
4173 }
4174
4175 ld::Fixup* fixupWithTarget = NULL;
4176 ld::Fixup* fixupWithMinusTarget = NULL;
4177 ld::Fixup* fixupWithStore = NULL;
f80fe69f 4178 ld::Fixup* fixupWithAddend = NULL;
a645023d
A
4179 const ld::Atom* target = NULL;
4180 const ld::Atom* minusTarget = NULL;
4181 uint64_t targetAddend = 0;
4182 uint64_t minusTargetAddend = 0;
e456bf10
A
4183#if SUPPORT_ARCH_arm64e
4184 ld::Fixup* fixupWithAuthData = NULL;
4185#endif
a645023d
A
4186 for (ld::Fixup::iterator fit = atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
4187 if ( fit->firstInCluster() ) {
4188 fixupWithTarget = NULL;
4189 fixupWithMinusTarget = NULL;
4190 fixupWithStore = NULL;
4191 target = NULL;
4192 minusTarget = NULL;
4193 targetAddend = 0;
4194 minusTargetAddend = 0;
4195 }
e456bf10 4196 if ( this->setsTarget(*fit) ) {
a645023d
A
4197 switch ( fit->binding ) {
4198 case ld::Fixup::bindingNone:
4199 case ld::Fixup::bindingByNameUnbound:
4200 break;
4201 case ld::Fixup::bindingByContentBound:
4202 case ld::Fixup::bindingDirectlyBound:
4203 fixupWithTarget = fit;
4204 target = fit->u.target;
4205 break;
4206 case ld::Fixup::bindingsIndirectlyBound:
4207 fixupWithTarget = fit;
4208 target = state.indirectBindingTable[fit->u.bindingIndex];
4209 break;
4210 }
4211 assert(target != NULL);
4212 }
4213 switch ( fit->kind ) {
4214 case ld::Fixup::kindAddAddend:
4215 targetAddend = fit->u.addend;
f80fe69f 4216 fixupWithAddend = fit;
a645023d
A
4217 break;
4218 case ld::Fixup::kindSubtractAddend:
4219 minusTargetAddend = fit->u.addend;
f80fe69f 4220 fixupWithAddend = fit;
a645023d
A
4221 break;
4222 case ld::Fixup::kindSubtractTargetAddress:
4223 switch ( fit->binding ) {
4224 case ld::Fixup::bindingNone:
4225 case ld::Fixup::bindingByNameUnbound:
4226 break;
4227 case ld::Fixup::bindingByContentBound:
4228 case ld::Fixup::bindingDirectlyBound:
4229 fixupWithMinusTarget = fit;
4230 minusTarget = fit->u.target;
4231 break;
4232 case ld::Fixup::bindingsIndirectlyBound:
4233 fixupWithMinusTarget = fit;
4234 minusTarget = state.indirectBindingTable[fit->u.bindingIndex];
4235 break;
4236 }
4237 assert(minusTarget != NULL);
4238 break;
ebf6f434
A
4239 case ld::Fixup::kindDataInCodeStartData:
4240 case ld::Fixup::kindDataInCodeStartJT8:
4241 case ld::Fixup::kindDataInCodeStartJT16:
4242 case ld::Fixup::kindDataInCodeStartJT32:
4243 case ld::Fixup::kindDataInCodeStartJTA32:
4244 case ld::Fixup::kindDataInCodeEnd:
4245 hasDataInCode = true;
4246 break;
e456bf10
A
4247#if SUPPORT_ARCH_arm64e
4248 case ld::Fixup::kindSetAuthData:
4249 fixupWithAuthData = fit;
4250 break;
4251#endif
ebf6f434 4252 default:
a645023d
A
4253 break;
4254 }
e456bf10 4255 if ( fit->isStore() ) {
a645023d
A
4256 fixupWithStore = fit;
4257 }
4258 if ( fit->lastInCluster() ) {
4259 if ( (fixupWithStore != NULL) && (target != NULL) ) {
4260 if ( _options.outputKind() == Options::kObjectFile ) {
f80fe69f 4261 this->addSectionRelocs(state, sect, atom, fixupWithTarget, fixupWithMinusTarget, fixupWithAddend, fixupWithStore,
e456bf10
A
4262#if SUPPORT_ARCH_arm64e
4263 fixupWithAuthData,
4264#endif
a645023d
A
4265 target, minusTarget, targetAddend, minusTargetAddend);
4266 }
4267 else {
4268 if ( _options.makeCompressedDyldInfo() ) {
4269 this->addDyldInfo(state, sect, atom, fixupWithTarget, fixupWithMinusTarget, fixupWithStore,
e456bf10
A
4270 target, minusTarget, targetAddend, minusTargetAddend);
4271 } else if ( _options.makeThreadedStartsSection() ) {
4272 this->addThreadedRebaseInfo(state, sect, atom, fixupWithTarget, fixupWithMinusTarget, fixupWithStore,
4273 target, minusTarget, targetAddend, minusTargetAddend);
a645023d
A
4274 }
4275 else {
4276 this->addClassicRelocs(state, sect, atom, fixupWithTarget, fixupWithMinusTarget, fixupWithStore,
4277 target, minusTarget, targetAddend, minusTargetAddend);
4278 }
4279 }
4280 }
4281 else if ( objc1ClassRefSection && (target != NULL) && (fixupWithStore == NULL) ) {
4282 // check for class refs to lazy loaded dylibs
4283 const ld::dylib::File* dylib = dynamic_cast<const ld::dylib::File*>(target->file());
4284 if ( (dylib != NULL) && dylib->willBeLazyLoadedDylib() )
4285 throwf("illegal class reference to %s in lazy loaded dylib %s", target->name(), dylib->path());
4286 }
4287 }
4288 }
4289 }
4290 }
4291}
4292
4293
4294void OutputFile::noteTextReloc(const ld::Atom* atom, const ld::Atom* target)
4295{
4296 if ( (atom->contentType() == ld::Atom::typeStub) || (atom->contentType() == ld::Atom::typeStubHelper) ) {
4297 // silently let stubs (synthesized by linker) use text relocs
4298 }
4299 else if ( _options.allowTextRelocs() ) {
4300 if ( _options.warnAboutTextRelocs() )
4301 warning("text reloc in %s to %s", atom->name(), target->name());
4302 }
ebf6f434 4303 else if ( _options.positionIndependentExecutable() && (_options.outputKind() == Options::kDynamicExecutable)
e456bf10 4304 && _options.platforms().minOS(ld::version2010Fall)) {
a645023d 4305 if ( ! this->pieDisabled ) {
0a8dc3df
A
4306 switch ( _options.architecture()) {
4307#if SUPPORT_ARCH_arm64
4308 case CPU_TYPE_ARM64:
4309#endif
f80fe69f 4310#if SUPPORT_ARCH_arm64
0a8dc3df 4311 {
f80fe69f
A
4312 const char* demangledName = strdup(_options.demangleSymbol(atom->name()));
4313 throwf("Absolute addressing not allowed in arm64 code but used in '%s' referencing '%s'", demangledName, _options.demangleSymbol(target->name()));
4314 }
f80fe69f 4315#endif
0a8dc3df 4316 default:
f80fe69f 4317 warning("PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) not allowed in code signed PIE, "
a645023d
A
4318 "but used in %s from %s. "
4319 "To fix this warning, don't compile with -mdynamic-no-pic or link with -Wl,-no_pie",
82b4b32b 4320 atom->name(), atom->safeFilePath());
f80fe69f 4321 }
a645023d
A
4322 }
4323 this->pieDisabled = true;
4324 }
afe874b1 4325 else if ( (target->scope() == ld::Atom::scopeGlobal) && (target->combine() == ld::Atom::combineByName) ) {
82b4b32b 4326 throwf("illegal text-relocoation (direct reference) to (global,weak) %s in %s from %s in %s", target->name(), target->safeFilePath(), atom->name(), atom->safeFilePath());
afe874b1 4327 }
a645023d 4328 else {
f80fe69f 4329 if ( (target->file() != NULL) && (atom->file() != NULL) )
82b4b32b 4330 throwf("illegal text-relocation to '%s' in %s from '%s' in %s", target->name(), target->safeFilePath(), atom->name(), atom->safeFilePath());
f80fe69f
A
4331 else
4332 throwf("illegal text reloc in '%s' to '%s'", atom->name(), target->name());
a645023d
A
4333 }
4334}
4335
4336void OutputFile::addDyldInfo(ld::Internal& state, ld::Internal::FinalSection* sect, const ld::Atom* atom,
4337 ld::Fixup* fixupWithTarget, ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithStore,
4338 const ld::Atom* target, const ld::Atom* minusTarget,
4339 uint64_t targetAddend, uint64_t minusTargetAddend)
4340{
4341 if ( sect->isSectionHidden() )
4342 return;
4343
4344 // no need to rebase or bind PCRel stores
e456bf10 4345 if ( this->isPcRelStore(fixupWithStore) ) {
a645023d 4346 // as long as target is in same linkage unit
afe874b1
A
4347 if ( (target == NULL) || (target->definition() != ld::Atom::definitionProxy) ) {
4348 // make sure target is not global and weak
4349 if ( (target->scope() == ld::Atom::scopeGlobal) && (target->combine() == ld::Atom::combineByName) && (target->definition() == ld::Atom::definitionRegular)) {
4350 if ( (atom->section().type() == ld::Section::typeCFI)
4351 || (atom->section().type() == ld::Section::typeDtraceDOF)
4352 || (atom->section().type() == ld::Section::typeUnwindInfo) ) {
4353 // ok for __eh_frame and __uwind_info to use pointer diffs to global weak symbols
4354 return;
4355 }
f80fe69f
A
4356 // <rdar://problem/13700961> spurious warning when weak function has reference to itself
4357 if ( fixupWithTarget->binding == ld::Fixup::bindingDirectlyBound ) {
4358 // ok to ignore pc-rel references within a weak function to itself
4359 return;
4360 }
afe874b1 4361 // Have direct reference to weak-global. This should be an indrect reference
ebf6f434 4362 const char* demangledName = strdup(_options.demangleSymbol(atom->name()));
0a8dc3df 4363 warning("direct access in function '%s' from file '%s' to global weak symbol '%s' from file '%s' means the weak symbol cannot be overridden at runtime. "
afe874b1 4364 "This was likely caused by different translation units being compiled with different visibility settings.",
82b4b32b 4365 demangledName, atom->safeFilePath(), _options.demangleSymbol(target->name()), target->safeFilePath());
afe874b1 4366 }
a645023d 4367 return;
afe874b1 4368 }
a645023d
A
4369 }
4370
4371 // no need to rebase or bind PIC internal pointer diff
4372 if ( minusTarget != NULL ) {
4373 // with pointer diffs, both need to be in same linkage unit
4374 assert(minusTarget->definition() != ld::Atom::definitionProxy);
4375 assert(target != NULL);
4376 assert(target->definition() != ld::Atom::definitionProxy);
4377 if ( target == minusTarget ) {
4378 // This is a compile time constant and could have been optimized away by compiler
4379 return;
4380 }
4381
afe874b1
A
4382 // check if target of pointer-diff is global and weak
4383 if ( (target->scope() == ld::Atom::scopeGlobal) && (target->combine() == ld::Atom::combineByName) && (target->definition() == ld::Atom::definitionRegular) ) {
4384 if ( (atom->section().type() == ld::Section::typeCFI)
4385 || (atom->section().type() == ld::Section::typeDtraceDOF)
4386 || (atom->section().type() == ld::Section::typeUnwindInfo) ) {
4387 // ok for __eh_frame and __uwind_info to use pointer diffs to global weak symbols
4388 return;
4389 }
4390 // Have direct reference to weak-global. This should be an indrect reference
ebf6f434 4391 const char* demangledName = strdup(_options.demangleSymbol(atom->name()));
0a8dc3df 4392 warning("direct access in function '%s' from file '%s' to global weak symbol '%s' from file '%s' means the weak symbol cannot be overridden at runtime. "
afe874b1 4393 "This was likely caused by different translation units being compiled with different visibility settings.",
82b4b32b 4394 demangledName, atom->safeFilePath(), _options.demangleSymbol(target->name()), target->safeFilePath());
a645023d
A
4395 }
4396 return;
4397 }
4398
4399 // no need to rebase or bind an atom's references to itself if the output is not slidable
4400 if ( (atom == target) && !_options.outputSlidable() )
4401 return;
4402
4403 // cluster has no target, so needs no rebasing or binding
4404 if ( target == NULL )
4405 return;
4406
82b4b32b 4407 const uint64_t pointerSize = (_options.architecture() & CPU_ARCH_ABI64) ? 8 : 4;
9543cb2f 4408 bool inReadOnlySeg = ((_options.initialSegProtection(sect->segmentName()) & VM_PROT_WRITE) == 0);
a645023d
A
4409 bool needsRebase = false;
4410 bool needsBinding = false;
4411 bool needsLazyBinding = false;
4412 bool needsWeakBinding = false;
4413
4414 uint8_t rebaseType = REBASE_TYPE_POINTER;
4415 uint8_t type = BIND_TYPE_POINTER;
4416 const ld::dylib::File* dylib = dynamic_cast<const ld::dylib::File*>(target->file());
ebf6f434 4417 bool weak_import = (fixupWithTarget->weakImport || ((dylib != NULL) && dylib->forcedWeakLinked()));
a645023d
A
4418 uint64_t address = atom->finalAddress() + fixupWithTarget->offsetInAtom;
4419 uint64_t addend = targetAddend - minusTargetAddend;
4420
4421 // special case lazy pointers
4422 if ( fixupWithTarget->kind == ld::Fixup::kindLazyTarget ) {
4423 assert(fixupWithTarget->u.target == target);
4424 assert(addend == 0);
4425 // lazy dylib lazy pointers do not have any dyld info
4426 if ( atom->section().type() == ld::Section::typeLazyDylibPointer )
4427 return;
4428 // lazy binding to weak definitions are done differently
4429 // they are directly bound to target, then have a weak bind in case of a collision
4430 if ( target->combine() == ld::Atom::combineByName ) {
4431 if ( target->definition() == ld::Atom::definitionProxy ) {
4432 // weak def exported from another dylib
4433 // must non-lazy bind to it plus have weak binding info in case of collision
4434 needsBinding = true;
4435 needsWeakBinding = true;
4436 }
4437 else {
4438 // weak def in this linkage unit.
4439 // just rebase, plus have weak binding info in case of collision
4440 // this will be done by other cluster on lazy pointer atom
4441 }
4442 }
f80fe69f 4443 else if ( target->contentType() == ld::Atom::typeResolver ) {
a645023d 4444 // <rdar://problem/8553647> Hidden resolver functions should not have lazy binding info
f80fe69f
A
4445 // <rdar://problem/12629331> Resolver function run before initializers when overriding the dyld shared cache
4446 // The lazy pointers used by stubs used when non-lazy binding to a resolver are not normal lazy pointers
4447 // and should not be in lazy binding info.
a645023d
A
4448 needsLazyBinding = false;
4449 }
4450 else {
4451 // normal case of a pointer to non-weak-def symbol, so can lazily bind
4452 needsLazyBinding = true;
4453 }
4454 }
4455 else {
4456 // everything except lazy pointers
4457 switch ( target->definition() ) {
4458 case ld::Atom::definitionProxy:
4459 if ( (dylib != NULL) && dylib->willBeLazyLoadedDylib() )
4460 throwf("illegal data reference to %s in lazy loaded dylib %s", target->name(), dylib->path());
4461 if ( target->contentType() == ld::Atom::typeTLV ) {
4462 if ( sect->type() != ld::Section::typeTLVPointers )
4463 throwf("illegal data reference in %s to thread local variable %s in dylib %s",
4464 atom->name(), target->name(), dylib->path());
4465 }
4466 if ( inReadOnlySeg )
4467 type = BIND_TYPE_TEXT_ABSOLUTE32;
4468 needsBinding = true;
4469 if ( target->combine() == ld::Atom::combineByName )
4470 needsWeakBinding = true;
4471 break;
4472 case ld::Atom::definitionRegular:
4473 case ld::Atom::definitionTentative:
4474 // only slideable images need rebasing info
4475 if ( _options.outputSlidable() ) {
4476 needsRebase = true;
4477 }
4478 // references to internal symbol never need binding
4479 if ( target->scope() != ld::Atom::scopeGlobal )
4480 break;
4481 // reference to global weak def needs weak binding
4482 if ( (target->combine() == ld::Atom::combineByName) && (target->definition() == ld::Atom::definitionRegular) )
4483 needsWeakBinding = true;
4484 else if ( _options.outputKind() == Options::kDynamicExecutable ) {
4485 // in main executables, the only way regular symbols are indirected is if -interposable is used
4486 if ( _options.interposable(target->name()) ) {
4487 needsRebase = false;
4488 needsBinding = true;
4489 }
4490 }
4491 else {
4492 // for flat-namespace or interposable two-level-namespace
4493 // all references to exported symbols get indirected
4494 if ( (_options.nameSpace() != Options::kTwoLevelNameSpace) || _options.interposable(target->name()) ) {
4495 // <rdar://problem/5254468> no external relocs for flat objc classes
4496 if ( strncmp(target->name(), ".objc_class_", 12) == 0 )
4497 break;
4498 // no rebase info for references to global symbols that will have binding info
4499 needsRebase = false;
4500 needsBinding = true;
4501 }
f80fe69f
A
4502 else if ( _options.forceCoalesce(target->name()) ) {
4503 needsWeakBinding = true;
4504 }
a645023d
A
4505 }
4506 break;
4507 case ld::Atom::definitionAbsolute:
4508 break;
4509 }
4510 }
4511
f80fe69f
A
4512 // <rdar://problem/13828711> if target is an import alias, use base of alias
4513 if ( target->isAlias() && (target->definition() == ld::Atom::definitionProxy) ) {
4514 for (ld::Fixup::iterator fit = target->fixupsBegin(), end=target->fixupsEnd(); fit != end; ++fit) {
4515 if ( fit->firstInCluster() ) {
4516 if ( fit->kind == ld::Fixup::kindNoneFollowOn ) {
4517 if ( fit->binding == ld::Fixup::bindingDirectlyBound ) {
4518 //fprintf(stderr, "switching import of %s to import of %s\n", target->name(), fit->u.target->name());
4519 target = fit->u.target;
4520 }
4521 }
4522 }
4523 }
e456bf10
A
4524 }
4525
4526 // Find the ordinal for the bind target
4527 int compressedOrdinal = 0;
4528 if ( needsBinding || needsLazyBinding || needsWeakBinding ) {
4529 compressedOrdinal = this->compressedOrdinalForAtom(target);
4530 }
4531 // Linked list binding puts the weak binds in to the regular binds but with a special ordinal.
4532 if ( needsWeakBinding && _options.useLinkedListBinding() ) {
4533 assert(!needsLazyBinding);
4534 needsWeakBinding = false;
4535 needsBinding = true;
4536 needsRebase = false;
4537 compressedOrdinal = BIND_SPECIAL_DYLIB_WEAK_LOOKUP;
4538 }
f80fe69f 4539
a645023d
A
4540 // record dyld info for this cluster
4541 if ( needsRebase ) {
4542 if ( inReadOnlySeg ) {
4543 noteTextReloc(atom, target);
4544 sect->hasLocalRelocs = true; // so dyld knows to change permissions on __TEXT segment
4545 rebaseType = REBASE_TYPE_TEXT_ABSOLUTE32;
4546 }
f80fe69f
A
4547 if ( _options.sharedRegionEligible() ) {
4548 // <rdar://problem/13287063> when range checking, ignore high byte of arm64 addends
4549 uint64_t checkAddend = addend;
0a8dc3df
A
4550 if ( (_options.architecture() == CPU_TYPE_ARM64)
4551 )
f80fe69f
A
4552 checkAddend &= 0x0FFFFFFFFFFFFFFFULL;
4553 if ( checkAddend != 0 ) {
4554 // make sure the addend does not cause the pointer to point outside the target's segment
4555 // if it does, update_dyld_shared_cache will not be able to put this dylib into the shared cache
4556 uint64_t targetAddress = target->finalAddress();
4557 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
4558 ld::Internal::FinalSection* sct = *sit;
4559 uint64_t sctEnd = (sct->address+sct->size);
4560 if ( (sct->address <= targetAddress) && (targetAddress < sctEnd) ) {
4561 if ( (targetAddress+checkAddend) > sctEnd ) {
4562 warning("data symbol %s from %s has pointer to %s + 0x%08llX. "
4563 "That large of an addend may disable %s from being put in the dyld shared cache.",
82b4b32b 4564 atom->name(), atom->safeFilePath(), target->name(), addend, _options.installPath() );
f80fe69f 4565 }
ebf6f434
A
4566 }
4567 }
4568 }
4569 }
82b4b32b 4570 if ( ((address & (pointerSize-1)) != 0) && (rebaseType == REBASE_TYPE_POINTER) ) {
bee7e226
A
4571 switch ( _options.unalignedPointerTreatment() ) {
4572 case Options::kUnalignedPointerError:
4573 throwf("pointer not aligned at address 0x%llX (%s + %lld from %s)",
4574 address, atom->name(), (address - atom->finalAddress()), atom->safeFilePath());
4575 break;
4576 case Options::kUnalignedPointerWarning:
4577 warning("pointer not aligned at address 0x%llX (%s + %lld from %s)",
4578 address, atom->name(), (address - atom->finalAddress()), atom->safeFilePath());
4579 break;
4580 case Options::kUnalignedPointerIgnore:
4581 // do nothing
4582 break;
82b4b32b 4583 }
e456bf10 4584 _hasUnalignedFixup = true;
82b4b32b 4585 }
a645023d
A
4586 _rebaseInfo.push_back(RebaseInfo(rebaseType, address));
4587 }
e456bf10 4588
a645023d
A
4589 if ( needsBinding ) {
4590 if ( inReadOnlySeg ) {
4591 noteTextReloc(atom, target);
4592 sect->hasExternalRelocs = true; // so dyld knows to change permissions on __TEXT segment
4593 }
82b4b32b 4594 if ( ((address & (pointerSize-1)) != 0) && (type == BIND_TYPE_POINTER) ) {
bee7e226
A
4595 switch ( _options.unalignedPointerTreatment() ) {
4596 case Options::kUnalignedPointerError:
4597 throwf("pointer not aligned at address 0x%llX (%s + %lld from %s)",
4598 address, atom->name(), (address - atom->finalAddress()), atom->safeFilePath());
4599 break;
4600 case Options::kUnalignedPointerWarning:
4601 warning("pointer not aligned at address 0x%llX (%s + %lld from %s)",
4602 address, atom->name(), (address - atom->finalAddress()), atom->safeFilePath());
4603 break;
4604 case Options::kUnalignedPointerIgnore:
4605 // do nothing
4606 break;
82b4b32b 4607 }
e456bf10 4608 _hasUnalignedFixup = true;
82b4b32b 4609 }
e456bf10 4610 _bindingInfo.push_back(BindingInfo(type, compressedOrdinal, target->name(), weak_import, address, addend));
a645023d
A
4611 }
4612 if ( needsLazyBinding ) {
4613 if ( _options.bindAtLoad() )
e456bf10 4614 _bindingInfo.push_back(BindingInfo(type, compressedOrdinal, target->name(), weak_import, address, addend));
a645023d 4615 else
e456bf10 4616 _lazyBindingInfo.push_back(BindingInfo(type, compressedOrdinal, target->name(), weak_import, address, addend));
a645023d
A
4617 }
4618 if ( needsWeakBinding )
4619 _weakBindingInfo.push_back(BindingInfo(type, 0, target->name(), false, address, addend));
a645023d
A
4620}
4621
e456bf10
A
4622void OutputFile::addThreadedRebaseInfo(ld::Internal& state, ld::Internal::FinalSection* sect, const ld::Atom* atom,
4623 ld::Fixup* fixupWithTarget, ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithStore,
4624 const ld::Atom* target, const ld::Atom* minusTarget,
4625 uint64_t targetAddend, uint64_t minusTargetAddend)
4626{
4627 if ( sect->isSectionHidden() )
4628 return;
4629
4630 // no need to rebase or bind PCRel stores
4631 if ( this->isPcRelStore(fixupWithStore) ) {
4632 // as long as target is in same linkage unit
4633 if ( (target == NULL) || (target->definition() != ld::Atom::definitionProxy) ) {
4634 // make sure target is not global and weak
4635 if ( (target->scope() == ld::Atom::scopeGlobal) && (target->combine() == ld::Atom::combineByName) && (target->definition() == ld::Atom::definitionRegular)) {
4636 if ( (atom->section().type() == ld::Section::typeCFI)
4637 || (atom->section().type() == ld::Section::typeDtraceDOF)
4638 || (atom->section().type() == ld::Section::typeUnwindInfo) ) {
4639 // ok for __eh_frame and __uwind_info to use pointer diffs to global weak symbols
4640 return;
4641 }
4642 // <rdar://problem/13700961> spurious warning when weak function has reference to itself
4643 if ( fixupWithTarget->binding == ld::Fixup::bindingDirectlyBound ) {
4644 // ok to ignore pc-rel references within a weak function to itself
4645 return;
4646 }
4647 // Have direct reference to weak-global. This should be an indrect reference
4648 const char* demangledName = strdup(_options.demangleSymbol(atom->name()));
4649 warning("direct access in function '%s' from file '%s' to global weak symbol '%s' from file '%s' means the weak symbol cannot be overridden at runtime. "
4650 "This was likely caused by different translation units being compiled with different visibility settings.",
4651 demangledName, atom->safeFilePath(), _options.demangleSymbol(target->name()), target->safeFilePath());
4652 }
4653 return;
4654 }
4655 }
4656
4657 // no need to rebase or bind PIC internal pointer diff
4658 if ( minusTarget != NULL ) {
4659 // with pointer diffs, both need to be in same linkage unit
4660 assert(minusTarget->definition() != ld::Atom::definitionProxy);
4661 assert(target != NULL);
4662 assert(target->definition() != ld::Atom::definitionProxy);
4663 if ( target == minusTarget ) {
4664 // This is a compile time constant and could have been optimized away by compiler
4665 return;
4666 }
4667
4668 // check if target of pointer-diff is global and weak
4669 if ( (target->scope() == ld::Atom::scopeGlobal) && (target->combine() == ld::Atom::combineByName) && (target->definition() == ld::Atom::definitionRegular) ) {
4670 if ( (atom->section().type() == ld::Section::typeCFI)
4671 || (atom->section().type() == ld::Section::typeDtraceDOF)
4672 || (atom->section().type() == ld::Section::typeUnwindInfo) ) {
4673 // ok for __eh_frame and __uwind_info to use pointer diffs to global weak symbols
4674 return;
4675 }
4676 // Have direct reference to weak-global. This should be an indrect reference
4677 const char* demangledName = strdup(_options.demangleSymbol(atom->name()));
4678 warning("direct access in function '%s' from file '%s' to global weak symbol '%s' from file '%s' means the weak symbol cannot be overridden at runtime. "
4679 "This was likely caused by different translation units being compiled with different visibility settings.",
4680 demangledName, atom->safeFilePath(), _options.demangleSymbol(target->name()), target->safeFilePath());
4681 }
4682 return;
4683 }
4684
4685 // no need to rebase or bind an atom's references to itself if the output is not slidable
4686 if ( (atom == target) && !_options.outputSlidable() )
4687 return;
4688
4689 // cluster has no target, so needs no rebasing or binding
4690 if ( target == NULL )
4691 return;
4692
4693 const uint64_t minAlignment = 4;
4694 bool inReadOnlySeg = ( strcmp(sect->segmentName(), "__TEXT") == 0 );
4695 bool needsRebase = false;
4696
4697 uint8_t rebaseType = REBASE_TYPE_POINTER;
4698 uint64_t address = atom->finalAddress() + fixupWithTarget->offsetInAtom;
4699
4700 // special case lazy pointers
4701 switch ( target->definition() ) {
4702 case ld::Atom::definitionProxy:
4703 break;
4704 case ld::Atom::definitionRegular:
4705 case ld::Atom::definitionTentative:
4706 needsRebase = true;
4707 break;
4708 case ld::Atom::definitionAbsolute:
4709 break;
4710 }
4711
4712 // record dyld info for this cluster
4713 if ( needsRebase ) {
4714 if ( inReadOnlySeg ) {
4715 noteTextReloc(atom, target);
4716 sect->hasLocalRelocs = true; // so dyld knows to change permissions on __TEXT segment
4717 }
4718 if ( ((address & (minAlignment-1)) != 0) ) {
4719 throwf("pointer not aligned to at least 4-bytes at address 0x%llX (%s + %lld from %s)",
4720 address, atom->name(), (address - atom->finalAddress()), atom->safeFilePath());
4721 }
4722 _rebaseInfo.push_back(RebaseInfo(rebaseType, address));
4723 }
4724}
4725
a645023d
A
4726
4727void OutputFile::addClassicRelocs(ld::Internal& state, ld::Internal::FinalSection* sect, const ld::Atom* atom,
4728 ld::Fixup* fixupWithTarget, ld::Fixup* fixupWithMinusTarget, ld::Fixup* fixupWithStore,
4729 const ld::Atom* target, const ld::Atom* minusTarget,
4730 uint64_t targetAddend, uint64_t minusTargetAddend)
4731{
4732 if ( sect->isSectionHidden() )
4733 return;
4734
4735 // non-lazy-pointer section is encoded in indirect symbol table - not using relocations
ebf6f434
A
4736 if ( sect->type() == ld::Section::typeNonLazyPointer ) {
4737 // except kexts and static pie which *do* use relocations
4738 switch (_options.outputKind()) {
4739 case Options::kKextBundle:
4740 break;
4741 case Options::kStaticExecutable:
4742 if ( _options.positionIndependentExecutable() )
4743 break;
4744 // else fall into default case
4745 default:
4746 assert(target != NULL);
4747 assert(fixupWithTarget != NULL);
4748 return;
4749 }
a645023d
A
4750 }
4751
4752 // no need to rebase or bind PCRel stores
e456bf10 4753 if ( this->isPcRelStore(fixupWithStore) ) {
a645023d
A
4754 // as long as target is in same linkage unit
4755 if ( (target == NULL) || (target->definition() != ld::Atom::definitionProxy) )
4756 return;
4757 }
4758
4759 // no need to rebase or bind PIC internal pointer diff
4760 if ( minusTarget != NULL ) {
4761 // with pointer diffs, both need to be in same linkage unit
4762 assert(minusTarget->definition() != ld::Atom::definitionProxy);
4763 assert(target != NULL);
4764 assert(target->definition() != ld::Atom::definitionProxy);
82b4b32b
A
4765 // check if target of pointer-diff is global and weak
4766 if ( (target->scope() == ld::Atom::scopeGlobal) && (target->combine() == ld::Atom::combineByName) && (target->definition() == ld::Atom::definitionRegular) ) {
4767 if ( (atom->section().type() == ld::Section::typeCFI)
4768 || (atom->section().type() == ld::Section::typeDtraceDOF)
4769 || (atom->section().type() == ld::Section::typeUnwindInfo) ) {
4770 // ok for __eh_frame and __uwind_info to use pointer diffs to global weak symbols
4771 return;
4772 }
4773 // Have direct reference to weak-global. This should be an indrect reference
4774 const char* demangledName = strdup(_options.demangleSymbol(atom->name()));
4775 warning("direct access in function '%s' from file '%s' to global weak symbol '%s' from file '%s' means the weak symbol cannot be overridden at runtime. "
4776 "This was likely caused by different translation units being compiled with different visibility settings.",
4777 demangledName, atom->safeFilePath(), _options.demangleSymbol(target->name()), target->safeFilePath());
a645023d
A
4778 }
4779 return;
4780 }
4781
4782 // cluster has no target, so needs no rebasing or binding
4783 if ( target == NULL )
4784 return;
4785
4786 assert(_localRelocsAtom != NULL);
4787 uint64_t relocAddress = atom->finalAddress() + fixupWithTarget->offsetInAtom - _localRelocsAtom->relocBaseAddress(state);
4788
4789 bool inReadOnlySeg = ( strcmp(sect->segmentName(), "__TEXT") == 0 );
4790 bool needsLocalReloc = false;
4791 bool needsExternReloc = false;
4792
4793 switch ( fixupWithStore->kind ) {
4794 case ld::Fixup::kindLazyTarget:
afe874b1 4795 // lazy pointers don't need relocs
a645023d
A
4796 break;
4797 case ld::Fixup::kindStoreLittleEndian32:
4798 case ld::Fixup::kindStoreLittleEndian64:
4799 case ld::Fixup::kindStoreBigEndian32:
4800 case ld::Fixup::kindStoreBigEndian64:
4801 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
4802 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
e456bf10
A
4803#if SUPPORT_ARCH_arm64e
4804 case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64:
4805#endif
a645023d
A
4806 case ld::Fixup::kindStoreTargetAddressBigEndian32:
4807 case ld::Fixup::kindStoreTargetAddressBigEndian64:
4808 // is pointer
4809 switch ( target->definition() ) {
4810 case ld::Atom::definitionProxy:
4811 needsExternReloc = true;
4812 break;
4813 case ld::Atom::definitionRegular:
4814 case ld::Atom::definitionTentative:
4815 // only slideable images need local relocs
4816 if ( _options.outputSlidable() )
4817 needsLocalReloc = true;
4818 // references to internal symbol never need binding
4819 if ( target->scope() != ld::Atom::scopeGlobal )
4820 break;
4821 // reference to global weak def needs weak binding in dynamic images
4822 if ( (target->combine() == ld::Atom::combineByName)
4823 && (target->definition() == ld::Atom::definitionRegular)
d425e388 4824 && (_options.outputKind() != Options::kStaticExecutable)
f80fe69f
A
4825 && (_options.outputKind() != Options::kPreload)
4826 && (atom != target) ) {
a645023d
A
4827 needsExternReloc = true;
4828 }
4829 else if ( _options.outputKind() == Options::kDynamicExecutable ) {
4830 // in main executables, the only way regular symbols are indirected is if -interposable is used
4831 if ( _options.interposable(target->name()) )
4832 needsExternReloc = true;
4833 }
4834 else {
4835 // for flat-namespace or interposable two-level-namespace
4836 // all references to exported symbols get indirected
4837 if ( (_options.nameSpace() != Options::kTwoLevelNameSpace) || _options.interposable(target->name()) ) {
4838 // <rdar://problem/5254468> no external relocs for flat objc classes
4839 if ( strncmp(target->name(), ".objc_class_", 12) == 0 )
4840 break;
4841 // no rebase info for references to global symbols that will have binding info
4842 needsExternReloc = true;
4843 }
4844 }
4845 if ( needsExternReloc )
4846 needsLocalReloc = false;
4847 break;
4848 case ld::Atom::definitionAbsolute:
4849 break;
4850 }
4851 if ( needsExternReloc ) {
4852 if ( inReadOnlySeg )
4853 noteTextReloc(atom, target);
4854 const ld::dylib::File* dylib = dynamic_cast<const ld::dylib::File*>(target->file());
4855 if ( (dylib != NULL) && dylib->willBeLazyLoadedDylib() )
4856 throwf("illegal data reference to %s in lazy loaded dylib %s", target->name(), dylib->path());
4857 _externalRelocsAtom->addExternalPointerReloc(relocAddress, target);
4858 sect->hasExternalRelocs = true;
4859 fixupWithTarget->contentAddendOnly = true;
a645023d
A
4860 }
4861 else if ( needsLocalReloc ) {
4862 assert(target != NULL);
4863 if ( inReadOnlySeg )
4864 noteTextReloc(atom, target);
4865 _localRelocsAtom->addPointerReloc(relocAddress, target->machoSection());
4866 sect->hasLocalRelocs = true;
4867 }
4868 break;
a645023d 4869 case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32:
f80fe69f
A
4870#if SUPPORT_ARCH_arm64
4871 case ld::Fixup::kindStoreTargetAddressARM64Branch26:
4872#endif
a645023d
A
4873 if ( _options.outputKind() == Options::kKextBundle ) {
4874 assert(target != NULL);
4875 if ( target->definition() == ld::Atom::definitionProxy ) {
4876 _externalRelocsAtom->addExternalCallSiteReloc(relocAddress, target);
4877 fixupWithStore->contentAddendOnly = true;
4878 }
4879 }
4880 break;
afe874b1
A
4881
4882 case ld::Fixup::kindStoreARMLow16:
4883 case ld::Fixup::kindStoreThumbLow16:
4884 // no way to encode rebasing of binding for these instructions
4885 if ( _options.outputSlidable() || (target->definition() == ld::Atom::definitionProxy) )
82b4b32b 4886 throwf("no supported runtime lo16 relocation in %s from %s to %s", atom->name(), atom->safeFilePath(), target->name());
afe874b1
A
4887 break;
4888
4889 case ld::Fixup::kindStoreARMHigh16:
4890 case ld::Fixup::kindStoreThumbHigh16:
4891 // no way to encode rebasing of binding for these instructions
4892 if ( _options.outputSlidable() || (target->definition() == ld::Atom::definitionProxy) )
82b4b32b 4893 throwf("no supported runtime hi16 relocation in %s from %s to %s", atom->name(), atom->safeFilePath(), target->name());
afe874b1
A
4894 break;
4895
e456bf10
A
4896#if SUPPORT_ARCH_arm64e
4897 case ld::Fixup::kindStoreLittleEndianAuth64:
4898 if ( _options.outputKind() == Options::kKextBundle ) {
4899 if ( target->definition() == ld::Atom::definitionProxy ) {
4900 _externalRelocsAtom->addExternalPointerReloc(relocAddress, target);
4901 sect->hasExternalRelocs = true;
4902 fixupWithTarget->contentAddendOnly = true;
4903 }
4904 else {
4905 _localRelocsAtom->addPointerReloc(relocAddress, target->machoSection());
4906 sect->hasLocalRelocs = true;
4907 }
4908 }
4909 else {
4910 throwf("authenticated pointer in atom %s from %s to %s is not supported", atom->name(), atom->safeFilePath(), target->name());
4911 }
4912 break;
4913#endif
a645023d
A
4914 default:
4915 break;
4916 }
4917}
4918
4919
4920bool OutputFile::useExternalSectionReloc(const ld::Atom* atom, const ld::Atom* target, ld::Fixup* fixupWithTarget)
4921{
0a8dc3df
A
4922 if ( (_options.architecture() == CPU_TYPE_X86_64)
4923 || (_options.architecture() == CPU_TYPE_ARM64)
4924 ) {
f80fe69f 4925 // x86_64 and ARM64 use external relocations for everthing that has a symbol
a645023d
A
4926 return ( target->symbolTableInclusion() != ld::Atom::symbolTableNotIn );
4927 }
afe874b1
A
4928
4929 // <rdar://problem/9513487> support arm branch interworking in -r mode
4930 if ( (_options.architecture() == CPU_TYPE_ARM) && (_options.outputKind() == Options::kObjectFile) ) {
4931 if ( atom->isThumb() != target->isThumb() ) {
4932 switch ( fixupWithTarget->kind ) {
4933 // have branch that switches mode, then might be 'b' not 'bl'
4934 // Force external relocation, since no way to do local reloc for 'b'
4935 case ld::Fixup::kindStoreTargetAddressThumbBranch22 :
4936 case ld::Fixup::kindStoreTargetAddressARMBranch24:
4937 return true;
4938 default:
4939 break;
4940 }
4941 }
4942 }
b1f7435d
A
4943
4944 if ( (_options.architecture() == CPU_TYPE_I386) && (_options.outputKind() == Options::kObjectFile) ) {
4945 if ( target->contentType() == ld::Atom::typeTLV )
4946 return true;
4947 }
afe874b1 4948
a645023d
A
4949 // most architectures use external relocations only for references
4950 // to a symbol in another translation unit or for references to "weak symbols" or tentative definitions
4951 assert(target != NULL);
4952 if ( target->definition() == ld::Atom::definitionProxy )
4953 return true;
4954 if ( (target->definition() == ld::Atom::definitionTentative) && ! _options.makeTentativeDefinitionsReal() )
4955 return true;
4956 if ( target->scope() != ld::Atom::scopeGlobal )
4957 return false;
4958 if ( (target->combine() == ld::Atom::combineByName) && (target->definition() == ld::Atom::definitionRegular) )
4959 return true;
4960 return false;
4961}
4962
f80fe69f
A
4963bool OutputFile::useSectionRelocAddend(ld::Fixup* fixupWithTarget)
4964{
4965#if SUPPORT_ARCH_arm64
4966 if ( _options.architecture() == CPU_TYPE_ARM64 ) {
4967 switch ( fixupWithTarget->kind ) {
4968 case ld::Fixup::kindStoreARM64Branch26:
4969 case ld::Fixup::kindStoreARM64Page21:
4970 case ld::Fixup::kindStoreARM64PageOff12:
4971 return true;
4972 default:
4973 return false;
4974 }
4975 }
4976#endif
4977 return false;
4978}
4979
a645023d
A
4980
4981
4982
4983void OutputFile::addSectionRelocs(ld::Internal& state, ld::Internal::FinalSection* sect, const ld::Atom* atom,
f80fe69f 4984 ld::Fixup* fixupWithTarget, ld::Fixup* fixupWithMinusTarget,
e456bf10
A
4985 ld::Fixup* fixupWithAddend, ld::Fixup* fixupWithStore,
4986#if SUPPORT_ARCH_arm64e
4987 ld::Fixup* fixupWithAuthData,
4988#endif
a645023d
A
4989 const ld::Atom* target, const ld::Atom* minusTarget,
4990 uint64_t targetAddend, uint64_t minusTargetAddend)
4991{
4992 if ( sect->isSectionHidden() )
4993 return;
4994
4995 // in -r mode where there will be no labels on __eh_frame section, there is no need for relocations
4996 if ( (sect->type() == ld::Section::typeCFI) && _options.removeEHLabels() )
4997 return;
4998
4999 // non-lazy-pointer section is encoded in indirect symbol table - not using relocations
5000 if ( sect->type() == ld::Section::typeNonLazyPointer )
5001 return;
5002
5003 // tentative defs don't have any relocations
5004 if ( sect->type() == ld::Section::typeTentativeDefs )
5005 return;
5006
5007 assert(target != NULL);
5008 assert(fixupWithTarget != NULL);
5009 bool targetUsesExternalReloc = this->useExternalSectionReloc(atom, target, fixupWithTarget);
5010 bool minusTargetUsesExternalReloc = (minusTarget != NULL) && this->useExternalSectionReloc(atom, minusTarget, fixupWithMinusTarget);
5011
f80fe69f 5012 // in x86_64 and arm64 .o files an external reloc means the content contains just the addend
0a8dc3df
A
5013 if ( (_options.architecture() == CPU_TYPE_X86_64)
5014 || (_options.architecture() == CPU_TYPE_ARM64)
5015 ) {
a645023d
A
5016 if ( targetUsesExternalReloc ) {
5017 fixupWithTarget->contentAddendOnly = true;
5018 fixupWithStore->contentAddendOnly = true;
f80fe69f
A
5019 if ( this->useSectionRelocAddend(fixupWithStore) && (fixupWithAddend != NULL) )
5020 fixupWithAddend->contentIgnoresAddend = true;
a645023d
A
5021 }
5022 if ( minusTargetUsesExternalReloc )
5023 fixupWithMinusTarget->contentAddendOnly = true;
5024 }
5025 else {
5026 // for other archs, content is addend only with (non pc-rel) pointers
5027 // pc-rel instructions are funny. If the target is _foo+8 and _foo is
5028 // external, then the pc-rel instruction *evalutates* to the address 8.
5029 if ( targetUsesExternalReloc ) {
b1f7435d
A
5030 // TLV support for i386 acts like RIP relative addressing
5031 // The addend is the offset from the PICBase to the end of the instruction
5032 if ( (_options.architecture() == CPU_TYPE_I386)
5033 && (_options.outputKind() == Options::kObjectFile)
5034 && (fixupWithStore->kind == ld::Fixup::kindStoreX86PCRel32TLVLoad) ) {
5035 fixupWithTarget->contentAddendOnly = true;
5036 fixupWithStore->contentAddendOnly = true;
5037 }
e456bf10 5038 else if ( isPcRelStore(fixupWithStore) ) {
a645023d
A
5039 fixupWithTarget->contentDetlaToAddendOnly = true;
5040 fixupWithStore->contentDetlaToAddendOnly = true;
5041 }
5042 else if ( minusTarget == NULL ){
5043 fixupWithTarget->contentAddendOnly = true;
5044 fixupWithStore->contentAddendOnly = true;
5045 }
5046 }
5047 }
5048
5049 if ( fixupWithStore != NULL ) {
5050 _sectionsRelocationsAtom->addSectionReloc(sect, fixupWithStore->kind, atom, fixupWithStore->offsetInAtom,
5051 targetUsesExternalReloc, minusTargetUsesExternalReloc,
e456bf10
A
5052#if SUPPORT_ARCH_arm64e
5053 fixupWithAuthData,
5054#endif
a645023d
A
5055 target, targetAddend, minusTarget, minusTargetAddend);
5056 }
5057
5058}
5059
a645023d
A
5060void OutputFile::makeSplitSegInfo(ld::Internal& state)
5061{
5062 if ( !_options.sharedRegionEligible() )
5063 return;
5064
5065 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
5066 ld::Internal::FinalSection* sect = *sit;
5067 if ( sect->isSectionHidden() )
5068 continue;
5069 if ( strcmp(sect->segmentName(), "__TEXT") != 0 )
5070 continue;
5071 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
5072 const ld::Atom* atom = *ait;
5073 const ld::Atom* target = NULL;
afe874b1
A
5074 const ld::Atom* fromTarget = NULL;
5075 uint64_t accumulator = 0;
5076 bool thumbTarget;
a645023d
A
5077 bool hadSubtract = false;
5078 for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
5079 if ( fit->firstInCluster() )
5080 target = NULL;
e456bf10 5081 if ( this->setsTarget(*fit) ) {
0a8dc3df 5082 accumulator = addressOf(state, fit, &target);
afe874b1
A
5083 thumbTarget = targetIsThumb(state, fit);
5084 if ( thumbTarget )
5085 accumulator |= 1;
a645023d 5086 }
afe874b1
A
5087 switch ( fit->kind ) {
5088 case ld::Fixup::kindSubtractTargetAddress:
5089 accumulator -= addressOf(state, fit, &fromTarget);
5090 hadSubtract = true;
a645023d 5091 break;
afe874b1
A
5092 case ld::Fixup::kindAddAddend:
5093 accumulator += fit->u.addend;
a645023d 5094 break;
afe874b1
A
5095 case ld::Fixup::kindSubtractAddend:
5096 accumulator -= fit->u.addend;
a645023d 5097 break;
a645023d
A
5098 case ld::Fixup::kindStoreBigEndian32:
5099 case ld::Fixup::kindStoreLittleEndian32:
5100 case ld::Fixup::kindStoreLittleEndian64:
5101 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
5102 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
5103 // if no subtract, then this is an absolute pointer which means
5104 // there is also a text reloc which update_dyld_shared_cache will use.
5105 if ( ! hadSubtract )
5106 break;
afe874b1 5107 // fall through
a645023d
A
5108 case ld::Fixup::kindStoreX86PCRel32:
5109 case ld::Fixup::kindStoreX86PCRel32_1:
5110 case ld::Fixup::kindStoreX86PCRel32_2:
5111 case ld::Fixup::kindStoreX86PCRel32_4:
5112 case ld::Fixup::kindStoreX86PCRel32GOTLoad:
5113 case ld::Fixup::kindStoreX86PCRel32GOTLoadNowLEA:
5114 case ld::Fixup::kindStoreX86PCRel32GOT:
f80fe69f
A
5115 case ld::Fixup::kindStoreX86PCRel32TLVLoad:
5116 case ld::Fixup::kindStoreX86PCRel32TLVLoadNowLEA:
a645023d
A
5117 case ld::Fixup::kindStoreTargetAddressX86PCRel32:
5118 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad:
5119 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA:
f80fe69f
A
5120 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad:
5121 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA:
afe874b1
A
5122 case ld::Fixup::kindStoreARMLow16:
5123 case ld::Fixup::kindStoreThumbLow16:
f80fe69f
A
5124#if SUPPORT_ARCH_arm64
5125 case ld::Fixup::kindStoreARM64Page21:
5126 case ld::Fixup::kindStoreARM64GOTLoadPage21:
5127 case ld::Fixup::kindStoreARM64GOTLeaPage21:
5128 case ld::Fixup::kindStoreARM64TLVPLoadPage21:
ec29ba20 5129 case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPage21:
f80fe69f
A
5130 case ld::Fixup::kindStoreTargetAddressARM64Page21:
5131 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
5132 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21:
ec29ba20
A
5133 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21:
5134 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPage21:
f80fe69f
A
5135 case ld::Fixup::kindStoreARM64PCRelToGOT:
5136#endif
a645023d
A
5137 assert(target != NULL);
5138 if ( strcmp(sect->segmentName(), target->section().segmentName()) != 0 ) {
5139 _splitSegInfos.push_back(SplitSegInfoEntry(atom->finalAddress()+fit->offsetInAtom,fit->kind));
5140 }
5141 break;
afe874b1
A
5142 case ld::Fixup::kindStoreARMHigh16:
5143 case ld::Fixup::kindStoreThumbHigh16:
5144 assert(target != NULL);
5145 if ( strcmp(sect->segmentName(), target->section().segmentName()) != 0 ) {
5146 // hi16 needs to know upper 4-bits of low16 to compute carry
5147 uint32_t extra = (accumulator >> 12) & 0xF;
5148 _splitSegInfos.push_back(SplitSegInfoEntry(atom->finalAddress()+fit->offsetInAtom,fit->kind, extra));
5149 }
5150 break;
5151 case ld::Fixup::kindSetTargetImageOffset:
0a8dc3df 5152 accumulator = addressOf(state, fit, &target);
afe874b1
A
5153 assert(target != NULL);
5154 hadSubtract = true;
5155 break;
e456bf10
A
5156#if SUPPORT_ARCH_arm64e
5157 case ld::Fixup::kindStoreLittleEndianAuth64:
5158 case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64:
5159 case ld::Fixup::kindSetAuthData:
5160 throw "authenticated pointers are not supported in split seg v1";
5161 break;
5162#endif
a645023d
A
5163 default:
5164 break;
5165 }
5166 }
5167 }
5168 }
5169}
5170
eaf282aa
A
5171void OutputFile::makeSplitSegInfoV2(ld::Internal& state)
5172{
5173 static const bool log = false;
5174 if ( !_options.sharedRegionEligible() )
5175 return;
5176
5177 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
5178 ld::Internal::FinalSection* sect = *sit;
5179 if ( sect->isSectionHidden() )
5180 continue;
5181 bool codeSection = (sect->type() == ld::Section::typeCode);
5182 if (log) fprintf(stderr, "sect: %s, address=0x%llX\n", sect->sectionName(), sect->address);
5183 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
5184 const ld::Atom* atom = *ait;
5185 const ld::Atom* target = NULL;
5186 const ld::Atom* fromTarget = NULL;
5187 uint32_t picBase = 0;
5188 uint64_t accumulator = 0;
5189 bool thumbTarget;
5190 bool hadSubtract = false;
5191 uint8_t fromSectionIndex = atom->machoSection();
5192 uint8_t toSectionIndex;
5193 uint8_t kind = 0;
5194 uint64_t fromOffset = 0;
5195 uint64_t toOffset = 0;
5196 uint64_t addend = 0;
5197 for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
5198 if ( fit->firstInCluster() ) {
5199 target = NULL;
0a8dc3df 5200 hadSubtract = false;
eaf282aa
A
5201 fromTarget = NULL;
5202 kind = 0;
5203 addend = 0;
5204 toSectionIndex = 255;
5205 fromOffset = atom->finalAddress() + fit->offsetInAtom - sect->address;
5206 }
e456bf10 5207 if ( this->setsTarget(*fit) ) {
0a8dc3df 5208 accumulator = addressAndTarget(state, fit, &target);
eaf282aa
A
5209 thumbTarget = targetIsThumb(state, fit);
5210 if ( thumbTarget )
5211 accumulator |= 1;
5212 toOffset = accumulator - state.atomToSection[target]->address;
5213 if ( target->definition() != ld::Atom::definitionProxy ) {
5214 if ( target->section().type() == ld::Section::typeMachHeader )
5215 toSectionIndex = 0;
5216 else
5217 toSectionIndex = target->machoSection();
5218 }
5219 }
5220 switch ( fit->kind ) {
5221 case ld::Fixup::kindSubtractTargetAddress:
0a8dc3df 5222 accumulator -= addressAndTarget(state, fit, &fromTarget);
eaf282aa
A
5223 hadSubtract = true;
5224 break;
5225 case ld::Fixup::kindAddAddend:
5226 accumulator += fit->u.addend;
5227 addend = fit->u.addend;
5228 break;
5229 case ld::Fixup::kindSubtractAddend:
5230 accumulator -= fit->u.addend;
5231 picBase = fit->u.addend;
5232 break;
5233 case ld::Fixup::kindSetLazyOffset:
5234 break;
5235 case ld::Fixup::kindStoreBigEndian32:
5236 case ld::Fixup::kindStoreLittleEndian32:
5237 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
5238 if ( kind != DYLD_CACHE_ADJ_V2_IMAGE_OFF_32 ) {
5239 if ( hadSubtract )
5240 kind = DYLD_CACHE_ADJ_V2_DELTA_32;
5241 else
5242 kind = DYLD_CACHE_ADJ_V2_POINTER_32;
5243 }
5244 break;
5245 case ld::Fixup::kindStoreLittleEndian64:
5246 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
5247 if ( hadSubtract )
5248 kind = DYLD_CACHE_ADJ_V2_DELTA_64;
e456bf10
A
5249 else if ( _options.useLinkedListBinding() && !this->_hasUnalignedFixup )
5250 kind = DYLD_CACHE_ADJ_V2_THREADED_POINTER_64;
eaf282aa
A
5251 else
5252 kind = DYLD_CACHE_ADJ_V2_POINTER_64;
5253 break;
e456bf10
A
5254#if SUPPORT_ARCH_arm64e
5255 case ld::Fixup::kindStoreLittleEndianAuth64:
5256 case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64:
5257 // FIXME: Do we need to handle subtracts on authenticated pointers?
5258 assert(!hadSubtract);
5259 kind = DYLD_CACHE_ADJ_V2_THREADED_POINTER_64;
5260 break;
5261#endif
eaf282aa
A
5262 case ld::Fixup::kindStoreX86PCRel32:
5263 case ld::Fixup::kindStoreX86PCRel32_1:
5264 case ld::Fixup::kindStoreX86PCRel32_2:
5265 case ld::Fixup::kindStoreX86PCRel32_4:
5266 case ld::Fixup::kindStoreX86PCRel32GOTLoad:
5267 case ld::Fixup::kindStoreX86PCRel32GOTLoadNowLEA:
5268 case ld::Fixup::kindStoreX86PCRel32GOT:
5269 case ld::Fixup::kindStoreX86PCRel32TLVLoad:
5270 case ld::Fixup::kindStoreX86PCRel32TLVLoadNowLEA:
5271 case ld::Fixup::kindStoreTargetAddressX86PCRel32:
5272 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad:
5273 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA:
5274 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad:
5275 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA:
5276#if SUPPORT_ARCH_arm64
5277 case ld::Fixup::kindStoreARM64PCRelToGOT:
5278#endif
5279 if ( (fromSectionIndex != toSectionIndex) || !codeSection )
5280 kind = DYLD_CACHE_ADJ_V2_DELTA_32;
5281 break;
5282#if SUPPORT_ARCH_arm64
5283 case ld::Fixup::kindStoreARM64Page21:
5284 case ld::Fixup::kindStoreARM64GOTLoadPage21:
5285 case ld::Fixup::kindStoreARM64GOTLeaPage21:
5286 case ld::Fixup::kindStoreARM64TLVPLoadPage21:
ec29ba20 5287 case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPage21:
eaf282aa
A
5288 case ld::Fixup::kindStoreTargetAddressARM64Page21:
5289 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
5290 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21:
ec29ba20
A
5291 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21:
5292 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPage21:
eaf282aa
A
5293 if ( fromSectionIndex != toSectionIndex )
5294 kind = DYLD_CACHE_ADJ_V2_ARM64_ADRP;
5295 break;
5296 case ld::Fixup::kindStoreARM64PageOff12:
5297 case ld::Fixup::kindStoreARM64GOTLeaPageOff12:
5298 case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPageOff12:
5299 case ld::Fixup::kindStoreTargetAddressARM64PageOff12:
5300 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPageOff12:
5301 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12:
5302 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12:
5303 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12:
5304 if ( fromSectionIndex != toSectionIndex )
5305 kind = DYLD_CACHE_ADJ_V2_ARM64_OFF12;
5306 break;
5307 case ld::Fixup::kindStoreARM64Branch26:
5308 case ld::Fixup::kindStoreTargetAddressARM64Branch26:
5309 if ( fromSectionIndex != toSectionIndex )
5310 kind = DYLD_CACHE_ADJ_V2_ARM64_BR26;
5311 break;
5312#endif
5313 case ld::Fixup::kindStoreARMHigh16:
5314 case ld::Fixup::kindStoreARMLow16:
5315 if ( (fromSectionIndex != toSectionIndex) && (fromTarget == atom) ) {
5316 kind = DYLD_CACHE_ADJ_V2_ARM_MOVW_MOVT;
5317 }
5318 break;
5319 case ld::Fixup::kindStoreARMBranch24:
5320 case ld::Fixup::kindStoreTargetAddressARMBranch24:
5321 if ( fromSectionIndex != toSectionIndex )
5322 kind = DYLD_CACHE_ADJ_V2_ARM_BR24;
5323 break;
5324 case ld::Fixup::kindStoreThumbLow16:
5325 case ld::Fixup::kindStoreThumbHigh16:
5326 if ( (fromSectionIndex != toSectionIndex) && (fromTarget == atom) ) {
5327 kind = DYLD_CACHE_ADJ_V2_THUMB_MOVW_MOVT;
5328 }
5329 break;
5330 case ld::Fixup::kindStoreThumbBranch22:
5331 case ld::Fixup::kindStoreTargetAddressThumbBranch22:
5332 if ( fromSectionIndex != toSectionIndex )
5333 kind = DYLD_CACHE_ADJ_V2_THUMB_BR22;
5334 break;
5335 case ld::Fixup::kindSetTargetImageOffset:
5336 kind = DYLD_CACHE_ADJ_V2_IMAGE_OFF_32;
0a8dc3df 5337 accumulator = addressAndTarget(state, fit, &target);
eaf282aa
A
5338 assert(target != NULL);
5339 toSectionIndex = target->machoSection();
5340 toOffset = accumulator - state.atomToSection[target]->address;
5341 hadSubtract = true;
5342 break;
5343 default:
5344 break;
5345 }
5346 if ( fit->lastInCluster() ) {
5347 if ( (kind != 0) && (target != NULL) && (target->definition() != ld::Atom::definitionProxy) ) {
5348 if ( !hadSubtract && addend )
5349 toOffset += addend;
5350 assert(toSectionIndex != 255);
5351 if (log) fprintf(stderr, "from (%d.%s + 0x%llX) to (%d.%s + 0x%llX), kind=%d, atomAddr=0x%llX, sectAddr=0x%llx\n",
5352 fromSectionIndex, sect->sectionName(), fromOffset, toSectionIndex, state.atomToSection[target]->sectionName(),
5353 toOffset, kind, atom->finalAddress(), sect->address);
5354 _splitSegV2Infos.push_back(SplitSegInfoV2Entry(fromSectionIndex, fromOffset, toSectionIndex, toOffset, kind));
5355 }
5356 }
5357 }
5358 }
5359 }
5360}
5361
a645023d
A
5362
5363void OutputFile::writeMapFile(ld::Internal& state)
5364{
5365 if ( _options.generatedMapPath() != NULL ) {
5366 FILE* mapFile = fopen(_options.generatedMapPath(), "w");
5367 if ( mapFile != NULL ) {
5368 // write output path
5369 fprintf(mapFile, "# Path: %s\n", _options.outputFilePath());
5370 // write output architecure
5371 fprintf(mapFile, "# Arch: %s\n", _options.architectureName());
5372 // write UUID
5373 //if ( fUUIDAtom != NULL ) {
5374 // const uint8_t* uuid = fUUIDAtom->getUUID();
5375 // fprintf(mapFile, "# UUID: %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X \n",
5376 // uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
5377 // uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
5378 //}
5379 // write table of object files
ebf6f434
A
5380 std::map<const ld::File*, ld::File::Ordinal> readerToOrdinal;
5381 std::map<ld::File::Ordinal, const ld::File*> ordinalToReader;
a645023d
A
5382 std::map<const ld::File*, uint32_t> readerToFileOrdinal;
5383 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
5384 ld::Internal::FinalSection* sect = *sit;
5385 if ( sect->isSectionHidden() )
5386 continue;
5387 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
5388 const ld::Atom* atom = *ait;
0a8dc3df 5389 const ld::File* reader = atom->originalFile();
a645023d
A
5390 if ( reader == NULL )
5391 continue;
ebf6f434
A
5392 ld::File::Ordinal readerOrdinal = reader->ordinal();
5393 std::map<const ld::File*, ld::File::Ordinal>::iterator pos = readerToOrdinal.find(reader);
a645023d
A
5394 if ( pos == readerToOrdinal.end() ) {
5395 readerToOrdinal[reader] = readerOrdinal;
5396 ordinalToReader[readerOrdinal] = reader;
5397 }
5398 }
5399 }
0a8dc3df
A
5400 for (const ld::Atom* atom : state.deadAtoms) {
5401 const ld::File* reader = atom->originalFile();
5402 if ( reader == NULL )
5403 continue;
5404 ld::File::Ordinal readerOrdinal = reader->ordinal();
5405 std::map<const ld::File*, ld::File::Ordinal>::iterator pos = readerToOrdinal.find(reader);
5406 if ( pos == readerToOrdinal.end() ) {
5407 readerToOrdinal[reader] = readerOrdinal;
5408 ordinalToReader[readerOrdinal] = reader;
5409 }
5410 }
a645023d
A
5411 fprintf(mapFile, "# Object files:\n");
5412 fprintf(mapFile, "[%3u] %s\n", 0, "linker synthesized");
ebf6f434
A
5413 uint32_t fileIndex = 1;
5414 for(std::map<ld::File::Ordinal, const ld::File*>::iterator it = ordinalToReader.begin(); it != ordinalToReader.end(); ++it) {
5415 fprintf(mapFile, "[%3u] %s\n", fileIndex, it->second->path());
5416 readerToFileOrdinal[it->second] = fileIndex++;
a645023d
A
5417 }
5418 // write table of sections
5419 fprintf(mapFile, "# Sections:\n");
5420 fprintf(mapFile, "# Address\tSize \tSegment\tSection\n");
5421 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
5422 ld::Internal::FinalSection* sect = *sit;
5423 if ( sect->isSectionHidden() )
5424 continue;
5425 fprintf(mapFile, "0x%08llX\t0x%08llX\t%s\t%s\n", sect->address, sect->size,
5426 sect->segmentName(), sect->sectionName());
5427 }
5428 // write table of symbols
5429 fprintf(mapFile, "# Symbols:\n");
5430 fprintf(mapFile, "# Address\tSize \tFile Name\n");
5431 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
5432 ld::Internal::FinalSection* sect = *sit;
5433 if ( sect->isSectionHidden() )
5434 continue;
5435 //bool isCstring = (sect->type() == ld::Section::typeCString);
5436 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
5437 char buffer[4096];
5438 const ld::Atom* atom = *ait;
5439 const char* name = atom->name();
d425e388
A
5440 // don't add auto-stripped aliases to .map file
5441 if ( (atom->size() == 0) && (atom->symbolTableInclusion() == ld::Atom::symbolTableNotInFinalLinkedImages) )
5442 continue;
a645023d
A
5443 if ( atom->contentType() == ld::Atom::typeCString ) {
5444 strcpy(buffer, "literal string: ");
0a8dc3df
A
5445 const char* s = (char*)atom->rawContentPointer();
5446 char* e = &buffer[4094];
5447 for (char* b = &buffer[strlen(buffer)]; b < e;) {
5448 char c = *s++;
5449 if ( c == '\n' ) {
5450 *b++ = '\\';
5451 *b++ = 'n';
5452 }
5453 else {
5454 *b++ = c;
5455 }
5456 if ( c == '\0' )
5457 break;
5458 }
5459 buffer[4095] = '\0';
a645023d
A
5460 name = buffer;
5461 }
5462 else if ( (atom->contentType() == ld::Atom::typeCFI) && (strcmp(name, "FDE") == 0) ) {
5463 for (ld::Fixup::iterator fit = atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
5464 if ( (fit->kind == ld::Fixup::kindSetTargetAddress) && (fit->clusterSize == ld::Fixup::k1of4) ) {
599556ff
A
5465 if ( (fit->binding == ld::Fixup::bindingDirectlyBound)
5466 && (fit->u.target->section().type() == ld::Section::typeCode) ) {
a645023d
A
5467 strcpy(buffer, "FDE for: ");
5468 strlcat(buffer, fit->u.target->name(), 4096);
5469 name = buffer;
5470 }
5471 }
5472 }
5473 }
5474 else if ( atom->contentType() == ld::Atom::typeNonLazyPointer ) {
5475 strcpy(buffer, "non-lazy-pointer");
5476 for (ld::Fixup::iterator fit = atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
5477 if ( fit->binding == ld::Fixup::bindingsIndirectlyBound ) {
5478 strcpy(buffer, "non-lazy-pointer-to: ");
5479 strlcat(buffer, state.indirectBindingTable[fit->u.bindingIndex]->name(), 4096);
5480 break;
5481 }
5482 else if ( fit->binding == ld::Fixup::bindingDirectlyBound ) {
5483 strcpy(buffer, "non-lazy-pointer-to-local: ");
5484 strlcat(buffer, fit->u.target->name(), 4096);
5485 break;
5486 }
5487 }
5488 name = buffer;
5489 }
5490 fprintf(mapFile, "0x%08llX\t0x%08llX\t[%3u] %s\n", atom->finalAddress(), atom->size(),
0a8dc3df
A
5491 readerToFileOrdinal[atom->originalFile()], name);
5492 }
5493 }
5494 // preload check is hack until 26613948 is fixed
5495 if ( _options.deadCodeStrip() && (_options.outputKind() != Options::kPreload) ) {
5496 fprintf(mapFile, "\n");
5497 fprintf(mapFile, "# Dead Stripped Symbols:\n");
5498 fprintf(mapFile, "# \tSize \tFile Name\n");
5499 for (const ld::Atom* atom : state.deadAtoms) {
5500 char buffer[4096];
5501 const char* name = atom->name();
5502 // don't add auto-stripped aliases to .map file
5503 if ( (atom->size() == 0) && (atom->symbolTableInclusion() == ld::Atom::symbolTableNotInFinalLinkedImages) )
5504 continue;
5505 if ( atom->contentType() == ld::Atom::typeCString ) {
5506 strcpy(buffer, "literal string: ");
5507 const char* s = (char*)atom->rawContentPointer();
5508 char* e = &buffer[4094];
5509 for (char* b = &buffer[strlen(buffer)]; b < e;) {
5510 char c = *s++;
5511 if ( c == '\n' ) {
5512 *b++ = '\\';
5513 *b++ = 'n';
5514 }
5515 else {
5516 *b++ = c;
5517 }
5518 if ( c == '\0' )
5519 break;
5520 }
5521 buffer[4095] = '\0';
5522 name = buffer;
5523 }
5524 fprintf(mapFile, "<<dead>> \t0x%08llX\t[%3u] %s\n", atom->size(),
5525 readerToFileOrdinal[atom->originalFile()], name);
a645023d
A
5526 }
5527 }
5528 fclose(mapFile);
5529 }
5530 else {
5531 warning("could not write map file: %s\n", _options.generatedMapPath());
5532 }
5533 }
5534}
5535
82b4b32b
A
5536static std::string realPathString(const char* path)
5537{
5538 char realName[MAXPATHLEN];
5539 if ( realpath(path, realName) != NULL )
5540 return realName;
5541 return path;
5542}
5543
0a8dc3df
A
5544void OutputFile::writeJSONEntry(ld::Internal& state)
5545{
5546 if ( _options.traceEmitJSON() && (_options.UUIDMode() != Options::kUUIDNone) && (_options.traceOutputFile() != NULL) ) {
5547
5548 // Convert the UUID to a string.
5549 const uint8_t* uuid = _headersAndLoadCommandAtom->getUUID();
5550 uuid_string_t uuidString;
5551
5552 uuid_unparse(uuid, uuidString);
5553
5554 // Enumerate the dylibs.
5555 std::vector<const ld::dylib::File*> dynamicList;
5556 std::vector<const ld::dylib::File*> upwardList;
5557 std::vector<const ld::dylib::File*> reexportList;
5558
5559 for (const ld::dylib::File* dylib : _dylibsToLoad) {
5560
5561 if (dylib->willBeUpwardDylib()) {
5562
5563 upwardList.push_back(dylib);
5564 } else if (dylib->willBeReExported()) {
5565
5566 reexportList.push_back(dylib);
5567 } else {
5568
5569 dynamicList.push_back(dylib);
5570 }
5571 }
5572
5573 /*
5574 * Build the JSON entry.
5575 */
5576
5577 std::string jsonEntry = "{";
5578
5579 jsonEntry += "\"uuid\":\"" + std::string(uuidString) + "\",";
5580
5581 // installPath() returns -final_output for non-dylibs
5582 const char* lastNameSlash = strrchr(_options.installPath(), '/');
5583 const char* leafName = (lastNameSlash != NULL) ? lastNameSlash+1 : _options.outputFilePath();
5584 jsonEntry += "\"name\":\"" + std::string(leafName) + "\",";
5585
5586 jsonEntry += "\"arch\":\"" + std::string(_options.architectureName()) + "\"";
5587
5588 if (dynamicList.size() > 0) {
5589 jsonEntry += ",\"dynamic\":[";
5590 for (const ld::dylib::File* dylib : dynamicList) {
82b4b32b 5591 jsonEntry += "\"" + realPathString(dylib->path()) + "\"";
0a8dc3df
A
5592 if ((dylib != dynamicList.back())) {
5593 jsonEntry += ",";
5594 }
5595 }
5596 jsonEntry += "]";
5597 }
5598
5599 if (upwardList.size() > 0) {
5600 jsonEntry += ",\"upward-dynamic\":[";
5601 for (const ld::dylib::File* dylib : upwardList) {
82b4b32b 5602 jsonEntry += "\"" + realPathString(dylib->path()) + "\"";
0a8dc3df
A
5603 if ((dylib != upwardList.back())) {
5604 jsonEntry += ",";
5605 }
5606 }
5607 jsonEntry += "]";
5608 }
5609
5610 if (reexportList.size() > 0) {
5611 jsonEntry += ",\"re-exports\":[";
5612 for (const ld::dylib::File* dylib : reexportList) {
82b4b32b 5613 jsonEntry += "\"" + realPathString(dylib->path()) + "\"";
0a8dc3df
A
5614 if ((dylib != reexportList.back())) {
5615 jsonEntry += ",";
5616 }
5617 }
5618 jsonEntry += "]";
5619 }
5620
5621 if (state.archivePaths.size() > 0) {
5622 jsonEntry += ",\"archives\":[";
5623 for (const std::string& archivePath : state.archivePaths) {
82b4b32b 5624 jsonEntry += "\"" + realPathString(archivePath.c_str()) + "\"";
0a8dc3df
A
5625 if ((archivePath != state.archivePaths.back())) {
5626 jsonEntry += ",";
5627 }
5628 }
5629 jsonEntry += "]";
5630 }
82b4b32b
A
5631
5632 if (state.bundleLoader != NULL) {
5633 jsonEntry += ",\"bundle-loader\":";
5634 jsonEntry += "\"" + realPathString(state.bundleLoader->path()) + "\"";
5635 }
5636
0a8dc3df
A
5637 jsonEntry += "}\n";
5638
5639 // Write the JSON entry to the trace file.
82b4b32b 5640 _options.writeToTraceFile(jsonEntry.c_str(), jsonEntry.size());
0a8dc3df
A
5641 }
5642}
5643
a645023d
A
5644// used to sort atoms with debug notes
5645class DebugNoteSorter
5646{
5647public:
5648 bool operator()(const ld::Atom* left, const ld::Atom* right) const
5649 {
5650 // first sort by reader
ebf6f434
A
5651 ld::File::Ordinal leftFileOrdinal = left->file()->ordinal();
5652 ld::File::Ordinal rightFileOrdinal = right->file()->ordinal();
a645023d
A
5653 if ( leftFileOrdinal!= rightFileOrdinal)
5654 return (leftFileOrdinal < rightFileOrdinal);
5655
5656 // then sort by atom objectAddress
afe874b1
A
5657 uint64_t leftAddr = left->finalAddress();
5658 uint64_t rightAddr = right->finalAddress();
a645023d
A
5659 return leftAddr < rightAddr;
5660 }
5661};
5662
5663
a645023d
A
5664const char* OutputFile::assureFullPath(const char* path)
5665{
5666 if ( path[0] == '/' )
5667 return path;
5668 char cwdbuff[MAXPATHLEN];
5669 if ( getcwd(cwdbuff, MAXPATHLEN) != NULL ) {
5670 char* result;
5671 asprintf(&result, "%s/%s", cwdbuff, path);
5672 if ( result != NULL )
5673 return result;
5674 }
5675 return path;
5676}
5677
599556ff
A
5678static time_t fileModTime(const char* path) {
5679 struct stat statBuffer;
5680 if ( stat(path, &statBuffer) == 0 ) {
5681 return statBuffer.st_mtime;
5682 }
5683 return 0;
5684}
5685
5686
a645023d
A
5687void OutputFile::synthesizeDebugNotes(ld::Internal& state)
5688{
5689 // -S means don't synthesize debug map
5690 if ( _options.debugInfoStripping() == Options::kDebugInfoNone )
5691 return;
5692 // make a vector of atoms that come from files compiled with dwarf debug info
5693 std::vector<const ld::Atom*> atomsNeedingDebugNotes;
5694 std::set<const ld::Atom*> atomsWithStabs;
bee7e226 5695 std::set<const ld::relocatable::File*> filesSeenWithStabs;
a645023d
A
5696 atomsNeedingDebugNotes.reserve(1024);
5697 const ld::relocatable::File* objFile = NULL;
5698 bool objFileHasDwarf = false;
5699 bool objFileHasStabs = false;
5700 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
5701 ld::Internal::FinalSection* sect = *sit;
5702 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
5703 const ld::Atom* atom = *ait;
5704 // no stabs for atoms that would not be in the symbol table
5705 if ( atom->symbolTableInclusion() == ld::Atom::symbolTableNotIn )
5706 continue;
5707 if ( atom->symbolTableInclusion() == ld::Atom::symbolTableNotInFinalLinkedImages )
5708 continue;
d425e388
A
5709 if ( atom->symbolTableInclusion() == ld::Atom::symbolTableInWithRandomAutoStripLabel )
5710 continue;
a645023d
A
5711 // no stabs for absolute symbols
5712 if ( atom->definition() == ld::Atom::definitionAbsolute )
5713 continue;
5714 // no stabs for .eh atoms
5715 if ( atom->contentType() == ld::Atom::typeCFI )
5716 continue;
d425e388
A
5717 // no stabs for string literal atoms
5718 if ( atom->contentType() == ld::Atom::typeCString )
5719 continue;
5720 // no stabs for kernel dtrace probes
5721 if ( (_options.outputKind() == Options::kStaticExecutable) && (strncmp(atom->name(), "__dtrace_probe$", 15) == 0) )
5722 continue;
a645023d
A
5723 const ld::File* file = atom->file();
5724 if ( file != NULL ) {
5725 if ( file != objFile ) {
5726 objFileHasDwarf = false;
5727 objFileHasStabs = false;
5728 objFile = dynamic_cast<const ld::relocatable::File*>(file);
5729 if ( objFile != NULL ) {
5730 switch ( objFile->debugInfo() ) {
5731 case ld::relocatable::File::kDebugInfoNone:
5732 break;
5733 case ld::relocatable::File::kDebugInfoDwarf:
5734 objFileHasDwarf = true;
5735 break;
5736 case ld::relocatable::File::kDebugInfoStabs:
5737 case ld::relocatable::File::kDebugInfoStabsUUID:
5738 objFileHasStabs = true;
5739 break;
5740 }
5741 }
5742 }
5743 if ( objFileHasDwarf )
5744 atomsNeedingDebugNotes.push_back(atom);
bee7e226 5745 if ( objFileHasStabs ) {
a645023d 5746 atomsWithStabs.insert(atom);
bee7e226
A
5747 if ( objFile != NULL )
5748 filesSeenWithStabs.insert(objFile);
5749 }
a645023d
A
5750 }
5751 }
5752 }
5753
5754 // sort by file ordinal then atom ordinal
5755 std::sort(atomsNeedingDebugNotes.begin(), atomsNeedingDebugNotes.end(), DebugNoteSorter());
5756
599556ff 5757 // <rdar://problem/17689030> Add -add_ast_path option to linker which add N_AST stab entry to output
f410558f 5758 std::set<std::string> seenAstPaths;
599556ff
A
5759 const std::vector<const char*>& astPaths = _options.astFilePaths();
5760 for (std::vector<const char*>::const_iterator it=astPaths.begin(); it != astPaths.end(); it++) {
5761 const char* path = *it;
f410558f
A
5762 if ( seenAstPaths.count(path) != 0 )
5763 continue;
5764 seenAstPaths.insert(path);
599556ff
A
5765 // emit N_AST
5766 ld::relocatable::File::Stab astStab;
5767 astStab.atom = NULL;
5768 astStab.type = N_AST;
5769 astStab.other = 0;
5770 astStab.desc = 0;
f410558f
A
5771 if ( _options.zeroModTimeInDebugMap() )
5772 astStab.value = 0;
5773 else
5774 astStab.value = fileModTime(path);
599556ff
A
5775 astStab.string = path;
5776 state.stabs.push_back(astStab);
5777 }
5778
a645023d
A
5779 // synthesize "debug notes" and add them to master stabs vector
5780 const char* dirPath = NULL;
5781 const char* filename = NULL;
5782 bool wroteStartSO = false;
5783 state.stabs.reserve(atomsNeedingDebugNotes.size()*4);
d425e388 5784 std::unordered_set<const char*, CStringHash, CStringEquals> seenFiles;
a645023d
A
5785 for (std::vector<const ld::Atom*>::iterator it=atomsNeedingDebugNotes.begin(); it != atomsNeedingDebugNotes.end(); it++) {
5786 const ld::Atom* atom = *it;
5787 const ld::File* atomFile = atom->file();
5788 const ld::relocatable::File* atomObjFile = dynamic_cast<const ld::relocatable::File*>(atomFile);
afe874b1 5789 //fprintf(stderr, "debug note for %s\n", atom->name());
599556ff
A
5790 const char* newPath = atom->translationUnitSource();
5791 if ( newPath != NULL ) {
5792 const char* newDirPath;
5793 const char* newFilename;
5794 const char* lastSlash = strrchr(newPath, '/');
5795 if ( lastSlash == NULL )
5796 continue;
5797 newFilename = lastSlash+1;
5798 char* temp = strdup(newPath);
5799 newDirPath = temp;
5800 // gdb like directory SO's to end in '/', but dwarf DW_AT_comp_dir usually does not have trailing '/'
5801 temp[lastSlash-newPath+1] = '\0';
a645023d 5802 // need SO's whenever the translation unit source file changes
599556ff 5803 if ( (filename == NULL) || (strcmp(newFilename,filename) != 0) || (strcmp(newDirPath,dirPath) != 0)) {
a645023d
A
5804 if ( filename != NULL ) {
5805 // translation unit change, emit ending SO
5806 ld::relocatable::File::Stab endFileStab;
5807 endFileStab.atom = NULL;
5808 endFileStab.type = N_SO;
5809 endFileStab.other = 1;
5810 endFileStab.desc = 0;
5811 endFileStab.value = 0;
5812 endFileStab.string = "";
5813 state.stabs.push_back(endFileStab);
5814 }
5815 // new translation unit, emit start SO's
5816 ld::relocatable::File::Stab dirPathStab;
5817 dirPathStab.atom = NULL;
5818 dirPathStab.type = N_SO;
5819 dirPathStab.other = 0;
5820 dirPathStab.desc = 0;
5821 dirPathStab.value = 0;
5822 dirPathStab.string = newDirPath;
5823 state.stabs.push_back(dirPathStab);
5824 ld::relocatable::File::Stab fileStab;
5825 fileStab.atom = NULL;
5826 fileStab.type = N_SO;
5827 fileStab.other = 0;
5828 fileStab.desc = 0;
5829 fileStab.value = 0;
5830 fileStab.string = newFilename;
5831 state.stabs.push_back(fileStab);
5832 // Synthesize OSO for start of file
5833 ld::relocatable::File::Stab objStab;
5834 objStab.atom = NULL;
5835 objStab.type = N_OSO;
5836 // <rdar://problem/6337329> linker should put cpusubtype in n_sect field of nlist entry for N_OSO debug note entries
5837 objStab.other = atomFile->cpuSubType();
5838 objStab.desc = 1;
5839 if ( atomObjFile != NULL ) {
5840 objStab.string = assureFullPath(atomObjFile->debugInfoPath());
f410558f
A
5841 if ( _options.zeroModTimeInDebugMap() )
5842 objStab.value = 0;
5843 else
5844 objStab.value = atomObjFile->debugInfoModificationTime();
a645023d
A
5845 }
5846 else {
5847 objStab.string = assureFullPath(atomFile->path());
f410558f
A
5848 if ( _options.zeroModTimeInDebugMap() )
5849 objStab.value = 0;
5850 else
5851 objStab.value = atomFile->modificationTime();
a645023d
A
5852 }
5853 state.stabs.push_back(objStab);
5854 wroteStartSO = true;
5855 // add the source file path to seenFiles so it does not show up in SOLs
5856 seenFiles.insert(newFilename);
5857 char* fullFilePath;
afe874b1 5858 asprintf(&fullFilePath, "%s%s", newDirPath, newFilename);
a645023d
A
5859 // add both leaf path and full path
5860 seenFiles.insert(fullFilePath);
f410558f
A
5861
5862 // <rdar://problem/34121435> Add linker support for propagating N_AST debug notes from .o files to linked image
5863 if ( const std::vector<relocatable::File::AstTimeAndPath>* asts = atomObjFile->astFiles() ) {
5864 for (const relocatable::File::AstTimeAndPath& file : *asts) {
5865 const char* cpath = file.path.c_str();
5866 if ( seenAstPaths.count(cpath) != 0 )
5867 continue;
5868 seenAstPaths.insert(cpath);
5869 // generate N_AST in output
5870 ld::relocatable::File::Stab astStab;
5871 astStab.atom = NULL;
5872 astStab.type = N_AST;
5873 astStab.other = 0;
5874 astStab.desc = 0;
5875 astStab.value = file.time;
5876 astStab.string = cpath;
5877 state.stabs.push_back(astStab);
5878 }
5879 }
a645023d
A
5880 }
5881 filename = newFilename;
5882 dirPath = newDirPath;
5883 if ( atom->section().type() == ld::Section::typeCode ) {
5884 // Synthesize BNSYM and start FUN stabs
5885 ld::relocatable::File::Stab beginSym;
5886 beginSym.atom = atom;
5887 beginSym.type = N_BNSYM;
5888 beginSym.other = 1;
5889 beginSym.desc = 0;
5890 beginSym.value = 0;
5891 beginSym.string = "";
5892 state.stabs.push_back(beginSym);
5893 ld::relocatable::File::Stab startFun;
5894 startFun.atom = atom;
5895 startFun.type = N_FUN;
5896 startFun.other = 1;
5897 startFun.desc = 0;
5898 startFun.value = 0;
5899 startFun.string = atom->name();
5900 state.stabs.push_back(startFun);
5901 // Synthesize any SOL stabs needed
5902 const char* curFile = NULL;
5903 for (ld::Atom::LineInfo::iterator lit = atom->beginLineInfo(); lit != atom->endLineInfo(); ++lit) {
5904 if ( lit->fileName != curFile ) {
5905 if ( seenFiles.count(lit->fileName) == 0 ) {
5906 seenFiles.insert(lit->fileName);
5907 ld::relocatable::File::Stab sol;
5908 sol.atom = 0;
5909 sol.type = N_SOL;
5910 sol.other = 0;
5911 sol.desc = 0;
5912 sol.value = 0;
5913 sol.string = lit->fileName;
5914 state.stabs.push_back(sol);
5915 }
5916 curFile = lit->fileName;
5917 }
5918 }
5919 // Synthesize end FUN and ENSYM stabs
5920 ld::relocatable::File::Stab endFun;
5921 endFun.atom = atom;
5922 endFun.type = N_FUN;
5923 endFun.other = 0;
5924 endFun.desc = 0;
5925 endFun.value = 0;
5926 endFun.string = "";
5927 state.stabs.push_back(endFun);
5928 ld::relocatable::File::Stab endSym;
5929 endSym.atom = atom;
5930 endSym.type = N_ENSYM;
5931 endSym.other = 1;
5932 endSym.desc = 0;
5933 endSym.value = 0;
5934 endSym.string = "";
5935 state.stabs.push_back(endSym);
5936 }
5937 else {
5938 ld::relocatable::File::Stab globalsStab;
5939 const char* name = atom->name();
5940 if ( atom->scope() == ld::Atom::scopeTranslationUnit ) {
5941 // Synthesize STSYM stab for statics
5942 globalsStab.atom = atom;
5943 globalsStab.type = N_STSYM;
5944 globalsStab.other = 1;
5945 globalsStab.desc = 0;
5946 globalsStab.value = 0;
5947 globalsStab.string = name;
5948 state.stabs.push_back(globalsStab);
5949 }
5950 else {
5951 // Synthesize GSYM stab for other globals
5952 globalsStab.atom = atom;
5953 globalsStab.type = N_GSYM;
5954 globalsStab.other = 1;
5955 globalsStab.desc = 0;
5956 globalsStab.value = 0;
5957 globalsStab.string = name;
5958 state.stabs.push_back(globalsStab);
5959 }
5960 }
5961 }
5962 }
5963
5964 if ( wroteStartSO ) {
5965 // emit ending SO
5966 ld::relocatable::File::Stab endFileStab;
5967 endFileStab.atom = NULL;
5968 endFileStab.type = N_SO;
5969 endFileStab.other = 1;
5970 endFileStab.desc = 0;
5971 endFileStab.value = 0;
5972 endFileStab.string = "";
5973 state.stabs.push_back(endFileStab);
5974 }
bee7e226
A
5975
5976 // copy any stabs from .o files
5977 bool deadStripping = _options.deadCodeStrip();
5978 for (const ld::relocatable::File* obj : filesSeenWithStabs) {
5979 const std::vector<ld::relocatable::File::Stab>* filesStabs = obj->stabs();
5980 if ( filesStabs != NULL ) {
5981 for (const ld::relocatable::File::Stab& stab : *filesStabs ) {
5982 // ignore stabs associated with atoms that were dead stripped or coalesced away
5983 if ( (stab.atom != NULL) && (atomsWithStabs.count(stab.atom) == 0) )
5984 continue;
5985 // <rdar://problem/8284718> Value of N_SO stabs should be address of first atom from translation unit
5986 if ( (stab.type == N_SO) && (stab.string != NULL) && (stab.string[0] != '\0') ) {
5987 uint64_t lowestAtomAddress = 0;
5988 const ld::Atom* lowestAddressAtom = NULL;
5989 for (const ld::relocatable::File::Stab& stab2 : *filesStabs ) {
5990 if ( stab2.atom == NULL )
a645023d 5991 continue;
bee7e226
A
5992 // skip over atoms that were dead stripped
5993 if ( deadStripping && !stab2.atom->live() )
5994 continue;
5995 if ( stab2.atom->coalescedAway() )
5996 continue;
5997 uint64_t atomAddr = stab2.atom->objectAddress();
5998 if ( (lowestAddressAtom == NULL) || (atomAddr < lowestAtomAddress) ) {
5999 lowestAddressAtom = stab2.atom;
6000 lowestAtomAddress = atomAddr;
a645023d 6001 }
a645023d 6002 }
bee7e226
A
6003 ld::relocatable::File::Stab altStab = stab;
6004 altStab.atom = lowestAddressAtom;
6005 state.stabs.push_back(altStab);
6006 }
6007 else {
6008 state.stabs.push_back(stab);
a645023d
A
6009 }
6010 }
6011 }
6012 }
f410558f 6013
a645023d
A
6014}
6015
6016
6017} // namespace tool
6018} // namespace ld
6019