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"
83 #include "parsers/archive_file.h"
84 #include "parsers/macho_relocatable_file.h"
85 #include "parsers/macho_dylib_file.h"
86 #include "parsers/lto_file.h"
87 #include "parsers/opaque_section_file.h"
90 struct PerformanceStatistics
{
92 uint64_t startInputFileProcessing
;
93 uint64_t startResolver
;
98 vm_statistics_data_t vmStart
;
99 vm_statistics_data_t vmEnd
;
106 class InternalState
: public ld::Internal
109 InternalState(const Options
& opts
) : _options(opts
), _atomsOrderedInSections(false) { }
110 virtual ld::Internal::FinalSection
* addAtom(const ld::Atom
& atom
);
111 virtual ld::Internal::FinalSection
* getFinalSection(const ld::Section
&);
114 void markAtomsOrdered() { _atomsOrderedInSections
= true; }
115 virtual ~InternalState() {}
118 class FinalSection
: public ld::Internal::FinalSection
121 FinalSection(const ld::Section
& sect
, uint32_t sectionsSeen
, bool objFile
);
122 static int sectionComparer(const void* l
, const void* r
);
123 static const ld::Section
& outputSection(const ld::Section
& sect
, bool mergeZeroFill
);
124 static const ld::Section
& objectOutputSection(const ld::Section
& sect
, bool makeTentativeDefsReal
);
126 friend class InternalState
;
127 static uint32_t sectionOrder(const ld::Section
& sect
, uint32_t sectionsSeen
);
128 static uint32_t segmentOrder(const ld::Section
& sect
, bool objFile
);
129 uint32_t _segmentOrder
;
130 uint32_t _sectionOrder
;
132 static std::vector
<const char*> _s_segmentsSeen
;
133 static ld::Section _s_DATA_data
;
134 static ld::Section _s_DATA_const
;
135 static ld::Section _s_TEXT_text
;
136 static ld::Section _s_TEXT_const
;
137 static ld::Section _s_DATA_nl_symbol_ptr
;
138 static ld::Section _s_DATA_common
;
139 static ld::Section _s_DATA_zerofill
;
144 size_t operator()(const ld::Section
*) const;
146 struct SectionEquals
{
147 bool operator()(const ld::Section
* left
, const ld::Section
* right
) const;
149 typedef std::unordered_map
<const ld::Section
*, FinalSection
*, SectionHash
, SectionEquals
> SectionInToOut
;
152 SectionInToOut _sectionInToFinalMap
;
153 const Options
& _options
;
154 bool _atomsOrderedInSections
;
157 ld::Section
InternalState::FinalSection::_s_DATA_data( "__DATA", "__data", ld::Section::typeUnclassified
);
158 ld::Section
InternalState::FinalSection::_s_DATA_const("__DATA", "__const", ld::Section::typeUnclassified
);
159 ld::Section
InternalState::FinalSection::_s_TEXT_text( "__TEXT", "__text", ld::Section::typeCode
);
160 ld::Section
InternalState::FinalSection::_s_TEXT_const("__TEXT", "__const", ld::Section::typeUnclassified
);
161 ld::Section
InternalState::FinalSection::_s_DATA_nl_symbol_ptr("__DATA", "__nl_symbol_ptr", ld::Section::typeNonLazyPointer
);
162 ld::Section
InternalState::FinalSection::_s_DATA_common("__DATA", "__common", ld::Section::typeZeroFill
);
163 ld::Section
InternalState::FinalSection::_s_DATA_zerofill("__DATA", "__zerofill", ld::Section::typeZeroFill
);
164 std::vector
<const char*> InternalState::FinalSection::_s_segmentsSeen
;
167 size_t InternalState::SectionHash::operator()(const ld::Section
* sect
) const
170 ld::CStringHash temp
;
171 hash
+= temp
.operator()(sect
->segmentName());
172 hash
+= temp
.operator()(sect
->sectionName());
176 bool InternalState::SectionEquals::operator()(const ld::Section
* left
, const ld::Section
* right
) const
178 return (*left
== *right
);
182 InternalState::FinalSection::FinalSection(const ld::Section
& sect
, uint32_t sectionsSeen
, bool objFile
)
183 : ld::Internal::FinalSection(sect
),
184 _segmentOrder(segmentOrder(sect
, objFile
)),
185 _sectionOrder(sectionOrder(sect
, sectionsSeen
))
187 //fprintf(stderr, "FinalSection(%s, %s) _segmentOrder=%d, _sectionOrder=%d\n",
188 // this->segmentName(), this->sectionName(), _segmentOrder, _sectionOrder);
191 const ld::Section
& InternalState::FinalSection::outputSection(const ld::Section
& sect
, bool mergeZeroFill
)
193 // merge sections in final linked image
194 switch ( sect
.type() ) {
195 case ld::Section::typeLiteral4
:
196 case ld::Section::typeLiteral8
:
197 case ld::Section::typeLiteral16
:
198 return _s_TEXT_const
;
199 case ld::Section::typeUnclassified
:
200 if ( strcmp(sect
.segmentName(), "__DATA") == 0 ) {
201 if ( strcmp(sect
.sectionName(), "__datacoal_nt") == 0 )
203 if ( strcmp(sect
.sectionName(), "__const_coal") == 0 )
204 return _s_DATA_const
;
206 else if ( strcmp(sect
.segmentName(), "__TEXT") == 0 ) {
207 if ( strcmp(sect
.sectionName(), "__const_coal") == 0 )
208 return _s_TEXT_const
;
211 case ld::Section::typeZeroFill
:
213 return _s_DATA_zerofill
;
215 case ld::Section::typeCode
:
216 if ( strcmp(sect
.segmentName(), "__TEXT") == 0 ) {
217 if ( strcmp(sect
.sectionName(), "__textcoal_nt") == 0 )
219 else if ( strcmp(sect
.sectionName(), "__StaticInit") == 0 )
223 case ld::Section::typeNonLazyPointer
:
224 if ( strcmp(sect
.segmentName(), "__DATA") == 0 ) {
225 if ( strcmp(sect
.sectionName(), "__nl_symbol_ptr") == 0 )
226 return _s_DATA_nl_symbol_ptr
;
228 else if ( strcmp(sect
.segmentName(), "__IMPORT") == 0 ) {
229 if ( strcmp(sect
.sectionName(), "__pointers") == 0 )
230 return _s_DATA_nl_symbol_ptr
;
233 case ld::Section::typeTentativeDefs
:
235 return _s_DATA_zerofill
;
237 return _s_DATA_common
;
246 const ld::Section
& InternalState::FinalSection::objectOutputSection(const ld::Section
& sect
, bool makeTentativeDefsReal
)
248 // in -r mode the only section that ever changes is __tenative -> __common with -d option
249 if ( (sect
.type() == ld::Section::typeTentativeDefs
) && makeTentativeDefsReal
)
250 return _s_DATA_common
;
254 uint32_t InternalState::FinalSection::segmentOrder(const ld::Section
& sect
, bool objFile
)
256 if ( strcmp(sect
.segmentName(), "__PAGEZERO") == 0 )
258 if ( strcmp(sect
.segmentName(), "__HEADER") == 0 ) // only used with -preload
260 if ( strcmp(sect
.segmentName(), "__TEXT") == 0 )
262 // in -r mode, want __DATA last so zerofill sections are at end
263 if ( strcmp(sect
.segmentName(), "__DATA") == 0 )
264 return (objFile
? 5 : 2);
265 if ( strcmp(sect
.segmentName(), "__OBJC") == 0 )
267 if ( strcmp(sect
.segmentName(), "__IMPORT") == 0 )
270 // layout non-standard segments in order seen (+10 to shift beyond standard segments)
271 for (uint32_t i
=0; i
< _s_segmentsSeen
.size(); ++i
) {
272 if ( strcmp(_s_segmentsSeen
[i
], sect
.segmentName()) == 0 )
275 _s_segmentsSeen
.push_back(sect
.segmentName());
276 return _s_segmentsSeen
.size()-1+10;
279 uint32_t InternalState::FinalSection::sectionOrder(const ld::Section
& sect
, uint32_t sectionsSeen
)
281 if ( sect
.type() == ld::Section::typeFirstSection
)
283 if ( sect
.type() == ld::Section::typeMachHeader
)
285 if ( sect
.type() == ld::Section::typeLastSection
)
287 if ( strcmp(sect
.segmentName(), "__TEXT") == 0 ) {
288 switch ( sect
.type() ) {
289 case ld::Section::typeCode
:
290 // <rdar://problem/8346444> make __text always be first "code" section
291 if ( strcmp(sect
.sectionName(), "__text") == 0 )
295 case ld::Section::typeStub
:
297 case ld::Section::typeStubHelper
:
299 case ld::Section::typeLSDA
:
301 case ld::Section::typeUnwindInfo
:
303 case ld::Section::typeCFI
:
305 case ld::Section::typeStubClose
:
308 return sectionsSeen
+20;
311 else if ( strcmp(sect
.segmentName(), "__DATA") == 0 ) {
312 switch ( sect
.type() ) {
313 case ld::Section::typeLazyPointerClose
:
315 case ld::Section::typeDyldInfo
:
317 case ld::Section::typeNonLazyPointer
:
319 case ld::Section::typeLazyPointer
:
321 case ld::Section::typeInitializerPointers
:
323 case ld::Section::typeTerminatorPointers
:
325 case ld::Section::typeTLVInitialValues
:
326 return INT_MAX
-4; // need TLV zero-fill to follow TLV init values
327 case ld::Section::typeTLVZeroFill
:
329 case ld::Section::typeZeroFill
:
330 // make sure __huge is always last zerofill section
331 if ( strcmp(sect
.sectionName(), "__huge") == 0 )
336 // <rdar://problem/14348664> __DATA,__const section should be near __mod_init_func not __data
337 if ( strcmp(sect
.sectionName(), "__const") == 0 )
339 // <rdar://problem/7435296> Reorder sections to reduce page faults in object files
340 else if ( strcmp(sect
.sectionName(), "__objc_classlist") == 0 )
342 else if ( strcmp(sect
.sectionName(), "__objc_nlclslist") == 0 )
344 else if ( strcmp(sect
.sectionName(), "__objc_catlist") == 0 )
346 else if ( strcmp(sect
.sectionName(), "__objc_protolist") == 0 )
348 else if ( strcmp(sect
.sectionName(), "__objc_imageinfo") == 0 )
350 else if ( strcmp(sect
.sectionName(), "__objc_const") == 0 )
352 else if ( strcmp(sect
.sectionName(), "__objc_selrefs") == 0 )
354 else if ( strcmp(sect
.sectionName(), "__objc_msgrefs") == 0 )
356 else if ( strcmp(sect
.sectionName(), "__objc_protorefs") == 0 )
358 else if ( strcmp(sect
.sectionName(), "__objc_classrefs") == 0 )
360 else if ( strcmp(sect
.sectionName(), "__objc_superrefs") == 0 )
362 else if ( strcmp(sect
.sectionName(), "__objc_data") == 0 )
365 return sectionsSeen
+40;
368 // make sure zerofill in any other section is at end of segment
369 if ( sect
.type() == ld::Section::typeZeroFill
)
371 return sectionsSeen
+20;
375 static void validateFixups(const ld::Atom
& atom
)
377 //fprintf(stderr, "validateFixups %s\n", atom.name());
378 bool lastWasClusterEnd
= true;
379 ld::Fixup::Cluster lastClusterSize
= ld::Fixup::k1of1
;
380 uint32_t curClusterOffsetInAtom
= 0;
381 for (ld::Fixup::iterator fit
=atom
.fixupsBegin(); fit
!= atom
.fixupsEnd(); ++fit
) {
382 //fprintf(stderr, " fixup offset=%d, cluster=%d\n", fit->offsetInAtom, fit->clusterSize);
383 assert((fit
->offsetInAtom
<= atom
.size()) || (fit
->offsetInAtom
== 0));
384 if ( fit
->firstInCluster() ) {
385 assert(lastWasClusterEnd
);
386 curClusterOffsetInAtom
= fit
->offsetInAtom
;
387 lastWasClusterEnd
= (fit
->clusterSize
== ld::Fixup::k1of1
);
390 assert(!lastWasClusterEnd
);
391 assert(fit
->offsetInAtom
== curClusterOffsetInAtom
);
392 switch ((ld::Fixup::Cluster
)fit
->clusterSize
) {
393 case ld::Fixup::k1of1
:
394 case ld::Fixup::k1of2
:
395 case ld::Fixup::k1of3
:
396 case ld::Fixup::k1of4
:
397 case ld::Fixup::k1of5
:
398 lastWasClusterEnd
= false;
400 case ld::Fixup::k2of2
:
401 assert(lastClusterSize
= ld::Fixup::k1of2
);
402 lastWasClusterEnd
= true;
404 case ld::Fixup::k2of3
:
405 assert(lastClusterSize
= ld::Fixup::k1of3
);
406 lastWasClusterEnd
= false;
408 case ld::Fixup::k2of4
:
409 assert(lastClusterSize
= ld::Fixup::k1of4
);
410 lastWasClusterEnd
= false;
412 case ld::Fixup::k2of5
:
413 assert(lastClusterSize
= ld::Fixup::k1of5
);
414 lastWasClusterEnd
= false;
416 case ld::Fixup::k3of3
:
417 assert(lastClusterSize
= ld::Fixup::k2of3
);
418 lastWasClusterEnd
= true;
420 case ld::Fixup::k3of4
:
421 assert(lastClusterSize
= ld::Fixup::k2of4
);
422 lastWasClusterEnd
= false;
424 case ld::Fixup::k3of5
:
425 assert(lastClusterSize
= ld::Fixup::k2of5
);
426 lastWasClusterEnd
= false;
428 case ld::Fixup::k4of4
:
429 assert(lastClusterSize
= ld::Fixup::k3of4
);
430 lastWasClusterEnd
= true;
432 case ld::Fixup::k4of5
:
433 assert(lastClusterSize
= ld::Fixup::k3of5
);
434 lastWasClusterEnd
= false;
436 case ld::Fixup::k5of5
:
437 assert(lastClusterSize
= ld::Fixup::k4of5
);
438 lastWasClusterEnd
= true;
442 lastClusterSize
= fit
->clusterSize
;
443 if ( fit
->binding
== ld::Fixup::bindingDirectlyBound
) {
444 assert(fit
->u
.target
!= NULL
);
447 switch (lastClusterSize
) {
448 case ld::Fixup::k1of1
:
449 case ld::Fixup::k2of2
:
450 case ld::Fixup::k3of3
:
451 case ld::Fixup::k4of4
:
452 case ld::Fixup::k5of5
:
455 assert(0 && "last fixup was not end of cluster");
461 ld::Internal::FinalSection
* InternalState::addAtom(const ld::Atom
& atom
)
463 ld::Internal::FinalSection
* fs
= this->getFinalSection(atom
.section());
464 //fprintf(stderr, "InternalState::doAtom(%p), name=%s, sect=%s, finalsect=%p\n", &atom, atom.name(), atom.section().sectionName(), fs);
466 validateFixups(atom
);
468 if ( _atomsOrderedInSections
) {
469 // make sure this atom is placed before any trailing section$end$ atom
470 if ( (fs
->atoms
.size() > 1) && (fs
->atoms
.back()->contentType() == ld::Atom::typeSectionEnd
) ) {
471 // last atom in section$end$ atom, insert before it
472 const ld::Atom
* endAtom
= fs
->atoms
.back();
473 fs
->atoms
.pop_back();
474 fs
->atoms
.push_back(&atom
);
475 fs
->atoms
.push_back(endAtom
);
478 // not end atom, just append new atom
479 fs
->atoms
.push_back(&atom
);
484 fs
->atoms
.push_back(&atom
);
489 ld::Internal::FinalSection
* InternalState::getFinalSection(const ld::Section
& inputSection
)
491 const ld::Section
* baseForFinalSection
= &inputSection
;
493 // see if input section already has a FinalSection
494 SectionInToOut::iterator pos
= _sectionInToFinalMap
.find(&inputSection
);
495 if ( pos
!= _sectionInToFinalMap
.end() ) {
499 // otherwise, create a new final section
500 bool objFile
= false;
501 switch ( _options
.outputKind() ) {
502 case Options::kStaticExecutable
:
503 case Options::kDynamicExecutable
:
504 case Options::kDynamicLibrary
:
505 case Options::kDynamicBundle
:
507 case Options::kKextBundle
:
508 case Options::kPreload
:
510 // coalesce some sections
511 const ld::Section
& outSect
= FinalSection::outputSection(inputSection
, _options
.mergeZeroFill());
512 pos
= _sectionInToFinalMap
.find(&outSect
);
513 if ( pos
!= _sectionInToFinalMap
.end() ) {
514 _sectionInToFinalMap
[&inputSection
] = pos
->second
;
515 //fprintf(stderr, "_sectionInToFinalMap[%p] = %p\n", &inputSection, pos->second);
518 else if ( outSect
!= inputSection
) {
519 // new output section created, but not in map
520 baseForFinalSection
= &outSect
;
524 case Options::kObjectFile
:
525 baseForFinalSection
= &FinalSection::objectOutputSection(inputSection
, _options
.makeTentativeDefinitionsReal());
526 pos
= _sectionInToFinalMap
.find(baseForFinalSection
);
527 if ( pos
!= _sectionInToFinalMap
.end() ) {
528 _sectionInToFinalMap
[&inputSection
] = pos
->second
;
529 //fprintf(stderr, "_sectionInToFinalMap[%p] = %p\n", &inputSection, pos->second);
536 InternalState::FinalSection
* result
= new InternalState::FinalSection(*baseForFinalSection
,
537 _sectionInToFinalMap
.size(), objFile
);
538 _sectionInToFinalMap
[baseForFinalSection
] = result
;
539 //fprintf(stderr, "_sectionInToFinalMap[%p] = %p\n", baseForFinalSection, result);
540 sections
.push_back(result
);
545 int InternalState::FinalSection::sectionComparer(const void* l
, const void* r
)
547 const FinalSection
* left
= *(FinalSection
**)l
;
548 const FinalSection
* right
= *(FinalSection
**)r
;
549 if ( left
->_segmentOrder
!= right
->_segmentOrder
)
550 return (left
->_segmentOrder
- right
->_segmentOrder
);
551 return (left
->_sectionOrder
- right
->_sectionOrder
);
554 void InternalState::sortSections()
556 //fprintf(stderr, "UNSORTED final sections:\n");
557 //for (std::vector<ld::Internal::FinalSection*>::iterator it = sections.begin(); it != sections.end(); ++it) {
558 // fprintf(stderr, "final section %p %s/%s\n", (*it), (*it)->segmentName(), (*it)->sectionName());
560 qsort(§ions
[0], sections
.size(), sizeof(FinalSection
*), &InternalState::FinalSection::sectionComparer
);
561 //fprintf(stderr, "SORTED final sections:\n");
562 //for (std::vector<ld::Internal::FinalSection*>::iterator it = sections.begin(); it != sections.end(); ++it) {
563 // fprintf(stderr, "final section %p %s/%s\n", (*it), (*it)->segmentName(), (*it)->sectionName());
565 assert((sections
[0]->type() == ld::Section::typeMachHeader
)
566 || ((sections
[0]->type() == ld::Section::typeFirstSection
) && (sections
[1]->type() == ld::Section::typeMachHeader
))
567 || ((sections
[0]->type() == ld::Section::typePageZero
) && (sections
[1]->type() == ld::Section::typeMachHeader
))
568 || ((sections
[0]->type() == ld::Section::typePageZero
) && (sections
[1]->type() == ld::Section::typeFirstSection
) && (sections
[2]->type() == ld::Section::typeMachHeader
)) );
572 static char* commatize(uint64_t in
, char* out
)
576 sprintf(rawNum
, "%llu", in
);
577 const int rawNumLen
= strlen(rawNum
);
578 for(int i
=0; i
< rawNumLen
-1; ++i
) {
580 if ( ((rawNumLen
-i
) % 3) == 1 )
583 *out
++ = rawNum
[rawNumLen
-1];
588 static void printTime(const char* msg
, uint64_t partTime
, uint64_t totalTime
)
590 static uint64_t sUnitsPerSecond
= 0;
591 if ( sUnitsPerSecond
== 0 ) {
592 struct mach_timebase_info timeBaseInfo
;
593 if ( mach_timebase_info(&timeBaseInfo
) != KERN_SUCCESS
)
595 sUnitsPerSecond
= 1000000000ULL * timeBaseInfo
.denom
/ timeBaseInfo
.numer
;
597 if ( partTime
< sUnitsPerSecond
) {
598 uint32_t milliSecondsTimeTen
= (partTime
*10000)/sUnitsPerSecond
;
599 uint32_t milliSeconds
= milliSecondsTimeTen
/10;
600 uint32_t percentTimesTen
= (partTime
*1000)/totalTime
;
601 uint32_t percent
= percentTimesTen
/10;
602 fprintf(stderr
, "%24s: % 4d.%d milliseconds (% 4d.%d%%)\n", msg
, milliSeconds
, milliSecondsTimeTen
-milliSeconds
*10, percent
, percentTimesTen
-percent
*10);
605 uint32_t secondsTimeTen
= (partTime
*10)/sUnitsPerSecond
;
606 uint32_t seconds
= secondsTimeTen
/10;
607 uint32_t percentTimesTen
= (partTime
*1000)/totalTime
;
608 uint32_t percent
= percentTimesTen
/10;
609 fprintf(stderr
, "%24s: % 4d.%d seconds (% 4d.%d%%)\n", msg
, seconds
, secondsTimeTen
-seconds
*10, percent
, percentTimesTen
-percent
*10);
614 static void getVMInfo(vm_statistics_data_t
& info
)
616 mach_msg_type_number_t count
= sizeof(vm_statistics_data_t
) / sizeof(natural_t
);
617 kern_return_t error
= host_statistics(mach_host_self(), HOST_VM_INFO
,
618 (host_info_t
)&info
, &count
);
619 if (error
!= KERN_SUCCESS
) {
620 bzero(&info
, sizeof(vm_statistics_data_t
));
626 static const char* sOverridePathlibLTO
= NULL
;
629 // This is magic glue that overrides the default behaviour
630 // of lazydylib1.o which is used to lazily load libLTO.dylib.
632 extern "C" const char* dyld_lazy_dylib_path_fix(const char* path
);
633 const char* dyld_lazy_dylib_path_fix(const char* path
)
635 if ( sOverridePathlibLTO
!= NULL
)
636 return sOverridePathlibLTO
;
643 int main(int argc
, const char* argv
[])
645 const char* archName
= NULL
;
646 bool showArch
= false;
647 bool archInferred
= false;
649 PerformanceStatistics statistics
;
650 statistics
.startTool
= mach_absolute_time();
652 // create object to track command line arguments
653 Options
options(argc
, argv
);
654 InternalState
state(options
);
656 // allow libLTO to be overridden by command line -lto_library
657 sOverridePathlibLTO
= options
.overridePathlibLTO();
660 if ( options
.printStatistics() )
661 getVMInfo(statistics
.vmStart
);
663 // update strings for error messages
664 showArch
= options
.printArchPrefix();
665 archName
= options
.architectureName();
666 archInferred
= (options
.architecture() == 0);
668 // open and parse input files
669 statistics
.startInputFileProcessing
= mach_absolute_time();
670 ld::tool::InputFiles
inputFiles(options
, &archName
);
672 // load and resolve all references
673 statistics
.startResolver
= mach_absolute_time();
674 ld::tool::Resolver
resolver(options
, inputFiles
, state
);
678 statistics
.startDylibs
= mach_absolute_time();
679 inputFiles
.dylibs(state
);
681 // do initial section sorting so passes have rough idea of the layout
682 state
.sortSections();
685 statistics
.startPasses
= mach_absolute_time();
686 ld::passes::objc::doPass(options
, state
);
687 ld::passes::stubs::doPass(options
, state
);
688 ld::passes::huge::doPass(options
, state
);
689 ld::passes::got::doPass(options
, state
);
690 ld::passes::tlvp::doPass(options
, state
);
691 ld::passes::dylibs::doPass(options
, state
); // must be after stubs and GOT passes
692 ld::passes::order::doPass(options
, state
);
693 state
.markAtomsOrdered();
694 ld::passes::branch_shim::doPass(options
, state
); // must be after stubs
695 ld::passes::branch_island::doPass(options
, state
); // must be after stubs and order pass
696 ld::passes::dtrace::doPass(options
, state
);
697 ld::passes::compact_unwind::doPass(options
, state
); // must be after order pass
699 // sort final sections
700 state
.sortSections();
703 statistics
.startOutput
= mach_absolute_time();
704 ld::tool::OutputFile
out(options
);
706 statistics
.startDone
= mach_absolute_time();
709 //mach_o::relocatable::printCounts();
710 if ( options
.printStatistics() ) {
711 getVMInfo(statistics
.vmEnd
);
712 uint64_t totalTime
= statistics
.startDone
- statistics
.startTool
;
713 printTime("ld total time", totalTime
, totalTime
);
714 printTime(" option parsing time", statistics
.startInputFileProcessing
- statistics
.startTool
, totalTime
);
715 printTime(" object file processing", statistics
.startResolver
- statistics
.startInputFileProcessing
,totalTime
);
716 printTime(" resolve symbols", statistics
.startDylibs
- statistics
.startResolver
, totalTime
);
717 printTime(" build atom list", statistics
.startPasses
- statistics
.startDylibs
, totalTime
);
718 printTime(" passess", statistics
.startOutput
- statistics
.startPasses
, totalTime
);
719 printTime(" write output", statistics
.startDone
- statistics
.startOutput
, totalTime
);
720 fprintf(stderr
, "pageins=%u, pageouts=%u, faults=%u\n",
721 statistics
.vmEnd
.pageins
-statistics
.vmStart
.pageins
,
722 statistics
.vmEnd
.pageouts
-statistics
.vmStart
.pageouts
,
723 statistics
.vmEnd
.faults
-statistics
.vmStart
.faults
);
725 fprintf(stderr
, "processed %3u object files, totaling %15s bytes\n", inputFiles
._totalObjectLoaded
, commatize(inputFiles
._totalObjectSize
, temp
));
726 fprintf(stderr
, "processed %3u archive files, totaling %15s bytes\n", inputFiles
._totalArchivesLoaded
, commatize(inputFiles
._totalArchiveSize
, temp
));
727 fprintf(stderr
, "processed %3u dylib files\n", inputFiles
._totalDylibsLoaded
);
728 fprintf(stderr
, "wrote output file totaling %15s bytes\n", commatize(out
.fileSize(), temp
));
730 // <rdar://problem/6780050> Would like linker warning to be build error.
731 if ( options
.errorBecauseOfWarnings() ) {
732 fprintf(stderr
, "ld: fatal warning(s) induced error (-fatal_warnings)\n");
736 catch (const char* msg
) {
738 fprintf(stderr
, "ld: %s for inferred architecture %s\n", msg
, archName
);
740 fprintf(stderr
, "ld: %s for architecture %s\n", msg
, archName
);
742 fprintf(stderr
, "ld: %s\n", msg
);
751 // implement assert() function to print out a backtrace before aborting
752 void __assert_rtn(const char* func
, const char* file
, int line
, const char* failedexpr
)
754 Snapshot
*snapshot
= Snapshot::globalSnapshot
;
756 snapshot
->setSnapshotMode(Snapshot::SNAPSHOT_DEBUG
);
757 snapshot
->createSnapshot();
758 snapshot
->recordAssertionMessage("Assertion failed: (%s), function %s, file %s, line %d.\n", failedexpr
, func
, file
, line
);
760 void* callStack
[128];
761 int depth
= ::backtrace(callStack
, 128);
762 char* buffer
= (char*)malloc(1024);
763 for(int i
=0; i
< depth
-1; ++i
) {
765 dladdr(callStack
[i
], &info
);
766 const char* symboName
= info
.dli_sname
;
767 if ( (symboName
!= NULL
) && (strncmp(symboName
, "_Z", 2) == 0) ) {
768 size_t bufLen
= 1024;
770 char* unmangled
= abi::__cxa_demangle(symboName
, buffer
, &bufLen
, &result
);
771 if ( unmangled
!= NULL
)
772 symboName
= unmangled
;
774 long offset
= (uintptr_t)callStack
[i
] - (uintptr_t)info
.dli_saddr
;
775 fprintf(stderr
, "%d %p %s + %ld\n", i
, callStack
[i
], symboName
, offset
);
776 snapshot
->recordAssertionMessage("%d %p %s + %ld\n", i
, callStack
[i
], symboName
, offset
);
778 fprintf(stderr
, "A linker snapshot was created at:\n\t%s\n", snapshot
->rootDir());
779 fprintf(stderr
, "ld: Assertion failed: (%s), function %s, file %s, line %d.\n", failedexpr
, func
, file
, line
);