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