]> git.saurik.com Git - apple/ld64.git/blame - src/ld/LinkEditClassic.hpp
ld64-274.1.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 {
494 if ( this->_options.prebind() )
495 entry.set_n_type(N_PBUD | N_EXT);
496 else
497 entry.set_n_type(N_UNDF | N_EXT);
498 }
499
500 // set n_sect
501 entry.set_n_sect(0);
502
503 uint16_t desc = 0;
504 if ( this->_options.outputKind() != Options::kObjectFile ) {
505 uint8_t ordinal = this->classicOrdinalForProxy(atom);
506 //fprintf(stderr, "ordinal=%u from reader=%p for symbol=%s\n", ordinal, atom->getFile(), atom->getName());
507 SET_LIBRARY_ORDINAL(desc, ordinal);
508
509#if 0
510 // set n_desc ( high byte is library ordinal, low byte is reference type )
511 std::map<const ObjectFile::Atom*,ObjectFile::Atom*>::iterator pos = fStubsMap.find(atom);
512 if ( pos != fStubsMap.end() || ( strncmp(atom->getName(), ".objc_class_name_", 17) == 0) )
513 desc |= REFERENCE_FLAG_UNDEFINED_LAZY;
514 else
515 desc |= REFERENCE_FLAG_UNDEFINED_NON_LAZY;
516#endif
517 }
518 else if ( atom->definition() == ld::Atom::definitionTentative ) {
519 uint8_t align = atom->alignment().powerOf2;
520 // always record custom alignment of common symbols to match what compiler does
521 SET_COMM_ALIGN(desc, align);
522 }
523 if ( (this->_options.outputKind() != Options::kObjectFile)
524 && (atom->definition() == ld::Atom::definitionProxy)
525 && (atom->combine() == ld::Atom::combineByName) ) {
526 desc |= N_REF_TO_WEAK;
527 }
afe874b1
A
528 const ld::dylib::File* dylib = dynamic_cast<const ld::dylib::File*>(atom->file());
529 if ( atom->weakImported() || ((dylib != NULL) && dylib->forcedWeakLinked()) )
a645023d
A
530 desc |= N_WEAK_REF;
531 entry.set_n_desc(desc);
532
533 // set n_value, zero for import proxy and size for tentative definition
534 if ( atom->definition() == ld::Atom::definitionTentative )
535 entry.set_n_value(atom->size());
599556ff 536 else if ( atom->section().type() != ld::Section::typeTempAlias )
a645023d 537 entry.set_n_value(0);
599556ff
A
538 else {
539 assert(atom->fixupsBegin() != atom->fixupsEnd());
540 for (ld::Fixup::iterator fit = atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
541 assert(fit->kind == ld::Fixup::kindNoneFollowOn);
542 switch ( fit->binding ) {
543 case ld::Fixup::bindingByNameUnbound:
544 entry.set_n_value(pool->add(fit->u.name));
545 break;
546 case ld::Fixup::bindingsIndirectlyBound:
547 entry.set_n_value(pool->add((_state.indirectBindingTable[fit->u.bindingIndex])->name()));
548 break;
549 default:
550 assert(0 && "internal error: unexpected alias binding");
551 }
552 }
553 }
a645023d
A
554
555 // add to array
556 _imports.push_back(entry);
557}
558
559template <typename A>
560uint8_t SymbolTableAtom<A>::sectionIndexForStab(const ld::relocatable::File::Stab& stab)
561{
562 // in FUN stabs, n_sect field is 0 for start FUN and 1 for end FUN
563 if ( stab.type == N_FUN )
564 return stab.other;
565 else if ( stab.type == N_GSYM )
566 return 0;
567 else if ( stab.atom != NULL )
568 return stab.atom->machoSection();
569 else
570 return stab.other;
571}
572
573
574template <typename A>
575uint64_t SymbolTableAtom<A>::valueForStab(const ld::relocatable::File::Stab& stab)
576{
577 switch ( stab.type ) {
578 case N_FUN:
579 if ( stab.atom == NULL ) {
580 // <rdar://problem/5591394> Add support to ld64 for N_FUN stabs when used for symbolic constants
581 return stab.value;
582 }
583 if ( (stab.string == NULL) || (strlen(stab.string) == 0) ) {
584 // end of function N_FUN has size
585 return stab.atom->size();
586 }
587 else {
588 // start of function N_FUN has address
589 return stab.atom->finalAddress();
590 }
591 case N_LBRAC:
592 case N_RBRAC:
593 case N_SLINE:
594 if ( stab.atom == NULL )
595 // some weird assembly files have slines not associated with a function
596 return stab.value;
597 else
598 // all these stab types need their value changed from an offset in the atom to an address
599 return stab.atom->finalAddress() + stab.value;
600 case N_STSYM:
601 case N_LCSYM:
602 case N_BNSYM:
603 // all these need address of atom
604 if ( stab.atom != NULL )
605 return stab.atom->finalAddress();
606 else
607 return 0; // <rdar://problem/7811357> work around for mismatch N_BNSYM
608 case N_ENSYM:
609 return stab.atom->size();
610 case N_SO:
611 if ( stab.atom == NULL ) {
612 return 0;
613 }
614 else {
615 if ( (stab.string == NULL) || (strlen(stab.string) == 0) ) {
616 // end of translation unit N_SO has address of end of last atom
617 return stab.atom->finalAddress() + stab.atom->size();
618 }
619 else {
620 // start of translation unit N_SO has address of end of first atom
621 return stab.atom->finalAddress();
622 }
623 }
624 break;
625 default:
626 return stab.value;
627 }
628}
629
630template <typename A>
631uint32_t SymbolTableAtom<A>::stringOffsetForStab(const ld::relocatable::File::Stab& stab, StringPoolAtom* pool)
632{
633 switch (stab.type) {
634 case N_SO:
635 if ( (stab.string == NULL) || stab.string[0] == '\0' ) {
636 return pool->emptyString();
637 break;
638 }
639 // fall into uniquing case
640 case N_SOL:
641 case N_BINCL:
642 case N_EXCL:
643 return pool->addUnique(stab.string);
644 break;
645 default:
646 if ( stab.string == NULL )
647 return 0;
648 else if ( stab.string[0] == '\0' )
649 return pool->emptyString();
650 else
651 return pool->add(stab.string);
652 }
653 return 0;
654}
655
656
657
658template <typename A>
659bool SymbolTableAtom<A>::hasStabs(uint32_t& ssos, uint32_t& ssoe, uint32_t& sos, uint32_t& soe)
660{
661 ssos = _stabsStringsOffsetStart;
662 ssoe = _stabsStringsOffsetEnd;
663 sos = _stabsIndexStart * sizeof(macho_nlist<P>);
664 soe = _stabsIndexEnd * sizeof(macho_nlist<P>);
665 return ( (_stabsIndexStart != _stabsIndexEnd) || (_stabsStringsOffsetStart != _stabsStringsOffsetEnd) );
666}
667
ebf6f434 668
a645023d
A
669template <typename A>
670void SymbolTableAtom<A>::encode()
671{
0a8dc3df
A
672 // Note: We lay out the symbol table so that the strings for the stabs (local) symbols are at the
673 // end of the string pool. The stabs strings are not used when calculated the UUID for the image.
674 // If the stabs strings were not last, the string offsets for all other symbols may very which would alter the UUID.
a645023d 675
0a8dc3df
A
676 // reserve space for local symbols
677 uint32_t localsCount = _state.stabs.size() + this->_writer._localAtoms.size();
a645023d
A
678
679 // make nlist entries for all global symbols
0a8dc3df 680 std::vector<const ld::Atom*>& globalAtoms = this->_writer._exportedAtoms;
a645023d 681 _globals.reserve(globalAtoms.size());
0a8dc3df
A
682 uint32_t symbolIndex = localsCount;
683 this->_writer._globalSymbolsStartIndex = localsCount;
a645023d
A
684 for (std::vector<const ld::Atom*>::const_iterator it=globalAtoms.begin(); it != globalAtoms.end(); ++it) {
685 const ld::Atom* atom = *it;
686 this->addGlobal(atom, this->_writer._stringPoolAtom);
687 this->_writer._atomToSymbolIndex[atom] = symbolIndex++;
688 }
689 this->_writer._globalSymbolsCount = symbolIndex - this->_writer._globalSymbolsStartIndex;
690
691 // make nlist entries for all undefined (imported) symbols
692 std::vector<const ld::Atom*>& importAtoms = this->_writer._importedAtoms;
693 _imports.reserve(importAtoms.size());
694 this->_writer._importSymbolsStartIndex = symbolIndex;
695 for (std::vector<const ld::Atom*>::const_iterator it=importAtoms.begin(); it != importAtoms.end(); ++it) {
696 this->addImport(*it, this->_writer._stringPoolAtom);
697 this->_writer._atomToSymbolIndex[*it] = symbolIndex++;
698 }
699 this->_writer._importSymbolsCount = symbolIndex - this->_writer._importSymbolsStartIndex;
0a8dc3df
A
700
701 // go back to start and make nlist entries for all local symbols
702 std::vector<const ld::Atom*>& localAtoms = this->_writer._localAtoms;
703 _locals.reserve(localsCount);
704 symbolIndex = 0;
705 this->_writer._localSymbolsStartIndex = 0;
706 _stabsIndexStart = 0;
707 _stabsStringsOffsetStart = this->_writer._stringPoolAtom->currentOffset();
708 for (const ld::relocatable::File::Stab& stab : _state.stabs) {
709 macho_nlist<P> entry;
710 entry.set_n_type(stab.type);
711 entry.set_n_sect(sectionIndexForStab(stab));
712 entry.set_n_desc(stab.desc);
713 entry.set_n_value(valueForStab(stab));
714 entry.set_n_strx(stringOffsetForStab(stab, this->_writer._stringPoolAtom));
715 _locals.push_back(entry);
716 ++symbolIndex;
717 }
718 _stabsIndexEnd = symbolIndex;
719 _stabsStringsOffsetEnd = this->_writer._stringPoolAtom->currentOffset();
720 for (const ld::Atom* atom : localAtoms) {
721 if ( this->addLocal(atom, this->_writer._stringPoolAtom) )
722 this->_writer._atomToSymbolIndex[atom] = symbolIndex++;
723 }
724 this->_writer._localSymbolsCount = symbolIndex;
a645023d
A
725}
726
727template <typename A>
728uint64_t SymbolTableAtom<A>::size() const
729{
730 return sizeof(macho_nlist<P>) * (_locals.size() + _globals.size() + _imports.size());
731}
732
733template <typename A>
734void SymbolTableAtom<A>::copyRawContent(uint8_t buffer[]) const
735{
736 memcpy(&buffer[this->_writer._localSymbolsStartIndex*sizeof(macho_nlist<P>)], &_locals[0],
737 this->_writer._localSymbolsCount*sizeof(macho_nlist<P>));
738 memcpy(&buffer[this->_writer._globalSymbolsStartIndex*sizeof(macho_nlist<P>)], &_globals[0],
739 this->_writer._globalSymbolsCount*sizeof(macho_nlist<P>));
740 memcpy(&buffer[this->_writer._importSymbolsStartIndex *sizeof(macho_nlist<P>)], &_imports[0],
741 this->_writer._importSymbolsCount*sizeof(macho_nlist<P>));
742}
743
744
745
746
747class RelocationsAtomAbstract : public ClassicLinkEditAtom
748{
749public:
750 RelocationsAtomAbstract(const Options& opts, ld::Internal& state,
751 OutputFile& writer, const ld::Section& sect,
752 unsigned int pointerSize)
753 : ClassicLinkEditAtom(opts, state, writer, sect, pointerSize) { }
754
755 virtual void addPointerReloc(uint64_t addr, uint32_t symNum) = 0;
756 virtual void addTextReloc(uint64_t addr, ld::Fixup::Kind k, uint64_t targetAddr, uint32_t symNum) = 0;
757 virtual void addExternalPointerReloc(uint64_t addr, const ld::Atom*) = 0;
758 virtual void addExternalCallSiteReloc(uint64_t addr, const ld::Atom*) = 0;
759 virtual uint64_t relocBaseAddress(ld::Internal& state) = 0;
760 virtual void addSectionReloc(ld::Internal::FinalSection* sect, ld::Fixup::Kind,
761 const ld::Atom* inAtom, uint32_t offsetInAtom,
762 bool toTargetUsesExternalReloc ,bool fromTargetExternalReloc,
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,
807 const ld::Atom* toTarget, uint64_t toAddend,
808 const ld::Atom* fromTarget, uint64_t fromAddend) { }
809
810private:
811 typedef typename A::P P;
812 typedef typename A::P::E E;
813 typedef typename A::P::uint_t pint_t;
814
815 std::vector<macho_relocation_info<P> > _relocs;
816
817 static ld::Section _s_section;
818};
819
820template <typename A>
821ld::Section LocalRelocationsAtom<A>::_s_section("__LINKEDIT", "__local_relocs", ld::Section::typeLinkEdit, true);
822
823
824template <>
825uint64_t LocalRelocationsAtom<x86_64>::relocBaseAddress(ld::Internal& state)
826{
827 if ( _options.outputKind() == Options::kKextBundle ) {
828 // for kext bundles the reloc base address starts at __TEXT segment
829 return _options.baseAddress();
830 }
599556ff 831 // for all other kinds, the x86_64 reloc base address starts at first writable segment (usually __DATA)
a645023d
A
832 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
833 ld::Internal::FinalSection* sect = *sit;
599556ff 834 if ( !sect->isSectionHidden() && _options.initialSegProtection(sect->segmentName()) & VM_PROT_WRITE )
a645023d
A
835 return sect->address;
836 }
599556ff 837 throw "writable (__DATA) segment not found";
a645023d
A
838}
839
840template <typename A>
841uint64_t LocalRelocationsAtom<A>::relocBaseAddress(ld::Internal& state)
842{
843 return _options.baseAddress();
844}
845
846template <typename A>
847void LocalRelocationsAtom<A>::addPointerReloc(uint64_t addr, uint32_t symNum)
848{
849 macho_relocation_info<P> reloc;
850 reloc.set_r_address(addr);
851 reloc.set_r_symbolnum(symNum);
852 reloc.set_r_pcrel(false);
853 reloc.set_r_length();
854 reloc.set_r_extern(false);
855 reloc.set_r_type(GENERIC_RELOC_VANILLA);
856 _relocs.push_back(reloc);
857}
858
859template <typename A>
860void LocalRelocationsAtom<A>::addTextReloc(uint64_t addr, ld::Fixup::Kind kind, uint64_t targetAddr, uint32_t symNum)
861{
a645023d
A
862}
863
864
865template <typename A>
866uint64_t LocalRelocationsAtom<A>::size() const
867{
868 return _relocs.size() * sizeof(macho_relocation_info<P>);
869}
870
871template <typename A>
872void LocalRelocationsAtom<A>::copyRawContent(uint8_t buffer[]) const
873{
874 memcpy(buffer, &_relocs[0], _relocs.size()*sizeof(macho_relocation_info<P>));
875}
876
877
878
879
880
881
882template <typename A>
883class ExternalRelocationsAtom : public RelocationsAtomAbstract
884{
885public:
886 ExternalRelocationsAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
887 : RelocationsAtomAbstract(opts, state, writer, _s_section, sizeof(pint_t)) { }
888
889 // overrides of ld::Atom
890 virtual const char* name() const { return "external relocations"; }
891 virtual uint64_t size() const;
892 virtual void copyRawContent(uint8_t buffer[]) const;
893 // overrides of ClassicLinkEditAtom
894 virtual void encode() {}
895 // overrides of RelocationsAtomAbstract
896 virtual void addPointerReloc(uint64_t addr, uint32_t symNum) {}
897 virtual void addTextReloc(uint64_t addr, ld::Fixup::Kind k, uint64_t targetAddr, uint32_t symNum) {}
898 virtual void addExternalPointerReloc(uint64_t addr, const ld::Atom*);
899 virtual void addExternalCallSiteReloc(uint64_t addr, const ld::Atom*);
900 virtual uint64_t relocBaseAddress(ld::Internal& state);
901 virtual void addSectionReloc(ld::Internal::FinalSection* sect, ld::Fixup::Kind,
902 const ld::Atom* inAtom, uint32_t offsetInAtom,
903 bool toTargetUsesExternalReloc ,bool fromTargetExternalReloc,
904 const ld::Atom* toTarget, uint64_t toAddend,
905 const ld::Atom* fromTarget, uint64_t fromAddend) { }
906
907
908private:
909 typedef typename A::P P;
910 typedef typename A::P::E E;
911 typedef typename A::P::uint_t pint_t;
912
913 struct LocAndAtom {
914 LocAndAtom(uint64_t l, const ld::Atom* a) : loc(l), atom(a), symbolIndex(0) {}
915
916 uint64_t loc;
917 const ld::Atom* atom;
918 uint32_t symbolIndex;
919
920 bool operator<(const LocAndAtom& rhs) const {
921 // sort first by symbol number
922 if ( this->symbolIndex != rhs.symbolIndex )
923 return (this->symbolIndex < rhs.symbolIndex);
924 // then sort all uses of the same symbol by address
925 return (this->loc < rhs.loc);
926 }
927
928 };
929
930 static uint32_t pointerReloc();
931 static uint32_t callReloc();
932
933 mutable std::vector<LocAndAtom> _pointerLocations;
934 mutable std::vector<LocAndAtom> _callSiteLocations;
935
936 static ld::Section _s_section;
937};
938
939template <typename A>
940ld::Section ExternalRelocationsAtom<A>::_s_section("__LINKEDIT", "__extrn_relocs", ld::Section::typeLinkEdit, true);
941
942template <>
943uint64_t ExternalRelocationsAtom<x86_64>::relocBaseAddress(ld::Internal& state)
944{
945 // for x86_64 the reloc base address starts at __DATA segment
946 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
947 ld::Internal::FinalSection* sect = *sit;
599556ff 948 if ( !sect->isSectionHidden() && _options.initialSegProtection(sect->segmentName()) & VM_PROT_WRITE )
a645023d
A
949 return sect->address;
950 }
599556ff 951 throw "writable (__DATA) segment not found";
a645023d
A
952}
953
954template <typename A>
955uint64_t ExternalRelocationsAtom<A>::relocBaseAddress(ld::Internal& state)
956{
957 return 0;
958}
959
960template <typename A>
961void ExternalRelocationsAtom<A>::addExternalPointerReloc(uint64_t addr, const ld::Atom* target)
962{
963 _pointerLocations.push_back(LocAndAtom(addr, target));
964}
965
966template <typename A>
967void ExternalRelocationsAtom<A>::addExternalCallSiteReloc(uint64_t addr, const ld::Atom* target)
968{
969 _callSiteLocations.push_back(LocAndAtom(addr, target));
970}
971
972
973template <typename A>
974uint64_t ExternalRelocationsAtom<A>::size() const
975{
976 if ( _options.outputKind() == Options::kStaticExecutable ) {
977 assert(_pointerLocations.size() == 0);
978 assert(_callSiteLocations.size() == 0);
979 }
980 return (_pointerLocations.size() + _callSiteLocations.size()) * sizeof(macho_relocation_info<P>);
981}
982
f80fe69f
A
983#if SUPPORT_ARCH_arm64
984template <> uint32_t ExternalRelocationsAtom<arm64>::pointerReloc() { return ARM64_RELOC_UNSIGNED; }
985#endif
ebf6f434 986#if SUPPORT_ARCH_arm_any
a645023d 987template <> uint32_t ExternalRelocationsAtom<arm>::pointerReloc() { return ARM_RELOC_VANILLA; }
ebf6f434 988#endif
a645023d 989template <> uint32_t ExternalRelocationsAtom<x86>::pointerReloc() { return GENERIC_RELOC_VANILLA; }
a645023d 990template <> uint32_t ExternalRelocationsAtom<x86_64>::pointerReloc() { return X86_64_RELOC_UNSIGNED; }
a645023d
A
991
992
993template <> uint32_t ExternalRelocationsAtom<x86_64>::callReloc() { return X86_64_RELOC_BRANCH; }
994template <> uint32_t ExternalRelocationsAtom<x86>::callReloc() { return GENERIC_RELOC_VANILLA; }
f80fe69f
A
995#if SUPPORT_ARCH_arm64
996template <> uint32_t ExternalRelocationsAtom<arm64>::callReloc() { return ARM64_RELOC_BRANCH26; }
997#endif
998
a645023d
A
999template <typename A>
1000uint32_t ExternalRelocationsAtom<A>::callReloc()
1001{
1002 assert(0 && "external call relocs not implemented");
1003 return 0;
1004}
1005
1006
1007template <typename A>
1008void ExternalRelocationsAtom<A>::copyRawContent(uint8_t buffer[]) const
1009{
1010 macho_relocation_info<P>* r = (macho_relocation_info<P>*)buffer;
1011
1012 // assign symbol index, now that symbol table is built
1013 for (typename std::vector<LocAndAtom>::iterator it = _pointerLocations.begin(); it != _pointerLocations.end(); ++it) {
1014 it->symbolIndex = symbolIndex(it->atom);
1015 }
1016 std::sort(_pointerLocations.begin(), _pointerLocations.end());
1017 for (typename std::vector<LocAndAtom>::const_iterator it = _pointerLocations.begin(); it != _pointerLocations.end(); ++it, ++r) {
1018 r->set_r_address(it->loc);
1019 r->set_r_symbolnum(it->symbolIndex);
1020 r->set_r_pcrel(false);
1021 r->set_r_length();
1022 r->set_r_extern(true);
1023 r->set_r_type(this->pointerReloc());
1024 }
1025
1026 for (typename std::vector<LocAndAtom>::iterator it = _callSiteLocations.begin(); it != _callSiteLocations.end(); ++it) {
1027 it->symbolIndex = symbolIndex(it->atom);
1028 }
1029 std::sort(_callSiteLocations.begin(), _callSiteLocations.end());
1030 for (typename std::vector<LocAndAtom>::const_iterator it = _callSiteLocations.begin(); it != _callSiteLocations.end(); ++it, ++r) {
1031 r->set_r_address(it->loc);
1032 r->set_r_symbolnum(it->symbolIndex);
1033 r->set_r_pcrel(true);
1034 r->set_r_length(2);
1035 r->set_r_extern(true);
1036 r->set_r_type(this->callReloc());
1037 }
1038}
1039
1040
1041template <typename A>
1042class SectionRelocationsAtom : public RelocationsAtomAbstract
1043{
1044public:
1045 SectionRelocationsAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
1046 : RelocationsAtomAbstract(opts, state, writer, _s_section, sizeof(pint_t)) { }
1047
1048 // overrides of ld::Atom
1049 virtual const char* name() const { return "section relocations"; }
1050 virtual uint64_t size() const;
1051 virtual void copyRawContent(uint8_t buffer[]) const;
1052 // overrides of ClassicLinkEditAtom
1053 virtual void encode();
1054 // overrides of RelocationsAtomAbstract
1055 virtual void addPointerReloc(uint64_t addr, uint32_t symNum) {}
1056 virtual void addTextReloc(uint64_t addr, ld::Fixup::Kind k, uint64_t targetAddr, uint32_t symNum) {}
1057 virtual void addExternalPointerReloc(uint64_t addr, const ld::Atom*) {}
1058 virtual void addExternalCallSiteReloc(uint64_t addr, const ld::Atom*) {}
1059 virtual uint64_t relocBaseAddress(ld::Internal& state) { return 0; }
1060 virtual void addSectionReloc(ld::Internal::FinalSection* sect, ld::Fixup::Kind,
1061 const ld::Atom* inAtom, uint32_t offsetInAtom,
1062 bool toTargetUsesExternalReloc ,bool fromTargetExternalReloc,
1063 const ld::Atom* toTarget, uint64_t toAddend,
1064 const ld::Atom* fromTarget, uint64_t fromAddend);
1065
1066private:
1067 typedef typename A::P P;
1068 typedef typename A::P::E E;
1069 typedef typename A::P::uint_t pint_t;
1070
1071
1072 struct Entry {
1073 ld::Fixup::Kind kind;
1074 bool toTargetUsesExternalReloc;
1075 bool fromTargetUsesExternalReloc;
1076 const ld::Atom* inAtom;
1077 uint32_t offsetInAtom;
1078 const ld::Atom* toTarget;
1079 uint64_t toAddend;
1080 const ld::Atom* fromTarget;
1081 uint64_t fromAddend;
1082 };
1083 uint32_t sectSymNum(bool external, const ld::Atom* target);
1084 void encodeSectionReloc(ld::Internal::FinalSection* sect,
1085 const Entry& entry, std::vector<macho_relocation_info<P> >& relocs);
1086
1087 struct SectionAndEntries {
1088 ld::Internal::FinalSection* sect;
1089 std::vector<Entry> entries;
1090 std::vector<macho_relocation_info<P> > relocs;
1091 };
1092
1093 std::vector<SectionAndEntries> _entriesBySection;
1094
1095 static ld::Section _s_section;
1096};
1097
1098template <typename A>
1099ld::Section SectionRelocationsAtom<A>::_s_section("__LINKEDIT", "__sect_relocs", ld::Section::typeLinkEdit, true);
1100
1101
1102
1103
1104template <typename A>
1105uint64_t SectionRelocationsAtom<A>::size() const
1106{
1107 uint32_t count = 0;
1108 for(typename std::vector<SectionAndEntries>::const_iterator it=_entriesBySection.begin(); it != _entriesBySection.end(); ++it) {
1109 const SectionAndEntries& se = *it;
1110 count += se.relocs.size();
1111 }
1112 return count * sizeof(macho_relocation_info<P>);
1113}
1114
1115template <typename A>
1116void SectionRelocationsAtom<A>::copyRawContent(uint8_t buffer[]) const
1117{
1118 uint32_t offset = 0;
1119 for(typename std::vector<SectionAndEntries>::const_iterator it=_entriesBySection.begin(); it != _entriesBySection.end(); ++it) {
1120 const SectionAndEntries& se = *it;
1121 memcpy(&buffer[offset], &se.relocs[0], se.relocs.size()*sizeof(macho_relocation_info<P>));
1122 offset += (se.relocs.size() * sizeof(macho_relocation_info<P>));
1123 }
1124}
1125
1126
1127template <>
1128void SectionRelocationsAtom<x86_64>::encodeSectionReloc(ld::Internal::FinalSection* sect,
1129 const Entry& entry, std::vector<macho_relocation_info<P> >& relocs)
1130{
1131 macho_relocation_info<P> reloc1;
1132 macho_relocation_info<P> reloc2;
1133 uint64_t address = entry.inAtom->finalAddress()+entry.offsetInAtom - sect->address;
1134 bool external = entry.toTargetUsesExternalReloc;
1135 uint32_t symbolNum = sectSymNum(external, entry.toTarget);
1136 bool fromExternal = false;
1137 uint32_t fromSymbolNum = 0;
1138 if ( entry.fromTarget != NULL ) {
1139 fromExternal = entry.fromTargetUsesExternalReloc;
1140 fromSymbolNum = sectSymNum(fromExternal, entry.fromTarget);
1141 }
1142
1143
1144 switch ( entry.kind ) {
1145 case ld::Fixup::kindStoreX86BranchPCRel32:
1146 case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32:
1147 case ld::Fixup::kindStoreX86DtraceCallSiteNop:
1148 case ld::Fixup::kindStoreX86DtraceIsEnableSiteClear:
1149 reloc1.set_r_address(address);
1150 reloc1.set_r_symbolnum(symbolNum);
1151 reloc1.set_r_pcrel(true);
1152 reloc1.set_r_length(2);
1153 reloc1.set_r_extern(external);
1154 reloc1.set_r_type(X86_64_RELOC_BRANCH);
1155 relocs.push_back(reloc1);
1156 break;
1157
1158 case ld::Fixup::kindStoreX86BranchPCRel8:
1159 reloc1.set_r_address(address);
1160 reloc1.set_r_symbolnum(symbolNum);
1161 reloc1.set_r_pcrel(true);
1162 reloc1.set_r_length(0);
1163 reloc1.set_r_extern(external);
1164 reloc1.set_r_type(X86_64_RELOC_BRANCH);
1165 relocs.push_back(reloc1);
1166 break;
1167
1168 case ld::Fixup::kindStoreX86PCRel32:
1169 case ld::Fixup::kindStoreTargetAddressX86PCRel32:
1170 reloc1.set_r_address(address);
1171 reloc1.set_r_symbolnum(symbolNum);
1172 reloc1.set_r_pcrel(true);
1173 reloc1.set_r_length(2);
1174 reloc1.set_r_extern(external);
1175 reloc1.set_r_type(X86_64_RELOC_SIGNED);
1176 relocs.push_back(reloc1);
1177 break;
1178
1179 case ld::Fixup::kindStoreX86PCRel32_1:
1180 reloc1.set_r_address(address);
1181 reloc1.set_r_symbolnum(symbolNum);
1182 reloc1.set_r_pcrel(true);
1183 reloc1.set_r_length(2);
1184 reloc1.set_r_extern(external);
1185 reloc1.set_r_type(X86_64_RELOC_SIGNED_1);
1186 relocs.push_back(reloc1);
1187 break;
1188
1189 case ld::Fixup::kindStoreX86PCRel32_2:
1190 reloc1.set_r_address(address);
1191 reloc1.set_r_symbolnum(symbolNum);
1192 reloc1.set_r_pcrel(true);
1193 reloc1.set_r_length(2);
1194 reloc1.set_r_extern(external);
1195 reloc1.set_r_type(X86_64_RELOC_SIGNED_2);
1196 relocs.push_back(reloc1);
1197 break;
1198
1199 case ld::Fixup::kindStoreX86PCRel32_4:
1200 reloc1.set_r_address(address);
1201 reloc1.set_r_symbolnum(symbolNum);
1202 reloc1.set_r_pcrel(true);
1203 reloc1.set_r_length(2);
1204 reloc1.set_r_extern(external);
1205 reloc1.set_r_type(X86_64_RELOC_SIGNED_4);
1206 relocs.push_back(reloc1);
1207 break;
1208
1209 case ld::Fixup::kindStoreX86PCRel32GOTLoad:
1210 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad:
1211 reloc1.set_r_address(address);
1212 reloc1.set_r_symbolnum(symbolNum);
1213 reloc1.set_r_pcrel(true);
1214 reloc1.set_r_length(2);
1215 reloc1.set_r_extern(external);
1216 reloc1.set_r_type(X86_64_RELOC_GOT_LOAD);
1217 relocs.push_back(reloc1);
1218 break;
1219
1220 case ld::Fixup::kindStoreX86PCRel32GOT:
1221 reloc1.set_r_address(address);
1222 reloc1.set_r_symbolnum(symbolNum);
1223 reloc1.set_r_pcrel(true);
1224 reloc1.set_r_length(2);
1225 reloc1.set_r_extern(external);
1226 reloc1.set_r_type(X86_64_RELOC_GOT);
1227 relocs.push_back(reloc1);
1228 break;
1229
1230 case ld::Fixup::kindStoreLittleEndian64:
1231 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
1232 if ( entry.fromTarget != NULL ) {
1233 // this is a pointer-diff
1234 reloc1.set_r_address(address);
1235 reloc1.set_r_symbolnum(symbolNum);
1236 reloc1.set_r_pcrel(false);
1237 reloc1.set_r_length(3);
1238 reloc1.set_r_extern(external);
1239 reloc1.set_r_type(X86_64_RELOC_UNSIGNED);
1240 reloc2.set_r_address(address);
1241 reloc2.set_r_symbolnum(fromSymbolNum);
1242 reloc2.set_r_pcrel(false);
1243 reloc2.set_r_length(3);
1244 reloc2.set_r_extern(fromExternal);
1245 reloc2.set_r_type(X86_64_RELOC_SUBTRACTOR);
1246 relocs.push_back(reloc2);
1247 relocs.push_back(reloc1);
1248 }
1249 else {
1250 // regular pointer
1251 reloc1.set_r_address(address);
1252 reloc1.set_r_symbolnum(symbolNum);
1253 reloc1.set_r_pcrel(false);
1254 reloc1.set_r_length(3);
1255 reloc1.set_r_extern(external);
1256 reloc1.set_r_type(X86_64_RELOC_UNSIGNED);
1257 relocs.push_back(reloc1);
1258 }
1259 break;
1260
1261 case ld::Fixup::kindStoreLittleEndian32:
1262 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
1263 if ( entry.fromTarget != NULL ) {
1264 // this is a pointer-diff
1265 reloc1.set_r_address(address);
1266 reloc1.set_r_symbolnum(symbolNum);
1267 reloc1.set_r_pcrel(false);
1268 reloc1.set_r_length(2);
1269 reloc1.set_r_extern(external);
1270 reloc1.set_r_type(X86_64_RELOC_UNSIGNED);
1271 reloc2.set_r_address(address);
1272 reloc2.set_r_symbolnum(fromSymbolNum);
1273 reloc2.set_r_pcrel(false);
1274 reloc2.set_r_length(2);
1275 reloc2.set_r_extern(fromExternal);
1276 reloc2.set_r_type(X86_64_RELOC_SUBTRACTOR);
1277 relocs.push_back(reloc2);
1278 relocs.push_back(reloc1);
1279 }
1280 else {
1281 // regular pointer
1282 reloc1.set_r_address(address);
1283 reloc1.set_r_symbolnum(symbolNum);
1284 reloc1.set_r_pcrel(false);
1285 reloc1.set_r_length(2);
1286 reloc1.set_r_extern(external);
1287 reloc1.set_r_type(X86_64_RELOC_UNSIGNED);
1288 relocs.push_back(reloc1);
1289 }
1290 break;
b1f7435d
A
1291 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad:
1292 reloc1.set_r_address(address);
1293 reloc1.set_r_symbolnum(symbolNum);
1294 reloc1.set_r_pcrel(true);
1295 reloc1.set_r_length(2);
1296 reloc1.set_r_extern(external);
1297 reloc1.set_r_type(X86_64_RELOC_TLV);
1298 relocs.push_back(reloc1);
1299 break;
a645023d
A
1300 default:
1301 assert(0 && "need to handle -r reloc");
1302
1303 }
1304
1305}
1306
1307
1308
1309template <typename A>
1310uint32_t SectionRelocationsAtom<A>::sectSymNum(bool external, const ld::Atom* target)
1311{
1312 if ( target->definition() == ld::Atom::definitionAbsolute )
1313 return R_ABS;
1314 if ( external )
1315 return this->symbolIndex(target); // in external relocations, r_symbolnum field is symbol index
1316 else
1317 return target->machoSection(); // in non-extern relocations, r_symbolnum is mach-o section index of target
1318}
1319
1320template <>
b1f7435d 1321void SectionRelocationsAtom<x86>::encodeSectionReloc(ld::Internal::FinalSection* sect,
a645023d
A
1322 const Entry& entry, std::vector<macho_relocation_info<P> >& relocs)
1323{
1324 macho_relocation_info<P> reloc1;
1325 macho_relocation_info<P> reloc2;
1326 macho_scattered_relocation_info<P>* sreloc1 = (macho_scattered_relocation_info<P>*)&reloc1;
1327 macho_scattered_relocation_info<P>* sreloc2 = (macho_scattered_relocation_info<P>*)&reloc2;
1328 uint64_t address = entry.inAtom->finalAddress()+entry.offsetInAtom - sect->address;
1329 bool external = entry.toTargetUsesExternalReloc;
1330 uint32_t symbolNum = sectSymNum(external, entry.toTarget);
1331 bool fromExternal = false;
1332 uint32_t fromSymbolNum = 0;
1333 if ( entry.fromTarget != NULL ) {
1334 fromExternal = entry.fromTargetUsesExternalReloc;
1335 fromSymbolNum = sectSymNum(fromExternal, entry.fromTarget);
1336 }
b1f7435d 1337
a645023d
A
1338 switch ( entry.kind ) {
1339 case ld::Fixup::kindStoreX86PCRel32:
1340 case ld::Fixup::kindStoreX86BranchPCRel32:
1341 case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32:
1342 case ld::Fixup::kindStoreX86DtraceCallSiteNop:
1343 case ld::Fixup::kindStoreX86DtraceIsEnableSiteClear:
1344 if ( !external && (entry.toAddend != 0) ) {
1345 // use scattered reloc is target offset is non-zero
1346 sreloc1->set_r_scattered(true);
1347 sreloc1->set_r_pcrel(true);
1348 sreloc1->set_r_length(2);
1349 sreloc1->set_r_type(GENERIC_RELOC_VANILLA);
1350 sreloc1->set_r_address(address);
1351 sreloc1->set_r_value(entry.toTarget->finalAddress());
1352 }
1353 else {
1354 reloc1.set_r_address(address);
1355 reloc1.set_r_symbolnum(symbolNum);
1356 reloc1.set_r_pcrel(true);
1357 reloc1.set_r_length(2);
1358 reloc1.set_r_extern(external);
1359 reloc1.set_r_type(GENERIC_RELOC_VANILLA);
1360 }
1361 relocs.push_back(reloc1);
1362 break;
1363
1364 case ld::Fixup::kindStoreX86BranchPCRel8:
1365 if ( !external && (entry.toAddend != 0) ) {
1366 // use scattered reloc is target offset is non-zero
1367 sreloc1->set_r_scattered(true);
1368 sreloc1->set_r_pcrel(true);
1369 sreloc1->set_r_length(0);
1370 sreloc1->set_r_type(GENERIC_RELOC_VANILLA);
1371 sreloc1->set_r_address(address);
1372 sreloc1->set_r_value(entry.toTarget->finalAddress());
1373 }
1374 else {
1375 reloc1.set_r_address(address);
1376 reloc1.set_r_symbolnum(symbolNum);
1377 reloc1.set_r_pcrel(true);
1378 reloc1.set_r_length(0);
1379 reloc1.set_r_extern(external);
1380 reloc1.set_r_type(GENERIC_RELOC_VANILLA);
1381 }
1382 relocs.push_back(reloc1);
1383 break;
1384
1385 case ld::Fixup::kindStoreX86PCRel16:
1386 if ( !external && (entry.toAddend != 0) ) {
1387 // use scattered reloc is target offset is non-zero
1388 sreloc1->set_r_scattered(true);
1389 sreloc1->set_r_pcrel(true);
1390 sreloc1->set_r_length(1);
1391 sreloc1->set_r_type(GENERIC_RELOC_VANILLA);
1392 sreloc1->set_r_address(address);
1393 sreloc1->set_r_value(entry.toTarget->finalAddress());
1394 }
1395 else {
1396 reloc1.set_r_address(address);
1397 reloc1.set_r_symbolnum(symbolNum);
1398 reloc1.set_r_pcrel(true);
1399 reloc1.set_r_length(1);
1400 reloc1.set_r_extern(external);
1401 reloc1.set_r_type(GENERIC_RELOC_VANILLA);
1402 }
1403 relocs.push_back(reloc1);
1404 break;
1405
1406 case ld::Fixup::kindStoreLittleEndian32:
1407 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
1408 if ( entry.fromTarget != NULL ) {
1409 // this is a pointer-diff
1410 sreloc1->set_r_scattered(true);
1411 sreloc1->set_r_pcrel(false);
1412 sreloc1->set_r_length(2);
1413 if ( entry.toTarget->scope() == ld::Atom::scopeTranslationUnit )
1414 sreloc1->set_r_type(GENERIC_RELOC_LOCAL_SECTDIFF);
1415 else
1416 sreloc1->set_r_type(GENERIC_RELOC_SECTDIFF);
1417 sreloc1->set_r_address(address);
afe874b1
A
1418 if ( entry.toTarget == entry.inAtom ) {
1419 if ( entry.toAddend > entry.toTarget->size() )
1420 sreloc1->set_r_value(entry.toTarget->finalAddress()+entry.offsetInAtom);
1421 else
1422 sreloc1->set_r_value(entry.toTarget->finalAddress()+entry.toAddend);
1423 }
a645023d
A
1424 else
1425 sreloc1->set_r_value(entry.toTarget->finalAddress());
1426 sreloc2->set_r_scattered(true);
1427 sreloc2->set_r_pcrel(false);
1428 sreloc2->set_r_length(2);
1429 sreloc2->set_r_type(GENERIC_RELOC_PAIR);
1430 sreloc2->set_r_address(0);
1431 if ( entry.fromTarget == entry.inAtom ) {
1432 if ( entry.fromAddend > entry.fromTarget->size() )
1433 sreloc2->set_r_value(entry.fromTarget->finalAddress()+entry.offsetInAtom);
1434 else
1435 sreloc2->set_r_value(entry.fromTarget->finalAddress()+entry.fromAddend);
1436 }
1437 else
1438 sreloc2->set_r_value(entry.fromTarget->finalAddress());
1439 relocs.push_back(reloc1);
1440 relocs.push_back(reloc2);
1441 }
1442 else {
1443 // regular pointer
ebf6f434
A
1444 if ( !external && (entry.toAddend != 0) && (entry.toTarget->symbolTableInclusion() != ld::Atom::symbolTableNotIn) ) {
1445 // use scattered reloc if target offset is non-zero into named atom (5658046)
a645023d
A
1446 sreloc1->set_r_scattered(true);
1447 sreloc1->set_r_pcrel(false);
1448 sreloc1->set_r_length(2);
1449 sreloc1->set_r_type(GENERIC_RELOC_VANILLA);
1450 sreloc1->set_r_address(address);
1451 sreloc1->set_r_value(entry.toTarget->finalAddress());
1452 }
1453 else {
1454 reloc1.set_r_address(address);
1455 reloc1.set_r_symbolnum(symbolNum);
1456 reloc1.set_r_pcrel(false);
1457 reloc1.set_r_length(2);
1458 reloc1.set_r_extern(external);
1459 reloc1.set_r_type(GENERIC_RELOC_VANILLA);
1460 }
1461 relocs.push_back(reloc1);
1462 }
1463 break;
b1f7435d
A
1464 case ld::Fixup::kindStoreX86PCRel32TLVLoad:
1465 case ld::Fixup::kindStoreX86Abs32TLVLoad:
1466 case ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoad:
1467 reloc1.set_r_address(address);
1468 reloc1.set_r_symbolnum(symbolNum);
1469 reloc1.set_r_pcrel(entry.kind == ld::Fixup::kindStoreX86PCRel32TLVLoad);
1470 reloc1.set_r_length(2);
1471 reloc1.set_r_extern(external);
1472 reloc1.set_r_type(GENERIC_RLEOC_TLV);
1473 relocs.push_back(reloc1);
1474 break;
a645023d
A
1475 default:
1476 assert(0 && "need to handle -r reloc");
1477
1478 }
1479}
1480
1481
b1f7435d 1482
ebf6f434 1483#if SUPPORT_ARCH_arm_any
a645023d
A
1484template <>
1485void SectionRelocationsAtom<arm>::encodeSectionReloc(ld::Internal::FinalSection* sect,
1486 const Entry& entry, std::vector<macho_relocation_info<P> >& relocs)
1487{
1488 macho_relocation_info<P> reloc1;
1489 macho_relocation_info<P> reloc2;
1490 macho_scattered_relocation_info<P>* sreloc1 = (macho_scattered_relocation_info<P>*)&reloc1;
1491 macho_scattered_relocation_info<P>* sreloc2 = (macho_scattered_relocation_info<P>*)&reloc2;
1492 uint64_t address = entry.inAtom->finalAddress()+entry.offsetInAtom - sect->address;
1493 bool external = entry.toTargetUsesExternalReloc;
1494 uint32_t symbolNum = sectSymNum(external, entry.toTarget);
1495 bool fromExternal = false;
1496 uint32_t fromSymbolNum = 0;
1497 if ( entry.fromTarget != NULL ) {
1498 fromExternal = entry.fromTargetUsesExternalReloc;
1499 fromSymbolNum = sectSymNum(fromExternal, entry.fromTarget);
1500 }
1501
1502
1503 switch ( entry.kind ) {
1504 case ld::Fixup::kindStoreTargetAddressARMBranch24:
1505 case ld::Fixup::kindStoreARMBranch24:
1506 case ld::Fixup::kindStoreARMDtraceCallSiteNop:
1507 case ld::Fixup::kindStoreARMDtraceIsEnableSiteClear:
1508 if ( !external && (entry.toAddend != 0) ) {
1509 // use scattered reloc is target offset is non-zero
1510 sreloc1->set_r_scattered(true);
1511 sreloc1->set_r_pcrel(true);
1512 sreloc1->set_r_length(2);
1513 sreloc1->set_r_type(ARM_RELOC_BR24);
1514 sreloc1->set_r_address(address);
1515 sreloc1->set_r_value(entry.toTarget->finalAddress());
1516 }
1517 else {
1518 reloc1.set_r_address(address);
1519 reloc1.set_r_symbolnum(symbolNum);
1520 reloc1.set_r_pcrel(true);
1521 reloc1.set_r_length(2);
1522 reloc1.set_r_extern(external);
1523 reloc1.set_r_type(ARM_RELOC_BR24);
1524 }
1525 relocs.push_back(reloc1);
1526 break;
1527
1528 case ld::Fixup::kindStoreTargetAddressThumbBranch22:
1529 case ld::Fixup::kindStoreThumbBranch22:
1530 case ld::Fixup::kindStoreThumbDtraceCallSiteNop:
1531 case ld::Fixup::kindStoreThumbDtraceIsEnableSiteClear:
1532 if ( !external && (entry.toAddend != 0) ) {
1533 // use scattered reloc is target offset is non-zero
1534 sreloc1->set_r_scattered(true);
1535 sreloc1->set_r_pcrel(true);
1536 sreloc1->set_r_length(2);
1537 sreloc1->set_r_type(ARM_THUMB_RELOC_BR22);
1538 sreloc1->set_r_address(address);
1539 sreloc1->set_r_value(entry.toTarget->finalAddress());
1540 }
1541 else {
1542 reloc1.set_r_address(address);
1543 reloc1.set_r_symbolnum(symbolNum);
1544 reloc1.set_r_pcrel(true);
1545 reloc1.set_r_length(2);
1546 reloc1.set_r_extern(external);
1547 reloc1.set_r_type(ARM_THUMB_RELOC_BR22);
1548 }
1549 relocs.push_back(reloc1);
1550 break;
1551
1552 case ld::Fixup::kindStoreLittleEndian32:
1553 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
1554 if ( entry.fromTarget != NULL ) {
1555 // this is a pointer-diff
1556 sreloc1->set_r_scattered(true);
1557 sreloc1->set_r_pcrel(false);
1558 sreloc1->set_r_length(2);
1559 if ( entry.toTarget->scope() == ld::Atom::scopeTranslationUnit )
1560 sreloc1->set_r_type(ARM_RELOC_LOCAL_SECTDIFF);
1561 else
1562 sreloc1->set_r_type(ARM_RELOC_SECTDIFF);
1563 sreloc1->set_r_address(address);
afe874b1
A
1564 if ( entry.toTarget == entry.inAtom ) {
1565 if ( entry.toAddend > entry.toTarget->size() )
1566 sreloc1->set_r_value(entry.toTarget->finalAddress()+entry.offsetInAtom);
1567 else
1568 sreloc1->set_r_value(entry.toTarget->finalAddress()+entry.toAddend);
1569 }
1570 else {
a645023d 1571 sreloc1->set_r_value(entry.toTarget->finalAddress());
afe874b1 1572 }
a645023d
A
1573 sreloc2->set_r_scattered(true);
1574 sreloc2->set_r_pcrel(false);
1575 sreloc2->set_r_length(2);
1576 sreloc2->set_r_type(ARM_RELOC_PAIR);
1577 sreloc2->set_r_address(0);
1578 if ( entry.fromTarget == entry.inAtom ) {
1579 //unsigned int pcBaseOffset = entry.inAtom->isThumb() ? 4 : 8;
1580 //if ( entry.fromAddend > pcBaseOffset )
1581 // sreloc2->set_r_value(entry.fromTarget->finalAddress()+entry.fromAddend-pcBaseOffset);
1582 //else
1583 sreloc2->set_r_value(entry.fromTarget->finalAddress()+entry.fromAddend);
1584 }
1585 else {
1586 sreloc2->set_r_value(entry.fromTarget->finalAddress());
1587 }
1588 relocs.push_back(reloc1);
1589 relocs.push_back(reloc2);
1590 }
1591 else {
1592 // regular pointer
1593 if ( !external && (entry.toAddend != 0) ) {
1594 // use scattered reloc is target offset is non-zero
1595 sreloc1->set_r_scattered(true);
1596 sreloc1->set_r_pcrel(false);
1597 sreloc1->set_r_length(2);
1598 sreloc1->set_r_type(ARM_RELOC_VANILLA);
1599 sreloc1->set_r_address(address);
1600 sreloc1->set_r_value(entry.toTarget->finalAddress());
1601 }
1602 else {
1603 reloc1.set_r_address(address);
1604 reloc1.set_r_symbolnum(symbolNum);
1605 reloc1.set_r_pcrel(false);
1606 reloc1.set_r_length(2);
1607 reloc1.set_r_extern(external);
1608 reloc1.set_r_type(ARM_RELOC_VANILLA);
1609 }
1610 relocs.push_back(reloc1);
1611 }
1612 break;
1613
1614 case ld::Fixup::kindStoreARMLow16:
1615 case ld::Fixup::kindStoreARMHigh16:
1616 case ld::Fixup::kindStoreThumbLow16:
1617 case ld::Fixup::kindStoreThumbHigh16:
1618 {
1619 int len = 0;
1620 uint32_t otherHalf = 0;
eaf282aa
A
1621 uint32_t value;
1622 if ( entry.fromTarget != NULL ) {
1623 // this is a sect-diff
1624 value = (entry.toTarget->finalAddress()+entry.toAddend) - (entry.fromTarget->finalAddress()+entry.fromAddend);
1625 }
1626 else {
1627 // this is an absolute address
1628 value = entry.toAddend;
1629 if ( !external )
1630 value += entry.toTarget->finalAddress();
1631 }
a645023d
A
1632 switch ( entry.kind ) {
1633 case ld::Fixup::kindStoreARMLow16:
1634 len = 0;
1635 otherHalf = value >> 16;
1636 break;
1637 case ld::Fixup::kindStoreARMHigh16:
1638 len = 1;
1639 otherHalf = value & 0xFFFF;
1640 break;
1641 case ld::Fixup::kindStoreThumbLow16:
1642 len = 2;
1643 otherHalf = value >> 16;
1644 break;
1645 case ld::Fixup::kindStoreThumbHigh16:
1646 len = 3;
1647 otherHalf = value & 0xFFFF;
1648 break;
1649 default:
1650 break;
1651 }
1652 if ( entry.fromTarget != NULL ) {
1653 // this is a sect-diff
1654 sreloc1->set_r_scattered(true);
1655 sreloc1->set_r_pcrel(false);
1656 sreloc1->set_r_length(len);
1657 sreloc1->set_r_type(ARM_RELOC_HALF_SECTDIFF);
1658 sreloc1->set_r_address(address);
1659 sreloc1->set_r_value(entry.toTarget->finalAddress());
1660 sreloc2->set_r_scattered(true);
1661 sreloc2->set_r_pcrel(false);
1662 sreloc2->set_r_length(len);
1663 sreloc2->set_r_type(ARM_RELOC_PAIR);
1664 sreloc2->set_r_address(otherHalf);
1665 if ( entry.fromTarget == entry.inAtom )
1666 sreloc2->set_r_value(entry.fromTarget->finalAddress()+entry.fromAddend);
1667 else
1668 sreloc2->set_r_value(entry.fromTarget->finalAddress());
1669 relocs.push_back(reloc1);
1670 relocs.push_back(reloc2);
1671 }
1672 else {
1673 // this is absolute address
1674 if ( !external && (entry.toAddend != 0) ) {
1675 // use scattered reloc is target offset is non-zero
1676 sreloc1->set_r_scattered(true);
1677 sreloc1->set_r_pcrel(false);
1678 sreloc1->set_r_length(len);
1679 sreloc1->set_r_type(ARM_RELOC_HALF);
1680 sreloc1->set_r_address(address);
1681 sreloc1->set_r_value(entry.toTarget->finalAddress());
1682 reloc2.set_r_address(otherHalf);
1683 reloc2.set_r_symbolnum(0);
1684 reloc2.set_r_pcrel(false);
1685 reloc2.set_r_length(len);
1686 reloc2.set_r_extern(false);
1687 reloc2.set_r_type(ARM_RELOC_PAIR);
1688 relocs.push_back(reloc1);
1689 relocs.push_back(reloc2);
1690 }
1691 else {
1692 reloc1.set_r_address(address);
1693 reloc1.set_r_symbolnum(symbolNum);
1694 reloc1.set_r_pcrel(false);
1695 reloc1.set_r_length(len);
afe874b1 1696 reloc1.set_r_extern(external);
a645023d
A
1697 reloc1.set_r_type(ARM_RELOC_HALF);
1698 reloc2.set_r_address(otherHalf); // other half
1699 reloc2.set_r_symbolnum(0);
1700 reloc2.set_r_pcrel(false);
1701 reloc2.set_r_length(len);
1702 reloc2.set_r_extern(false);
1703 reloc2.set_r_type(ARM_RELOC_PAIR);
1704 relocs.push_back(reloc1);
1705 relocs.push_back(reloc2);
1706 }
1707 }
1708 }
1709 break;
1710
1711 default:
1712 assert(0 && "need to handle -r reloc");
1713
1714 }
1715}
ebf6f434 1716#endif
a645023d 1717
f80fe69f
A
1718#if SUPPORT_ARCH_arm64
1719template <>
1720void SectionRelocationsAtom<arm64>::encodeSectionReloc(ld::Internal::FinalSection* sect,
1721 const Entry& entry, std::vector<macho_relocation_info<P> >& relocs)
1722{
1723 macho_relocation_info<P> reloc1;
1724 macho_relocation_info<P> reloc2;
1725 uint64_t address = entry.inAtom->finalAddress()+entry.offsetInAtom - sect->address;
1726 bool external = entry.toTargetUsesExternalReloc;
1727 uint32_t symbolNum = sectSymNum(external, entry.toTarget);
1728 bool fromExternal = false;
1729 uint32_t fromSymbolNum = 0;
1730 if ( entry.fromTarget != NULL ) {
1731 fromExternal = entry.fromTargetUsesExternalReloc;
1732 fromSymbolNum = sectSymNum(fromExternal, entry.fromTarget);
1733 }
1734
1735
1736 switch ( entry.kind ) {
1737 case ld::Fixup::kindStoreARM64Branch26:
1738 if ( entry.toAddend != 0 ) {
1739 assert(entry.toAddend < 0x400000);
1740 reloc2.set_r_address(address);
1741 reloc2.set_r_symbolnum(entry.toAddend);
1742 reloc2.set_r_pcrel(false);
1743 reloc2.set_r_length(2);
1744 reloc2.set_r_extern(false);
1745 reloc2.set_r_type(ARM64_RELOC_ADDEND);
1746 relocs.push_back(reloc2);
1747 }
1748 // fall into next case
1749 case ld::Fixup::kindStoreTargetAddressARM64Branch26:
1750 case ld::Fixup::kindStoreARM64DtraceCallSiteNop:
1751 case ld::Fixup::kindStoreARM64DtraceIsEnableSiteClear:
1752 reloc1.set_r_address(address);
1753 reloc1.set_r_symbolnum(symbolNum);
1754 reloc1.set_r_pcrel(true);
1755 reloc1.set_r_length(2);
1756 reloc1.set_r_extern(external);
1757 reloc1.set_r_type(ARM64_RELOC_BRANCH26);
1758 relocs.push_back(reloc1);
1759 break;
1760
1761 case ld::Fixup::kindStoreARM64Page21:
1762 if ( entry.toAddend != 0 ) {
1763 assert(entry.toAddend < 0x400000);
1764 reloc2.set_r_address(address);
1765 reloc2.set_r_symbolnum(entry.toAddend);
1766 reloc2.set_r_pcrel(false);
1767 reloc2.set_r_length(2);
1768 reloc2.set_r_extern(false);
1769 reloc2.set_r_type(ARM64_RELOC_ADDEND);
1770 relocs.push_back(reloc2);
1771 }
1772 // fall into next case
1773 case ld::Fixup::kindStoreTargetAddressARM64Page21:
1774 reloc1.set_r_address(address);
1775 reloc1.set_r_symbolnum(symbolNum);
1776 reloc1.set_r_pcrel(true);
1777 reloc1.set_r_length(2);
1778 reloc1.set_r_extern(external);
1779 reloc1.set_r_type(ARM64_RELOC_PAGE21);
1780 relocs.push_back(reloc1);
1781 break;
1782
1783 case ld::Fixup::kindStoreARM64PageOff12:
1784 if ( entry.toAddend != 0 ) {
1785 assert(entry.toAddend < 0x400000);
1786 reloc2.set_r_address(address);
1787 reloc2.set_r_symbolnum(entry.toAddend);
1788 reloc2.set_r_pcrel(false);
1789 reloc2.set_r_length(2);
1790 reloc2.set_r_extern(false);
1791 reloc2.set_r_type(ARM64_RELOC_ADDEND);
1792 relocs.push_back(reloc2);
1793 }
1794 // fall into next case
1795 case ld::Fixup::kindStoreTargetAddressARM64PageOff12:
1796 reloc1.set_r_address(address);
1797 reloc1.set_r_symbolnum(symbolNum);
1798 reloc1.set_r_pcrel(false);
1799 reloc1.set_r_length(2);
1800 reloc1.set_r_extern(external);
1801 reloc1.set_r_type(ARM64_RELOC_PAGEOFF12);
1802 relocs.push_back(reloc1);
1803 break;
1804
1805 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
1806 case ld::Fixup::kindStoreARM64GOTLoadPage21:
1807 reloc1.set_r_address(address);
1808 reloc1.set_r_symbolnum(symbolNum);
1809 reloc1.set_r_pcrel(true);
1810 reloc1.set_r_length(2);
1811 reloc1.set_r_extern(external);
1812 reloc1.set_r_type(ARM64_RELOC_GOT_LOAD_PAGE21);
1813 relocs.push_back(reloc1);
1814 break;
1815
1816 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12:
1817 case ld::Fixup::kindStoreARM64GOTLoadPageOff12:
1818 reloc1.set_r_address(address);
1819 reloc1.set_r_symbolnum(symbolNum);
1820 reloc1.set_r_pcrel(false);
1821 reloc1.set_r_length(2);
1822 reloc1.set_r_extern(external);
1823 reloc1.set_r_type(ARM64_RELOC_GOT_LOAD_PAGEOFF12);
1824 relocs.push_back(reloc1);
1825 break;
1826
1827
1828 case ld::Fixup::kindStoreLittleEndian64:
1829 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
1830 if ( entry.fromTarget != NULL ) {
1831 // this is a pointer-diff
1832 reloc1.set_r_address(address);
1833 reloc1.set_r_symbolnum(symbolNum);
1834 reloc1.set_r_pcrel(false);
1835 reloc1.set_r_length(3);
1836 reloc1.set_r_extern(external);
1837 reloc1.set_r_type(ARM64_RELOC_UNSIGNED);
1838 reloc2.set_r_address(address);
1839 reloc2.set_r_symbolnum(fromSymbolNum);
1840 reloc2.set_r_pcrel(false);
1841 reloc2.set_r_length(3);
1842 reloc2.set_r_extern(fromExternal);
1843 reloc2.set_r_type(ARM64_RELOC_SUBTRACTOR);
1844 relocs.push_back(reloc2);
1845 relocs.push_back(reloc1);
1846 }
1847 else {
1848 // regular pointer
1849 reloc1.set_r_address(address);
1850 reloc1.set_r_symbolnum(symbolNum);
1851 reloc1.set_r_pcrel(false);
1852 reloc1.set_r_length(3);
1853 reloc1.set_r_extern(external);
1854 reloc1.set_r_type(ARM64_RELOC_UNSIGNED);
1855 relocs.push_back(reloc1);
1856 }
1857 break;
1858
1859 case ld::Fixup::kindStoreLittleEndian32:
1860 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
1861 if ( entry.fromTarget != NULL ) {
1862 // this is a pointer-diff
1863 reloc1.set_r_address(address);
1864 reloc1.set_r_symbolnum(symbolNum);
1865 reloc1.set_r_pcrel(false);
1866 reloc1.set_r_length(2);
1867 reloc1.set_r_extern(external);
1868 reloc1.set_r_type(ARM64_RELOC_UNSIGNED);
1869 reloc2.set_r_address(address);
1870 reloc2.set_r_symbolnum(fromSymbolNum);
1871 reloc2.set_r_pcrel(false);
1872 reloc2.set_r_length(2);
1873 reloc2.set_r_extern(fromExternal);
1874 reloc2.set_r_type(ARM64_RELOC_SUBTRACTOR);
1875 relocs.push_back(reloc2);
1876 relocs.push_back(reloc1);
1877 }
1878 else {
1879 // regular pointer
1880 reloc1.set_r_address(address);
1881 reloc1.set_r_symbolnum(symbolNum);
1882 reloc1.set_r_pcrel(false);
1883 reloc1.set_r_length(2);
1884 reloc1.set_r_extern(external);
1885 reloc1.set_r_type(ARM64_RELOC_UNSIGNED);
1886 relocs.push_back(reloc1);
1887 }
1888 break;
1889
1890 case ld::Fixup::kindStoreARM64PointerToGOT:
1891 reloc1.set_r_address(address);
1892 reloc1.set_r_symbolnum(symbolNum);
1893 reloc1.set_r_pcrel(false);
1894 reloc1.set_r_length(3);
1895 reloc1.set_r_extern(external);
1896 reloc1.set_r_type(ARM64_RELOC_POINTER_TO_GOT);
1897 relocs.push_back(reloc1);
1898 break;
1899
1900 case ld::Fixup::kindStoreARM64PCRelToGOT:
1901 reloc1.set_r_address(address);
1902 reloc1.set_r_symbolnum(symbolNum);
1903 reloc1.set_r_pcrel(true);
1904 reloc1.set_r_length(2);
1905 reloc1.set_r_extern(external);
1906 reloc1.set_r_type(ARM64_RELOC_POINTER_TO_GOT);
1907 relocs.push_back(reloc1);
1908 break;
1909
1910 default:
1911 assert(0 && "need to handle arm64 -r reloc");
1912
1913 }
1914
1915}
1916#endif // SUPPORT_ARCH_arm64
a645023d 1917
a645023d
A
1918
1919template <typename A>
1920void SectionRelocationsAtom<A>::addSectionReloc(ld::Internal::FinalSection* sect, ld::Fixup::Kind kind,
1921 const ld::Atom* inAtom, uint32_t offsetInAtom,
1922 bool toTargetUsesExternalReloc ,bool fromTargetExternalReloc,
1923 const ld::Atom* toTarget, uint64_t toAddend,
1924 const ld::Atom* fromTarget, uint64_t fromAddend)
1925{
1926 Entry entry;
1927 entry.kind = kind;
1928 entry.toTargetUsesExternalReloc = toTargetUsesExternalReloc;
1929 entry.fromTargetUsesExternalReloc = fromTargetExternalReloc;
1930 entry.inAtom = inAtom;
1931 entry.offsetInAtom = offsetInAtom;
1932 entry.toTarget = toTarget;
1933 entry.toAddend = toAddend;
1934 entry.fromTarget = fromTarget;
1935 entry.fromAddend = fromAddend;
1936
1937 static ld::Internal::FinalSection* lastSection = NULL;
1938 static SectionAndEntries* lastSectionAndEntries = NULL;
1939
1940 if ( sect != lastSection ) {
1941 for(typename std::vector<SectionAndEntries>::iterator it=_entriesBySection.begin(); it != _entriesBySection.end(); ++it) {
1942 if ( sect == it->sect ) {
1943 lastSection = sect;
1944 lastSectionAndEntries = &*it;
1945 break;
1946 }
1947 }
1948 if ( sect != lastSection ) {
1949 SectionAndEntries tmp;
1950 tmp.sect = sect;
1951 _entriesBySection.push_back(tmp);
1952 lastSection = sect;
1953 lastSectionAndEntries = &_entriesBySection.back();
1954 }
1955 }
1956 lastSectionAndEntries->entries.push_back(entry);
1957}
1958
1959template <typename A>
1960void SectionRelocationsAtom<A>::encode()
1961{
1962 // convert each Entry record to one or two reloc records
1963 for(typename std::vector<SectionAndEntries>::iterator it=_entriesBySection.begin(); it != _entriesBySection.end(); ++it) {
1964 SectionAndEntries& se = *it;
1965 for(typename std::vector<Entry>::iterator eit=se.entries.begin(); eit != se.entries.end(); ++eit) {
1966 encodeSectionReloc(se.sect, *eit, se.relocs);
1967 }
1968 }
1969
1970 // update sections with start and count or relocs
1971 uint32_t index = 0;
1972 for(typename std::vector<SectionAndEntries>::iterator it=_entriesBySection.begin(); it != _entriesBySection.end(); ++it) {
1973 SectionAndEntries& se = *it;
1974 se.sect->relocStart = index;
1975 se.sect->relocCount = se.relocs.size();
1976 index += se.sect->relocCount;
1977 }
1978
1979}
1980
1981
1982
1983template <typename A>
1984class IndirectSymbolTableAtom : public ClassicLinkEditAtom
1985{
1986public:
1987 IndirectSymbolTableAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
1988 : ClassicLinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { }
1989
1990 // overrides of ld::Atom
1991 virtual const char* name() const { return "indirect symbol table"; }
1992 virtual uint64_t size() const;
1993 virtual void copyRawContent(uint8_t buffer[]) const;
1994 // overrides of ClassicLinkEditAtom
1995 virtual void encode();
1996
1997private:
1998 typedef typename A::P P;
1999 typedef typename A::P::E E;
2000 typedef typename A::P::uint_t pint_t;
2001
2002 void encodeStubSection(ld::Internal::FinalSection* sect);
2003 void encodeLazyPointerSection(ld::Internal::FinalSection* sect);
2004 void encodeNonLazyPointerSection(ld::Internal::FinalSection* sect);
2005 uint32_t symIndexOfStubAtom(const ld::Atom*);
2006 uint32_t symIndexOfLazyPointerAtom(const ld::Atom*);
2007 uint32_t symIndexOfNonLazyPointerAtom(const ld::Atom*);
2008 uint32_t symbolIndex(const ld::Atom*);
a645023d
A
2009
2010
2011 std::vector<uint32_t> _entries;
2012
2013 static ld::Section _s_section;
2014};
2015
2016template <typename A>
2017ld::Section IndirectSymbolTableAtom<A>::_s_section("__LINKEDIT", "__ind_sym_tab", ld::Section::typeLinkEdit, true);
2018
2019
2020
2021
2022template <typename A>
2023uint32_t IndirectSymbolTableAtom<A>::symbolIndex(const ld::Atom* atom)
2024{
2025 std::map<const ld::Atom*, uint32_t>::iterator pos = this->_writer._atomToSymbolIndex.find(atom);
2026 if ( pos != this->_writer._atomToSymbolIndex.end() )
2027 return pos->second;
2028 //fprintf(stderr, "_atomToSymbolIndex content:\n");
2029 //for(std::map<const ld::Atom*, uint32_t>::iterator it = this->_writer._atomToSymbolIndex.begin(); it != this->_writer._atomToSymbolIndex.end(); ++it) {
2030 // fprintf(stderr, "%p(%s) => %d\n", it->first, it->first->name(), it->second);
2031 //}
2032 throwf("internal error: atom not found in symbolIndex(%s)", atom->name());
2033}
2034
2035template <typename A>
2036uint32_t IndirectSymbolTableAtom<A>::symIndexOfStubAtom(const ld::Atom* stubAtom)
2037{
2038 for (ld::Fixup::iterator fit = stubAtom->fixupsBegin(); fit != stubAtom->fixupsEnd(); ++fit) {
2039 if ( fit->binding == ld::Fixup::bindingDirectlyBound ) {
ec29ba20
A
2040 ld::Atom::ContentType type = fit->u.target->contentType();
2041 if (( type == ld::Atom::typeLazyPointer) || (type == ld::Atom::typeLazyDylibPointer) )
2042 return symIndexOfLazyPointerAtom(fit->u.target);
2043 if ( type == ld::Atom::typeNonLazyPointer )
2044 return symIndexOfNonLazyPointerAtom(fit->u.target);
a645023d
A
2045 }
2046 }
2047 throw "internal error: stub missing fixup to lazy pointer";
2048}
2049
2050
2051template <typename A>
2052uint32_t IndirectSymbolTableAtom<A>::symIndexOfLazyPointerAtom(const ld::Atom* lpAtom)
2053{
2054 for (ld::Fixup::iterator fit = lpAtom->fixupsBegin(); fit != lpAtom->fixupsEnd(); ++fit) {
2055 if ( fit->kind == ld::Fixup::kindLazyTarget ) {
2056 assert(fit->binding == ld::Fixup::bindingDirectlyBound);
2057 return symbolIndex(fit->u.target);
2058 }
2059 }
2060 throw "internal error: lazy pointer missing fixupLazyTarget fixup";
2061}
2062
2063template <typename A>
2064uint32_t IndirectSymbolTableAtom<A>::symIndexOfNonLazyPointerAtom(const ld::Atom* nlpAtom)
2065{
2066 //fprintf(stderr, "symIndexOfNonLazyPointerAtom(%p) %s\n", nlpAtom, nlpAtom->name());
2067 for (ld::Fixup::iterator fit = nlpAtom->fixupsBegin(); fit != nlpAtom->fixupsEnd(); ++fit) {
2068 // non-lazy-pointer to a stripped symbol => no symbol index
2069 if ( fit->clusterSize != ld::Fixup::k1of1 )
2070 return INDIRECT_SYMBOL_LOCAL;
2071 const ld::Atom* target;
2072 switch ( fit->binding ) {
2073 case ld::Fixup::bindingDirectlyBound:
2074 target = fit->u.target;
2075 break;
2076 case ld::Fixup::bindingsIndirectlyBound:
2077 target = _state.indirectBindingTable[fit->u.bindingIndex];
2078 break;
2079 default:
2080 throw "internal error: unexpected non-lazy pointer binding";
2081 }
a645023d
A
2082 bool targetIsGlobal = (target->scope() == ld::Atom::scopeGlobal);
2083 switch ( target->definition() ) {
2084 case ld::Atom::definitionRegular:
2085 if ( targetIsGlobal ) {
2086 if ( _options.outputKind() == Options::kObjectFile ) {
2087 // nlpointer to global symbol uses indirect symbol table in .o files
2088 return symbolIndex(target);
2089 }
2090 else if ( target->combine() == ld::Atom::combineByName ) {
2091 // dyld needs to bind nlpointer to global weak def
2092 return symbolIndex(target);
2093 }
2094 else if ( _options.nameSpace() != Options::kTwoLevelNameSpace ) {
2095 // dyld needs to bind nlpointer to global def linked for flat namespace
2096 return symbolIndex(target);
2097 }
2098 }
2099 break;
2100 case ld::Atom::definitionTentative:
2101 case ld::Atom::definitionAbsolute:
2102 if ( _options.outputKind() == Options::kObjectFile ) {
2103 // tentative def in .o file always uses symbol index
2104 return symbolIndex(target);
2105 }
2106 // dyld needs to bind nlpointer to global def linked for flat namespace
2107 if ( targetIsGlobal && _options.nameSpace() != Options::kTwoLevelNameSpace )
2108 return symbolIndex(target);
2109 break;
2110 case ld::Atom::definitionProxy:
2111 // dyld needs to bind nlpointer to something in another dylib
2112 {
2113 const ld::dylib::File* dylib = dynamic_cast<const ld::dylib::File*>(target->file());
2114 if ( (dylib != NULL) && dylib->willBeLazyLoadedDylib() )
2115 throwf("illegal data reference to %s in lazy loaded dylib %s", target->name(), dylib->path());
2116 }
2117 return symbolIndex(target);
2118 }
2119 }
2120 if ( nlpAtom->fixupsBegin() == nlpAtom->fixupsEnd() ) {
2121 // no fixups means this is the ImageLoader cache slot
2122 return INDIRECT_SYMBOL_ABS;
2123 }
2124
2125 // The magic index INDIRECT_SYMBOL_LOCAL tells dyld it should does not need to bind
2126 // this non-lazy pointer.
2127 return INDIRECT_SYMBOL_LOCAL;
2128}
2129
2130
2131
2132template <typename A>
2133void IndirectSymbolTableAtom<A>::encodeStubSection(ld::Internal::FinalSection* sect)
2134{
2135 sect->indirectSymTabStartIndex = _entries.size();
2136 sect->indirectSymTabElementSize = sect->atoms[0]->size();
2137 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
2138 _entries.push_back(symIndexOfStubAtom(*ait));
2139 }
2140}
2141
2142template <typename A>
2143void IndirectSymbolTableAtom<A>::encodeLazyPointerSection(ld::Internal::FinalSection* sect)
2144{
2145 sect->indirectSymTabStartIndex = _entries.size();
2146 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
2147 _entries.push_back(symIndexOfLazyPointerAtom(*ait));
2148 }
2149}
2150
2151template <typename A>
2152void IndirectSymbolTableAtom<A>::encodeNonLazyPointerSection(ld::Internal::FinalSection* sect)
2153{
2154 sect->indirectSymTabStartIndex = _entries.size();
2155 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
2156 _entries.push_back(symIndexOfNonLazyPointerAtom(*ait));
2157 }
2158}
2159
a645023d
A
2160template <typename A>
2161void IndirectSymbolTableAtom<A>::encode()
2162{
ebf6f434
A
2163 // static executables should not have an indirect symbol table, unless PIE
2164 if ( (this->_options.outputKind() == Options::kStaticExecutable) && !_options.positionIndependentExecutable() )
a645023d
A
2165 return;
2166
ec29ba20
A
2167 // x86_64 kext bundles should not have an indirect symbol table unless using stubs
2168 if ( (this->_options.outputKind() == Options::kKextBundle) && !this->_options.kextsUseStubs() )
a645023d
A
2169 return;
2170
ebf6f434
A
2171 // slidable static executables (-static -pie) should not have an indirect symbol table
2172 if ( (this->_options.outputKind() == Options::kStaticExecutable) && this->_options.positionIndependentExecutable() )
2173 return;
2174
a645023d
A
2175 // find all special sections that need a range of the indirect symbol table section
2176 for (std::vector<ld::Internal::FinalSection*>::iterator sit = this->_state.sections.begin(); sit != this->_state.sections.end(); ++sit) {
2177 ld::Internal::FinalSection* sect = *sit;
2178 switch ( sect->type() ) {
2179 case ld::Section::typeStub:
2180 case ld::Section::typeStubClose:
2181 this->encodeStubSection(sect);
2182 break;
2183 case ld::Section::typeLazyPointerClose:
2184 case ld::Section::typeLazyPointer:
2185 case ld::Section::typeLazyDylibPointer:
2186 this->encodeLazyPointerSection(sect);
2187 break;
2188 case ld::Section::typeNonLazyPointer:
2189 this->encodeNonLazyPointerSection(sect);
2190 break;
2191 default:
2192 break;
2193 }
2194 }
2195}
2196
2197template <typename A>
2198uint64_t IndirectSymbolTableAtom<A>::size() const
2199{
2200 return _entries.size() * sizeof(uint32_t);
2201}
2202
2203template <typename A>
2204void IndirectSymbolTableAtom<A>::copyRawContent(uint8_t buffer[]) const
2205{
2206 uint32_t* array = (uint32_t*)buffer;
2207 for(unsigned long i=0; i < _entries.size(); ++i) {
2208 E::set32(array[i], _entries[i]);
2209 }
2210}
2211
2212
2213
2214
2215
2216
2217
2218
2219} // namespace tool
2220} // namespace ld
2221
2222#endif // __LINKEDIT_CLASSIC_HPP__