]> git.saurik.com Git - apple/ld64.git/blob - src/ld/LinkEdit.hpp
ld64-409.12.tar.gz
[apple/ld64.git] / src / ld / LinkEdit.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_HPP__
26 #define __LINKEDIT_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 #include <unordered_map>
36
37 #include "Options.h"
38 #include "ld.hpp"
39 #include "Architectures.hpp"
40 #include "MachOFileAbstraction.hpp"
41 #include "code-sign-blobs/superblob.h"
42
43 namespace ld {
44 namespace tool {
45
46 class ByteStream {
47 private:
48 std::vector<uint8_t> _data;
49 public:
50 std::vector<uint8_t>& bytes() { return _data; }
51 unsigned long size() const { return _data.size(); }
52 void reserve(unsigned long l) { _data.reserve(l); }
53 const uint8_t* start() const { return &_data[0]; }
54
55 void append_uleb128(uint64_t value) {
56 uint8_t byte;
57 do {
58 byte = value & 0x7F;
59 value &= ~0x7F;
60 if ( value != 0 )
61 byte |= 0x80;
62 _data.push_back(byte);
63 value = value >> 7;
64 } while( byte >= 0x80 );
65 }
66
67 void append_sleb128(int64_t value) {
68 bool isNeg = ( value < 0 );
69 uint8_t byte;
70 bool more;
71 do {
72 byte = value & 0x7F;
73 value = value >> 7;
74 if ( isNeg )
75 more = ( (value != -1) || ((byte & 0x40) == 0) );
76 else
77 more = ( (value != 0) || ((byte & 0x40) != 0) );
78 if ( more )
79 byte |= 0x80;
80 _data.push_back(byte);
81 }
82 while( more );
83 }
84
85 void append_delta_encoded_uleb128_run(uint64_t start, const std::vector<uint64_t>& locations) {
86 uint64_t lastAddr = start;
87 for(std::vector<uint64_t>::const_iterator it = locations.begin(); it != locations.end(); ++it) {
88 uint64_t nextAddr = *it;
89 uint64_t delta = nextAddr - lastAddr;
90 assert(delta != 0);
91 append_uleb128(delta);
92 lastAddr = nextAddr;
93 }
94 }
95
96 void append_string(const char* str) {
97 for (const char* s = str; *s != '\0'; ++s)
98 _data.push_back(*s);
99 _data.push_back('\0');
100 }
101
102 void append_byte(uint8_t byte) {
103 _data.push_back(byte);
104 }
105
106 static unsigned int uleb128_size(uint64_t value) {
107 uint32_t result = 0;
108 do {
109 value = value >> 7;
110 ++result;
111 } while ( value != 0 );
112 return result;
113 }
114
115 void pad_to_size(unsigned int alignment) {
116 while ( (_data.size() % alignment) != 0 )
117 _data.push_back(0);
118 }
119 };
120
121
122 class LinkEditAtom : public ld::Atom
123 {
124 public:
125
126 // overrides of ld::Atom
127 virtual ld::File* file() const { return NULL; }
128 virtual uint64_t objectAddress() const { return 0; }
129 virtual uint64_t size() const;
130 virtual void copyRawContent(uint8_t buffer[]) const;
131
132 virtual void encode() const = 0;
133
134 LinkEditAtom(const Options& opts, ld::Internal& state,
135 OutputFile& writer, const ld::Section& sect,
136 unsigned int pointerSize)
137 : ld::Atom(sect, ld::Atom::definitionRegular,
138 ld::Atom::combineNever, ld::Atom::scopeTranslationUnit,
139 ld::Atom::typeUnclassified, ld::Atom::symbolTableNotIn,
140 false, false, false, ld::Atom::Alignment(log2(pointerSize))),
141 _options(opts), _state(state), _writer(writer),
142 _encoded(false) { }
143 protected:
144 const Options& _options;
145 ld::Internal& _state;
146 OutputFile& _writer;
147 mutable ByteStream _encodedData;
148 mutable bool _encoded;
149 };
150
151 uint64_t LinkEditAtom::size() const
152 {
153 assert(_encoded);
154 return _encodedData.size();
155 }
156
157 void LinkEditAtom::copyRawContent(uint8_t buffer[]) const
158 {
159 assert(_encoded);
160 memcpy(buffer, _encodedData.start(), _encodedData.size());
161 }
162
163
164
165
166 template <typename A>
167 class RebaseInfoAtom : public LinkEditAtom
168 {
169 public:
170 RebaseInfoAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
171 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { _encoded = true; }
172
173 // overrides of ld::Atom
174 virtual const char* name() const { return "rebase info"; }
175 // overrides of LinkEditAtom
176 virtual void encode() const;
177
178 private:
179 void encodeV1() const;
180
181 struct rebase_tmp
182 {
183 rebase_tmp(uint8_t op, uint64_t p1, uint64_t p2=0) : opcode(op), operand1(p1), operand2(p2) {}
184 uint8_t opcode;
185 uint64_t operand1;
186 uint64_t operand2;
187 };
188
189 typedef typename A::P P;
190 typedef typename A::P::E E;
191 typedef typename A::P::uint_t pint_t;
192
193 static ld::Section _s_section;
194 };
195
196 template <typename A>
197 ld::Section RebaseInfoAtom<A>::_s_section("__LINKEDIT", "__rebase", ld::Section::typeLinkEdit, true);
198
199
200 template <typename A>
201 void RebaseInfoAtom<A>::encode() const
202 {
203 // omit relocs if this was supposed to be PIE but PIE not possible
204 if ( _options.positionIndependentExecutable() && this->_writer.pieDisabled )
205 return;
206
207 // sort rebase info by type, then address
208 std::vector<OutputFile::RebaseInfo>& info = this->_writer._rebaseInfo;
209 if (info.empty())
210 return;
211
212 std::sort(info.begin(), info.end());
213
214 // use encoding based on target minOS
215 if ( _options.useLinkedListBinding() && !this->_writer._hasUnalignedFixup ) {
216 if ( info.back()._type != REBASE_TYPE_POINTER )
217 throw "unsupported rebase type with linked list opcodes";
218 // As the binding and rebasing are both linked lists, just use the binds
219 // to do everything.
220 } else {
221 encodeV1();
222 }
223 }
224
225
226 template <typename A>
227 void RebaseInfoAtom<A>::encodeV1() const
228 {
229 std::vector<OutputFile::RebaseInfo>& info = this->_writer._rebaseInfo;
230
231 // convert to temp encoding that can be more easily optimized
232 std::vector<rebase_tmp> mid;
233 uint64_t curSegStart = 0;
234 uint64_t curSegEnd = 0;
235 uint32_t curSegIndex = 0;
236 uint8_t type = 0;
237 uint64_t address = (uint64_t)(-1);
238 for (std::vector<OutputFile::RebaseInfo>::iterator it = info.begin(); it != info.end(); ++it) {
239 if ( type != it->_type ) {
240 mid.push_back(rebase_tmp(REBASE_OPCODE_SET_TYPE_IMM, it->_type));
241 type = it->_type;
242 }
243 if ( address != it->_address ) {
244 if ( (it->_address < curSegStart) || ( it->_address >= curSegEnd) ) {
245 if ( ! this->_writer.findSegment(this->_state, it->_address, &curSegStart, &curSegEnd, &curSegIndex) )
246 throw "binding address outside range of any segment";
247 mid.push_back(rebase_tmp(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, curSegIndex, it->_address - curSegStart));
248 }
249 else {
250 mid.push_back(rebase_tmp(REBASE_OPCODE_ADD_ADDR_ULEB, it->_address-address));
251 }
252 address = it->_address;
253 }
254 mid.push_back(rebase_tmp(REBASE_OPCODE_DO_REBASE_ULEB_TIMES, 1));
255 address += sizeof(pint_t);
256 if ( address >= curSegEnd )
257 address = 0;
258 }
259 mid.push_back(rebase_tmp(REBASE_OPCODE_DONE, 0));
260
261 // optimize phase 1, compress packed runs of pointers
262 rebase_tmp* dst = &mid[0];
263 for (const rebase_tmp* src = &mid[0]; src->opcode != REBASE_OPCODE_DONE; ++src) {
264 if ( (src->opcode == REBASE_OPCODE_DO_REBASE_ULEB_TIMES) && (src->operand1 == 1) ) {
265 *dst = *src++;
266 while (src->opcode == REBASE_OPCODE_DO_REBASE_ULEB_TIMES ) {
267 dst->operand1 += src->operand1;
268 ++src;
269 }
270 --src;
271 ++dst;
272 }
273 else {
274 *dst++ = *src;
275 }
276 }
277 dst->opcode = REBASE_OPCODE_DONE;
278
279 // optimize phase 2, combine rebase/add pairs
280 dst = &mid[0];
281 for (const rebase_tmp* src = &mid[0]; src->opcode != REBASE_OPCODE_DONE; ++src) {
282 if ( (src->opcode == REBASE_OPCODE_DO_REBASE_ULEB_TIMES)
283 && (src->operand1 == 1)
284 && (src[1].opcode == REBASE_OPCODE_ADD_ADDR_ULEB)) {
285 dst->opcode = REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB;
286 dst->operand1 = src[1].operand1;
287 ++src;
288 ++dst;
289 }
290 else {
291 *dst++ = *src;
292 }
293 }
294 dst->opcode = REBASE_OPCODE_DONE;
295
296 // optimize phase 3, compress packed runs of REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB with
297 // same addr delta into one REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB
298 dst = &mid[0];
299 for (const rebase_tmp* src = &mid[0]; src->opcode != REBASE_OPCODE_DONE; ++src) {
300 uint64_t delta = src->operand1;
301 if ( (src->opcode == REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB)
302 && (src[1].opcode == REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB)
303 && (src[2].opcode == REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB)
304 && (src[1].operand1 == delta)
305 && (src[2].operand1 == delta) ) {
306 // found at least three in a row, this is worth compressing
307 dst->opcode = REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB;
308 dst->operand1 = 1;
309 dst->operand2 = delta;
310 ++src;
311 while ( (src->opcode == REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB)
312 && (src->operand1 == delta) ) {
313 dst->operand1++;
314 ++src;
315 }
316 --src;
317 ++dst;
318 }
319 else {
320 *dst++ = *src;
321 }
322 }
323 dst->opcode = REBASE_OPCODE_DONE;
324
325 // optimize phase 4, use immediate encodings
326 for (rebase_tmp* p = &mid[0]; p->opcode != REBASE_OPCODE_DONE; ++p) {
327 if ( (p->opcode == REBASE_OPCODE_ADD_ADDR_ULEB)
328 && (p->operand1 < (15*sizeof(pint_t)))
329 && ((p->operand1 % sizeof(pint_t)) == 0) ) {
330 p->opcode = REBASE_OPCODE_ADD_ADDR_IMM_SCALED;
331 p->operand1 = p->operand1/sizeof(pint_t);
332 }
333 else if ( (p->opcode == REBASE_OPCODE_DO_REBASE_ULEB_TIMES) && (p->operand1 < 15) ) {
334 p->opcode = REBASE_OPCODE_DO_REBASE_IMM_TIMES;
335 }
336 }
337
338 // convert to compressed encoding
339 const static bool log = false;
340 this->_encodedData.reserve(info.size()*2);
341 bool done = false;
342 for (typename std::vector<rebase_tmp>::iterator it = mid.begin(); !done && it != mid.end() ; ++it) {
343 switch ( it->opcode ) {
344 case REBASE_OPCODE_DONE:
345 if ( log ) fprintf(stderr, "REBASE_OPCODE_DONE()\n");
346 done = true;
347 break;
348 case REBASE_OPCODE_SET_TYPE_IMM:
349 if ( log ) fprintf(stderr, "REBASE_OPCODE_SET_TYPE_IMM(%lld)\n", it->operand1);
350 this->_encodedData.append_byte(REBASE_OPCODE_SET_TYPE_IMM | it->operand1);
351 break;
352 case REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
353 if ( log ) fprintf(stderr, "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB(%lld, 0x%llX)\n", it->operand1, it->operand2);
354 this->_encodedData.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | it->operand1);
355 this->_encodedData.append_uleb128(it->operand2);
356 break;
357 case REBASE_OPCODE_ADD_ADDR_ULEB:
358 if ( log ) fprintf(stderr, "REBASE_OPCODE_ADD_ADDR_ULEB(0x%llX)\n", it->operand1);
359 this->_encodedData.append_byte(REBASE_OPCODE_ADD_ADDR_ULEB);
360 this->_encodedData.append_uleb128(it->operand1);
361 break;
362 case REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
363 if ( log ) fprintf(stderr, "REBASE_OPCODE_ADD_ADDR_IMM_SCALED(%lld=0x%llX)\n", it->operand1, it->operand1*sizeof(pint_t));
364 this->_encodedData.append_byte(REBASE_OPCODE_ADD_ADDR_IMM_SCALED | it->operand1 );
365 break;
366 case REBASE_OPCODE_DO_REBASE_IMM_TIMES:
367 if ( log ) fprintf(stderr, "REBASE_OPCODE_DO_REBASE_IMM_TIMES(%lld)\n", it->operand1);
368 this->_encodedData.append_byte(REBASE_OPCODE_DO_REBASE_IMM_TIMES | it->operand1);
369 break;
370 case REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
371 if ( log ) fprintf(stderr, "REBASE_OPCODE_DO_REBASE_ULEB_TIMES(%lld)\n", it->operand1);
372 this->_encodedData.append_byte(REBASE_OPCODE_DO_REBASE_ULEB_TIMES);
373 this->_encodedData.append_uleb128(it->operand1);
374 break;
375 case REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
376 if ( log ) fprintf(stderr, "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB(0x%llX)\n", it->operand1);
377 this->_encodedData.append_byte(REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB);
378 this->_encodedData.append_uleb128(it->operand1);
379 break;
380 case REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
381 if ( log ) fprintf(stderr, "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB(%lld, %lld)\n", it->operand1, it->operand2);
382 this->_encodedData.append_byte(REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB);
383 this->_encodedData.append_uleb128(it->operand1);
384 this->_encodedData.append_uleb128(it->operand2);
385 break;
386 }
387 }
388
389
390 // align to pointer size
391 this->_encodedData.pad_to_size(sizeof(pint_t));
392
393 this->_encoded = true;
394
395 if (log) fprintf(stderr, "total rebase info size = %ld\n", this->_encodedData.size());
396 }
397
398
399 template <typename A>
400 class BindingInfoAtom : public LinkEditAtom
401 {
402 public:
403 BindingInfoAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
404 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { }
405
406 // overrides of ld::Atom
407 virtual const char* name() const { return "binding info"; }
408 // overrides of LinkEditAtom
409 virtual void encode() const;
410
411
412 private:
413 void encodeV1() const;
414 void encodeV2() const;
415
416 typedef typename A::P P;
417 typedef typename A::P::E E;
418 typedef typename A::P::uint_t pint_t;
419
420 struct binding_tmp
421 {
422 binding_tmp(uint8_t op, uint64_t p1, uint64_t p2=0, const char* s=NULL)
423 : opcode(op), operand1(p1), operand2(p2), name(s) {}
424 uint8_t opcode;
425 uint64_t operand1;
426 uint64_t operand2;
427 const char* name;
428 };
429
430 static ld::Section _s_section;
431 };
432
433 template <typename A>
434 ld::Section BindingInfoAtom<A>::_s_section("__LINKEDIT", "__binding", ld::Section::typeLinkEdit, true);
435
436
437 template <typename A>
438 void BindingInfoAtom<A>::encode() const
439 {
440 // use encoding based on target minOS
441 if ( _options.useLinkedListBinding() && !this->_writer._hasUnalignedFixup ) {
442 encodeV2();
443 } else {
444 encodeV1();
445 }
446 }
447
448
449 template <typename A>
450 void BindingInfoAtom<A>::encodeV1() const
451 {
452 // sort by library, symbol, type, then address
453 std::vector<OutputFile::BindingInfo>& info = this->_writer._bindingInfo;
454 std::sort(info.begin(), info.end());
455
456 // convert to temp encoding that can be more easily optimized
457 std::vector<binding_tmp> mid;
458 uint64_t curSegStart = 0;
459 uint64_t curSegEnd = 0;
460 uint32_t curSegIndex = 0;
461 int ordinal = 0x80000000;
462 const char* symbolName = NULL;
463 uint8_t type = 0;
464 uint64_t address = (uint64_t)(-1);
465 int64_t addend = 0;
466 for (std::vector<OutputFile::BindingInfo>::const_iterator it = info.begin(); it != info.end(); ++it) {
467 if ( ordinal != it->_libraryOrdinal ) {
468 if ( it->_libraryOrdinal <= 0 ) {
469 // special lookups are encoded as negative numbers in BindingInfo
470 mid.push_back(binding_tmp(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM, it->_libraryOrdinal));
471 }
472 else {
473 mid.push_back(binding_tmp(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB, it->_libraryOrdinal));
474 }
475 ordinal = it->_libraryOrdinal;
476 }
477 if ( symbolName != it->_symbolName ) {
478 mid.push_back(binding_tmp(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM, it->_flags, 0, it->_symbolName));
479 symbolName = it->_symbolName;
480 }
481 if ( type != it->_type ) {
482 mid.push_back(binding_tmp(BIND_OPCODE_SET_TYPE_IMM, it->_type));
483 type = it->_type;
484 }
485 if ( address != it->_address ) {
486 if ( (it->_address < curSegStart) || ( it->_address >= curSegEnd) ) {
487 if ( ! this->_writer.findSegment(this->_state, it->_address, &curSegStart, &curSegEnd, &curSegIndex) )
488 throw "binding address outside range of any segment";
489 mid.push_back(binding_tmp(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, curSegIndex, it->_address - curSegStart));
490 }
491 else {
492 mid.push_back(binding_tmp(BIND_OPCODE_ADD_ADDR_ULEB, it->_address-address));
493 }
494 address = it->_address;
495 }
496 if ( addend != it->_addend ) {
497 mid.push_back(binding_tmp(BIND_OPCODE_SET_ADDEND_SLEB, it->_addend));
498 addend = it->_addend;
499 }
500 mid.push_back(binding_tmp(BIND_OPCODE_DO_BIND, 0));
501 address += sizeof(pint_t);
502 }
503 mid.push_back(binding_tmp(BIND_OPCODE_DONE, 0));
504
505
506 // optimize phase 1, combine bind/add pairs
507 binding_tmp* dst = &mid[0];
508 for (const binding_tmp* src = &mid[0]; src->opcode != BIND_OPCODE_DONE; ++src) {
509 if ( (src->opcode == BIND_OPCODE_DO_BIND)
510 && (src[1].opcode == BIND_OPCODE_ADD_ADDR_ULEB) ) {
511 dst->opcode = BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB;
512 dst->operand1 = src[1].operand1;
513 ++src;
514 ++dst;
515 }
516 else {
517 *dst++ = *src;
518 }
519 }
520 dst->opcode = BIND_OPCODE_DONE;
521
522 // optimize phase 2, compress packed runs of BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB with
523 // same addr delta into one BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB
524 dst = &mid[0];
525 for (const binding_tmp* src = &mid[0]; src->opcode != BIND_OPCODE_DONE; ++src) {
526 uint64_t delta = src->operand1;
527 if ( (src->opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
528 && (src[1].opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
529 && (src[1].operand1 == delta) ) {
530 // found at least two in a row, this is worth compressing
531 dst->opcode = BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB;
532 dst->operand1 = 1;
533 dst->operand2 = delta;
534 ++src;
535 while ( (src->opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
536 && (src->operand1 == delta) ) {
537 dst->operand1++;
538 ++src;
539 }
540 --src;
541 ++dst;
542 }
543 else {
544 *dst++ = *src;
545 }
546 }
547 dst->opcode = BIND_OPCODE_DONE;
548
549 // optimize phase 3, use immediate encodings
550 for (binding_tmp* p = &mid[0]; p->opcode != REBASE_OPCODE_DONE; ++p) {
551 if ( (p->opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
552 && (p->operand1 < (15*sizeof(pint_t)))
553 && ((p->operand1 % sizeof(pint_t)) == 0) ) {
554 p->opcode = BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED;
555 p->operand1 = p->operand1/sizeof(pint_t);
556 }
557 else if ( (p->opcode == BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB) && (p->operand1 <= 15) ) {
558 p->opcode = BIND_OPCODE_SET_DYLIB_ORDINAL_IMM;
559 }
560 }
561 dst->opcode = BIND_OPCODE_DONE;
562
563 // convert to compressed encoding
564 const static bool log = false;
565 this->_encodedData.reserve(info.size()*2);
566 bool done = false;
567 for (typename std::vector<binding_tmp>::iterator it = mid.begin(); !done && it != mid.end() ; ++it) {
568 switch ( it->opcode ) {
569 case BIND_OPCODE_DONE:
570 if ( log ) fprintf(stderr, "BIND_OPCODE_DONE()\n");
571 done = true;
572 break;
573 case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
574 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM(%lld)\n", it->operand1);
575 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | it->operand1);
576 break;
577 case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
578 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB(%lld)\n", it->operand1);
579 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
580 this->_encodedData.append_uleb128(it->operand1);
581 break;
582 case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
583 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM(%lld)\n", it->operand1);
584 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | (it->operand1 & BIND_IMMEDIATE_MASK));
585 break;
586 case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
587 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM(0x%0llX, %s)\n", it->operand1, it->name);
588 this->_encodedData.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | it->operand1);
589 this->_encodedData.append_string(it->name);
590 break;
591 case BIND_OPCODE_SET_TYPE_IMM:
592 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_TYPE_IMM(%lld)\n", it->operand1);
593 this->_encodedData.append_byte(BIND_OPCODE_SET_TYPE_IMM | it->operand1);
594 break;
595 case BIND_OPCODE_SET_ADDEND_SLEB:
596 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_ADDEND_SLEB(%lld)\n", it->operand1);
597 this->_encodedData.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
598 this->_encodedData.append_sleb128(it->operand1);
599 break;
600 case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
601 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB(%lld, 0x%llX)\n", it->operand1, it->operand2);
602 this->_encodedData.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | it->operand1);
603 this->_encodedData.append_uleb128(it->operand2);
604 break;
605 case BIND_OPCODE_ADD_ADDR_ULEB:
606 if ( log ) fprintf(stderr, "BIND_OPCODE_ADD_ADDR_ULEB(0x%llX)\n", it->operand1);
607 this->_encodedData.append_byte(BIND_OPCODE_ADD_ADDR_ULEB);
608 this->_encodedData.append_uleb128(it->operand1);
609 break;
610 case BIND_OPCODE_DO_BIND:
611 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND()\n");
612 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND);
613 break;
614 case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
615 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB(0x%llX)\n", it->operand1);
616 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB);
617 this->_encodedData.append_uleb128(it->operand1);
618 break;
619 case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
620 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED(%lld=0x%llX)\n", it->operand1, it->operand1*sizeof(pint_t));
621 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED | it->operand1 );
622 break;
623 case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
624 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB(%lld, %lld)\n", it->operand1, it->operand2);
625 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB);
626 this->_encodedData.append_uleb128(it->operand1);
627 this->_encodedData.append_uleb128(it->operand2);
628 break;
629 }
630 }
631
632 // align to pointer size
633 this->_encodedData.pad_to_size(sizeof(pint_t));
634
635 this->_encoded = true;
636
637 if (log) fprintf(stderr, "total binding info size = %ld\n", this->_encodedData.size());
638 }
639
640 template <typename A>
641 void BindingInfoAtom<A>::encodeV2() const
642 {
643 std::vector<OutputFile::BindingInfo>& bindInfo = this->_writer._bindingInfo;
644 std::vector<OutputFile::RebaseInfo>& rebaseInfo = this->_writer._rebaseInfo;
645 const static bool log = false;
646
647 std::sort(bindInfo.begin(), bindInfo.end());
648
649 // convert to temp encoding that can be more easily optimized
650 std::vector<binding_tmp> mid;
651 uint64_t curSegStart = 0;
652 uint64_t curSegEnd = 0;
653 uint32_t curSegIndex = 0;
654 int ordinal = 0x80000000;
655 const char* symbolName = NULL;
656 uint8_t type = 0;
657 uint64_t address = (uint64_t)(-1);
658 int64_t addend = 0;
659 uint64_t numBinds = (uint64_t)(-1);
660 for (std::vector<OutputFile::BindingInfo>::iterator it = bindInfo.begin(); it != bindInfo.end(); ++it) {
661 bool madeChange = false;
662 if ( ordinal != it->_libraryOrdinal ) {
663 if ( it->_libraryOrdinal <= 0 ) {
664 // special lookups are encoded as negative numbers in BindingInfo
665 mid.push_back(binding_tmp(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM, it->_libraryOrdinal));
666 }
667 else if ( it->_libraryOrdinal <= 15 ) {
668 mid.push_back(binding_tmp(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM, it->_libraryOrdinal));
669 }
670 else {
671 mid.push_back(binding_tmp(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB, it->_libraryOrdinal));
672 }
673 ordinal = it->_libraryOrdinal;
674 madeChange = true;
675 }
676 if ( symbolName != it->_symbolName ) {
677 mid.push_back(binding_tmp(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM, it->_flags, 0, it->_symbolName));
678 symbolName = it->_symbolName;
679 madeChange = true;
680 }
681 if ( type != it->_type ) {
682 if ( it->_type != BIND_TYPE_POINTER )
683 throw "unsupported bind type with linked list opcodes";
684 mid.push_back(binding_tmp(BIND_OPCODE_SET_TYPE_IMM, it->_type));
685 type = it->_type;
686 madeChange = true;
687 }
688 if ( address != it->_address ) {
689 // Note, we don't push the addresses here. That is all done later with the threaded chains
690 if ( (it->_address < curSegStart) || ( it->_address >= curSegEnd) ) {
691 if ( ! this->_writer.findSegment(this->_state, it->_address, &curSegStart, &curSegEnd, &curSegIndex) )
692 throw "binding address outside range of any segment";
693 }
694 address = it->_address;
695 }
696 if ( addend != it->_addend ) {
697 mid.push_back(binding_tmp(BIND_OPCODE_SET_ADDEND_SLEB, it->_addend));
698 addend = it->_addend;
699 madeChange = true;
700 }
701
702 if (madeChange) {
703 ++numBinds;
704 mid.push_back(binding_tmp(BIND_OPCODE_DO_BIND, 0));
705 }
706 it->_threadedBindOrdinal = numBinds;
707 }
708
709 // We can only support 2^16 bind ordinals.
710 if ( (numBinds > 0x10000) && (numBinds != (uint64_t)(-1)) )
711 throwf("too many binds (%llu). The limit is 65536", numBinds);
712
713 // Now that we have the bind ordinal table populate, set the page starts.
714
715 std::vector<int64_t>& threadedRebaseBindIndices = this->_writer._threadedRebaseBindIndices;
716 threadedRebaseBindIndices.reserve(bindInfo.size() + rebaseInfo.size());
717
718 for (int64_t i = 0, e = rebaseInfo.size(); i != e; ++i)
719 threadedRebaseBindIndices.push_back(-i);
720
721 for (int64_t i = 0, e = bindInfo.size(); i != e; ++i)
722 threadedRebaseBindIndices.push_back(i + 1);
723
724 // Now sort the entries by address.
725 std::sort(threadedRebaseBindIndices.begin(), threadedRebaseBindIndices.end(),
726 [&rebaseInfo, &bindInfo](int64_t indexA, int64_t indexB) {
727 if (indexA == indexB)
728 return false;
729 uint64_t addressA = indexA <= 0 ? rebaseInfo[-indexA]._address : bindInfo[indexA - 1]._address;
730 uint64_t addressB = indexB <= 0 ? rebaseInfo[-indexB]._address : bindInfo[indexB - 1]._address;
731 assert(addressA != addressB);
732 return addressA < addressB;
733 });
734
735 curSegStart = 0;
736 curSegEnd = 0;
737 curSegIndex = 0;
738 uint64_t prevPageIndex = 0;
739 for (int64_t entryIndex : threadedRebaseBindIndices) {
740 OutputFile::RebaseInfo* rebase = nullptr;
741 OutputFile::BindingInfo* bind = nullptr;
742 uint64_t address = 0;
743 if (entryIndex <= 0) {
744 rebase = &rebaseInfo[-entryIndex];
745 address = rebase->_address;
746 } else {
747 bind = &bindInfo[entryIndex - 1];
748 address = bind->_address;
749 }
750 assert((address & 7) == 0);
751
752 bool newSegment = false;
753 if ( (address < curSegStart) || ( address >= curSegEnd) ) {
754 // Start of a new segment.
755 if ( ! this->_writer.findSegment(this->_state, address, &curSegStart, &curSegEnd, &curSegIndex) )
756 throw "binding address outside range of any segment";
757 newSegment = true;
758 }
759
760 // At this point we know we have the page starts array space reserved
761 // so set the page start for this entry if we haven't got one already.
762 uint64_t pageIndex = ( address - curSegStart ) / 4096;
763 if ( newSegment || (pageIndex != prevPageIndex) ) {
764 mid.push_back(binding_tmp(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, curSegIndex, address - curSegStart));
765 mid.push_back(binding_tmp(BIND_OPCODE_THREADED | BIND_SUBOPCODE_THREADED_APPLY, 0));
766 }
767 prevPageIndex = pageIndex;
768 }
769 mid.push_back(binding_tmp(BIND_OPCODE_DONE, 0));
770
771 // convert to compressed encoding
772 this->_encodedData.reserve(bindInfo.size()*2);
773
774 // First push the total number of binds so that we can allocate space for this in dyld.
775 if ( log ) fprintf(stderr, "BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB(%lld)\n", numBinds + 1);
776 this->_encodedData.append_byte(BIND_OPCODE_THREADED | BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB);
777 this->_encodedData.append_uleb128(numBinds + 1);
778
779 bool done = false;
780 for (typename std::vector<binding_tmp>::iterator it = mid.begin(); !done && it != mid.end() ; ++it) {
781 switch ( it->opcode ) {
782 case BIND_OPCODE_DONE:
783 if ( log ) fprintf(stderr, "BIND_OPCODE_DONE()\n");
784 done = true;
785 break;
786 case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
787 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM(%lld)\n", it->operand1);
788 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | it->operand1);
789 break;
790 case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
791 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB(%lld)\n", it->operand1);
792 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
793 this->_encodedData.append_uleb128(it->operand1);
794 break;
795 case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
796 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM(%lld)\n", it->operand1);
797 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | (it->operand1 & BIND_IMMEDIATE_MASK));
798 break;
799 case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
800 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM(0x%0llX, %s)\n", it->operand1, it->name);
801 this->_encodedData.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | it->operand1);
802 this->_encodedData.append_string(it->name);
803 break;
804 case BIND_OPCODE_SET_TYPE_IMM:
805 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_TYPE_IMM(%lld)\n", it->operand1);
806 this->_encodedData.append_byte(BIND_OPCODE_SET_TYPE_IMM | it->operand1);
807 break;
808 case BIND_OPCODE_SET_ADDEND_SLEB:
809 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_ADDEND_SLEB(%lld)\n", it->operand1);
810 this->_encodedData.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
811 this->_encodedData.append_sleb128(it->operand1);
812 break;
813 case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
814 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB(%lld, 0x%llX)\n", it->operand1, it->operand2);
815 this->_encodedData.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | it->operand1);
816 this->_encodedData.append_uleb128(it->operand2);
817 break;
818 case BIND_OPCODE_ADD_ADDR_ULEB:
819 if ( log ) fprintf(stderr, "BIND_OPCODE_ADD_ADDR_ULEB(0x%llX)\n", it->operand1);
820 this->_encodedData.append_byte(BIND_OPCODE_ADD_ADDR_ULEB);
821 this->_encodedData.append_uleb128(it->operand1);
822 break;
823 case BIND_OPCODE_DO_BIND:
824 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND()\n");
825 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND);
826 break;
827 case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
828 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB(0x%llX)\n", it->operand1);
829 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB);
830 this->_encodedData.append_uleb128(it->operand1);
831 break;
832 case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
833 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED(%lld=0x%llX)\n", it->operand1, it->operand1*sizeof(pint_t));
834 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED | it->operand1 );
835 break;
836 case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
837 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB(%lld, %lld)\n", it->operand1, it->operand2);
838 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB);
839 this->_encodedData.append_uleb128(it->operand1);
840 this->_encodedData.append_uleb128(it->operand2);
841 break;
842 case BIND_OPCODE_THREADED | BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB:
843 if ( log ) fprintf(stderr, "BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB(%lld)\n", it->operand1);
844 this->_encodedData.append_byte(BIND_OPCODE_THREADED | BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB);
845 this->_encodedData.append_uleb128(it->operand1);
846 break;
847 case BIND_OPCODE_THREADED | BIND_SUBOPCODE_THREADED_APPLY:
848 this->_encodedData.append_byte(BIND_OPCODE_THREADED | BIND_SUBOPCODE_THREADED_APPLY);
849 if ( log ) fprintf(stderr, "BIND_SUBOPCODE_THREADED_APPLY()\n");
850 break;
851 }
852 }
853
854 // align to pointer size
855 this->_encodedData.append_byte(BIND_OPCODE_DONE);
856 this->_encodedData.pad_to_size(sizeof(pint_t));
857
858 this->_encoded = true;
859
860 if (log) fprintf(stderr, "total binding info size = %ld\n", this->_encodedData.size());
861 }
862
863
864
865 template <typename A>
866 class WeakBindingInfoAtom : public LinkEditAtom
867 {
868 public:
869 WeakBindingInfoAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
870 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { _encoded = true; }
871
872 // overrides of ld::Atom
873 virtual const char* name() const { return "weak binding info"; }
874 // overrides of LinkEditAtom
875 virtual void encode() const;
876
877 private:
878 typedef typename A::P P;
879 typedef typename A::P::E E;
880 typedef typename A::P::uint_t pint_t;
881
882 struct WeakBindingSorter
883 {
884 bool operator()(const OutputFile::BindingInfo& left, const OutputFile::BindingInfo& right)
885 {
886 // sort by symbol, type, address
887 if ( left._symbolName != right._symbolName )
888 return ( strcmp(left._symbolName, right._symbolName) < 0 );
889 if ( left._type != right._type )
890 return (left._type < right._type);
891 return (left._address < right._address);
892 }
893 };
894
895 struct binding_tmp
896 {
897 binding_tmp(uint8_t op, uint64_t p1, uint64_t p2=0, const char* s=NULL)
898 : opcode(op), operand1(p1), operand2(p2), name(s) {}
899 uint8_t opcode;
900 uint64_t operand1;
901 uint64_t operand2;
902 const char* name;
903 };
904
905 static ld::Section _s_section;
906 };
907
908 template <typename A>
909 ld::Section WeakBindingInfoAtom<A>::_s_section("__LINKEDIT", "__weak_binding", ld::Section::typeLinkEdit, true);
910
911
912 template <typename A>
913 void WeakBindingInfoAtom<A>::encode() const
914 {
915 // sort by symbol, type, address
916 std::vector<OutputFile::BindingInfo>& info = this->_writer._weakBindingInfo;
917 if ( info.size() == 0 ) {
918 // short circuit if no weak binding needed
919 this->_encoded = true;
920 return;
921 }
922 std::sort(info.begin(), info.end(), WeakBindingSorter());
923
924 // convert to temp encoding that can be more easily optimized
925 std::vector<binding_tmp> mid;
926 mid.reserve(info.size());
927 uint64_t curSegStart = 0;
928 uint64_t curSegEnd = 0;
929 uint32_t curSegIndex = 0;
930 const char* symbolName = NULL;
931 uint8_t type = 0;
932 uint64_t address = (uint64_t)(-1);
933 int64_t addend = 0;
934 for (typename std::vector<OutputFile::BindingInfo>::const_iterator it = info.begin(); it != info.end(); ++it) {
935 if ( symbolName != it->_symbolName ) {
936 mid.push_back(binding_tmp(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM, it->_flags, 0, it->_symbolName));
937 symbolName = it->_symbolName;
938 }
939 // non-weak symbols just have BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
940 // weak symbols have SET_SEG, ADD_ADDR, SET_ADDED, DO_BIND
941 if ( it->_type != BIND_TYPE_OVERRIDE_OF_WEAKDEF_IN_DYLIB ) {
942 if ( type != it->_type ) {
943 mid.push_back(binding_tmp(BIND_OPCODE_SET_TYPE_IMM, it->_type));
944 type = it->_type;
945 }
946 if ( address != it->_address ) {
947 if ( (it->_address < curSegStart) || ( it->_address >= curSegEnd) ) {
948 if ( ! this->_writer.findSegment(this->_state, it->_address, &curSegStart, &curSegEnd, &curSegIndex) )
949 throw "binding address outside range of any segment";
950 mid.push_back(binding_tmp(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, curSegIndex, it->_address - curSegStart));
951 }
952 else {
953 mid.push_back(binding_tmp(BIND_OPCODE_ADD_ADDR_ULEB, it->_address-address));
954 }
955 address = it->_address;
956 }
957 if ( addend != it->_addend ) {
958 mid.push_back(binding_tmp(BIND_OPCODE_SET_ADDEND_SLEB, it->_addend));
959 addend = it->_addend;
960 }
961 mid.push_back(binding_tmp(BIND_OPCODE_DO_BIND, 0));
962 address += sizeof(pint_t);
963 }
964 }
965 mid.push_back(binding_tmp(BIND_OPCODE_DONE, 0));
966
967
968 // optimize phase 1, combine bind/add pairs
969 binding_tmp* dst = &mid[0];
970 for (const binding_tmp* src = &mid[0]; src->opcode != BIND_OPCODE_DONE; ++src) {
971 if ( (src->opcode == BIND_OPCODE_DO_BIND)
972 && (src[1].opcode == BIND_OPCODE_ADD_ADDR_ULEB) ) {
973 dst->opcode = BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB;
974 dst->operand1 = src[1].operand1;
975 ++src;
976 ++dst;
977 }
978 else {
979 *dst++ = *src;
980 }
981 }
982 dst->opcode = BIND_OPCODE_DONE;
983
984 // optimize phase 2, compress packed runs of BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB with
985 // same addr delta into one BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB
986 dst = &mid[0];
987 for (const binding_tmp* src = &mid[0]; src->opcode != BIND_OPCODE_DONE; ++src) {
988 uint64_t delta = src->operand1;
989 if ( (src->opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
990 && (src[1].opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
991 && (src[1].operand1 == delta) ) {
992 // found at least two in a row, this is worth compressing
993 dst->opcode = BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB;
994 dst->operand1 = 1;
995 dst->operand2 = delta;
996 ++src;
997 while ( (src->opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
998 && (src->operand1 == delta) ) {
999 dst->operand1++;
1000 ++src;
1001 }
1002 --src;
1003 ++dst;
1004 }
1005 else {
1006 *dst++ = *src;
1007 }
1008 }
1009 dst->opcode = BIND_OPCODE_DONE;
1010
1011 // optimize phase 3, use immediate encodings
1012 for (binding_tmp* p = &mid[0]; p->opcode != REBASE_OPCODE_DONE; ++p) {
1013 if ( (p->opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
1014 && (p->operand1 < (15*sizeof(pint_t)))
1015 && ((p->operand1 % sizeof(pint_t)) == 0) ) {
1016 p->opcode = BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED;
1017 p->operand1 = p->operand1/sizeof(pint_t);
1018 }
1019 }
1020 dst->opcode = BIND_OPCODE_DONE;
1021
1022
1023 // convert to compressed encoding
1024 const static bool log = false;
1025 this->_encodedData.reserve(info.size()*2);
1026 bool done = false;
1027 for (typename std::vector<binding_tmp>::iterator it = mid.begin(); !done && it != mid.end() ; ++it) {
1028 switch ( it->opcode ) {
1029 case BIND_OPCODE_DONE:
1030 if ( log ) fprintf(stderr, "BIND_OPCODE_DONE()\n");
1031 this->_encodedData.append_byte(BIND_OPCODE_DONE);
1032 done = true;
1033 break;
1034 case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
1035 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM(%lld)\n", it->operand1);
1036 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | it->operand1);
1037 break;
1038 case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
1039 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB(%lld)\n", it->operand1);
1040 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
1041 this->_encodedData.append_uleb128(it->operand1);
1042 break;
1043 case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
1044 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM(%lld)\n", it->operand1);
1045 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | (it->operand1 & BIND_IMMEDIATE_MASK));
1046 break;
1047 case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
1048 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM(0x%0llX, %s)\n", it->operand1, it->name);
1049 this->_encodedData.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | it->operand1);
1050 this->_encodedData.append_string(it->name);
1051 break;
1052 case BIND_OPCODE_SET_TYPE_IMM:
1053 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_TYPE_IMM(%lld)\n", it->operand1);
1054 this->_encodedData.append_byte(BIND_OPCODE_SET_TYPE_IMM | it->operand1);
1055 break;
1056 case BIND_OPCODE_SET_ADDEND_SLEB:
1057 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_ADDEND_SLEB(%lld)\n", it->operand1);
1058 this->_encodedData.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
1059 this->_encodedData.append_sleb128(it->operand1);
1060 break;
1061 case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
1062 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB(%lld, 0x%llX)\n", it->operand1, it->operand2);
1063 this->_encodedData.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | it->operand1);
1064 this->_encodedData.append_uleb128(it->operand2);
1065 break;
1066 case BIND_OPCODE_ADD_ADDR_ULEB:
1067 if ( log ) fprintf(stderr, "BIND_OPCODE_ADD_ADDR_ULEB(0x%llX)\n", it->operand1);
1068 this->_encodedData.append_byte(BIND_OPCODE_ADD_ADDR_ULEB);
1069 this->_encodedData.append_uleb128(it->operand1);
1070 break;
1071 case BIND_OPCODE_DO_BIND:
1072 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND()\n");
1073 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND);
1074 break;
1075 case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
1076 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB(0x%llX)\n", it->operand1);
1077 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB);
1078 this->_encodedData.append_uleb128(it->operand1);
1079 break;
1080 case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
1081 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED(%lld=0x%llX)\n", it->operand1, it->operand1*sizeof(pint_t));
1082 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED | it->operand1 );
1083 break;
1084 case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
1085 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB(%lld, %lld)\n", it->operand1, it->operand2);
1086 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB);
1087 this->_encodedData.append_uleb128(it->operand1);
1088 this->_encodedData.append_uleb128(it->operand2);
1089 break;
1090 }
1091 }
1092
1093 // align to pointer size
1094 this->_encodedData.pad_to_size(sizeof(pint_t));
1095
1096 this->_encoded = true;
1097
1098 if (log) fprintf(stderr, "total weak binding info size = %ld\n", this->_encodedData.size());
1099
1100 }
1101
1102
1103
1104 template <typename A>
1105 class LazyBindingInfoAtom : public LinkEditAtom
1106 {
1107 public:
1108 LazyBindingInfoAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
1109 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) {_encoded = true; }
1110
1111 // overrides of ld::Atom
1112 virtual const char* name() const { return "lazy binding info"; }
1113 // overrides of LinkEditAtom
1114 virtual void encode() const;
1115
1116 private:
1117 typedef typename A::P P;
1118 typedef typename A::P::E E;
1119 typedef typename A::P::uint_t pint_t;
1120
1121 static ld::Section _s_section;
1122 };
1123
1124 template <typename A>
1125 ld::Section LazyBindingInfoAtom<A>::_s_section("__LINKEDIT", "__lazy_binding", ld::Section::typeLinkEdit, true);
1126
1127
1128
1129 template <typename A>
1130 void LazyBindingInfoAtom<A>::encode() const
1131 {
1132 // stream all lazy bindings and record start offsets
1133 std::vector<OutputFile::BindingInfo>& info = this->_writer._lazyBindingInfo;
1134 for (std::vector<OutputFile::BindingInfo>::const_iterator it = info.begin(); it != info.end(); ++it) {
1135 // record start offset for use by stub helper
1136 this->_writer.setLazyBindingInfoOffset(it->_address, this->_encodedData.size());
1137
1138 // write address to bind
1139 uint64_t segStart = 0;
1140 uint64_t segEnd = 0;
1141 uint32_t segIndex = 0;
1142 if ( ! this->_writer.findSegment(this->_state, it->_address, &segStart, &segEnd, &segIndex) )
1143 throw "lazy binding address outside range of any segment";
1144 this->_encodedData.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | segIndex);
1145 this->_encodedData.append_uleb128(it->_address - segStart);
1146
1147 // write ordinal
1148 if ( it->_libraryOrdinal <= 0 ) {
1149 // special lookups are encoded as negative numbers in BindingInfo
1150 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | (it->_libraryOrdinal & BIND_IMMEDIATE_MASK) );
1151 }
1152 else if ( it->_libraryOrdinal <= 15 ) {
1153 // small ordinals are encoded in opcode
1154 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | it->_libraryOrdinal);
1155 }
1156 else {
1157 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
1158 this->_encodedData.append_uleb128(it->_libraryOrdinal);
1159 }
1160 // write symbol name
1161 this->_encodedData.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | it->_flags);
1162 this->_encodedData.append_string(it->_symbolName);
1163 // write do bind
1164 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND);
1165 this->_encodedData.append_byte(BIND_OPCODE_DONE);
1166 }
1167
1168 // align to pointer size
1169 this->_encodedData.pad_to_size(sizeof(pint_t));
1170
1171 this->_encoded = true;
1172 //fprintf(stderr, "lazy binding info size = %ld, for %ld entries\n", _encodedData.size(), allLazys.size());
1173 }
1174
1175
1176
1177 template <typename A>
1178 class ExportInfoAtom : public LinkEditAtom
1179 {
1180 public:
1181 ExportInfoAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
1182 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { _encoded = true; }
1183
1184 // overrides of ld::Atom
1185 virtual const char* name() const { return "export info"; }
1186 // overrides of LinkEditAtom
1187 virtual void encode() const;
1188
1189 private:
1190 typedef typename A::P P;
1191 typedef typename A::P::E E;
1192 typedef typename A::P::uint_t pint_t;
1193
1194 const ld::Atom* stubForResolverFunction(const ld::Atom* resolver) const;
1195
1196 struct TrieEntriesSorter
1197 {
1198 TrieEntriesSorter(const Options& o) : _options(o) {}
1199
1200 bool operator()(const mach_o::trie::Entry& left, const mach_o::trie::Entry& right)
1201 {
1202 unsigned int leftOrder;
1203 unsigned int rightOrder;
1204 _options.exportedSymbolOrder(left.name, &leftOrder);
1205 _options.exportedSymbolOrder(right.name, &rightOrder);
1206 if ( leftOrder != rightOrder )
1207 return (leftOrder < rightOrder);
1208 else
1209 return (left.address < right.address);
1210 }
1211 private:
1212 const Options& _options;
1213 };
1214
1215 static ld::Section _s_section;
1216 };
1217
1218 template <typename A>
1219 ld::Section ExportInfoAtom<A>::_s_section("__LINKEDIT", "__export", ld::Section::typeLinkEdit, true);
1220
1221 template <typename A>
1222 const ld::Atom* ExportInfoAtom<A>::stubForResolverFunction(const ld::Atom* resolver) const
1223 {
1224 for (std::vector<ld::Internal::FinalSection*>::iterator sit = _state.sections.begin(); sit != _state.sections.end(); ++sit) {
1225 ld::Internal::FinalSection* sect = *sit;
1226 if ( (sect->type() == ld::Section::typeStub) || (sect->type() == ld::Section::typeStubClose) ) {
1227 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
1228 const ld::Atom* atom = *ait;
1229 if ( strcmp(atom->name(), resolver->name()) == 0 )
1230 return atom;
1231 }
1232 }
1233 }
1234 assert(0 && "no stub for resolver function");
1235 return NULL;
1236 }
1237
1238
1239 template <typename A>
1240 void ExportInfoAtom<A>::encode() const
1241 {
1242 // make vector of mach_o::trie::Entry for all exported symbols
1243 std::vector<const ld::Atom*>& exports = this->_writer._exportedAtoms;
1244 uint64_t imageBaseAddress = this->_writer.headerAndLoadCommandsSection->address;
1245 std::vector<mach_o::trie::Entry> entries;
1246 unsigned int padding = 0;
1247 entries.reserve(exports.size());
1248 for (std::vector<const ld::Atom*>::const_iterator it = exports.begin(); it != exports.end(); ++it) {
1249 const ld::Atom* atom = *it;
1250 mach_o::trie::Entry entry;
1251 uint64_t flags = (atom->contentType() == ld::Atom::typeTLV) ? EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL : EXPORT_SYMBOL_FLAGS_KIND_REGULAR;
1252 uint64_t other = 0;
1253 uint64_t address = atom->finalAddress() - imageBaseAddress;
1254 if ( atom->definition() == ld::Atom::definitionProxy ) {
1255 entry.name = atom->name();
1256 entry.flags = flags | EXPORT_SYMBOL_FLAGS_REEXPORT;
1257 if ( atom->combine() == ld::Atom::combineByName )
1258 entry.flags |= EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION;
1259 entry.other = this->_writer.compressedOrdinalForAtom(atom);
1260 if ( entry.other == BIND_SPECIAL_DYLIB_SELF ) {
1261 warning("not adding explict export for symbol %s because it is already re-exported from dylib %s", entry.name, atom->safeFilePath());
1262 continue;
1263 }
1264 if ( atom->isAlias() ) {
1265 // alias proxy means symbol was re-exported with a name change
1266 const ld::Atom* aliasOf = NULL;
1267 for (ld::Fixup::iterator fit = atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
1268 if ( fit->kind == ld::Fixup::kindNoneFollowOn ) {
1269 assert(fit->binding == ld::Fixup::bindingDirectlyBound);
1270 aliasOf = fit->u.target;
1271 }
1272 }
1273 assert(aliasOf != NULL);
1274 entry.importName = aliasOf->name();
1275 }
1276 else {
1277 // symbol name stays same as re-export
1278 entry.importName = atom->name();
1279 }
1280 entries.push_back(entry);
1281 //fprintf(stderr, "re-export %s from lib %llu as %s\n", entry.importName, entry.other, entry.name);
1282 }
1283 else if ( atom->definition() == ld::Atom::definitionAbsolute ) {
1284 entry.name = atom->name();
1285 entry.flags = _options.canUseAbsoluteSymbols() ? EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE : EXPORT_SYMBOL_FLAGS_KIND_REGULAR;
1286 entry.address = address;
1287 entry.other = other;
1288 entry.importName = NULL;
1289 entries.push_back(entry);
1290 }
1291 else {
1292 if ( (atom->definition() == ld::Atom::definitionRegular) && (atom->combine() == ld::Atom::combineByName) )
1293 flags |= EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION;
1294 if ( atom->isThumb() )
1295 address |= 1;
1296 if ( atom->contentType() == ld::Atom::typeResolver ) {
1297 flags |= EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER;
1298 // set normal lookup to return stub address
1299 // and add resolver function in new location that newer dyld's can access
1300 other = address;
1301 const ld::Atom* stub = stubForResolverFunction(atom);
1302 address = stub->finalAddress() - imageBaseAddress;
1303 if ( stub->isThumb() )
1304 address |= 1;
1305 }
1306 entry.name = atom->name();
1307 entry.flags = flags;
1308 entry.address = address;
1309 entry.other = other;
1310 entry.importName = NULL;
1311 entries.push_back(entry);
1312 }
1313
1314 if (_options.sharedRegionEligible() && strncmp(atom->section().segmentName(), "__DATA", 6) == 0) {
1315 // Maximum address is 64bit which is 10 bytes as a uleb128. Minimum is 1 byte
1316 // Pad the section out so we can deal with addresses getting larger when __DATA segment
1317 // is moved before __TEXT in dyld shared cache.
1318 padding += 9;
1319 }
1320 }
1321
1322 // sort vector by -exported_symbols_order, and any others by address
1323 std::sort(entries.begin(), entries.end(), TrieEntriesSorter(_options));
1324
1325 // create trie
1326 mach_o::trie::makeTrie(entries, this->_encodedData.bytes());
1327
1328 //Add additional data padding for the unoptimized shared cache
1329 for (unsigned int i = 0; i < padding; ++i)
1330 this->_encodedData.append_byte(0);
1331
1332 // align to pointer size
1333 this->_encodedData.pad_to_size(sizeof(pint_t));
1334
1335 this->_encoded = true;
1336 }
1337
1338
1339 template <typename A>
1340 class SplitSegInfoV1Atom : public LinkEditAtom
1341 {
1342 public:
1343 SplitSegInfoV1Atom(const Options& opts, ld::Internal& state, OutputFile& writer)
1344 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { }
1345
1346 // overrides of ld::Atom
1347 virtual const char* name() const { return "split seg info"; }
1348 // overrides of LinkEditAtom
1349 virtual void encode() const;
1350
1351 private:
1352 typedef typename A::P P;
1353 typedef typename A::P::E E;
1354 typedef typename A::P::uint_t pint_t;
1355
1356 void addSplitSegInfo(uint64_t address, ld::Fixup::Kind k, uint32_t) const;
1357 void uleb128EncodeAddresses(const std::vector<uint64_t>& locations) const;
1358
1359 mutable std::vector<uint64_t> _32bitPointerLocations;
1360 mutable std::vector<uint64_t> _64bitPointerLocations;
1361 mutable std::vector<uint64_t> _thumbLo16Locations;
1362 mutable std::vector<uint64_t> _thumbHi16Locations[16];
1363 mutable std::vector<uint64_t> _armLo16Locations;
1364 mutable std::vector<uint64_t> _armHi16Locations[16];
1365 mutable std::vector<uint64_t> _adrpLocations;
1366
1367
1368 static ld::Section _s_section;
1369 };
1370
1371 template <typename A>
1372 ld::Section SplitSegInfoV1Atom<A>::_s_section("__LINKEDIT", "__splitSegInfo", ld::Section::typeLinkEdit, true);
1373
1374 template <>
1375 void SplitSegInfoV1Atom<x86_64>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind kind, uint32_t extra) const
1376 {
1377 switch (kind) {
1378 case ld::Fixup::kindStoreX86PCRel32:
1379 case ld::Fixup::kindStoreX86PCRel32_1:
1380 case ld::Fixup::kindStoreX86PCRel32_2:
1381 case ld::Fixup::kindStoreX86PCRel32_4:
1382 case ld::Fixup::kindStoreX86PCRel32GOTLoad:
1383 case ld::Fixup::kindStoreX86PCRel32GOTLoadNowLEA:
1384 case ld::Fixup::kindStoreX86PCRel32GOT:
1385 case ld::Fixup::kindStoreLittleEndian32:
1386 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
1387 case ld::Fixup::kindStoreTargetAddressX86PCRel32:
1388 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad:
1389 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA:
1390 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad:
1391 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA:
1392 _32bitPointerLocations.push_back(address);
1393 break;
1394 case ld::Fixup::kindStoreLittleEndian64:
1395 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
1396 _64bitPointerLocations.push_back(address);
1397 break;
1398 #if SUPPORT_ARCH_arm64e
1399 case ld::Fixup::kindStoreLittleEndianAuth64:
1400 case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64:
1401 assert(false);
1402 break;
1403 #endif
1404 default:
1405 warning("codegen at address 0x%08llX prevents image from working in dyld shared cache", address);
1406 break;
1407 }
1408 }
1409
1410 template <>
1411 void SplitSegInfoV1Atom<x86>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind kind, uint32_t extra) const
1412 {
1413 switch (kind) {
1414 case ld::Fixup::kindStoreLittleEndian32:
1415 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
1416 case ld::Fixup::kindStoreX86PCRel32TLVLoad:
1417 case ld::Fixup::kindStoreX86PCRel32TLVLoadNowLEA:
1418 _32bitPointerLocations.push_back(address);
1419 break;
1420 default:
1421 warning("codegen at address 0x%08llX prevents image from working in dyld shared cache", address);
1422 break;
1423 }
1424 }
1425
1426 template <>
1427 void SplitSegInfoV1Atom<arm>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind kind, uint32_t extra) const
1428 {
1429 switch (kind) {
1430 case ld::Fixup::kindStoreLittleEndian32:
1431 _32bitPointerLocations.push_back(address);
1432 break;
1433 case ld::Fixup::kindStoreARMLow16:
1434 _armLo16Locations.push_back(address);
1435 break;
1436 case ld::Fixup::kindStoreThumbLow16:
1437 _thumbLo16Locations.push_back(address);
1438 break;
1439 case ld::Fixup::kindStoreARMHigh16:
1440 assert(extra < 16);
1441 _armHi16Locations[extra].push_back(address);
1442 break;
1443 case ld::Fixup::kindStoreThumbHigh16:
1444 assert(extra < 16);
1445 _thumbHi16Locations[extra].push_back(address);
1446 break;
1447 default:
1448 warning("codegen at address 0x%08llX prevents image from working in dyld shared cache", address);
1449 break;
1450 }
1451 }
1452
1453 #if SUPPORT_ARCH_arm64
1454 template <>
1455 void SplitSegInfoV1Atom<arm64>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind kind, uint32_t extra) const
1456 {
1457 switch (kind) {
1458 case ld::Fixup::kindStoreARM64Page21:
1459 case ld::Fixup::kindStoreARM64GOTLoadPage21:
1460 case ld::Fixup::kindStoreARM64GOTLeaPage21:
1461 case ld::Fixup::kindStoreARM64TLVPLoadPage21:
1462 case ld::Fixup::kindStoreTargetAddressARM64Page21:
1463 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
1464 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21:
1465 _adrpLocations.push_back(address);
1466 break;
1467 case ld::Fixup::kindStoreLittleEndian32:
1468 case ld::Fixup::kindStoreARM64PCRelToGOT:
1469 _32bitPointerLocations.push_back(address);
1470 break;
1471 case ld::Fixup::kindStoreLittleEndian64:
1472 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
1473 _64bitPointerLocations.push_back(address);
1474 break;
1475 #if SUPPORT_ARCH_arm64e
1476 case ld::Fixup::kindStoreLittleEndianAuth64:
1477 case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64:
1478 warning("authenticated pointer at address 0x%08llX prevents image from working in dyld shared cache", address);
1479 break;
1480 #endif
1481 default:
1482 warning("codegen at address 0x%08llX prevents image from working in dyld shared cache", address);
1483 break;
1484 }
1485 }
1486 #endif
1487
1488 template <typename A>
1489 void SplitSegInfoV1Atom<A>::uleb128EncodeAddresses(const std::vector<uint64_t>& locations) const
1490 {
1491 pint_t addr = this->_options.baseAddress();
1492 for(typename std::vector<uint64_t>::const_iterator it = locations.begin(); it != locations.end(); ++it) {
1493 pint_t nextAddr = *it;
1494 //fprintf(stderr, "nextAddr=0x%0llX\n", (uint64_t)nextAddr);
1495 uint64_t delta = nextAddr - addr;
1496 //fprintf(stderr, "delta=0x%0llX\n", delta);
1497 if ( delta == 0 )
1498 throw "double split seg info for same address";
1499 // uleb128 encode
1500 uint8_t byte;
1501 do {
1502 byte = delta & 0x7F;
1503 delta &= ~0x7F;
1504 if ( delta != 0 )
1505 byte |= 0x80;
1506 this->_encodedData.append_byte(byte);
1507 delta = delta >> 7;
1508 }
1509 while( byte >= 0x80 );
1510 addr = nextAddr;
1511 }
1512 }
1513
1514
1515 template <typename A>
1516 void SplitSegInfoV1Atom<A>::encode() const
1517 {
1518 // sort into group by pointer adjustment kind
1519 std::vector<OutputFile::SplitSegInfoEntry>& info = this->_writer._splitSegInfos;
1520 for (std::vector<OutputFile::SplitSegInfoEntry>::const_iterator it = info.begin(); it != info.end(); ++it) {
1521 this->addSplitSegInfo(it->fixupAddress, it->kind, it->extra);
1522 }
1523
1524 // delta compress runs of addresses
1525 this->_encodedData.reserve(8192);
1526 if ( _32bitPointerLocations.size() != 0 ) {
1527 this->_encodedData.append_byte(1);
1528 //fprintf(stderr, "type 1:\n");
1529 std::sort(_32bitPointerLocations.begin(), _32bitPointerLocations.end());
1530 this->uleb128EncodeAddresses(_32bitPointerLocations);
1531 this->_encodedData.append_byte(0); // terminator
1532 }
1533
1534 if ( _64bitPointerLocations.size() != 0 ) {
1535 this->_encodedData.append_byte(2);
1536 //fprintf(stderr, "type 2:\n");
1537 std::sort(_64bitPointerLocations.begin(), _64bitPointerLocations.end());
1538 this->uleb128EncodeAddresses(_64bitPointerLocations);
1539 this->_encodedData.append_byte(0); // terminator
1540 }
1541
1542 if ( _adrpLocations.size() != 0 ) {
1543 this->_encodedData.append_byte(3);
1544 //fprintf(stderr, "type 3:\n");
1545 std::sort(_adrpLocations.begin(), _adrpLocations.end());
1546 this->uleb128EncodeAddresses(_adrpLocations);
1547 this->_encodedData.append_byte(0); // terminator
1548 }
1549
1550 if ( _thumbLo16Locations.size() != 0 ) {
1551 this->_encodedData.append_byte(5);
1552 //fprintf(stderr, "type 5:\n");
1553 std::sort(_thumbLo16Locations.begin(), _thumbLo16Locations.end());
1554 this->uleb128EncodeAddresses(_thumbLo16Locations);
1555 this->_encodedData.append_byte(0); // terminator
1556 }
1557
1558 if ( _armLo16Locations.size() != 0 ) {
1559 this->_encodedData.append_byte(6);
1560 //fprintf(stderr, "type 6:\n");
1561 std::sort(_armLo16Locations.begin(), _armLo16Locations.end());
1562 this->uleb128EncodeAddresses(_armLo16Locations);
1563 this->_encodedData.append_byte(0); // terminator
1564 }
1565
1566 for (uint32_t i=0; i < 16; ++i) {
1567 if ( _thumbHi16Locations[i].size() != 0 ) {
1568 this->_encodedData.append_byte(16+i);
1569 //fprintf(stderr, "type 16+%d:\n", i);
1570 std::sort(_thumbHi16Locations[i].begin(), _thumbHi16Locations[i].end());
1571 this->uleb128EncodeAddresses(_thumbHi16Locations[i]);
1572 this->_encodedData.append_byte(0); // terminator
1573 }
1574 }
1575
1576 for (uint32_t i=0; i < 16; ++i) {
1577 if ( _armHi16Locations[i].size() != 0 ) {
1578 this->_encodedData.append_byte(32+i);
1579 //fprintf(stderr, "type 32+%d:\n", i);
1580 std::sort(_armHi16Locations[i].begin(), _armHi16Locations[i].end());
1581 this->uleb128EncodeAddresses(_armHi16Locations[i]);
1582 this->_encodedData.append_byte(0); // terminator
1583 }
1584 }
1585
1586 // always add zero byte to mark end
1587 this->_encodedData.append_byte(0);
1588
1589 // align to pointer size
1590 this->_encodedData.pad_to_size(sizeof(pint_t));
1591
1592 this->_encoded = true;
1593
1594 // clean up temporaries
1595 _32bitPointerLocations.clear();
1596 _64bitPointerLocations.clear();
1597 }
1598
1599
1600 template <typename A>
1601 class SplitSegInfoV2Atom : public LinkEditAtom
1602 {
1603 public:
1604 SplitSegInfoV2Atom(const Options& opts, ld::Internal& state, OutputFile& writer)
1605 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { }
1606
1607 // overrides of ld::Atom
1608 virtual const char* name() const { return "split seg info"; }
1609 // overrides of LinkEditAtom
1610 virtual void encode() const;
1611
1612 private:
1613 typedef typename A::P P;
1614 typedef typename A::P::E E;
1615 typedef typename A::P::uint_t pint_t;
1616
1617 // Whole :== <count> FromToSection+
1618 // FromToSection :== <from-sect-index> <to-sect-index> <count> ToOffset+
1619 // ToOffset :== <to-sect-offset-delta> <count> FromOffset+
1620 // FromOffset :== <kind> <count> <from-sect-offset-delta>
1621
1622 typedef uint32_t SectionIndexes;
1623 typedef std::map<uint8_t, std::vector<uint64_t> > FromOffsetMap;
1624 typedef std::map<uint64_t, FromOffsetMap> ToOffsetMap;
1625 typedef std::map<SectionIndexes, ToOffsetMap> WholeMap;
1626
1627
1628 static ld::Section _s_section;
1629 };
1630
1631 template <typename A>
1632 ld::Section SplitSegInfoV2Atom<A>::_s_section("__LINKEDIT", "__splitSegInfo", ld::Section::typeLinkEdit, true);
1633
1634
1635 template <typename A>
1636 void SplitSegInfoV2Atom<A>::encode() const
1637 {
1638 // sort into group by adjustment kind
1639 //fprintf(stderr, "_splitSegV2Infos.size=%lu\n", this->_writer._splitSegV2Infos.size());
1640 WholeMap whole;
1641 for (const OutputFile::SplitSegInfoV2Entry& entry : this->_writer._splitSegV2Infos) {
1642 //fprintf(stderr, "from=%d, to=%d\n", entry.fixupSectionIndex, entry.targetSectionIndex);
1643 SectionIndexes index = entry.fixupSectionIndex << 16 | entry.targetSectionIndex;
1644 ToOffsetMap& toOffsets = whole[index];
1645 FromOffsetMap& fromOffsets = toOffsets[entry.targetSectionOffset];
1646 fromOffsets[entry.referenceKind].push_back(entry.fixupSectionOffset);
1647 }
1648
1649 // Add marker that this is V2 data
1650 this->_encodedData.reserve(8192);
1651 this->_encodedData.append_byte(DYLD_CACHE_ADJ_V2_FORMAT);
1652
1653 // stream out
1654 // Whole :== <count> FromToSection+
1655 this->_encodedData.append_uleb128(whole.size());
1656 for (auto& fromToSection : whole) {
1657 uint8_t fromSectionIndex = fromToSection.first >> 16;
1658 uint8_t toSectionIndex = fromToSection.first & 0xFFFF;
1659 ToOffsetMap& toOffsets = fromToSection.second;
1660 // FromToSection :== <from-sect-index> <to-sect-index> <count> ToOffset+
1661 this->_encodedData.append_uleb128(fromSectionIndex);
1662 this->_encodedData.append_uleb128(toSectionIndex);
1663 this->_encodedData.append_uleb128(toOffsets.size());
1664 //fprintf(stderr, "from sect=%d, to sect=%d, count=%lu\n", fromSectionIndex, toSectionIndex, toOffsets.size());
1665 uint64_t lastToOffset = 0;
1666 for (auto& fromToOffsets : toOffsets) {
1667 uint64_t toSectionOffset = fromToOffsets.first;
1668 FromOffsetMap& fromOffsets = fromToOffsets.second;
1669 // ToOffset :== <to-sect-offset-delta> <count> FromOffset+
1670 this->_encodedData.append_uleb128(toSectionOffset - lastToOffset);
1671 this->_encodedData.append_uleb128(fromOffsets.size());
1672 for (auto& kindAndOffsets : fromOffsets) {
1673 uint8_t kind = kindAndOffsets.first;
1674 std::vector<uint64_t>& fromOffsets = kindAndOffsets.second;
1675 // FromOffset :== <kind> <count> <from-sect-offset-delta>
1676 this->_encodedData.append_uleb128(kind);
1677 this->_encodedData.append_uleb128(fromOffsets.size());
1678 std::sort(fromOffsets.begin(), fromOffsets.end());
1679 uint64_t lastFromOffset = 0;
1680 for (uint64_t offset : fromOffsets) {
1681 this->_encodedData.append_uleb128(offset - lastFromOffset);
1682 lastFromOffset = offset;
1683 }
1684 }
1685 lastToOffset = toSectionOffset;
1686 }
1687 }
1688
1689
1690 // always add zero byte to mark end
1691 this->_encodedData.append_byte(0);
1692
1693 // align to pointer size
1694 this->_encodedData.pad_to_size(sizeof(pint_t));
1695
1696 this->_encoded = true;
1697 }
1698
1699
1700
1701 template <typename A>
1702 class FunctionStartsAtom : public LinkEditAtom
1703 {
1704 public:
1705 FunctionStartsAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
1706 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { }
1707
1708 // overrides of ld::Atom
1709 virtual const char* name() const { return "function starts"; }
1710 // overrides of LinkEditAtom
1711 virtual void encode() const;
1712
1713 private:
1714 typedef typename A::P P;
1715 typedef typename A::P::E E;
1716 typedef typename A::P::uint_t pint_t;
1717
1718 static ld::Section _s_section;
1719 };
1720
1721 template <typename A>
1722 ld::Section FunctionStartsAtom<A>::_s_section("__LINKEDIT", "__funcStarts", ld::Section::typeLinkEdit, true);
1723
1724
1725 template <typename A>
1726 void FunctionStartsAtom<A>::encode() const
1727 {
1728 this->_encodedData.reserve(8192);
1729 const uint64_t badAddress = 0xFFFFFFFFFFFFFFFF;
1730 uint64_t addr = badAddress;
1731 // delta compress all function addresses
1732 for (std::vector<ld::Internal::FinalSection*>::iterator it = this->_state.sections.begin(); it != this->_state.sections.end(); ++it) {
1733 ld::Internal::FinalSection* sect = *it;
1734 if ( sect->type() == ld::Section::typeMachHeader ) {
1735 // start with delta from start of __TEXT
1736 addr = sect->address;
1737 }
1738 else if ( sect->type() == ld::Section::typeCode ) {
1739 assert(addr != badAddress);
1740 std::vector<const ld::Atom*>& atoms = sect->atoms;
1741 for (std::vector<const ld::Atom*>::iterator ait = atoms.begin(); ait != atoms.end(); ++ait) {
1742 const ld::Atom* atom = *ait;
1743 // <rdar://problem/10422823> filter out zero-length atoms, so LC_FUNCTION_STARTS address can't spill into next section
1744 if ( atom->size() == 0 )
1745 continue;
1746 uint64_t nextAddr = atom->finalAddress();
1747 if ( atom->isThumb() )
1748 nextAddr |= 1;
1749 uint64_t delta = nextAddr - addr;
1750 if ( delta != 0 )
1751 this->_encodedData.append_uleb128(delta);
1752 addr = nextAddr;
1753 }
1754 }
1755 }
1756
1757 // terminator
1758 this->_encodedData.append_byte(0);
1759
1760 // align to pointer size
1761 this->_encodedData.pad_to_size(sizeof(pint_t));
1762
1763 this->_encoded = true;
1764 }
1765
1766
1767 // <rdar://problem/9218847> Need way to formalize data in code
1768 template <typename A>
1769 class DataInCodeAtom : public LinkEditAtom
1770 {
1771 public:
1772 DataInCodeAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
1773 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { }
1774
1775 // overrides of ld::Atom
1776 virtual const char* name() const { return "data-in-code info"; }
1777 // overrides of LinkEditAtom
1778 virtual void encode() const;
1779
1780 private:
1781 typedef typename A::P P;
1782 typedef typename A::P::E E;
1783 typedef typename A::P::uint_t pint_t;
1784
1785 struct FixupByAddressSorter
1786 {
1787 bool operator()(const ld::Fixup* left, const ld::Fixup* right)
1788 {
1789 return (left->offsetInAtom < right->offsetInAtom);
1790 }
1791 };
1792
1793 void encodeEntry(uint32_t startImageOffset, int len, ld::Fixup::Kind kind) const {
1794 //fprintf(stderr, "encodeEntry(start=0x%08X, len=0x%04X, kind=%04X\n", startImageOffset, len, kind);
1795 do {
1796 macho_data_in_code_entry<P> entry;
1797 entry.set_offset(startImageOffset);
1798 entry.set_length(len);
1799 switch ( kind ) {
1800 case ld::Fixup::kindDataInCodeStartData:
1801 entry.set_kind(DICE_KIND_DATA);
1802 break;
1803 case ld::Fixup::kindDataInCodeStartJT8:
1804 entry.set_kind(DICE_KIND_JUMP_TABLE8);
1805 break;
1806 case ld::Fixup::kindDataInCodeStartJT16:
1807 entry.set_kind(DICE_KIND_JUMP_TABLE16);
1808 break;
1809 case ld::Fixup::kindDataInCodeStartJT32:
1810 entry.set_kind(DICE_KIND_JUMP_TABLE32);
1811 break;
1812 case ld::Fixup::kindDataInCodeStartJTA32:
1813 entry.set_kind(DICE_KIND_ABS_JUMP_TABLE32);
1814 break;
1815 default:
1816 assert(0 && "bad L$start$ label to encode");
1817 }
1818 uint8_t* bp = (uint8_t*)&entry;
1819 this->_encodedData.append_byte(bp[0]);
1820 this->_encodedData.append_byte(bp[1]);
1821 this->_encodedData.append_byte(bp[2]);
1822 this->_encodedData.append_byte(bp[3]);
1823 this->_encodedData.append_byte(bp[4]);
1824 this->_encodedData.append_byte(bp[5]);
1825 this->_encodedData.append_byte(bp[6]);
1826 this->_encodedData.append_byte(bp[7]);
1827 // in rare case data range is huge, create multiple entries
1828 len -= 0xFFF8;
1829 startImageOffset += 0xFFF8;
1830 } while ( len > 0 );
1831 }
1832
1833 static ld::Section _s_section;
1834 };
1835
1836 template <typename A>
1837 ld::Section DataInCodeAtom<A>::_s_section("__LINKEDIT", "__dataInCode", ld::Section::typeLinkEdit, true);
1838
1839
1840 template <typename A>
1841 void DataInCodeAtom<A>::encode() const
1842 {
1843 if ( this->_writer.hasDataInCode ) {
1844 uint64_t mhAddress = 0;
1845 for (std::vector<ld::Internal::FinalSection*>::iterator sit = _state.sections.begin(); sit != _state.sections.end(); ++sit) {
1846 ld::Internal::FinalSection* sect = *sit;
1847 if ( sect->type() == ld::Section::typeMachHeader )
1848 mhAddress = sect->address;
1849 if ( sect->type() != ld::Section::typeCode )
1850 continue;
1851 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
1852 const ld::Atom* atom = *ait;
1853 // gather all code-in-data labels
1854 std::vector<const ld::Fixup*> dataInCodeLabels;
1855 for (ld::Fixup::iterator fit = atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
1856 switch ( fit->kind ) {
1857 case ld::Fixup::kindDataInCodeStartData:
1858 case ld::Fixup::kindDataInCodeStartJT8:
1859 case ld::Fixup::kindDataInCodeStartJT16:
1860 case ld::Fixup::kindDataInCodeStartJT32:
1861 case ld::Fixup::kindDataInCodeStartJTA32:
1862 case ld::Fixup::kindDataInCodeEnd:
1863 dataInCodeLabels.push_back(fit);
1864 break;
1865 default:
1866 break;
1867 }
1868 }
1869 // to do: sort labels by address
1870 std::sort(dataInCodeLabels.begin(), dataInCodeLabels.end(), FixupByAddressSorter());
1871
1872 // convert to array of struct data_in_code_entry
1873 ld::Fixup::Kind prevKind = ld::Fixup::kindDataInCodeEnd;
1874 uint32_t prevOffset = 0;
1875 for ( std::vector<const ld::Fixup*>::iterator sfit = dataInCodeLabels.begin(); sfit != dataInCodeLabels.end(); ++sfit) {
1876 if ( ((*sfit)->kind != prevKind) && (prevKind != ld::Fixup::kindDataInCodeEnd) ) {
1877 int len = (*sfit)->offsetInAtom - prevOffset;
1878 if ( len == 0 )
1879 warning("multiple L$start$ labels found at same address in %s at offset 0x%04X", atom->name(), prevOffset);
1880 this->encodeEntry(atom->finalAddress()+prevOffset-mhAddress, (*sfit)->offsetInAtom - prevOffset, prevKind);
1881 }
1882 prevKind = (*sfit)->kind;
1883 prevOffset = (*sfit)->offsetInAtom;
1884 }
1885 if ( prevKind != ld::Fixup::kindDataInCodeEnd ) {
1886 // add entry if function ends with data
1887 this->encodeEntry(atom->finalAddress()+prevOffset-mhAddress, atom->size() - prevOffset, prevKind);
1888 }
1889 }
1890 }
1891 }
1892
1893 this->_encoded = true;
1894 }
1895
1896
1897
1898
1899
1900
1901 template <typename A>
1902 class OptimizationHintsAtom : public LinkEditAtom
1903 {
1904 public:
1905 OptimizationHintsAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
1906 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) {
1907 assert(opts.outputKind() == Options::kObjectFile);
1908 }
1909
1910 // overrides of ld::Atom
1911 virtual const char* name() const { return "linker optimization hints"; }
1912 // overrides of LinkEditAtom
1913 virtual void encode() const;
1914
1915 private:
1916 typedef typename A::P P;
1917 typedef typename A::P::E E;
1918 typedef typename A::P::uint_t pint_t;
1919
1920 static ld::Section _s_section;
1921
1922 };
1923
1924 template <typename A>
1925 ld::Section OptimizationHintsAtom<A>::_s_section("__LINKEDIT", "__opt_hints", ld::Section::typeLinkEdit, true);
1926
1927 template <typename A>
1928 void OptimizationHintsAtom<A>::encode() const
1929 {
1930 if ( _state.someObjectHasOptimizationHints ) {
1931 for (std::vector<ld::Internal::FinalSection*>::iterator sit = _state.sections.begin(); sit != _state.sections.end(); ++sit) {
1932 ld::Internal::FinalSection* sect = *sit;
1933 if ( sect->type() != ld::Section::typeCode )
1934 continue;
1935 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
1936 const ld::Atom* atom = *ait;
1937 uint64_t address = atom->finalAddress();
1938 for (ld::Fixup::iterator fit = atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
1939 if ( fit->kind != ld::Fixup::kindLinkerOptimizationHint)
1940 continue;
1941 ld::Fixup::LOH_arm64 extra;
1942 extra.addend = fit->u.addend;
1943 _encodedData.append_uleb128(extra.info.kind);
1944 _encodedData.append_uleb128(extra.info.count+1);
1945 _encodedData.append_uleb128((extra.info.delta1 << 2) + fit->offsetInAtom + address);
1946 if ( extra.info.count > 0 )
1947 _encodedData.append_uleb128((extra.info.delta2 << 2) + fit->offsetInAtom + address);
1948 if ( extra.info.count > 1 )
1949 _encodedData.append_uleb128((extra.info.delta3 << 2) + fit->offsetInAtom + address);
1950 if ( extra.info.count > 2 )
1951 _encodedData.append_uleb128((extra.info.delta4 << 2) + fit->offsetInAtom + address);
1952 }
1953 }
1954 }
1955
1956 this->_encodedData.pad_to_size(sizeof(pint_t));
1957 }
1958
1959 this->_encoded = true;
1960 }
1961
1962
1963 } // namespace tool
1964 } // namespace ld
1965
1966 #endif // __LINKEDIT_HPP__