1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-*
3 * Copyright (c) 2005-2011 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 // start temp HACK for cross builds
26 extern "C" double log2 ( double );
28 // end temp HACK for cross builds
32 #include <sys/types.h>
35 #include <sys/sysctl.h>
41 #include <mach/mach_time.h>
42 #include <mach/vm_statistics.h>
43 #include <mach/mach_init.h>
44 #include <mach/mach_host.h>
46 #include <mach-o/dyld.h>
48 #include <AvailabilityMacros.h>
57 #include <unordered_map>
62 #include "MachOFileAbstraction.hpp"
63 #include "Architectures.hpp"
66 #include "InputFiles.h"
68 #include "OutputFile.h"
71 #include "passes/stubs/make_stubs.h"
72 #include "passes/dtrace_dof.h"
73 #include "passes/got.h"
74 #include "passes/tlvp.h"
75 #include "passes/huge.h"
76 #include "passes/compact_unwind.h"
77 #include "passes/order.h"
78 #include "passes/branch_island.h"
79 #include "passes/branch_shim.h"
80 #include "passes/objc.h"
81 #include "passes/dylibs.h"
82 #include "passes/bitcode_bundle.h"
83 #include "passes/code_dedup.h"
85 #include "parsers/archive_file.h"
86 #include "parsers/macho_relocatable_file.h"
87 #include "parsers/macho_dylib_file.h"
88 #include "parsers/lto_file.h"
89 #include "parsers/opaque_section_file.h"
92 struct PerformanceStatistics
{
94 uint64_t startInputFileProcessing
;
95 uint64_t startResolver
;
100 vm_statistics_data_t vmStart
;
101 vm_statistics_data_t vmEnd
;
105 class InternalState
: public ld::Internal
108 InternalState(const Options
& opts
) : _options(opts
), _atomsOrderedInSections(false) { }
109 virtual ld::Internal::FinalSection
* addAtom(const ld::Atom
& atom
);
110 virtual ld::Internal::FinalSection
* getFinalSection(const ld::Section
&);
111 ld::Internal::FinalSection
* getFinalSection(const char* seg
, const char* sect
, ld::Section::Type type
);
113 uint64_t assignFileOffsets();
114 void setSectionSizesAndAlignments();
116 void markAtomsOrdered() { _atomsOrderedInSections
= true; }
117 bool hasReferenceToWeakExternal(const ld::Atom
& atom
);
119 virtual ~InternalState() {}
121 bool inMoveRWChain(const ld::Atom
& atom
, const char* filePath
, const char*& dstSeg
, bool& wildCardMatch
);
122 bool inMoveROChain(const ld::Atom
& atom
, const char* filePath
, const char*& dstSeg
, bool& wildCardMatch
);
124 class FinalSection
: public ld::Internal::FinalSection
127 FinalSection(const ld::Section
& sect
, uint32_t sectionsSeen
, const Options
&);
128 static int sectionComparer(const void* l
, const void* r
);
129 static const ld::Section
& outputSection(const ld::Section
& sect
, bool mergeZeroFill
);
130 static const ld::Section
& objectOutputSection(const ld::Section
& sect
, const Options
&);
132 friend class InternalState
;
133 static uint32_t sectionOrder(const ld::Section
& sect
, uint32_t sectionsSeen
, const Options
& options
);
134 static uint32_t segmentOrder(const ld::Section
& sect
, const Options
& options
);
135 uint32_t _segmentOrder
;
136 uint32_t _sectionOrder
;
138 static std::vector
<const char*> _s_segmentsSeen
;
139 static ld::Section _s_DATA_data
;
140 static ld::Section _s_DATA_const
;
141 static ld::Section _s_TEXT_text
;
142 static ld::Section _s_TEXT_const
;
143 static ld::Section _s_DATA_nl_symbol_ptr
;
144 static ld::Section _s_DATA_common
;
145 static ld::Section _s_DATA_zerofill
;
146 static ld::Section _s_DATA_DIRTY_data
;
147 static ld::Section _s_DATA_CONST_const
;
150 bool hasZeroForFileOffset(const ld::Section
* sect
);
151 uint64_t pageAlign(uint64_t addr
);
152 uint64_t pageAlign(uint64_t addr
, uint64_t pageSize
);
155 size_t operator()(const ld::Section
*) const;
157 struct SectionEquals
{
158 bool operator()(const ld::Section
* left
, const ld::Section
* right
) const;
160 typedef std::unordered_map
<const ld::Section
*, FinalSection
*, SectionHash
, SectionEquals
> SectionInToOut
;
163 SectionInToOut _sectionInToFinalMap
;
164 const Options
& _options
;
165 bool _atomsOrderedInSections
;
166 std::unordered_map
<const ld::Atom
*, const char*> _pendingSegMove
;
169 ld::Section
InternalState::FinalSection::_s_DATA_data( "__DATA", "__data", ld::Section::typeUnclassified
);
170 ld::Section
InternalState::FinalSection::_s_DATA_const("__DATA", "__const", ld::Section::typeUnclassified
);
171 ld::Section
InternalState::FinalSection::_s_TEXT_text( "__TEXT", "__text", ld::Section::typeCode
);
172 ld::Section
InternalState::FinalSection::_s_TEXT_const("__TEXT", "__const", ld::Section::typeUnclassified
);
173 ld::Section
InternalState::FinalSection::_s_DATA_nl_symbol_ptr("__DATA", "__nl_symbol_ptr", ld::Section::typeNonLazyPointer
);
174 ld::Section
InternalState::FinalSection::_s_DATA_common("__DATA", "__common", ld::Section::typeZeroFill
);
175 ld::Section
InternalState::FinalSection::_s_DATA_zerofill("__DATA", "__zerofill", ld::Section::typeZeroFill
);
176 ld::Section
InternalState::FinalSection::_s_DATA_DIRTY_data( "__DATA_DIRTY", "__data", ld::Section::typeUnclassified
);
177 ld::Section
InternalState::FinalSection::_s_DATA_CONST_const( "__DATA_CONST", "__const", ld::Section::typeUnclassified
);
179 std::vector
<const char*> InternalState::FinalSection::_s_segmentsSeen
;
182 size_t InternalState::SectionHash::operator()(const ld::Section
* sect
) const
185 ld::CStringHash temp
;
186 hash
+= temp
.operator()(sect
->segmentName());
187 hash
+= temp
.operator()(sect
->sectionName());
191 bool InternalState::SectionEquals::operator()(const ld::Section
* left
, const ld::Section
* right
) const
193 return (*left
== *right
);
197 InternalState::FinalSection::FinalSection(const ld::Section
& sect
, uint32_t sectionsSeen
, const Options
& opts
)
198 : ld::Internal::FinalSection(sect
),
199 _segmentOrder(segmentOrder(sect
, opts
)),
200 _sectionOrder(sectionOrder(sect
, sectionsSeen
, opts
))
202 //fprintf(stderr, "FinalSection(%16s, %16s) _segmentOrder=%3d, _sectionOrder=0x%08X\n",
203 // this->segmentName(), this->sectionName(), _segmentOrder, _sectionOrder);
206 const ld::Section
& InternalState::FinalSection::outputSection(const ld::Section
& sect
, bool mergeZeroFill
)
208 // merge sections in final linked image
209 switch ( sect
.type() ) {
210 case ld::Section::typeLiteral4
:
211 case ld::Section::typeLiteral8
:
212 case ld::Section::typeLiteral16
:
213 if ( strcmp(sect
.segmentName(), "__TEXT") == 0 )
214 return _s_TEXT_const
;
216 case ld::Section::typeUnclassified
:
217 if ( strcmp(sect
.segmentName(), "__DATA") == 0 ) {
218 if ( strcmp(sect
.sectionName(), "__datacoal_nt") == 0 )
220 if ( strcmp(sect
.sectionName(), "__const_coal") == 0 )
221 return _s_DATA_const
;
223 else if ( strcmp(sect
.segmentName(), "__TEXT") == 0 ) {
224 if ( strcmp(sect
.sectionName(), "__const_coal") == 0 )
225 return _s_TEXT_const
;
227 else if ( strcmp(sect
.segmentName(), "__DATA_DIRTY") == 0 ) {
228 if ( strcmp(sect
.sectionName(), "__datacoal_nt") == 0 )
229 return _s_DATA_DIRTY_data
;
231 else if ( strcmp(sect
.segmentName(), "__DATA_CONST") == 0 ) {
232 if ( strcmp(sect
.sectionName(), "__const_coal") == 0 )
233 return _s_DATA_CONST_const
;
236 case ld::Section::typeZeroFill
:
238 return _s_DATA_zerofill
;
240 case ld::Section::typeCode
:
241 if ( strcmp(sect
.segmentName(), "__TEXT") == 0 ) {
242 if ( strcmp(sect
.sectionName(), "__textcoal_nt") == 0 )
244 else if ( strcmp(sect
.sectionName(), "__StaticInit") == 0 )
248 case ld::Section::typeNonLazyPointer
:
249 if ( strcmp(sect
.segmentName(), "__DATA") == 0 ) {
250 if ( strcmp(sect
.sectionName(), "__nl_symbol_ptr") == 0 )
251 return _s_DATA_nl_symbol_ptr
;
253 else if ( strcmp(sect
.segmentName(), "__IMPORT") == 0 ) {
254 if ( strcmp(sect
.sectionName(), "__pointers") == 0 )
255 return _s_DATA_nl_symbol_ptr
;
258 case ld::Section::typeTentativeDefs
:
259 if ( (strcmp(sect
.segmentName(), "__DATA") == 0) && (strcmp(sect
.sectionName(), "__comm/tent") == 0) ) {
261 return _s_DATA_zerofill
;
263 return _s_DATA_common
;
273 const ld::Section
& InternalState::FinalSection::objectOutputSection(const ld::Section
& sect
, const Options
& options
)
275 // in -r mode the only section that ever changes is __tenative -> __common with -d option
276 if ( (sect
.type() == ld::Section::typeTentativeDefs
) && options
.makeTentativeDefinitionsReal())
277 return _s_DATA_common
;
281 uint32_t InternalState::FinalSection::segmentOrder(const ld::Section
& sect
, const Options
& options
)
283 if ( options
.outputKind() == Options::kPreload
) {
284 if ( strcmp(sect
.segmentName(), "__HEADER") == 0 )
286 const std::vector
<const char*>& order
= options
.segmentOrder();
287 for (size_t i
=0; i
!= order
.size(); ++i
) {
288 if ( strcmp(sect
.segmentName(), order
[i
]) == 0 )
291 if ( strcmp(sect
.segmentName(), "__TEXT") == 0 )
292 return order
.size()+1;
293 if ( strcmp(sect
.segmentName(), "__DATA") == 0 )
294 return order
.size()+2;
296 else if ( options
.outputKind() == Options::kStaticExecutable
) {
297 const std::vector
<const char*>& order
= options
.segmentOrder();
298 for (size_t i
=0; i
!= order
.size(); ++i
) {
299 if ( strcmp(sect
.segmentName(), order
[i
]) == 0 )
302 if ( strcmp(sect
.segmentName(), "__PAGEZERO") == 0 )
304 if ( strcmp(sect
.segmentName(), "__TEXT") == 0 )
305 return order
.size()+1;
306 if ( strcmp(sect
.segmentName(), "__DATA") == 0 )
307 return order
.size()+2;
310 if ( strcmp(sect
.segmentName(), "__PAGEZERO") == 0 )
312 if ( strcmp(sect
.segmentName(), "__TEXT") == 0 )
314 if ( strcmp(sect
.segmentName(), "__TEXT_EXEC") == 0 )
316 // in -r mode, want __DATA last so zerofill sections are at end
317 if ( strcmp(sect
.segmentName(), "__DATA") == 0 )
318 return (options
.outputKind() == Options::kObjectFile
) ? 6 : 3;
319 if ( strcmp(sect
.segmentName(), "__OBJC") == 0 )
321 if ( strcmp(sect
.segmentName(), "__IMPORT") == 0 )
324 // layout non-standard segments in order seen (+100 to shift beyond standard segments)
325 for (uint32_t i
=0; i
< _s_segmentsSeen
.size(); ++i
) {
326 if ( strcmp(_s_segmentsSeen
[i
], sect
.segmentName()) == 0 )
329 _s_segmentsSeen
.push_back(sect
.segmentName());
330 return _s_segmentsSeen
.size()-1+100;
333 uint32_t InternalState::FinalSection::sectionOrder(const ld::Section
& sect
, uint32_t sectionsSeen
, const Options
& options
)
335 if ( sect
.type() == ld::Section::typeFirstSection
)
337 if ( sect
.type() == ld::Section::typeMachHeader
)
339 if ( sect
.type() == ld::Section::typeLastSection
)
341 const std::vector
<const char*>* sectionList
= options
.sectionOrder(sect
.segmentName());
342 if ( ((options
.outputKind() == Options::kPreload
) || (options
.outputKind() == Options::kDyld
)) && (sectionList
!= NULL
) ) {
344 for (std::vector
<const char*>::const_iterator it
=sectionList
->begin(); it
!= sectionList
->end(); ++it
, ++count
) {
345 if ( strcmp(*it
, sect
.sectionName()) == 0 )
349 if ( strcmp(sect
.segmentName(), "__TEXT") == 0 ) {
350 switch ( sect
.type() ) {
351 case ld::Section::typeCode
:
352 // <rdar://problem/8346444> make __text always be first "code" section
353 if ( strcmp(sect
.sectionName(), "__text") == 0 )
357 case ld::Section::typeNonStdCString
:
358 if ( (strcmp(sect
.sectionName(), "__oslogstring") == 0) && options
.makeEncryptable() )
361 return sectionsSeen
+20;
362 case ld::Section::typeStub
:
364 case ld::Section::typeStubHelper
:
366 case ld::Section::typeLSDA
:
368 case ld::Section::typeUnwindInfo
:
370 case ld::Section::typeCFI
:
372 case ld::Section::typeStubClose
:
375 return sectionsSeen
+20;
378 else if ( strncmp(sect
.segmentName(), "__DATA", 6) == 0 ) {
379 switch ( sect
.type() ) {
380 case ld::Section::typeLazyPointerClose
:
382 case ld::Section::typeDyldInfo
:
384 case ld::Section::typeNonLazyPointer
:
386 case ld::Section::typeLazyPointer
:
388 case ld::Section::typeInitializerPointers
:
390 case ld::Section::typeTerminatorPointers
:
392 case ld::Section::typeTLVInitialValues
:
393 return INT_MAX
-259; // need TLV zero-fill to follow TLV init values
394 case ld::Section::typeTLVZeroFill
:
396 case ld::Section::typeZeroFill
:
397 // make sure __huge is always last zerofill section
398 if ( strcmp(sect
.sectionName(), "__huge") == 0 )
401 return INT_MAX
-256+sectionsSeen
; // <rdar://problem/25448494> zero fill need to be last and in "seen" order
403 // <rdar://problem/14348664> __DATA,__const section should be near __mod_init_func not __data
404 if ( strcmp(sect
.sectionName(), "__const") == 0 )
406 // <rdar://problem/17125893> Linker should put __cfstring near __const
407 if ( strcmp(sect
.sectionName(), "__cfstring") == 0 )
409 // <rdar://problem/7435296> Reorder sections to reduce page faults in object files
410 else if ( strcmp(sect
.sectionName(), "__objc_classlist") == 0 )
412 else if ( strcmp(sect
.sectionName(), "__objc_nlclslist") == 0 )
414 else if ( strcmp(sect
.sectionName(), "__objc_catlist") == 0 )
416 else if ( strcmp(sect
.sectionName(), "__objc_nlcatlist") == 0 )
418 else if ( strcmp(sect
.sectionName(), "__objc_protolist") == 0 )
420 else if ( strcmp(sect
.sectionName(), "__objc_imageinfo") == 0 )
422 else if ( strcmp(sect
.sectionName(), "__objc_const") == 0 )
424 else if ( strcmp(sect
.sectionName(), "__objc_selrefs") == 0 )
426 else if ( strcmp(sect
.sectionName(), "__objc_msgrefs") == 0 )
428 else if ( strcmp(sect
.sectionName(), "__objc_protorefs") == 0 )
430 else if ( strcmp(sect
.sectionName(), "__objc_classrefs") == 0 )
432 else if ( strcmp(sect
.sectionName(), "__objc_superrefs") == 0 )
434 else if ( strcmp(sect
.sectionName(), "__objc_ivar") == 0 )
436 else if ( strcmp(sect
.sectionName(), "__objc_data") == 0 )
439 return sectionsSeen
+40;
442 // make sure zerofill in any other section is at end of segment
443 if ( sect
.type() == ld::Section::typeZeroFill
)
444 return INT_MAX
-256+sectionsSeen
;
445 return sectionsSeen
+20;
449 static void validateFixups(const ld::Atom
& atom
)
451 //fprintf(stderr, "validateFixups %s\n", atom.name());
452 bool lastWasClusterEnd
= true;
453 ld::Fixup::Cluster lastClusterSize
= ld::Fixup::k1of1
;
454 uint32_t curClusterOffsetInAtom
= 0;
455 for (ld::Fixup::iterator fit
=atom
.fixupsBegin(); fit
!= atom
.fixupsEnd(); ++fit
) {
456 //fprintf(stderr, " fixup offset=%d, cluster=%d\n", fit->offsetInAtom, fit->clusterSize);
457 assert((fit
->offsetInAtom
<= atom
.size()) || (fit
->offsetInAtom
== 0));
458 if ( fit
->firstInCluster() ) {
459 assert(lastWasClusterEnd
);
460 curClusterOffsetInAtom
= fit
->offsetInAtom
;
461 lastWasClusterEnd
= (fit
->clusterSize
== ld::Fixup::k1of1
);
464 assert(!lastWasClusterEnd
);
465 assert(fit
->offsetInAtom
== curClusterOffsetInAtom
);
466 switch ((ld::Fixup::Cluster
)fit
->clusterSize
) {
467 case ld::Fixup::k1of1
:
468 case ld::Fixup::k1of2
:
469 case ld::Fixup::k1of3
:
470 case ld::Fixup::k1of4
:
471 case ld::Fixup::k1of5
:
472 lastWasClusterEnd
= false;
474 case ld::Fixup::k2of2
:
475 assert(lastClusterSize
= ld::Fixup::k1of2
);
476 lastWasClusterEnd
= true;
478 case ld::Fixup::k2of3
:
479 assert(lastClusterSize
= ld::Fixup::k1of3
);
480 lastWasClusterEnd
= false;
482 case ld::Fixup::k2of4
:
483 assert(lastClusterSize
= ld::Fixup::k1of4
);
484 lastWasClusterEnd
= false;
486 case ld::Fixup::k2of5
:
487 assert(lastClusterSize
= ld::Fixup::k1of5
);
488 lastWasClusterEnd
= false;
490 case ld::Fixup::k3of3
:
491 assert(lastClusterSize
= ld::Fixup::k2of3
);
492 lastWasClusterEnd
= true;
494 case ld::Fixup::k3of4
:
495 assert(lastClusterSize
= ld::Fixup::k2of4
);
496 lastWasClusterEnd
= false;
498 case ld::Fixup::k3of5
:
499 assert(lastClusterSize
= ld::Fixup::k2of5
);
500 lastWasClusterEnd
= false;
502 case ld::Fixup::k4of4
:
503 assert(lastClusterSize
= ld::Fixup::k3of4
);
504 lastWasClusterEnd
= true;
506 case ld::Fixup::k4of5
:
507 assert(lastClusterSize
= ld::Fixup::k3of5
);
508 lastWasClusterEnd
= false;
510 case ld::Fixup::k5of5
:
511 assert(lastClusterSize
= ld::Fixup::k4of5
);
512 lastWasClusterEnd
= true;
516 lastClusterSize
= fit
->clusterSize
;
517 if ( fit
->binding
== ld::Fixup::bindingDirectlyBound
) {
518 assert(fit
->u
.target
!= NULL
);
521 switch (lastClusterSize
) {
522 case ld::Fixup::k1of1
:
523 case ld::Fixup::k2of2
:
524 case ld::Fixup::k3of3
:
525 case ld::Fixup::k4of4
:
526 case ld::Fixup::k5of5
:
529 assert(0 && "last fixup was not end of cluster");
535 bool InternalState::hasReferenceToWeakExternal(const ld::Atom
& atom
)
537 // if __DATA,__const atom has pointer to weak external symbol, don't move to __DATA_CONST
538 const ld::Atom
* target
= NULL
;
539 for (ld::Fixup::iterator fit
=atom
.fixupsBegin(); fit
!= atom
.fixupsEnd(); ++fit
) {
540 if ( fit
->firstInCluster() ) {
543 switch ( fit
->binding
) {
544 case ld::Fixup::bindingNone
:
545 case ld::Fixup::bindingByNameUnbound
:
547 case ld::Fixup::bindingByContentBound
:
548 case ld::Fixup::bindingDirectlyBound
:
549 target
= fit
->u
.target
;
551 case ld::Fixup::bindingsIndirectlyBound
:
552 target
= indirectBindingTable
[fit
->u
.bindingIndex
];
555 if ( (target
!= NULL
) && (target
->definition() == ld::Atom::definitionRegular
)
556 && (target
->combine() == ld::Atom::combineByName
) && (target
->scope() == ld::Atom::scopeGlobal
) ) {
563 bool InternalState::inMoveRWChain(const ld::Atom
& atom
, const char* filePath
, const char*& dstSeg
, bool& wildCardMatch
)
565 if ( !_options
.hasDataSymbolMoves() )
568 auto pos
= _pendingSegMove
.find(&atom
);
569 if ( pos
!= _pendingSegMove
.end() ) {
570 dstSeg
= pos
->second
;
575 if ( _options
.moveRwSymbol(atom
.name(), filePath
, dstSeg
, wildCardMatch
) )
578 for (ld::Fixup::iterator fit
=atom
.fixupsBegin(); fit
!= atom
.fixupsEnd(); ++fit
) {
579 if ( fit
->kind
== ld::Fixup::kindNoneFollowOn
) {
580 if ( fit
->binding
== ld::Fixup::bindingDirectlyBound
) {
581 if ( inMoveRWChain(*(fit
->u
.target
), filePath
, dstSeg
, wildCardMatch
) )
588 for (ld::Fixup::iterator fit
=atom
.fixupsBegin(); fit
!= atom
.fixupsEnd(); ++fit
) {
589 if ( fit
->kind
== ld::Fixup::kindNoneFollowOn
) {
590 if ( fit
->binding
== ld::Fixup::bindingDirectlyBound
) {
591 _pendingSegMove
[fit
->u
.target
] = dstSeg
;
601 bool InternalState::inMoveROChain(const ld::Atom
& atom
, const char* filePath
, const char*& dstSeg
, bool& wildCardMatch
)
603 if ( !_options
.hasCodeSymbolMoves() )
606 auto pos
= _pendingSegMove
.find(&atom
);
607 if ( pos
!= _pendingSegMove
.end() ) {
608 dstSeg
= pos
->second
;
613 if ( _options
.moveRoSymbol(atom
.name(), filePath
, dstSeg
, wildCardMatch
) )
616 for (ld::Fixup::iterator fit
=atom
.fixupsBegin(); fit
!= atom
.fixupsEnd(); ++fit
) {
617 if ( fit
->kind
== ld::Fixup::kindNoneFollowOn
) {
618 if ( fit
->binding
== ld::Fixup::bindingDirectlyBound
) {
619 if ( inMoveROChain(*(fit
->u
.target
), filePath
, dstSeg
, wildCardMatch
) )
626 for (ld::Fixup::iterator fit
=atom
.fixupsBegin(); fit
!= atom
.fixupsEnd(); ++fit
) {
627 if ( fit
->kind
== ld::Fixup::kindNoneFollowOn
) {
628 if ( fit
->binding
== ld::Fixup::bindingDirectlyBound
) {
629 _pendingSegMove
[fit
->u
.target
] = dstSeg
;
641 ld::Internal::FinalSection
* InternalState::addAtom(const ld::Atom
& atom
)
643 //fprintf(stderr, "addAtom: %s\n", atom.name());
644 ld::Internal::FinalSection
* fs
= NULL
;
645 const char* curSectName
= atom
.section().sectionName();
646 const char* curSegName
= atom
.section().segmentName();
647 ld::Section::Type sectType
= atom
.section().type();
648 const ld::File
* f
= atom
.file();
649 const char* path
= (f
!= NULL
) ? f
->path() : NULL
;
650 if ( atom
.section().type() == ld::Section::typeTentativeDefs
) {
651 // tentative defintions don't have a real section name yet
652 sectType
= ld::Section::typeZeroFill
;
653 if ( _options
.mergeZeroFill() )
654 curSectName
= FinalSection::_s_DATA_zerofill
.sectionName();
656 curSectName
= FinalSection::_s_DATA_common
.sectionName();
658 // Support for -move_to_r._segment
659 if ( atom
.symbolTableInclusion() == ld::Atom::symbolTableIn
) {
662 if ( inMoveRWChain(atom
, path
, dstSeg
, wildCardMatch
) ) {
663 if ( (sectType
!= ld::Section::typeZeroFill
)
664 && (sectType
!= ld::Section::typeUnclassified
)
665 && (sectType
!= ld::Section::typeTentativeDefs
)
666 && (sectType
!= ld::Section::typeDyldInfo
) ) {
667 if ( !wildCardMatch
)
668 warning("cannot move symbol '%s' from file %s to segment '%s' because symbol is not data (is %d)", atom
.name(), path
, dstSeg
, sectType
);
672 if ( _options
.traceSymbolLayout() )
673 printf("symbol '%s', -move_to_rw_segment mapped it to %s/%s\n", atom
.name(), curSegName
, curSectName
);
674 fs
= this->getFinalSection(curSegName
, curSectName
, sectType
);
677 if ( (fs
== NULL
) && inMoveROChain(atom
, path
, dstSeg
, wildCardMatch
) ) {
678 if ( (sectType
!= ld::Section::typeCode
)
679 && (sectType
!= ld::Section::typeUnclassified
) ) {
680 if ( !wildCardMatch
)
681 warning("cannot move symbol '%s' from file %s to segment '%s' because symbol is not code (is %d)", atom
.name(), path
, dstSeg
, sectType
);
685 if ( _options
.traceSymbolLayout() )
686 printf("symbol '%s', -move_to_ro_segment mapped it to %s/%s\n", atom
.name(), curSegName
, curSectName
);
687 fs
= this->getFinalSection(curSegName
, curSectName
, ld::Section::typeCode
);
691 // support for -rename_section and -rename_segment
692 for (const Options::SectionRename
& rename
: _options
.sectionRenames()) {
693 if ( (strcmp(curSectName
, rename
.fromSection
) == 0) && (strcmp(curSegName
, rename
.fromSegment
) == 0) ) {
694 if ( _options
.useDataConstSegment() && (strcmp(curSectName
, "__const") == 0) && (strcmp(curSegName
, "__DATA") == 0) && hasReferenceToWeakExternal(atom
) ) {
695 // if __DATA,__const atom has pointer to weak external symbol, don't move to __DATA_CONST
696 curSectName
= "__const_weak";
697 fs
= this->getFinalSection(curSegName
, curSectName
, sectType
);
698 if ( _options
.traceSymbolLayout() )
699 printf("symbol '%s', contains pointers to weak symbols, so mapped it to __DATA/__const_weak\n", atom
.name());
701 else if ( _options
.useDataConstSegment() && (sectType
== ld::Section::typeNonLazyPointer
) && hasReferenceToWeakExternal(atom
) ) {
702 // if __DATA,__nl_symbol_ptr atom has pointer to weak external symbol, don't move to __DATA_CONST
703 curSectName
= "__got_weak";
704 fs
= this->getFinalSection("__DATA", curSectName
, sectType
);
705 if ( _options
.traceSymbolLayout() )
706 printf("symbol '%s', contains pointers to weak symbols, so mapped it to __DATA/__got_weak\n", atom
.name());
709 curSegName
= rename
.toSegment
;
710 curSectName
= rename
.toSection
;
711 fs
= this->getFinalSection(rename
.toSegment
, rename
.toSection
, sectType
);
712 if ( _options
.traceSymbolLayout() )
713 printf("symbol '%s', -rename_section mapped it to %s/%s\n", atom
.name(), fs
->segmentName(), fs
->sectionName());
717 for (const Options::SegmentRename
& rename
: _options
.segmentRenames()) {
718 if ( strcmp(curSegName
, rename
.fromSegment
) == 0 ) {
719 if ( _options
.traceSymbolLayout() )
720 printf("symbol '%s', -rename_segment mapped it to %s/%s\n", atom
.name(), rename
.toSegment
, curSectName
);
721 fs
= this->getFinalSection(rename
.toSegment
, curSectName
, sectType
);
725 // if no override, use default location
727 fs
= this->getFinalSection(atom
.section());
728 if ( _options
.traceSymbolLayout() && (atom
.symbolTableInclusion() == ld::Atom::symbolTableIn
) )
729 printf("symbol '%s', use default mapping to %s/%s\n", atom
.name(), fs
->segmentName(), fs
->sectionName());
732 //fprintf(stderr, "InternalState::doAtom(%p), name=%s, sect=%s, finalseg=%s\n", &atom, atom.name(), atom.section().sectionName(), fs->segmentName());
734 validateFixups(atom
);
736 if ( _atomsOrderedInSections
) {
737 // make sure this atom is placed before any trailing section$end$ atom
738 if ( (fs
->atoms
.size() > 1) && (fs
->atoms
.back()->contentType() == ld::Atom::typeSectionEnd
) ) {
739 // last atom in section$end$ atom, insert before it
740 const ld::Atom
* endAtom
= fs
->atoms
.back();
741 fs
->atoms
.pop_back();
742 fs
->atoms
.push_back(&atom
);
743 fs
->atoms
.push_back(endAtom
);
746 // not end atom, just append new atom
747 fs
->atoms
.push_back(&atom
);
752 fs
->atoms
.push_back(&atom
);
754 this->atomToSection
[&atom
] = fs
;
760 ld::Internal::FinalSection
* InternalState::getFinalSection(const char* seg
, const char* sect
, ld::Section::Type type
)
762 for (std::vector
<ld::Internal::FinalSection
*>::iterator it
=sections
.begin(); it
!= sections
.end(); ++it
) {
763 if ( (strcmp((*it
)->segmentName(),seg
) == 0) && (strcmp((*it
)->sectionName(),sect
) == 0) )
766 return this->getFinalSection(*new ld::Section(seg
, sect
, type
, false));
769 ld::Internal::FinalSection
* InternalState::getFinalSection(const ld::Section
& inputSection
)
771 const ld::Section
* baseForFinalSection
= &inputSection
;
773 // see if input section already has a FinalSection
774 SectionInToOut::iterator pos
= _sectionInToFinalMap
.find(&inputSection
);
775 if ( pos
!= _sectionInToFinalMap
.end() ) {
779 // otherwise, create a new final section
780 switch ( _options
.outputKind() ) {
781 case Options::kStaticExecutable
:
782 case Options::kDynamicExecutable
:
783 case Options::kDynamicLibrary
:
784 case Options::kDynamicBundle
:
786 case Options::kKextBundle
:
787 case Options::kPreload
:
789 // coalesce some sections
790 const ld::Section
& outSect
= FinalSection::outputSection(inputSection
, _options
.mergeZeroFill());
791 pos
= _sectionInToFinalMap
.find(&outSect
);
792 if ( pos
!= _sectionInToFinalMap
.end() ) {
793 _sectionInToFinalMap
[&inputSection
] = pos
->second
;
794 //fprintf(stderr, "_sectionInToFinalMap[%p] = %p\n", &inputSection, pos->second);
797 else if ( outSect
!= inputSection
) {
798 // new output section created, but not in map
799 baseForFinalSection
= &outSect
;
803 case Options::kObjectFile
:
804 baseForFinalSection
= &FinalSection::objectOutputSection(inputSection
, _options
);
805 pos
= _sectionInToFinalMap
.find(baseForFinalSection
);
806 if ( pos
!= _sectionInToFinalMap
.end() ) {
807 _sectionInToFinalMap
[&inputSection
] = pos
->second
;
808 //fprintf(stderr, "_sectionInToFinalMap[%p] = %p\n", &inputSection, pos->second);
814 InternalState::FinalSection
* result
= new InternalState::FinalSection(*baseForFinalSection
,
815 _sectionInToFinalMap
.size(), _options
);
816 _sectionInToFinalMap
[baseForFinalSection
] = result
;
817 //fprintf(stderr, "_sectionInToFinalMap[%p(%s)] = %p\n", baseForFinalSection, baseForFinalSection->sectionName(), result);
818 sections
.push_back(result
);
823 int InternalState::FinalSection::sectionComparer(const void* l
, const void* r
)
825 const FinalSection
* left
= *(FinalSection
**)l
;
826 const FinalSection
* right
= *(FinalSection
**)r
;
827 if ( left
->_segmentOrder
!= right
->_segmentOrder
)
828 return (left
->_segmentOrder
- right
->_segmentOrder
);
829 return (left
->_sectionOrder
- right
->_sectionOrder
);
832 void InternalState::sortSections()
834 //fprintf(stderr, "UNSORTED final sections:\n");
835 //for (std::vector<ld::Internal::FinalSection*>::iterator it = sections.begin(); it != sections.end(); ++it) {
836 // fprintf(stderr, "final section %p %s/%s\n", (*it), (*it)->segmentName(), (*it)->sectionName());
838 qsort(§ions
[0], sections
.size(), sizeof(FinalSection
*), &InternalState::FinalSection::sectionComparer
);
839 //fprintf(stderr, "SORTED final sections:\n");
840 //for (std::vector<ld::Internal::FinalSection*>::iterator it = sections.begin(); it != sections.end(); ++it) {
841 // fprintf(stderr, "final section %p %s/%s\n", (*it), (*it)->segmentName(), (*it)->sectionName());
843 assert((sections
[0]->type() == ld::Section::typeMachHeader
)
844 || ((sections
[0]->type() == ld::Section::typeFirstSection
) && (sections
[1]->type() == ld::Section::typeMachHeader
))
845 || ((sections
[0]->type() == ld::Section::typePageZero
) && (sections
[1]->type() == ld::Section::typeMachHeader
))
846 || ((sections
[0]->type() == ld::Section::typePageZero
) && (sections
[1]->type() == ld::Section::typeFirstSection
) && (sections
[2]->type() == ld::Section::typeMachHeader
)) );
851 bool InternalState::hasZeroForFileOffset(const ld::Section
* sect
)
853 switch ( sect
->type() ) {
854 case ld::Section::typeZeroFill
:
855 case ld::Section::typeTLVZeroFill
:
856 return _options
.optimizeZeroFill();
857 case ld::Section::typePageZero
:
858 case ld::Section::typeStack
:
859 case ld::Section::typeTentativeDefs
:
867 uint64_t InternalState::pageAlign(uint64_t addr
)
869 const uint64_t alignment
= _options
.segmentAlignment();
870 return ((addr
+alignment
-1) & (-alignment
));
873 uint64_t InternalState::pageAlign(uint64_t addr
, uint64_t pageSize
)
875 return ((addr
+pageSize
-1) & (-pageSize
));
878 void InternalState::setSectionSizesAndAlignments()
880 for (std::vector
<ld::Internal::FinalSection
*>::iterator sit
= sections
.begin(); sit
!= sections
.end(); ++sit
) {
881 ld::Internal::FinalSection
* sect
= *sit
;
882 if ( sect
->type() == ld::Section::typeAbsoluteSymbols
) {
883 // absolute symbols need their finalAddress() to their value
884 for (std::vector
<const ld::Atom
*>::iterator ait
= sect
->atoms
.begin(); ait
!= sect
->atoms
.end(); ++ait
) {
885 const ld::Atom
* atom
= *ait
;
886 (const_cast<ld::Atom
*>(atom
))->setSectionOffset(atom
->objectAddress());
890 uint16_t maxAlignment
= 0;
892 for (std::vector
<const ld::Atom
*>::iterator ait
= sect
->atoms
.begin(); ait
!= sect
->atoms
.end(); ++ait
) {
893 const ld::Atom
* atom
= *ait
;
894 bool pagePerAtom
= false;
895 uint32_t atomAlignmentPowerOf2
= atom
->alignment().powerOf2
;
896 uint32_t atomModulus
= atom
->alignment().modulus
;
897 if ( _options
.pageAlignDataAtoms() && ( strncmp(atom
->section().segmentName(), "__DATA", 6) == 0) ) {
898 // most objc sections cannot be padded
899 bool contiguousObjCSection
= ( strncmp(atom
->section().sectionName(), "__objc_", 7) == 0 );
900 if ( strcmp(atom
->section().sectionName(), "__objc_const") == 0 )
901 contiguousObjCSection
= false;
902 if ( strcmp(atom
->section().sectionName(), "__objc_data") == 0 )
903 contiguousObjCSection
= false;
904 switch ( atom
->section().type() ) {
905 case ld::Section::typeUnclassified
:
906 case ld::Section::typeTentativeDefs
:
907 case ld::Section::typeZeroFill
:
908 if ( contiguousObjCSection
)
911 if ( atomAlignmentPowerOf2
< 12 ) {
912 atomAlignmentPowerOf2
= 12;
920 if ( atomAlignmentPowerOf2
> maxAlignment
)
921 maxAlignment
= atomAlignmentPowerOf2
;
922 // calculate section offset for this atom
923 uint64_t alignment
= 1 << atomAlignmentPowerOf2
;
924 uint64_t currentModulus
= (offset
% alignment
);
925 uint64_t requiredModulus
= atomModulus
;
926 if ( currentModulus
!= requiredModulus
) {
927 if ( requiredModulus
> currentModulus
)
928 offset
+= requiredModulus
-currentModulus
;
930 offset
+= requiredModulus
+alignment
-currentModulus
;
932 // LINKEDIT atoms are laid out later
933 if ( sect
->type() != ld::Section::typeLinkEdit
) {
934 (const_cast<ld::Atom
*>(atom
))->setSectionOffset(offset
);
935 offset
+= atom
->size();
937 offset
= (offset
+ 4095) & (-4096); // round up to end of page
940 if ( (atom
->scope() == ld::Atom::scopeGlobal
)
941 && (atom
->definition() == ld::Atom::definitionRegular
)
942 && (atom
->combine() == ld::Atom::combineByName
)
943 && ((atom
->symbolTableInclusion() == ld::Atom::symbolTableIn
)
944 || (atom
->symbolTableInclusion() == ld::Atom::symbolTableInAndNeverStrip
)) ) {
945 this->hasWeakExternalSymbols
= true;
946 if ( _options
.warnWeakExports() )
947 warning("weak external symbol: %s", atom
->name());
951 // section alignment is that of a contained atom with the greatest alignment
952 sect
->alignment
= maxAlignment
;
953 // unless -sectalign command line option overrides
954 if ( _options
.hasCustomSectionAlignment(sect
->segmentName(), sect
->sectionName()) )
955 sect
->alignment
= _options
.customSectionAlignment(sect
->segmentName(), sect
->sectionName());
956 // each atom in __eh_frame has zero alignment to assure they pack together,
957 // but compilers usually make the CFIs pointer sized, so we want whole section
958 // to start on pointer sized boundary.
959 if ( sect
->type() == ld::Section::typeCFI
)
961 if ( sect
->type() == ld::Section::typeTLVDefs
)
962 this->hasThreadLocalVariableDefinitions
= true;
966 // <rdar://problem/24221680> All __thread_data and __thread_bss sections must have same alignment
967 uint8_t maxThreadAlign
= 0;
968 for (ld::Internal::FinalSection
* sect
: sections
) {
969 if ( (sect
->type() == ld::Section::typeTLVInitialValues
) || (sect
->type() == ld::Section::typeTLVZeroFill
) ) {
970 if ( sect
->alignment
> maxThreadAlign
)
971 maxThreadAlign
= sect
->alignment
;
974 for (ld::Internal::FinalSection
* sect
: sections
) {
975 if ( (sect
->type() == ld::Section::typeTLVInitialValues
) || (sect
->type() == ld::Section::typeTLVZeroFill
) ) {
976 sect
->alignment
= maxThreadAlign
;
982 uint64_t InternalState::assignFileOffsets()
984 const bool log
= false;
985 const bool hiddenSectionsOccupyAddressSpace
= ((_options
.outputKind() != Options::kObjectFile
)
986 && (_options
.outputKind() != Options::kPreload
));
987 const bool segmentsArePageAligned
= (_options
.outputKind() != Options::kObjectFile
);
989 uint64_t address
= 0;
990 const char* lastSegName
= "";
991 uint64_t floatingAddressStart
= _options
.baseAddress();
992 bool haveFixedSegments
= false;
994 // mark all sections as not having an address yet
995 for (std::vector
<ld::Internal::FinalSection
*>::iterator it
= sections
.begin(); it
!= sections
.end(); ++it
) {
996 ld::Internal::FinalSection
* sect
= *it
;
997 sect
->alignmentPaddingBytes
= 0;
998 sect
->address
= ULLONG_MAX
;
1001 // first pass, assign addresses to sections in segments with fixed start addresses
1002 if ( log
) fprintf(stderr
, "Fixed address segments:\n");
1003 for (std::vector
<ld::Internal::FinalSection
*>::iterator it
= sections
.begin(); it
!= sections
.end(); ++it
) {
1004 ld::Internal::FinalSection
* sect
= *it
;
1005 if ( ! _options
.hasCustomSegmentAddress(sect
->segmentName()) )
1007 haveFixedSegments
= true;
1008 if ( segmentsArePageAligned
) {
1009 if ( strcmp(lastSegName
, sect
->segmentName()) != 0 ) {
1010 address
= _options
.customSegmentAddress(sect
->segmentName());
1011 lastSegName
= sect
->segmentName();
1014 // adjust section address based on alignment
1015 uint64_t unalignedAddress
= address
;
1016 uint64_t alignment
= (1 << sect
->alignment
);
1017 address
= ( (unalignedAddress
+alignment
-1) & (-alignment
) );
1019 // update section info
1020 sect
->address
= address
;
1021 sect
->alignmentPaddingBytes
= (address
- unalignedAddress
);
1023 // sanity check size
1024 if ( ((address
+ sect
->size
) > _options
.maxAddress()) && (_options
.outputKind() != Options::kObjectFile
)
1025 && (_options
.outputKind() != Options::kStaticExecutable
) )
1026 throwf("section %s (address=0x%08llX, size=%llu) would make the output executable exceed available address range",
1027 sect
->sectionName(), address
, sect
->size
);
1029 if ( log
) fprintf(stderr
, " address=0x%08llX, hidden=%d, alignment=%02d, section=%s,%s\n",
1030 sect
->address
, sect
->isSectionHidden(), sect
->alignment
, sect
->segmentName(), sect
->sectionName());
1031 // update running totals
1032 if ( !sect
->isSectionHidden() || hiddenSectionsOccupyAddressSpace
)
1033 address
+= sect
->size
;
1035 // if TEXT segment address is fixed, then flow other segments after it
1036 if ( strcmp(sect
->segmentName(), "__TEXT") == 0 ) {
1037 floatingAddressStart
= address
;
1041 // second pass, assign section addresses to sections in segments that are ordered after a segment with a fixed address
1042 if ( haveFixedSegments
&& !_options
.segmentOrder().empty() ) {
1043 if ( log
) fprintf(stderr
, "After Fixed address segments:\n");
1045 ld::Internal::FinalSection
* lastSect
= NULL
;
1046 for (std::vector
<ld::Internal::FinalSection
*>::iterator it
= sections
.begin(); it
!= sections
.end(); ++it
) {
1047 ld::Internal::FinalSection
* sect
= *it
;
1048 if ( (sect
->address
== ULLONG_MAX
) && _options
.segmentOrderAfterFixedAddressSegment(sect
->segmentName()) ) {
1049 address
= lastSect
->address
+ lastSect
->size
;
1050 if ( (strcmp(lastSegName
, sect
->segmentName()) != 0) && segmentsArePageAligned
) {
1051 // round up size of last segment
1052 address
= pageAlign(address
, _options
.segPageSize(lastSegName
));
1054 // adjust section address based on alignment
1055 uint64_t unalignedAddress
= address
;
1056 uint64_t alignment
= (1 << sect
->alignment
);
1057 address
= ( (unalignedAddress
+alignment
-1) & (-alignment
) );
1058 sect
->alignmentPaddingBytes
= (address
- unalignedAddress
);
1059 sect
->address
= address
;
1060 if ( log
) fprintf(stderr
, " address=0x%08llX, hidden=%d, alignment=%02d, section=%s,%s\n",
1061 sect
->address
, sect
->isSectionHidden(), sect
->alignment
, sect
->segmentName(), sect
->sectionName());
1062 // update running totals
1063 if ( !sect
->isSectionHidden() || hiddenSectionsOccupyAddressSpace
)
1064 address
+= sect
->size
;
1066 lastSegName
= sect
->segmentName();
1071 // last pass, assign addresses to remaining sections
1072 address
= floatingAddressStart
;
1074 ld::Internal::FinalSection
* overlappingFixedSection
= NULL
;
1075 ld::Internal::FinalSection
* overlappingFlowSection
= NULL
;
1076 ld::Internal::FinalSection
* prevSect
= NULL
;
1077 if ( log
) fprintf(stderr
, "Regular layout segments:\n");
1078 for (std::vector
<ld::Internal::FinalSection
*>::iterator it
= sections
.begin(); it
!= sections
.end(); ++it
) {
1079 ld::Internal::FinalSection
* sect
= *it
;
1080 if ( sect
->address
!= ULLONG_MAX
)
1082 if ( (_options
.outputKind() == Options::kPreload
) && (sect
->type() == ld::Section::typeMachHeader
) ) {
1083 sect
->alignmentPaddingBytes
= 0;
1086 if ( segmentsArePageAligned
) {
1087 if ( strcmp(lastSegName
, sect
->segmentName()) != 0 ) {
1088 // round up size of last segment if needed
1089 if ( *lastSegName
!= '\0' ) {
1090 address
= pageAlign(address
, _options
.segPageSize(lastSegName
));
1092 // set segment address based on end of last segment
1093 address
= pageAlign(address
);
1094 lastSegName
= sect
->segmentName();
1098 // adjust section address based on alignment
1099 uint64_t unalignedAddress
= address
;
1100 uint64_t alignment
= (1 << sect
->alignment
);
1101 address
= ( (unalignedAddress
+alignment
-1) & (-alignment
) );
1103 // update section info
1104 sect
->address
= address
;
1105 sect
->alignmentPaddingBytes
= (address
- unalignedAddress
);
1107 // <rdar://problem/21994854> if first section is more aligned than segment, move segment start up to match
1108 if ( (prevSect
!= NULL
) && (prevSect
->type() == ld::Section::typeFirstSection
) && (strcmp(prevSect
->segmentName(), sect
->segmentName()) == 0) ) {
1109 assert(prevSect
->size
== 0);
1110 if ( prevSect
->address
!= sect
->address
) {
1111 prevSect
->alignmentPaddingBytes
+= (sect
->address
- prevSect
->address
);
1112 prevSect
->address
= sect
->address
;
1116 // sanity check size
1117 if ( ((address
+ sect
->size
) > _options
.maxAddress()) && (_options
.outputKind() != Options::kObjectFile
)
1118 && (_options
.outputKind() != Options::kStaticExecutable
) )
1119 throwf("section %s (address=0x%08llX, size=%llu) would make the output executable exceed available address range",
1120 sect
->sectionName(), address
, sect
->size
);
1122 // sanity check it does not overlap a fixed address segment
1123 for (std::vector
<ld::Internal::FinalSection
*>::iterator sit
= sections
.begin(); sit
!= sections
.end(); ++sit
) {
1124 ld::Internal::FinalSection
* otherSect
= *sit
;
1125 if ( ! _options
.hasCustomSegmentAddress(otherSect
->segmentName()) )
1127 if ( otherSect
->size
== 0 )
1129 if ( sect
->size
== 0 )
1131 if ( sect
->address
> otherSect
->address
) {
1132 if ( (otherSect
->address
+otherSect
->size
) > sect
->address
) {
1133 overlappingFixedSection
= otherSect
;
1134 overlappingFlowSection
= sect
;
1138 if ( (sect
->address
+sect
->size
) > otherSect
->address
) {
1139 overlappingFixedSection
= otherSect
;
1140 overlappingFlowSection
= sect
;
1145 if ( log
) fprintf(stderr
, " address=0x%08llX, size=0x%08llX, hidden=%d, alignment=%02d, padBytes=%d, section=%s,%s\n",
1146 sect
->address
, sect
->size
, sect
->isSectionHidden(), sect
->alignment
, sect
->alignmentPaddingBytes
,
1147 sect
->segmentName(), sect
->sectionName());
1148 // update running totals
1149 if ( !sect
->isSectionHidden() || hiddenSectionsOccupyAddressSpace
)
1150 address
+= sect
->size
;
1153 if ( overlappingFixedSection
!= NULL
) {
1154 fprintf(stderr
, "Section layout:\n");
1155 for (std::vector
<ld::Internal::FinalSection
*>::iterator it
= sections
.begin(); it
!= sections
.end(); ++it
) {
1156 ld::Internal::FinalSection
* sect
= *it
;
1157 //if ( sect->isSectionHidden() )
1159 fprintf(stderr
, " address:0x%08llX, alignment:2^%d, size:0x%08llX, padBytes:%d, section:%s/%s\n",
1160 sect
->address
, sect
->alignment
, sect
->size
, sect
->alignmentPaddingBytes
,
1161 sect
->segmentName(), sect
->sectionName());
1164 throwf("Section (%s/%s) overlaps fixed address section (%s/%s)",
1165 overlappingFlowSection
->segmentName(), overlappingFlowSection
->sectionName(),
1166 overlappingFixedSection
->segmentName(), overlappingFixedSection
->sectionName());
1170 // third pass, assign section file offsets
1171 uint64_t fileOffset
= 0;
1173 if ( log
) fprintf(stderr
, "All segments with file offsets:\n");
1174 for (std::vector
<ld::Internal::FinalSection
*>::iterator it
= sections
.begin(); it
!= sections
.end(); ++it
) {
1175 ld::Internal::FinalSection
* sect
= *it
;
1176 if ( hasZeroForFileOffset(sect
) ) {
1177 // fileoff of zerofill sections is moot, but historically it is set to zero
1178 sect
->fileOffset
= 0;
1180 // <rdar://problem/10445047> align file offset with address layout
1181 fileOffset
+= sect
->alignmentPaddingBytes
;
1184 // page align file offset at start of each segment
1185 if ( segmentsArePageAligned
&& (*lastSegName
!= '\0') && (strcmp(lastSegName
, sect
->segmentName()) != 0) ) {
1186 fileOffset
= pageAlign(fileOffset
, _options
.segPageSize(lastSegName
));
1188 lastSegName
= sect
->segmentName();
1190 // align file offset with address layout
1191 fileOffset
+= sect
->alignmentPaddingBytes
;
1193 // update section info
1194 sect
->fileOffset
= fileOffset
;
1196 // update running total
1197 fileOffset
+= sect
->size
;
1200 if ( log
) fprintf(stderr
, " fileoffset=0x%08llX, address=0x%08llX, hidden=%d, size=%lld, alignment=%02d, section=%s,%s\n",
1201 sect
->fileOffset
, sect
->address
, sect
->isSectionHidden(), sect
->size
, sect
->alignment
,
1202 sect
->segmentName(), sect
->sectionName());
1206 // for encrypted iPhoneOS apps
1207 if ( _options
.makeEncryptable() ) {
1208 // remember end of __TEXT for later use by load command
1209 for (std::vector
<ld::Internal::FinalSection
*>::iterator it
= state
.sections
.begin(); it
!= state
.sections
.end(); ++it
) {
1210 ld::Internal::FinalSection
* sect
= *it
;
1211 if ( strcmp(sect
->segmentName(), "__TEXT") == 0 ) {
1212 _encryptedTEXTendOffset
= pageAlign(sect
->fileOffset
+ sect
->size
);
1218 // return total file size
1222 static char* commatize(uint64_t in
, char* out
)
1226 sprintf(rawNum
, "%llu", in
);
1227 const int rawNumLen
= strlen(rawNum
);
1228 for(int i
=0; i
< rawNumLen
-1; ++i
) {
1230 if ( ((rawNumLen
-i
) % 3) == 1 )
1233 *out
++ = rawNum
[rawNumLen
-1];
1238 static void printTime(const char* msg
, uint64_t partTime
, uint64_t totalTime
)
1240 static uint64_t sUnitsPerSecond
= 0;
1241 if ( sUnitsPerSecond
== 0 ) {
1242 struct mach_timebase_info timeBaseInfo
;
1243 if ( mach_timebase_info(&timeBaseInfo
) != KERN_SUCCESS
)
1245 sUnitsPerSecond
= 1000000000ULL * timeBaseInfo
.denom
/ timeBaseInfo
.numer
;
1247 if ( partTime
< sUnitsPerSecond
) {
1248 uint32_t milliSecondsTimeTen
= (partTime
*10000)/sUnitsPerSecond
;
1249 uint32_t milliSeconds
= milliSecondsTimeTen
/10;
1250 uint32_t percentTimesTen
= (partTime
*1000)/totalTime
;
1251 uint32_t percent
= percentTimesTen
/10;
1252 fprintf(stderr
, "%24s: % 4d.%d milliseconds (% 4d.%d%%)\n", msg
, milliSeconds
, milliSecondsTimeTen
-milliSeconds
*10, percent
, percentTimesTen
-percent
*10);
1255 uint32_t secondsTimeTen
= (partTime
*10)/sUnitsPerSecond
;
1256 uint32_t seconds
= secondsTimeTen
/10;
1257 uint32_t percentTimesTen
= (partTime
*1000)/totalTime
;
1258 uint32_t percent
= percentTimesTen
/10;
1259 fprintf(stderr
, "%24s: % 4d.%d seconds (% 4d.%d%%)\n", msg
, seconds
, secondsTimeTen
-seconds
*10, percent
, percentTimesTen
-percent
*10);
1264 static void getVMInfo(vm_statistics_data_t
& info
)
1266 mach_msg_type_number_t count
= sizeof(vm_statistics_data_t
) / sizeof(natural_t
);
1267 kern_return_t error
= host_statistics(mach_host_self(), HOST_VM_INFO
,
1268 (host_info_t
)&info
, &count
);
1269 if (error
!= KERN_SUCCESS
) {
1270 bzero(&info
, sizeof(vm_statistics_data_t
));
1276 static const char* sOverridePathlibLTO
= NULL
;
1279 // This is magic glue that overrides the default behaviour
1280 // of lazydylib1.o which is used to lazily load libLTO.dylib.
1282 extern "C" const char* dyld_lazy_dylib_path_fix(const char* path
);
1283 const char* dyld_lazy_dylib_path_fix(const char* path
)
1285 if ( sOverridePathlibLTO
!= NULL
)
1286 return sOverridePathlibLTO
;
1293 int main(int argc
, const char* argv
[])
1295 const char* archName
= NULL
;
1296 bool showArch
= false;
1297 bool archInferred
= false;
1299 PerformanceStatistics statistics
;
1300 statistics
.startTool
= mach_absolute_time();
1302 // create object to track command line arguments
1303 Options
options(argc
, argv
);
1304 InternalState
state(options
);
1306 // allow libLTO to be overridden by command line -lto_library
1307 sOverridePathlibLTO
= options
.overridePathlibLTO();
1310 if ( options
.printStatistics() )
1311 getVMInfo(statistics
.vmStart
);
1313 // update strings for error messages
1314 showArch
= options
.printArchPrefix();
1315 archName
= options
.architectureName();
1316 archInferred
= (options
.architecture() == 0);
1318 // open and parse input files
1319 statistics
.startInputFileProcessing
= mach_absolute_time();
1320 ld::tool::InputFiles
inputFiles(options
, &archName
);
1322 // load and resolve all references
1323 statistics
.startResolver
= mach_absolute_time();
1324 ld::tool::Resolver
resolver(options
, inputFiles
, state
);
1328 statistics
.startDylibs
= mach_absolute_time();
1329 inputFiles
.dylibs(state
);
1331 // do initial section sorting so passes have rough idea of the layout
1332 state
.sortSections();
1335 statistics
.startPasses
= mach_absolute_time();
1336 ld::passes::objc::doPass(options
, state
);
1337 ld::passes::stubs::doPass(options
, state
);
1338 ld::passes::huge::doPass(options
, state
);
1339 ld::passes::got::doPass(options
, state
);
1340 ld::passes::tlvp::doPass(options
, state
);
1341 ld::passes::dylibs::doPass(options
, state
); // must be after stubs and GOT passes
1342 ld::passes::order::doPass(options
, state
);
1343 state
.markAtomsOrdered();
1344 ld::passes::dedup::doPass(options
, state
);
1345 ld::passes::branch_shim::doPass(options
, state
); // must be after stubs
1346 ld::passes::branch_island::doPass(options
, state
); // must be after stubs and order pass
1347 ld::passes::dtrace::doPass(options
, state
);
1348 ld::passes::compact_unwind::doPass(options
, state
); // must be after order pass
1349 ld::passes::bitcode_bundle::doPass(options
, state
); // must be after dylib
1351 // sort final sections
1352 state
.sortSections();
1354 // write output file
1355 statistics
.startOutput
= mach_absolute_time();
1356 ld::tool::OutputFile
out(options
);
1358 statistics
.startDone
= mach_absolute_time();
1361 //mach_o::relocatable::printCounts();
1362 if ( options
.printStatistics() ) {
1363 getVMInfo(statistics
.vmEnd
);
1364 uint64_t totalTime
= statistics
.startDone
- statistics
.startTool
;
1365 printTime("ld total time", totalTime
, totalTime
);
1366 printTime(" option parsing time", statistics
.startInputFileProcessing
- statistics
.startTool
, totalTime
);
1367 printTime(" object file processing", statistics
.startResolver
- statistics
.startInputFileProcessing
,totalTime
);
1368 printTime(" resolve symbols", statistics
.startDylibs
- statistics
.startResolver
, totalTime
);
1369 printTime(" build atom list", statistics
.startPasses
- statistics
.startDylibs
, totalTime
);
1370 printTime(" passess", statistics
.startOutput
- statistics
.startPasses
, totalTime
);
1371 printTime(" write output", statistics
.startDone
- statistics
.startOutput
, totalTime
);
1372 fprintf(stderr
, "pageins=%u, pageouts=%u, faults=%u\n",
1373 statistics
.vmEnd
.pageins
-statistics
.vmStart
.pageins
,
1374 statistics
.vmEnd
.pageouts
-statistics
.vmStart
.pageouts
,
1375 statistics
.vmEnd
.faults
-statistics
.vmStart
.faults
);
1377 fprintf(stderr
, "processed %3u object files, totaling %15s bytes\n", inputFiles
._totalObjectLoaded
, commatize(inputFiles
._totalObjectSize
, temp
));
1378 fprintf(stderr
, "processed %3u archive files, totaling %15s bytes\n", inputFiles
._totalArchivesLoaded
, commatize(inputFiles
._totalArchiveSize
, temp
));
1379 fprintf(stderr
, "processed %3u dylib files\n", inputFiles
._totalDylibsLoaded
);
1380 fprintf(stderr
, "wrote output file totaling %15s bytes\n", commatize(out
.fileSize(), temp
));
1382 // <rdar://problem/6780050> Would like linker warning to be build error.
1383 if ( options
.errorBecauseOfWarnings() ) {
1384 fprintf(stderr
, "ld: fatal warning(s) induced error (-fatal_warnings)\n");
1388 catch (const char* msg
) {
1389 if ( strstr(msg
, "malformed") != NULL
)
1390 fprintf(stderr
, "ld: %s\n", msg
);
1391 else if ( archInferred
)
1392 fprintf(stderr
, "ld: %s for inferred architecture %s\n", msg
, archName
);
1393 else if ( showArch
)
1394 fprintf(stderr
, "ld: %s for architecture %s\n", msg
, archName
);
1396 fprintf(stderr
, "ld: %s\n", msg
);
1405 // implement assert() function to print out a backtrace before aborting
1406 void __assert_rtn(const char* func
, const char* file
, int line
, const char* failedexpr
)
1408 Snapshot
*snapshot
= Snapshot::globalSnapshot
;
1410 snapshot
->setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
1411 snapshot
->createSnapshot();
1412 snapshot
->recordAssertionMessage("Assertion failed: (%s), function %s, file %s, line %d.\n", failedexpr
, func
, file
, line
);
1414 void* callStack
[128];
1415 int depth
= ::backtrace(callStack
, 128);
1416 char* buffer
= (char*)malloc(1024);
1417 for(int i
=0; i
< depth
-1; ++i
) {
1419 dladdr(callStack
[i
], &info
);
1420 const char* symboName
= info
.dli_sname
;
1421 if ( (symboName
!= NULL
) && (strncmp(symboName
, "_Z", 2) == 0) ) {
1422 size_t bufLen
= 1024;
1424 char* unmangled
= abi::__cxa_demangle(symboName
, buffer
, &bufLen
, &result
);
1425 if ( unmangled
!= NULL
)
1426 symboName
= unmangled
;
1428 long offset
= (uintptr_t)callStack
[i
] - (uintptr_t)info
.dli_saddr
;
1429 fprintf(stderr
, "%d %p %s + %ld\n", i
, callStack
[i
], symboName
, offset
);
1430 snapshot
->recordAssertionMessage("%d %p %s + %ld\n", i
, callStack
[i
], symboName
, offset
);
1432 fprintf(stderr
, "A linker snapshot was created at:\n\t%s\n", snapshot
->rootDir());
1433 fprintf(stderr
, "ld: Assertion failed: (%s), function %s, file %s, line %d.\n", failedexpr
, func
, file
, line
);