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;
181 rebase_tmp(uint8_t op, uint64_t p1, uint64_t p2=0) : opcode(op), operand1(p1), operand2(p2) {}
187 typedef typename A::P P;
188 typedef typename A::P::E E;
189 typedef typename A::P::uint_t pint_t;
191 static ld::Section _s_section;
194 template <typename A>
195 ld::Section RebaseInfoAtom<A>::_s_section("__LINKEDIT", "__rebase", ld::Section::typeLinkEdit, true);
198 template <typename A>
199 void RebaseInfoAtom<A>::encode() const
201 // omit relocs if this was supposed to be PIE but PIE not possible
202 if ( _options.positionIndependentExecutable() && this->_writer.pieDisabled )
205 // sort rebase info by type, then address
206 std::vector<OutputFile::RebaseInfo>& info = this->_writer._rebaseInfo;
207 std::sort(info.begin(), info.end());
209 // convert to temp encoding that can be more easily optimized
210 std::vector<rebase_tmp> mid;
211 uint64_t curSegStart = 0;
212 uint64_t curSegEnd = 0;
213 uint32_t curSegIndex = 0;
215 uint64_t address = (uint64_t)(-1);
216 for (std::vector<OutputFile::RebaseInfo>::iterator it = info.begin(); it != info.end(); ++it) {
217 if ( type != it->_type ) {
218 mid.push_back(rebase_tmp(REBASE_OPCODE_SET_TYPE_IMM, it->_type));
221 if ( address != it->_address ) {
222 if ( (it->_address < curSegStart) || ( it->_address >= curSegEnd) ) {
223 if ( ! this->_writer.findSegment(this->_state, it->_address, &curSegStart, &curSegEnd, &curSegIndex) )
224 throw "binding address outside range of any segment";
225 mid.push_back(rebase_tmp(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, curSegIndex, it->_address - curSegStart));
228 mid.push_back(rebase_tmp(REBASE_OPCODE_ADD_ADDR_ULEB, it->_address-address));
230 address = it->_address;
232 mid.push_back(rebase_tmp(REBASE_OPCODE_DO_REBASE_ULEB_TIMES, 1));
233 address += sizeof(pint_t);
234 if ( address >= curSegEnd )
237 mid.push_back(rebase_tmp(REBASE_OPCODE_DONE, 0));
239 // optimize phase 1, compress packed runs of pointers
240 rebase_tmp* dst = &mid[0];
241 for (const rebase_tmp* src = &mid[0]; src->opcode != REBASE_OPCODE_DONE; ++src) {
242 if ( (src->opcode == REBASE_OPCODE_DO_REBASE_ULEB_TIMES) && (src->operand1 == 1) ) {
244 while (src->opcode == REBASE_OPCODE_DO_REBASE_ULEB_TIMES ) {
245 dst->operand1 += src->operand1;
255 dst->opcode = REBASE_OPCODE_DONE;
257 // optimize phase 2, combine rebase/add pairs
259 for (const rebase_tmp* src = &mid[0]; src->opcode != REBASE_OPCODE_DONE; ++src) {
260 if ( (src->opcode == REBASE_OPCODE_DO_REBASE_ULEB_TIMES)
261 && (src->operand1 == 1)
262 && (src[1].opcode == REBASE_OPCODE_ADD_ADDR_ULEB)) {
263 dst->opcode = REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB;
264 dst->operand1 = src[1].operand1;
272 dst->opcode = REBASE_OPCODE_DONE;
274 // optimize phase 3, compress packed runs of REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB with
275 // same addr delta into one REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB
277 for (const rebase_tmp* src = &mid[0]; src->opcode != REBASE_OPCODE_DONE; ++src) {
278 uint64_t delta = src->operand1;
279 if ( (src->opcode == REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB)
280 && (src[1].opcode == REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB)
281 && (src[2].opcode == REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB)
282 && (src[1].operand1 == delta)
283 && (src[2].operand1 == delta) ) {
284 // found at least three in a row, this is worth compressing
285 dst->opcode = REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB;
287 dst->operand2 = delta;
289 while ( (src->opcode == REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB)
290 && (src->operand1 == delta) ) {
301 dst->opcode = REBASE_OPCODE_DONE;
303 // optimize phase 4, use immediate encodings
304 for (rebase_tmp* p = &mid[0]; p->opcode != REBASE_OPCODE_DONE; ++p) {
305 if ( (p->opcode == REBASE_OPCODE_ADD_ADDR_ULEB)
306 && (p->operand1 < (15*sizeof(pint_t)))
307 && ((p->operand1 % sizeof(pint_t)) == 0) ) {
308 p->opcode = REBASE_OPCODE_ADD_ADDR_IMM_SCALED;
309 p->operand1 = p->operand1/sizeof(pint_t);
311 else if ( (p->opcode == REBASE_OPCODE_DO_REBASE_ULEB_TIMES) && (p->operand1 < 15) ) {
312 p->opcode = REBASE_OPCODE_DO_REBASE_IMM_TIMES;
316 // convert to compressed encoding
317 const static bool log = false;
318 this->_encodedData.reserve(info.size()*2);
320 for (typename std::vector<rebase_tmp>::iterator it = mid.begin(); !done && it != mid.end() ; ++it) {
321 switch ( it->opcode ) {
322 case REBASE_OPCODE_DONE:
323 if ( log ) fprintf(stderr, "REBASE_OPCODE_DONE()\n");
326 case REBASE_OPCODE_SET_TYPE_IMM:
327 if ( log ) fprintf(stderr, "REBASE_OPCODE_SET_TYPE_IMM(%lld)\n", it->operand1);
328 this->_encodedData.append_byte(REBASE_OPCODE_SET_TYPE_IMM | it->operand1);
330 case REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
331 if ( log ) fprintf(stderr, "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB(%lld, 0x%llX)\n", it->operand1, it->operand2);
332 this->_encodedData.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | it->operand1);
333 this->_encodedData.append_uleb128(it->operand2);
335 case REBASE_OPCODE_ADD_ADDR_ULEB:
336 if ( log ) fprintf(stderr, "REBASE_OPCODE_ADD_ADDR_ULEB(0x%llX)\n", it->operand1);
337 this->_encodedData.append_byte(REBASE_OPCODE_ADD_ADDR_ULEB);
338 this->_encodedData.append_uleb128(it->operand1);
340 case REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
341 if ( log ) fprintf(stderr, "REBASE_OPCODE_ADD_ADDR_IMM_SCALED(%lld=0x%llX)\n", it->operand1, it->operand1*sizeof(pint_t));
342 this->_encodedData.append_byte(REBASE_OPCODE_ADD_ADDR_IMM_SCALED | it->operand1 );
344 case REBASE_OPCODE_DO_REBASE_IMM_TIMES:
345 if ( log ) fprintf(stderr, "REBASE_OPCODE_DO_REBASE_IMM_TIMES(%lld)\n", it->operand1);
346 this->_encodedData.append_byte(REBASE_OPCODE_DO_REBASE_IMM_TIMES | it->operand1);
348 case REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
349 if ( log ) fprintf(stderr, "REBASE_OPCODE_DO_REBASE_ULEB_TIMES(%lld)\n", it->operand1);
350 this->_encodedData.append_byte(REBASE_OPCODE_DO_REBASE_ULEB_TIMES);
351 this->_encodedData.append_uleb128(it->operand1);
353 case REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
354 if ( log ) fprintf(stderr, "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB(0x%llX)\n", it->operand1);
355 this->_encodedData.append_byte(REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB);
356 this->_encodedData.append_uleb128(it->operand1);
358 case REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
359 if ( log ) fprintf(stderr, "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB(%lld, %lld)\n", it->operand1, it->operand2);
360 this->_encodedData.append_byte(REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB);
361 this->_encodedData.append_uleb128(it->operand1);
362 this->_encodedData.append_uleb128(it->operand2);
368 // align to pointer size
369 this->_encodedData.pad_to_size(sizeof(pint_t));
371 this->_encoded = true;
373 if (log) fprintf(stderr, "total rebase info size = %ld\n", this->_encodedData.size());
377 template <typename A>
378 class BindingInfoAtom : public LinkEditAtom
381 BindingInfoAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
382 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { }
384 // overrides of ld::Atom
385 virtual const char* name() const { return "binding info"; }
386 // overrides of LinkEditAtom
387 virtual void encode() const;
391 typedef typename A::P P;
392 typedef typename A::P::E E;
393 typedef typename A::P::uint_t pint_t;
397 binding_tmp(uint8_t op, uint64_t p1, uint64_t p2=0, const char* s=NULL)
398 : opcode(op), operand1(p1), operand2(p2), name(s) {}
405 static ld::Section _s_section;
408 template <typename A>
409 ld::Section BindingInfoAtom<A>::_s_section("__LINKEDIT", "__binding", ld::Section::typeLinkEdit, true);
412 template <typename A>
413 void BindingInfoAtom<A>::encode() const
415 // sort by library, symbol, type, then address
416 std::vector<OutputFile::BindingInfo>& info = this->_writer._bindingInfo;
417 std::sort(info.begin(), info.end());
419 // convert to temp encoding that can be more easily optimized
420 std::vector<binding_tmp> mid;
421 uint64_t curSegStart = 0;
422 uint64_t curSegEnd = 0;
423 uint32_t curSegIndex = 0;
424 int ordinal = 0x80000000;
425 const char* symbolName = NULL;
427 uint64_t address = (uint64_t)(-1);
429 for (std::vector<OutputFile::BindingInfo>::const_iterator it = info.begin(); it != info.end(); ++it) {
430 if ( ordinal != it->_libraryOrdinal ) {
431 if ( it->_libraryOrdinal <= 0 ) {
432 // special lookups are encoded as negative numbers in BindingInfo
433 mid.push_back(binding_tmp(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM, it->_libraryOrdinal));
436 mid.push_back(binding_tmp(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB, it->_libraryOrdinal));
438 ordinal = it->_libraryOrdinal;
440 if ( symbolName != it->_symbolName ) {
441 mid.push_back(binding_tmp(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM, it->_flags, 0, it->_symbolName));
442 symbolName = it->_symbolName;
444 if ( type != it->_type ) {
445 mid.push_back(binding_tmp(BIND_OPCODE_SET_TYPE_IMM, it->_type));
448 if ( address != it->_address ) {
449 if ( (it->_address < curSegStart) || ( it->_address >= curSegEnd) ) {
450 if ( ! this->_writer.findSegment(this->_state, it->_address, &curSegStart, &curSegEnd, &curSegIndex) )
451 throw "binding address outside range of any segment";
452 mid.push_back(binding_tmp(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, curSegIndex, it->_address - curSegStart));
455 mid.push_back(binding_tmp(BIND_OPCODE_ADD_ADDR_ULEB, it->_address-address));
457 address = it->_address;
459 if ( addend != it->_addend ) {
460 mid.push_back(binding_tmp(BIND_OPCODE_SET_ADDEND_SLEB, it->_addend));
461 addend = it->_addend;
463 mid.push_back(binding_tmp(BIND_OPCODE_DO_BIND, 0));
464 address += sizeof(pint_t);
466 mid.push_back(binding_tmp(BIND_OPCODE_DONE, 0));
469 // optimize phase 1, combine bind/add pairs
470 binding_tmp* dst = &mid[0];
471 for (const binding_tmp* src = &mid[0]; src->opcode != BIND_OPCODE_DONE; ++src) {
472 if ( (src->opcode == BIND_OPCODE_DO_BIND)
473 && (src[1].opcode == BIND_OPCODE_ADD_ADDR_ULEB) ) {
474 dst->opcode = BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB;
475 dst->operand1 = src[1].operand1;
483 dst->opcode = BIND_OPCODE_DONE;
485 // optimize phase 2, compress packed runs of BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB with
486 // same addr delta into one BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB
488 for (const binding_tmp* src = &mid[0]; src->opcode != BIND_OPCODE_DONE; ++src) {
489 uint64_t delta = src->operand1;
490 if ( (src->opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
491 && (src[1].opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
492 && (src[1].operand1 == delta) ) {
493 // found at least two in a row, this is worth compressing
494 dst->opcode = BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB;
496 dst->operand2 = delta;
498 while ( (src->opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
499 && (src->operand1 == delta) ) {
510 dst->opcode = BIND_OPCODE_DONE;
512 // optimize phase 3, use immediate encodings
513 for (binding_tmp* p = &mid[0]; p->opcode != REBASE_OPCODE_DONE; ++p) {
514 if ( (p->opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
515 && (p->operand1 < (15*sizeof(pint_t)))
516 && ((p->operand1 % sizeof(pint_t)) == 0) ) {
517 p->opcode = BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED;
518 p->operand1 = p->operand1/sizeof(pint_t);
520 else if ( (p->opcode == BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB) && (p->operand1 <= 15) ) {
521 p->opcode = BIND_OPCODE_SET_DYLIB_ORDINAL_IMM;
524 dst->opcode = BIND_OPCODE_DONE;
526 // convert to compressed encoding
527 const static bool log = false;
528 this->_encodedData.reserve(info.size()*2);
530 for (typename std::vector<binding_tmp>::iterator it = mid.begin(); !done && it != mid.end() ; ++it) {
531 switch ( it->opcode ) {
532 case BIND_OPCODE_DONE:
533 if ( log ) fprintf(stderr, "BIND_OPCODE_DONE()\n");
536 case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
537 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM(%lld)\n", it->operand1);
538 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | it->operand1);
540 case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
541 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB(%lld)\n", it->operand1);
542 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
543 this->_encodedData.append_uleb128(it->operand1);
545 case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
546 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM(%lld)\n", it->operand1);
547 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | (it->operand1 & BIND_IMMEDIATE_MASK));
549 case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
550 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM(0x%0llX, %s)\n", it->operand1, it->name);
551 this->_encodedData.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | it->operand1);
552 this->_encodedData.append_string(it->name);
554 case BIND_OPCODE_SET_TYPE_IMM:
555 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_TYPE_IMM(%lld)\n", it->operand1);
556 this->_encodedData.append_byte(BIND_OPCODE_SET_TYPE_IMM | it->operand1);
558 case BIND_OPCODE_SET_ADDEND_SLEB:
559 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_ADDEND_SLEB(%lld)\n", it->operand1);
560 this->_encodedData.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
561 this->_encodedData.append_sleb128(it->operand1);
563 case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
564 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB(%lld, 0x%llX)\n", it->operand1, it->operand2);
565 this->_encodedData.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | it->operand1);
566 this->_encodedData.append_uleb128(it->operand2);
568 case BIND_OPCODE_ADD_ADDR_ULEB:
569 if ( log ) fprintf(stderr, "BIND_OPCODE_ADD_ADDR_ULEB(0x%llX)\n", it->operand1);
570 this->_encodedData.append_byte(BIND_OPCODE_ADD_ADDR_ULEB);
571 this->_encodedData.append_uleb128(it->operand1);
573 case BIND_OPCODE_DO_BIND:
574 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND()\n");
575 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND);
577 case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
578 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB(0x%llX)\n", it->operand1);
579 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB);
580 this->_encodedData.append_uleb128(it->operand1);
582 case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
583 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED(%lld=0x%llX)\n", it->operand1, it->operand1*sizeof(pint_t));
584 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED | it->operand1 );
586 case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
587 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB(%lld, %lld)\n", it->operand1, it->operand2);
588 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB);
589 this->_encodedData.append_uleb128(it->operand1);
590 this->_encodedData.append_uleb128(it->operand2);
595 // align to pointer size
596 this->_encodedData.pad_to_size(sizeof(pint_t));
598 this->_encoded = true;
600 if (log) fprintf(stderr, "total binding info size = %ld\n", this->_encodedData.size());
605 template <typename A>
606 class WeakBindingInfoAtom : public LinkEditAtom
609 WeakBindingInfoAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
610 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { _encoded = true; }
612 // overrides of ld::Atom
613 virtual const char* name() const { return "weak binding info"; }
614 // overrides of LinkEditAtom
615 virtual void encode() const;
618 typedef typename A::P P;
619 typedef typename A::P::E E;
620 typedef typename A::P::uint_t pint_t;
622 struct WeakBindingSorter
624 bool operator()(const OutputFile::BindingInfo& left, const OutputFile::BindingInfo& right)
626 // sort by symbol, type, address
627 if ( left._symbolName != right._symbolName )
628 return ( strcmp(left._symbolName, right._symbolName) < 0 );
629 if ( left._type != right._type )
630 return (left._type < right._type);
631 return (left._address < right._address);
637 binding_tmp(uint8_t op, uint64_t p1, uint64_t p2=0, const char* s=NULL)
638 : opcode(op), operand1(p1), operand2(p2), name(s) {}
645 static ld::Section _s_section;
648 template <typename A>
649 ld::Section WeakBindingInfoAtom<A>::_s_section("__LINKEDIT", "__weak_binding", ld::Section::typeLinkEdit, true);
652 template <typename A>
653 void WeakBindingInfoAtom<A>::encode() const
655 // sort by symbol, type, address
656 std::vector<OutputFile::BindingInfo>& info = this->_writer._weakBindingInfo;
657 if ( info.size() == 0 ) {
658 // short circuit if no weak binding needed
659 this->_encoded = true;
662 std::sort(info.begin(), info.end(), WeakBindingSorter());
664 // convert to temp encoding that can be more easily optimized
665 std::vector<binding_tmp> mid;
666 mid.reserve(info.size());
667 uint64_t curSegStart = 0;
668 uint64_t curSegEnd = 0;
669 uint32_t curSegIndex = 0;
670 const char* symbolName = NULL;
672 uint64_t address = (uint64_t)(-1);
674 for (typename std::vector<OutputFile::BindingInfo>::const_iterator it = info.begin(); it != info.end(); ++it) {
675 if ( symbolName != it->_symbolName ) {
676 mid.push_back(binding_tmp(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM, it->_flags, 0, it->_symbolName));
677 symbolName = it->_symbolName;
679 // non-weak symbols just have BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
680 // weak symbols have SET_SEG, ADD_ADDR, SET_ADDED, DO_BIND
681 if ( it->_type != BIND_TYPE_OVERRIDE_OF_WEAKDEF_IN_DYLIB ) {
682 if ( type != it->_type ) {
683 mid.push_back(binding_tmp(BIND_OPCODE_SET_TYPE_IMM, it->_type));
686 if ( address != it->_address ) {
687 if ( (it->_address < curSegStart) || ( it->_address >= curSegEnd) ) {
688 if ( ! this->_writer.findSegment(this->_state, it->_address, &curSegStart, &curSegEnd, &curSegIndex) )
689 throw "binding address outside range of any segment";
690 mid.push_back(binding_tmp(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, curSegIndex, it->_address - curSegStart));
693 mid.push_back(binding_tmp(BIND_OPCODE_ADD_ADDR_ULEB, it->_address-address));
695 address = it->_address;
697 if ( addend != it->_addend ) {
698 mid.push_back(binding_tmp(BIND_OPCODE_SET_ADDEND_SLEB, it->_addend));
699 addend = it->_addend;
701 mid.push_back(binding_tmp(BIND_OPCODE_DO_BIND, 0));
702 address += sizeof(pint_t);
705 mid.push_back(binding_tmp(BIND_OPCODE_DONE, 0));
708 // optimize phase 1, combine bind/add pairs
709 binding_tmp* dst = &mid[0];
710 for (const binding_tmp* src = &mid[0]; src->opcode != BIND_OPCODE_DONE; ++src) {
711 if ( (src->opcode == BIND_OPCODE_DO_BIND)
712 && (src[1].opcode == BIND_OPCODE_ADD_ADDR_ULEB) ) {
713 dst->opcode = BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB;
714 dst->operand1 = src[1].operand1;
722 dst->opcode = BIND_OPCODE_DONE;
724 // optimize phase 2, compress packed runs of BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB with
725 // same addr delta into one BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB
727 for (const binding_tmp* src = &mid[0]; src->opcode != BIND_OPCODE_DONE; ++src) {
728 uint64_t delta = src->operand1;
729 if ( (src->opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
730 && (src[1].opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
731 && (src[1].operand1 == delta) ) {
732 // found at least two in a row, this is worth compressing
733 dst->opcode = BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB;
735 dst->operand2 = delta;
737 while ( (src->opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
738 && (src->operand1 == delta) ) {
749 dst->opcode = BIND_OPCODE_DONE;
751 // optimize phase 3, use immediate encodings
752 for (binding_tmp* p = &mid[0]; p->opcode != REBASE_OPCODE_DONE; ++p) {
753 if ( (p->opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
754 && (p->operand1 < (15*sizeof(pint_t)))
755 && ((p->operand1 % sizeof(pint_t)) == 0) ) {
756 p->opcode = BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED;
757 p->operand1 = p->operand1/sizeof(pint_t);
760 dst->opcode = BIND_OPCODE_DONE;
763 // convert to compressed encoding
764 const static bool log = false;
765 this->_encodedData.reserve(info.size()*2);
767 for (typename std::vector<binding_tmp>::iterator it = mid.begin(); !done && it != mid.end() ; ++it) {
768 switch ( it->opcode ) {
769 case BIND_OPCODE_DONE:
770 if ( log ) fprintf(stderr, "BIND_OPCODE_DONE()\n");
771 this->_encodedData.append_byte(BIND_OPCODE_DONE);
774 case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
775 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM(%lld)\n", it->operand1);
776 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | it->operand1);
778 case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
779 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB(%lld)\n", it->operand1);
780 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
781 this->_encodedData.append_uleb128(it->operand1);
783 case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
784 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM(%lld)\n", it->operand1);
785 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | (it->operand1 & BIND_IMMEDIATE_MASK));
787 case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
788 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM(0x%0llX, %s)\n", it->operand1, it->name);
789 this->_encodedData.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | it->operand1);
790 this->_encodedData.append_string(it->name);
792 case BIND_OPCODE_SET_TYPE_IMM:
793 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_TYPE_IMM(%lld)\n", it->operand1);
794 this->_encodedData.append_byte(BIND_OPCODE_SET_TYPE_IMM | it->operand1);
796 case BIND_OPCODE_SET_ADDEND_SLEB:
797 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_ADDEND_SLEB(%lld)\n", it->operand1);
798 this->_encodedData.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
799 this->_encodedData.append_sleb128(it->operand1);
801 case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
802 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB(%lld, 0x%llX)\n", it->operand1, it->operand2);
803 this->_encodedData.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | it->operand1);
804 this->_encodedData.append_uleb128(it->operand2);
806 case BIND_OPCODE_ADD_ADDR_ULEB:
807 if ( log ) fprintf(stderr, "BIND_OPCODE_ADD_ADDR_ULEB(0x%llX)\n", it->operand1);
808 this->_encodedData.append_byte(BIND_OPCODE_ADD_ADDR_ULEB);
809 this->_encodedData.append_uleb128(it->operand1);
811 case BIND_OPCODE_DO_BIND:
812 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND()\n");
813 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND);
815 case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
816 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB(0x%llX)\n", it->operand1);
817 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB);
818 this->_encodedData.append_uleb128(it->operand1);
820 case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
821 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED(%lld=0x%llX)\n", it->operand1, it->operand1*sizeof(pint_t));
822 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED | it->operand1 );
824 case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
825 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB(%lld, %lld)\n", it->operand1, it->operand2);
826 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB);
827 this->_encodedData.append_uleb128(it->operand1);
828 this->_encodedData.append_uleb128(it->operand2);
833 // align to pointer size
834 this->_encodedData.pad_to_size(sizeof(pint_t));
836 this->_encoded = true;
838 if (log) fprintf(stderr, "total weak binding info size = %ld\n", this->_encodedData.size());
844 template <typename A>
845 class LazyBindingInfoAtom : public LinkEditAtom
848 LazyBindingInfoAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
849 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) {_encoded = true; }
851 // overrides of ld::Atom
852 virtual const char* name() const { return "lazy binding info"; }
853 // overrides of LinkEditAtom
854 virtual void encode() const;
857 typedef typename A::P P;
858 typedef typename A::P::E E;
859 typedef typename A::P::uint_t pint_t;
861 static ld::Section _s_section;
864 template <typename A>
865 ld::Section LazyBindingInfoAtom<A>::_s_section("__LINKEDIT", "__lazy_binding", ld::Section::typeLinkEdit, true);
869 template <typename A>
870 void LazyBindingInfoAtom<A>::encode() const
872 // stream all lazy bindings and record start offsets
873 std::vector<OutputFile::BindingInfo>& info = this->_writer._lazyBindingInfo;
874 for (std::vector<OutputFile::BindingInfo>::const_iterator it = info.begin(); it != info.end(); ++it) {
875 // record start offset for use by stub helper
876 this->_writer.setLazyBindingInfoOffset(it->_address, this->_encodedData.size());
878 // write address to bind
879 uint64_t segStart = 0;
881 uint32_t segIndex = 0;
882 if ( ! this->_writer.findSegment(this->_state, it->_address, &segStart, &segEnd, &segIndex) )
883 throw "lazy binding address outside range of any segment";
884 this->_encodedData.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | segIndex);
885 this->_encodedData.append_uleb128(it->_address - segStart);
888 if ( it->_libraryOrdinal <= 0 ) {
889 // special lookups are encoded as negative numbers in BindingInfo
890 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | (it->_libraryOrdinal & BIND_IMMEDIATE_MASK) );
892 else if ( it->_libraryOrdinal <= 15 ) {
893 // small ordinals are encoded in opcode
894 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | it->_libraryOrdinal);
897 this->_encodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
898 this->_encodedData.append_uleb128(it->_libraryOrdinal);
901 this->_encodedData.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | it->_flags);
902 this->_encodedData.append_string(it->_symbolName);
904 this->_encodedData.append_byte(BIND_OPCODE_DO_BIND);
905 this->_encodedData.append_byte(BIND_OPCODE_DONE);
908 // align to pointer size
909 this->_encodedData.pad_to_size(sizeof(pint_t));
911 this->_encoded = true;
912 //fprintf(stderr, "lazy binding info size = %ld, for %ld entries\n", _encodedData.size(), allLazys.size());
917 template <typename A>
918 class ExportInfoAtom : public LinkEditAtom
921 ExportInfoAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
922 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { _encoded = true; }
924 // overrides of ld::Atom
925 virtual const char* name() const { return "export info"; }
926 // overrides of LinkEditAtom
927 virtual void encode() const;
930 typedef typename A::P P;
931 typedef typename A::P::E E;
932 typedef typename A::P::uint_t pint_t;
934 const ld::Atom* stubForResolverFunction(const ld::Atom* resolver) const;
936 struct TrieEntriesSorter
938 TrieEntriesSorter(const Options& o) : _options(o) {}
940 bool operator()(const mach_o::trie::Entry& left, const mach_o::trie::Entry& right)
942 unsigned int leftOrder;
943 unsigned int rightOrder;
944 _options.exportedSymbolOrder(left.name, &leftOrder);
945 _options.exportedSymbolOrder(right.name, &rightOrder);
946 if ( leftOrder != rightOrder )
947 return (leftOrder < rightOrder);
949 return (left.address < right.address);
952 const Options& _options;
955 static ld::Section _s_section;
958 template <typename A>
959 ld::Section ExportInfoAtom<A>::_s_section("__LINKEDIT", "__export", ld::Section::typeLinkEdit, true);
961 template <typename A>
962 const ld::Atom* ExportInfoAtom<A>::stubForResolverFunction(const ld::Atom* resolver) const
964 for (std::vector<ld::Internal::FinalSection*>::iterator sit = _state.sections.begin(); sit != _state.sections.end(); ++sit) {
965 ld::Internal::FinalSection* sect = *sit;
966 if ( (sect->type() == ld::Section::typeStub) || (sect->type() == ld::Section::typeStubClose) ) {
967 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
968 const ld::Atom* atom = *ait;
969 if ( strcmp(atom->name(), resolver->name()) == 0 )
974 assert(0 && "no stub for resolver function");
979 template <typename A>
980 void ExportInfoAtom<A>::encode() const
982 // make vector of mach_o::trie::Entry for all exported symbols
983 std::vector<const ld::Atom*>& exports = this->_writer._exportedAtoms;
984 uint64_t imageBaseAddress = this->_writer.headerAndLoadCommandsSection->address;
985 std::vector<mach_o::trie::Entry> entries;
986 unsigned int padding = 0;
987 entries.reserve(exports.size());
988 for (std::vector<const ld::Atom*>::const_iterator it = exports.begin(); it != exports.end(); ++it) {
989 const ld::Atom* atom = *it;
990 mach_o::trie::Entry entry;
991 uint64_t flags = (atom->contentType() == ld::Atom::typeTLV) ? EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL : EXPORT_SYMBOL_FLAGS_KIND_REGULAR;
993 uint64_t address = atom->finalAddress() - imageBaseAddress;
994 if ( atom->definition() == ld::Atom::definitionProxy ) {
995 entry.name = atom->name();
996 entry.flags = flags | EXPORT_SYMBOL_FLAGS_REEXPORT;
997 if ( atom->combine() == ld::Atom::combineByName )
998 entry.flags |= EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION;
999 entry.other = this->_writer.compressedOrdinalForAtom(atom);
1000 if ( entry.other == BIND_SPECIAL_DYLIB_SELF ) {
1001 warning("not adding explict export for symbol %s because it is already re-exported from dylib %s", entry.name, atom->file()->path());
1004 if ( atom->isAlias() ) {
1005 // alias proxy means symbol was re-exported with a name change
1006 const ld::Atom* aliasOf = NULL;
1007 for (ld::Fixup::iterator fit = atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
1008 if ( fit->kind == ld::Fixup::kindNoneFollowOn ) {
1009 assert(fit->binding == ld::Fixup::bindingDirectlyBound);
1010 aliasOf = fit->u.target;
1013 assert(aliasOf != NULL);
1014 entry.importName = aliasOf->name();
1017 // symbol name stays same as re-export
1018 entry.importName = atom->name();
1020 entries.push_back(entry);
1021 //fprintf(stderr, "re-export %s from lib %llu as %s\n", entry.importName, entry.other, entry.name);
1023 else if ( atom->definition() == ld::Atom::definitionAbsolute ) {
1024 entry.name = atom->name();
1025 entry.flags = _options.canUseAbsoluteSymbols() ? EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE : EXPORT_SYMBOL_FLAGS_KIND_REGULAR;
1026 entry.address = address;
1027 entry.other = other;
1028 entry.importName = NULL;
1029 entries.push_back(entry);
1032 if ( (atom->definition() == ld::Atom::definitionRegular) && (atom->combine() == ld::Atom::combineByName) )
1033 flags |= EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION;
1034 if ( atom->isThumb() )
1036 if ( atom->contentType() == ld::Atom::typeResolver ) {
1037 flags |= EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER;
1038 // set normal lookup to return stub address
1039 // and add resolver function in new location that newer dyld's can access
1041 const ld::Atom* stub = stubForResolverFunction(atom);
1042 address = stub->finalAddress() - imageBaseAddress;
1043 if ( stub->isThumb() )
1046 entry.name = atom->name();
1047 entry.flags = flags;
1048 entry.address = address;
1049 entry.other = other;
1050 entry.importName = NULL;
1051 entries.push_back(entry);
1054 if (_options.sharedRegionEligible() && strncmp(atom->section().segmentName(), "__DATA", 6) == 0) {
1055 // Maximum address is 64bit which is 10 bytes as a uleb128. Minimum is 1 byte
1056 // Pad the section out so we can deal with addresses getting larger when __DATA segment
1057 // is moved before __TEXT in dyld shared cache.
1062 // sort vector by -exported_symbols_order, and any others by address
1063 std::sort(entries.begin(), entries.end(), TrieEntriesSorter(_options));
1066 mach_o::trie::makeTrie(entries, this->_encodedData.bytes());
1068 //Add additional data padding for the unoptimized shared cache
1069 for (unsigned int i = 0; i < padding; ++i)
1070 this->_encodedData.append_byte(0);
1072 // align to pointer size
1073 this->_encodedData.pad_to_size(sizeof(pint_t));
1075 this->_encoded = true;
1079 template <typename A>
1080 class SplitSegInfoV1Atom : public LinkEditAtom
1083 SplitSegInfoV1Atom(const Options& opts, ld::Internal& state, OutputFile& writer)
1084 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { }
1086 // overrides of ld::Atom
1087 virtual const char* name() const { return "split seg info"; }
1088 // overrides of LinkEditAtom
1089 virtual void encode() const;
1092 typedef typename A::P P;
1093 typedef typename A::P::E E;
1094 typedef typename A::P::uint_t pint_t;
1096 void addSplitSegInfo(uint64_t address, ld::Fixup::Kind k, uint32_t) const;
1097 void uleb128EncodeAddresses(const std::vector<uint64_t>& locations) const;
1099 mutable std::vector<uint64_t> _32bitPointerLocations;
1100 mutable std::vector<uint64_t> _64bitPointerLocations;
1101 mutable std::vector<uint64_t> _thumbLo16Locations;
1102 mutable std::vector<uint64_t> _thumbHi16Locations[16];
1103 mutable std::vector<uint64_t> _armLo16Locations;
1104 mutable std::vector<uint64_t> _armHi16Locations[16];
1105 mutable std::vector<uint64_t> _adrpLocations;
1108 static ld::Section _s_section;
1111 template <typename A>
1112 ld::Section SplitSegInfoV1Atom<A>::_s_section("__LINKEDIT", "__splitSegInfo", ld::Section::typeLinkEdit, true);
1115 void SplitSegInfoV1Atom<x86_64>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind kind, uint32_t extra) const
1118 case ld::Fixup::kindStoreX86PCRel32:
1119 case ld::Fixup::kindStoreX86PCRel32_1:
1120 case ld::Fixup::kindStoreX86PCRel32_2:
1121 case ld::Fixup::kindStoreX86PCRel32_4:
1122 case ld::Fixup::kindStoreX86PCRel32GOTLoad:
1123 case ld::Fixup::kindStoreX86PCRel32GOTLoadNowLEA:
1124 case ld::Fixup::kindStoreX86PCRel32GOT:
1125 case ld::Fixup::kindStoreLittleEndian32:
1126 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
1127 case ld::Fixup::kindStoreTargetAddressX86PCRel32:
1128 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad:
1129 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA:
1130 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad:
1131 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA:
1132 _32bitPointerLocations.push_back(address);
1134 case ld::Fixup::kindStoreLittleEndian64:
1135 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
1136 _64bitPointerLocations.push_back(address);
1139 warning("codegen at address 0x%08llX prevents image from working in dyld shared cache", address);
1145 void SplitSegInfoV1Atom<x86>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind kind, uint32_t extra) const
1148 case ld::Fixup::kindStoreLittleEndian32:
1149 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
1150 case ld::Fixup::kindStoreX86PCRel32TLVLoad:
1151 case ld::Fixup::kindStoreX86PCRel32TLVLoadNowLEA:
1152 _32bitPointerLocations.push_back(address);
1155 warning("codegen at address 0x%08llX prevents image from working in dyld shared cache", address);
1161 void SplitSegInfoV1Atom<arm>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind kind, uint32_t extra) const
1164 case ld::Fixup::kindStoreLittleEndian32:
1165 _32bitPointerLocations.push_back(address);
1167 case ld::Fixup::kindStoreARMLow16:
1168 _armLo16Locations.push_back(address);
1170 case ld::Fixup::kindStoreThumbLow16:
1171 _thumbLo16Locations.push_back(address);
1173 case ld::Fixup::kindStoreARMHigh16:
1175 _armHi16Locations[extra].push_back(address);
1177 case ld::Fixup::kindStoreThumbHigh16:
1179 _thumbHi16Locations[extra].push_back(address);
1182 warning("codegen at address 0x%08llX prevents image from working in dyld shared cache", address);
1187 #if SUPPORT_ARCH_arm64
1189 void SplitSegInfoV1Atom<arm64>::addSplitSegInfo(uint64_t address, ld::Fixup::Kind kind, uint32_t extra) const
1192 case ld::Fixup::kindStoreARM64Page21:
1193 case ld::Fixup::kindStoreARM64GOTLoadPage21:
1194 case ld::Fixup::kindStoreARM64GOTLeaPage21:
1195 case ld::Fixup::kindStoreARM64TLVPLoadPage21:
1196 case ld::Fixup::kindStoreTargetAddressARM64Page21:
1197 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
1198 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21:
1199 _adrpLocations.push_back(address);
1201 case ld::Fixup::kindStoreLittleEndian32:
1202 case ld::Fixup::kindStoreARM64PCRelToGOT:
1203 _32bitPointerLocations.push_back(address);
1205 case ld::Fixup::kindStoreLittleEndian64:
1206 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
1207 _64bitPointerLocations.push_back(address);
1210 warning("codegen at address 0x%08llX prevents image from working in dyld shared cache", address);
1216 template <typename A>
1217 void SplitSegInfoV1Atom<A>::uleb128EncodeAddresses(const std::vector<uint64_t>& locations) const
1219 pint_t addr = this->_options.baseAddress();
1220 for(typename std::vector<uint64_t>::const_iterator it = locations.begin(); it != locations.end(); ++it) {
1221 pint_t nextAddr = *it;
1222 //fprintf(stderr, "nextAddr=0x%0llX\n", (uint64_t)nextAddr);
1223 uint64_t delta = nextAddr - addr;
1224 //fprintf(stderr, "delta=0x%0llX\n", delta);
1226 throw "double split seg info for same address";
1230 byte = delta & 0x7F;
1234 this->_encodedData.append_byte(byte);
1237 while( byte >= 0x80 );
1243 template <typename A>
1244 void SplitSegInfoV1Atom<A>::encode() const
1246 // sort into group by pointer adjustment kind
1247 std::vector<OutputFile::SplitSegInfoEntry>& info = this->_writer._splitSegInfos;
1248 for (std::vector<OutputFile::SplitSegInfoEntry>::const_iterator it = info.begin(); it != info.end(); ++it) {
1249 this->addSplitSegInfo(it->fixupAddress, it->kind, it->extra);
1252 // delta compress runs of addresses
1253 this->_encodedData.reserve(8192);
1254 if ( _32bitPointerLocations.size() != 0 ) {
1255 this->_encodedData.append_byte(1);
1256 //fprintf(stderr, "type 1:\n");
1257 std::sort(_32bitPointerLocations.begin(), _32bitPointerLocations.end());
1258 this->uleb128EncodeAddresses(_32bitPointerLocations);
1259 this->_encodedData.append_byte(0); // terminator
1262 if ( _64bitPointerLocations.size() != 0 ) {
1263 this->_encodedData.append_byte(2);
1264 //fprintf(stderr, "type 2:\n");
1265 std::sort(_64bitPointerLocations.begin(), _64bitPointerLocations.end());
1266 this->uleb128EncodeAddresses(_64bitPointerLocations);
1267 this->_encodedData.append_byte(0); // terminator
1270 if ( _adrpLocations.size() != 0 ) {
1271 this->_encodedData.append_byte(3);
1272 //fprintf(stderr, "type 3:\n");
1273 std::sort(_adrpLocations.begin(), _adrpLocations.end());
1274 this->uleb128EncodeAddresses(_adrpLocations);
1275 this->_encodedData.append_byte(0); // terminator
1278 if ( _thumbLo16Locations.size() != 0 ) {
1279 this->_encodedData.append_byte(5);
1280 //fprintf(stderr, "type 5:\n");
1281 std::sort(_thumbLo16Locations.begin(), _thumbLo16Locations.end());
1282 this->uleb128EncodeAddresses(_thumbLo16Locations);
1283 this->_encodedData.append_byte(0); // terminator
1286 if ( _armLo16Locations.size() != 0 ) {
1287 this->_encodedData.append_byte(6);
1288 //fprintf(stderr, "type 6:\n");
1289 std::sort(_armLo16Locations.begin(), _armLo16Locations.end());
1290 this->uleb128EncodeAddresses(_armLo16Locations);
1291 this->_encodedData.append_byte(0); // terminator
1294 for (uint32_t i=0; i < 16; ++i) {
1295 if ( _thumbHi16Locations[i].size() != 0 ) {
1296 this->_encodedData.append_byte(16+i);
1297 //fprintf(stderr, "type 16+%d:\n", i);
1298 std::sort(_thumbHi16Locations[i].begin(), _thumbHi16Locations[i].end());
1299 this->uleb128EncodeAddresses(_thumbHi16Locations[i]);
1300 this->_encodedData.append_byte(0); // terminator
1304 for (uint32_t i=0; i < 16; ++i) {
1305 if ( _armHi16Locations[i].size() != 0 ) {
1306 this->_encodedData.append_byte(32+i);
1307 //fprintf(stderr, "type 32+%d:\n", i);
1308 std::sort(_armHi16Locations[i].begin(), _armHi16Locations[i].end());
1309 this->uleb128EncodeAddresses(_armHi16Locations[i]);
1310 this->_encodedData.append_byte(0); // terminator
1314 // always add zero byte to mark end
1315 this->_encodedData.append_byte(0);
1317 // align to pointer size
1318 this->_encodedData.pad_to_size(sizeof(pint_t));
1320 this->_encoded = true;
1322 // clean up temporaries
1323 _32bitPointerLocations.clear();
1324 _64bitPointerLocations.clear();
1328 template <typename A>
1329 class SplitSegInfoV2Atom : public LinkEditAtom
1332 SplitSegInfoV2Atom(const Options& opts, ld::Internal& state, OutputFile& writer)
1333 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { }
1335 // overrides of ld::Atom
1336 virtual const char* name() const { return "split seg info"; }
1337 // overrides of LinkEditAtom
1338 virtual void encode() const;
1341 typedef typename A::P P;
1342 typedef typename A::P::E E;
1343 typedef typename A::P::uint_t pint_t;
1345 // Whole :== <count> FromToSection+
1346 // FromToSection :== <from-sect-index> <to-sect-index> <count> ToOffset+
1347 // ToOffset :== <to-sect-offset-delta> <count> FromOffset+
1348 // FromOffset :== <kind> <count> <from-sect-offset-delta>
1350 typedef uint32_t SectionIndexes;
1351 typedef std::map<uint8_t, std::vector<uint64_t> > FromOffsetMap;
1352 typedef std::map<uint64_t, FromOffsetMap> ToOffsetMap;
1353 typedef std::map<SectionIndexes, ToOffsetMap> WholeMap;
1356 static ld::Section _s_section;
1359 template <typename A>
1360 ld::Section SplitSegInfoV2Atom<A>::_s_section("__LINKEDIT", "__splitSegInfo", ld::Section::typeLinkEdit, true);
1363 template <typename A>
1364 void SplitSegInfoV2Atom<A>::encode() const
1366 // sort into group by adjustment kind
1367 //fprintf(stderr, "_splitSegV2Infos.size=%lu\n", this->_writer._splitSegV2Infos.size());
1369 for (const OutputFile::SplitSegInfoV2Entry& entry : this->_writer._splitSegV2Infos) {
1370 //fprintf(stderr, "from=%d, to=%d\n", entry.fixupSectionIndex, entry.targetSectionIndex);
1371 SectionIndexes index = entry.fixupSectionIndex << 16 | entry.targetSectionIndex;
1372 ToOffsetMap& toOffsets = whole[index];
1373 FromOffsetMap& fromOffsets = toOffsets[entry.targetSectionOffset];
1374 fromOffsets[entry.referenceKind].push_back(entry.fixupSectionOffset);
1377 // Add marker that this is V2 data
1378 this->_encodedData.reserve(8192);
1379 this->_encodedData.append_byte(DYLD_CACHE_ADJ_V2_FORMAT);
1382 // Whole :== <count> FromToSection+
1383 this->_encodedData.append_uleb128(whole.size());
1384 for (auto& fromToSection : whole) {
1385 uint8_t fromSectionIndex = fromToSection.first >> 16;
1386 uint8_t toSectionIndex = fromToSection.first & 0xFFFF;
1387 ToOffsetMap& toOffsets = fromToSection.second;
1388 // FromToSection :== <from-sect-index> <to-sect-index> <count> ToOffset+
1389 this->_encodedData.append_uleb128(fromSectionIndex);
1390 this->_encodedData.append_uleb128(toSectionIndex);
1391 this->_encodedData.append_uleb128(toOffsets.size());
1392 //fprintf(stderr, "from sect=%d, to sect=%d, count=%lu\n", fromSectionIndex, toSectionIndex, toOffsets.size());
1393 uint64_t lastToOffset = 0;
1394 for (auto& fromToOffsets : toOffsets) {
1395 uint64_t toSectionOffset = fromToOffsets.first;
1396 FromOffsetMap& fromOffsets = fromToOffsets.second;
1397 // ToOffset :== <to-sect-offset-delta> <count> FromOffset+
1398 this->_encodedData.append_uleb128(toSectionOffset - lastToOffset);
1399 this->_encodedData.append_uleb128(fromOffsets.size());
1400 for (auto& kindAndOffsets : fromOffsets) {
1401 uint8_t kind = kindAndOffsets.first;
1402 std::vector<uint64_t>& fromOffsets = kindAndOffsets.second;
1403 // FromOffset :== <kind> <count> <from-sect-offset-delta>
1404 this->_encodedData.append_uleb128(kind);
1405 this->_encodedData.append_uleb128(fromOffsets.size());
1406 std::sort(fromOffsets.begin(), fromOffsets.end());
1407 uint64_t lastFromOffset = 0;
1408 for (uint64_t offset : fromOffsets) {
1409 this->_encodedData.append_uleb128(offset - lastFromOffset);
1410 lastFromOffset = offset;
1413 lastToOffset = toSectionOffset;
1418 // always add zero byte to mark end
1419 this->_encodedData.append_byte(0);
1421 // align to pointer size
1422 this->_encodedData.pad_to_size(sizeof(pint_t));
1424 this->_encoded = true;
1429 template <typename A>
1430 class FunctionStartsAtom : public LinkEditAtom
1433 FunctionStartsAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
1434 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { }
1436 // overrides of ld::Atom
1437 virtual const char* name() const { return "function starts"; }
1438 // overrides of LinkEditAtom
1439 virtual void encode() const;
1442 typedef typename A::P P;
1443 typedef typename A::P::E E;
1444 typedef typename A::P::uint_t pint_t;
1446 static ld::Section _s_section;
1449 template <typename A>
1450 ld::Section FunctionStartsAtom<A>::_s_section("__LINKEDIT", "__funcStarts", ld::Section::typeLinkEdit, true);
1453 template <typename A>
1454 void FunctionStartsAtom<A>::encode() const
1456 this->_encodedData.reserve(8192);
1457 const uint64_t badAddress = 0xFFFFFFFFFFFFFFFF;
1458 uint64_t addr = badAddress;
1459 // delta compress all function addresses
1460 for (std::vector<ld::Internal::FinalSection*>::iterator it = this->_state.sections.begin(); it != this->_state.sections.end(); ++it) {
1461 ld::Internal::FinalSection* sect = *it;
1462 if ( sect->type() == ld::Section::typeMachHeader ) {
1463 // start with delta from start of __TEXT
1464 addr = sect->address;
1466 else if ( sect->type() == ld::Section::typeCode ) {
1467 assert(addr != badAddress);
1468 std::vector<const ld::Atom*>& atoms = sect->atoms;
1469 for (std::vector<const ld::Atom*>::iterator ait = atoms.begin(); ait != atoms.end(); ++ait) {
1470 const ld::Atom* atom = *ait;
1471 // <rdar://problem/10422823> filter out zero-length atoms, so LC_FUNCTION_STARTS address can't spill into next section
1472 if ( atom->size() == 0 )
1474 uint64_t nextAddr = atom->finalAddress();
1475 if ( atom->isThumb() )
1477 uint64_t delta = nextAddr - addr;
1479 this->_encodedData.append_uleb128(delta);
1486 this->_encodedData.append_byte(0);
1488 // align to pointer size
1489 this->_encodedData.pad_to_size(sizeof(pint_t));
1491 this->_encoded = true;
1495 // <rdar://problem/9218847> Need way to formalize data in code
1496 template <typename A>
1497 class DataInCodeAtom : public LinkEditAtom
1500 DataInCodeAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
1501 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) { }
1503 // overrides of ld::Atom
1504 virtual const char* name() const { return "data-in-code info"; }
1505 // overrides of LinkEditAtom
1506 virtual void encode() const;
1509 typedef typename A::P P;
1510 typedef typename A::P::E E;
1511 typedef typename A::P::uint_t pint_t;
1513 struct FixupByAddressSorter
1515 bool operator()(const ld::Fixup* left, const ld::Fixup* right)
1517 return (left->offsetInAtom < right->offsetInAtom);
1521 void encodeEntry(uint32_t startImageOffset, int len, ld::Fixup::Kind kind) const {
1522 //fprintf(stderr, "encodeEntry(start=0x%08X, len=0x%04X, kind=%04X\n", startImageOffset, len, kind);
1524 macho_data_in_code_entry<P> entry;
1525 entry.set_offset(startImageOffset);
1526 entry.set_length(len);
1528 case ld::Fixup::kindDataInCodeStartData:
1529 entry.set_kind(DICE_KIND_DATA);
1531 case ld::Fixup::kindDataInCodeStartJT8:
1532 entry.set_kind(DICE_KIND_JUMP_TABLE8);
1534 case ld::Fixup::kindDataInCodeStartJT16:
1535 entry.set_kind(DICE_KIND_JUMP_TABLE16);
1537 case ld::Fixup::kindDataInCodeStartJT32:
1538 entry.set_kind(DICE_KIND_JUMP_TABLE32);
1540 case ld::Fixup::kindDataInCodeStartJTA32:
1541 entry.set_kind(DICE_KIND_ABS_JUMP_TABLE32);
1544 assert(0 && "bad L$start$ label to encode");
1546 uint8_t* bp = (uint8_t*)&entry;
1547 this->_encodedData.append_byte(bp[0]);
1548 this->_encodedData.append_byte(bp[1]);
1549 this->_encodedData.append_byte(bp[2]);
1550 this->_encodedData.append_byte(bp[3]);
1551 this->_encodedData.append_byte(bp[4]);
1552 this->_encodedData.append_byte(bp[5]);
1553 this->_encodedData.append_byte(bp[6]);
1554 this->_encodedData.append_byte(bp[7]);
1555 // in rare case data range is huge, create multiple entries
1557 startImageOffset += 0xFFF8;
1558 } while ( len > 0 );
1561 static ld::Section _s_section;
1564 template <typename A>
1565 ld::Section DataInCodeAtom<A>::_s_section("__LINKEDIT", "__dataInCode", ld::Section::typeLinkEdit, true);
1568 template <typename A>
1569 void DataInCodeAtom<A>::encode() const
1571 if ( this->_writer.hasDataInCode ) {
1572 uint64_t mhAddress = 0;
1573 for (std::vector<ld::Internal::FinalSection*>::iterator sit = _state.sections.begin(); sit != _state.sections.end(); ++sit) {
1574 ld::Internal::FinalSection* sect = *sit;
1575 if ( sect->type() == ld::Section::typeMachHeader )
1576 mhAddress = sect->address;
1577 if ( sect->type() != ld::Section::typeCode )
1579 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
1580 const ld::Atom* atom = *ait;
1581 // gather all code-in-data labels
1582 std::vector<const ld::Fixup*> dataInCodeLabels;
1583 for (ld::Fixup::iterator fit = atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
1584 switch ( fit->kind ) {
1585 case ld::Fixup::kindDataInCodeStartData:
1586 case ld::Fixup::kindDataInCodeStartJT8:
1587 case ld::Fixup::kindDataInCodeStartJT16:
1588 case ld::Fixup::kindDataInCodeStartJT32:
1589 case ld::Fixup::kindDataInCodeStartJTA32:
1590 case ld::Fixup::kindDataInCodeEnd:
1591 dataInCodeLabels.push_back(fit);
1597 // to do: sort labels by address
1598 std::sort(dataInCodeLabels.begin(), dataInCodeLabels.end(), FixupByAddressSorter());
1600 // convert to array of struct data_in_code_entry
1601 ld::Fixup::Kind prevKind = ld::Fixup::kindDataInCodeEnd;
1602 uint32_t prevOffset = 0;
1603 for ( std::vector<const ld::Fixup*>::iterator sfit = dataInCodeLabels.begin(); sfit != dataInCodeLabels.end(); ++sfit) {
1604 if ( ((*sfit)->kind != prevKind) && (prevKind != ld::Fixup::kindDataInCodeEnd) ) {
1605 int len = (*sfit)->offsetInAtom - prevOffset;
1607 warning("multiple L$start$ labels found at same address in %s at offset 0x%04X", atom->name(), prevOffset);
1608 this->encodeEntry(atom->finalAddress()+prevOffset-mhAddress, (*sfit)->offsetInAtom - prevOffset, prevKind);
1610 prevKind = (*sfit)->kind;
1611 prevOffset = (*sfit)->offsetInAtom;
1613 if ( prevKind != ld::Fixup::kindDataInCodeEnd ) {
1614 // add entry if function ends with data
1615 this->encodeEntry(atom->finalAddress()+prevOffset-mhAddress, atom->size() - prevOffset, prevKind);
1621 this->_encoded = true;
1629 template <typename A>
1630 class OptimizationHintsAtom : public LinkEditAtom
1633 OptimizationHintsAtom(const Options& opts, ld::Internal& state, OutputFile& writer)
1634 : LinkEditAtom(opts, state, writer, _s_section, sizeof(pint_t)) {
1635 assert(opts.outputKind() == Options::kObjectFile);
1638 // overrides of ld::Atom
1639 virtual const char* name() const { return "linker optimization hints"; }
1640 // overrides of LinkEditAtom
1641 virtual void encode() const;
1644 typedef typename A::P P;
1645 typedef typename A::P::E E;
1646 typedef typename A::P::uint_t pint_t;
1648 static ld::Section _s_section;
1652 template <typename A>
1653 ld::Section OptimizationHintsAtom<A>::_s_section("__LINKEDIT", "__opt_hints", ld::Section::typeLinkEdit, true);
1655 template <typename A>
1656 void OptimizationHintsAtom<A>::encode() const
1658 if ( _state.someObjectHasOptimizationHints ) {
1659 for (std::vector<ld::Internal::FinalSection*>::iterator sit = _state.sections.begin(); sit != _state.sections.end(); ++sit) {
1660 ld::Internal::FinalSection* sect = *sit;
1661 if ( sect->type() != ld::Section::typeCode )
1663 for (std::vector<const ld::Atom*>::iterator ait = sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
1664 const ld::Atom* atom = *ait;
1665 uint64_t address = atom->finalAddress();
1666 for (ld::Fixup::iterator fit = atom->fixupsBegin(); fit != atom->fixupsEnd(); ++fit) {
1667 if ( fit->kind != ld::Fixup::kindLinkerOptimizationHint)
1669 ld::Fixup::LOH_arm64 extra;
1670 extra.addend = fit->u.addend;
1671 _encodedData.append_uleb128(extra.info.kind);
1672 _encodedData.append_uleb128(extra.info.count+1);
1673 _encodedData.append_uleb128((extra.info.delta1 << 2) + fit->offsetInAtom + address);
1674 if ( extra.info.count > 0 )
1675 _encodedData.append_uleb128((extra.info.delta2 << 2) + fit->offsetInAtom + address);
1676 if ( extra.info.count > 1 )
1677 _encodedData.append_uleb128((extra.info.delta3 << 2) + fit->offsetInAtom + address);
1678 if ( extra.info.count > 2 )
1679 _encodedData.append_uleb128((extra.info.delta4 << 2) + fit->offsetInAtom + address);
1684 this->_encodedData.pad_to_size(sizeof(pint_t));
1687 this->_encoded = true;
1694 #endif // __LINKEDIT_HPP__