]> git.saurik.com Git - apple/ld64.git/blob - src/ld/ld.cpp
ld64-127.2.tar.gz
[apple/ld64.git] / src / ld / ld.cpp
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-*
2 *
3 * Copyright (c) 2005-2010 Apple Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
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
12 * file.
13 *
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.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25 // start temp HACK for cross builds
26 extern "C" double log2 ( double );
27 //#define __MATH__
28 // end temp HACK for cross builds
29
30
31 #include <stdlib.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <sys/mman.h>
35 #include <sys/sysctl.h>
36 #include <fcntl.h>
37 #include <errno.h>
38 #include <limits.h>
39 #include <unistd.h>
40 #include <execinfo.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>
45 #include <dlfcn.h>
46 #include <mach-o/dyld.h>
47 #include <dlfcn.h>
48 #include <AvailabilityMacros.h>
49
50 #include <string>
51 #include <map>
52 #include <set>
53 #include <string>
54 #include <vector>
55 #include <list>
56 #include <algorithm>
57 #include <ext/hash_map>
58 #include <ext/hash_set>
59 #include <cxxabi.h>
60
61 #include "Options.h"
62
63 #include "MachOFileAbstraction.hpp"
64 #include "Architectures.hpp"
65 #include "ld.hpp"
66
67 #include "InputFiles.h"
68 #include "Resolver.h"
69 #include "OutputFile.h"
70
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_file.h"
78 #include "passes/branch_island.h"
79 #include "passes/branch_shim.h"
80 #include "passes/objc.h"
81 #include "passes/dylibs.h"
82
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"
88
89
90 class InternalState : public ld::Internal
91 {
92 public:
93 InternalState(const Options& opts) : _options(opts) { }
94 virtual ld::Internal::FinalSection* addAtom(const ld::Atom& atom);
95 virtual ld::Internal::FinalSection* getFinalSection(const ld::Section&);
96
97 void sortSections();
98 virtual ~InternalState() {}
99 private:
100
101 class FinalSection : public ld::Internal::FinalSection
102 {
103 public:
104 FinalSection(const ld::Section& sect, uint32_t sectionsSeen, bool objFile);
105 static int sectionComparer(const void* l, const void* r);
106 static const ld::Section& outputSection(const ld::Section& sect, bool mergeZeroFill);
107 static const ld::Section& objectOutputSection(const ld::Section& sect, bool makeTentativeDefsReal);
108 private:
109 friend class InternalState;
110 static uint32_t sectionOrder(const ld::Section& sect, uint32_t sectionsSeen);
111 static uint32_t segmentOrder(const ld::Section& sect, bool objFile);
112 uint32_t _segmentOrder;
113 uint32_t _sectionOrder;
114
115 static std::vector<const char*> _s_segmentsSeen;
116 static ld::Section _s_DATA_data;
117 static ld::Section _s_DATA_const;
118 static ld::Section _s_TEXT_text;
119 static ld::Section _s_TEXT_const;
120 static ld::Section _s_DATA_nl_symbol_ptr;
121 static ld::Section _s_DATA_common;
122 static ld::Section _s_DATA_zerofill;
123 };
124
125
126 struct SectionHash {
127 size_t operator()(const ld::Section*) const;
128 };
129 struct SectionEquals {
130 bool operator()(const ld::Section* left, const ld::Section* right) const;
131 };
132 typedef __gnu_cxx::hash_map<const ld::Section*, FinalSection*, SectionHash, SectionEquals> SectionInToOut;
133
134
135 SectionInToOut _sectionInToFinalMap;
136 const Options& _options;
137 };
138
139 ld::Section InternalState::FinalSection::_s_DATA_data( "__DATA", "__data", ld::Section::typeUnclassified);
140 ld::Section InternalState::FinalSection::_s_DATA_const("__DATA", "__const", ld::Section::typeUnclassified);
141 ld::Section InternalState::FinalSection::_s_TEXT_text( "__TEXT", "__text", ld::Section::typeCode);
142 ld::Section InternalState::FinalSection::_s_TEXT_const("__TEXT", "__const", ld::Section::typeUnclassified);
143 ld::Section InternalState::FinalSection::_s_DATA_nl_symbol_ptr("__DATA", "__nl_symbol_ptr", ld::Section::typeNonLazyPointer);
144 ld::Section InternalState::FinalSection::_s_DATA_common("__DATA", "__common", ld::Section::typeZeroFill);
145 ld::Section InternalState::FinalSection::_s_DATA_zerofill("__DATA", "__zerofill", ld::Section::typeZeroFill);
146 std::vector<const char*> InternalState::FinalSection::_s_segmentsSeen;
147
148
149 size_t InternalState::SectionHash::operator()(const ld::Section* sect) const
150 {
151 size_t hash = 0;
152 __gnu_cxx::hash<const char*> temp;
153 hash += temp.operator()(sect->segmentName());
154 hash += temp.operator()(sect->sectionName());
155 return hash;
156 }
157
158 bool InternalState::SectionEquals::operator()(const ld::Section* left, const ld::Section* right) const
159 {
160 return (*left == *right);
161 }
162
163
164 InternalState::FinalSection::FinalSection(const ld::Section& sect, uint32_t sectionsSeen, bool objFile)
165 : ld::Internal::FinalSection(sect),
166 _segmentOrder(segmentOrder(sect, objFile)),
167 _sectionOrder(sectionOrder(sect, sectionsSeen))
168 {
169 //fprintf(stderr, "FinalSection(%s, %s) _segmentOrder=%d, _sectionOrder=%d\n",
170 // this->segmentName(), this->sectionName(), _segmentOrder, _sectionOrder);
171 }
172
173 const ld::Section& InternalState::FinalSection::outputSection(const ld::Section& sect, bool mergeZeroFill)
174 {
175 // merge sections in final linked image
176 switch ( sect.type() ) {
177 case ld::Section::typeLiteral4:
178 case ld::Section::typeLiteral8:
179 case ld::Section::typeLiteral16:
180 return _s_TEXT_const;
181 case ld::Section::typeUnclassified:
182 if ( strcmp(sect.segmentName(), "__DATA") == 0 ) {
183 if ( strcmp(sect.sectionName(), "__datacoal_nt") == 0 )
184 return _s_DATA_data;
185 if ( strcmp(sect.sectionName(), "__const_coal") == 0 )
186 return _s_DATA_const;
187 }
188 else if ( strcmp(sect.segmentName(), "__TEXT") == 0 ) {
189 if ( strcmp(sect.sectionName(), "__const_coal") == 0 )
190 return _s_TEXT_const;
191 }
192 break;
193 case ld::Section::typeZeroFill:
194 if ( mergeZeroFill )
195 return _s_DATA_zerofill;
196 break;
197 case ld::Section::typeCode:
198 if ( strcmp(sect.segmentName(), "__TEXT") == 0 ) {
199 if ( strcmp(sect.sectionName(), "__textcoal_nt") == 0 )
200 return _s_TEXT_text;
201 else if ( strcmp(sect.sectionName(), "__StaticInit") == 0 )
202 return _s_TEXT_text;
203 }
204 break;
205 case ld::Section::typeNonLazyPointer:
206 if ( strcmp(sect.segmentName(), "__DATA") == 0 ) {
207 if ( strcmp(sect.sectionName(), "__nl_symbol_ptr") == 0 )
208 return _s_DATA_nl_symbol_ptr;
209 }
210 else if ( strcmp(sect.segmentName(), "__IMPORT") == 0 ) {
211 if ( strcmp(sect.sectionName(), "__pointers") == 0 )
212 return _s_DATA_nl_symbol_ptr;
213 }
214 break;
215 case ld::Section::typeTentativeDefs:
216 if ( mergeZeroFill )
217 return _s_DATA_zerofill;
218 else
219 return _s_DATA_common;
220 break;
221 // FIX ME: more
222 default:
223 break;
224 }
225 return sect;
226 }
227
228 const ld::Section& InternalState::FinalSection::objectOutputSection(const ld::Section& sect, bool makeTentativeDefsReal)
229 {
230 // in -r mode the only section that ever changes is __tenative -> __common with -d option
231 if ( (sect.type() == ld::Section::typeTentativeDefs) && makeTentativeDefsReal)
232 return _s_DATA_common;
233 return sect;
234 }
235
236 uint32_t InternalState::FinalSection::segmentOrder(const ld::Section& sect, bool objFile)
237 {
238 if ( strcmp(sect.segmentName(), "__PAGEZERO") == 0 )
239 return 0;
240 if ( strcmp(sect.segmentName(), "__HEADER") == 0 ) // only used with -preload
241 return 0;
242 if ( strcmp(sect.segmentName(), "__TEXT") == 0 )
243 return 1;
244 // in -r mode, want __DATA last so zerofill sections are at end
245 if ( strcmp(sect.segmentName(), "__DATA") == 0 )
246 return (objFile ? 5 : 2);
247 if ( strcmp(sect.segmentName(), "__OBJC") == 0 )
248 return 3;
249 if ( strcmp(sect.segmentName(), "__IMPORT") == 0 )
250 return 4;
251
252 // layout non-standard segments in order seen (+10 to shift beyond standard segments)
253 for (uint32_t i=0; i < _s_segmentsSeen.size(); ++i) {
254 if ( strcmp(_s_segmentsSeen[i], sect.segmentName()) == 0 )
255 return i+10;
256 }
257 _s_segmentsSeen.push_back(sect.segmentName());
258 return _s_segmentsSeen.size()-1+10;
259 }
260
261 uint32_t InternalState::FinalSection::sectionOrder(const ld::Section& sect, uint32_t sectionsSeen)
262 {
263 if ( sect.type() == ld::Section::typeFirstSection )
264 return 0;
265 if ( sect.type() == ld::Section::typeMachHeader )
266 return 1;
267 if ( sect.type() == ld::Section::typeLastSection )
268 return INT_MAX;
269 if ( strcmp(sect.segmentName(), "__TEXT") == 0 ) {
270 switch ( sect.type() ) {
271 case ld::Section::typeCode:
272 // <rdar://problem/8346444> make __text always be first "code" section
273 if ( strcmp(sect.sectionName(), "__text") == 0 )
274 return 10;
275 else
276 return 11;
277 case ld::Section::typeStub:
278 return 12;
279 case ld::Section::typeStubHelper:
280 return 13;
281 case ld::Section::typeLSDA:
282 return INT_MAX-3;
283 case ld::Section::typeUnwindInfo:
284 return INT_MAX-2;
285 case ld::Section::typeCFI:
286 return INT_MAX-1;
287 case ld::Section::typeStubClose:
288 return INT_MAX;
289 default:
290 return sectionsSeen+20;
291 }
292 }
293 else if ( strcmp(sect.segmentName(), "__DATA") == 0 ) {
294 switch ( sect.type() ) {
295 case ld::Section::typeLazyPointerClose:
296 return 8;
297 case ld::Section::typeDyldInfo:
298 return 9;
299 case ld::Section::typeNonLazyPointer:
300 return 10;
301 case ld::Section::typeLazyPointer:
302 return 11;
303 case ld::Section::typeInitializerPointers:
304 return 12;
305 case ld::Section::typeTerminatorPointers:
306 return 13;
307 case ld::Section::typeTLVInitialValues:
308 return INT_MAX-4; // need TLV zero-fill to follow TLV init values
309 case ld::Section::typeTLVZeroFill:
310 return INT_MAX-3;
311 case ld::Section::typeZeroFill:
312 // make sure __huge is always last zerofill section
313 if ( strcmp(sect.sectionName(), "__huge") == 0 )
314 return INT_MAX-1;
315 else
316 return INT_MAX-2;
317 default:
318 // <rdar://problem/7435296> Reorder sections to reduce page faults in object files
319 if ( strcmp(sect.sectionName(), "__objc_classlist") == 0 )
320 return 20;
321 else if ( strcmp(sect.sectionName(), "__objc_nlclslist") == 0 )
322 return 21;
323 else if ( strcmp(sect.sectionName(), "__objc_catlist") == 0 )
324 return 22;
325 else if ( strcmp(sect.sectionName(), "__objc_protolist") == 0 )
326 return 23;
327 else if ( strcmp(sect.sectionName(), "__objc_imageinfo") == 0 )
328 return 24;
329 else if ( strcmp(sect.sectionName(), "__objc_const") == 0 )
330 return 25;
331 else if ( strcmp(sect.sectionName(), "__objc_selrefs") == 0 )
332 return 26;
333 else if ( strcmp(sect.sectionName(), "__objc_msgrefs") == 0 )
334 return 27;
335 else if ( strcmp(sect.sectionName(), "__objc_protorefs") == 0 )
336 return 28;
337 else if ( strcmp(sect.sectionName(), "__objc_classrefs") == 0 )
338 return 29;
339 else if ( strcmp(sect.sectionName(), "__objc_superrefs") == 0 )
340 return 30;
341 else if ( strcmp(sect.sectionName(), "__objc_data") == 0 )
342 return 31;
343 else
344 return sectionsSeen+40;
345 }
346 }
347 // make sure zerofill in any other section is at end of segment
348 if ( sect.type() == ld::Section::typeZeroFill )
349 return INT_MAX-1;
350 return sectionsSeen+20;
351 }
352
353 #ifndef NDEBUG
354 static void validateFixups(const ld::Atom& atom)
355 {
356 //fprintf(stderr, "validateFixups %s\n", atom.name());
357 bool lastWasClusterEnd = true;
358 ld::Fixup::Cluster lastClusterSize = ld::Fixup::k1of1;
359 uint32_t curClusterOffsetInAtom = 0;
360 for (ld::Fixup::iterator fit=atom.fixupsBegin(); fit != atom.fixupsEnd(); ++fit) {
361 //fprintf(stderr, " fixup offset=%d, cluster=%d\n", fit->offsetInAtom, fit->clusterSize);
362 assert((fit->offsetInAtom < atom.size()) || (fit->offsetInAtom == 0));
363 if ( fit->firstInCluster() ) {
364 assert(lastWasClusterEnd);
365 curClusterOffsetInAtom = fit->offsetInAtom;
366 lastWasClusterEnd = (fit->clusterSize == ld::Fixup::k1of1);
367 }
368 else {
369 assert(!lastWasClusterEnd);
370 assert(fit->offsetInAtom == curClusterOffsetInAtom);
371 switch ((ld::Fixup::Cluster)fit->clusterSize) {
372 case ld::Fixup::k1of1:
373 case ld::Fixup::k1of2:
374 case ld::Fixup::k1of3:
375 case ld::Fixup::k1of4:
376 case ld::Fixup::k1of5:
377 lastWasClusterEnd = false;
378 break;
379 case ld::Fixup::k2of2:
380 assert(lastClusterSize = ld::Fixup::k1of2);
381 lastWasClusterEnd = true;
382 break;
383 case ld::Fixup::k2of3:
384 assert(lastClusterSize = ld::Fixup::k1of3);
385 lastWasClusterEnd = false;
386 break;
387 case ld::Fixup::k2of4:
388 assert(lastClusterSize = ld::Fixup::k1of4);
389 lastWasClusterEnd = false;
390 break;
391 case ld::Fixup::k2of5:
392 assert(lastClusterSize = ld::Fixup::k1of5);
393 lastWasClusterEnd = false;
394 break;
395 case ld::Fixup::k3of3:
396 assert(lastClusterSize = ld::Fixup::k2of3);
397 lastWasClusterEnd = true;
398 break;
399 case ld::Fixup::k3of4:
400 assert(lastClusterSize = ld::Fixup::k2of4);
401 lastWasClusterEnd = false;
402 break;
403 case ld::Fixup::k3of5:
404 assert(lastClusterSize = ld::Fixup::k2of5);
405 lastWasClusterEnd = false;
406 break;
407 case ld::Fixup::k4of4:
408 assert(lastClusterSize = ld::Fixup::k3of4);
409 lastWasClusterEnd = true;
410 break;
411 case ld::Fixup::k4of5:
412 assert(lastClusterSize = ld::Fixup::k3of5);
413 lastWasClusterEnd = false;
414 break;
415 case ld::Fixup::k5of5:
416 assert(lastClusterSize = ld::Fixup::k4of5);
417 lastWasClusterEnd = true;
418 break;
419 }
420 }
421 lastClusterSize = fit->clusterSize;
422 if ( fit->binding == ld::Fixup::bindingDirectlyBound ) {
423 assert(fit->u.target != NULL);
424 }
425 }
426 switch (lastClusterSize) {
427 case ld::Fixup::k1of1:
428 case ld::Fixup::k2of2:
429 case ld::Fixup::k3of3:
430 case ld::Fixup::k4of4:
431 case ld::Fixup::k5of5:
432 break;
433 default:
434 assert(0 && "last fixup was not end of cluster");
435 break;
436 }
437 }
438 #endif
439
440 ld::Internal::FinalSection* InternalState::addAtom(const ld::Atom& atom)
441 {
442 ld::Internal::FinalSection* fs = this->getFinalSection(atom.section());
443
444 // <rdar://problem/8612550> When order file used on data, turn ordered zero fill symbols into zero data
445 switch ( atom.section().type() ) {
446 case ld::Section::typeZeroFill:
447 case ld::Section::typeTentativeDefs:
448 if ( (atom.symbolTableInclusion() == ld::Atom::symbolTableIn)
449 && (atom.size() <= 512) && (_options.orderedSymbolsCount() != 0) ) {
450 for(Options::OrderedSymbolsIterator it = _options.orderedSymbolsBegin(); it != _options.orderedSymbolsEnd(); ++it) {
451 if ( (it->objectFileName == NULL) && (strcmp(it->symbolName, atom.name()) == 0) ) {
452 // found in order file, move to __data section
453 fs = getFinalSection(InternalState::FinalSection::_s_DATA_data);\
454 //fprintf(stderr, "moved %s to __data section\n", atom.name());
455 break;
456 }
457 }
458 }
459 break;
460 default:
461 break;
462 }
463
464 //fprintf(stderr, "InternalState::doAtom(%p), name=%s, sect=%s, finalsect=%p\n", &atom, atom.name(), atom.section().sectionName(), fs);
465 #ifndef NDEBUG
466 validateFixups(atom);
467 #endif
468 fs->atoms.push_back(&atom);
469 return fs;
470 }
471
472 ld::Internal::FinalSection* InternalState::getFinalSection(const ld::Section& inputSection)
473 {
474 const ld::Section* baseForFinalSection = &inputSection;
475
476 // see if input section already has a FinalSection
477 SectionInToOut::iterator pos = _sectionInToFinalMap.find(&inputSection);
478 if ( pos != _sectionInToFinalMap.end() ) {
479 return pos->second;
480 }
481
482 // otherwise, create a new final section
483 bool objFile = false;
484 switch ( _options.outputKind() ) {
485 case Options::kStaticExecutable:
486 case Options::kDynamicExecutable:
487 case Options::kDynamicLibrary:
488 case Options::kDynamicBundle:
489 case Options::kDyld:
490 case Options::kKextBundle:
491 case Options::kPreload:
492 {
493 // coalesce some sections
494 const ld::Section& outSect = FinalSection::outputSection(inputSection, _options.mergeZeroFill());
495 pos = _sectionInToFinalMap.find(&outSect);
496 if ( pos != _sectionInToFinalMap.end() ) {
497 _sectionInToFinalMap[&inputSection] = pos->second;
498 //fprintf(stderr, "_sectionInToFinalMap[%p] = %p\n", &inputSection, pos->second);
499 return pos->second;
500 }
501 else if ( outSect != inputSection ) {
502 // new output section created, but not in map
503 baseForFinalSection = &outSect;
504 }
505 }
506 break;
507 case Options::kObjectFile:
508 baseForFinalSection = &FinalSection::objectOutputSection(inputSection, _options.makeTentativeDefinitionsReal());
509 pos = _sectionInToFinalMap.find(baseForFinalSection);
510 if ( pos != _sectionInToFinalMap.end() ) {
511 _sectionInToFinalMap[&inputSection] = pos->second;
512 //fprintf(stderr, "_sectionInToFinalMap[%p] = %p\n", &inputSection, pos->second);
513 return pos->second;
514 }
515 objFile = true;
516 break;
517 }
518
519 InternalState::FinalSection* result = new InternalState::FinalSection(*baseForFinalSection,
520 _sectionInToFinalMap.size(), objFile);
521 _sectionInToFinalMap[baseForFinalSection] = result;
522 //fprintf(stderr, "_sectionInToFinalMap[%p] = %p\n", baseForFinalSection, result);
523 sections.push_back(result);
524 return result;
525 }
526
527
528 int InternalState::FinalSection::sectionComparer(const void* l, const void* r)
529 {
530 const FinalSection* left = *(FinalSection**)l;
531 const FinalSection* right = *(FinalSection**)r;
532 if ( left->_segmentOrder != right->_segmentOrder )
533 return (left->_segmentOrder - right->_segmentOrder);
534 return (left->_sectionOrder - right->_sectionOrder);
535 }
536
537 void InternalState::sortSections()
538 {
539 //fprintf(stderr, "UNSORTED final sections:\n");
540 //for (std::vector<ld::Internal::FinalSection*>::iterator it = sections.begin(); it != sections.end(); ++it) {
541 // fprintf(stderr, "final section %p %s/%s\n", (*it), (*it)->segmentName(), (*it)->sectionName());
542 //}
543 qsort(&sections[0], sections.size(), sizeof(FinalSection*), &InternalState::FinalSection::sectionComparer);
544 //fprintf(stderr, "SORTED final sections:\n");
545 //for (std::vector<ld::Internal::FinalSection*>::iterator it = sections.begin(); it != sections.end(); ++it) {
546 // fprintf(stderr, "final section %p %s/%s\n", (*it), (*it)->segmentName(), (*it)->sectionName());
547 //}
548 assert((sections[0]->type() == ld::Section::typeMachHeader)
549 || ((sections[0]->type() == ld::Section::typeFirstSection) && (sections[1]->type() == ld::Section::typeMachHeader))
550 || ((sections[0]->type() == ld::Section::typePageZero) && (sections[1]->type() == ld::Section::typeMachHeader))
551 || ((sections[0]->type() == ld::Section::typePageZero) && (sections[1]->type() == ld::Section::typeFirstSection) && (sections[2]->type() == ld::Section::typeMachHeader)) );
552
553 }
554
555 static void getVMInfo(vm_statistics_data_t& info)
556 {
557 mach_msg_type_number_t count = sizeof(vm_statistics_data_t) / sizeof(natural_t);
558 kern_return_t error = host_statistics(mach_host_self(), HOST_VM_INFO,
559 (host_info_t)&info, &count);
560 if (error != KERN_SUCCESS) {
561 bzero(&info, sizeof(vm_statistics_data_t));
562 }
563 }
564
565 int main(int argc, const char* argv[])
566 {
567 #if DEBUG
568 usleep(1000000);
569 #endif
570 const char* archName = NULL;
571 bool showArch = false;
572 bool archInferred = false;
573 try {
574 vm_statistics_data_t vmStart;
575 vm_statistics_data_t vmEnd;
576 getVMInfo(vmStart);
577
578 // create object to track command line arguments
579 Options options(argc, argv);
580
581 // gather stats
582 if ( options.printStatistics() )
583 getVMInfo(vmStart);
584
585 // update strings for error messages
586 showArch = options.printArchPrefix();
587 archName = options.architectureName();
588 archInferred = (options.architecture() == 0);
589
590 // open and parse input files
591 ld::tool::InputFiles inputFiles(options, &archName);
592
593 // load and resolve all references
594 InternalState state(options);
595 ld::tool::Resolver resolver(options, inputFiles, state);
596 resolver.resolve();
597
598 // add dylibs used
599 inputFiles.dylibs(state);
600
601 // do initial section sorting so passes have rough idea of the layout
602 state.sortSections();
603
604 // run passes
605 ld::passes::objc::doPass(options, state);
606 ld::passes::stubs::doPass(options, state);
607 ld::passes::huge::doPass(options, state);
608 ld::passes::got::doPass(options, state);
609 ld::passes::tlvp::doPass(options, state);
610 ld::passes::dylibs::doPass(options, state); // must be after stubs and GOT passes
611 ld::passes::order_file::doPass(options, state);
612 ld::passes::branch_shim::doPass(options, state); // must be after stubs
613 ld::passes::branch_island::doPass(options, state); // must be after stubs and order_file pass
614 ld::passes::dtrace::doPass(options, state);
615 ld::passes::compact_unwind::doPass(options, state); // must be after order-file pass
616
617 // sort final sections
618 state.sortSections();
619
620 // write output file
621 ld::tool::OutputFile out(options);
622 out.write(state);
623
624 // print statistics
625 //mach_o::relocatable::printCounts();
626 if ( options.printStatistics() ) {
627 getVMInfo(vmEnd);
628 fprintf(stderr, "pageins=%u, pageouts=%u, faults=%u\n", vmEnd.pageins-vmStart.pageins,
629 vmEnd.pageouts-vmStart.pageouts, vmEnd.faults-vmStart.faults);
630
631 }
632 }
633 catch (const char* msg) {
634 if ( archInferred )
635 fprintf(stderr, "ld: %s for inferred architecture %s\n", msg, archName);
636 else if ( showArch )
637 fprintf(stderr, "ld: %s for architecture %s\n", msg, archName);
638 else
639 fprintf(stderr, "ld: %s\n", msg);
640 return 1;
641 }
642
643 return 0;
644 }
645
646
647 #ifndef NDEBUG
648 // implement assert() function to print out a backtrace before aborting
649 void __assert_rtn(const char* func, const char* file, int line, const char* failedexpr)
650 {
651 fprintf(stderr, "Assertion failed: (%s), function %s, file %s, line %d.\n", failedexpr, func, file, line);
652
653 void* callStack[128];
654 int depth = ::backtrace(callStack, 128);
655 char* buffer = (char*)malloc(1024);
656 for(int i=0; i < depth-1; ++i) {
657 Dl_info info;
658 dladdr(callStack[i], &info);
659 const char* symboName = info.dli_sname;
660 if ( (symboName != NULL) && (strncmp(symboName, "_Z", 2) == 0) ) {
661 size_t bufLen = 1024;
662 int result;
663 char* unmangled = abi::__cxa_demangle(symboName, buffer, &bufLen, &result);
664 if ( unmangled != NULL )
665 symboName = unmangled;
666 }
667 long offset = (uintptr_t)callStack[i] - (uintptr_t)info.dli_saddr;
668 fprintf(stderr, "%d %p %s + %ld\n", i, callStack[i], symboName, offset);
669 }
670 exit(1);
671 }
672 #endif
673
674