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"
84 #include "parsers/archive_file.h"
85 #include "parsers/macho_relocatable_file.h"
86 #include "parsers/macho_dylib_file.h"
87 #include "parsers/lto_file.h"
88 #include "parsers/opaque_section_file.h"
91 struct PerformanceStatistics
{
93 uint64_t startInputFileProcessing
;
94 uint64_t startResolver
;
99 vm_statistics_data_t vmStart
;
100 vm_statistics_data_t vmEnd
;
104 class InternalState
: public ld::Internal
107 InternalState(const Options
& opts
) : _options(opts
), _atomsOrderedInSections(false) { }
108 virtual ld::Internal::FinalSection
* addAtom(const ld::Atom
& atom
);
109 virtual ld::Internal::FinalSection
* getFinalSection(const ld::Section
&);
110 ld::Internal::FinalSection
* getFinalSection(const char* seg
, const char* sect
, ld::Section::Type type
);
112 uint64_t assignFileOffsets();
113 void setSectionSizesAndAlignments();
115 void markAtomsOrdered() { _atomsOrderedInSections
= true; }
116 bool hasReferenceToWeakExternal(const ld::Atom
& atom
);
118 virtual ~InternalState() {}
121 class FinalSection
: public ld::Internal::FinalSection
124 FinalSection(const ld::Section
& sect
, uint32_t sectionsSeen
, const Options
&);
125 static int sectionComparer(const void* l
, const void* r
);
126 static const ld::Section
& outputSection(const ld::Section
& sect
, bool mergeZeroFill
);
127 static const ld::Section
& objectOutputSection(const ld::Section
& sect
, const Options
&);
129 friend class InternalState
;
130 static uint32_t sectionOrder(const ld::Section
& sect
, uint32_t sectionsSeen
, const Options
& options
);
131 static uint32_t segmentOrder(const ld::Section
& sect
, const Options
& options
);
132 uint32_t _segmentOrder
;
133 uint32_t _sectionOrder
;
135 static std::vector
<const char*> _s_segmentsSeen
;
136 static ld::Section _s_DATA_data
;
137 static ld::Section _s_DATA_const
;
138 static ld::Section _s_TEXT_text
;
139 static ld::Section _s_TEXT_const
;
140 static ld::Section _s_DATA_nl_symbol_ptr
;
141 static ld::Section _s_DATA_common
;
142 static ld::Section _s_DATA_zerofill
;
143 static ld::Section _s_DATA_DIRTY_data
;
144 static ld::Section _s_DATA_CONST_const
;
147 bool hasZeroForFileOffset(const ld::Section
* sect
);
148 uint64_t pageAlign(uint64_t addr
);
149 uint64_t pageAlign(uint64_t addr
, uint64_t pageSize
);
152 size_t operator()(const ld::Section
*) const;
154 struct SectionEquals
{
155 bool operator()(const ld::Section
* left
, const ld::Section
* right
) const;
157 typedef std::unordered_map
<const ld::Section
*, FinalSection
*, SectionHash
, SectionEquals
> SectionInToOut
;
160 SectionInToOut _sectionInToFinalMap
;
161 const Options
& _options
;
162 bool _atomsOrderedInSections
;
165 ld::Section
InternalState::FinalSection::_s_DATA_data( "__DATA", "__data", ld::Section::typeUnclassified
);
166 ld::Section
InternalState::FinalSection::_s_DATA_const("__DATA", "__const", ld::Section::typeUnclassified
);
167 ld::Section
InternalState::FinalSection::_s_TEXT_text( "__TEXT", "__text", ld::Section::typeCode
);
168 ld::Section
InternalState::FinalSection::_s_TEXT_const("__TEXT", "__const", ld::Section::typeUnclassified
);
169 ld::Section
InternalState::FinalSection::_s_DATA_nl_symbol_ptr("__DATA", "__nl_symbol_ptr", ld::Section::typeNonLazyPointer
);
170 ld::Section
InternalState::FinalSection::_s_DATA_common("__DATA", "__common", ld::Section::typeZeroFill
);
171 ld::Section
InternalState::FinalSection::_s_DATA_zerofill("__DATA", "__zerofill", ld::Section::typeZeroFill
);
172 ld::Section
InternalState::FinalSection::_s_DATA_DIRTY_data( "__DATA_DIRTY", "__data", ld::Section::typeUnclassified
);
173 ld::Section
InternalState::FinalSection::_s_DATA_CONST_const( "__DATA_CONST", "__const", ld::Section::typeUnclassified
);
175 std::vector
<const char*> InternalState::FinalSection::_s_segmentsSeen
;
178 size_t InternalState::SectionHash::operator()(const ld::Section
* sect
) const
181 ld::CStringHash temp
;
182 hash
+= temp
.operator()(sect
->segmentName());
183 hash
+= temp
.operator()(sect
->sectionName());
187 bool InternalState::SectionEquals::operator()(const ld::Section
* left
, const ld::Section
* right
) const
189 return (*left
== *right
);
193 InternalState::FinalSection::FinalSection(const ld::Section
& sect
, uint32_t sectionsSeen
, const Options
& opts
)
194 : ld::Internal::FinalSection(sect
),
195 _segmentOrder(segmentOrder(sect
, opts
)),
196 _sectionOrder(sectionOrder(sect
, sectionsSeen
, opts
))
198 //fprintf(stderr, "FinalSection(%s, %s) _segmentOrder=%d, _sectionOrder=%d\n",
199 // this->segmentName(), this->sectionName(), _segmentOrder, _sectionOrder);
202 const ld::Section
& InternalState::FinalSection::outputSection(const ld::Section
& sect
, bool mergeZeroFill
)
204 // merge sections in final linked image
205 switch ( sect
.type() ) {
206 case ld::Section::typeLiteral4
:
207 case ld::Section::typeLiteral8
:
208 case ld::Section::typeLiteral16
:
209 if ( strcmp(sect
.segmentName(), "__TEXT") == 0 )
210 return _s_TEXT_const
;
212 case ld::Section::typeUnclassified
:
213 if ( strcmp(sect
.segmentName(), "__DATA") == 0 ) {
214 if ( strcmp(sect
.sectionName(), "__datacoal_nt") == 0 )
216 if ( strcmp(sect
.sectionName(), "__const_coal") == 0 )
217 return _s_DATA_const
;
219 else if ( strcmp(sect
.segmentName(), "__TEXT") == 0 ) {
220 if ( strcmp(sect
.sectionName(), "__const_coal") == 0 )
221 return _s_TEXT_const
;
223 else if ( strcmp(sect
.segmentName(), "__DATA_DIRTY") == 0 ) {
224 if ( strcmp(sect
.sectionName(), "__datacoal_nt") == 0 )
225 return _s_DATA_DIRTY_data
;
227 else if ( strcmp(sect
.segmentName(), "__DATA_CONST") == 0 ) {
228 if ( strcmp(sect
.sectionName(), "__const_coal") == 0 )
229 return _s_DATA_CONST_const
;
232 case ld::Section::typeZeroFill
:
234 return _s_DATA_zerofill
;
236 case ld::Section::typeCode
:
237 if ( strcmp(sect
.segmentName(), "__TEXT") == 0 ) {
238 if ( strcmp(sect
.sectionName(), "__textcoal_nt") == 0 )
240 else if ( strcmp(sect
.sectionName(), "__StaticInit") == 0 )
244 case ld::Section::typeNonLazyPointer
:
245 if ( strcmp(sect
.segmentName(), "__DATA") == 0 ) {
246 if ( strcmp(sect
.sectionName(), "__nl_symbol_ptr") == 0 )
247 return _s_DATA_nl_symbol_ptr
;
249 else if ( strcmp(sect
.segmentName(), "__IMPORT") == 0 ) {
250 if ( strcmp(sect
.sectionName(), "__pointers") == 0 )
251 return _s_DATA_nl_symbol_ptr
;
254 case ld::Section::typeTentativeDefs
:
255 if ( (strcmp(sect
.segmentName(), "__DATA") == 0) && (strcmp(sect
.sectionName(), "__comm/tent") == 0) ) {
257 return _s_DATA_zerofill
;
259 return _s_DATA_common
;
269 const ld::Section
& InternalState::FinalSection::objectOutputSection(const ld::Section
& sect
, const Options
& options
)
271 // in -r mode the only section that ever changes is __tenative -> __common with -d option
272 if ( (sect
.type() == ld::Section::typeTentativeDefs
) && options
.makeTentativeDefinitionsReal())
273 return _s_DATA_common
;
277 uint32_t InternalState::FinalSection::segmentOrder(const ld::Section
& sect
, const Options
& options
)
279 if ( options
.outputKind() == Options::kPreload
) {
280 if ( strcmp(sect
.segmentName(), "__HEADER") == 0 )
282 const std::vector
<const char*>& order
= options
.segmentOrder();
283 for (size_t i
=0; i
!= order
.size(); ++i
) {
284 if ( strcmp(sect
.segmentName(), order
[i
]) == 0 )
287 if ( strcmp(sect
.segmentName(), "__TEXT") == 0 )
288 return order
.size()+1;
289 if ( strcmp(sect
.segmentName(), "__DATA") == 0 )
290 return order
.size()+2;
293 if ( strcmp(sect
.segmentName(), "__PAGEZERO") == 0 )
295 if ( strcmp(sect
.segmentName(), "__TEXT") == 0 )
297 // in -r mode, want __DATA last so zerofill sections are at end
298 if ( strcmp(sect
.segmentName(), "__DATA") == 0 )
299 return (options
.outputKind() == Options::kObjectFile
) ? 5 : 2;
300 if ( strcmp(sect
.segmentName(), "__OBJC") == 0 )
302 if ( strcmp(sect
.segmentName(), "__IMPORT") == 0 )
305 // layout non-standard segments in order seen (+100 to shift beyond standard segments)
306 for (uint32_t i
=0; i
< _s_segmentsSeen
.size(); ++i
) {
307 if ( strcmp(_s_segmentsSeen
[i
], sect
.segmentName()) == 0 )
310 _s_segmentsSeen
.push_back(sect
.segmentName());
311 return _s_segmentsSeen
.size()-1+100;
314 uint32_t InternalState::FinalSection::sectionOrder(const ld::Section
& sect
, uint32_t sectionsSeen
, const Options
& options
)
316 if ( sect
.type() == ld::Section::typeFirstSection
)
318 if ( sect
.type() == ld::Section::typeMachHeader
)
320 if ( sect
.type() == ld::Section::typeLastSection
)
322 const std::vector
<const char*>* sectionList
= options
.sectionOrder(sect
.segmentName());
323 if ( ((options
.outputKind() == Options::kPreload
) || (options
.outputKind() == Options::kDyld
)) && (sectionList
!= NULL
) ) {
325 for (std::vector
<const char*>::const_iterator it
=sectionList
->begin(); it
!= sectionList
->end(); ++it
, ++count
) {
326 if ( strcmp(*it
, sect
.sectionName()) == 0 )
330 if ( strcmp(sect
.segmentName(), "__TEXT") == 0 ) {
331 switch ( sect
.type() ) {
332 case ld::Section::typeCode
:
333 // <rdar://problem/8346444> make __text always be first "code" section
334 if ( strcmp(sect
.sectionName(), "__text") == 0 )
338 case ld::Section::typeStub
:
340 case ld::Section::typeStubHelper
:
342 case ld::Section::typeLSDA
:
344 case ld::Section::typeUnwindInfo
:
346 case ld::Section::typeCFI
:
348 case ld::Section::typeStubClose
:
351 return sectionsSeen
+20;
354 else if ( strncmp(sect
.segmentName(), "__DATA", 6) == 0 ) {
355 switch ( sect
.type() ) {
356 case ld::Section::typeLazyPointerClose
:
358 case ld::Section::typeDyldInfo
:
360 case ld::Section::typeNonLazyPointer
:
362 case ld::Section::typeLazyPointer
:
364 case ld::Section::typeInitializerPointers
:
366 case ld::Section::typeTerminatorPointers
:
368 case ld::Section::typeTLVInitialValues
:
369 return INT_MAX
-4; // need TLV zero-fill to follow TLV init values
370 case ld::Section::typeTLVZeroFill
:
372 case ld::Section::typeZeroFill
:
373 // make sure __huge is always last zerofill section
374 if ( strcmp(sect
.sectionName(), "__huge") == 0 )
379 // <rdar://problem/14348664> __DATA,__const section should be near __mod_init_func not __data
380 if ( strcmp(sect
.sectionName(), "__const") == 0 )
382 // <rdar://problem/17125893> Linker should put __cfstring near __const
383 if ( strcmp(sect
.sectionName(), "__cfstring") == 0 )
385 // <rdar://problem/7435296> Reorder sections to reduce page faults in object files
386 else if ( strcmp(sect
.sectionName(), "__objc_classlist") == 0 )
388 else if ( strcmp(sect
.sectionName(), "__objc_nlclslist") == 0 )
390 else if ( strcmp(sect
.sectionName(), "__objc_catlist") == 0 )
392 else if ( strcmp(sect
.sectionName(), "__objc_nlcatlist") == 0 )
394 else if ( strcmp(sect
.sectionName(), "__objc_protolist") == 0 )
396 else if ( strcmp(sect
.sectionName(), "__objc_imageinfo") == 0 )
398 else if ( strcmp(sect
.sectionName(), "__objc_const") == 0 )
400 else if ( strcmp(sect
.sectionName(), "__objc_selrefs") == 0 )
402 else if ( strcmp(sect
.sectionName(), "__objc_msgrefs") == 0 )
404 else if ( strcmp(sect
.sectionName(), "__objc_protorefs") == 0 )
406 else if ( strcmp(sect
.sectionName(), "__objc_classrefs") == 0 )
408 else if ( strcmp(sect
.sectionName(), "__objc_superrefs") == 0 )
410 else if ( strcmp(sect
.sectionName(), "__objc_ivar") == 0 )
412 else if ( strcmp(sect
.sectionName(), "__objc_data") == 0 )
415 return sectionsSeen
+40;
418 // make sure zerofill in any other section is at end of segment
419 if ( sect
.type() == ld::Section::typeZeroFill
)
421 return sectionsSeen
+20;
425 static void validateFixups(const ld::Atom
& atom
)
427 //fprintf(stderr, "validateFixups %s\n", atom.name());
428 bool lastWasClusterEnd
= true;
429 ld::Fixup::Cluster lastClusterSize
= ld::Fixup::k1of1
;
430 uint32_t curClusterOffsetInAtom
= 0;
431 for (ld::Fixup::iterator fit
=atom
.fixupsBegin(); fit
!= atom
.fixupsEnd(); ++fit
) {
432 //fprintf(stderr, " fixup offset=%d, cluster=%d\n", fit->offsetInAtom, fit->clusterSize);
433 assert((fit
->offsetInAtom
<= atom
.size()) || (fit
->offsetInAtom
== 0));
434 if ( fit
->firstInCluster() ) {
435 assert(lastWasClusterEnd
);
436 curClusterOffsetInAtom
= fit
->offsetInAtom
;
437 lastWasClusterEnd
= (fit
->clusterSize
== ld::Fixup::k1of1
);
440 assert(!lastWasClusterEnd
);
441 assert(fit
->offsetInAtom
== curClusterOffsetInAtom
);
442 switch ((ld::Fixup::Cluster
)fit
->clusterSize
) {
443 case ld::Fixup::k1of1
:
444 case ld::Fixup::k1of2
:
445 case ld::Fixup::k1of3
:
446 case ld::Fixup::k1of4
:
447 case ld::Fixup::k1of5
:
448 lastWasClusterEnd
= false;
450 case ld::Fixup::k2of2
:
451 assert(lastClusterSize
= ld::Fixup::k1of2
);
452 lastWasClusterEnd
= true;
454 case ld::Fixup::k2of3
:
455 assert(lastClusterSize
= ld::Fixup::k1of3
);
456 lastWasClusterEnd
= false;
458 case ld::Fixup::k2of4
:
459 assert(lastClusterSize
= ld::Fixup::k1of4
);
460 lastWasClusterEnd
= false;
462 case ld::Fixup::k2of5
:
463 assert(lastClusterSize
= ld::Fixup::k1of5
);
464 lastWasClusterEnd
= false;
466 case ld::Fixup::k3of3
:
467 assert(lastClusterSize
= ld::Fixup::k2of3
);
468 lastWasClusterEnd
= true;
470 case ld::Fixup::k3of4
:
471 assert(lastClusterSize
= ld::Fixup::k2of4
);
472 lastWasClusterEnd
= false;
474 case ld::Fixup::k3of5
:
475 assert(lastClusterSize
= ld::Fixup::k2of5
);
476 lastWasClusterEnd
= false;
478 case ld::Fixup::k4of4
:
479 assert(lastClusterSize
= ld::Fixup::k3of4
);
480 lastWasClusterEnd
= true;
482 case ld::Fixup::k4of5
:
483 assert(lastClusterSize
= ld::Fixup::k3of5
);
484 lastWasClusterEnd
= false;
486 case ld::Fixup::k5of5
:
487 assert(lastClusterSize
= ld::Fixup::k4of5
);
488 lastWasClusterEnd
= true;
492 lastClusterSize
= fit
->clusterSize
;
493 if ( fit
->binding
== ld::Fixup::bindingDirectlyBound
) {
494 assert(fit
->u
.target
!= NULL
);
497 switch (lastClusterSize
) {
498 case ld::Fixup::k1of1
:
499 case ld::Fixup::k2of2
:
500 case ld::Fixup::k3of3
:
501 case ld::Fixup::k4of4
:
502 case ld::Fixup::k5of5
:
505 assert(0 && "last fixup was not end of cluster");
511 bool InternalState::hasReferenceToWeakExternal(const ld::Atom
& atom
)
513 // if __DATA,__const atom has pointer to weak external symbol, don't move to __DATA_CONST
514 const ld::Atom
* target
= NULL
;
515 for (ld::Fixup::iterator fit
=atom
.fixupsBegin(); fit
!= atom
.fixupsEnd(); ++fit
) {
516 if ( fit
->firstInCluster() ) {
519 switch ( fit
->binding
) {
520 case ld::Fixup::bindingNone
:
521 case ld::Fixup::bindingByNameUnbound
:
523 case ld::Fixup::bindingByContentBound
:
524 case ld::Fixup::bindingDirectlyBound
:
525 target
= fit
->u
.target
;
527 case ld::Fixup::bindingsIndirectlyBound
:
528 target
= indirectBindingTable
[fit
->u
.bindingIndex
];
531 if ( (target
!= NULL
) && (target
->definition() == ld::Atom::definitionRegular
)
532 && (target
->combine() == ld::Atom::combineByName
) && (target
->scope() == ld::Atom::scopeGlobal
) ) {
539 ld::Internal::FinalSection
* InternalState::addAtom(const ld::Atom
& atom
)
541 ld::Internal::FinalSection
* fs
= NULL
;
542 const char* sectName
= atom
.section().sectionName();
543 ld::Section::Type sectType
= atom
.section().type();
544 const ld::File
* f
= atom
.file();
545 const char* path
= (f
!= NULL
) ? f
->path() : NULL
;
546 if ( atom
.section().type() == ld::Section::typeTentativeDefs
) {
547 // tentative defintions don't have a real section name yet
548 sectType
= ld::Section::typeZeroFill
;
549 if ( _options
.mergeZeroFill() )
550 sectName
= FinalSection::_s_DATA_zerofill
.sectionName();
552 sectName
= FinalSection::_s_DATA_common
.sectionName();
554 // Support for -move_to_r._segment
555 if ( atom
.symbolTableInclusion() == ld::Atom::symbolTableIn
) {
557 //fprintf(stderr, "%s\n", atom.name());
559 if ( _options
.moveRwSymbol(atom
.name(), path
, dstSeg
, wildCardMatch
) ) {
560 if ( (sectType
!= ld::Section::typeZeroFill
)
561 && (sectType
!= ld::Section::typeUnclassified
)
562 && (sectType
!= ld::Section::typeTentativeDefs
)
563 && (sectType
!= ld::Section::typeDyldInfo
) ) {
564 if ( !wildCardMatch
)
565 warning("cannot move symbol '%s' from file %s to segment '%s' because symbol is not data (is %d)", atom
.name(), path
, dstSeg
, sectType
);
568 if ( _options
.traceSymbolLayout() )
569 printf("symbol '%s', -move_to_rw_segment mapped it to %s/%s\n", atom
.name(), dstSeg
, sectName
);
570 fs
= this->getFinalSection(dstSeg
, sectName
, sectType
);
573 if ( (fs
== NULL
) && _options
.moveRoSymbol(atom
.name(), path
, dstSeg
, wildCardMatch
) ) {
574 if ( (sectType
!= ld::Section::typeCode
)
575 && (sectType
!= ld::Section::typeUnclassified
) ) {
576 if ( !wildCardMatch
)
577 warning("cannot move symbol '%s' from file %s to segment '%s' because symbol is not code (is %d)", atom
.name(), path
, dstSeg
, sectType
);
580 if ( _options
.traceSymbolLayout() )
581 printf("symbol '%s', -move_to_ro_segment mapped it to %s/%s\n", atom
.name(), dstSeg
, sectName
);
582 fs
= this->getFinalSection(dstSeg
, sectName
, ld::Section::typeCode
);
586 // support for -rename_section and -rename_segment
588 const std::vector
<Options::SectionRename
>& sectRenames
= _options
.sectionRenames();
589 const std::vector
<Options::SegmentRename
>& segRenames
= _options
.segmentRenames();
590 for ( std::vector
<Options::SectionRename
>::const_iterator it
=sectRenames
.begin(); it
!= sectRenames
.end(); ++it
) {
591 if ( (strcmp(sectName
, it
->fromSection
) == 0) && (strcmp(atom
.section().segmentName(), it
->fromSegment
) == 0) ) {
592 if ( _options
.useDataConstSegment() && (strcmp(sectName
, "__const") == 0)
593 && (strcmp(atom
.section().segmentName(), "__DATA") == 0) && hasReferenceToWeakExternal(atom
) ) {
594 // if __DATA,__const atom has pointer to weak external symbol, don't move to __DATA_CONST
595 fs
= this->getFinalSection("__DATA", "__const_weak", sectType
);
596 if ( _options
.traceSymbolLayout() )
597 printf("symbol '%s', contains pointers to weak symbols, so mapped it to __DATA/_const_weak\n", atom
.name());
599 else if ( _options
.useDataConstSegment() && (sectType
== ld::Section::typeNonLazyPointer
) && hasReferenceToWeakExternal(atom
) ) {
600 // if __DATA,__nl_symbol_ptr atom has pointer to weak external symbol, don't move to __DATA_CONST
601 fs
= this->getFinalSection("__DATA", "__got_weak", sectType
);
602 if ( _options
.traceSymbolLayout() )
603 printf("symbol '%s', contains pointers to weak symbols, so mapped it to __DATA/__got_weak\n", atom
.name());
606 fs
= this->getFinalSection(it
->toSegment
, it
->toSection
, sectType
);
607 if ( _options
.traceSymbolLayout() )
608 printf("symbol '%s', -rename_section mapped it to %s/%s\n", atom
.name(), fs
->segmentName(), fs
->sectionName());
613 for ( std::vector
<Options::SegmentRename
>::const_iterator it
=segRenames
.begin(); it
!= segRenames
.end(); ++it
) {
614 if ( strcmp(atom
.section().segmentName(), it
->fromSegment
) == 0 ) {
615 if ( _options
.traceSymbolLayout() )
616 printf("symbol '%s', -rename_segment mapped it to %s/%s\n", atom
.name(), it
->toSegment
, sectName
);
617 fs
= this->getFinalSection(it
->toSegment
, sectName
, sectType
);
623 // if no override, use default location
625 fs
= this->getFinalSection(atom
.section());
626 if ( _options
.traceSymbolLayout() && (atom
.symbolTableInclusion() == ld::Atom::symbolTableIn
) )
627 printf("symbol '%s', use default mapping to %s/%s\n", atom
.name(), fs
->segmentName(), fs
->sectionName());
630 //fprintf(stderr, "InternalState::doAtom(%p), name=%s, sect=%s, finalsect=%p\n", &atom, atom.name(), atom.section().sectionName(), fs);
632 validateFixups(atom
);
634 if ( _atomsOrderedInSections
) {
635 // make sure this atom is placed before any trailing section$end$ atom
636 if ( (fs
->atoms
.size() > 1) && (fs
->atoms
.back()->contentType() == ld::Atom::typeSectionEnd
) ) {
637 // last atom in section$end$ atom, insert before it
638 const ld::Atom
* endAtom
= fs
->atoms
.back();
639 fs
->atoms
.pop_back();
640 fs
->atoms
.push_back(&atom
);
641 fs
->atoms
.push_back(endAtom
);
644 // not end atom, just append new atom
645 fs
->atoms
.push_back(&atom
);
650 fs
->atoms
.push_back(&atom
);
652 this->atomToSection
[&atom
] = fs
;
658 ld::Internal::FinalSection
* InternalState::getFinalSection(const char* seg
, const char* sect
, ld::Section::Type type
)
660 for (std::vector
<ld::Internal::FinalSection
*>::iterator it
=sections
.begin(); it
!= sections
.end(); ++it
) {
661 if ( (strcmp((*it
)->segmentName(),seg
) == 0) && (strcmp((*it
)->sectionName(),sect
) == 0) )
664 return this->getFinalSection(*new ld::Section(seg
, sect
, type
, false));
667 ld::Internal::FinalSection
* InternalState::getFinalSection(const ld::Section
& inputSection
)
669 const ld::Section
* baseForFinalSection
= &inputSection
;
671 // see if input section already has a FinalSection
672 SectionInToOut::iterator pos
= _sectionInToFinalMap
.find(&inputSection
);
673 if ( pos
!= _sectionInToFinalMap
.end() ) {
677 // otherwise, create a new final section
678 switch ( _options
.outputKind() ) {
679 case Options::kStaticExecutable
:
680 case Options::kDynamicExecutable
:
681 case Options::kDynamicLibrary
:
682 case Options::kDynamicBundle
:
684 case Options::kKextBundle
:
685 case Options::kPreload
:
687 // coalesce some sections
688 const ld::Section
& outSect
= FinalSection::outputSection(inputSection
, _options
.mergeZeroFill());
689 pos
= _sectionInToFinalMap
.find(&outSect
);
690 if ( pos
!= _sectionInToFinalMap
.end() ) {
691 _sectionInToFinalMap
[&inputSection
] = pos
->second
;
692 //fprintf(stderr, "_sectionInToFinalMap[%p] = %p\n", &inputSection, pos->second);
695 else if ( outSect
!= inputSection
) {
696 // new output section created, but not in map
697 baseForFinalSection
= &outSect
;
701 case Options::kObjectFile
:
702 baseForFinalSection
= &FinalSection::objectOutputSection(inputSection
, _options
);
703 pos
= _sectionInToFinalMap
.find(baseForFinalSection
);
704 if ( pos
!= _sectionInToFinalMap
.end() ) {
705 _sectionInToFinalMap
[&inputSection
] = pos
->second
;
706 //fprintf(stderr, "_sectionInToFinalMap[%p] = %p\n", &inputSection, pos->second);
712 InternalState::FinalSection
* result
= new InternalState::FinalSection(*baseForFinalSection
,
713 _sectionInToFinalMap
.size(), _options
);
714 _sectionInToFinalMap
[baseForFinalSection
] = result
;
715 //fprintf(stderr, "_sectionInToFinalMap[%p(%s)] = %p\n", baseForFinalSection, baseForFinalSection->sectionName(), result);
716 sections
.push_back(result
);
721 int InternalState::FinalSection::sectionComparer(const void* l
, const void* r
)
723 const FinalSection
* left
= *(FinalSection
**)l
;
724 const FinalSection
* right
= *(FinalSection
**)r
;
725 if ( left
->_segmentOrder
!= right
->_segmentOrder
)
726 return (left
->_segmentOrder
- right
->_segmentOrder
);
727 return (left
->_sectionOrder
- right
->_sectionOrder
);
730 void InternalState::sortSections()
732 //fprintf(stderr, "UNSORTED final sections:\n");
733 //for (std::vector<ld::Internal::FinalSection*>::iterator it = sections.begin(); it != sections.end(); ++it) {
734 // fprintf(stderr, "final section %p %s/%s\n", (*it), (*it)->segmentName(), (*it)->sectionName());
736 qsort(§ions
[0], sections
.size(), sizeof(FinalSection
*), &InternalState::FinalSection::sectionComparer
);
737 //fprintf(stderr, "SORTED final sections:\n");
738 //for (std::vector<ld::Internal::FinalSection*>::iterator it = sections.begin(); it != sections.end(); ++it) {
739 // fprintf(stderr, "final section %p %s/%s\n", (*it), (*it)->segmentName(), (*it)->sectionName());
741 assert((sections
[0]->type() == ld::Section::typeMachHeader
)
742 || ((sections
[0]->type() == ld::Section::typeFirstSection
) && (sections
[1]->type() == ld::Section::typeMachHeader
))
743 || ((sections
[0]->type() == ld::Section::typePageZero
) && (sections
[1]->type() == ld::Section::typeMachHeader
))
744 || ((sections
[0]->type() == ld::Section::typePageZero
) && (sections
[1]->type() == ld::Section::typeFirstSection
) && (sections
[2]->type() == ld::Section::typeMachHeader
)) );
749 bool InternalState::hasZeroForFileOffset(const ld::Section
* sect
)
751 switch ( sect
->type() ) {
752 case ld::Section::typeZeroFill
:
753 case ld::Section::typeTLVZeroFill
:
754 return _options
.optimizeZeroFill();
755 case ld::Section::typePageZero
:
756 case ld::Section::typeStack
:
757 case ld::Section::typeTentativeDefs
:
765 uint64_t InternalState::pageAlign(uint64_t addr
)
767 const uint64_t alignment
= _options
.segmentAlignment();
768 return ((addr
+alignment
-1) & (-alignment
));
771 uint64_t InternalState::pageAlign(uint64_t addr
, uint64_t pageSize
)
773 return ((addr
+pageSize
-1) & (-pageSize
));
776 void InternalState::setSectionSizesAndAlignments()
778 for (std::vector
<ld::Internal::FinalSection
*>::iterator sit
= sections
.begin(); sit
!= sections
.end(); ++sit
) {
779 ld::Internal::FinalSection
* sect
= *sit
;
780 if ( sect
->type() == ld::Section::typeAbsoluteSymbols
) {
781 // absolute symbols need their finalAddress() to their value
782 for (std::vector
<const ld::Atom
*>::iterator ait
= sect
->atoms
.begin(); ait
!= sect
->atoms
.end(); ++ait
) {
783 const ld::Atom
* atom
= *ait
;
784 (const_cast<ld::Atom
*>(atom
))->setSectionOffset(atom
->objectAddress());
788 uint16_t maxAlignment
= 0;
790 for (std::vector
<const ld::Atom
*>::iterator ait
= sect
->atoms
.begin(); ait
!= sect
->atoms
.end(); ++ait
) {
791 const ld::Atom
* atom
= *ait
;
792 bool pagePerAtom
= false;
793 uint32_t atomAlignmentPowerOf2
= atom
->alignment().powerOf2
;
794 uint32_t atomModulus
= atom
->alignment().modulus
;
795 if ( _options
.pageAlignDataAtoms() && ( strncmp(atom
->section().segmentName(), "__DATA", 6) == 0) ) {
796 // most objc sections cannot be padded
797 bool contiguousObjCSection
= ( strncmp(atom
->section().sectionName(), "__objc_", 7) == 0 );
798 if ( strcmp(atom
->section().sectionName(), "__objc_const") == 0 )
799 contiguousObjCSection
= false;
800 if ( strcmp(atom
->section().sectionName(), "__objc_data") == 0 )
801 contiguousObjCSection
= false;
802 switch ( atom
->section().type() ) {
803 case ld::Section::typeUnclassified
:
804 case ld::Section::typeTentativeDefs
:
805 case ld::Section::typeZeroFill
:
806 if ( contiguousObjCSection
)
809 if ( atomAlignmentPowerOf2
< 12 ) {
810 atomAlignmentPowerOf2
= 12;
818 if ( atomAlignmentPowerOf2
> maxAlignment
)
819 maxAlignment
= atomAlignmentPowerOf2
;
820 // calculate section offset for this atom
821 uint64_t alignment
= 1 << atomAlignmentPowerOf2
;
822 uint64_t currentModulus
= (offset
% alignment
);
823 uint64_t requiredModulus
= atomModulus
;
824 if ( currentModulus
!= requiredModulus
) {
825 if ( requiredModulus
> currentModulus
)
826 offset
+= requiredModulus
-currentModulus
;
828 offset
+= requiredModulus
+alignment
-currentModulus
;
830 // LINKEDIT atoms are laid out later
831 if ( sect
->type() != ld::Section::typeLinkEdit
) {
832 (const_cast<ld::Atom
*>(atom
))->setSectionOffset(offset
);
833 offset
+= atom
->size();
835 offset
= (offset
+ 4095) & (-4096); // round up to end of page
838 if ( (atom
->scope() == ld::Atom::scopeGlobal
)
839 && (atom
->definition() == ld::Atom::definitionRegular
)
840 && (atom
->combine() == ld::Atom::combineByName
)
841 && ((atom
->symbolTableInclusion() == ld::Atom::symbolTableIn
)
842 || (atom
->symbolTableInclusion() == ld::Atom::symbolTableInAndNeverStrip
)) ) {
843 this->hasWeakExternalSymbols
= true;
844 if ( _options
.warnWeakExports() )
845 warning("weak external symbol: %s", atom
->name());
849 // section alignment is that of a contained atom with the greatest alignment
850 sect
->alignment
= maxAlignment
;
851 // unless -sectalign command line option overrides
852 if ( _options
.hasCustomSectionAlignment(sect
->segmentName(), sect
->sectionName()) )
853 sect
->alignment
= _options
.customSectionAlignment(sect
->segmentName(), sect
->sectionName());
854 // each atom in __eh_frame has zero alignment to assure they pack together,
855 // but compilers usually make the CFIs pointer sized, so we want whole section
856 // to start on pointer sized boundary.
857 if ( sect
->type() == ld::Section::typeCFI
)
859 if ( sect
->type() == ld::Section::typeTLVDefs
)
860 this->hasThreadLocalVariableDefinitions
= true;
865 uint64_t InternalState::assignFileOffsets()
867 const bool log
= false;
868 const bool hiddenSectionsOccupyAddressSpace
= ((_options
.outputKind() != Options::kObjectFile
)
869 && (_options
.outputKind() != Options::kPreload
));
870 const bool segmentsArePageAligned
= (_options
.outputKind() != Options::kObjectFile
);
872 uint64_t address
= 0;
873 const char* lastSegName
= "";
874 uint64_t floatingAddressStart
= _options
.baseAddress();
875 bool haveFixedSegments
= false;
877 // mark all sections as not having an address yet
878 for (std::vector
<ld::Internal::FinalSection
*>::iterator it
= sections
.begin(); it
!= sections
.end(); ++it
) {
879 ld::Internal::FinalSection
* sect
= *it
;
880 sect
->alignmentPaddingBytes
= 0;
881 sect
->address
= ULLONG_MAX
;
884 // first pass, assign addresses to sections in segments with fixed start addresses
885 if ( log
) fprintf(stderr
, "Fixed address segments:\n");
886 for (std::vector
<ld::Internal::FinalSection
*>::iterator it
= sections
.begin(); it
!= sections
.end(); ++it
) {
887 ld::Internal::FinalSection
* sect
= *it
;
888 if ( ! _options
.hasCustomSegmentAddress(sect
->segmentName()) )
890 haveFixedSegments
= true;
891 if ( segmentsArePageAligned
) {
892 if ( strcmp(lastSegName
, sect
->segmentName()) != 0 ) {
893 address
= _options
.customSegmentAddress(sect
->segmentName());
894 lastSegName
= sect
->segmentName();
897 // adjust section address based on alignment
898 uint64_t unalignedAddress
= address
;
899 uint64_t alignment
= (1 << sect
->alignment
);
900 address
= ( (unalignedAddress
+alignment
-1) & (-alignment
) );
902 // update section info
903 sect
->address
= address
;
904 sect
->alignmentPaddingBytes
= (address
- unalignedAddress
);
907 if ( ((address
+ sect
->size
) > _options
.maxAddress()) && (_options
.outputKind() != Options::kObjectFile
)
908 && (_options
.outputKind() != Options::kStaticExecutable
) )
909 throwf("section %s (address=0x%08llX, size=%llu) would make the output executable exceed available address range",
910 sect
->sectionName(), address
, sect
->size
);
912 if ( log
) fprintf(stderr
, " address=0x%08llX, hidden=%d, alignment=%02d, section=%s,%s\n",
913 sect
->address
, sect
->isSectionHidden(), sect
->alignment
, sect
->segmentName(), sect
->sectionName());
914 // update running totals
915 if ( !sect
->isSectionHidden() || hiddenSectionsOccupyAddressSpace
)
916 address
+= sect
->size
;
918 // if TEXT segment address is fixed, then flow other segments after it
919 if ( strcmp(sect
->segmentName(), "__TEXT") == 0 ) {
920 floatingAddressStart
= address
;
924 // second pass, assign section addresses to sections in segments that are ordered after a segment with a fixed address
925 if ( haveFixedSegments
&& !_options
.segmentOrder().empty() ) {
926 if ( log
) fprintf(stderr
, "After Fixed address segments:\n");
928 ld::Internal::FinalSection
* lastSect
= NULL
;
929 for (std::vector
<ld::Internal::FinalSection
*>::iterator it
= sections
.begin(); it
!= sections
.end(); ++it
) {
930 ld::Internal::FinalSection
* sect
= *it
;
931 if ( (sect
->address
== ULLONG_MAX
) && _options
.segmentOrderAfterFixedAddressSegment(sect
->segmentName()) ) {
932 address
= lastSect
->address
+ lastSect
->size
;
933 if ( (strcmp(lastSegName
, sect
->segmentName()) != 0) && segmentsArePageAligned
) {
934 // round up size of last segment
935 address
= pageAlign(address
, _options
.segPageSize(lastSegName
));
937 // adjust section address based on alignment
938 uint64_t unalignedAddress
= address
;
939 uint64_t alignment
= (1 << sect
->alignment
);
940 address
= ( (unalignedAddress
+alignment
-1) & (-alignment
) );
941 sect
->alignmentPaddingBytes
= (address
- unalignedAddress
);
942 sect
->address
= address
;
943 if ( log
) fprintf(stderr
, " address=0x%08llX, hidden=%d, alignment=%02d, section=%s,%s\n",
944 sect
->address
, sect
->isSectionHidden(), sect
->alignment
, sect
->segmentName(), sect
->sectionName());
945 // update running totals
946 if ( !sect
->isSectionHidden() || hiddenSectionsOccupyAddressSpace
)
947 address
+= sect
->size
;
949 lastSegName
= sect
->segmentName();
954 // last pass, assign addresses to remaining sections
955 address
= floatingAddressStart
;
957 ld::Internal::FinalSection
* overlappingFixedSection
= NULL
;
958 ld::Internal::FinalSection
* overlappingFlowSection
= NULL
;
959 if ( log
) fprintf(stderr
, "Regular layout segments:\n");
960 for (std::vector
<ld::Internal::FinalSection
*>::iterator it
= sections
.begin(); it
!= sections
.end(); ++it
) {
961 ld::Internal::FinalSection
* sect
= *it
;
962 if ( sect
->address
!= ULLONG_MAX
)
964 if ( (_options
.outputKind() == Options::kPreload
) && (sect
->type() == ld::Section::typeMachHeader
) ) {
965 sect
->alignmentPaddingBytes
= 0;
968 if ( segmentsArePageAligned
) {
969 if ( strcmp(lastSegName
, sect
->segmentName()) != 0 ) {
970 // round up size of last segment if needed
971 if ( *lastSegName
!= '\0' ) {
972 address
= pageAlign(address
, _options
.segPageSize(lastSegName
));
974 // set segment address based on end of last segment
975 address
= pageAlign(address
);
976 lastSegName
= sect
->segmentName();
980 // adjust section address based on alignment
981 uint64_t unalignedAddress
= address
;
982 uint64_t alignment
= (1 << sect
->alignment
);
983 address
= ( (unalignedAddress
+alignment
-1) & (-alignment
) );
985 // update section info
986 sect
->address
= address
;
987 sect
->alignmentPaddingBytes
= (address
- unalignedAddress
);
990 if ( ((address
+ sect
->size
) > _options
.maxAddress()) && (_options
.outputKind() != Options::kObjectFile
)
991 && (_options
.outputKind() != Options::kStaticExecutable
) )
992 throwf("section %s (address=0x%08llX, size=%llu) would make the output executable exceed available address range",
993 sect
->sectionName(), address
, sect
->size
);
995 // sanity check it does not overlap a fixed address segment
996 for (std::vector
<ld::Internal::FinalSection
*>::iterator sit
= sections
.begin(); sit
!= sections
.end(); ++sit
) {
997 ld::Internal::FinalSection
* otherSect
= *sit
;
998 if ( ! _options
.hasCustomSegmentAddress(otherSect
->segmentName()) )
1000 if ( otherSect
->size
== 0 )
1002 if ( sect
->size
== 0 )
1004 if ( sect
->address
> otherSect
->address
) {
1005 if ( (otherSect
->address
+otherSect
->size
) > sect
->address
) {
1006 overlappingFixedSection
= otherSect
;
1007 overlappingFlowSection
= sect
;
1011 if ( (sect
->address
+sect
->size
) > otherSect
->address
) {
1012 overlappingFixedSection
= otherSect
;
1013 overlappingFlowSection
= sect
;
1018 if ( log
) fprintf(stderr
, " address=0x%08llX, size=0x%08llX, hidden=%d, alignment=%02d, padBytes=%d, section=%s,%s\n",
1019 sect
->address
, sect
->size
, sect
->isSectionHidden(), sect
->alignment
, sect
->alignmentPaddingBytes
,
1020 sect
->segmentName(), sect
->sectionName());
1021 // update running totals
1022 if ( !sect
->isSectionHidden() || hiddenSectionsOccupyAddressSpace
)
1023 address
+= sect
->size
;
1025 if ( overlappingFixedSection
!= NULL
) {
1026 fprintf(stderr
, "Section layout:\n");
1027 for (std::vector
<ld::Internal::FinalSection
*>::iterator it
= sections
.begin(); it
!= sections
.end(); ++it
) {
1028 ld::Internal::FinalSection
* sect
= *it
;
1029 //if ( sect->isSectionHidden() )
1031 fprintf(stderr
, " address:0x%08llX, alignment:2^%d, size:0x%08llX, padBytes:%d, section:%s/%s\n",
1032 sect
->address
, sect
->alignment
, sect
->size
, sect
->alignmentPaddingBytes
,
1033 sect
->segmentName(), sect
->sectionName());
1036 throwf("Section (%s/%s) overlaps fixed address section (%s/%s)",
1037 overlappingFlowSection
->segmentName(), overlappingFlowSection
->sectionName(),
1038 overlappingFixedSection
->segmentName(), overlappingFixedSection
->sectionName());
1042 // third pass, assign section file offsets
1043 uint64_t fileOffset
= 0;
1045 if ( log
) fprintf(stderr
, "All segments with file offsets:\n");
1046 for (std::vector
<ld::Internal::FinalSection
*>::iterator it
= sections
.begin(); it
!= sections
.end(); ++it
) {
1047 ld::Internal::FinalSection
* sect
= *it
;
1048 if ( hasZeroForFileOffset(sect
) ) {
1049 // fileoff of zerofill sections is moot, but historically it is set to zero
1050 sect
->fileOffset
= 0;
1052 // <rdar://problem/10445047> align file offset with address layout
1053 fileOffset
+= sect
->alignmentPaddingBytes
;
1056 // page align file offset at start of each segment
1057 if ( segmentsArePageAligned
&& (*lastSegName
!= '\0') && (strcmp(lastSegName
, sect
->segmentName()) != 0) ) {
1058 fileOffset
= pageAlign(fileOffset
, _options
.segPageSize(lastSegName
));
1060 lastSegName
= sect
->segmentName();
1062 // align file offset with address layout
1063 fileOffset
+= sect
->alignmentPaddingBytes
;
1065 // update section info
1066 sect
->fileOffset
= fileOffset
;
1068 // update running total
1069 fileOffset
+= sect
->size
;
1072 if ( log
) fprintf(stderr
, " fileoffset=0x%08llX, address=0x%08llX, hidden=%d, size=%lld, alignment=%02d, section=%s,%s\n",
1073 sect
->fileOffset
, sect
->address
, sect
->isSectionHidden(), sect
->size
, sect
->alignment
,
1074 sect
->segmentName(), sect
->sectionName());
1078 // for encrypted iPhoneOS apps
1079 if ( _options
.makeEncryptable() ) {
1080 // remember end of __TEXT for later use by load command
1081 for (std::vector
<ld::Internal::FinalSection
*>::iterator it
= state
.sections
.begin(); it
!= state
.sections
.end(); ++it
) {
1082 ld::Internal::FinalSection
* sect
= *it
;
1083 if ( strcmp(sect
->segmentName(), "__TEXT") == 0 ) {
1084 _encryptedTEXTendOffset
= pageAlign(sect
->fileOffset
+ sect
->size
);
1090 // return total file size
1094 static char* commatize(uint64_t in
, char* out
)
1098 sprintf(rawNum
, "%llu", in
);
1099 const int rawNumLen
= strlen(rawNum
);
1100 for(int i
=0; i
< rawNumLen
-1; ++i
) {
1102 if ( ((rawNumLen
-i
) % 3) == 1 )
1105 *out
++ = rawNum
[rawNumLen
-1];
1110 static void printTime(const char* msg
, uint64_t partTime
, uint64_t totalTime
)
1112 static uint64_t sUnitsPerSecond
= 0;
1113 if ( sUnitsPerSecond
== 0 ) {
1114 struct mach_timebase_info timeBaseInfo
;
1115 if ( mach_timebase_info(&timeBaseInfo
) != KERN_SUCCESS
)
1117 sUnitsPerSecond
= 1000000000ULL * timeBaseInfo
.denom
/ timeBaseInfo
.numer
;
1119 if ( partTime
< sUnitsPerSecond
) {
1120 uint32_t milliSecondsTimeTen
= (partTime
*10000)/sUnitsPerSecond
;
1121 uint32_t milliSeconds
= milliSecondsTimeTen
/10;
1122 uint32_t percentTimesTen
= (partTime
*1000)/totalTime
;
1123 uint32_t percent
= percentTimesTen
/10;
1124 fprintf(stderr
, "%24s: % 4d.%d milliseconds (% 4d.%d%%)\n", msg
, milliSeconds
, milliSecondsTimeTen
-milliSeconds
*10, percent
, percentTimesTen
-percent
*10);
1127 uint32_t secondsTimeTen
= (partTime
*10)/sUnitsPerSecond
;
1128 uint32_t seconds
= secondsTimeTen
/10;
1129 uint32_t percentTimesTen
= (partTime
*1000)/totalTime
;
1130 uint32_t percent
= percentTimesTen
/10;
1131 fprintf(stderr
, "%24s: % 4d.%d seconds (% 4d.%d%%)\n", msg
, seconds
, secondsTimeTen
-seconds
*10, percent
, percentTimesTen
-percent
*10);
1136 static void getVMInfo(vm_statistics_data_t
& info
)
1138 mach_msg_type_number_t count
= sizeof(vm_statistics_data_t
) / sizeof(natural_t
);
1139 kern_return_t error
= host_statistics(mach_host_self(), HOST_VM_INFO
,
1140 (host_info_t
)&info
, &count
);
1141 if (error
!= KERN_SUCCESS
) {
1142 bzero(&info
, sizeof(vm_statistics_data_t
));
1148 static const char* sOverridePathlibLTO
= NULL
;
1151 // This is magic glue that overrides the default behaviour
1152 // of lazydylib1.o which is used to lazily load libLTO.dylib.
1154 extern "C" const char* dyld_lazy_dylib_path_fix(const char* path
);
1155 const char* dyld_lazy_dylib_path_fix(const char* path
)
1157 if ( sOverridePathlibLTO
!= NULL
)
1158 return sOverridePathlibLTO
;
1165 int main(int argc
, const char* argv
[])
1167 const char* archName
= NULL
;
1168 bool showArch
= false;
1169 bool archInferred
= false;
1171 PerformanceStatistics statistics
;
1172 statistics
.startTool
= mach_absolute_time();
1174 // create object to track command line arguments
1175 Options
options(argc
, argv
);
1176 InternalState
state(options
);
1178 // allow libLTO to be overridden by command line -lto_library
1179 sOverridePathlibLTO
= options
.overridePathlibLTO();
1182 if ( options
.printStatistics() )
1183 getVMInfo(statistics
.vmStart
);
1185 // update strings for error messages
1186 showArch
= options
.printArchPrefix();
1187 archName
= options
.architectureName();
1188 archInferred
= (options
.architecture() == 0);
1190 // open and parse input files
1191 statistics
.startInputFileProcessing
= mach_absolute_time();
1192 ld::tool::InputFiles
inputFiles(options
, &archName
);
1194 // load and resolve all references
1195 statistics
.startResolver
= mach_absolute_time();
1196 ld::tool::Resolver
resolver(options
, inputFiles
, state
);
1200 statistics
.startDylibs
= mach_absolute_time();
1201 inputFiles
.dylibs(state
);
1203 // do initial section sorting so passes have rough idea of the layout
1204 state
.sortSections();
1207 statistics
.startPasses
= mach_absolute_time();
1208 ld::passes::objc::doPass(options
, state
);
1209 ld::passes::stubs::doPass(options
, state
);
1210 ld::passes::huge::doPass(options
, state
);
1211 ld::passes::got::doPass(options
, state
);
1212 ld::passes::tlvp::doPass(options
, state
);
1213 ld::passes::dylibs::doPass(options
, state
); // must be after stubs and GOT passes
1214 ld::passes::order::doPass(options
, state
);
1215 state
.markAtomsOrdered();
1216 ld::passes::branch_shim::doPass(options
, state
); // must be after stubs
1217 ld::passes::branch_island::doPass(options
, state
); // must be after stubs and order pass
1218 ld::passes::dtrace::doPass(options
, state
);
1219 ld::passes::compact_unwind::doPass(options
, state
); // must be after order pass
1220 ld::passes::bitcode_bundle::doPass(options
, state
); // must be after dylib
1222 // sort final sections
1223 state
.sortSections();
1225 // write output file
1226 statistics
.startOutput
= mach_absolute_time();
1227 ld::tool::OutputFile
out(options
);
1229 statistics
.startDone
= mach_absolute_time();
1232 //mach_o::relocatable::printCounts();
1233 if ( options
.printStatistics() ) {
1234 getVMInfo(statistics
.vmEnd
);
1235 uint64_t totalTime
= statistics
.startDone
- statistics
.startTool
;
1236 printTime("ld total time", totalTime
, totalTime
);
1237 printTime(" option parsing time", statistics
.startInputFileProcessing
- statistics
.startTool
, totalTime
);
1238 printTime(" object file processing", statistics
.startResolver
- statistics
.startInputFileProcessing
,totalTime
);
1239 printTime(" resolve symbols", statistics
.startDylibs
- statistics
.startResolver
, totalTime
);
1240 printTime(" build atom list", statistics
.startPasses
- statistics
.startDylibs
, totalTime
);
1241 printTime(" passess", statistics
.startOutput
- statistics
.startPasses
, totalTime
);
1242 printTime(" write output", statistics
.startDone
- statistics
.startOutput
, totalTime
);
1243 fprintf(stderr
, "pageins=%u, pageouts=%u, faults=%u\n",
1244 statistics
.vmEnd
.pageins
-statistics
.vmStart
.pageins
,
1245 statistics
.vmEnd
.pageouts
-statistics
.vmStart
.pageouts
,
1246 statistics
.vmEnd
.faults
-statistics
.vmStart
.faults
);
1248 fprintf(stderr
, "processed %3u object files, totaling %15s bytes\n", inputFiles
._totalObjectLoaded
, commatize(inputFiles
._totalObjectSize
, temp
));
1249 fprintf(stderr
, "processed %3u archive files, totaling %15s bytes\n", inputFiles
._totalArchivesLoaded
, commatize(inputFiles
._totalArchiveSize
, temp
));
1250 fprintf(stderr
, "processed %3u dylib files\n", inputFiles
._totalDylibsLoaded
);
1251 fprintf(stderr
, "wrote output file totaling %15s bytes\n", commatize(out
.fileSize(), temp
));
1253 // <rdar://problem/6780050> Would like linker warning to be build error.
1254 if ( options
.errorBecauseOfWarnings() ) {
1255 fprintf(stderr
, "ld: fatal warning(s) induced error (-fatal_warnings)\n");
1259 catch (const char* msg
) {
1261 fprintf(stderr
, "ld: %s for inferred architecture %s\n", msg
, archName
);
1262 else if ( showArch
)
1263 fprintf(stderr
, "ld: %s for architecture %s\n", msg
, archName
);
1265 fprintf(stderr
, "ld: %s\n", msg
);
1274 // implement assert() function to print out a backtrace before aborting
1275 void __assert_rtn(const char* func
, const char* file
, int line
, const char* failedexpr
)
1277 Snapshot
*snapshot
= Snapshot::globalSnapshot
;
1279 snapshot
->setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
1280 snapshot
->createSnapshot();
1281 snapshot
->recordAssertionMessage("Assertion failed: (%s), function %s, file %s, line %d.\n", failedexpr
, func
, file
, line
);
1283 void* callStack
[128];
1284 int depth
= ::backtrace(callStack
, 128);
1285 char* buffer
= (char*)malloc(1024);
1286 for(int i
=0; i
< depth
-1; ++i
) {
1288 dladdr(callStack
[i
], &info
);
1289 const char* symboName
= info
.dli_sname
;
1290 if ( (symboName
!= NULL
) && (strncmp(symboName
, "_Z", 2) == 0) ) {
1291 size_t bufLen
= 1024;
1293 char* unmangled
= abi::__cxa_demangle(symboName
, buffer
, &bufLen
, &result
);
1294 if ( unmangled
!= NULL
)
1295 symboName
= unmangled
;
1297 long offset
= (uintptr_t)callStack
[i
] - (uintptr_t)info
.dli_saddr
;
1298 fprintf(stderr
, "%d %p %s + %ld\n", i
, callStack
[i
], symboName
, offset
);
1299 snapshot
->recordAssertionMessage("%d %p %s + %ld\n", i
, callStack
[i
], symboName
, offset
);
1301 fprintf(stderr
, "A linker snapshot was created at:\n\t%s\n", snapshot
->rootDir());
1302 fprintf(stderr
, "ld: Assertion failed: (%s), function %s, file %s, line %d.\n", failedexpr
, func
, file
, line
);