1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-*
3 * Copyright (c) 2009-2010 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
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
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.
22 * @APPLE_LICENSE_HEADER_END@
25 #ifndef __LINKEDIT_HPP__
26 #define __LINKEDIT_HPP__
29 #include <sys/types.h>
35 #include <unordered_map>
39 #include "Architectures.hpp"
40 #include "MachOFileAbstraction.hpp"
41 #include "code-sign-blobs/superblob.h"
48 std::vector<uint8_t> _data;
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]; }
55 void append_uleb128(uint64_t value) {
62 _data.push_back(byte);
64 } while( byte >= 0x80 );
67 void append_sleb128(int64_t value) {
68 bool isNeg = ( value < 0 );
75 more = ( (value != -1) || ((byte & 0x40) == 0) );
77 more = ( (value != 0) || ((byte & 0x40) != 0) );
80 _data.push_back(byte);
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;
91 append_uleb128(delta);
96 void append_string(const char* str) {
97 for (const char* s = str; *s != '\0'; ++s)
99 _data.push_back('\0');
102 void append_byte(uint8_t byte) {
103 _data.push_back(byte);
106 static unsigned int uleb128_size(uint64_t value) {
111 } while ( value != 0 );
115 void pad_to_size(unsigned int alignment) {
116 while ( (_data.size() % alignment) != 0 )
122 class LinkEditAtom : public ld::Atom
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;
132 virtual void encode() const = 0;
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),
144 const Options& _options;
145 ld::Internal& _state;
147 mutable ByteStream _encodedData;
148 mutable bool _encoded;
151 uint64_t LinkEditAtom::size() const
154 return _encodedData.size();
157 void LinkEditAtom::copyRawContent(uint8_t buffer[]) const
160 memcpy(buffer, _encodedData.start(), _encodedData.size());
166 template <typename A>
167 class RebaseInfoAtom : public LinkEditAtom
170 RebaseInfoAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
171 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { _encoded = true; }
173 // overrides of ld::Atom
174 virtual const char* name() const { return "rebase info"; }
175 // overrides of LinkEditAtom
176 virtual void encode() const;
179 void encodeV1() const;
183 rebase_tmp(uint8_t op, uint64_t p1, uint64_t p2=0) : opcode(op), operand1(p1), operand2(p2) {}
189 typedef typename A::P P;
190 typedef typename A::P::E E;
191 typedef typename A::P::uint_t pint_t;
193 static ld::Section _s_section;
196 template <typename A>
197 ld::Section RebaseInfoAtom<A>::_s_section("__LINKEDIT", "__rebase", ld::Section::typeLinkEdit, true);
200 template <typename A>
201 void RebaseInfoAtom<A>::encode() const
203 // omit relocs if this was supposed to be PIE but PIE not possible
204 if ( _options.positionIndependentExecutable() && this->_writer.pieDisabled )
207 // sort rebase info by type, then address
208 std::vector<OutputFile::RebaseInfo>& info = this->_writer._rebaseInfo;
212 std::sort(info.begin(), info.end());
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
226 template <typename A>
227 void RebaseInfoAtom<A>::encodeV1() const
229 std::vector<OutputFile::RebaseInfo>& info = this->_writer._rebaseInfo;
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;
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));
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));
250 mid.push_back(rebase_tmp(REBASE_OPCODE_ADD_ADDR_ULEB, it->_address-address));
252 address = it->_address;
254 mid.push_back(rebase_tmp(REBASE_OPCODE_DO_REBASE_ULEB_TIMES, 1));
255 address += sizeof(pint_t);
256 if ( address >= curSegEnd )
259 mid.push_back(rebase_tmp(REBASE_OPCODE_DONE, 0));
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) ) {
266 while (src->opcode == REBASE_OPCODE_DO_REBASE_ULEB_TIMES ) {
267 dst->operand1 += src->operand1;
277 dst->opcode = REBASE_OPCODE_DONE;
279 // optimize phase 2, combine rebase/add pairs
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;
294 dst->opcode = REBASE_OPCODE_DONE;
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
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;
309 dst->operand2 = delta;
311 while ( (src->opcode == REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB)
312 && (src->operand1 == delta) ) {
323 dst->opcode = REBASE_OPCODE_DONE;
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);
333 else if ( (p->opcode == REBASE_OPCODE_DO_REBASE_ULEB_TIMES) && (p->operand1 < 15) ) {
334 p->opcode = REBASE_OPCODE_DO_REBASE_IMM_TIMES;
338 // convert to compressed encoding
339 const static bool log = false;
340 this->_encodedData.reserve(info.size()*2);
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");
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);
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);
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);
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 );
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);
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);
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);
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);
390 // align to pointer size
391 this->_encodedData.pad_to_size(sizeof(pint_t));
393 this->_encoded = true;
395 if (log) fprintf(stderr, "total rebase info size = %ld\n", this->_encodedData.size());
399 template <typename A>
400 class BindingInfoAtom : public LinkEditAtom
403 BindingInfoAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
404 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { }
406 // overrides of ld::Atom
407 virtual const char* name() const { return "binding info"; }
408 // overrides of LinkEditAtom
409 virtual void encode() const;
413 void encodeV1() const;
414 void encodeV2() const;
416 typedef typename A::P P;
417 typedef typename A::P::E E;
418 typedef typename A::P::uint_t pint_t;
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) {}
430 static ld::Section _s_section;
433 template <typename A>
434 ld::Section BindingInfoAtom<A>::_s_section("__LINKEDIT", "__binding", ld::Section::typeLinkEdit, true);
437 template <typename A>
438 void BindingInfoAtom<A>::encode() const
440 // use encoding based on target minOS
441 if ( _options.useLinkedListBinding() && !this->_writer._hasUnalignedFixup ) {
449 template <typename A>
450 void BindingInfoAtom<A>::encodeV1() const
452 // sort by library, symbol, type, then address
453 std::vector<OutputFile::BindingInfo>& info = this->_writer._bindingInfo;
454 std::sort(info.begin(), info.end());
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;
464 uint64_t address = (uint64_t)(-1);
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));
473 mid.push_back(binding_tmp(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB, it->_libraryOrdinal));
475 ordinal = it->_libraryOrdinal;
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;
481 if ( type != it->_type ) {
482 mid.push_back(binding_tmp(BIND_OPCODE_SET_TYPE_IMM, it->_type));
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));
492 mid.push_back(binding_tmp(BIND_OPCODE_ADD_ADDR_ULEB, it->_address-address));
494 address = it->_address;
496 if ( addend != it->_addend ) {
497 mid.push_back(binding_tmp(BIND_OPCODE_SET_ADDEND_SLEB, it->_addend));
498 addend = it->_addend;
500 mid.push_back(binding_tmp(BIND_OPCODE_DO_BIND, 0));
501 address += sizeof(pint_t);
503 mid.push_back(binding_tmp(BIND_OPCODE_DONE, 0));
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;
520 dst->opcode = BIND_OPCODE_DONE;
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
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;
533 dst->operand2 = delta;
535 while ( (src->opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
536 && (src->operand1 == delta) ) {
547 dst->opcode = BIND_OPCODE_DONE;
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);
557 else if ( (p->opcode == BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB) && (p->operand1 <= 15) ) {
558 p->opcode = BIND_OPCODE_SET_DYLIB_ORDINAL_IMM;
561 dst->opcode = BIND_OPCODE_DONE;
563 // convert to compressed encoding
564 const static bool log = false;
565 this->_encodedData.reserve(info.size()*2);
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");
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);
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);
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));
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);
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);
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);
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);
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);
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);
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);
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 );
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);
632 // align to pointer size
633 this->_encodedData.pad_to_size(sizeof(pint_t));
635 this->_encoded = true;
637 if (log) fprintf(stderr, "total binding info size = %ld\n", this->_encodedData.size());
640 template <typename A>
641 void BindingInfoAtom<A>::encodeV2() const
643 std::vector<OutputFile::BindingInfo>& bindInfo = this->_writer._bindingInfo;
644 std::vector<OutputFile::RebaseInfo>& rebaseInfo = this->_writer._rebaseInfo;
645 const static bool log = false;
647 std::sort(bindInfo.begin(), bindInfo.end());
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;
657 uint64_t address = (uint64_t)(-1);
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));
667 else if ( it->_libraryOrdinal <= 15 ) {
668 mid.push_back(binding_tmp(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM, it->_libraryOrdinal));
671 mid.push_back(binding_tmp(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB, it->_libraryOrdinal));
673 ordinal = it->_libraryOrdinal;
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;
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));
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";
694 address = it->_address;
696 if ( addend != it->_addend ) {
697 mid.push_back(binding_tmp(BIND_OPCODE_SET_ADDEND_SLEB, it->_addend));
698 addend = it->_addend;
704 mid.push_back(binding_tmp(BIND_OPCODE_DO_BIND, 0));
706 it->_threadedBindOrdinal = numBinds;
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);
713 // Now that we have the bind ordinal table populate, set the page starts.
715 std::vector<int64_t>& threadedRebaseBindIndices = this->_writer._threadedRebaseBindIndices;
716 threadedRebaseBindIndices.reserve(bindInfo.size() + rebaseInfo.size());
718 for (int64_t i = 0, e = rebaseInfo.size(); i != e; ++i)
719 threadedRebaseBindIndices.push_back(-i);
721 for (int64_t i = 0, e = bindInfo.size(); i != e; ++i)
722 threadedRebaseBindIndices.push_back(i + 1);
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)
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;
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;
747 bind = &bindInfo[entryIndex - 1];
748 address = bind->_address;
750 assert((address & 7) == 0);
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";
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));
767 prevPageIndex = pageIndex;
769 mid.push_back(binding_tmp(BIND_OPCODE_DONE, 0));
771 // convert to compressed encoding
772 this->_encodedData.reserve(bindInfo.size()*2);
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);
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");
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);
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);
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));
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);
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);
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);
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);
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);
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);
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);
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 );
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);
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);
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");
854 // align to pointer size
855 this->_encodedData.append_byte(BIND_OPCODE_DONE);
856 this->_encodedData.pad_to_size(sizeof(pint_t));
858 this->_encoded = true;
860 if (log) fprintf(stderr, "total binding info size = %ld\n", this->_encodedData.size());
865 template <typename A>
866 class WeakBindingInfoAtom : public LinkEditAtom
869 WeakBindingInfoAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
870 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { _encoded = true; }
872 // overrides of ld::Atom
873 virtual const char* name() const { return "weak binding info"; }
874 // overrides of LinkEditAtom
875 virtual void encode() const;
878 typedef typename A::P P;
879 typedef typename A::P::E E;
880 typedef typename A::P::uint_t pint_t;
882 struct WeakBindingSorter
884 bool operator()(const OutputFile::BindingInfo& left, const OutputFile::BindingInfo& right)
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);
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) {}
905 static ld::Section _s_section;
908 template <typename A>
909 ld::Section WeakBindingInfoAtom<A>::_s_section("__LINKEDIT", "__weak_binding", ld::Section::typeLinkEdit, true);
912 template <typename A>
913 void WeakBindingInfoAtom<A>::encode() const
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;
922 std::sort(info.begin(), info.end(), WeakBindingSorter());
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;
932 uint64_t address = (uint64_t)(-1);
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;
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));
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));
953 mid.push_back(binding_tmp(BIND_OPCODE_ADD_ADDR_ULEB, it->_address-address));
955 address = it->_address;
957 if ( addend != it->_addend ) {
958 mid.push_back(binding_tmp(BIND_OPCODE_SET_ADDEND_SLEB, it->_addend));
959 addend = it->_addend;
961 mid.push_back(binding_tmp(BIND_OPCODE_DO_BIND, 0));
962 address += sizeof(pint_t);
965 mid.push_back(binding_tmp(BIND_OPCODE_DONE, 0));
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;
982 dst->opcode = BIND_OPCODE_DONE;
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
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;
995 dst->operand2 = delta;
997 while ( (src->opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
998 && (src->operand1 == delta) ) {
1009 dst->opcode = BIND_OPCODE_DONE;
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);
1020 dst->opcode = BIND_OPCODE_DONE;
1023 // convert to compressed encoding
1024 const static bool log = false;
1025 this->_encodedData.reserve(info.size()*2);
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);
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);
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);
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));
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);
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);
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);
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);
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);
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);
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);
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 );
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);
1093 // align to pointer size
1094 this->_encodedData.pad_to_size(sizeof(pint_t));
1096 this->_encoded = true;
1098 if (log) fprintf(stderr, "total weak binding info size = %ld\n", this->_encodedData.size());
1104 template <typename A>
1105 class LazyBindingInfoAtom : public LinkEditAtom
1108 LazyBindingInfoAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
1109 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) {_encoded = true; }
1111 // overrides of ld::Atom
1112 virtual const char* name() const { return "lazy binding info"; }
1113 // overrides of LinkEditAtom
1114 virtual void encode() const;
1117 typedef typename A::P P;
1118 typedef typename A::P::E E;
1119 typedef typename A::P::uint_t pint_t;
1121 static ld::Section _s_section;
1124 template <typename A>
1125 ld::Section LazyBindingInfoAtom<A>::_s_section("__LINKEDIT", "__lazy_binding", ld::Section::typeLinkEdit, true);
1129 template <typename A>
1130 void LazyBindingInfoAtom<A>::encode() const
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());
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);
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) );
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);
1157 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
1158 this->_encodedData.append_uleb128(it->_libraryOrdinal);
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);
1164 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND);
1165 this->_encodedData.append_byte(BIND_OPCODE_DONE);
1168 // align to pointer size
1169 this->_encodedData.pad_to_size(sizeof(pint_t));
1171 this->_encoded = true;
1172 //fprintf(stderr, "lazy binding info size = %ld, for %ld entries\n", _encodedData.size(), allLazys.size());
1177 template <typename A>
1178 class ExportInfoAtom : public LinkEditAtom
1181 ExportInfoAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
1182 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { _encoded = true; }
1184 // overrides of ld::Atom
1185 virtual const char* name() const { return "export info"; }
1186 // overrides of LinkEditAtom
1187 virtual void encode() const;
1190 typedef typename A::P P;
1191 typedef typename A::P::E E;
1192 typedef typename A::P::uint_t pint_t;
1194 const ld::Atom* stubForResolverFunction(const ld::Atom* resolver) const;
1196 struct TrieEntriesSorter
1198 TrieEntriesSorter(const Options& o) : _options(o) {}
1200 bool operator()(const mach_o::trie::Entry& left, const mach_o::trie::Entry& right)
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);
1209 return (left.address < right.address);
1212 const Options& _options;
1215 static ld::Section _s_section;
1218 template <typename A>
1219 ld::Section ExportInfoAtom<A>::_s_section("__LINKEDIT", "__export", ld::Section::typeLinkEdit, true);
1221 template <typename A>
1222 const ld::Atom* ExportInfoAtom<A>::stubForResolverFunction(const ld::Atom* resolver) const
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 )
1234 assert(0 && "no stub for resolver function");
1239 template <typename A>
1240 void ExportInfoAtom<A>::encode() const
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;
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());
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;
1273 assert(aliasOf != NULL);
1274 entry.importName = aliasOf->name();
1277 // symbol name stays same as re-export
1278 entry.importName = atom->name();
1280 entries.push_back(entry);
1281 //fprintf(stderr, "re-export %s from lib %llu as %s\n", entry.importName, entry.other, entry.name);
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);
1292 if ( (atom->definition() == ld::Atom::definitionRegular) && (atom->combine() == ld::Atom::combineByName) )
1293 flags |= EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION;
1294 if ( atom->isThumb() )
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
1301 const ld::Atom* stub = stubForResolverFunction(atom);
1302 address = stub->finalAddress() - imageBaseAddress;
1303 if ( stub->isThumb() )
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);
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.
1322 // sort vector by -exported_symbols_order, and any others by address
1323 std::sort(entries.begin(), entries.end(), TrieEntriesSorter(_options));
1326 mach_o::trie::makeTrie(entries, this->_encodedData.bytes());
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);
1332 // align to pointer size
1333 this->_encodedData.pad_to_size(sizeof(pint_t));
1335 this->_encoded = true;
1339 template <typename A>
1340 class SplitSegInfoV1Atom : public LinkEditAtom
1343 SplitSegInfoV1Atom(const Options& opts, ld::Internal& state, OutputFile& writer)
1344 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { }
1346 // overrides of ld::Atom
1347 virtual const char* name() const { return "split seg info"; }
1348 // overrides of LinkEditAtom
1349 virtual void encode() const;
1352 typedef typename A::P P;
1353 typedef typename A::P::E E;
1354 typedef typename A::P::uint_t pint_t;
1356 void addSplitSegInfo(uint64_t address, ld::Fixup::Kind k, uint32_t) const;
1357 void uleb128EncodeAddresses(const std::vector<uint64_t>& locations) const;
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;
1368 static ld::Section _s_section;
1371 template <typename A>
1372 ld::Section SplitSegInfoV1Atom<A>::_s_section("__LINKEDIT", "__splitSegInfo", ld::Section::typeLinkEdit, true);
1375 void SplitSegInfoV1Atom<x86_64>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind kind, uint32_t extra) const
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);
1394 case ld::Fixup::kindStoreLittleEndian64:
1395 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
1396 _64bitPointerLocations.push_back(address);
1398 #if SUPPORT_ARCH_arm64e
1399 case ld::Fixup::kindStoreLittleEndianAuth64:
1400 case ld::Fixup::kindStoreTargetAddressLittleEndianAuth64:
1405 warning("codegen at address 0x%08llX prevents image from working in dyld shared cache", address);
1411 void SplitSegInfoV1Atom<x86>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind kind, uint32_t extra) const
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);
1421 warning("codegen at address 0x%08llX prevents image from working in dyld shared cache", address);
1427 void SplitSegInfoV1Atom<arm>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind kind, uint32_t extra) const
1430 case ld::Fixup::kindStoreLittleEndian32:
1431 _32bitPointerLocations.push_back(address);
1433 case ld::Fixup::kindStoreARMLow16:
1434 _armLo16Locations.push_back(address);
1436 case ld::Fixup::kindStoreThumbLow16:
1437 _thumbLo16Locations.push_back(address);
1439 case ld::Fixup::kindStoreARMHigh16:
1441 _armHi16Locations[extra].push_back(address);
1443 case ld::Fixup::kindStoreThumbHigh16:
1445 _thumbHi16Locations[extra].push_back(address);
1448 warning("codegen at address 0x%08llX prevents image from working in dyld shared cache", address);
1453 #if SUPPORT_ARCH_arm64
1455 void SplitSegInfoV1Atom<arm64>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind kind, uint32_t extra) const
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);
1467 case ld::Fixup::kindStoreLittleEndian32:
1468 case ld::Fixup::kindStoreARM64PCRelToGOT:
1469 _32bitPointerLocations.push_back(address);
1471 case ld::Fixup::kindStoreLittleEndian64:
1472 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
1473 _64bitPointerLocations.push_back(address);
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);
1482 warning("codegen at address 0x%08llX prevents image from working in dyld shared cache", address);
1488 template <typename A>
1489 void SplitSegInfoV1Atom<A>::uleb128EncodeAddresses(const std::vector<uint64_t>& locations) const
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);
1498 throw "double split seg info for same address";
1502 byte = delta & 0x7F;
1506 this->_encodedData.append_byte(byte);
1509 while( byte >= 0x80 );
1515 template <typename A>
1516 void SplitSegInfoV1Atom<A>::encode() const
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);
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
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
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
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
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
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
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
1586 // always add zero byte to mark end
1587 this->_encodedData.append_byte(0);
1589 // align to pointer size
1590 this->_encodedData.pad_to_size(sizeof(pint_t));
1592 this->_encoded = true;
1594 // clean up temporaries
1595 _32bitPointerLocations.clear();
1596 _64bitPointerLocations.clear();
1600 template <typename A>
1601 class SplitSegInfoV2Atom : public LinkEditAtom
1604 SplitSegInfoV2Atom(const Options& opts, ld::Internal& state, OutputFile& writer)
1605 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { }
1607 // overrides of ld::Atom
1608 virtual const char* name() const { return "split seg info"; }
1609 // overrides of LinkEditAtom
1610 virtual void encode() const;
1613 typedef typename A::P P;
1614 typedef typename A::P::E E;
1615 typedef typename A::P::uint_t pint_t;
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>
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;
1628 static ld::Section _s_section;
1631 template <typename A>
1632 ld::Section SplitSegInfoV2Atom<A>::_s_section("__LINKEDIT", "__splitSegInfo", ld::Section::typeLinkEdit, true);
1635 template <typename A>
1636 void SplitSegInfoV2Atom<A>::encode() const
1638 // sort into group by adjustment kind
1639 //fprintf(stderr, "_splitSegV2Infos.size=%lu\n", this->_writer._splitSegV2Infos.size());
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);
1649 // Add marker that this is V2 data
1650 this->_encodedData.reserve(8192);
1651 this->_encodedData.append_byte(DYLD_CACHE_ADJ_V2_FORMAT);
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;
1685 lastToOffset = toSectionOffset;
1690 // always add zero byte to mark end
1691 this->_encodedData.append_byte(0);
1693 // align to pointer size
1694 this->_encodedData.pad_to_size(sizeof(pint_t));
1696 this->_encoded = true;
1701 template <typename A>
1702 class FunctionStartsAtom : public LinkEditAtom
1705 FunctionStartsAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
1706 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { }
1708 // overrides of ld::Atom
1709 virtual const char* name() const { return "function starts"; }
1710 // overrides of LinkEditAtom
1711 virtual void encode() const;
1714 typedef typename A::P P;
1715 typedef typename A::P::E E;
1716 typedef typename A::P::uint_t pint_t;
1718 static ld::Section _s_section;
1721 template <typename A>
1722 ld::Section FunctionStartsAtom<A>::_s_section("__LINKEDIT", "__funcStarts", ld::Section::typeLinkEdit, true);
1725 template <typename A>
1726 void FunctionStartsAtom<A>::encode() const
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;
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 )
1746 uint64_t nextAddr = atom->finalAddress();
1747 if ( atom->isThumb() )
1749 uint64_t delta = nextAddr - addr;
1751 this->_encodedData.append_uleb128(delta);
1758 this->_encodedData.append_byte(0);
1760 // align to pointer size
1761 this->_encodedData.pad_to_size(sizeof(pint_t));
1763 this->_encoded = true;
1767 // <rdar://problem/9218847> Need way to formalize data in code
1768 template <typename A>
1769 class DataInCodeAtom : public LinkEditAtom
1772 DataInCodeAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
1773 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { }
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;
1781 typedef typename A::P P;
1782 typedef typename A::P::E E;
1783 typedef typename A::P::uint_t pint_t;
1785 struct FixupByAddressSorter
1787 bool operator()(const ld::Fixup* left, const ld::Fixup* right)
1789 return (left->offsetInAtom < right->offsetInAtom);
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);
1796 macho_data_in_code_entry<P> entry;
1797 entry.set_offset(startImageOffset);
1798 entry.set_length(len);
1800 case ld::Fixup::kindDataInCodeStartData:
1801 entry.set_kind(DICE_KIND_DATA);
1803 case ld::Fixup::kindDataInCodeStartJT8:
1804 entry.set_kind(DICE_KIND_JUMP_TABLE8);
1806 case ld::Fixup::kindDataInCodeStartJT16:
1807 entry.set_kind(DICE_KIND_JUMP_TABLE16);
1809 case ld::Fixup::kindDataInCodeStartJT32:
1810 entry.set_kind(DICE_KIND_JUMP_TABLE32);
1812 case ld::Fixup::kindDataInCodeStartJTA32:
1813 entry.set_kind(DICE_KIND_ABS_JUMP_TABLE32);
1816 assert(0 && "bad L$start$ label to encode");
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
1829 startImageOffset += 0xFFF8;
1830 } while ( len > 0 );
1833 static ld::Section _s_section;
1836 template <typename A>
1837 ld::Section DataInCodeAtom<A>::_s_section("__LINKEDIT", "__dataInCode", ld::Section::typeLinkEdit, true);
1840 template <typename A>
1841 void DataInCodeAtom<A>::encode() const
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 )
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);
1869 // to do: sort labels by address
1870 std::sort(dataInCodeLabels.begin(), dataInCodeLabels.end(), FixupByAddressSorter());
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;
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);
1882 prevKind = (*sfit)->kind;
1883 prevOffset = (*sfit)->offsetInAtom;
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);
1893 this->_encoded = true;
1901 template <typename A>
1902 class OptimizationHintsAtom : public LinkEditAtom
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);
1910 // overrides of ld::Atom
1911 virtual const char* name() const { return "linker optimization hints"; }
1912 // overrides of LinkEditAtom
1913 virtual void encode() const;
1916 typedef typename A::P P;
1917 typedef typename A::P::E E;
1918 typedef typename A::P::uint_t pint_t;
1920 static ld::Section _s_section;
1924 template <typename A>
1925 ld::Section OptimizationHintsAtom<A>::_s_section("__LINKEDIT", "__opt_hints", ld::Section::typeLinkEdit, true);
1927 template <typename A>
1928 void OptimizationHintsAtom<A>::encode() const
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 )
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)
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);
1956 this->_encodedData.pad_to_size(sizeof(pint_t));
1959 this->_encoded = true;
1966 #endif // __LINKEDIT_HPP__