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