]> git.saurik.com Git - apple/ld64.git/blame - src/ld/LinkEditClassic.hpp
ld64-409.12.tar.gz
[apple/ld64.git] / src / ld / LinkEditClassic.hpp
CommitLineData
a645023d
A
1/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-*
2 *
3 * Copyright (c) 2009-2010 Apple Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
12 * file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25#ifndef __LINKEDIT_CLASSIC_HPP__
26#define __LINKEDIT_CLASSIC_HPP__
27
28#include <stdlib.h>
29#include <sys/types.h>
30#include <errno.h>
31#include <limits.h>
32#include <unistd.h>
33
34#include <vector>
d425e388 35#include <unordered_map>
a645023d
A
36
37#include "Options.h"
38#include "ld.hpp"
39#include "Architectures.hpp"
40#include "MachOFileAbstraction.hpp"
41
42namespace ld {
43namespace tool {
44
45
46
47class ClassicLinkEditAtom : public ld::Atom
48{
49public:
50
51 // overrides of ld::Atom
52 virtual ld::File* file() const { return NULL; }
a645023d
A
53 virtual uint64_t objectAddress() const { return 0; }
54
55 virtual void encode() = 0;
56 virtual bool hasStabs(uint32_t& ssos, uint32_t& ssoe, uint32_t& sos, uint32_t& soe) { return false; }
57
58 ClassicLinkEditAtom(const Options& opts, ld::Internal& state,
59 OutputFile& writer, const ld::Section& sect,
60 unsigned int pointerSize)
61 : ld::Atom(sect, ld::Atom::definitionRegular,
62 ld::Atom::combineNever, ld::Atom::scopeTranslationUnit,
63 ld::Atom::typeUnclassified, ld::Atom::symbolTableNotIn,
64 false, false, false, ld::Atom::Alignment(log2(pointerSize))),
65 _options(opts), _state(state), _writer(writer) { }
66protected:
67 const Options& _options;
68 ld::Internal& _state;
69 OutputFile& _writer;
70};
71
72
73
74class StringPoolAtom : public ClassicLinkEditAtom
75{
76public:
77 StringPoolAtom(const Options& opts, ld::Internal& state,
78 OutputFile& writer, int pointerSize);
79
80 // overrides of ld::Atom
81 virtual const char* name() const { return "string pool"; }
82 virtual uint64_t size() const;
83 virtual void copyRawContent(uint8_t buffer[]) const;
84 // overrides of ClassicLinkEditAtom
85 virtual void encode() { }
86
87 int32_t add(const char* name);
88 int32_t addUnique(const char* name);
89 int32_t emptyString() { return 1; }
90 const char* stringForIndex(int32_t) const;
91 uint32_t currentOffset();
92
93private:
a645023d 94 enum { kBufferSize = 0x01000000 };
d425e388 95 typedef std::unordered_map<const char*, int32_t, CStringHash, CStringEquals> StringToOffset;
a645023d
A
96
97 const uint32_t _pointerSize;
98 std::vector<char*> _fullBuffers;
99 char* _currentBuffer;
100 uint32_t _currentBufferUsed;
101 StringToOffset _uniqueStrings;
102
103 static ld::Section _s_section;
104};
105
106ld::Section StringPoolAtom::_s_section("__LINKEDIT", "__string_pool", ld::Section::typeLinkEdit, true);
107
108
109StringPoolAtom::StringPoolAtom(const Options& opts, ld::Internal& state, OutputFile& writer, int pointerSize)
110 : ClassicLinkEditAtom(opts, state, writer, _s_section, pointerSize),
111 _pointerSize(pointerSize), _currentBuffer(NULL), _currentBufferUsed(0)
112{
113 _currentBuffer = new char[kBufferSize];
114 // burn first byte of string pool (so zero is never a valid string offset)
115 _currentBuffer[_currentBufferUsed++] = ' ';
116 // make offset 1 always point to an empty string
117 _currentBuffer[_currentBufferUsed++] = '\0';
118}
119
120uint64_t StringPoolAtom::size() const
121{
122 // pointer size align size
123 return (kBufferSize * _fullBuffers.size() + _currentBufferUsed + _pointerSize-1) & (-_pointerSize);
124}
125
126void StringPoolAtom::copyRawContent(uint8_t buffer[]) const
127{
128 uint64_t offset = 0;
129 for (unsigned int i=0; i < _fullBuffers.size(); ++i) {
130 memcpy(&buffer[offset], _fullBuffers[i], kBufferSize);
131 offset += kBufferSize;
132 }
133 memcpy(&buffer[offset], _currentBuffer, _currentBufferUsed);
134 // zero fill end to align
135 offset += _currentBufferUsed;
136 while ( (offset % _pointerSize) != 0 )
137 buffer[offset++] = 0;
138}
139
140int32_t StringPoolAtom::add(const char* str)
141{
142 int32_t offset = kBufferSize * _fullBuffers.size() + _currentBufferUsed;
143 int lenNeeded = strlcpy(&_currentBuffer[_currentBufferUsed], str, kBufferSize-_currentBufferUsed)+1;
144 if ( (_currentBufferUsed+lenNeeded) < kBufferSize ) {
145 _currentBufferUsed += lenNeeded;
146 }
147 else {
148 int copied = kBufferSize-_currentBufferUsed-1;
149 // change trailing '\0' that strlcpy added to real char
150 _currentBuffer[kBufferSize-1] = str[copied];
151 // alloc next buffer
152 _fullBuffers.push_back(_currentBuffer);
153 _currentBuffer = new char[kBufferSize];
154 _currentBufferUsed = 0;
155 // append rest of string
156 this->add(&str[copied+1]);
157 }
158 return offset;
159}
160
161uint32_t StringPoolAtom::currentOffset()
162{
163 return kBufferSize * _fullBuffers.size() + _currentBufferUsed;
164}
165
166
167int32_t StringPoolAtom::addUnique(const char* str)
168{
169 StringToOffset::iterator pos = _uniqueStrings.find(str);
170 if ( pos != _uniqueStrings.end() ) {
171 return pos->second;
172 }
173 else {
174 int32_t offset = this->add(str);
175 _uniqueStrings[str] = offset;
176 return offset;
177 }
178}
179
180
181const char* StringPoolAtom::stringForIndex(int32_t index) const
182{
183 int32_t currentBufferStartIndex = kBufferSize * _fullBuffers.size();
184 int32_t maxIndex = currentBufferStartIndex + _currentBufferUsed;
185 // check for out of bounds
186 if ( index > maxIndex )
187 return "";
188 // check for index in _currentBuffer
189 if ( index > currentBufferStartIndex )
190 return &_currentBuffer[index-currentBufferStartIndex];
191 // otherwise index is in a full buffer
192 uint32_t fullBufferIndex = index/kBufferSize;
193 return &_fullBuffers[fullBufferIndex][index-(kBufferSize*fullBufferIndex)];
194}
195
196
197
198template <typename A>
199class SymbolTableAtom : public ClassicLinkEditAtom
200{
201public:
202 SymbolTableAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
203 : ClassicLinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)),
204 _stabsStringsOffsetStart(0), _stabsStringsOffsetEnd(0),
205 _stabsIndexStart(0), _stabsIndexEnd(0) { }
206
207 // overrides of ld::Atom
208 virtual const char* name() const { return "symbol table"; }
209 virtual uint64_t size() const;
210 virtual void copyRawContent(uint8_t buffer[]) const;
211 // overrides of ClassicLinkEditAtom
212 virtual void encode();
213 virtual bool hasStabs(uint32_t& ssos, uint32_t& ssoe, uint32_t& sos, uint32_t& soe);
214
215private:
216 typedef typename A::P P;
217 typedef typename A::P::E E;
218 typedef typename A::P::uint_t pint_t;
219
220 bool addLocal(const ld::Atom* atom, StringPoolAtom* pool);
221 void addGlobal(const ld::Atom* atom, StringPoolAtom* pool);
222 void addImport(const ld::Atom* atom, StringPoolAtom* pool);
223 uint8_t classicOrdinalForProxy(const ld::Atom* atom);
224 uint32_t stringOffsetForStab(const ld::relocatable::File::Stab& stab, StringPoolAtom* pool);
225 uint64_t valueForStab(const ld::relocatable::File::Stab& stab);
226 uint8_t sectionIndexForStab(const ld::relocatable::File::Stab& stab);
599556ff 227 bool isAltEntry(const ld::Atom* atom);
a645023d
A
228
229 mutable std::vector<macho_nlist<P> > _globals;
230 mutable std::vector<macho_nlist<P> > _locals;
231 mutable std::vector<macho_nlist<P> > _imports;
232
233 uint32_t _stabsStringsOffsetStart;
234 uint32_t _stabsStringsOffsetEnd;
235 uint32_t _stabsIndexStart;
236 uint32_t _stabsIndexEnd;
237
238 static ld::Section _s_section;
ebf6f434
A
239 static int _s_anonNameIndex;
240
a645023d
A
241};
242
243template <typename A>
244ld::Section SymbolTableAtom<A>::_s_section("__LINKEDIT", "__symbol_table", ld::Section::typeLinkEdit, true);
245
ebf6f434
A
246template <typename A>
247int SymbolTableAtom<A>::_s_anonNameIndex = 1;
a645023d
A
248
249
599556ff
A
250template <typename A>
251bool SymbolTableAtom<A>::isAltEntry(const ld::Atom* atom)
252{
253 // alt entries have a group subordinate reference to the previous atom
254 for (ld::Fixup::iterator fit = atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
255 if ( fit->kind == ld::Fixup::kindNoneGroupSubordinate ) {
256 if ( fit->binding == Fixup::bindingDirectlyBound ) {
257 const Atom* prevAtom = fit->u.target;
258 assert(prevAtom != NULL);
259 for (ld::Fixup::iterator fit2 = prevAtom->fixupsBegin(); fit2 != prevAtom->fixupsEnd(); ++fit2) {
260 if ( fit2->kind == ld::Fixup::kindNoneFollowOn ) {
261 if ( fit2->binding == Fixup::bindingDirectlyBound ) {
262 if ( fit2->u.target == atom )
263 return true;
264 }
265 }
266 }
267 }
268 }
269 }
270 return false;
271}
272
a645023d
A
273template <typename A>
274bool SymbolTableAtom<A>::addLocal(const ld::Atom* atom, StringPoolAtom* pool)
275{
276 macho_nlist<P> entry;
a645023d
A
277 assert(atom->symbolTableInclusion() != ld::Atom::symbolTableNotIn);
278
279 // set n_strx
280 const char* symbolName = atom->name();
281 char anonName[32];
282 if ( this->_options.outputKind() == Options::kObjectFile ) {
283 if ( atom->contentType() == ld::Atom::typeCString ) {
284 if ( atom->combine() == ld::Atom::combineByNameAndContent ) {
285 // don't use 'l' labels for x86_64 strings
286 // <rdar://problem/6605499> x86_64 obj-c runtime confused when static lib is stripped
ebf6f434 287 sprintf(anonName, "LC%u", _s_anonNameIndex++);
a645023d
A
288 symbolName = anonName;
289 }
290 }
291 else if ( atom->contentType() == ld::Atom::typeCFI ) {
292 if ( _options.removeEHLabels() )
293 return false;
294 // synthesize .eh name
295 if ( strcmp(atom->name(), "CIE") == 0 )
296 symbolName = "EH_Frame1";
297 else
298 symbolName = "func.eh";
299 }
300 else if ( atom->symbolTableInclusion() == ld::Atom::symbolTableInWithRandomAutoStripLabel ) {
301 // make auto-strip anonymous name for symbol
ebf6f434 302 sprintf(anonName, "l%03u", _s_anonNameIndex++);
a645023d
A
303 symbolName = anonName;
304 }
305 }
306 entry.set_n_strx(pool->add(symbolName));
307
308 // set n_type
309 uint8_t type = N_SECT;
310 if ( atom->definition() == ld::Atom::definitionAbsolute ) {
311 type = N_ABS;
312 }
313 else if ( (atom->section().type() == ld::Section::typeObjC1Classes)
314 && (this->_options.outputKind() == Options::kObjectFile) ) {
315 // __OBJC __class has floating abs symbols for each class data structure
316 type = N_ABS;
317 }
318 if ( atom->scope() == ld::Atom::scopeLinkageUnit )
319 type |= N_PEXT;
320 entry.set_n_type(type);
321
322 // set n_sect (section number of implementation )
323 if ( atom->definition() == ld::Atom::definitionAbsolute )
324 entry.set_n_sect(0);
325 else
326 entry.set_n_sect(atom->machoSection());
327
328 // set n_desc
329 uint16_t desc = 0;
330 if ( atom->symbolTableInclusion() == ld::Atom::symbolTableInAndNeverStrip )
331 desc |= REFERENCED_DYNAMICALLY;
332 if ( atom->dontDeadStrip() && (this->_options.outputKind() == Options::kObjectFile) )
333 desc |= N_NO_DEAD_STRIP;
334 if ( (atom->definition() == ld::Atom::definitionRegular) && (atom->combine() == ld::Atom::combineByName) )
335 desc |= N_WEAK_DEF;
336 if ( atom->isThumb() )
337 desc |= N_ARM_THUMB_DEF;
599556ff
A
338 if ( (this->_options.outputKind() == Options::kObjectFile) && this->_state.allObjectFilesScatterable && isAltEntry(atom) )
339 desc |= N_ALT_ENTRY;
a645023d
A
340 entry.set_n_desc(desc);
341
342 // set n_value ( address this symbol will be at if this executable is loaded at it preferred address )
343 if ( atom->definition() == ld::Atom::definitionAbsolute )
344 entry.set_n_value(atom->objectAddress());
345 else
346 entry.set_n_value(atom->finalAddress());
347
348 // add to array
349 _locals.push_back(entry);
350 return true;
351}
352
353
354template <typename A>
355void SymbolTableAtom<A>::addGlobal(const ld::Atom* atom, StringPoolAtom* pool)
356{
357 macho_nlist<P> entry;
358
359 // set n_strx
ebf6f434
A
360 const char* symbolName = atom->name();
361 char anonName[32];
362 if ( this->_options.outputKind() == Options::kObjectFile ) {
363 if ( atom->symbolTableInclusion() == ld::Atom::symbolTableInWithRandomAutoStripLabel ) {
364 // make auto-strip anonymous name for symbol
365 sprintf(anonName, "l%03u", _s_anonNameIndex++);
366 symbolName = anonName;
367 }
368 }
369 entry.set_n_strx(pool->add(symbolName));
a645023d
A
370
371 // set n_type
372 if ( atom->definition() == ld::Atom::definitionAbsolute ) {
373 entry.set_n_type(N_EXT | N_ABS);
374 }
375 else if ( (atom->section().type() == ld::Section::typeObjC1Classes)
376 && (this->_options.outputKind() == Options::kObjectFile) ) {
377 // __OBJC __class has floating abs symbols for each class data structure
378 entry.set_n_type(N_EXT | N_ABS);
379 }
380 else if ( (atom->definition() == ld::Atom::definitionProxy) && (atom->scope() == ld::Atom::scopeGlobal) ) {
381 entry.set_n_type(N_EXT | N_INDR);
382 }
383 else {
384 entry.set_n_type(N_EXT | N_SECT);
385 if ( (atom->scope() == ld::Atom::scopeLinkageUnit) && (this->_options.outputKind() == Options::kObjectFile) ) {
386 if ( this->_options.keepPrivateExterns() )
387 entry.set_n_type(N_EXT | N_SECT | N_PEXT);
388 }
389 else if ( (atom->symbolTableInclusion() == ld::Atom::symbolTableInAndNeverStrip)
ebf6f434
A
390 && (atom->section().type() == ld::Section::typeMachHeader)
391 && !_options.positionIndependentExecutable() ) {
392 // the __mh_execute_header is historical magic in non-pie executabls and must be an absolute symbol
a645023d
A
393 entry.set_n_type(N_EXT | N_ABS);
394 }
395 }
396
397 // set n_sect (section number of implementation)
398 if ( atom->definition() == ld::Atom::definitionAbsolute )
399 entry.set_n_sect(0);
400 else if ( (atom->definition() == ld::Atom::definitionProxy) && (atom->scope() == ld::Atom::scopeGlobal) )
401 entry.set_n_sect(0);
402 else
403 entry.set_n_sect(atom->machoSection());
404
405 // set n_desc
406 uint16_t desc = 0;
407 if ( atom->isThumb() )
408 desc |= N_ARM_THUMB_DEF;
409 if ( atom->symbolTableInclusion() == ld::Atom::symbolTableInAndNeverStrip )
410 desc |= REFERENCED_DYNAMICALLY;
411 if ( (atom->contentType() == ld::Atom::typeResolver) && (this->_options.outputKind() == Options::kObjectFile) )
412 desc |= N_SYMBOL_RESOLVER;
413 if ( atom->dontDeadStrip() && (this->_options.outputKind() == Options::kObjectFile) )
414 desc |= N_NO_DEAD_STRIP;
599556ff
A
415 if ( (this->_options.outputKind() == Options::kObjectFile) && this->_state.allObjectFilesScatterable && isAltEntry(atom) )
416 desc |= N_ALT_ENTRY;
a645023d
A
417 if ( (atom->definition() == ld::Atom::definitionRegular) && (atom->combine() == ld::Atom::combineByName) ) {
418 desc |= N_WEAK_DEF;
419 // <rdar://problem/6783167> support auto hidden weak symbols: .weak_def_can_be_hidden
420 if ( (atom->scope() == ld::Atom::scopeGlobal) && atom->autoHide() && (this->_options.outputKind() == Options::kObjectFile) )
421 desc |= N_WEAK_REF;
422 }
423 entry.set_n_desc(desc);
424
425 // set n_value ( address this symbol will be at if this executable is loaded at it preferred address )
426 if ( atom->definition() == ld::Atom::definitionAbsolute )
427 entry.set_n_value(atom->objectAddress());
428 else if ( (atom->definition() == ld::Atom::definitionProxy) && (atom->scope() == ld::Atom::scopeGlobal) ) {
429 if ( atom->isAlias() ) {
430 // this re-export also renames
431 for (ld::Fixup::iterator fit = atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
432 if ( fit->kind == ld::Fixup::kindNoneFollowOn ) {
433 assert(fit->binding == ld::Fixup::bindingDirectlyBound);
434 entry.set_n_value(pool->add(fit->u.target->name()));
435 }
436 }
437 }
438 else
439 entry.set_n_value(entry.n_strx());
440 }
441 else
442 entry.set_n_value(atom->finalAddress());
443
444 // add to array
445 _globals.push_back(entry);
446}
447
448template <typename A>
449uint8_t SymbolTableAtom<A>::classicOrdinalForProxy(const ld::Atom* atom)
450{
451 assert(atom->definition() == ld::Atom::definitionProxy);
452 // when linking for flat-namespace ordinals are always zero
453 if ( _options.nameSpace() != Options::kTwoLevelNameSpace )
454 return 0;
455 const ld::dylib::File* dylib = dynamic_cast<const ld::dylib::File*>(atom->file());
456 // when linking -undefined dynamic_lookup, unbound symbols use DYNAMIC_LOOKUP_ORDINAL
457 if ( dylib == NULL ) {
458 if (_options.undefinedTreatment() == Options::kUndefinedDynamicLookup )
459 return DYNAMIC_LOOKUP_ORDINAL;
460 if (_options.allowedUndefined(atom->name()) )
461 return DYNAMIC_LOOKUP_ORDINAL;
462 }
463 assert(dylib != NULL);
464 int ord = this->_writer.dylibToOrdinal(dylib);
465 if ( ord == BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE )
466 return EXECUTABLE_ORDINAL;
467 return ord;
468}
469
470
471template <typename A>
472void SymbolTableAtom<A>::addImport(const ld::Atom* atom, StringPoolAtom* pool)
473{
474 macho_nlist<P> entry;
475
476 // set n_strx
477 entry.set_n_strx(pool->add(atom->name()));
478
479 // set n_type
480 if ( this->_options.outputKind() == Options::kObjectFile ) {
599556ff
A
481 if ( atom->section().type() == ld::Section::typeTempAlias ) {
482 if ( atom->scope() == ld::Atom::scopeLinkageUnit )
483 entry.set_n_type(N_INDR | N_EXT | N_PEXT);
484 else
485 entry.set_n_type(N_INDR | N_EXT);
486 }
487 else if ( (atom->scope() == ld::Atom::scopeLinkageUnit)
a645023d
A
488 && (atom->definition() == ld::Atom::definitionTentative) )
489 entry.set_n_type(N_UNDF | N_EXT | N_PEXT);
490 else
491 entry.set_n_type(N_UNDF | N_EXT);
492 }
493 else {
e456bf10 494 entry.set_n_type(N_UNDF | N_EXT);
a645023d
A
495 }
496
497 // set n_sect
498 entry.set_n_sect(0);
499
500 uint16_t desc = 0;
501 if ( this->_options.outputKind() != Options::kObjectFile ) {
502 uint8_t ordinal = this->classicOrdinalForProxy(atom);
503 //fprintf(stderr, "ordinal=%u from reader=%p for symbol=%s\n", ordinal, atom->getFile(), atom->getName());
504 SET_LIBRARY_ORDINAL(desc, ordinal);
505
506#if 0
507 // set n_desc ( high byte is library ordinal, low byte is reference type )
508 std::map<const ObjectFile::Atom*,ObjectFile::Atom*>::iterator pos = fStubsMap.find(atom);
509 if ( pos != fStubsMap.end() || ( strncmp(atom->getName(), ".objc_class_name_", 17) == 0) )
510 desc |= REFERENCE_FLAG_UNDEFINED_LAZY;
511 else
512 desc |= REFERENCE_FLAG_UNDEFINED_NON_LAZY;
513#endif
514 }
515 else if ( atom->definition() == ld::Atom::definitionTentative ) {
516 uint8_t align = atom->alignment().powerOf2;
517 // always record custom alignment of common symbols to match what compiler does
518 SET_COMM_ALIGN(desc, align);
519 }
520 if ( (this->_options.outputKind() != Options::kObjectFile)
521 && (atom->definition() == ld::Atom::definitionProxy)
522 && (atom->combine() == ld::Atom::combineByName) ) {
523 desc |= N_REF_TO_WEAK;
524 }
afe874b1
A
525 const ld::dylib::File* dylib = dynamic_cast<const ld::dylib::File*>(atom->file());
526 if ( atom->weakImported() || ((dylib != NULL) && dylib->forcedWeakLinked()) )
a645023d
A
527 desc |= N_WEAK_REF;
528 entry.set_n_desc(desc);
529
530 // set n_value, zero for import proxy and size for tentative definition
531 if ( atom->definition() == ld::Atom::definitionTentative )
532 entry.set_n_value(atom->size());
599556ff 533 else if ( atom->section().type() != ld::Section::typeTempAlias )
a645023d 534 entry.set_n_value(0);
599556ff
A
535 else {
536 assert(atom->fixupsBegin() != atom->fixupsEnd());
537 for (ld::Fixup::iterator fit = atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
538 assert(fit->kind == ld::Fixup::kindNoneFollowOn);
539 switch ( fit->binding ) {
540 case ld::Fixup::bindingByNameUnbound:
541 entry.set_n_value(pool->add(fit->u.name));
542 break;
543 case ld::Fixup::bindingsIndirectlyBound:
544 entry.set_n_value(pool->add((_state.indirectBindingTable[fit->u.bindingIndex])->name()));
545 break;
546 default:
547 assert(0 && "internal error: unexpected alias binding");
548 }
549 }
550 }
a645023d
A
551
552 // add to array
553 _imports.push_back(entry);
554}
555
556template <typename A>
557uint8_t SymbolTableAtom<A>::sectionIndexForStab(const ld::relocatable::File::Stab& stab)
558{
559 // in FUN stabs, n_sect field is 0 for start FUN and 1 for end FUN
560 if ( stab.type == N_FUN )
561 return stab.other;
562 else if ( stab.type == N_GSYM )
563 return 0;
564 else if ( stab.atom != NULL )
565 return stab.atom->machoSection();
566 else
567 return stab.other;
568}
569
570
571template <typename A>
572uint64_t SymbolTableAtom<A>::valueForStab(const ld::relocatable::File::Stab& stab)
573{
574 switch ( stab.type ) {
575 case N_FUN:
576 if ( stab.atom == NULL ) {
577 // <rdar://problem/5591394> Add support to ld64 for N_FUN stabs when used for symbolic constants
578 return stab.value;
579 }
580 if ( (stab.string == NULL) || (strlen(stab.string) == 0) ) {
581 // end of function N_FUN has size
582 return stab.atom->size();
583 }
584 else {
585 // start of function N_FUN has address
586 return stab.atom->finalAddress();
587 }
588 case N_LBRAC:
589 case N_RBRAC:
590 case N_SLINE:
591 if ( stab.atom == NULL )
592 // some weird assembly files have slines not associated with a function
593 return stab.value;
594 else
595 // all these stab types need their value changed from an offset in the atom to an address
596 return stab.atom->finalAddress() + stab.value;
597 case N_STSYM:
598 case N_LCSYM:
599 case N_BNSYM:
600 // all these need address of atom
601 if ( stab.atom != NULL )
602 return stab.atom->finalAddress();
603 else
604 return 0; // <rdar://problem/7811357> work around for mismatch N_BNSYM
605 case N_ENSYM:
606 return stab.atom->size();
607 case N_SO:
608 if ( stab.atom == NULL ) {
609 return 0;
610 }
611 else {
612 if ( (stab.string == NULL) || (strlen(stab.string) == 0) ) {
613 // end of translation unit N_SO has address of end of last atom
614 return stab.atom->finalAddress() + stab.atom->size();
615 }
616 else {
617 // start of translation unit N_SO has address of end of first atom
618 return stab.atom->finalAddress();
619 }
620 }
621 break;
622 default:
623 return stab.value;
624 }
625}
626
627template <typename A>
628uint32_t SymbolTableAtom<A>::stringOffsetForStab(const ld::relocatable::File::Stab& stab, StringPoolAtom* pool)
629{
630 switch (stab.type) {
631 case N_SO:
632 if ( (stab.string == NULL) || stab.string[0] == '\0' ) {
633 return pool->emptyString();
634 break;
635 }
636 // fall into uniquing case
637 case N_SOL:
638 case N_BINCL:
639 case N_EXCL:
640 return pool->addUnique(stab.string);
641 break;
642 default:
643 if ( stab.string == NULL )
644 return 0;
645 else if ( stab.string[0] == '\0' )
646 return pool->emptyString();
647 else
648 return pool->add(stab.string);
649 }
650 return 0;
651}
652
653
654
655template <typename A>
656bool SymbolTableAtom<A>::hasStabs(uint32_t& ssos, uint32_t& ssoe, uint32_t& sos, uint32_t& soe)
657{
658 ssos = _stabsStringsOffsetStart;
659 ssoe = _stabsStringsOffsetEnd;
660 sos = _stabsIndexStart * sizeof(macho_nlist<P>);
661 soe = _stabsIndexEnd * sizeof(macho_nlist<P>);
662 return ( (_stabsIndexStart != _stabsIndexEnd) || (_stabsStringsOffsetStart != _stabsStringsOffsetEnd) );
663}
664
ebf6f434 665
a645023d
A
666template <typename A>
667void SymbolTableAtom<A>::encode()
668{
0a8dc3df
A
669 // Note: We lay out the symbol table so that the strings for the stabs (local) symbols are at the
670 // end of the string pool. The stabs strings are not used when calculated the UUID for the image.
671 // If the stabs strings were not last, the string offsets for all other symbols may very which would alter the UUID.
a645023d 672
0a8dc3df
A
673 // reserve space for local symbols
674 uint32_t localsCount = _state.stabs.size() + this->_writer._localAtoms.size();
a645023d
A
675
676 // make nlist entries for all global symbols
0a8dc3df 677 std::vector<const ld::Atom*>& globalAtoms = this->_writer._exportedAtoms;
a645023d 678 _globals.reserve(globalAtoms.size());
0a8dc3df
A
679 uint32_t symbolIndex = localsCount;
680 this->_writer._globalSymbolsStartIndex = localsCount;
a645023d
A
681 for (std::vector<const ld::Atom*>::const_iterator it=globalAtoms.begin(); it != globalAtoms.end(); ++it) {
682 const ld::Atom* atom = *it;
683 this->addGlobal(atom, this->_writer._stringPoolAtom);
684 this->_writer._atomToSymbolIndex[atom] = symbolIndex++;
685 }
686 this->_writer._globalSymbolsCount = symbolIndex - this->_writer._globalSymbolsStartIndex;
687
688 // make nlist entries for all undefined (imported) symbols
689 std::vector<const ld::Atom*>& importAtoms = this->_writer._importedAtoms;
690 _imports.reserve(importAtoms.size());
691 this->_writer._importSymbolsStartIndex = symbolIndex;
692 for (std::vector<const ld::Atom*>::const_iterator it=importAtoms.begin(); it != importAtoms.end(); ++it) {
693 this->addImport(*it, this->_writer._stringPoolAtom);
694 this->_writer._atomToSymbolIndex[*it] = symbolIndex++;
695 }
696 this->_writer._importSymbolsCount = symbolIndex - this->_writer._importSymbolsStartIndex;
0a8dc3df
A
697
698 // go back to start and make nlist entries for all local symbols
699 std::vector<const ld::Atom*>& localAtoms = this->_writer._localAtoms;
700 _locals.reserve(localsCount);
701 symbolIndex = 0;
702 this->_writer._localSymbolsStartIndex = 0;
703 _stabsIndexStart = 0;
704 _stabsStringsOffsetStart = this->_writer._stringPoolAtom->currentOffset();
705 for (const ld::relocatable::File::Stab& stab : _state.stabs) {
706 macho_nlist<P> entry;
707 entry.set_n_type(stab.type);
708 entry.set_n_sect(sectionIndexForStab(stab));
709 entry.set_n_desc(stab.desc);
710 entry.set_n_value(valueForStab(stab));
711 entry.set_n_strx(stringOffsetForStab(stab, this->_writer._stringPoolAtom));
712 _locals.push_back(entry);
713 ++symbolIndex;
714 }
715 _stabsIndexEnd = symbolIndex;
716 _stabsStringsOffsetEnd = this->_writer._stringPoolAtom->currentOffset();
717 for (const ld::Atom* atom : localAtoms) {
718 if ( this->addLocal(atom, this->_writer._stringPoolAtom) )
719 this->_writer._atomToSymbolIndex[atom] = symbolIndex++;
720 }
721 this->_writer._localSymbolsCount = symbolIndex;
a645023d
A
722}
723
724template <typename A>
725uint64_t SymbolTableAtom<A>::size() const
726{
727 return sizeof(macho_nlist<P>) * (_locals.size() + _globals.size() + _imports.size());
728}
729
730template <typename A>
731void SymbolTableAtom<A>::copyRawContent(uint8_t buffer[]) const
732{
733 memcpy(&buffer[this->_writer._localSymbolsStartIndex*sizeof(macho_nlist<P>)], &_locals[0],
734 this->_writer._localSymbolsCount*sizeof(macho_nlist<P>));
735 memcpy(&buffer[this->_writer._globalSymbolsStartIndex*sizeof(macho_nlist<P>)], &_globals[0],
736 this->_writer._globalSymbolsCount*sizeof(macho_nlist<P>));
737 memcpy(&buffer[this->_writer._importSymbolsStartIndex *sizeof(macho_nlist<P>)], &_imports[0],
738 this->_writer._importSymbolsCount*sizeof(macho_nlist<P>));
739}
740
741
742
743
744class RelocationsAtomAbstract : public ClassicLinkEditAtom
745{
746public:
747 RelocationsAtomAbstract(const Options& opts, ld::Internal& state,
748 OutputFile& writer, const ld::Section& sect,
749 unsigned int pointerSize)
750 : ClassicLinkEditAtom(opts, state, writer, sect, pointerSize) { }
751
752 virtual void addPointerReloc(uint64_t addr, uint32_t symNum) = 0;
753 virtual void addTextReloc(uint64_t addr, ld::Fixup::Kind k, uint64_t targetAddr, uint32_t symNum) = 0;
754 virtual void addExternalPointerReloc(uint64_t addr, const ld::Atom*) = 0;
755 virtual void addExternalCallSiteReloc(uint64_t addr, const ld::Atom*) = 0;
756 virtual uint64_t relocBaseAddress(ld::Internal& state) = 0;
757 virtual void addSectionReloc(ld::Internal::FinalSection* sect, ld::Fixup::Kind,
758 const ld::Atom* inAtom, uint32_t offsetInAtom,
759 bool toTargetUsesExternalReloc ,bool fromTargetExternalReloc,
e456bf10
A
760#if SUPPORT_ARCH_arm64e
761 ld::Fixup* fixupWithAuthData,
762#endif
a645023d
A
763 const ld::Atom* toTarget, uint64_t toAddend,
764 const ld::Atom* fromTarget, uint64_t fromAddend) = 0;
765protected:
766 uint32_t symbolIndex(const ld::Atom* atom) const;
767
768};
769
770
771
772uint32_t RelocationsAtomAbstract::symbolIndex(const ld::Atom* atom) const
773{
774 std::map<const ld::Atom*, uint32_t>::iterator pos = this->_writer._atomToSymbolIndex.find(atom);
775 if ( pos != this->_writer._atomToSymbolIndex.end() )
776 return pos->second;
777 fprintf(stderr, "_atomToSymbolIndex content:\n");
778 for(std::map<const ld::Atom*, uint32_t>::iterator it = this->_writer._atomToSymbolIndex.begin(); it != this->_writer._atomToSymbolIndex.end(); ++it) {
779 fprintf(stderr, "%p(%s) => %d\n", it->first, it->first->name(), it->second);
780 }
781 throwf("internal error: atom not found in symbolIndex(%s)", atom->name());
782}
783
784
785template <typename A>
786class LocalRelocationsAtom : public RelocationsAtomAbstract
787{
788public:
789 LocalRelocationsAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
790 : RelocationsAtomAbstract(opts, state, writer, _s_section, sizeof(pint_t)) { }
791
792 // overrides of ld::Atom
793 virtual const char* name() const { return "local relocations"; }
794 virtual uint64_t size() const;
795 virtual void copyRawContent(uint8_t buffer[]) const;
796 // overrides of ClassicLinkEditAtom
797 virtual void encode() {}
798 // overrides of RelocationsAtomAbstract
799 virtual void addPointerReloc(uint64_t addr, uint32_t symNum);
800 virtual void addExternalPointerReloc(uint64_t addr, const ld::Atom*) {}
801 virtual void addExternalCallSiteReloc(uint64_t addr, const ld::Atom*) {}
802 virtual uint64_t relocBaseAddress(ld::Internal& state);
803 virtual void addTextReloc(uint64_t addr, ld::Fixup::Kind k, uint64_t targetAddr, uint32_t symNum);
804 virtual void addSectionReloc(ld::Internal::FinalSection* sect, ld::Fixup::Kind,
805 const ld::Atom* inAtom, uint32_t offsetInAtom,
806 bool toTargetUsesExternalReloc ,bool fromTargetExternalReloc,
e456bf10
A
807#if SUPPORT_ARCH_arm64e
808 ld::Fixup* fixupWithAuthData,
809#endif
a645023d
A
810 const ld::Atom* toTarget, uint64_t toAddend,
811 const ld::Atom* fromTarget, uint64_t fromAddend) { }
812
813private:
814 typedef typename A::P P;
815 typedef typename A::P::E E;
816 typedef typename A::P::uint_t pint_t;
817
818 std::vector<macho_relocation_info<P> > _relocs;
819
820 static ld::Section _s_section;
821};
822
823template <typename A>
824ld::Section LocalRelocationsAtom<A>::_s_section("__LINKEDIT", "__local_relocs", ld::Section::typeLinkEdit, true);
825
826
827template <>
828uint64_t LocalRelocationsAtom<x86_64>::relocBaseAddress(ld::Internal& state)
829{
830 if ( _options.outputKind() == Options::kKextBundle ) {
831 // for kext bundles the reloc base address starts at __TEXT segment
832 return _options.baseAddress();
833 }
599556ff 834 // for all other kinds, the x86_64 reloc base address starts at first writable segment (usually __DATA)
a645023d
A
835 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
836 ld::Internal::FinalSection* sect = *sit;
599556ff 837 if ( !sect->isSectionHidden() && _options.initialSegProtection(sect->segmentName()) & VM_PROT_WRITE )
a645023d
A
838 return sect->address;
839 }
599556ff 840 throw "writable (__DATA) segment not found";
a645023d
A
841}
842
843template <typename A>
844uint64_t LocalRelocationsAtom<A>::relocBaseAddress(ld::Internal& state)
845{
846 return _options.baseAddress();
847}
848
849template <typename A>
850void LocalRelocationsAtom<A>::addPointerReloc(uint64_t addr, uint32_t symNum)
851{
852 macho_relocation_info<P> reloc;
853 reloc.set_r_address(addr);
854 reloc.set_r_symbolnum(symNum);
855 reloc.set_r_pcrel(false);
856 reloc.set_r_length();
857 reloc.set_r_extern(false);
858 reloc.set_r_type(GENERIC_RELOC_VANILLA);
859 _relocs.push_back(reloc);
860}
861
862template <typename A>
863void LocalRelocationsAtom<A>::addTextReloc(uint64_t addr, ld::Fixup::Kind kind, uint64_t targetAddr, uint32_t symNum)
864{
a645023d
A
865}
866
867
868template <typename A>
869uint64_t LocalRelocationsAtom<A>::size() const
870{
871 return _relocs.size() * sizeof(macho_relocation_info<P>);
872}
873
874template <typename A>
875void LocalRelocationsAtom<A>::copyRawContent(uint8_t buffer[]) const
876{
877 memcpy(buffer, &_relocs[0], _relocs.size()*sizeof(macho_relocation_info<P>));
878}
879
880
881
882
883
884
885template <typename A>
886class ExternalRelocationsAtom : public RelocationsAtomAbstract
887{
888public:
889 ExternalRelocationsAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
890 : RelocationsAtomAbstract(opts, state, writer, _s_section, sizeof(pint_t)) { }
891
892 // overrides of ld::Atom
893 virtual const char* name() const { return "external relocations"; }
894 virtual uint64_t size() const;
895 virtual void copyRawContent(uint8_t buffer[]) const;
896 // overrides of ClassicLinkEditAtom
897 virtual void encode() {}
898 // overrides of RelocationsAtomAbstract
899 virtual void addPointerReloc(uint64_t addr, uint32_t symNum) {}
900 virtual void addTextReloc(uint64_t addr, ld::Fixup::Kind k, uint64_t targetAddr, uint32_t symNum) {}
901 virtual void addExternalPointerReloc(uint64_t addr, const ld::Atom*);
902 virtual void addExternalCallSiteReloc(uint64_t addr, const ld::Atom*);
903 virtual uint64_t relocBaseAddress(ld::Internal& state);
904 virtual void addSectionReloc(ld::Internal::FinalSection* sect, ld::Fixup::Kind,
905 const ld::Atom* inAtom, uint32_t offsetInAtom,
906 bool toTargetUsesExternalReloc ,bool fromTargetExternalReloc,
e456bf10
A
907#if SUPPORT_ARCH_arm64e
908 ld::Fixup* fixupWithAuthData,
909#endif
a645023d
A
910 const ld::Atom* toTarget, uint64_t toAddend,
911 const ld::Atom* fromTarget, uint64_t fromAddend) { }
912
913
914private:
915 typedef typename A::P P;
916 typedef typename A::P::E E;
917 typedef typename A::P::uint_t pint_t;
918
919 struct LocAndAtom {
920 LocAndAtom(uint64_t l, const ld::Atom* a) : loc(l), atom(a), symbolIndex(0) {}
921
922 uint64_t loc;
923 const ld::Atom* atom;
924 uint32_t symbolIndex;
925
926 bool operator<(const LocAndAtom& rhs) const {
927 // sort first by symbol number
928 if ( this->symbolIndex != rhs.symbolIndex )
929 return (this->symbolIndex < rhs.symbolIndex);
930 // then sort all uses of the same symbol by address
931 return (this->loc < rhs.loc);
932 }
933
934 };
935
936 static uint32_t pointerReloc();
937 static uint32_t callReloc();
938
939 mutable std::vector<LocAndAtom> _pointerLocations;
940 mutable std::vector<LocAndAtom> _callSiteLocations;
941
942 static ld::Section _s_section;
943};
944
945template <typename A>
946ld::Section ExternalRelocationsAtom<A>::_s_section("__LINKEDIT", "__extrn_relocs", ld::Section::typeLinkEdit, true);
947
948template <>
949uint64_t ExternalRelocationsAtom<x86_64>::relocBaseAddress(ld::Internal& state)
950{
951 // for x86_64 the reloc base address starts at __DATA segment
952 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
953 ld::Internal::FinalSection* sect = *sit;
599556ff 954 if ( !sect->isSectionHidden() && _options.initialSegProtection(sect->segmentName()) & VM_PROT_WRITE )
a645023d
A
955 return sect->address;
956 }
599556ff 957 throw "writable (__DATA) segment not found";
a645023d
A
958}
959
960template <typename A>
961uint64_t ExternalRelocationsAtom<A>::relocBaseAddress(ld::Internal& state)
962{
963 return 0;
964}
965
966template <typename A>
967void ExternalRelocationsAtom<A>::addExternalPointerReloc(uint64_t addr, const ld::Atom* target)
968{
969 _pointerLocations.push_back(LocAndAtom(addr, target));
970}
971
972template <typename A>
973void ExternalRelocationsAtom<A>::addExternalCallSiteReloc(uint64_t addr, const ld::Atom* target)
974{
975 _callSiteLocations.push_back(LocAndAtom(addr, target));
976}
977
978
979template <typename A>
980uint64_t ExternalRelocationsAtom<A>::size() const
981{
982 if ( _options.outputKind() == Options::kStaticExecutable ) {
983 assert(_pointerLocations.size() == 0);
984 assert(_callSiteLocations.size() == 0);
985 }
986 return (_pointerLocations.size() + _callSiteLocations.size()) * sizeof(macho_relocation_info<P>);
987}
988
f80fe69f
A
989#if SUPPORT_ARCH_arm64
990template <> uint32_t ExternalRelocationsAtom<arm64>::pointerReloc() { return ARM64_RELOC_UNSIGNED; }
991#endif
ebf6f434 992#if SUPPORT_ARCH_arm_any
a645023d 993template <> uint32_t ExternalRelocationsAtom<arm>::pointerReloc() { return ARM_RELOC_VANILLA; }
ebf6f434 994#endif
a645023d 995template <> uint32_t ExternalRelocationsAtom<x86>::pointerReloc() { return GENERIC_RELOC_VANILLA; }
a645023d 996template <> uint32_t ExternalRelocationsAtom<x86_64>::pointerReloc() { return X86_64_RELOC_UNSIGNED; }
a645023d
A
997
998
999template <> uint32_t ExternalRelocationsAtom<x86_64>::callReloc() { return X86_64_RELOC_BRANCH; }
1000template <> uint32_t ExternalRelocationsAtom<x86>::callReloc() { return GENERIC_RELOC_VANILLA; }
f80fe69f
A
1001#if SUPPORT_ARCH_arm64
1002template <> uint32_t ExternalRelocationsAtom<arm64>::callReloc() { return ARM64_RELOC_BRANCH26; }
1003#endif
1004
a645023d
A
1005template <typename A>
1006uint32_t ExternalRelocationsAtom<A>::callReloc()
1007{
1008 assert(0 && "external call relocs not implemented");
1009 return 0;
1010}
1011
1012
1013template <typename A>
1014void ExternalRelocationsAtom<A>::copyRawContent(uint8_t buffer[]) const
1015{
1016 macho_relocation_info<P>* r = (macho_relocation_info<P>*)buffer;
1017
1018 // assign symbol index, now that symbol table is built
1019 for (typename std::vector<LocAndAtom>::iterator it = _pointerLocations.begin(); it != _pointerLocations.end(); ++it) {
1020 it->symbolIndex = symbolIndex(it->atom);
1021 }
1022 std::sort(_pointerLocations.begin(), _pointerLocations.end());
1023 for (typename std::vector<LocAndAtom>::const_iterator it = _pointerLocations.begin(); it != _pointerLocations.end(); ++it, ++r) {
1024 r->set_r_address(it->loc);
1025 r->set_r_symbolnum(it->symbolIndex);
1026 r->set_r_pcrel(false);
1027 r->set_r_length();
1028 r->set_r_extern(true);
1029 r->set_r_type(this->pointerReloc());
1030 }
1031
1032 for (typename std::vector<LocAndAtom>::iterator it = _callSiteLocations.begin(); it != _callSiteLocations.end(); ++it) {
1033 it->symbolIndex = symbolIndex(it->atom);
1034 }
1035 std::sort(_callSiteLocations.begin(), _callSiteLocations.end());
1036 for (typename std::vector<LocAndAtom>::const_iterator it = _callSiteLocations.begin(); it != _callSiteLocations.end(); ++it, ++r) {
1037 r->set_r_address(it->loc);
1038 r->set_r_symbolnum(it->symbolIndex);
1039 r->set_r_pcrel(true);
1040 r->set_r_length(2);
1041 r->set_r_extern(true);
1042 r->set_r_type(this->callReloc());
1043 }
1044}
1045
1046
1047template <typename A>
1048class SectionRelocationsAtom : public RelocationsAtomAbstract
1049{
1050public:
1051 SectionRelocationsAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
1052 : RelocationsAtomAbstract(opts, state, writer, _s_section, sizeof(pint_t)) { }
1053
1054 // overrides of ld::Atom
1055 virtual const char* name() const { return "section relocations"; }
1056 virtual uint64_t size() const;
1057 virtual void copyRawContent(uint8_t buffer[]) const;
1058 // overrides of ClassicLinkEditAtom
1059 virtual void encode();
1060 // overrides of RelocationsAtomAbstract
1061 virtual void addPointerReloc(uint64_t addr, uint32_t symNum) {}
1062 virtual void addTextReloc(uint64_t addr, ld::Fixup::Kind k, uint64_t targetAddr, uint32_t symNum) {}
1063 virtual void addExternalPointerReloc(uint64_t addr, const ld::Atom*) {}
1064 virtual void addExternalCallSiteReloc(uint64_t addr, const ld::Atom*) {}
1065 virtual uint64_t relocBaseAddress(ld::Internal& state) { return 0; }
1066 virtual void addSectionReloc(ld::Internal::FinalSection* sect, ld::Fixup::Kind,
1067 const ld::Atom* inAtom, uint32_t offsetInAtom,
1068 bool toTargetUsesExternalReloc ,bool fromTargetExternalReloc,
e456bf10
A
1069#if SUPPORT_ARCH_arm64e
1070 ld::Fixup* fixupWithAuthData,
1071#endif
a645023d
A
1072 const ld::Atom* toTarget, uint64_t toAddend,
1073 const ld::Atom* fromTarget, uint64_t fromAddend);
1074
1075private:
1076 typedef typename A::P P;
1077 typedef typename A::P::E E;
1078 typedef typename A::P::uint_t pint_t;
1079
1080
1081 struct Entry {
1082 ld::Fixup::Kind kind;
1083 bool toTargetUsesExternalReloc;
1084 bool fromTargetUsesExternalReloc;
1085 const ld::Atom* inAtom;
1086 uint32_t offsetInAtom;
1087 const ld::Atom* toTarget;
1088 uint64_t toAddend;
1089 const ld::Atom* fromTarget;
1090 uint64_t fromAddend;
e456bf10
A
1091#if SUPPORT_ARCH_arm64e
1092 bool hasAuthData;
1093 ld::Fixup::AuthData authData;
1094#endif
a645023d
A
1095 };
1096 uint32_t sectSymNum(bool external, const ld::Atom* target);
1097 void encodeSectionReloc(ld::Internal::FinalSection* sect,
1098 const Entry& entry, std::vector<macho_relocation_info<P> >& relocs);
1099
1100 struct SectionAndEntries {
1101 ld::Internal::FinalSection* sect;
1102 std::vector<Entry> entries;
1103 std::vector<macho_relocation_info<P> > relocs;
1104 };
1105
1106 std::vector<SectionAndEntries> _entriesBySection;
1107
1108 static ld::Section _s_section;
1109};
1110
1111template <typename A>
1112ld::Section SectionRelocationsAtom<A>::_s_section("__LINKEDIT", "__sect_relocs", ld::Section::typeLinkEdit, true);
1113
1114
1115
1116
1117template <typename A>
1118uint64_t SectionRelocationsAtom<A>::size() const
1119{
1120 uint32_t count = 0;
1121 for(typename std::vector<SectionAndEntries>::const_iterator it=_entriesBySection.begin(); it != _entriesBySection.end(); ++it) {
1122 const SectionAndEntries& se = *it;
1123 count += se.relocs.size();
1124 }
1125 return count * sizeof(macho_relocation_info<P>);
1126}
1127
1128template <typename A>
1129void SectionRelocationsAtom<A>::copyRawContent(uint8_t buffer[]) const
1130{
1131 uint32_t offset = 0;
1132 for(typename std::vector<SectionAndEntries>::const_iterator it=_entriesBySection.begin(); it != _entriesBySection.end(); ++it) {
1133 const SectionAndEntries& se = *it;
1134 memcpy(&buffer[offset], &se.relocs[0], se.relocs.size()*sizeof(macho_relocation_info<P>));
1135 offset += (se.relocs.size() * sizeof(macho_relocation_info<P>));
1136 }
1137}
1138
1139
1140template <>
1141void SectionRelocationsAtom<x86_64>::encodeSectionReloc(ld::Internal::FinalSection* sect,
1142 const Entry& entry, std::vector<macho_relocation_info<P> >& relocs)
1143{
1144 macho_relocation_info<P> reloc1;
1145 macho_relocation_info<P> reloc2;
1146 uint64_t address = entry.inAtom->finalAddress()+entry.offsetInAtom - sect->address;
1147 bool external = entry.toTargetUsesExternalReloc;
1148 uint32_t symbolNum = sectSymNum(external, entry.toTarget);
1149 bool fromExternal = false;
1150 uint32_t fromSymbolNum = 0;
1151 if ( entry.fromTarget != NULL ) {
1152 fromExternal = entry.fromTargetUsesExternalReloc;
1153 fromSymbolNum = sectSymNum(fromExternal, entry.fromTarget);
1154 }
1155
1156
1157 switch ( entry.kind ) {
1158 case ld::Fixup::kindStoreX86BranchPCRel32:
1159 case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32:
1160 case ld::Fixup::kindStoreX86DtraceCallSiteNop:
1161 case ld::Fixup::kindStoreX86DtraceIsEnableSiteClear:
1162 reloc1.set_r_address(address);
1163 reloc1.set_r_symbolnum(symbolNum);
1164 reloc1.set_r_pcrel(true);
1165 reloc1.set_r_length(2);
1166 reloc1.set_r_extern(external);
1167 reloc1.set_r_type(X86_64_RELOC_BRANCH);
1168 relocs.push_back(reloc1);
1169 break;
1170
1171 case ld::Fixup::kindStoreX86BranchPCRel8:
1172 reloc1.set_r_address(address);
1173 reloc1.set_r_symbolnum(symbolNum);
1174 reloc1.set_r_pcrel(true);
1175 reloc1.set_r_length(0);
1176 reloc1.set_r_extern(external);
1177 reloc1.set_r_type(X86_64_RELOC_BRANCH);
1178 relocs.push_back(reloc1);
1179 break;
1180
1181 case ld::Fixup::kindStoreX86PCRel32:
1182 case ld::Fixup::kindStoreTargetAddressX86PCRel32:
1183 reloc1.set_r_address(address);
1184 reloc1.set_r_symbolnum(symbolNum);
1185 reloc1.set_r_pcrel(true);
1186 reloc1.set_r_length(2);
1187 reloc1.set_r_extern(external);
1188 reloc1.set_r_type(X86_64_RELOC_SIGNED);
1189 relocs.push_back(reloc1);
1190 break;
1191
1192 case ld::Fixup::kindStoreX86PCRel32_1:
1193 reloc1.set_r_address(address);
1194 reloc1.set_r_symbolnum(symbolNum);
1195 reloc1.set_r_pcrel(true);
1196 reloc1.set_r_length(2);
1197 reloc1.set_r_extern(external);
1198 reloc1.set_r_type(X86_64_RELOC_SIGNED_1);
1199 relocs.push_back(reloc1);
1200 break;
1201
1202 case ld::Fixup::kindStoreX86PCRel32_2:
1203 reloc1.set_r_address(address);
1204 reloc1.set_r_symbolnum(symbolNum);
1205 reloc1.set_r_pcrel(true);
1206 reloc1.set_r_length(2);
1207 reloc1.set_r_extern(external);
1208 reloc1.set_r_type(X86_64_RELOC_SIGNED_2);
1209 relocs.push_back(reloc1);
1210 break;
1211
1212 case ld::Fixup::kindStoreX86PCRel32_4:
1213 reloc1.set_r_address(address);
1214 reloc1.set_r_symbolnum(symbolNum);
1215 reloc1.set_r_pcrel(true);
1216 reloc1.set_r_length(2);
1217 reloc1.set_r_extern(external);
1218 reloc1.set_r_type(X86_64_RELOC_SIGNED_4);
1219 relocs.push_back(reloc1);
1220 break;
1221
1222 case ld::Fixup::kindStoreX86PCRel32GOTLoad:
1223 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad:
1224 reloc1.set_r_address(address);
1225 reloc1.set_r_symbolnum(symbolNum);
1226 reloc1.set_r_pcrel(true);
1227 reloc1.set_r_length(2);
1228 reloc1.set_r_extern(external);
1229 reloc1.set_r_type(X86_64_RELOC_GOT_LOAD);
1230 relocs.push_back(reloc1);
1231 break;
1232
1233 case ld::Fixup::kindStoreX86PCRel32GOT:
1234 reloc1.set_r_address(address);
1235 reloc1.set_r_symbolnum(symbolNum);
1236 reloc1.set_r_pcrel(true);
1237 reloc1.set_r_length(2);
1238 reloc1.set_r_extern(external);
1239 reloc1.set_r_type(X86_64_RELOC_GOT);
1240 relocs.push_back(reloc1);
1241 break;
1242
1243 case ld::Fixup::kindStoreLittleEndian64:
1244 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
1245 if ( entry.fromTarget != NULL ) {
1246 // this is a pointer-diff
1247 reloc1.set_r_address(address);
1248 reloc1.set_r_symbolnum(symbolNum);
1249 reloc1.set_r_pcrel(false);
1250 reloc1.set_r_length(3);
1251 reloc1.set_r_extern(external);
1252 reloc1.set_r_type(X86_64_RELOC_UNSIGNED);
1253 reloc2.set_r_address(address);
1254 reloc2.set_r_symbolnum(fromSymbolNum);
1255 reloc2.set_r_pcrel(false);
1256 reloc2.set_r_length(3);
1257 reloc2.set_r_extern(fromExternal);
1258 reloc2.set_r_type(X86_64_RELOC_SUBTRACTOR);
1259 relocs.push_back(reloc2);
1260 relocs.push_back(reloc1);
1261 }
1262 else {
1263 // regular pointer
1264 reloc1.set_r_address(address);
1265 reloc1.set_r_symbolnum(symbolNum);
1266 reloc1.set_r_pcrel(false);
1267 reloc1.set_r_length(3);
1268 reloc1.set_r_extern(external);
1269 reloc1.set_r_type(X86_64_RELOC_UNSIGNED);
1270 relocs.push_back(reloc1);
1271 }
1272 break;
1273
1274 case ld::Fixup::kindStoreLittleEndian32:
1275 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
1276 if ( entry.fromTarget != NULL ) {
1277 // this is a pointer-diff
1278 reloc1.set_r_address(address);
1279 reloc1.set_r_symbolnum(symbolNum);
1280 reloc1.set_r_pcrel(false);
1281 reloc1.set_r_length(2);
1282 reloc1.set_r_extern(external);
1283 reloc1.set_r_type(X86_64_RELOC_UNSIGNED);
1284 reloc2.set_r_address(address);
1285 reloc2.set_r_symbolnum(fromSymbolNum);
1286 reloc2.set_r_pcrel(false);
1287 reloc2.set_r_length(2);
1288 reloc2.set_r_extern(fromExternal);
1289 reloc2.set_r_type(X86_64_RELOC_SUBTRACTOR);
1290 relocs.push_back(reloc2);
1291 relocs.push_back(reloc1);
1292 }
1293 else {
1294 // regular pointer
1295 reloc1.set_r_address(address);
1296 reloc1.set_r_symbolnum(symbolNum);
1297 reloc1.set_r_pcrel(false);
1298 reloc1.set_r_length(2);
1299 reloc1.set_r_extern(external);
1300 reloc1.set_r_type(X86_64_RELOC_UNSIGNED);
1301 relocs.push_back(reloc1);
1302 }
1303 break;
b1f7435d
A
1304 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad:
1305 reloc1.set_r_address(address);
1306 reloc1.set_r_symbolnum(symbolNum);
1307 reloc1.set_r_pcrel(true);
1308 reloc1.set_r_length(2);
1309 reloc1.set_r_extern(external);
1310 reloc1.set_r_type(X86_64_RELOC_TLV);
1311 relocs.push_back(reloc1);
1312 break;
a645023d
A
1313 default:
1314 assert(0 && "need to handle -r reloc");
1315
1316 }
1317
1318}
1319
1320
1321
1322template <typename A>
1323uint32_t SectionRelocationsAtom<A>::sectSymNum(bool external, const ld::Atom* target)
1324{
1325 if ( target->definition() == ld::Atom::definitionAbsolute )
1326 return R_ABS;
1327 if ( external )
1328 return this->symbolIndex(target); // in external relocations, r_symbolnum field is symbol index
1329 else
1330 return target->machoSection(); // in non-extern relocations, r_symbolnum is mach-o section index of target
1331}
1332
1333template <>
b1f7435d 1334void SectionRelocationsAtom<x86>::encodeSectionReloc(ld::Internal::FinalSection* sect,
a645023d
A
1335 const Entry& entry, std::vector<macho_relocation_info<P> >& relocs)
1336{
1337 macho_relocation_info<P> reloc1;
1338 macho_relocation_info<P> reloc2;
1339 macho_scattered_relocation_info<P>* sreloc1 = (macho_scattered_relocation_info<P>*)&reloc1;
1340 macho_scattered_relocation_info<P>* sreloc2 = (macho_scattered_relocation_info<P>*)&reloc2;
1341 uint64_t address = entry.inAtom->finalAddress()+entry.offsetInAtom - sect->address;
1342 bool external = entry.toTargetUsesExternalReloc;
1343 uint32_t symbolNum = sectSymNum(external, entry.toTarget);
1344 bool fromExternal = false;
1345 uint32_t fromSymbolNum = 0;
1346 if ( entry.fromTarget != NULL ) {
1347 fromExternal = entry.fromTargetUsesExternalReloc;
1348 fromSymbolNum = sectSymNum(fromExternal, entry.fromTarget);
1349 }
b1f7435d 1350
a645023d
A
1351 switch ( entry.kind ) {
1352 case ld::Fixup::kindStoreX86PCRel32:
1353 case ld::Fixup::kindStoreX86BranchPCRel32:
1354 case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32:
1355 case ld::Fixup::kindStoreX86DtraceCallSiteNop:
1356 case ld::Fixup::kindStoreX86DtraceIsEnableSiteClear:
1357 if ( !external && (entry.toAddend != 0) ) {
1358 // use scattered reloc is target offset is non-zero
1359 sreloc1->set_r_scattered(true);
1360 sreloc1->set_r_pcrel(true);
1361 sreloc1->set_r_length(2);
1362 sreloc1->set_r_type(GENERIC_RELOC_VANILLA);
1363 sreloc1->set_r_address(address);
1364 sreloc1->set_r_value(entry.toTarget->finalAddress());
1365 }
1366 else {
1367 reloc1.set_r_address(address);
1368 reloc1.set_r_symbolnum(symbolNum);
1369 reloc1.set_r_pcrel(true);
1370 reloc1.set_r_length(2);
1371 reloc1.set_r_extern(external);
1372 reloc1.set_r_type(GENERIC_RELOC_VANILLA);
1373 }
1374 relocs.push_back(reloc1);
1375 break;
1376
1377 case ld::Fixup::kindStoreX86BranchPCRel8:
1378 if ( !external && (entry.toAddend != 0) ) {
1379 // use scattered reloc is target offset is non-zero
1380 sreloc1->set_r_scattered(true);
1381 sreloc1->set_r_pcrel(true);
1382 sreloc1->set_r_length(0);
1383 sreloc1->set_r_type(GENERIC_RELOC_VANILLA);
1384 sreloc1->set_r_address(address);
1385 sreloc1->set_r_value(entry.toTarget->finalAddress());
1386 }
1387 else {
1388 reloc1.set_r_address(address);
1389 reloc1.set_r_symbolnum(symbolNum);
1390 reloc1.set_r_pcrel(true);
1391 reloc1.set_r_length(0);
1392 reloc1.set_r_extern(external);
1393 reloc1.set_r_type(GENERIC_RELOC_VANILLA);
1394 }
1395 relocs.push_back(reloc1);
1396 break;
1397
1398 case ld::Fixup::kindStoreX86PCRel16:
1399 if ( !external && (entry.toAddend != 0) ) {
1400 // use scattered reloc is target offset is non-zero
1401 sreloc1->set_r_scattered(true);
1402 sreloc1->set_r_pcrel(true);
1403 sreloc1->set_r_length(1);
1404 sreloc1->set_r_type(GENERIC_RELOC_VANILLA);
1405 sreloc1->set_r_address(address);
1406 sreloc1->set_r_value(entry.toTarget->finalAddress());
1407 }
1408 else {
1409 reloc1.set_r_address(address);
1410 reloc1.set_r_symbolnum(symbolNum);
1411 reloc1.set_r_pcrel(true);
1412 reloc1.set_r_length(1);
1413 reloc1.set_r_extern(external);
1414 reloc1.set_r_type(GENERIC_RELOC_VANILLA);
1415 }
1416 relocs.push_back(reloc1);
1417 break;
1418
1419 case ld::Fixup::kindStoreLittleEndian32:
1420 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
1421 if ( entry.fromTarget != NULL ) {
1422 // this is a pointer-diff
1423 sreloc1->set_r_scattered(true);
1424 sreloc1->set_r_pcrel(false);
1425 sreloc1->set_r_length(2);
1426 if ( entry.toTarget->scope() == ld::Atom::scopeTranslationUnit )
1427 sreloc1->set_r_type(GENERIC_RELOC_LOCAL_SECTDIFF);
1428 else
1429 sreloc1->set_r_type(GENERIC_RELOC_SECTDIFF);
1430 sreloc1->set_r_address(address);
afe874b1
A
1431 if ( entry.toTarget == entry.inAtom ) {
1432 if ( entry.toAddend > entry.toTarget->size() )
1433 sreloc1->set_r_value(entry.toTarget->finalAddress()+entry.offsetInAtom);
1434 else
1435 sreloc1->set_r_value(entry.toTarget->finalAddress()+entry.toAddend);
1436 }
a645023d
A
1437 else
1438 sreloc1->set_r_value(entry.toTarget->finalAddress());
1439 sreloc2->set_r_scattered(true);
1440 sreloc2->set_r_pcrel(false);
1441 sreloc2->set_r_length(2);
1442 sreloc2->set_r_type(GENERIC_RELOC_PAIR);
1443 sreloc2->set_r_address(0);
1444 if ( entry.fromTarget == entry.inAtom ) {
1445 if ( entry.fromAddend > entry.fromTarget->size() )
1446 sreloc2->set_r_value(entry.fromTarget->finalAddress()+entry.offsetInAtom);
1447 else
1448 sreloc2->set_r_value(entry.fromTarget->finalAddress()+entry.fromAddend);
1449 }
1450 else
1451 sreloc2->set_r_value(entry.fromTarget->finalAddress());
1452 relocs.push_back(reloc1);
1453 relocs.push_back(reloc2);
1454 }
1455 else {
1456 // regular pointer
ebf6f434
A
1457 if ( !external && (entry.toAddend != 0) && (entry.toTarget->symbolTableInclusion() != ld::Atom::symbolTableNotIn) ) {
1458 // use scattered reloc if target offset is non-zero into named atom (5658046)
a645023d
A
1459 sreloc1->set_r_scattered(true);
1460 sreloc1->set_r_pcrel(false);
1461 sreloc1->set_r_length(2);
1462 sreloc1->set_r_type(GENERIC_RELOC_VANILLA);
1463 sreloc1->set_r_address(address);
1464 sreloc1->set_r_value(entry.toTarget->finalAddress());
1465 }
1466 else {
1467 reloc1.set_r_address(address);
1468 reloc1.set_r_symbolnum(symbolNum);
1469 reloc1.set_r_pcrel(false);
1470 reloc1.set_r_length(2);
1471 reloc1.set_r_extern(external);
1472 reloc1.set_r_type(GENERIC_RELOC_VANILLA);
1473 }
1474 relocs.push_back(reloc1);
1475 }
1476 break;
b1f7435d
A
1477 case ld::Fixup::kindStoreX86PCRel32TLVLoad:
1478 case ld::Fixup::kindStoreX86Abs32TLVLoad:
1479 case ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoad:
1480 reloc1.set_r_address(address);
1481 reloc1.set_r_symbolnum(symbolNum);
1482 reloc1.set_r_pcrel(entry.kind == ld::Fixup::kindStoreX86PCRel32TLVLoad);
1483 reloc1.set_r_length(2);
1484 reloc1.set_r_extern(external);
1485 reloc1.set_r_type(GENERIC_RLEOC_TLV);
1486 relocs.push_back(reloc1);
1487 break;
a645023d
A
1488 default:
1489 assert(0 && "need to handle -r reloc");
1490
1491 }
1492}
1493
1494
b1f7435d 1495
ebf6f434 1496#if SUPPORT_ARCH_arm_any
a645023d
A
1497template <>
1498void SectionRelocationsAtom<arm>::encodeSectionReloc(ld::Internal::FinalSection* sect,
1499 const Entry& entry, std::vector<macho_relocation_info<P> >& relocs)
1500{
1501 macho_relocation_info<P> reloc1;
1502 macho_relocation_info<P> reloc2;
1503 macho_scattered_relocation_info<P>* sreloc1 = (macho_scattered_relocation_info<P>*)&reloc1;
1504 macho_scattered_relocation_info<P>* sreloc2 = (macho_scattered_relocation_info<P>*)&reloc2;
1505 uint64_t address = entry.inAtom->finalAddress()+entry.offsetInAtom - sect->address;
1506 bool external = entry.toTargetUsesExternalReloc;
1507 uint32_t symbolNum = sectSymNum(external, entry.toTarget);
1508 bool fromExternal = false;
1509 uint32_t fromSymbolNum = 0;
1510 if ( entry.fromTarget != NULL ) {
1511 fromExternal = entry.fromTargetUsesExternalReloc;
1512 fromSymbolNum = sectSymNum(fromExternal, entry.fromTarget);
1513 }
1514
1515
1516 switch ( entry.kind ) {
1517 case ld::Fixup::kindStoreTargetAddressARMBranch24:
1518 case ld::Fixup::kindStoreARMBranch24:
1519 case ld::Fixup::kindStoreARMDtraceCallSiteNop:
1520 case ld::Fixup::kindStoreARMDtraceIsEnableSiteClear:
1521 if ( !external && (entry.toAddend != 0) ) {
1522 // use scattered reloc is target offset is non-zero
1523 sreloc1->set_r_scattered(true);
1524 sreloc1->set_r_pcrel(true);
1525 sreloc1->set_r_length(2);
1526 sreloc1->set_r_type(ARM_RELOC_BR24);
1527 sreloc1->set_r_address(address);
1528 sreloc1->set_r_value(entry.toTarget->finalAddress());
1529 }
1530 else {
1531 reloc1.set_r_address(address);
1532 reloc1.set_r_symbolnum(symbolNum);
1533 reloc1.set_r_pcrel(true);
1534 reloc1.set_r_length(2);
1535 reloc1.set_r_extern(external);
1536 reloc1.set_r_type(ARM_RELOC_BR24);
1537 }
1538 relocs.push_back(reloc1);
1539 break;
1540
1541 case ld::Fixup::kindStoreTargetAddressThumbBranch22:
1542 case ld::Fixup::kindStoreThumbBranch22:
1543 case ld::Fixup::kindStoreThumbDtraceCallSiteNop:
1544 case ld::Fixup::kindStoreThumbDtraceIsEnableSiteClear:
1545 if ( !external && (entry.toAddend != 0) ) {
1546 // use scattered reloc is target offset is non-zero
1547 sreloc1->set_r_scattered(true);
1548 sreloc1->set_r_pcrel(true);
1549 sreloc1->set_r_length(2);
1550 sreloc1->set_r_type(ARM_THUMB_RELOC_BR22);
1551 sreloc1->set_r_address(address);
1552 sreloc1->set_r_value(entry.toTarget->finalAddress());
1553 }
1554 else {
1555 reloc1.set_r_address(address);
1556 reloc1.set_r_symbolnum(symbolNum);
1557 reloc1.set_r_pcrel(true);
1558 reloc1.set_r_length(2);
1559 reloc1.set_r_extern(external);
1560 reloc1.set_r_type(ARM_THUMB_RELOC_BR22);
1561 }
1562 relocs.push_back(reloc1);
1563 break;
1564
1565 case ld::Fixup::kindStoreLittleEndian32:
1566 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
1567 if ( entry.fromTarget != NULL ) {
1568 // this is a pointer-diff
1569 sreloc1->set_r_scattered(true);
1570 sreloc1->set_r_pcrel(false);
1571 sreloc1->set_r_length(2);
1572 if ( entry.toTarget->scope() == ld::Atom::scopeTranslationUnit )
1573 sreloc1->set_r_type(ARM_RELOC_LOCAL_SECTDIFF);
1574 else
1575 sreloc1->set_r_type(ARM_RELOC_SECTDIFF);
1576 sreloc1->set_r_address(address);
afe874b1
A
1577 if ( entry.toTarget == entry.inAtom ) {
1578 if ( entry.toAddend > entry.toTarget->size() )
1579 sreloc1->set_r_value(entry.toTarget->finalAddress()+entry.offsetInAtom);
1580 else
1581 sreloc1->set_r_value(entry.toTarget->finalAddress()+entry.toAddend);
1582 }
1583 else {
a645023d 1584 sreloc1->set_r_value(entry.toTarget->finalAddress());
afe874b1 1585 }
a645023d
A
1586 sreloc2->set_r_scattered(true);
1587 sreloc2->set_r_pcrel(false);
1588 sreloc2->set_r_length(2);
1589 sreloc2->set_r_type(ARM_RELOC_PAIR);
1590 sreloc2->set_r_address(0);
1591 if ( entry.fromTarget == entry.inAtom ) {
1592 //unsigned int pcBaseOffset = entry.inAtom->isThumb() ? 4 : 8;
1593 //if ( entry.fromAddend > pcBaseOffset )
1594 // sreloc2->set_r_value(entry.fromTarget->finalAddress()+entry.fromAddend-pcBaseOffset);
1595 //else
1596 sreloc2->set_r_value(entry.fromTarget->finalAddress()+entry.fromAddend);
1597 }
1598 else {
1599 sreloc2->set_r_value(entry.fromTarget->finalAddress());
1600 }
1601 relocs.push_back(reloc1);
1602 relocs.push_back(reloc2);
1603 }
1604 else {
1605 // regular pointer
1606 if ( !external && (entry.toAddend != 0) ) {
1607 // use scattered reloc is target offset is non-zero
1608 sreloc1->set_r_scattered(true);
1609 sreloc1->set_r_pcrel(false);
1610 sreloc1->set_r_length(2);
1611 sreloc1->set_r_type(ARM_RELOC_VANILLA);
1612 sreloc1->set_r_address(address);
1613 sreloc1->set_r_value(entry.toTarget->finalAddress());
1614 }
1615 else {
1616 reloc1.set_r_address(address);
1617 reloc1.set_r_symbolnum(symbolNum);
1618 reloc1.set_r_pcrel(false);
1619 reloc1.set_r_length(2);
1620 reloc1.set_r_extern(external);
1621 reloc1.set_r_type(ARM_RELOC_VANILLA);
1622 }
1623 relocs.push_back(reloc1);
1624 }
1625 break;
1626
1627 case ld::Fixup::kindStoreARMLow16:
1628 case ld::Fixup::kindStoreARMHigh16:
1629 case ld::Fixup::kindStoreThumbLow16:
1630 case ld::Fixup::kindStoreThumbHigh16:
1631 {
1632 int len = 0;
1633 uint32_t otherHalf = 0;
eaf282aa
A
1634 uint32_t value;
1635 if ( entry.fromTarget != NULL ) {
1636 // this is a sect-diff
1637 value = (entry.toTarget->finalAddress()+entry.toAddend) - (entry.fromTarget->finalAddress()+entry.fromAddend);
1638 }
1639 else {
1640 // this is an absolute address
1641 value = entry.toAddend;
1642 if ( !external )
1643 value += entry.toTarget->finalAddress();
1644 }
a645023d
A
1645 switch ( entry.kind ) {
1646 case ld::Fixup::kindStoreARMLow16:
1647 len = 0;
1648 otherHalf = value >> 16;
1649 break;
1650 case ld::Fixup::kindStoreARMHigh16:
1651 len = 1;
1652 otherHalf = value & 0xFFFF;
1653 break;
1654 case ld::Fixup::kindStoreThumbLow16:
1655 len = 2;
1656 otherHalf = value >> 16;
1657 break;
1658 case ld::Fixup::kindStoreThumbHigh16:
1659 len = 3;
1660 otherHalf = value & 0xFFFF;
1661 break;
1662 default:
1663 break;
1664 }
1665 if ( entry.fromTarget != NULL ) {
1666 // this is a sect-diff
1667 sreloc1->set_r_scattered(true);
1668 sreloc1->set_r_pcrel(false);
1669 sreloc1->set_r_length(len);
1670 sreloc1->set_r_type(ARM_RELOC_HALF_SECTDIFF);
1671 sreloc1->set_r_address(address);
1672 sreloc1->set_r_value(entry.toTarget->finalAddress());
1673 sreloc2->set_r_scattered(true);
1674 sreloc2->set_r_pcrel(false);
1675 sreloc2->set_r_length(len);
1676 sreloc2->set_r_type(ARM_RELOC_PAIR);
1677 sreloc2->set_r_address(otherHalf);
1678 if ( entry.fromTarget == entry.inAtom )
1679 sreloc2->set_r_value(entry.fromTarget->finalAddress()+entry.fromAddend);
1680 else
1681 sreloc2->set_r_value(entry.fromTarget->finalAddress());
1682 relocs.push_back(reloc1);
1683 relocs.push_back(reloc2);
1684 }
1685 else {
1686 // this is absolute address
1687 if ( !external && (entry.toAddend != 0) ) {
1688 // use scattered reloc is target offset is non-zero
1689 sreloc1->set_r_scattered(true);
1690 sreloc1->set_r_pcrel(false);
1691 sreloc1->set_r_length(len);
1692 sreloc1->set_r_type(ARM_RELOC_HALF);
1693 sreloc1->set_r_address(address);
1694 sreloc1->set_r_value(entry.toTarget->finalAddress());
1695 reloc2.set_r_address(otherHalf);
1696 reloc2.set_r_symbolnum(0);
1697 reloc2.set_r_pcrel(false);
1698 reloc2.set_r_length(len);
1699 reloc2.set_r_extern(false);
1700 reloc2.set_r_type(ARM_RELOC_PAIR);
1701 relocs.push_back(reloc1);
1702 relocs.push_back(reloc2);
1703 }
1704 else {
1705 reloc1.set_r_address(address);
1706 reloc1.set_r_symbolnum(symbolNum);
1707 reloc1.set_r_pcrel(false);
1708 reloc1.set_r_length(len);
afe874b1 1709 reloc1.set_r_extern(external);
a645023d
A
1710 reloc1.set_r_type(ARM_RELOC_HALF);
1711 reloc2.set_r_address(otherHalf); // other half
1712 reloc2.set_r_symbolnum(0);
1713 reloc2.set_r_pcrel(false);
1714 reloc2.set_r_length(len);
1715 reloc2.set_r_extern(false);
1716 reloc2.set_r_type(ARM_RELOC_PAIR);
1717 relocs.push_back(reloc1);
1718 relocs.push_back(reloc2);
1719 }
1720 }
1721 }
1722 break;
1723
1724 default:
1725 assert(0 && "need to handle -r reloc");
1726
1727 }
1728}
ebf6f434 1729#endif
a645023d 1730
f80fe69f
A
1731#if SUPPORT_ARCH_arm64
1732template <>
1733void SectionRelocationsAtom<arm64>::encodeSectionReloc(ld::Internal::FinalSection* sect,
1734 const Entry& entry, std::vector<macho_relocation_info<P> >& relocs)
1735{
1736 macho_relocation_info<P> reloc1;
1737 macho_relocation_info<P> reloc2;
1738 uint64_t address = entry.inAtom->finalAddress()+entry.offsetInAtom - sect->address;
1739 bool external = entry.toTargetUsesExternalReloc;
1740 uint32_t symbolNum = sectSymNum(external, entry.toTarget);
1741 bool fromExternal = false;
1742 uint32_t fromSymbolNum = 0;
1743 if ( entry.fromTarget != NULL ) {
1744 fromExternal = entry.fromTargetUsesExternalReloc;
1745 fromSymbolNum = sectSymNum(fromExternal, entry.fromTarget);
1746 }
1747
1748
1749 switch ( entry.kind ) {
1750 case ld::Fixup::kindStoreARM64Branch26:
1751 if ( entry.toAddend != 0 ) {
1752 assert(entry.toAddend < 0x400000);
1753 reloc2.set_r_address(address);
1754 reloc2.set_r_symbolnum(entry.toAddend);
1755 reloc2.set_r_pcrel(false);
1756 reloc2.set_r_length(2);
1757 reloc2.set_r_extern(false);
1758 reloc2.set_r_type(ARM64_RELOC_ADDEND);
1759 relocs.push_back(reloc2);
1760 }
1761 // fall into next case
1762 case ld::Fixup::kindStoreTargetAddressARM64Branch26:
1763 case ld::Fixup::kindStoreARM64DtraceCallSiteNop:
1764 case ld::Fixup::kindStoreARM64DtraceIsEnableSiteClear:
1765 reloc1.set_r_address(address);
1766 reloc1.set_r_symbolnum(symbolNum);
1767 reloc1.set_r_pcrel(true);
1768 reloc1.set_r_length(2);
1769 reloc1.set_r_extern(external);
1770 reloc1.set_r_type(ARM64_RELOC_BRANCH26);
1771 relocs.push_back(reloc1);
1772 break;
1773
1774 case ld::Fixup::kindStoreARM64Page21:
1775 if ( entry.toAddend != 0 ) {
1776 assert(entry.toAddend < 0x400000);
1777 reloc2.set_r_address(address);
1778 reloc2.set_r_symbolnum(entry.toAddend);
1779 reloc2.set_r_pcrel(false);
1780 reloc2.set_r_length(2);
1781 reloc2.set_r_extern(false);
1782 reloc2.set_r_type(ARM64_RELOC_ADDEND);
1783 relocs.push_back(reloc2);
1784 }
1785 // fall into next case
1786 case ld::Fixup::kindStoreTargetAddressARM64Page21:
1787 reloc1.set_r_address(address);
1788 reloc1.set_r_symbolnum(symbolNum);
1789 reloc1.set_r_pcrel(true);
1790 reloc1.set_r_length(2);
1791 reloc1.set_r_extern(external);
1792 reloc1.set_r_type(ARM64_RELOC_PAGE21);
1793 relocs.push_back(reloc1);
1794 break;
1795
1796 case ld::Fixup::kindStoreARM64PageOff12:
1797 if ( entry.toAddend != 0 ) {
1798 assert(entry.toAddend < 0x400000);
1799 reloc2.set_r_address(address);
1800 reloc2.set_r_symbolnum(entry.toAddend);
1801 reloc2.set_r_pcrel(false);
1802 reloc2.set_r_length(2);
1803 reloc2.set_r_extern(false);
1804 reloc2.set_r_type(ARM64_RELOC_ADDEND);
1805 relocs.push_back(reloc2);
1806 }
1807 // fall into next case
1808 case ld::Fixup::kindStoreTargetAddressARM64PageOff12:
1809 reloc1.set_r_address(address);
1810 reloc1.set_r_symbolnum(symbolNum);
1811 reloc1.set_r_pcrel(false);
1812 reloc1.set_r_length(2);
1813 reloc1.set_r_extern(external);
1814 reloc1.set_r_type(ARM64_RELOC_PAGEOFF12);
1815 relocs.push_back(reloc1);
1816 break;
1817
1818 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
1819 case ld::Fixup::kindStoreARM64GOTLoadPage21:
1820 reloc1.set_r_address(address);
1821 reloc1.set_r_symbolnum(symbolNum);
1822 reloc1.set_r_pcrel(true);
1823 reloc1.set_r_length(2);
1824 reloc1.set_r_extern(external);
1825 reloc1.set_r_type(ARM64_RELOC_GOT_LOAD_PAGE21);
1826 relocs.push_back(reloc1);
1827 break;
1828
1829 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12:
1830 case ld::Fixup::kindStoreARM64GOTLoadPageOff12:
1831 reloc1.set_r_address(address);
1832 reloc1.set_r_symbolnum(symbolNum);
1833 reloc1.set_r_pcrel(false);
1834 reloc1.set_r_length(2);
1835 reloc1.set_r_extern(external);
1836 reloc1.set_r_type(ARM64_RELOC_GOT_LOAD_PAGEOFF12);
1837 relocs.push_back(reloc1);
1838 break;
1839
82b4b32b
A
1840 case ld::Fixup::kindStoreARM64TLVPLoadPageOff12:
1841 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12:
1842 reloc1.set_r_address(address);
1843 reloc1.set_r_symbolnum(symbolNum);
1844 reloc1.set_r_pcrel(false);
1845 reloc1.set_r_length(2);
1846 reloc1.set_r_extern(external);
1847 reloc1.set_r_type(ARM64_RELOC_TLVP_LOAD_PAGEOFF12);
1848 relocs.push_back(reloc1);
1849 break;
1850
1851 case ld::Fixup::kindStoreARM64TLVPLoadPage21:
1852 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21:
1853 reloc1.set_r_address(address);
1854 reloc1.set_r_symbolnum(symbolNum);
1855 reloc1.set_r_pcrel(true);
1856 reloc1.set_r_length(2);
1857 reloc1.set_r_extern(external);
1858 reloc1.set_r_type(ARM64_RELOC_TLVP_LOAD_PAGE21);
1859 relocs.push_back(reloc1);
1860 break;
f80fe69f
A
1861
1862 case ld::Fixup::kindStoreLittleEndian64:
1863 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
1864 if ( entry.fromTarget != NULL ) {
1865 // this is a pointer-diff
1866 reloc1.set_r_address(address);
1867 reloc1.set_r_symbolnum(symbolNum);
1868 reloc1.set_r_pcrel(false);
1869 reloc1.set_r_length(3);
1870 reloc1.set_r_extern(external);
1871 reloc1.set_r_type(ARM64_RELOC_UNSIGNED);
1872 reloc2.set_r_address(address);
1873 reloc2.set_r_symbolnum(fromSymbolNum);
1874 reloc2.set_r_pcrel(false);
1875 reloc2.set_r_length(3);
1876 reloc2.set_r_extern(fromExternal);
1877 reloc2.set_r_type(ARM64_RELOC_SUBTRACTOR);
1878 relocs.push_back(reloc2);
1879 relocs.push_back(reloc1);
1880 }
1881 else {
1882 // regular pointer
1883 reloc1.set_r_address(address);
1884 reloc1.set_r_symbolnum(symbolNum);
1885 reloc1.set_r_pcrel(false);
1886 reloc1.set_r_length(3);
1887 reloc1.set_r_extern(external);
1888 reloc1.set_r_type(ARM64_RELOC_UNSIGNED);
1889 relocs.push_back(reloc1);
1890 }
1891 break;
1892
1893 case ld::Fixup::kindStoreLittleEndian32:
1894 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
1895 if ( entry.fromTarget != NULL ) {
1896 // this is a pointer-diff
1897 reloc1.set_r_address(address);
1898 reloc1.set_r_symbolnum(symbolNum);
1899 reloc1.set_r_pcrel(false);
1900 reloc1.set_r_length(2);
1901 reloc1.set_r_extern(external);
1902 reloc1.set_r_type(ARM64_RELOC_UNSIGNED);
1903 reloc2.set_r_address(address);
1904 reloc2.set_r_symbolnum(fromSymbolNum);
1905 reloc2.set_r_pcrel(false);
1906 reloc2.set_r_length(2);
1907 reloc2.set_r_extern(fromExternal);
1908 reloc2.set_r_type(ARM64_RELOC_SUBTRACTOR);
1909 relocs.push_back(reloc2);
1910 relocs.push_back(reloc1);
1911 }
1912 else {
1913 // regular pointer
1914 reloc1.set_r_address(address);
1915 reloc1.set_r_symbolnum(symbolNum);
1916 reloc1.set_r_pcrel(false);
1917 reloc1.set_r_length(2);
1918 reloc1.set_r_extern(external);
1919 reloc1.set_r_type(ARM64_RELOC_UNSIGNED);
1920 relocs.push_back(reloc1);
1921 }
1922 break;
1923
1924 case ld::Fixup::kindStoreARM64PointerToGOT:
1925 reloc1.set_r_address(address);
1926 reloc1.set_r_symbolnum(symbolNum);
1927 reloc1.set_r_pcrel(false);
1928 reloc1.set_r_length(3);
1929 reloc1.set_r_extern(external);
1930 reloc1.set_r_type(ARM64_RELOC_POINTER_TO_GOT);
1931 relocs.push_back(reloc1);
1932 break;
1933
1934 case ld::Fixup::kindStoreARM64PCRelToGOT:
1935 reloc1.set_r_address(address);
1936 reloc1.set_r_symbolnum(symbolNum);
1937 reloc1.set_r_pcrel(true);
1938 reloc1.set_r_length(2);
1939 reloc1.set_r_extern(external);
1940 reloc1.set_r_type(ARM64_RELOC_POINTER_TO_GOT);
1941 relocs.push_back(reloc1);
1942 break;
1943
e456bf10
A
1944#if SUPPORT_ARCH_arm64e
1945 case ld::Fixup::kindStoreLittleEndianAuth64:
1946 case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64: {
1947 assert(entry.fromTarget == NULL);
1948 assert(entry.hasAuthData);
1949
1950 // An authenticated pointer is:
1951 // {
1952 // int32_t addend;
1953 // uint16_t diversityData;
1954 // uint16_t hasAddressDiversity : 1;
1955 // uint16_t key : 2;
1956 // uint16_t zeroes : 11;
1957 // uint16_t zero : 1;
1958 // uint16_t authenticated : 1;
1959 // }
1960 reloc1.set_r_address(address);
1961 reloc1.set_r_symbolnum(symbolNum);
1962 reloc1.set_r_pcrel(false);
1963 reloc1.set_r_length(3);
1964 reloc1.set_r_extern(external);
1965 reloc1.set_r_type(ARM64_RELOC_AUTHENTICATED_POINTER);
1966 relocs.push_back(reloc1);
1967 }
1968 break;
1969#endif
1970
f80fe69f
A
1971 default:
1972 assert(0 && "need to handle arm64 -r reloc");
1973
1974 }
1975
1976}
1977#endif // SUPPORT_ARCH_arm64
a645023d 1978
a645023d
A
1979
1980template <typename A>
1981void SectionRelocationsAtom<A>::addSectionReloc(ld::Internal::FinalSection* sect, ld::Fixup::Kind kind,
1982 const ld::Atom* inAtom, uint32_t offsetInAtom,
1983 bool toTargetUsesExternalReloc ,bool fromTargetExternalReloc,
e456bf10
A
1984#if SUPPORT_ARCH_arm64e
1985 ld::Fixup* fixupWithAuthData,
1986#endif
a645023d
A
1987 const ld::Atom* toTarget, uint64_t toAddend,
1988 const ld::Atom* fromTarget, uint64_t fromAddend)
1989{
1990 Entry entry;
1991 entry.kind = kind;
1992 entry.toTargetUsesExternalReloc = toTargetUsesExternalReloc;
1993 entry.fromTargetUsesExternalReloc = fromTargetExternalReloc;
1994 entry.inAtom = inAtom;
1995 entry.offsetInAtom = offsetInAtom;
1996 entry.toTarget = toTarget;
1997 entry.toAddend = toAddend;
1998 entry.fromTarget = fromTarget;
1999 entry.fromAddend = fromAddend;
e456bf10
A
2000#if SUPPORT_ARCH_arm64e
2001 if (fixupWithAuthData) {
2002 entry.hasAuthData = true;
2003 entry.authData = fixupWithAuthData->u.authData;
2004 } else {
2005 entry.hasAuthData = false;
2006 }
2007#endif
a645023d
A
2008
2009 static ld::Internal::FinalSection* lastSection = NULL;
2010 static SectionAndEntries* lastSectionAndEntries = NULL;
2011
2012 if ( sect != lastSection ) {
2013 for(typename std::vector<SectionAndEntries>::iterator it=_entriesBySection.begin(); it != _entriesBySection.end(); ++it) {
2014 if ( sect == it->sect ) {
2015 lastSection = sect;
2016 lastSectionAndEntries = &*it;
2017 break;
2018 }
2019 }
2020 if ( sect != lastSection ) {
2021 SectionAndEntries tmp;
2022 tmp.sect = sect;
2023 _entriesBySection.push_back(tmp);
2024 lastSection = sect;
2025 lastSectionAndEntries = &_entriesBySection.back();
2026 }
2027 }
2028 lastSectionAndEntries->entries.push_back(entry);
2029}
2030
2031template <typename A>
2032void SectionRelocationsAtom<A>::encode()
2033{
2034 // convert each Entry record to one or two reloc records
2035 for(typename std::vector<SectionAndEntries>::iterator it=_entriesBySection.begin(); it != _entriesBySection.end(); ++it) {
2036 SectionAndEntries& se = *it;
2037 for(typename std::vector<Entry>::iterator eit=se.entries.begin(); eit != se.entries.end(); ++eit) {
2038 encodeSectionReloc(se.sect, *eit, se.relocs);
2039 }
2040 }
2041
2042 // update sections with start and count or relocs
2043 uint32_t index = 0;
2044 for(typename std::vector<SectionAndEntries>::iterator it=_entriesBySection.begin(); it != _entriesBySection.end(); ++it) {
2045 SectionAndEntries& se = *it;
2046 se.sect->relocStart = index;
2047 se.sect->relocCount = se.relocs.size();
2048 index += se.sect->relocCount;
2049 }
2050
2051}
2052
2053
2054
2055template <typename A>
2056class IndirectSymbolTableAtom : public ClassicLinkEditAtom
2057{
2058public:
2059 IndirectSymbolTableAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
2060 : ClassicLinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { }
2061
2062 // overrides of ld::Atom
2063 virtual const char* name() const { return "indirect symbol table"; }
2064 virtual uint64_t size() const;
2065 virtual void copyRawContent(uint8_t buffer[]) const;
2066 // overrides of ClassicLinkEditAtom
2067 virtual void encode();
2068
2069private:
2070 typedef typename A::P P;
2071 typedef typename A::P::E E;
2072 typedef typename A::P::uint_t pint_t;
2073
2074 void encodeStubSection(ld::Internal::FinalSection* sect);
2075 void encodeLazyPointerSection(ld::Internal::FinalSection* sect);
2076 void encodeNonLazyPointerSection(ld::Internal::FinalSection* sect);
2077 uint32_t symIndexOfStubAtom(const ld::Atom*);
2078 uint32_t symIndexOfLazyPointerAtom(const ld::Atom*);
2079 uint32_t symIndexOfNonLazyPointerAtom(const ld::Atom*);
2080 uint32_t symbolIndex(const ld::Atom*);
a645023d
A
2081
2082
2083 std::vector<uint32_t> _entries;
2084
2085 static ld::Section _s_section;
2086};
2087
2088template <typename A>
2089ld::Section IndirectSymbolTableAtom<A>::_s_section("__LINKEDIT", "__ind_sym_tab", ld::Section::typeLinkEdit, true);
2090
2091
2092
2093
2094template <typename A>
2095uint32_t IndirectSymbolTableAtom<A>::symbolIndex(const ld::Atom* atom)
2096{
2097 std::map<const ld::Atom*, uint32_t>::iterator pos = this->_writer._atomToSymbolIndex.find(atom);
2098 if ( pos != this->_writer._atomToSymbolIndex.end() )
2099 return pos->second;
2100 //fprintf(stderr, "_atomToSymbolIndex content:\n");
2101 //for(std::map<const ld::Atom*, uint32_t>::iterator it = this->_writer._atomToSymbolIndex.begin(); it != this->_writer._atomToSymbolIndex.end(); ++it) {
2102 // fprintf(stderr, "%p(%s) => %d\n", it->first, it->first->name(), it->second);
2103 //}
2104 throwf("internal error: atom not found in symbolIndex(%s)", atom->name());
2105}
2106
2107template <typename A>
2108uint32_t IndirectSymbolTableAtom<A>::symIndexOfStubAtom(const ld::Atom* stubAtom)
2109{
2110 for (ld::Fixup::iterator fit = stubAtom->fixupsBegin(); fit != stubAtom->fixupsEnd(); ++fit) {
2111 if ( fit->binding == ld::Fixup::bindingDirectlyBound ) {
ec29ba20
A
2112 ld::Atom::ContentType type = fit->u.target->contentType();
2113 if (( type == ld::Atom::typeLazyPointer) || (type == ld::Atom::typeLazyDylibPointer) )
2114 return symIndexOfLazyPointerAtom(fit->u.target);
2115 if ( type == ld::Atom::typeNonLazyPointer )
2116 return symIndexOfNonLazyPointerAtom(fit->u.target);
a645023d
A
2117 }
2118 }
2119 throw "internal error: stub missing fixup to lazy pointer";
2120}
2121
2122
2123template <typename A>
2124uint32_t IndirectSymbolTableAtom<A>::symIndexOfLazyPointerAtom(const ld::Atom* lpAtom)
2125{
e456bf10
A
2126 if ( lpAtom->contentType() == ld::Atom::typeLazyPointer || lpAtom->contentType() == ld::Atom::typeLazyDylibPointer ) {
2127 for (ld::Fixup::iterator fit = lpAtom->fixupsBegin(); fit != lpAtom->fixupsEnd(); ++fit) {
2128 if ( fit->kind == ld::Fixup::kindLazyTarget ) {
2129 assert(fit->binding == ld::Fixup::bindingDirectlyBound);
2130 return symbolIndex(fit->u.target);
2131 }
2132 }
2133 }
2134 else if ( lpAtom->contentType() == ld::Atom::typeNonLazyPointer ) {
2135 for (ld::Fixup::iterator fit = lpAtom->fixupsBegin(); fit != lpAtom->fixupsEnd(); ++fit) {
2136 if ( (fit->kind == ld::Fixup::kindStoreTargetAddressLittleEndian32) || (fit->kind == ld::Fixup::kindStoreTargetAddressLittleEndian64) ) {
2137 assert(fit->binding == ld::Fixup::bindingDirectlyBound);
2138 return symbolIndex(fit->u.target);
2139 }
a645023d
A
2140 }
2141 }
2142 throw "internal error: lazy pointer missing fixupLazyTarget fixup";
2143}
2144
2145template <typename A>
2146uint32_t IndirectSymbolTableAtom<A>::symIndexOfNonLazyPointerAtom(const ld::Atom* nlpAtom)
2147{
2148 //fprintf(stderr, "symIndexOfNonLazyPointerAtom(%p) %s\n", nlpAtom, nlpAtom->name());
2149 for (ld::Fixup::iterator fit = nlpAtom->fixupsBegin(); fit != nlpAtom->fixupsEnd(); ++fit) {
e456bf10
A
2150#if SUPPORT_ARCH_arm64e
2151 // Skip authentication fixups
2152 if ( fit->clusterSize == ld::Fixup::k1of2 ) {
2153 if ( fit->kind != ld::Fixup::kindSetAuthData )
2154 break;
2155 ++fit;
2156 } else
2157#endif
2158 {
2159 if ( fit->clusterSize != ld::Fixup::k1of1 )
2160 return INDIRECT_SYMBOL_LOCAL;
2161 }
a645023d
A
2162 const ld::Atom* target;
2163 switch ( fit->binding ) {
2164 case ld::Fixup::bindingDirectlyBound:
2165 target = fit->u.target;
2166 break;
2167 case ld::Fixup::bindingsIndirectlyBound:
2168 target = _state.indirectBindingTable[fit->u.bindingIndex];
2169 break;
2170 default:
2171 throw "internal error: unexpected non-lazy pointer binding";
2172 }
a645023d
A
2173 bool targetIsGlobal = (target->scope() == ld::Atom::scopeGlobal);
2174 switch ( target->definition() ) {
2175 case ld::Atom::definitionRegular:
2176 if ( targetIsGlobal ) {
2177 if ( _options.outputKind() == Options::kObjectFile ) {
2178 // nlpointer to global symbol uses indirect symbol table in .o files
2179 return symbolIndex(target);
2180 }
2181 else if ( target->combine() == ld::Atom::combineByName ) {
2182 // dyld needs to bind nlpointer to global weak def
2183 return symbolIndex(target);
2184 }
2185 else if ( _options.nameSpace() != Options::kTwoLevelNameSpace ) {
2186 // dyld needs to bind nlpointer to global def linked for flat namespace
2187 return symbolIndex(target);
2188 }
2189 }
2190 break;
2191 case ld::Atom::definitionTentative:
2192 case ld::Atom::definitionAbsolute:
2193 if ( _options.outputKind() == Options::kObjectFile ) {
2194 // tentative def in .o file always uses symbol index
2195 return symbolIndex(target);
2196 }
2197 // dyld needs to bind nlpointer to global def linked for flat namespace
2198 if ( targetIsGlobal && _options.nameSpace() != Options::kTwoLevelNameSpace )
2199 return symbolIndex(target);
2200 break;
2201 case ld::Atom::definitionProxy:
2202 // dyld needs to bind nlpointer to something in another dylib
2203 {
2204 const ld::dylib::File* dylib = dynamic_cast<const ld::dylib::File*>(target->file());
2205 if ( (dylib != NULL) && dylib->willBeLazyLoadedDylib() )
2206 throwf("illegal data reference to %s in lazy loaded dylib %s", target->name(), dylib->path());
2207 }
2208 return symbolIndex(target);
2209 }
2210 }
2211 if ( nlpAtom->fixupsBegin() == nlpAtom->fixupsEnd() ) {
2212 // no fixups means this is the ImageLoader cache slot
2213 return INDIRECT_SYMBOL_ABS;
2214 }
2215
2216 // The magic index INDIRECT_SYMBOL_LOCAL tells dyld it should does not need to bind
2217 // this non-lazy pointer.
2218 return INDIRECT_SYMBOL_LOCAL;
2219}
2220
2221
2222
2223template <typename A>
2224void IndirectSymbolTableAtom<A>::encodeStubSection(ld::Internal::FinalSection* sect)
2225{
2226 sect->indirectSymTabStartIndex = _entries.size();
2227 sect->indirectSymTabElementSize = sect->atoms[0]->size();
2228 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
2229 _entries.push_back(symIndexOfStubAtom(*ait));
2230 }
2231}
2232
2233template <typename A>
2234void IndirectSymbolTableAtom<A>::encodeLazyPointerSection(ld::Internal::FinalSection* sect)
2235{
2236 sect->indirectSymTabStartIndex = _entries.size();
2237 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
2238 _entries.push_back(symIndexOfLazyPointerAtom(*ait));
2239 }
2240}
2241
2242template <typename A>
2243void IndirectSymbolTableAtom<A>::encodeNonLazyPointerSection(ld::Internal::FinalSection* sect)
2244{
2245 sect->indirectSymTabStartIndex = _entries.size();
2246 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
2247 _entries.push_back(symIndexOfNonLazyPointerAtom(*ait));
2248 }
2249}
2250
a645023d
A
2251template <typename A>
2252void IndirectSymbolTableAtom<A>::encode()
2253{
ebf6f434
A
2254 // static executables should not have an indirect symbol table, unless PIE
2255 if ( (this->_options.outputKind() == Options::kStaticExecutable) && !_options.positionIndependentExecutable() )
a645023d
A
2256 return;
2257
ec29ba20
A
2258 // x86_64 kext bundles should not have an indirect symbol table unless using stubs
2259 if ( (this->_options.outputKind() == Options::kKextBundle) && !this->_options.kextsUseStubs() )
a645023d
A
2260 return;
2261
ebf6f434
A
2262 // slidable static executables (-static -pie) should not have an indirect symbol table
2263 if ( (this->_options.outputKind() == Options::kStaticExecutable) && this->_options.positionIndependentExecutable() )
2264 return;
2265
a645023d
A
2266 // find all special sections that need a range of the indirect symbol table section
2267 for (std::vector<ld::Internal::FinalSection*>::iterator sit = this->_state.sections.begin(); sit != this->_state.sections.end(); ++sit) {
2268 ld::Internal::FinalSection* sect = *sit;
2269 switch ( sect->type() ) {
2270 case ld::Section::typeStub:
2271 case ld::Section::typeStubClose:
2272 this->encodeStubSection(sect);
2273 break;
2274 case ld::Section::typeLazyPointerClose:
2275 case ld::Section::typeLazyPointer:
2276 case ld::Section::typeLazyDylibPointer:
2277 this->encodeLazyPointerSection(sect);
2278 break;
2279 case ld::Section::typeNonLazyPointer:
2280 this->encodeNonLazyPointerSection(sect);
2281 break;
2282 default:
2283 break;
2284 }
2285 }
2286}
2287
2288template <typename A>
2289uint64_t IndirectSymbolTableAtom<A>::size() const
2290{
2291 return _entries.size() * sizeof(uint32_t);
2292}
2293
2294template <typename A>
2295void IndirectSymbolTableAtom<A>::copyRawContent(uint8_t buffer[]) const
2296{
2297 uint32_t* array = (uint32_t*)buffer;
2298 for(unsigned long i=0; i < _entries.size(); ++i) {
2299 E::set32(array[i], _entries[i]);
2300 }
2301}
2302
2303
2304
2305
2306
2307
2308
2309
2310} // namespace tool
2311} // namespace ld
2312
2313#endif // __LINKEDIT_CLASSIC_HPP__