]> git.saurik.com Git - apple/ld64.git/blob - src/ld/LinkEditClassic.hpp
172bb4c3cde82d485bde97ef3cc8db9b4421f18d
[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 void addDataInCodeLabels(const ld::Atom* atom, uint32_t& symbolIndex);
234
235
236 mutable std::vector<macho_nlist<P> > _globals;
237 mutable std::vector<macho_nlist<P> > _locals;
238 mutable std::vector<macho_nlist<P> > _imports;
239
240 uint32_t _stabsStringsOffsetStart;
241 uint32_t _stabsStringsOffsetEnd;
242 uint32_t _stabsIndexStart;
243 uint32_t _stabsIndexEnd;
244
245 static ld::Section _s_section;
246 static int _s_anonNameIndex;
247
248 };
249
250 template <typename A>
251 ld::Section SymbolTableAtom<A>::_s_section("__LINKEDIT", "__symbol_table", ld::Section::typeLinkEdit, true);
252
253 template <typename A>
254 int SymbolTableAtom<A>::_s_anonNameIndex = 1;
255
256
257 template <typename A>
258 bool SymbolTableAtom<A>::addLocal(const ld::Atom* atom, StringPoolAtom* pool)
259 {
260 macho_nlist<P> entry;
261 assert(atom->symbolTableInclusion() != ld::Atom::symbolTableNotIn);
262
263 // set n_strx
264 const char* symbolName = atom->name();
265 char anonName[32];
266 if ( this->_options.outputKind() == Options::kObjectFile ) {
267 if ( atom->contentType() == ld::Atom::typeCString ) {
268 if ( atom->combine() == ld::Atom::combineByNameAndContent ) {
269 // don't use 'l' labels for x86_64 strings
270 // <rdar://problem/6605499> x86_64 obj-c runtime confused when static lib is stripped
271 sprintf(anonName, "LC%u", _s_anonNameIndex++);
272 symbolName = anonName;
273 }
274 }
275 else if ( atom->contentType() == ld::Atom::typeCFI ) {
276 if ( _options.removeEHLabels() )
277 return false;
278 // synthesize .eh name
279 if ( strcmp(atom->name(), "CIE") == 0 )
280 symbolName = "EH_Frame1";
281 else
282 symbolName = "func.eh";
283 }
284 else if ( atom->symbolTableInclusion() == ld::Atom::symbolTableInWithRandomAutoStripLabel ) {
285 // make auto-strip anonymous name for symbol
286 sprintf(anonName, "l%03u", _s_anonNameIndex++);
287 symbolName = anonName;
288 }
289 }
290 entry.set_n_strx(pool->add(symbolName));
291
292 // set n_type
293 uint8_t type = N_SECT;
294 if ( atom->definition() == ld::Atom::definitionAbsolute ) {
295 type = N_ABS;
296 }
297 else if ( (atom->section().type() == ld::Section::typeObjC1Classes)
298 && (this->_options.outputKind() == Options::kObjectFile) ) {
299 // __OBJC __class has floating abs symbols for each class data structure
300 type = N_ABS;
301 }
302 if ( atom->scope() == ld::Atom::scopeLinkageUnit )
303 type |= N_PEXT;
304 entry.set_n_type(type);
305
306 // set n_sect (section number of implementation )
307 if ( atom->definition() == ld::Atom::definitionAbsolute )
308 entry.set_n_sect(0);
309 else
310 entry.set_n_sect(atom->machoSection());
311
312 // set n_desc
313 uint16_t desc = 0;
314 if ( atom->symbolTableInclusion() == ld::Atom::symbolTableInAndNeverStrip )
315 desc |= REFERENCED_DYNAMICALLY;
316 if ( atom->dontDeadStrip() && (this->_options.outputKind() == Options::kObjectFile) )
317 desc |= N_NO_DEAD_STRIP;
318 if ( (atom->definition() == ld::Atom::definitionRegular) && (atom->combine() == ld::Atom::combineByName) )
319 desc |= N_WEAK_DEF;
320 if ( atom->isThumb() )
321 desc |= N_ARM_THUMB_DEF;
322 entry.set_n_desc(desc);
323
324 // set n_value ( address this symbol will be at if this executable is loaded at it preferred address )
325 if ( atom->definition() == ld::Atom::definitionAbsolute )
326 entry.set_n_value(atom->objectAddress());
327 else
328 entry.set_n_value(atom->finalAddress());
329
330 // add to array
331 _locals.push_back(entry);
332 return true;
333 }
334
335
336 template <typename A>
337 void SymbolTableAtom<A>::addGlobal(const ld::Atom* atom, StringPoolAtom* pool)
338 {
339 macho_nlist<P> entry;
340
341 // set n_strx
342 const char* symbolName = atom->name();
343 char anonName[32];
344 if ( this->_options.outputKind() == Options::kObjectFile ) {
345 if ( atom->symbolTableInclusion() == ld::Atom::symbolTableInWithRandomAutoStripLabel ) {
346 // make auto-strip anonymous name for symbol
347 sprintf(anonName, "l%03u", _s_anonNameIndex++);
348 symbolName = anonName;
349 }
350 }
351 entry.set_n_strx(pool->add(symbolName));
352
353 // set n_type
354 if ( atom->definition() == ld::Atom::definitionAbsolute ) {
355 entry.set_n_type(N_EXT | N_ABS);
356 }
357 else if ( (atom->section().type() == ld::Section::typeObjC1Classes)
358 && (this->_options.outputKind() == Options::kObjectFile) ) {
359 // __OBJC __class has floating abs symbols for each class data structure
360 entry.set_n_type(N_EXT | N_ABS);
361 }
362 else if ( (atom->definition() == ld::Atom::definitionProxy) && (atom->scope() == ld::Atom::scopeGlobal) ) {
363 entry.set_n_type(N_EXT | N_INDR);
364 }
365 else {
366 entry.set_n_type(N_EXT | N_SECT);
367 if ( (atom->scope() == ld::Atom::scopeLinkageUnit) && (this->_options.outputKind() == Options::kObjectFile) ) {
368 if ( this->_options.keepPrivateExterns() )
369 entry.set_n_type(N_EXT | N_SECT | N_PEXT);
370 }
371 else if ( (atom->symbolTableInclusion() == ld::Atom::symbolTableInAndNeverStrip)
372 && (atom->section().type() == ld::Section::typeMachHeader)
373 && !_options.positionIndependentExecutable() ) {
374 // the __mh_execute_header is historical magic in non-pie executabls and must be an absolute symbol
375 entry.set_n_type(N_EXT | N_ABS);
376 }
377 }
378
379 // set n_sect (section number of implementation)
380 if ( atom->definition() == ld::Atom::definitionAbsolute )
381 entry.set_n_sect(0);
382 else if ( (atom->definition() == ld::Atom::definitionProxy) && (atom->scope() == ld::Atom::scopeGlobal) )
383 entry.set_n_sect(0);
384 else
385 entry.set_n_sect(atom->machoSection());
386
387 // set n_desc
388 uint16_t desc = 0;
389 if ( atom->isThumb() )
390 desc |= N_ARM_THUMB_DEF;
391 if ( atom->symbolTableInclusion() == ld::Atom::symbolTableInAndNeverStrip )
392 desc |= REFERENCED_DYNAMICALLY;
393 if ( (atom->contentType() == ld::Atom::typeResolver) && (this->_options.outputKind() == Options::kObjectFile) )
394 desc |= N_SYMBOL_RESOLVER;
395 if ( atom->dontDeadStrip() && (this->_options.outputKind() == Options::kObjectFile) )
396 desc |= N_NO_DEAD_STRIP;
397 if ( (atom->definition() == ld::Atom::definitionRegular) && (atom->combine() == ld::Atom::combineByName) ) {
398 desc |= N_WEAK_DEF;
399 // <rdar://problem/6783167> support auto hidden weak symbols: .weak_def_can_be_hidden
400 if ( (atom->scope() == ld::Atom::scopeGlobal) && atom->autoHide() && (this->_options.outputKind() == Options::kObjectFile) )
401 desc |= N_WEAK_REF;
402 }
403 entry.set_n_desc(desc);
404
405 // set n_value ( address this symbol will be at if this executable is loaded at it preferred address )
406 if ( atom->definition() == ld::Atom::definitionAbsolute )
407 entry.set_n_value(atom->objectAddress());
408 else if ( (atom->definition() == ld::Atom::definitionProxy) && (atom->scope() == ld::Atom::scopeGlobal) ) {
409 if ( atom->isAlias() ) {
410 // this re-export also renames
411 for (ld::Fixup::iterator fit = atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
412 if ( fit->kind == ld::Fixup::kindNoneFollowOn ) {
413 assert(fit->binding == ld::Fixup::bindingDirectlyBound);
414 entry.set_n_value(pool->add(fit->u.target->name()));
415 }
416 }
417 }
418 else
419 entry.set_n_value(entry.n_strx());
420 }
421 else
422 entry.set_n_value(atom->finalAddress());
423
424 // add to array
425 _globals.push_back(entry);
426 }
427
428 template <typename A>
429 uint8_t SymbolTableAtom<A>::classicOrdinalForProxy(const ld::Atom* atom)
430 {
431 assert(atom->definition() == ld::Atom::definitionProxy);
432 // when linking for flat-namespace ordinals are always zero
433 if ( _options.nameSpace() != Options::kTwoLevelNameSpace )
434 return 0;
435 const ld::dylib::File* dylib = dynamic_cast<const ld::dylib::File*>(atom->file());
436 // when linking -undefined dynamic_lookup, unbound symbols use DYNAMIC_LOOKUP_ORDINAL
437 if ( dylib == NULL ) {
438 if (_options.undefinedTreatment() == Options::kUndefinedDynamicLookup )
439 return DYNAMIC_LOOKUP_ORDINAL;
440 if (_options.allowedUndefined(atom->name()) )
441 return DYNAMIC_LOOKUP_ORDINAL;
442 }
443 assert(dylib != NULL);
444 int ord = this->_writer.dylibToOrdinal(dylib);
445 if ( ord == BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE )
446 return EXECUTABLE_ORDINAL;
447 return ord;
448 }
449
450
451 template <typename A>
452 void SymbolTableAtom<A>::addImport(const ld::Atom* atom, StringPoolAtom* pool)
453 {
454 macho_nlist<P> entry;
455
456 // set n_strx
457 entry.set_n_strx(pool->add(atom->name()));
458
459 // set n_type
460 if ( this->_options.outputKind() == Options::kObjectFile ) {
461 if ( (atom->scope() == ld::Atom::scopeLinkageUnit)
462 && (atom->definition() == ld::Atom::definitionTentative) )
463 entry.set_n_type(N_UNDF | N_EXT | N_PEXT);
464 else
465 entry.set_n_type(N_UNDF | N_EXT);
466 }
467 else {
468 if ( this->_options.prebind() )
469 entry.set_n_type(N_PBUD | N_EXT);
470 else
471 entry.set_n_type(N_UNDF | N_EXT);
472 }
473
474 // set n_sect
475 entry.set_n_sect(0);
476
477 uint16_t desc = 0;
478 if ( this->_options.outputKind() != Options::kObjectFile ) {
479 uint8_t ordinal = this->classicOrdinalForProxy(atom);
480 //fprintf(stderr, "ordinal=%u from reader=%p for symbol=%s\n", ordinal, atom->getFile(), atom->getName());
481 SET_LIBRARY_ORDINAL(desc, ordinal);
482
483 #if 0
484 // set n_desc ( high byte is library ordinal, low byte is reference type )
485 std::map<const ObjectFile::Atom*,ObjectFile::Atom*>::iterator pos = fStubsMap.find(atom);
486 if ( pos != fStubsMap.end() || ( strncmp(atom->getName(), ".objc_class_name_", 17) == 0) )
487 desc |= REFERENCE_FLAG_UNDEFINED_LAZY;
488 else
489 desc |= REFERENCE_FLAG_UNDEFINED_NON_LAZY;
490 #endif
491 }
492 else if ( atom->definition() == ld::Atom::definitionTentative ) {
493 uint8_t align = atom->alignment().powerOf2;
494 // always record custom alignment of common symbols to match what compiler does
495 SET_COMM_ALIGN(desc, align);
496 }
497 if ( (this->_options.outputKind() != Options::kObjectFile)
498 && (atom->definition() == ld::Atom::definitionProxy)
499 && (atom->combine() == ld::Atom::combineByName) ) {
500 desc |= N_REF_TO_WEAK;
501 }
502 const ld::dylib::File* dylib = dynamic_cast<const ld::dylib::File*>(atom->file());
503 if ( atom->weakImported() || ((dylib != NULL) && dylib->forcedWeakLinked()) )
504 desc |= N_WEAK_REF;
505 entry.set_n_desc(desc);
506
507 // set n_value, zero for import proxy and size for tentative definition
508 if ( atom->definition() == ld::Atom::definitionTentative )
509 entry.set_n_value(atom->size());
510 else
511 entry.set_n_value(0);
512
513 // add to array
514 _imports.push_back(entry);
515 }
516
517 template <typename A>
518 uint8_t SymbolTableAtom<A>::sectionIndexForStab(const ld::relocatable::File::Stab& stab)
519 {
520 // in FUN stabs, n_sect field is 0 for start FUN and 1 for end FUN
521 if ( stab.type == N_FUN )
522 return stab.other;
523 else if ( stab.type == N_GSYM )
524 return 0;
525 else if ( stab.atom != NULL )
526 return stab.atom->machoSection();
527 else
528 return stab.other;
529 }
530
531
532 template <typename A>
533 uint64_t SymbolTableAtom<A>::valueForStab(const ld::relocatable::File::Stab& stab)
534 {
535 switch ( stab.type ) {
536 case N_FUN:
537 if ( stab.atom == NULL ) {
538 // <rdar://problem/5591394> Add support to ld64 for N_FUN stabs when used for symbolic constants
539 return stab.value;
540 }
541 if ( (stab.string == NULL) || (strlen(stab.string) == 0) ) {
542 // end of function N_FUN has size
543 return stab.atom->size();
544 }
545 else {
546 // start of function N_FUN has address
547 return stab.atom->finalAddress();
548 }
549 case N_LBRAC:
550 case N_RBRAC:
551 case N_SLINE:
552 if ( stab.atom == NULL )
553 // some weird assembly files have slines not associated with a function
554 return stab.value;
555 else
556 // all these stab types need their value changed from an offset in the atom to an address
557 return stab.atom->finalAddress() + stab.value;
558 case N_STSYM:
559 case N_LCSYM:
560 case N_BNSYM:
561 // all these need address of atom
562 if ( stab.atom != NULL )
563 return stab.atom->finalAddress();
564 else
565 return 0; // <rdar://problem/7811357> work around for mismatch N_BNSYM
566 case N_ENSYM:
567 return stab.atom->size();
568 case N_SO:
569 if ( stab.atom == NULL ) {
570 return 0;
571 }
572 else {
573 if ( (stab.string == NULL) || (strlen(stab.string) == 0) ) {
574 // end of translation unit N_SO has address of end of last atom
575 return stab.atom->finalAddress() + stab.atom->size();
576 }
577 else {
578 // start of translation unit N_SO has address of end of first atom
579 return stab.atom->finalAddress();
580 }
581 }
582 break;
583 default:
584 return stab.value;
585 }
586 }
587
588 template <typename A>
589 uint32_t SymbolTableAtom<A>::stringOffsetForStab(const ld::relocatable::File::Stab& stab, StringPoolAtom* pool)
590 {
591 switch (stab.type) {
592 case N_SO:
593 if ( (stab.string == NULL) || stab.string[0] == '\0' ) {
594 return pool->emptyString();
595 break;
596 }
597 // fall into uniquing case
598 case N_SOL:
599 case N_BINCL:
600 case N_EXCL:
601 return pool->addUnique(stab.string);
602 break;
603 default:
604 if ( stab.string == NULL )
605 return 0;
606 else if ( stab.string[0] == '\0' )
607 return pool->emptyString();
608 else
609 return pool->add(stab.string);
610 }
611 return 0;
612 }
613
614
615
616 template <typename A>
617 bool SymbolTableAtom<A>::hasStabs(uint32_t& ssos, uint32_t& ssoe, uint32_t& sos, uint32_t& soe)
618 {
619 ssos = _stabsStringsOffsetStart;
620 ssoe = _stabsStringsOffsetEnd;
621 sos = _stabsIndexStart * sizeof(macho_nlist<P>);
622 soe = _stabsIndexEnd * sizeof(macho_nlist<P>);
623 return ( (_stabsIndexStart != _stabsIndexEnd) || (_stabsStringsOffsetStart != _stabsStringsOffsetEnd) );
624 }
625
626
627 template <typename A>
628 void SymbolTableAtom<A>::addDataInCodeLabels(const ld::Atom* atom, uint32_t& symbolIndex)
629 {
630 char label[64];
631 for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
632 label[0] = '\0';
633 switch ( fit->kind ) {
634 case ld::Fixup::kindDataInCodeStartData:
635 sprintf(label, "L$start$data$%03u", symbolIndex);
636 break;
637 case ld::Fixup::kindDataInCodeStartJT8:
638 sprintf(label, "L$start$jt8$%03u", symbolIndex);
639 break;
640 case ld::Fixup::kindDataInCodeStartJT16:
641 sprintf(label, "L$start$jt16$%03u", symbolIndex);
642 break;
643 case ld::Fixup::kindDataInCodeStartJT32:
644 sprintf(label, "L$start$jt32$%03u", symbolIndex);
645 break;
646 case ld::Fixup::kindDataInCodeStartJTA32:
647 sprintf(label, "L$start$jta32$%03u", symbolIndex);
648 break;
649 case ld::Fixup::kindDataInCodeEnd:
650 sprintf(label, "L$start$code$%03u", symbolIndex);
651 break;
652 default:
653 break;
654 }
655 if ( label[0] != '\0' ) {
656 macho_nlist<P> entry;
657 entry.set_n_type(N_SECT);
658 entry.set_n_sect(atom->machoSection());
659 entry.set_n_desc(0);
660 entry.set_n_value(atom->finalAddress() + fit->offsetInAtom);
661 entry.set_n_strx(this->_writer._stringPoolAtom->add(label));
662 _locals.push_back(entry);
663 ++symbolIndex;
664 }
665 }
666 }
667
668
669 template <typename A>
670 void SymbolTableAtom<A>::encode()
671 {
672 uint32_t symbolIndex = 0;
673
674 // make nlist entries for all local symbols
675 std::vector<const ld::Atom*>& localAtoms = this->_writer._localAtoms;
676 std::vector<const ld::Atom*>& globalAtoms = this->_writer._exportedAtoms;
677 _locals.reserve(localAtoms.size()+this->_state.stabs.size());
678 this->_writer._localSymbolsStartIndex = 0;
679 // make nlist entries for all debug notes
680 _stabsIndexStart = symbolIndex;
681 _stabsStringsOffsetStart = this->_writer._stringPoolAtom->currentOffset();
682 for (std::vector<ld::relocatable::File::Stab>::const_iterator sit=this->_state.stabs.begin(); sit != this->_state.stabs.end(); ++sit) {
683 macho_nlist<P> entry;
684 entry.set_n_type(sit->type);
685 entry.set_n_sect(sectionIndexForStab(*sit));
686 entry.set_n_desc(sit->desc);
687 entry.set_n_value(valueForStab(*sit));
688 entry.set_n_strx(stringOffsetForStab(*sit, this->_writer._stringPoolAtom));
689 _locals.push_back(entry);
690 ++symbolIndex;
691 }
692 _stabsIndexEnd = symbolIndex;
693 _stabsStringsOffsetEnd = this->_writer._stringPoolAtom->currentOffset();
694 for (std::vector<const ld::Atom*>::const_iterator it=localAtoms.begin(); it != localAtoms.end(); ++it) {
695 const ld::Atom* atom = *it;
696 if ( this->addLocal(atom, this->_writer._stringPoolAtom) )
697 this->_writer._atomToSymbolIndex[atom] = symbolIndex++;
698 }
699 // <rdar://problem/9218847> recreate L$start$ labels in -r mode
700 if ( (_options.outputKind() == Options::kObjectFile) && this->_writer.hasDataInCode ) {
701 for (std::vector<const ld::Atom*>::const_iterator it=globalAtoms.begin(); it != globalAtoms.end(); ++it) {
702 this->addDataInCodeLabels(*it, symbolIndex);
703 }
704 for (std::vector<const ld::Atom*>::const_iterator it=localAtoms.begin(); it != localAtoms.end(); ++it) {
705 this->addDataInCodeLabels(*it, symbolIndex);
706 }
707 }
708 this->_writer._localSymbolsCount = symbolIndex;
709
710
711 // make nlist entries for all global symbols
712 _globals.reserve(globalAtoms.size());
713 this->_writer._globalSymbolsStartIndex = symbolIndex;
714 for (std::vector<const ld::Atom*>::const_iterator it=globalAtoms.begin(); it != globalAtoms.end(); ++it) {
715 const ld::Atom* atom = *it;
716 this->addGlobal(atom, this->_writer._stringPoolAtom);
717 this->_writer._atomToSymbolIndex[atom] = symbolIndex++;
718 }
719 this->_writer._globalSymbolsCount = symbolIndex - this->_writer._globalSymbolsStartIndex;
720
721 // make nlist entries for all undefined (imported) symbols
722 std::vector<const ld::Atom*>& importAtoms = this->_writer._importedAtoms;
723 _imports.reserve(importAtoms.size());
724 this->_writer._importSymbolsStartIndex = symbolIndex;
725 for (std::vector<const ld::Atom*>::const_iterator it=importAtoms.begin(); it != importAtoms.end(); ++it) {
726 this->addImport(*it, this->_writer._stringPoolAtom);
727 this->_writer._atomToSymbolIndex[*it] = symbolIndex++;
728 }
729 this->_writer._importSymbolsCount = symbolIndex - this->_writer._importSymbolsStartIndex;
730 }
731
732 template <typename A>
733 uint64_t SymbolTableAtom<A>::size() const
734 {
735 return sizeof(macho_nlist<P>) * (_locals.size() + _globals.size() + _imports.size());
736 }
737
738 template <typename A>
739 void SymbolTableAtom<A>::copyRawContent(uint8_t buffer[]) const
740 {
741 memcpy(&buffer[this->_writer._localSymbolsStartIndex*sizeof(macho_nlist<P>)], &_locals[0],
742 this->_writer._localSymbolsCount*sizeof(macho_nlist<P>));
743 memcpy(&buffer[this->_writer._globalSymbolsStartIndex*sizeof(macho_nlist<P>)], &_globals[0],
744 this->_writer._globalSymbolsCount*sizeof(macho_nlist<P>));
745 memcpy(&buffer[this->_writer._importSymbolsStartIndex *sizeof(macho_nlist<P>)], &_imports[0],
746 this->_writer._importSymbolsCount*sizeof(macho_nlist<P>));
747 }
748
749
750
751
752 class RelocationsAtomAbstract : public ClassicLinkEditAtom
753 {
754 public:
755 RelocationsAtomAbstract(const Options& opts, ld::Internal& state,
756 OutputFile& writer, const ld::Section& sect,
757 unsigned int pointerSize)
758 : ClassicLinkEditAtom(opts, state, writer, sect, pointerSize) { }
759
760 virtual void addPointerReloc(uint64_t addr, uint32_t symNum) = 0;
761 virtual void addTextReloc(uint64_t addr, ld::Fixup::Kind k, uint64_t targetAddr, uint32_t symNum) = 0;
762 virtual void addExternalPointerReloc(uint64_t addr, const ld::Atom*) = 0;
763 virtual void addExternalCallSiteReloc(uint64_t addr, const ld::Atom*) = 0;
764 virtual uint64_t relocBaseAddress(ld::Internal& state) = 0;
765 virtual void addSectionReloc(ld::Internal::FinalSection* sect, ld::Fixup::Kind,
766 const ld::Atom* inAtom, uint32_t offsetInAtom,
767 bool toTargetUsesExternalReloc ,bool fromTargetExternalReloc,
768 const ld::Atom* toTarget, uint64_t toAddend,
769 const ld::Atom* fromTarget, uint64_t fromAddend) = 0;
770 protected:
771 uint32_t symbolIndex(const ld::Atom* atom) const;
772
773 };
774
775
776
777 uint32_t RelocationsAtomAbstract::symbolIndex(const ld::Atom* atom) const
778 {
779 std::map<const ld::Atom*, uint32_t>::iterator pos = this->_writer._atomToSymbolIndex.find(atom);
780 if ( pos != this->_writer._atomToSymbolIndex.end() )
781 return pos->second;
782 fprintf(stderr, "_atomToSymbolIndex content:\n");
783 for(std::map<const ld::Atom*, uint32_t>::iterator it = this->_writer._atomToSymbolIndex.begin(); it != this->_writer._atomToSymbolIndex.end(); ++it) {
784 fprintf(stderr, "%p(%s) => %d\n", it->first, it->first->name(), it->second);
785 }
786 throwf("internal error: atom not found in symbolIndex(%s)", atom->name());
787 }
788
789
790 template <typename A>
791 class LocalRelocationsAtom : public RelocationsAtomAbstract
792 {
793 public:
794 LocalRelocationsAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
795 : RelocationsAtomAbstract(opts, state, writer, _s_section, sizeof(pint_t)) { }
796
797 // overrides of ld::Atom
798 virtual const char* name() const { return "local relocations"; }
799 virtual uint64_t size() const;
800 virtual void copyRawContent(uint8_t buffer[]) const;
801 // overrides of ClassicLinkEditAtom
802 virtual void encode() {}
803 // overrides of RelocationsAtomAbstract
804 virtual void addPointerReloc(uint64_t addr, uint32_t symNum);
805 virtual void addExternalPointerReloc(uint64_t addr, const ld::Atom*) {}
806 virtual void addExternalCallSiteReloc(uint64_t addr, const ld::Atom*) {}
807 virtual uint64_t relocBaseAddress(ld::Internal& state);
808 virtual void addTextReloc(uint64_t addr, ld::Fixup::Kind k, uint64_t targetAddr, uint32_t symNum);
809 virtual void addSectionReloc(ld::Internal::FinalSection* sect, ld::Fixup::Kind,
810 const ld::Atom* inAtom, uint32_t offsetInAtom,
811 bool toTargetUsesExternalReloc ,bool fromTargetExternalReloc,
812 const ld::Atom* toTarget, uint64_t toAddend,
813 const ld::Atom* fromTarget, uint64_t fromAddend) { }
814
815 private:
816 typedef typename A::P P;
817 typedef typename A::P::E E;
818 typedef typename A::P::uint_t pint_t;
819
820 std::vector<macho_relocation_info<P> > _relocs;
821
822 static ld::Section _s_section;
823 };
824
825 template <typename A>
826 ld::Section LocalRelocationsAtom<A>::_s_section("__LINKEDIT", "__local_relocs", ld::Section::typeLinkEdit, true);
827
828
829 template <>
830 uint64_t LocalRelocationsAtom<x86_64>::relocBaseAddress(ld::Internal& state)
831 {
832 if ( _options.outputKind() == Options::kKextBundle ) {
833 // for kext bundles the reloc base address starts at __TEXT segment
834 return _options.baseAddress();
835 }
836 // for all other kinds, the x86_64 reloc base address starts at __DATA segment
837 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
838 ld::Internal::FinalSection* sect = *sit;
839 if ( strcmp(sect->segmentName(), "__DATA") == 0 )
840 return sect->address;
841 }
842 throw "__DATA segment not found";
843 }
844
845 template <typename A>
846 uint64_t LocalRelocationsAtom<A>::relocBaseAddress(ld::Internal& state)
847 {
848 return _options.baseAddress();
849 }
850
851 template <typename A>
852 void LocalRelocationsAtom<A>::addPointerReloc(uint64_t addr, uint32_t symNum)
853 {
854 macho_relocation_info<P> reloc;
855 reloc.set_r_address(addr);
856 reloc.set_r_symbolnum(symNum);
857 reloc.set_r_pcrel(false);
858 reloc.set_r_length();
859 reloc.set_r_extern(false);
860 reloc.set_r_type(GENERIC_RELOC_VANILLA);
861 _relocs.push_back(reloc);
862 }
863
864 template <typename A>
865 void LocalRelocationsAtom<A>::addTextReloc(uint64_t addr, ld::Fixup::Kind kind, uint64_t targetAddr, uint32_t symNum)
866 {
867 }
868
869
870 template <typename A>
871 uint64_t LocalRelocationsAtom<A>::size() const
872 {
873 return _relocs.size() * sizeof(macho_relocation_info<P>);
874 }
875
876 template <typename A>
877 void LocalRelocationsAtom<A>::copyRawContent(uint8_t buffer[]) const
878 {
879 memcpy(buffer, &_relocs[0], _relocs.size()*sizeof(macho_relocation_info<P>));
880 }
881
882
883
884
885
886
887 template <typename A>
888 class ExternalRelocationsAtom : public RelocationsAtomAbstract
889 {
890 public:
891 ExternalRelocationsAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
892 : RelocationsAtomAbstract(opts, state, writer, _s_section, sizeof(pint_t)) { }
893
894 // overrides of ld::Atom
895 virtual const char* name() const { return "external relocations"; }
896 virtual uint64_t size() const;
897 virtual void copyRawContent(uint8_t buffer[]) const;
898 // overrides of ClassicLinkEditAtom
899 virtual void encode() {}
900 // overrides of RelocationsAtomAbstract
901 virtual void addPointerReloc(uint64_t addr, uint32_t symNum) {}
902 virtual void addTextReloc(uint64_t addr, ld::Fixup::Kind k, uint64_t targetAddr, uint32_t symNum) {}
903 virtual void addExternalPointerReloc(uint64_t addr, const ld::Atom*);
904 virtual void addExternalCallSiteReloc(uint64_t addr, const ld::Atom*);
905 virtual uint64_t relocBaseAddress(ld::Internal& state);
906 virtual void addSectionReloc(ld::Internal::FinalSection* sect, ld::Fixup::Kind,
907 const ld::Atom* inAtom, uint32_t offsetInAtom,
908 bool toTargetUsesExternalReloc ,bool fromTargetExternalReloc,
909 const ld::Atom* toTarget, uint64_t toAddend,
910 const ld::Atom* fromTarget, uint64_t fromAddend) { }
911
912
913 private:
914 typedef typename A::P P;
915 typedef typename A::P::E E;
916 typedef typename A::P::uint_t pint_t;
917
918 struct LocAndAtom {
919 LocAndAtom(uint64_t l, const ld::Atom* a) : loc(l), atom(a), symbolIndex(0) {}
920
921 uint64_t loc;
922 const ld::Atom* atom;
923 uint32_t symbolIndex;
924
925 bool operator<(const LocAndAtom& rhs) const {
926 // sort first by symbol number
927 if ( this->symbolIndex != rhs.symbolIndex )
928 return (this->symbolIndex < rhs.symbolIndex);
929 // then sort all uses of the same symbol by address
930 return (this->loc < rhs.loc);
931 }
932
933 };
934
935 static uint32_t pointerReloc();
936 static uint32_t callReloc();
937
938 mutable std::vector<LocAndAtom> _pointerLocations;
939 mutable std::vector<LocAndAtom> _callSiteLocations;
940
941 static ld::Section _s_section;
942 };
943
944 template <typename A>
945 ld::Section ExternalRelocationsAtom<A>::_s_section("__LINKEDIT", "__extrn_relocs", ld::Section::typeLinkEdit, true);
946
947 template <>
948 uint64_t ExternalRelocationsAtom<x86_64>::relocBaseAddress(ld::Internal& state)
949 {
950 // for x86_64 the reloc base address starts at __DATA segment
951 for (std::vector<ld::Internal::FinalSection*>::iterator sit = state.sections.begin(); sit != state.sections.end(); ++sit) {
952 ld::Internal::FinalSection* sect = *sit;
953 if ( strcmp(sect->segmentName(), "__DATA") == 0 )
954 return sect->address;
955 }
956 throw "__DATA segment not found";
957 }
958
959 template <typename A>
960 uint64_t ExternalRelocationsAtom<A>::relocBaseAddress(ld::Internal& state)
961 {
962 return 0;
963 }
964
965 template <typename A>
966 void ExternalRelocationsAtom<A>::addExternalPointerReloc(uint64_t addr, const ld::Atom* target)
967 {
968 _pointerLocations.push_back(LocAndAtom(addr, target));
969 }
970
971 template <typename A>
972 void ExternalRelocationsAtom<A>::addExternalCallSiteReloc(uint64_t addr, const ld::Atom* target)
973 {
974 _callSiteLocations.push_back(LocAndAtom(addr, target));
975 }
976
977
978 template <typename A>
979 uint64_t ExternalRelocationsAtom<A>::size() const
980 {
981 if ( _options.outputKind() == Options::kStaticExecutable ) {
982 assert(_pointerLocations.size() == 0);
983 assert(_callSiteLocations.size() == 0);
984 }
985 return (_pointerLocations.size() + _callSiteLocations.size()) * sizeof(macho_relocation_info<P>);
986 }
987
988 #if SUPPORT_ARCH_arm_any
989 template <> uint32_t ExternalRelocationsAtom<arm>::pointerReloc() { return ARM_RELOC_VANILLA; }
990 #endif
991 template <> uint32_t ExternalRelocationsAtom<x86>::pointerReloc() { return GENERIC_RELOC_VANILLA; }
992 template <> uint32_t ExternalRelocationsAtom<x86_64>::pointerReloc() { return X86_64_RELOC_UNSIGNED; }
993
994
995 template <> uint32_t ExternalRelocationsAtom<x86_64>::callReloc() { return X86_64_RELOC_BRANCH; }
996 template <> uint32_t ExternalRelocationsAtom<x86>::callReloc() { return GENERIC_RELOC_VANILLA; }
997 template <typename A>
998 uint32_t ExternalRelocationsAtom<A>::callReloc()
999 {
1000 assert(0 && "external call relocs not implemented");
1001 return 0;
1002 }
1003
1004
1005 template <typename A>
1006 void ExternalRelocationsAtom<A>::copyRawContent(uint8_t buffer[]) const
1007 {
1008 macho_relocation_info<P>* r = (macho_relocation_info<P>*)buffer;
1009
1010 // assign symbol index, now that symbol table is built
1011 for (typename std::vector<LocAndAtom>::iterator it = _pointerLocations.begin(); it != _pointerLocations.end(); ++it) {
1012 it->symbolIndex = symbolIndex(it->atom);
1013 }
1014 std::sort(_pointerLocations.begin(), _pointerLocations.end());
1015 for (typename std::vector<LocAndAtom>::const_iterator it = _pointerLocations.begin(); it != _pointerLocations.end(); ++it, ++r) {
1016 r->set_r_address(it->loc);
1017 r->set_r_symbolnum(it->symbolIndex);
1018 r->set_r_pcrel(false);
1019 r->set_r_length();
1020 r->set_r_extern(true);
1021 r->set_r_type(this->pointerReloc());
1022 }
1023
1024 for (typename std::vector<LocAndAtom>::iterator it = _callSiteLocations.begin(); it != _callSiteLocations.end(); ++it) {
1025 it->symbolIndex = symbolIndex(it->atom);
1026 }
1027 std::sort(_callSiteLocations.begin(), _callSiteLocations.end());
1028 for (typename std::vector<LocAndAtom>::const_iterator it = _callSiteLocations.begin(); it != _callSiteLocations.end(); ++it, ++r) {
1029 r->set_r_address(it->loc);
1030 r->set_r_symbolnum(it->symbolIndex);
1031 r->set_r_pcrel(true);
1032 r->set_r_length(2);
1033 r->set_r_extern(true);
1034 r->set_r_type(this->callReloc());
1035 }
1036 }
1037
1038
1039 template <typename A>
1040 class SectionRelocationsAtom : public RelocationsAtomAbstract
1041 {
1042 public:
1043 SectionRelocationsAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
1044 : RelocationsAtomAbstract(opts, state, writer, _s_section, sizeof(pint_t)) { }
1045
1046 // overrides of ld::Atom
1047 virtual const char* name() const { return "section relocations"; }
1048 virtual uint64_t size() const;
1049 virtual void copyRawContent(uint8_t buffer[]) const;
1050 // overrides of ClassicLinkEditAtom
1051 virtual void encode();
1052 // overrides of RelocationsAtomAbstract
1053 virtual void addPointerReloc(uint64_t addr, uint32_t symNum) {}
1054 virtual void addTextReloc(uint64_t addr, ld::Fixup::Kind k, uint64_t targetAddr, uint32_t symNum) {}
1055 virtual void addExternalPointerReloc(uint64_t addr, const ld::Atom*) {}
1056 virtual void addExternalCallSiteReloc(uint64_t addr, const ld::Atom*) {}
1057 virtual uint64_t relocBaseAddress(ld::Internal& state) { return 0; }
1058 virtual void addSectionReloc(ld::Internal::FinalSection* sect, ld::Fixup::Kind,
1059 const ld::Atom* inAtom, uint32_t offsetInAtom,
1060 bool toTargetUsesExternalReloc ,bool fromTargetExternalReloc,
1061 const ld::Atom* toTarget, uint64_t toAddend,
1062 const ld::Atom* fromTarget, uint64_t fromAddend);
1063
1064 private:
1065 typedef typename A::P P;
1066 typedef typename A::P::E E;
1067 typedef typename A::P::uint_t pint_t;
1068
1069
1070 struct Entry {
1071 ld::Fixup::Kind kind;
1072 bool toTargetUsesExternalReloc;
1073 bool fromTargetUsesExternalReloc;
1074 const ld::Atom* inAtom;
1075 uint32_t offsetInAtom;
1076 const ld::Atom* toTarget;
1077 uint64_t toAddend;
1078 const ld::Atom* fromTarget;
1079 uint64_t fromAddend;
1080 };
1081 uint32_t sectSymNum(bool external, const ld::Atom* target);
1082 void encodeSectionReloc(ld::Internal::FinalSection* sect,
1083 const Entry& entry, std::vector<macho_relocation_info<P> >& relocs);
1084
1085 struct SectionAndEntries {
1086 ld::Internal::FinalSection* sect;
1087 std::vector<Entry> entries;
1088 std::vector<macho_relocation_info<P> > relocs;
1089 };
1090
1091 std::vector<SectionAndEntries> _entriesBySection;
1092
1093 static ld::Section _s_section;
1094 };
1095
1096 template <typename A>
1097 ld::Section SectionRelocationsAtom<A>::_s_section("__LINKEDIT", "__sect_relocs", ld::Section::typeLinkEdit, true);
1098
1099
1100
1101
1102 template <typename A>
1103 uint64_t SectionRelocationsAtom<A>::size() const
1104 {
1105 uint32_t count = 0;
1106 for(typename std::vector<SectionAndEntries>::const_iterator it=_entriesBySection.begin(); it != _entriesBySection.end(); ++it) {
1107 const SectionAndEntries& se = *it;
1108 count += se.relocs.size();
1109 }
1110 return count * sizeof(macho_relocation_info<P>);
1111 }
1112
1113 template <typename A>
1114 void SectionRelocationsAtom<A>::copyRawContent(uint8_t buffer[]) const
1115 {
1116 uint32_t offset = 0;
1117 for(typename std::vector<SectionAndEntries>::const_iterator it=_entriesBySection.begin(); it != _entriesBySection.end(); ++it) {
1118 const SectionAndEntries& se = *it;
1119 memcpy(&buffer[offset], &se.relocs[0], se.relocs.size()*sizeof(macho_relocation_info<P>));
1120 offset += (se.relocs.size() * sizeof(macho_relocation_info<P>));
1121 }
1122 }
1123
1124
1125 template <>
1126 void SectionRelocationsAtom<x86_64>::encodeSectionReloc(ld::Internal::FinalSection* sect,
1127 const Entry& entry, std::vector<macho_relocation_info<P> >& relocs)
1128 {
1129 macho_relocation_info<P> reloc1;
1130 macho_relocation_info<P> reloc2;
1131 uint64_t address = entry.inAtom->finalAddress()+entry.offsetInAtom - sect->address;
1132 bool external = entry.toTargetUsesExternalReloc;
1133 uint32_t symbolNum = sectSymNum(external, entry.toTarget);
1134 bool fromExternal = false;
1135 uint32_t fromSymbolNum = 0;
1136 if ( entry.fromTarget != NULL ) {
1137 fromExternal = entry.fromTargetUsesExternalReloc;
1138 fromSymbolNum = sectSymNum(fromExternal, entry.fromTarget);
1139 }
1140
1141
1142 switch ( entry.kind ) {
1143 case ld::Fixup::kindStoreX86BranchPCRel32:
1144 case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32:
1145 case ld::Fixup::kindStoreX86DtraceCallSiteNop:
1146 case ld::Fixup::kindStoreX86DtraceIsEnableSiteClear:
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_BRANCH);
1153 relocs.push_back(reloc1);
1154 break;
1155
1156 case ld::Fixup::kindStoreX86BranchPCRel8:
1157 reloc1.set_r_address(address);
1158 reloc1.set_r_symbolnum(symbolNum);
1159 reloc1.set_r_pcrel(true);
1160 reloc1.set_r_length(0);
1161 reloc1.set_r_extern(external);
1162 reloc1.set_r_type(X86_64_RELOC_BRANCH);
1163 relocs.push_back(reloc1);
1164 break;
1165
1166 case ld::Fixup::kindStoreX86PCRel32:
1167 case ld::Fixup::kindStoreTargetAddressX86PCRel32:
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);
1174 relocs.push_back(reloc1);
1175 break;
1176
1177 case ld::Fixup::kindStoreX86PCRel32_1:
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_1);
1184 relocs.push_back(reloc1);
1185 break;
1186
1187 case ld::Fixup::kindStoreX86PCRel32_2:
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_SIGNED_2);
1194 relocs.push_back(reloc1);
1195 break;
1196
1197 case ld::Fixup::kindStoreX86PCRel32_4:
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_SIGNED_4);
1204 relocs.push_back(reloc1);
1205 break;
1206
1207 case ld::Fixup::kindStoreX86PCRel32GOTLoad:
1208 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad:
1209 reloc1.set_r_address(address);
1210 reloc1.set_r_symbolnum(symbolNum);
1211 reloc1.set_r_pcrel(true);
1212 reloc1.set_r_length(2);
1213 reloc1.set_r_extern(external);
1214 reloc1.set_r_type(X86_64_RELOC_GOT_LOAD);
1215 relocs.push_back(reloc1);
1216 break;
1217
1218 case ld::Fixup::kindStoreX86PCRel32GOT:
1219 reloc1.set_r_address(address);
1220 reloc1.set_r_symbolnum(symbolNum);
1221 reloc1.set_r_pcrel(true);
1222 reloc1.set_r_length(2);
1223 reloc1.set_r_extern(external);
1224 reloc1.set_r_type(X86_64_RELOC_GOT);
1225 relocs.push_back(reloc1);
1226 break;
1227
1228 case ld::Fixup::kindStoreLittleEndian64:
1229 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
1230 if ( entry.fromTarget != NULL ) {
1231 // this is a pointer-diff
1232 reloc1.set_r_address(address);
1233 reloc1.set_r_symbolnum(symbolNum);
1234 reloc1.set_r_pcrel(false);
1235 reloc1.set_r_length(3);
1236 reloc1.set_r_extern(external);
1237 reloc1.set_r_type(X86_64_RELOC_UNSIGNED);
1238 reloc2.set_r_address(address);
1239 reloc2.set_r_symbolnum(fromSymbolNum);
1240 reloc2.set_r_pcrel(false);
1241 reloc2.set_r_length(3);
1242 reloc2.set_r_extern(fromExternal);
1243 reloc2.set_r_type(X86_64_RELOC_SUBTRACTOR);
1244 relocs.push_back(reloc2);
1245 relocs.push_back(reloc1);
1246 }
1247 else {
1248 // regular pointer
1249 reloc1.set_r_address(address);
1250 reloc1.set_r_symbolnum(symbolNum);
1251 reloc1.set_r_pcrel(false);
1252 reloc1.set_r_length(3);
1253 reloc1.set_r_extern(external);
1254 reloc1.set_r_type(X86_64_RELOC_UNSIGNED);
1255 relocs.push_back(reloc1);
1256 }
1257 break;
1258
1259 case ld::Fixup::kindStoreLittleEndian32:
1260 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
1261 if ( entry.fromTarget != NULL ) {
1262 // this is a pointer-diff
1263 reloc1.set_r_address(address);
1264 reloc1.set_r_symbolnum(symbolNum);
1265 reloc1.set_r_pcrel(false);
1266 reloc1.set_r_length(2);
1267 reloc1.set_r_extern(external);
1268 reloc1.set_r_type(X86_64_RELOC_UNSIGNED);
1269 reloc2.set_r_address(address);
1270 reloc2.set_r_symbolnum(fromSymbolNum);
1271 reloc2.set_r_pcrel(false);
1272 reloc2.set_r_length(2);
1273 reloc2.set_r_extern(fromExternal);
1274 reloc2.set_r_type(X86_64_RELOC_SUBTRACTOR);
1275 relocs.push_back(reloc2);
1276 relocs.push_back(reloc1);
1277 }
1278 else {
1279 // regular pointer
1280 reloc1.set_r_address(address);
1281 reloc1.set_r_symbolnum(symbolNum);
1282 reloc1.set_r_pcrel(false);
1283 reloc1.set_r_length(2);
1284 reloc1.set_r_extern(external);
1285 reloc1.set_r_type(X86_64_RELOC_UNSIGNED);
1286 relocs.push_back(reloc1);
1287 }
1288 break;
1289 default:
1290 assert(0 && "need to handle -r reloc");
1291
1292 }
1293
1294 }
1295
1296
1297
1298 template <typename A>
1299 uint32_t SectionRelocationsAtom<A>::sectSymNum(bool external, const ld::Atom* target)
1300 {
1301 if ( target->definition() == ld::Atom::definitionAbsolute )
1302 return R_ABS;
1303 if ( external )
1304 return this->symbolIndex(target); // in external relocations, r_symbolnum field is symbol index
1305 else
1306 return target->machoSection(); // in non-extern relocations, r_symbolnum is mach-o section index of target
1307 }
1308
1309 template <>
1310 void SectionRelocationsAtom<x86>::encodeSectionReloc(ld::Internal::FinalSection* sect,
1311 const Entry& entry, std::vector<macho_relocation_info<P> >& relocs)
1312 {
1313 macho_relocation_info<P> reloc1;
1314 macho_relocation_info<P> reloc2;
1315 macho_scattered_relocation_info<P>* sreloc1 = (macho_scattered_relocation_info<P>*)&reloc1;
1316 macho_scattered_relocation_info<P>* sreloc2 = (macho_scattered_relocation_info<P>*)&reloc2;
1317 uint64_t address = entry.inAtom->finalAddress()+entry.offsetInAtom - sect->address;
1318 bool external = entry.toTargetUsesExternalReloc;
1319 uint32_t symbolNum = sectSymNum(external, entry.toTarget);
1320 bool fromExternal = false;
1321 uint32_t fromSymbolNum = 0;
1322 if ( entry.fromTarget != NULL ) {
1323 fromExternal = entry.fromTargetUsesExternalReloc;
1324 fromSymbolNum = sectSymNum(fromExternal, entry.fromTarget);
1325 }
1326
1327
1328 switch ( entry.kind ) {
1329 case ld::Fixup::kindStoreX86PCRel32:
1330 case ld::Fixup::kindStoreX86BranchPCRel32:
1331 case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32:
1332 case ld::Fixup::kindStoreX86DtraceCallSiteNop:
1333 case ld::Fixup::kindStoreX86DtraceIsEnableSiteClear:
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(2);
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(2);
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::kindStoreX86BranchPCRel8:
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(0);
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(0);
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::kindStoreX86PCRel16:
1376 if ( !external && (entry.toAddend != 0) ) {
1377 // use scattered reloc is target offset is non-zero
1378 sreloc1->set_r_scattered(true);
1379 sreloc1->set_r_pcrel(true);
1380 sreloc1->set_r_length(1);
1381 sreloc1->set_r_type(GENERIC_RELOC_VANILLA);
1382 sreloc1->set_r_address(address);
1383 sreloc1->set_r_value(entry.toTarget->finalAddress());
1384 }
1385 else {
1386 reloc1.set_r_address(address);
1387 reloc1.set_r_symbolnum(symbolNum);
1388 reloc1.set_r_pcrel(true);
1389 reloc1.set_r_length(1);
1390 reloc1.set_r_extern(external);
1391 reloc1.set_r_type(GENERIC_RELOC_VANILLA);
1392 }
1393 relocs.push_back(reloc1);
1394 break;
1395
1396 case ld::Fixup::kindStoreLittleEndian32:
1397 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
1398 if ( entry.fromTarget != NULL ) {
1399 // this is a pointer-diff
1400 sreloc1->set_r_scattered(true);
1401 sreloc1->set_r_pcrel(false);
1402 sreloc1->set_r_length(2);
1403 if ( entry.toTarget->scope() == ld::Atom::scopeTranslationUnit )
1404 sreloc1->set_r_type(GENERIC_RELOC_LOCAL_SECTDIFF);
1405 else
1406 sreloc1->set_r_type(GENERIC_RELOC_SECTDIFF);
1407 sreloc1->set_r_address(address);
1408 if ( entry.toTarget == entry.inAtom ) {
1409 if ( entry.toAddend > entry.toTarget->size() )
1410 sreloc1->set_r_value(entry.toTarget->finalAddress()+entry.offsetInAtom);
1411 else
1412 sreloc1->set_r_value(entry.toTarget->finalAddress()+entry.toAddend);
1413 }
1414 else
1415 sreloc1->set_r_value(entry.toTarget->finalAddress());
1416 sreloc2->set_r_scattered(true);
1417 sreloc2->set_r_pcrel(false);
1418 sreloc2->set_r_length(2);
1419 sreloc2->set_r_type(GENERIC_RELOC_PAIR);
1420 sreloc2->set_r_address(0);
1421 if ( entry.fromTarget == entry.inAtom ) {
1422 if ( entry.fromAddend > entry.fromTarget->size() )
1423 sreloc2->set_r_value(entry.fromTarget->finalAddress()+entry.offsetInAtom);
1424 else
1425 sreloc2->set_r_value(entry.fromTarget->finalAddress()+entry.fromAddend);
1426 }
1427 else
1428 sreloc2->set_r_value(entry.fromTarget->finalAddress());
1429 relocs.push_back(reloc1);
1430 relocs.push_back(reloc2);
1431 }
1432 else {
1433 // regular pointer
1434 if ( !external && (entry.toAddend != 0) && (entry.toTarget->symbolTableInclusion() != ld::Atom::symbolTableNotIn) ) {
1435 // use scattered reloc if target offset is non-zero into named atom (5658046)
1436 sreloc1->set_r_scattered(true);
1437 sreloc1->set_r_pcrel(false);
1438 sreloc1->set_r_length(2);
1439 sreloc1->set_r_type(GENERIC_RELOC_VANILLA);
1440 sreloc1->set_r_address(address);
1441 sreloc1->set_r_value(entry.toTarget->finalAddress());
1442 }
1443 else {
1444 reloc1.set_r_address(address);
1445 reloc1.set_r_symbolnum(symbolNum);
1446 reloc1.set_r_pcrel(false);
1447 reloc1.set_r_length(2);
1448 reloc1.set_r_extern(external);
1449 reloc1.set_r_type(GENERIC_RELOC_VANILLA);
1450 }
1451 relocs.push_back(reloc1);
1452 }
1453 break;
1454 default:
1455 assert(0 && "need to handle -r reloc");
1456
1457 }
1458 }
1459
1460
1461 #if SUPPORT_ARCH_arm_any
1462 template <>
1463 void SectionRelocationsAtom<arm>::encodeSectionReloc(ld::Internal::FinalSection* sect,
1464 const Entry& entry, std::vector<macho_relocation_info<P> >& relocs)
1465 {
1466 macho_relocation_info<P> reloc1;
1467 macho_relocation_info<P> reloc2;
1468 macho_scattered_relocation_info<P>* sreloc1 = (macho_scattered_relocation_info<P>*)&reloc1;
1469 macho_scattered_relocation_info<P>* sreloc2 = (macho_scattered_relocation_info<P>*)&reloc2;
1470 uint64_t address = entry.inAtom->finalAddress()+entry.offsetInAtom - sect->address;
1471 bool external = entry.toTargetUsesExternalReloc;
1472 uint32_t symbolNum = sectSymNum(external, entry.toTarget);
1473 bool fromExternal = false;
1474 uint32_t fromSymbolNum = 0;
1475 if ( entry.fromTarget != NULL ) {
1476 fromExternal = entry.fromTargetUsesExternalReloc;
1477 fromSymbolNum = sectSymNum(fromExternal, entry.fromTarget);
1478 }
1479
1480
1481 switch ( entry.kind ) {
1482 case ld::Fixup::kindStoreTargetAddressARMBranch24:
1483 case ld::Fixup::kindStoreARMBranch24:
1484 case ld::Fixup::kindStoreARMDtraceCallSiteNop:
1485 case ld::Fixup::kindStoreARMDtraceIsEnableSiteClear:
1486 if ( !external && (entry.toAddend != 0) ) {
1487 // use scattered reloc is target offset is non-zero
1488 sreloc1->set_r_scattered(true);
1489 sreloc1->set_r_pcrel(true);
1490 sreloc1->set_r_length(2);
1491 sreloc1->set_r_type(ARM_RELOC_BR24);
1492 sreloc1->set_r_address(address);
1493 sreloc1->set_r_value(entry.toTarget->finalAddress());
1494 }
1495 else {
1496 reloc1.set_r_address(address);
1497 reloc1.set_r_symbolnum(symbolNum);
1498 reloc1.set_r_pcrel(true);
1499 reloc1.set_r_length(2);
1500 reloc1.set_r_extern(external);
1501 reloc1.set_r_type(ARM_RELOC_BR24);
1502 }
1503 relocs.push_back(reloc1);
1504 break;
1505
1506 case ld::Fixup::kindStoreTargetAddressThumbBranch22:
1507 case ld::Fixup::kindStoreThumbBranch22:
1508 case ld::Fixup::kindStoreThumbDtraceCallSiteNop:
1509 case ld::Fixup::kindStoreThumbDtraceIsEnableSiteClear:
1510 if ( !external && (entry.toAddend != 0) ) {
1511 // use scattered reloc is target offset is non-zero
1512 sreloc1->set_r_scattered(true);
1513 sreloc1->set_r_pcrel(true);
1514 sreloc1->set_r_length(2);
1515 sreloc1->set_r_type(ARM_THUMB_RELOC_BR22);
1516 sreloc1->set_r_address(address);
1517 sreloc1->set_r_value(entry.toTarget->finalAddress());
1518 }
1519 else {
1520 reloc1.set_r_address(address);
1521 reloc1.set_r_symbolnum(symbolNum);
1522 reloc1.set_r_pcrel(true);
1523 reloc1.set_r_length(2);
1524 reloc1.set_r_extern(external);
1525 reloc1.set_r_type(ARM_THUMB_RELOC_BR22);
1526 }
1527 relocs.push_back(reloc1);
1528 break;
1529
1530 case ld::Fixup::kindStoreLittleEndian32:
1531 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
1532 if ( entry.fromTarget != NULL ) {
1533 // this is a pointer-diff
1534 sreloc1->set_r_scattered(true);
1535 sreloc1->set_r_pcrel(false);
1536 sreloc1->set_r_length(2);
1537 if ( entry.toTarget->scope() == ld::Atom::scopeTranslationUnit )
1538 sreloc1->set_r_type(ARM_RELOC_LOCAL_SECTDIFF);
1539 else
1540 sreloc1->set_r_type(ARM_RELOC_SECTDIFF);
1541 sreloc1->set_r_address(address);
1542 if ( entry.toTarget == entry.inAtom ) {
1543 if ( entry.toAddend > entry.toTarget->size() )
1544 sreloc1->set_r_value(entry.toTarget->finalAddress()+entry.offsetInAtom);
1545 else
1546 sreloc1->set_r_value(entry.toTarget->finalAddress()+entry.toAddend);
1547 }
1548 else {
1549 sreloc1->set_r_value(entry.toTarget->finalAddress());
1550 }
1551 sreloc2->set_r_scattered(true);
1552 sreloc2->set_r_pcrel(false);
1553 sreloc2->set_r_length(2);
1554 sreloc2->set_r_type(ARM_RELOC_PAIR);
1555 sreloc2->set_r_address(0);
1556 if ( entry.fromTarget == entry.inAtom ) {
1557 //unsigned int pcBaseOffset = entry.inAtom->isThumb() ? 4 : 8;
1558 //if ( entry.fromAddend > pcBaseOffset )
1559 // sreloc2->set_r_value(entry.fromTarget->finalAddress()+entry.fromAddend-pcBaseOffset);
1560 //else
1561 sreloc2->set_r_value(entry.fromTarget->finalAddress()+entry.fromAddend);
1562 }
1563 else {
1564 sreloc2->set_r_value(entry.fromTarget->finalAddress());
1565 }
1566 relocs.push_back(reloc1);
1567 relocs.push_back(reloc2);
1568 }
1569 else {
1570 // regular pointer
1571 if ( !external && (entry.toAddend != 0) ) {
1572 // use scattered reloc is target offset is non-zero
1573 sreloc1->set_r_scattered(true);
1574 sreloc1->set_r_pcrel(false);
1575 sreloc1->set_r_length(2);
1576 sreloc1->set_r_type(ARM_RELOC_VANILLA);
1577 sreloc1->set_r_address(address);
1578 sreloc1->set_r_value(entry.toTarget->finalAddress());
1579 }
1580 else {
1581 reloc1.set_r_address(address);
1582 reloc1.set_r_symbolnum(symbolNum);
1583 reloc1.set_r_pcrel(false);
1584 reloc1.set_r_length(2);
1585 reloc1.set_r_extern(external);
1586 reloc1.set_r_type(ARM_RELOC_VANILLA);
1587 }
1588 relocs.push_back(reloc1);
1589 }
1590 break;
1591
1592 case ld::Fixup::kindStoreARMLow16:
1593 case ld::Fixup::kindStoreARMHigh16:
1594 case ld::Fixup::kindStoreThumbLow16:
1595 case ld::Fixup::kindStoreThumbHigh16:
1596 {
1597 int len = 0;
1598 uint32_t otherHalf = 0;
1599 uint32_t value = entry.toTarget->finalAddress()+entry.toAddend;
1600 if ( entry.fromTarget != NULL )
1601 value -= (entry.fromTarget->finalAddress()+entry.fromAddend);
1602 switch ( entry.kind ) {
1603 case ld::Fixup::kindStoreARMLow16:
1604 len = 0;
1605 otherHalf = value >> 16;
1606 break;
1607 case ld::Fixup::kindStoreARMHigh16:
1608 len = 1;
1609 otherHalf = value & 0xFFFF;
1610 break;
1611 case ld::Fixup::kindStoreThumbLow16:
1612 len = 2;
1613 otherHalf = value >> 16;
1614 break;
1615 case ld::Fixup::kindStoreThumbHigh16:
1616 len = 3;
1617 otherHalf = value & 0xFFFF;
1618 break;
1619 default:
1620 break;
1621 }
1622 if ( entry.fromTarget != NULL ) {
1623 // this is a sect-diff
1624 sreloc1->set_r_scattered(true);
1625 sreloc1->set_r_pcrel(false);
1626 sreloc1->set_r_length(len);
1627 sreloc1->set_r_type(ARM_RELOC_HALF_SECTDIFF);
1628 sreloc1->set_r_address(address);
1629 sreloc1->set_r_value(entry.toTarget->finalAddress());
1630 sreloc2->set_r_scattered(true);
1631 sreloc2->set_r_pcrel(false);
1632 sreloc2->set_r_length(len);
1633 sreloc2->set_r_type(ARM_RELOC_PAIR);
1634 sreloc2->set_r_address(otherHalf);
1635 if ( entry.fromTarget == entry.inAtom )
1636 sreloc2->set_r_value(entry.fromTarget->finalAddress()+entry.fromAddend);
1637 else
1638 sreloc2->set_r_value(entry.fromTarget->finalAddress());
1639 relocs.push_back(reloc1);
1640 relocs.push_back(reloc2);
1641 }
1642 else {
1643 // this is absolute address
1644 if ( !external && (entry.toAddend != 0) ) {
1645 // use scattered reloc is target offset is non-zero
1646 sreloc1->set_r_scattered(true);
1647 sreloc1->set_r_pcrel(false);
1648 sreloc1->set_r_length(len);
1649 sreloc1->set_r_type(ARM_RELOC_HALF);
1650 sreloc1->set_r_address(address);
1651 sreloc1->set_r_value(entry.toTarget->finalAddress());
1652 reloc2.set_r_address(otherHalf);
1653 reloc2.set_r_symbolnum(0);
1654 reloc2.set_r_pcrel(false);
1655 reloc2.set_r_length(len);
1656 reloc2.set_r_extern(false);
1657 reloc2.set_r_type(ARM_RELOC_PAIR);
1658 relocs.push_back(reloc1);
1659 relocs.push_back(reloc2);
1660 }
1661 else {
1662 reloc1.set_r_address(address);
1663 reloc1.set_r_symbolnum(symbolNum);
1664 reloc1.set_r_pcrel(false);
1665 reloc1.set_r_length(len);
1666 reloc1.set_r_extern(external);
1667 reloc1.set_r_type(ARM_RELOC_HALF);
1668 reloc2.set_r_address(otherHalf); // other half
1669 reloc2.set_r_symbolnum(0);
1670 reloc2.set_r_pcrel(false);
1671 reloc2.set_r_length(len);
1672 reloc2.set_r_extern(false);
1673 reloc2.set_r_type(ARM_RELOC_PAIR);
1674 relocs.push_back(reloc1);
1675 relocs.push_back(reloc2);
1676 }
1677 }
1678 }
1679 break;
1680
1681 default:
1682 assert(0 && "need to handle -r reloc");
1683
1684 }
1685 }
1686 #endif
1687
1688
1689
1690 template <typename A>
1691 void SectionRelocationsAtom<A>::addSectionReloc(ld::Internal::FinalSection* sect, ld::Fixup::Kind kind,
1692 const ld::Atom* inAtom, uint32_t offsetInAtom,
1693 bool toTargetUsesExternalReloc ,bool fromTargetExternalReloc,
1694 const ld::Atom* toTarget, uint64_t toAddend,
1695 const ld::Atom* fromTarget, uint64_t fromAddend)
1696 {
1697 Entry entry;
1698 entry.kind = kind;
1699 entry.toTargetUsesExternalReloc = toTargetUsesExternalReloc;
1700 entry.fromTargetUsesExternalReloc = fromTargetExternalReloc;
1701 entry.inAtom = inAtom;
1702 entry.offsetInAtom = offsetInAtom;
1703 entry.toTarget = toTarget;
1704 entry.toAddend = toAddend;
1705 entry.fromTarget = fromTarget;
1706 entry.fromAddend = fromAddend;
1707
1708 static ld::Internal::FinalSection* lastSection = NULL;
1709 static SectionAndEntries* lastSectionAndEntries = NULL;
1710
1711 if ( sect != lastSection ) {
1712 for(typename std::vector<SectionAndEntries>::iterator it=_entriesBySection.begin(); it != _entriesBySection.end(); ++it) {
1713 if ( sect == it->sect ) {
1714 lastSection = sect;
1715 lastSectionAndEntries = &*it;
1716 break;
1717 }
1718 }
1719 if ( sect != lastSection ) {
1720 SectionAndEntries tmp;
1721 tmp.sect = sect;
1722 _entriesBySection.push_back(tmp);
1723 lastSection = sect;
1724 lastSectionAndEntries = &_entriesBySection.back();
1725 }
1726 }
1727 lastSectionAndEntries->entries.push_back(entry);
1728 }
1729
1730 template <typename A>
1731 void SectionRelocationsAtom<A>::encode()
1732 {
1733 // convert each Entry record to one or two reloc records
1734 for(typename std::vector<SectionAndEntries>::iterator it=_entriesBySection.begin(); it != _entriesBySection.end(); ++it) {
1735 SectionAndEntries& se = *it;
1736 for(typename std::vector<Entry>::iterator eit=se.entries.begin(); eit != se.entries.end(); ++eit) {
1737 encodeSectionReloc(se.sect, *eit, se.relocs);
1738 }
1739 }
1740
1741 // update sections with start and count or relocs
1742 uint32_t index = 0;
1743 for(typename std::vector<SectionAndEntries>::iterator it=_entriesBySection.begin(); it != _entriesBySection.end(); ++it) {
1744 SectionAndEntries& se = *it;
1745 se.sect->relocStart = index;
1746 se.sect->relocCount = se.relocs.size();
1747 index += se.sect->relocCount;
1748 }
1749
1750 }
1751
1752
1753
1754 template <typename A>
1755 class IndirectSymbolTableAtom : public ClassicLinkEditAtom
1756 {
1757 public:
1758 IndirectSymbolTableAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
1759 : ClassicLinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { }
1760
1761 // overrides of ld::Atom
1762 virtual const char* name() const { return "indirect symbol table"; }
1763 virtual uint64_t size() const;
1764 virtual void copyRawContent(uint8_t buffer[]) const;
1765 // overrides of ClassicLinkEditAtom
1766 virtual void encode();
1767
1768 private:
1769 typedef typename A::P P;
1770 typedef typename A::P::E E;
1771 typedef typename A::P::uint_t pint_t;
1772
1773 void encodeStubSection(ld::Internal::FinalSection* sect);
1774 void encodeLazyPointerSection(ld::Internal::FinalSection* sect);
1775 void encodeNonLazyPointerSection(ld::Internal::FinalSection* sect);
1776 uint32_t symIndexOfStubAtom(const ld::Atom*);
1777 uint32_t symIndexOfLazyPointerAtom(const ld::Atom*);
1778 uint32_t symIndexOfNonLazyPointerAtom(const ld::Atom*);
1779 uint32_t symbolIndex(const ld::Atom*);
1780 bool kextBundlesDontHaveIndirectSymbolTable();
1781
1782
1783 std::vector<uint32_t> _entries;
1784
1785 static ld::Section _s_section;
1786 };
1787
1788 template <typename A>
1789 ld::Section IndirectSymbolTableAtom<A>::_s_section("__LINKEDIT", "__ind_sym_tab", ld::Section::typeLinkEdit, true);
1790
1791
1792
1793
1794 template <typename A>
1795 uint32_t IndirectSymbolTableAtom<A>::symbolIndex(const ld::Atom* atom)
1796 {
1797 std::map<const ld::Atom*, uint32_t>::iterator pos = this->_writer._atomToSymbolIndex.find(atom);
1798 if ( pos != this->_writer._atomToSymbolIndex.end() )
1799 return pos->second;
1800 //fprintf(stderr, "_atomToSymbolIndex content:\n");
1801 //for(std::map<const ld::Atom*, uint32_t>::iterator it = this->_writer._atomToSymbolIndex.begin(); it != this->_writer._atomToSymbolIndex.end(); ++it) {
1802 // fprintf(stderr, "%p(%s) => %d\n", it->first, it->first->name(), it->second);
1803 //}
1804 throwf("internal error: atom not found in symbolIndex(%s)", atom->name());
1805 }
1806
1807 template <typename A>
1808 uint32_t IndirectSymbolTableAtom<A>::symIndexOfStubAtom(const ld::Atom* stubAtom)
1809 {
1810 for (ld::Fixup::iterator fit = stubAtom->fixupsBegin(); fit != stubAtom->fixupsEnd(); ++fit) {
1811 if ( fit->binding == ld::Fixup::bindingDirectlyBound ) {
1812 assert((fit->u.target->contentType() == ld::Atom::typeLazyPointer)
1813 || (fit->u.target->contentType() == ld::Atom::typeLazyDylibPointer));
1814 return symIndexOfLazyPointerAtom(fit->u.target);
1815 }
1816 }
1817 throw "internal error: stub missing fixup to lazy pointer";
1818 }
1819
1820
1821 template <typename A>
1822 uint32_t IndirectSymbolTableAtom<A>::symIndexOfLazyPointerAtom(const ld::Atom* lpAtom)
1823 {
1824 for (ld::Fixup::iterator fit = lpAtom->fixupsBegin(); fit != lpAtom->fixupsEnd(); ++fit) {
1825 if ( fit->kind == ld::Fixup::kindLazyTarget ) {
1826 assert(fit->binding == ld::Fixup::bindingDirectlyBound);
1827 return symbolIndex(fit->u.target);
1828 }
1829 }
1830 throw "internal error: lazy pointer missing fixupLazyTarget fixup";
1831 }
1832
1833 template <typename A>
1834 uint32_t IndirectSymbolTableAtom<A>::symIndexOfNonLazyPointerAtom(const ld::Atom* nlpAtom)
1835 {
1836 //fprintf(stderr, "symIndexOfNonLazyPointerAtom(%p) %s\n", nlpAtom, nlpAtom->name());
1837 for (ld::Fixup::iterator fit = nlpAtom->fixupsBegin(); fit != nlpAtom->fixupsEnd(); ++fit) {
1838 // non-lazy-pointer to a stripped symbol => no symbol index
1839 if ( fit->clusterSize != ld::Fixup::k1of1 )
1840 return INDIRECT_SYMBOL_LOCAL;
1841 const ld::Atom* target;
1842 switch ( fit->binding ) {
1843 case ld::Fixup::bindingDirectlyBound:
1844 target = fit->u.target;
1845 break;
1846 case ld::Fixup::bindingsIndirectlyBound:
1847 target = _state.indirectBindingTable[fit->u.bindingIndex];
1848 break;
1849 default:
1850 throw "internal error: unexpected non-lazy pointer binding";
1851 }
1852 bool targetIsGlobal = (target->scope() == ld::Atom::scopeGlobal);
1853 switch ( target->definition() ) {
1854 case ld::Atom::definitionRegular:
1855 if ( targetIsGlobal ) {
1856 if ( _options.outputKind() == Options::kObjectFile ) {
1857 // nlpointer to global symbol uses indirect symbol table in .o files
1858 return symbolIndex(target);
1859 }
1860 else if ( target->combine() == ld::Atom::combineByName ) {
1861 // dyld needs to bind nlpointer to global weak def
1862 return symbolIndex(target);
1863 }
1864 else if ( _options.nameSpace() != Options::kTwoLevelNameSpace ) {
1865 // dyld needs to bind nlpointer to global def linked for flat namespace
1866 return symbolIndex(target);
1867 }
1868 }
1869 break;
1870 case ld::Atom::definitionTentative:
1871 case ld::Atom::definitionAbsolute:
1872 if ( _options.outputKind() == Options::kObjectFile ) {
1873 // tentative def in .o file always uses symbol index
1874 return symbolIndex(target);
1875 }
1876 // dyld needs to bind nlpointer to global def linked for flat namespace
1877 if ( targetIsGlobal && _options.nameSpace() != Options::kTwoLevelNameSpace )
1878 return symbolIndex(target);
1879 break;
1880 case ld::Atom::definitionProxy:
1881 // dyld needs to bind nlpointer to something in another dylib
1882 {
1883 const ld::dylib::File* dylib = dynamic_cast<const ld::dylib::File*>(target->file());
1884 if ( (dylib != NULL) && dylib->willBeLazyLoadedDylib() )
1885 throwf("illegal data reference to %s in lazy loaded dylib %s", target->name(), dylib->path());
1886 }
1887 return symbolIndex(target);
1888 }
1889 }
1890 if ( nlpAtom->fixupsBegin() == nlpAtom->fixupsEnd() ) {
1891 // no fixups means this is the ImageLoader cache slot
1892 return INDIRECT_SYMBOL_ABS;
1893 }
1894
1895 // The magic index INDIRECT_SYMBOL_LOCAL tells dyld it should does not need to bind
1896 // this non-lazy pointer.
1897 return INDIRECT_SYMBOL_LOCAL;
1898 }
1899
1900
1901
1902 template <typename A>
1903 void IndirectSymbolTableAtom<A>::encodeStubSection(ld::Internal::FinalSection* sect)
1904 {
1905 sect->indirectSymTabStartIndex = _entries.size();
1906 sect->indirectSymTabElementSize = sect->atoms[0]->size();
1907 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
1908 _entries.push_back(symIndexOfStubAtom(*ait));
1909 }
1910 }
1911
1912 template <typename A>
1913 void IndirectSymbolTableAtom<A>::encodeLazyPointerSection(ld::Internal::FinalSection* sect)
1914 {
1915 sect->indirectSymTabStartIndex = _entries.size();
1916 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
1917 _entries.push_back(symIndexOfLazyPointerAtom(*ait));
1918 }
1919 }
1920
1921 template <typename A>
1922 void IndirectSymbolTableAtom<A>::encodeNonLazyPointerSection(ld::Internal::FinalSection* sect)
1923 {
1924 sect->indirectSymTabStartIndex = _entries.size();
1925 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
1926 _entries.push_back(symIndexOfNonLazyPointerAtom(*ait));
1927 }
1928 }
1929
1930 template <typename A>
1931 bool IndirectSymbolTableAtom<A>::kextBundlesDontHaveIndirectSymbolTable()
1932 {
1933 return true;
1934 }
1935
1936 template <typename A>
1937 void IndirectSymbolTableAtom<A>::encode()
1938 {
1939 // static executables should not have an indirect symbol table, unless PIE
1940 if ( (this->_options.outputKind() == Options::kStaticExecutable) && !_options.positionIndependentExecutable() )
1941 return;
1942
1943 // x86_64 kext bundles should not have an indirect symbol table
1944 if ( (this->_options.outputKind() == Options::kKextBundle) && kextBundlesDontHaveIndirectSymbolTable() )
1945 return;
1946
1947 // slidable static executables (-static -pie) should not have an indirect symbol table
1948 if ( (this->_options.outputKind() == Options::kStaticExecutable) && this->_options.positionIndependentExecutable() )
1949 return;
1950
1951 // find all special sections that need a range of the indirect symbol table section
1952 for (std::vector<ld::Internal::FinalSection*>::iterator sit = this->_state.sections.begin(); sit != this->_state.sections.end(); ++sit) {
1953 ld::Internal::FinalSection* sect = *sit;
1954 switch ( sect->type() ) {
1955 case ld::Section::typeStub:
1956 case ld::Section::typeStubClose:
1957 this->encodeStubSection(sect);
1958 break;
1959 case ld::Section::typeLazyPointerClose:
1960 case ld::Section::typeLazyPointer:
1961 case ld::Section::typeLazyDylibPointer:
1962 this->encodeLazyPointerSection(sect);
1963 break;
1964 case ld::Section::typeNonLazyPointer:
1965 this->encodeNonLazyPointerSection(sect);
1966 break;
1967 default:
1968 break;
1969 }
1970 }
1971 }
1972
1973 template <typename A>
1974 uint64_t IndirectSymbolTableAtom<A>::size() const
1975 {
1976 return _entries.size() * sizeof(uint32_t);
1977 }
1978
1979 template <typename A>
1980 void IndirectSymbolTableAtom<A>::copyRawContent(uint8_t buffer[]) const
1981 {
1982 uint32_t* array = (uint32_t*)buffer;
1983 for(unsigned long i=0; i < _entries.size(); ++i) {
1984 E::set32(array[i], _entries[i]);
1985 }
1986 }
1987
1988
1989
1990
1991
1992
1993
1994
1995 } // namespace tool
1996 } // namespace ld
1997
1998 #endif // __LINKEDIT_CLASSIC_HPP__