]> git.saurik.com Git - apple/ld64.git/blame_incremental - src/other/ObjectDump.cpp
ld64-409.12.tar.gz
[apple/ld64.git] / src / other / ObjectDump.cpp
... / ...
CommitLineData
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#include <sys/types.h>
26#include <sys/stat.h>
27#include <sys/mman.h>
28#include <fcntl.h>
29#include <mach-o/nlist.h>
30#include <mach-o/stab.h>
31#include <mach-o/fat.h>
32#include <mach-o/loader.h>
33
34#include "MachOFileAbstraction.hpp"
35#include "parsers/macho_relocatable_file.h"
36#include "parsers/lto_file.h"
37
38const ld::VersionSet ld::File::_platforms;
39
40static bool sDumpContent= true;
41static bool sDumpStabs = false;
42static bool sSort = true;
43static bool sNMmode = false;
44static bool sShowSection = true;
45static bool sShowDefinitionKind = true;
46static bool sShowCombineKind = true;
47static bool sShowLineInfo = true;
48
49static cpu_type_t sPreferredArch = 0xFFFFFFFF;
50static cpu_subtype_t sPreferredSubArch = 0xFFFFFFFF;
51static const char* sMatchName = NULL;
52static int sPrintRestrict;
53static int sPrintAlign;
54static int sPrintName;
55
56 __attribute__((noreturn))
57void throwf(const char* format, ...)
58{
59 va_list list;
60 char* p;
61 va_start(list, format);
62 vasprintf(&p, format, list);
63 va_end(list);
64
65 const char* t = p;
66 throw t;
67}
68
69void warning(const char* format, ...)
70{
71 va_list list;
72 fprintf(stderr, "warning: ");
73 va_start(list, format);
74 vfprintf(stderr, format, list);
75 va_end(list);
76 fprintf(stderr, "\n");
77}
78
79static void dumpStabs(const std::vector<ld::relocatable::File::Stab>* stabs)
80{
81 // debug info
82 printf("stabs: (%lu)\n", stabs->size());
83 for (std::vector<ld::relocatable::File::Stab>::const_iterator it = stabs->begin(); it != stabs->end(); ++it ) {
84 const ld::relocatable::File::Stab& stab = *it;
85 const char* code = "?????";
86 switch (stab.type) {
87 case N_GSYM:
88 code = " GSYM";
89 break;
90 case N_FNAME:
91 code = "FNAME";
92 break;
93 case N_FUN:
94 code = " FUN";
95 break;
96 case N_STSYM:
97 code = "STSYM";
98 break;
99 case N_LCSYM:
100 code = "LCSYM";
101 break;
102 case N_BNSYM:
103 code = "BNSYM";
104 break;
105 case N_OPT:
106 code = " OPT";
107 break;
108 case N_RSYM:
109 code = " RSYM";
110 break;
111 case N_SLINE:
112 code = "SLINE";
113 break;
114 case N_ENSYM:
115 code = "ENSYM";
116 break;
117 case N_SSYM:
118 code = " SSYM";
119 break;
120 case N_SO:
121 code = " SO";
122 break;
123 case N_OSO:
124 code = " OSO";
125 break;
126 case N_LSYM:
127 code = " LSYM";
128 break;
129 case N_BINCL:
130 code = "BINCL";
131 break;
132 case N_SOL:
133 code = " SOL";
134 break;
135 case N_PARAMS:
136 code = "PARMS";
137 break;
138 case N_VERSION:
139 code = " VERS";
140 break;
141 case N_OLEVEL:
142 code = "OLEVL";
143 break;
144 case N_PSYM:
145 code = " PSYM";
146 break;
147 case N_EINCL:
148 code = "EINCL";
149 break;
150 case N_ENTRY:
151 code = "ENTRY";
152 break;
153 case N_LBRAC:
154 code = "LBRAC";
155 break;
156 case N_EXCL:
157 code = " EXCL";
158 break;
159 case N_RBRAC:
160 code = "RBRAC";
161 break;
162 case N_BCOMM:
163 code = "BCOMM";
164 break;
165 case N_ECOMM:
166 code = "ECOMM";
167 break;
168 case N_LENG:
169 code = "LENG";
170 break;
171 }
172 printf(" [atom=%20s] %02X %04X %s %s\n", ((stab.atom != NULL) ? stab.atom->name() : ""), stab.other, stab.desc, code, stab.string);
173 }
174}
175
176#if 0
177static void dumpAtomLikeNM(ld::Atom* atom)
178{
179 uint32_t size = atom->size();
180
181 const char* visibility;
182 switch ( atom->scope() ) {
183 case ld::Atom::scopeTranslationUnit:
184 visibility = "internal";
185 break;
186 case ld::Atom::scopeLinkageUnit:
187 visibility = "hidden ";
188 break;
189 case ld::Atom::scopeGlobal:
190 visibility = "global ";
191 break;
192 default:
193 visibility = " ";
194 break;
195 }
196
197 const char* kind;
198 switch ( atom->definitionKind() ) {
199 case ld::Atom::kRegularDefinition:
200 kind = "regular ";
201 break;
202 case ld::Atom::kTentativeDefinition:
203 kind = "tentative";
204 break;
205 case ld::Atom::kWeakDefinition:
206 kind = "weak ";
207 break;
208 case ld::Atom::kAbsoluteSymbol:
209 kind = "absolute ";
210 break;
211 default:
212 kind = " ";
213 break;
214 }
215
216 printf("0x%08X %s %s %s\n", size, visibility, kind, atom->name());
217}
218
219
220static void dumpAtom(ld::Atom* atom)
221{
222 if(sMatchName && strcmp(sMatchName, atom->name()))
223 return;
224
225 //printf("atom: %p\n", atom);
226
227 // name
228 if(!sPrintRestrict || sPrintName)
229 printf("name: %s\n", atom->name());
230
231 // scope
232 if(!sPrintRestrict)
233 switch ( atom->scope() ) {
234 case ld::Atom::scopeTranslationUnit:
235 printf("scope: translation unit\n");
236 break;
237 case ld::Atom::scopeLinkageUnit:
238 printf("scope: linkage unit\n");
239 break;
240 case ld::Atom::scopeGlobal:
241 printf("scope: global\n");
242 break;
243 default:
244 printf("scope: unknown\n");
245 }
246
247 // kind
248 if(!sPrintRestrict)
249 switch ( atom->definitionKind() ) {
250 case ld::Atom::kRegularDefinition:
251 printf("kind: regular\n");
252 break;
253 case ld::Atom::kWeakDefinition:
254 printf("kind: weak\n");
255 break;
256 case ld::Atom::kTentativeDefinition:
257 printf("kind: tentative\n");
258 break;
259 case ld::Atom::kExternalDefinition:
260 printf("kind: import\n");
261 break;
262 case ld::Atom::kExternalWeakDefinition:
263 printf("kind: weak import\n");
264 break;
265 case ld::Atom::kAbsoluteSymbol:
266 printf("kind: absolute symbol\n");
267 break;
268 default:
269 printf("kind: unknown\n");
270 }
271
272 // segment and section
273 if(!sPrintRestrict && (atom->section().sectionName() != NULL) )
274 printf("section: %s,%s\n", atom->section().segmentName(), atom->section().sectionName());
275
276 // attributes
277 if(!sPrintRestrict) {
278 printf("attrs: ");
279 if ( atom->dontDeadStrip() )
280 printf("dont-dead-strip ");
281 if ( atom->isThumb() )
282 printf("thumb ");
283 printf("\n");
284 }
285
286 // size
287 if(!sPrintRestrict)
288 printf("size: 0x%012llX\n", atom->size());
289
290 // alignment
291 if(!sPrintRestrict || sPrintAlign)
292 printf("align: %u mod %u\n", atom->alignment().modulus, (1 << atom->alignment().powerOf2) );
293
294 // content
295 if (!sPrintRestrict && sDumpContent ) {
296 uint64_t size = atom->size();
297 if ( size < 4096 ) {
298 uint8_t content[size];
299 atom->copyRawContent(content);
300 printf("content: ");
301 if ( atom->contentType() == ld::Atom::typeCString ) {
302 printf("\"");
303 for (unsigned int i=0; i < size; ++i) {
304 if(content[i]<'!' || content[i]>=127)
305 printf("\\%o", content[i]);
306 else
307 printf("%c", content[i]);
308 }
309 printf("\"");
310 }
311 else {
312 for (unsigned int i=0; i < size; ++i)
313 printf("%02X ", content[i]);
314 }
315 }
316 printf("\n");
317 }
318
319 // unwind info
320 if(!sPrintRestrict) {
321 if ( atom->beginUnwind() != atom->endUnwind() ) {
322 printf("unwind encodings:\n");
323 for (ld::Atom::UnwindInfo::iterator it = atom->beginUnwind(); it != atom->endUnwind(); ++it) {
324 printf("\t 0x%04X 0x%08X\n", it->startOffset, it->unwindInfo);
325 }
326 }
327 }
328#if 0
329 // references
330 if(!sPrintRestrict) {
331 std::vector<ObjectFile::Reference*>& references = atom->getReferences();
332 const int refCount = references.size();
333 printf("references: (%u)\n", refCount);
334 for (int i=0; i < refCount; ++i) {
335 ObjectFile::Reference* ref = references[i];
336 printf(" %s\n", ref->getDescription());
337 }
338 }
339#endif
340 // line info
341 if(!sPrintRestrict) {
342 if ( atom->beginLineInfo() != atom->endLineInfo() ) {
343 printf("line info:\n");
344 for (ld::Atom::LineInfo::iterator it = atom->beginLineInfo(); it != atom->endLineInfo(); ++it) {
345 printf(" offset 0x%04X, line %d, file %s\n", it->atomOffset, it->lineNumber, it->fileName);
346 }
347 }
348 }
349
350 if(!sPrintRestrict)
351 printf("\n");
352}
353#endif
354struct AtomSorter
355{
356 bool operator()(const ld::Atom* left, const ld::Atom* right)
357 {
358 if ( left == right )
359 return false;
360 // first sort by segment name
361 int diff = strcmp(left->section().segmentName(), right->section().segmentName());
362 if ( diff != 0 )
363 return (diff > 0);
364
365 // then sort by section name
366 diff = strcmp(left->section().sectionName(), right->section().sectionName());
367 if ( diff != 0 )
368 return (diff < 0);
369
370 // then sort by atom name
371 diff = strcmp(left->name(), right->name());
372 if ( diff != 0 )
373 return (diff < 0);
374
375 // if cstring, sort by content
376 if ( left->contentType() == ld::Atom::typeCString ) {
377 diff = strcmp((char*)left->rawContentPointer(), (char*)right->rawContentPointer());
378 if ( diff != 0 )
379 return (diff < 0);
380 }
381 else if ( left->section().type() == ld::Section::typeCStringPointer ) {
382 // if pointer to c-string sort by name
383 const char* leftString = NULL;
384 assert(left->fixupsBegin() != left->fixupsEnd());
385 for (ld::Fixup::iterator fit = left->fixupsBegin(); fit != left->fixupsEnd(); ++fit) {
386 if ( fit->binding == ld::Fixup::bindingByContentBound ) {
387 const ld::Atom* cstringAtom = fit->u.target;
388 assert(cstringAtom->contentType() == ld::Atom::typeCString);
389 leftString = (char*)cstringAtom->rawContentPointer();
390 }
391 }
392 const char* rightString = NULL;
393 assert(right->fixupsBegin() != right->fixupsEnd());
394 for (ld::Fixup::iterator fit = right->fixupsBegin(); fit != right->fixupsEnd(); ++fit) {
395 if ( fit->binding == ld::Fixup::bindingByContentBound ) {
396 const ld::Atom* cstringAtom = fit->u.target;
397 assert(cstringAtom->contentType() == ld::Atom::typeCString);
398 rightString = (char*)cstringAtom->rawContentPointer();
399 }
400 }
401 if ( leftString != rightString ) {
402 assert(leftString != NULL);
403 assert(rightString != NULL);
404 diff = strcmp(leftString, rightString);
405 if ( diff != 0 )
406 return (diff < 0);
407 }
408 }
409 else if ( left->section().type() == ld::Section::typeLiteral4 ) {
410 // if literal sort by content
411 uint32_t leftValue = *(uint32_t*)left->rawContentPointer();
412 uint32_t rightValue = *(uint32_t*)right->rawContentPointer();
413 diff = (leftValue - rightValue);
414 if ( diff != 0 )
415 return (diff < 0);
416 }
417 else if ( left->section().type() == ld::Section::typeCFI ) {
418 // if __he_frame sort by address
419 diff = (left->objectAddress() - right->objectAddress());
420 if ( diff != 0 )
421 return (diff < 0);
422 }
423 else if ( left->section().type() == ld::Section::typeNonLazyPointer ) {
424 // if non-lazy-pointer sort by name
425 const char* leftString = NULL;
426 assert(left->fixupsBegin() != left->fixupsEnd());
427 for (ld::Fixup::iterator fit = left->fixupsBegin(); fit != left->fixupsEnd(); ++fit) {
428 if ( fit->binding == ld::Fixup::bindingByNameUnbound ) {
429 leftString = fit->u.name;
430 }
431 else if ( fit->binding == ld::Fixup::bindingDirectlyBound ) {
432 leftString = fit->u.target->name();
433 }
434 }
435 const char* rightString = NULL;
436 assert(right->fixupsBegin() != right->fixupsEnd());
437 for (ld::Fixup::iterator fit = right->fixupsBegin(); fit != right->fixupsEnd(); ++fit) {
438 if ( fit->binding == ld::Fixup::bindingByNameUnbound ) {
439 rightString = fit->u.name;
440 }
441 else if ( fit->binding == ld::Fixup::bindingDirectlyBound ) {
442 rightString = fit->u.target->name();
443 }
444 }
445 assert(leftString != NULL);
446 assert(rightString != NULL);
447 diff = strcmp(leftString, rightString);
448 if ( diff != 0 )
449 return (diff < 0);
450 }
451
452 // else sort by size
453 return (left->size() < right->size());
454 }
455};
456
457
458class dumper : public ld::File::AtomHandler
459{
460public:
461 void dump();
462 virtual void doAtom(const ld::Atom&);
463 virtual void doFile(const ld::File&) {}
464private:
465 void dumpAtom(const ld::Atom& atom);
466 const char* scopeString(const ld::Atom&);
467 const char* definitionString(const ld::Atom&);
468 const char* combineString(const ld::Atom&);
469 const char* inclusionString(const ld::Atom&);
470 const char* attributeString(const ld::Atom&);
471 const char* makeName(const ld::Atom& atom);
472 const char* referenceTargetAtomName(const ld::Fixup* ref);
473 void dumpFixup(const ld::Fixup* ref);
474
475 uint64_t addressOfFirstAtomInSection(const ld::Section&);
476
477 std::vector<const ld::Atom*> _atoms;
478};
479
480const char* dumper::scopeString(const ld::Atom& atom)
481{
482 switch ( (ld::Atom::Scope)atom.scope() ) {
483 case ld::Atom::scopeTranslationUnit:
484 return "translation-unit";
485 case ld::Atom::scopeLinkageUnit:
486 return "hidden";
487 case ld::Atom::scopeGlobal:
488 if ( atom.autoHide() )
489 return "global but automatically hidden";
490 else
491 return "global";
492 }
493 return "UNKNOWN";
494}
495
496const char* dumper::definitionString(const ld::Atom& atom)
497{
498 switch ( (ld::Atom::Definition)atom.definition() ) {
499 case ld::Atom::definitionRegular:
500 return "regular";
501 case ld::Atom::definitionTentative:
502 return "tentative";
503 case ld::Atom::definitionAbsolute:
504 return "absolute";
505 case ld::Atom::definitionProxy:
506 return "proxy";
507 }
508 return "UNKNOWN";
509}
510
511const char* dumper::combineString(const ld::Atom& atom)
512{
513 switch ( (ld::Atom::Combine)atom.combine() ) {
514 case ld::Atom::combineNever:
515 return "never";
516 case ld::Atom::combineByName:
517 return "by-name";
518 case ld::Atom::combineByNameAndContent:
519 return "by-name-and-content";
520 case ld::Atom::combineByNameAndReferences:
521 return "by-name-and-references";
522 }
523 return "UNKNOWN";
524}
525
526const char* dumper::inclusionString(const ld::Atom& atom)
527{
528 switch ( (ld::Atom::SymbolTableInclusion)atom.symbolTableInclusion() ) {
529 case ld::Atom::symbolTableNotIn:
530 return "not in";
531 case ld::Atom::symbolTableNotInFinalLinkedImages:
532 return "not in final linked images";
533 case ld::Atom::symbolTableIn:
534 return "in";
535 case ld::Atom::symbolTableInAndNeverStrip:
536 return "in and never strip";
537 case ld::Atom::symbolTableInAsAbsolute:
538 return "in as absolute";
539 case ld::Atom::symbolTableInWithRandomAutoStripLabel:
540 return "in as random auto-strip label";
541 }
542 return "UNKNOWN";
543}
544
545
546
547const char* dumper::attributeString(const ld::Atom& atom)
548{
549 static char buffer[256];
550 buffer[0] = '\0';
551
552 if ( atom.dontDeadStrip() )
553 strcat(buffer, "dont-dead-strip ");
554
555 if ( atom.isThumb() )
556 strcat(buffer, "thumb ");
557
558 if ( atom.isAlias() )
559 strcat(buffer, "alias ");
560
561 if ( atom.contentType() == ld::Atom::typeResolver )
562 strcat(buffer, "resolver ");
563
564 return buffer;
565}
566
567const char* dumper::makeName(const ld::Atom& atom)
568{
569 static char buffer[4096];
570 strcpy(buffer, "???");
571 switch ( atom.symbolTableInclusion() ) {
572 case ld::Atom::symbolTableNotIn:
573 if ( atom.contentType() == ld::Atom::typeCString ) {
574 strcpy(buffer, "cstring=");
575 strlcat(buffer, (char*)atom.rawContentPointer(), 4096);
576 }
577 else if ( atom.section().type() == ld::Section::typeLiteral4 ) {
578 char temp[16];
579 strcpy(buffer, "literal4=");
580 uint32_t value = *(uint32_t*)atom.rawContentPointer();
581 sprintf(temp, "0x%08X", value);
582 strcat(buffer, temp);
583 }
584 else if ( atom.section().type() == ld::Section::typeLiteral8 ) {
585 char temp[32];
586 strcpy(buffer, "literal8=");
587 uint32_t value1 = *(uint32_t*)atom.rawContentPointer();
588 uint32_t value2 = ((uint32_t*)atom.rawContentPointer())[1];
589 sprintf(temp, "0x%08X%08X", value1, value2);
590 strcat(buffer, temp);
591 }
592 else if ( atom.section().type() == ld::Section::typeLiteral16 ) {
593 char temp[64];
594 strcpy(buffer, "literal16=");
595 uint32_t value1 = *(uint32_t*)atom.rawContentPointer();
596 uint32_t value2 = ((uint32_t*)atom.rawContentPointer())[1];
597 uint32_t value3 = ((uint32_t*)atom.rawContentPointer())[2];
598 uint32_t value4 = ((uint32_t*)atom.rawContentPointer())[3];
599 sprintf(temp, "0x%08X%08X%08X%08X", value1, value2, value3, value4);
600 strcat(buffer, temp);
601 }
602 else if ( atom.section().type() == ld::Section::typeCStringPointer ) {
603 assert(atom.fixupsBegin() != atom.fixupsEnd());
604 for (ld::Fixup::iterator fit = atom.fixupsBegin(); fit != atom.fixupsEnd(); ++fit) {
605 if ( fit->binding == ld::Fixup::bindingByContentBound ) {
606 const ld::Atom* cstringAtom = fit->u.target;
607 if ( (cstringAtom != NULL) && (cstringAtom->contentType() == ld::Atom::typeCString) ) {
608 strlcpy(buffer, atom.name(), 4096);
609 strlcat(buffer, "=", 4096);
610 strlcat(buffer, (char*)cstringAtom->rawContentPointer(), 4096);
611 }
612 }
613 }
614 }
615 else if ( atom.section().type() == ld::Section::typeNonLazyPointer ) {
616 assert(atom.fixupsBegin() != atom.fixupsEnd());
617 for (ld::Fixup::iterator fit = atom.fixupsBegin(); fit != atom.fixupsEnd(); ++fit) {
618 if ( fit->binding == ld::Fixup::bindingByNameUnbound ) {
619 strcpy(buffer, "non-lazy-pointer-to:");
620 strlcat(buffer, fit->u.name, 4096);
621 return buffer;
622 }
623 else if ( fit->binding == ld::Fixup::bindingDirectlyBound ) {
624 strcpy(buffer, "non-lazy-pointer-to-local:");
625 strlcat(buffer, fit->u.target->name(), 4096);
626 return buffer;
627 }
628 }
629 strlcpy(buffer, atom.name(), 4096);
630 }
631 else {
632 uint64_t sectAddr = addressOfFirstAtomInSection(atom.section());
633 sprintf(buffer, "%s@%s+0x%08llX", atom.name(), atom.section().sectionName(), atom.objectAddress()-sectAddr);
634 }
635 break;
636 case ld::Atom::symbolTableNotInFinalLinkedImages:
637 case ld::Atom::symbolTableIn:
638 case ld::Atom::symbolTableInAndNeverStrip:
639 case ld::Atom::symbolTableInAsAbsolute:
640 case ld::Atom::symbolTableInWithRandomAutoStripLabel:
641 strlcpy(buffer, atom.name(), 4096);
642 break;
643 }
644 return buffer;
645}
646
647const char* dumper::referenceTargetAtomName(const ld::Fixup* ref)
648{
649 static char buffer[4096];
650 switch ( ref->binding ) {
651 case ld::Fixup::bindingNone:
652 return "NO BINDING";
653 case ld::Fixup::bindingByNameUnbound:
654 strcpy(buffer, "by-name(");
655 strlcat(buffer, ref->u.name, 4096);
656 strlcat(buffer, ")", 4096);
657 return buffer;
658 //return ref->u.name;
659 case ld::Fixup::bindingByContentBound:
660 strcpy(buffer, "by-content(");
661 strlcat(buffer, makeName(*ref->u.target), 4096);
662 strlcat(buffer, ")", 4096);
663 return buffer;
664 case ld::Fixup::bindingDirectlyBound:
665 strcpy(buffer, "direct(");
666 strlcat(buffer, makeName(*ref->u.target), 4096);
667 strlcat(buffer, ")", 4096);
668 return buffer;
669 case ld::Fixup::bindingsIndirectlyBound:
670 return "BOUND INDIRECTLY";
671 }
672 return "BAD BINDING";
673}
674
675
676void dumper::dumpFixup(const ld::Fixup* ref)
677{
678 if ( ref->weakImport ) {
679 printf("weak_import ");
680 }
681 switch ( (ld::Fixup::Kind)(ref->kind) ) {
682 case ld::Fixup::kindNone:
683 printf("none");
684 break;
685 case ld::Fixup::kindNoneFollowOn:
686 printf("followed by %s", referenceTargetAtomName(ref));
687 break;
688 case ld::Fixup::kindNoneGroupSubordinate:
689 printf("group subordinate %s", referenceTargetAtomName(ref));
690 break;
691 case ld::Fixup::kindNoneGroupSubordinateFDE:
692 printf("group subordinate FDE %s", referenceTargetAtomName(ref));
693 break;
694 case ld::Fixup::kindNoneGroupSubordinateLSDA:
695 printf("group subordinate LSDA %s", referenceTargetAtomName(ref));
696 break;
697 case ld::Fixup::kindNoneGroupSubordinatePersonality:
698 printf("group subordinate personality %s", referenceTargetAtomName(ref));
699 break;
700 case ld::Fixup::kindSetTargetAddress:
701 printf("%s", referenceTargetAtomName(ref));
702 break;
703 case ld::Fixup::kindSubtractTargetAddress:
704 printf(" - %s", referenceTargetAtomName(ref));
705 break;
706 case ld::Fixup::kindAddAddend:
707 printf(" + 0x%llX", ref->u.addend);
708 break;
709 case ld::Fixup::kindSubtractAddend:
710 printf(" - 0x%llX", ref->u.addend);
711 break;
712 case ld::Fixup::kindSetTargetImageOffset:
713 printf("imageOffset(%s)", referenceTargetAtomName(ref));
714 break;
715 case ld::Fixup::kindSetTargetSectionOffset:
716 printf("sectionOffset(%s)", referenceTargetAtomName(ref));
717 break;
718 case ld::Fixup::kindStore8:
719 printf(", then store byte");
720 break;
721 case ld::Fixup::kindStoreLittleEndian16:
722 printf(", then store 16-bit little endian");
723 break;
724 case ld::Fixup::kindStoreLittleEndianLow24of32:
725 printf(", then store low 24-bit little endian");
726 break;
727 case ld::Fixup::kindStoreLittleEndian32:
728 printf(", then store 32-bit little endian");
729 break;
730 case ld::Fixup::kindStoreLittleEndian64:
731 printf(", then store 64-bit little endian");
732 break;
733 case ld::Fixup::kindStoreBigEndian16:
734 printf(", then store 16-bit big endian");
735 break;
736 case ld::Fixup::kindStoreBigEndianLow24of32:
737 printf(", then store low 24-bit big endian");
738 break;
739 case ld::Fixup::kindStoreBigEndian32:
740 printf(", then store 32-bit big endian");
741 break;
742 case ld::Fixup::kindStoreBigEndian64:
743 printf(", then store 64-bit big endian");
744 break;
745 case ld::Fixup::kindStoreX86BranchPCRel8:
746 printf(", then store as x86 8-bit pcrel branch");
747 break;
748 case ld::Fixup::kindStoreX86BranchPCRel32:
749 printf(", then store as x86 32-bit pcrel branch");
750 break;
751 case ld::Fixup::kindStoreX86PCRel8:
752 printf(", then store as x86 8-bit pcrel");
753 break;
754 case ld::Fixup::kindStoreX86PCRel16:
755 printf(", then store as x86 16-bit pcrel");
756 break;
757 case ld::Fixup::kindStoreX86PCRel32:
758 printf(", then store as x86 32-bit pcrel");
759 break;
760 case ld::Fixup::kindStoreX86PCRel32_1:
761 printf(", then store as x86 32-bit pcrel from +1");
762 break;
763 case ld::Fixup::kindStoreX86PCRel32_2:
764 printf(", then store as x86 32-bit pcrel from +2");
765 break;
766 case ld::Fixup::kindStoreX86PCRel32_4:
767 printf(", then store as x86 32-bit pcrel from +4");
768 break;
769 case ld::Fixup::kindStoreX86PCRel32GOTLoad:
770 printf(", then store as x86 32-bit pcrel GOT load");
771 break;
772 case ld::Fixup::kindStoreX86PCRel32GOTLoadNowLEA:
773 printf(", then store as x86 32-bit pcrel GOT load -> LEA");
774 break;
775 case ld::Fixup::kindStoreX86PCRel32GOT:
776 printf(", then store as x86 32-bit pcrel GOT access");
777 break;
778 case ld::Fixup::kindStoreX86PCRel32TLVLoad:
779 printf(", then store as x86 32-bit pcrel TLV load");
780 break;
781 case ld::Fixup::kindStoreX86PCRel32TLVLoadNowLEA:
782 printf(", then store as x86 32-bit pcrel TLV load");
783 break;
784 case ld::Fixup::kindStoreX86Abs32TLVLoad:
785 printf(", then store as x86 32-bit absolute TLV load");
786 break;
787 case ld::Fixup::kindStoreX86Abs32TLVLoadNowLEA:
788 printf(", then store as x86 32-bit absolute TLV load -> LEA");
789 break;
790 case ld::Fixup::kindStoreARMBranch24:
791 printf(", then store as ARM 24-bit pcrel branch");
792 break;
793 case ld::Fixup::kindStoreThumbBranch22:
794 printf(", then store as Thumb 22-bit pcrel branch");
795 break;
796 case ld::Fixup::kindStoreARMLoad12:
797 printf(", then store as ARM 12-bit pcrel load");
798 break;
799 case ld::Fixup::kindStoreARMLow16:
800 printf(", then store low-16 in ARM movw");
801 break;
802 case ld::Fixup::kindStoreARMHigh16:
803 printf(", then store high-16 in ARM movt");
804 break;
805 case ld::Fixup::kindStoreThumbLow16:
806 printf(", then store low-16 in Thumb movw");
807 break;
808 case ld::Fixup::kindStoreThumbHigh16:
809 printf(", then store high-16 in Thumb movt");
810 break;
811#if SUPPORT_ARCH_arm64
812 case ld::Fixup::kindStoreARM64Branch26:
813 printf(", then store as ARM64 26-bit pcrel branch");
814 break;
815 case ld::Fixup::kindStoreARM64Page21:
816 printf(", then store as ARM64 21-bit pcrel ADRP");
817 break;
818 case ld::Fixup::kindStoreARM64PageOff12:
819 printf(", then store as ARM64 12-bit offset");
820 break;
821 case ld::Fixup::kindStoreARM64GOTLoadPage21:
822 printf(", then store as ARM64 21-bit pcrel ADRP of GOT");
823 break;
824 case ld::Fixup::kindStoreARM64GOTLoadPageOff12:
825 printf(", then store as ARM64 12-bit page offset of GOT");
826 break;
827 case ld::Fixup::kindStoreARM64GOTLeaPage21:
828 printf(", then store as ARM64 21-bit pcrel ADRP of GOT lea");
829 break;
830 case ld::Fixup::kindStoreARM64GOTLeaPageOff12:
831 printf(", then store as ARM64 12-bit page offset of GOT lea");
832 break;
833 case ld::Fixup::kindStoreARM64TLVPLoadPage21:
834 printf(", then store as ARM64 21-bit pcrel ADRP of TLVP");
835 break;
836 case ld::Fixup::kindStoreARM64TLVPLoadPageOff12:
837 printf(", then store as ARM64 12-bit page offset of TLVP");
838 break;
839 case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPage21:
840 printf(", then store as ARM64 21-bit pcrel ADRP of lea of TLVP");
841 break;
842 case ld::Fixup::kindStoreARM64TLVPLoadNowLeaPageOff12:
843 printf(", then store as ARM64 12-bit page offset of lea of TLVP");
844 break;
845 case ld::Fixup::kindStoreARM64PointerToGOT:
846 printf(", then store as 64-bit pointer to GOT entry");
847 break;
848 case ld::Fixup::kindStoreARM64PCRelToGOT:
849 printf(", then store as 32-bit delta to GOT entry");
850 break;
851#endif
852 case ld::Fixup::kindDtraceExtra:
853 printf("dtrace static probe extra info");
854 break;
855 case ld::Fixup::kindStoreX86DtraceCallSiteNop:
856 printf("x86 dtrace static probe site");
857 break;
858 case ld::Fixup::kindStoreX86DtraceIsEnableSiteClear:
859 printf("x86 dtrace static is-enabled site");
860 break;
861 case ld::Fixup::kindStoreARMDtraceCallSiteNop:
862 printf("ARM dtrace static probe site");
863 break;
864 case ld::Fixup::kindStoreARMDtraceIsEnableSiteClear:
865 printf("ARM dtrace static is-enabled site");
866 break;
867 case ld::Fixup::kindStoreThumbDtraceCallSiteNop:
868 printf("Thumb dtrace static probe site");
869 break;
870 case ld::Fixup::kindStoreThumbDtraceIsEnableSiteClear:
871 printf("Thumb dtrace static is-enabled site");
872 break;
873#if SUPPORT_ARCH_arm64
874 case ld::Fixup::kindStoreARM64DtraceCallSiteNop:
875 printf("ARM64 dtrace static probe site");
876 break;
877 case ld::Fixup::kindStoreARM64DtraceIsEnableSiteClear:
878 printf("ARM64 dtrace static is-enabled site");
879 break;
880#endif
881 case ld::Fixup::kindLazyTarget:
882 printf("lazy reference to external symbol %s", referenceTargetAtomName(ref));
883 break;
884 case ld::Fixup::kindSetLazyOffset:
885 printf("offset of lazy binding info for %s", referenceTargetAtomName(ref));
886 break;
887 case ld::Fixup::kindIslandTarget:
888 printf("ultimate target of island %s", referenceTargetAtomName(ref));
889 break;
890 case ld::Fixup::kindDataInCodeStartData:
891 printf("start of data in code");
892 break;
893 case ld::Fixup::kindDataInCodeStartJT8:
894 printf("start of jump table 8 data in code");
895 break;
896 case ld::Fixup::kindDataInCodeStartJT16:
897 printf("start of jump table 16 data in code");
898 break;
899 case ld::Fixup::kindDataInCodeStartJT32:
900 printf("start of jump table 32 data in code");
901 break;
902 case ld::Fixup::kindDataInCodeStartJTA32:
903 printf("start of jump table absolute 32 data in code");
904 break;
905 case ld::Fixup::kindDataInCodeEnd:
906 printf("end of data in code");
907 break;
908 case ld::Fixup::kindLinkerOptimizationHint:
909#if SUPPORT_ARCH_arm64
910 ld::Fixup::LOH_arm64 extra;
911 extra.addend = ref->u.addend;
912 printf("ARM64 hint: ");
913 switch(extra.info.kind) {
914 case LOH_ARM64_ADRP_ADRP:
915 printf("ADRP-ADRP");
916 break;
917 case LOH_ARM64_ADRP_LDR:
918 printf("ADRP-LDR");
919 break;
920 case LOH_ARM64_ADRP_ADD_LDR:
921 printf("ADRP-ADD-LDR");
922 break;
923 case LOH_ARM64_ADRP_LDR_GOT_LDR:
924 printf("ADRP-LDR-GOT-LDR");
925 break;
926 case LOH_ARM64_ADRP_ADD_STR:
927 printf("ADRP-ADD-STR");
928 break;
929 case LOH_ARM64_ADRP_LDR_GOT_STR:
930 printf("ADRP-LDR-GOT-STR");
931 break;
932 case LOH_ARM64_ADRP_ADD:
933 printf("ADRP-ADD");
934 break;
935 default:
936 printf("kind=%d", extra.info.kind);
937 break;
938 }
939 printf(", offset1=0x%X", (extra.info.delta1 << 2) + ref->offsetInAtom);
940 if ( extra.info.count > 0 )
941 printf(", offset2=0x%X", (extra.info.delta2 << 2) + ref->offsetInAtom);
942 if ( extra.info.count > 1 )
943 printf(", offset3=0x%X", (extra.info.delta3 << 2) + ref->offsetInAtom);
944 if ( extra.info.count > 2 )
945 printf(", offset4=0x%X", (extra.info.delta4 << 2) + ref->offsetInAtom);
946#endif
947 break;
948 case ld::Fixup::kindStoreTargetAddressLittleEndian32:
949 printf("store 32-bit little endian address of %s", referenceTargetAtomName(ref));
950 break;
951 case ld::Fixup::kindStoreTargetAddressLittleEndian64:
952 printf("store 64-bit little endian address of %s", referenceTargetAtomName(ref));
953 break;
954 case ld::Fixup::kindStoreTargetAddressBigEndian32:
955 printf("store 32-bit big endian address of %s", referenceTargetAtomName(ref));
956 break;
957 case ld::Fixup::kindStoreTargetAddressBigEndian64:
958 printf("store 64-bit big endian address of %s", referenceTargetAtomName(ref));
959 break;
960 case ld::Fixup::kindStoreTargetAddressX86PCRel32:
961 printf("x86 store 32-bit pc-rel address of %s", referenceTargetAtomName(ref));
962 break;
963 case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32:
964 printf("x86 store 32-bit pc-rel branch to %s", referenceTargetAtomName(ref));
965 break;
966 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad:
967 printf("x86 store 32-bit pc-rel GOT load of %s", referenceTargetAtomName(ref));
968 break;
969 case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA:
970 printf("x86 store 32-bit pc-rel lea of %s", referenceTargetAtomName(ref));
971 break;
972 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad:
973 printf("x86 store 32-bit pc-rel TLV load of %s", referenceTargetAtomName(ref));
974 break;
975 case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA:
976 printf("x86 store 32-bit pc-rel TLV lea of %s", referenceTargetAtomName(ref));
977 break;
978 case ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoad:
979 printf("x86 store 32-bit absolute TLV load of %s", referenceTargetAtomName(ref));
980 break;
981 case ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoadNowLEA:
982 printf("x86 store 32-bit absolute TLV lea of %s", referenceTargetAtomName(ref));
983 break;
984 case ld::Fixup::kindStoreTargetAddressARMBranch24:
985 printf("ARM store 24-bit pc-rel branch to %s", referenceTargetAtomName(ref));
986 break;
987 case ld::Fixup::kindStoreTargetAddressThumbBranch22:
988 printf("Thumb store 22-bit pc-rel branch to %s", referenceTargetAtomName(ref));
989 break;
990 case ld::Fixup::kindStoreTargetAddressARMLoad12:
991 printf("ARM store 12-bit pc-rel branch to %s", referenceTargetAtomName(ref));
992 break;
993 case ld::Fixup::kindSetTargetTLVTemplateOffset:
994 case ld::Fixup::kindSetTargetTLVTemplateOffsetLittleEndian32:
995 case ld::Fixup::kindSetTargetTLVTemplateOffsetLittleEndian64:
996 printf("tlv template offset of %s", referenceTargetAtomName(ref));
997 break;
998#if SUPPORT_ARCH_arm64
999 case ld::Fixup::kindStoreTargetAddressARM64Branch26:
1000 printf("ARM64 store 26-bit pcrel branch to %s", referenceTargetAtomName(ref));
1001 break;
1002 case ld::Fixup::kindStoreTargetAddressARM64Page21:
1003 printf("ARM64 store 21-bit pcrel ADRP to %s", referenceTargetAtomName(ref));
1004 break;
1005 case ld::Fixup::kindStoreTargetAddressARM64PageOff12:
1006 printf("ARM64 store 12-bit page offset of %s", referenceTargetAtomName(ref));
1007 break;
1008 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21:
1009 printf("ARM64 store 21-bit pcrel ADRP to GOT for %s", referenceTargetAtomName(ref));
1010 break;
1011 case ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12:
1012 printf("ARM64 store 12-bit page offset of GOT of %s", referenceTargetAtomName(ref));
1013 break;
1014 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPage21:
1015 printf("ARM64 store 21-bit pcrel ADRP to GOT lea for %s", referenceTargetAtomName(ref));
1016 break;
1017 case ld::Fixup::kindStoreTargetAddressARM64GOTLeaPageOff12:
1018 printf("ARM64 store 12-bit page offset of GOT lea of %s", referenceTargetAtomName(ref));
1019 break;
1020 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21:
1021 printf("ARM64 store 21-bit pcrel ADRP to TLV for %s", referenceTargetAtomName(ref));
1022 break;
1023 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12:
1024 printf("ARM64 store 12-bit page offset of TLV of %s", referenceTargetAtomName(ref));
1025 break;
1026 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPage21:
1027 printf("ARM64 store 21-bit pcrel ADRP to lea for TLV for %s", referenceTargetAtomName(ref));
1028 break;
1029 case ld::Fixup::kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12:
1030 printf("ARM64 store 12-bit page offset of lea for TLV of %s", referenceTargetAtomName(ref));
1031 break;
1032#endif
1033 //default:
1034 // printf("unknown fixup");
1035 // break;
1036 }
1037}
1038
1039uint64_t dumper::addressOfFirstAtomInSection(const ld::Section& sect)
1040{
1041 uint64_t lowestAddr = (uint64_t)(-1);
1042 for (std::vector<const ld::Atom*>::iterator it=_atoms.begin(); it != _atoms.end(); ++it) {
1043 const ld::Atom* atom = *it;
1044 if ( &atom->section() == &sect ) {
1045 if ( atom->objectAddress() < lowestAddr )
1046 lowestAddr = atom->objectAddress();
1047 }
1048 }
1049 return lowestAddr;
1050}
1051
1052void dumper::doAtom(const ld::Atom& atom)
1053{
1054 if ( (sMatchName != NULL) && (strcmp(sMatchName, atom.name()) != 0) )
1055 return;
1056 _atoms.push_back(&atom);
1057}
1058
1059void dumper::dump()
1060{
1061 if ( sSort )
1062 std::sort(_atoms.begin(), _atoms.end(), AtomSorter());
1063
1064 for (std::vector<const ld::Atom*>::iterator it=_atoms.begin(); it != _atoms.end(); ++it) {
1065 this->dumpAtom(**it);
1066 }
1067}
1068
1069void dumper::dumpAtom(const ld::Atom& atom)
1070{
1071 printf("name: %s\n", makeName(atom));
1072 printf("size: 0x%0llX\n", atom.size());
1073 printf("align: %u mod %u\n", atom.alignment().modulus, (1 << atom.alignment().powerOf2) );
1074 printf("scope: %s\n", scopeString(atom));
1075 if ( sShowDefinitionKind )
1076 printf("def: %s\n", definitionString(atom));
1077 if ( sShowCombineKind )
1078 printf("combine: %s\n", combineString(atom));
1079 printf("symbol: %s\n", inclusionString(atom));
1080 printf("attrs: %s\n", attributeString(atom));
1081 if ( sShowSection )
1082 printf("section: %s,%s\n", atom.section().segmentName(), atom.section().sectionName());
1083 if ( atom.beginUnwind() != atom.endUnwind() ) {
1084 uint32_t lastOffset = 0;
1085 uint32_t lastCUE = 0;
1086 bool first = true;
1087 const char* label = "unwind:";
1088 for (ld::Atom::UnwindInfo::iterator it=atom.beginUnwind(); it != atom.endUnwind(); ++it) {
1089 if ( !first ) {
1090 printf("%s 0x%08X -> 0x%08X: 0x%08X\n", label, lastOffset, it->startOffset, lastCUE);
1091 label = " ";
1092 }
1093 lastOffset = it->startOffset;
1094 lastCUE = it->unwindInfo;
1095 first = false;
1096 }
1097 printf("%s 0x%08X -> 0x%08X: 0x%08X\n", label, lastOffset, (uint32_t)atom.size(), lastCUE);
1098 }
1099 if ( atom.contentType() == ld::Atom::typeCString ) {
1100 uint8_t buffer[atom.size()+2];
1101 atom.copyRawContent(buffer);
1102 buffer[atom.size()] = '\0';
1103 printf("content: \"%s\"\n", buffer);
1104 }
1105 if ( atom.fixupsBegin() != atom.fixupsEnd() ) {
1106 printf("fixups:\n");
1107 for (unsigned int off=0; off < atom.size()+1; ++off) {
1108 for (ld::Fixup::iterator it = atom.fixupsBegin(); it != atom.fixupsEnd(); ++it) {
1109 if ( it->offsetInAtom == off ) {
1110 switch ( it->clusterSize ) {
1111 case ld::Fixup::k1of1:
1112 printf(" 0x%04X ", it->offsetInAtom);
1113 dumpFixup(it);
1114 break;
1115 case ld::Fixup::k1of2:
1116 printf(" 0x%04X ", it->offsetInAtom);
1117 dumpFixup(it);
1118 ++it;
1119 dumpFixup(it);
1120 break;
1121 case ld::Fixup::k1of3:
1122 printf(" 0x%04X ", it->offsetInAtom);
1123 dumpFixup(it);
1124 ++it;
1125 dumpFixup(it);
1126 ++it;
1127 dumpFixup(it);
1128 break;
1129 case ld::Fixup::k1of4:
1130 printf(" 0x%04X ", it->offsetInAtom);
1131 dumpFixup(it);
1132 ++it;
1133 dumpFixup(it);
1134 ++it;
1135 dumpFixup(it);
1136 ++it;
1137 dumpFixup(it);
1138 break;
1139 case ld::Fixup::k1of5:
1140 printf(" 0x%04X ", it->offsetInAtom);
1141 dumpFixup(it);
1142 ++it;
1143 dumpFixup(it);
1144 ++it;
1145 dumpFixup(it);
1146 ++it;
1147 dumpFixup(it);
1148 ++it;
1149 dumpFixup(it);
1150 break;
1151 default:
1152 printf(" BAD CLUSTER SIZE: cluster=%d\n", it->clusterSize);
1153 }
1154 printf("\n");
1155 }
1156 }
1157 }
1158 }
1159 if ( sShowLineInfo ) {
1160 if ( atom.beginLineInfo() != atom.endLineInfo() ) {
1161 printf("line info:\n");
1162 for (ld::Atom::LineInfo::iterator it = atom.beginLineInfo(); it != atom.endLineInfo(); ++it) {
1163 printf(" offset 0x%04X, line %d, file %s\n", it->atomOffset, it->lineNumber, it->fileName);
1164 }
1165 }
1166 }
1167
1168 printf("\n");
1169}
1170
1171static void dumpFile(ld::relocatable::File* file)
1172{
1173 // stabs debug info
1174 if ( sDumpStabs && (file->debugInfo() == ld::relocatable::File::kDebugInfoStabs) ) {
1175 const std::vector<ld::relocatable::File::Stab>* stabs = file->stabs();
1176 if ( stabs != NULL )
1177 dumpStabs(stabs);
1178 }
1179 // dump atoms
1180 dumper d;
1181 file->forEachAtom(d);
1182 d.dump();
1183
1184#if 0
1185 // get all atoms
1186 std::vector<ObjectFile::Atom*> atoms = reader->getAtoms();
1187
1188 // make copy of vector and sort (so output is canonical)
1189 std::vector<ObjectFile::Atom*> sortedAtoms(atoms);
1190 if ( sSort )
1191 std::sort(sortedAtoms.begin(), sortedAtoms.end(), AtomSorter());
1192
1193 for(std::vector<ObjectFile::Atom*>::iterator it=sortedAtoms.begin(); it != sortedAtoms.end(); ++it) {
1194 if ( sNMmode )
1195 dumpAtomLikeNM(*it);
1196 else
1197 dumpAtom(*it);
1198 }
1199#endif
1200}
1201
1202
1203static ld::relocatable::File* createReader(const char* path)
1204{
1205 struct stat stat_buf;
1206
1207 int fd = ::open(path, O_RDONLY, 0);
1208 if ( fd == -1 )
1209 throwf("cannot open file: %s", path);
1210 ::fstat(fd, &stat_buf);
1211 uint8_t* p = (uint8_t*)::mmap(NULL, stat_buf.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
1212 ::close(fd);
1213 if ( p == (uint8_t*)(-1) )
1214 throwf("cannot mmap file: %s", path);
1215 const mach_header* mh = (mach_header*)p;
1216 uint64_t fileLen = stat_buf.st_size;
1217 bool foundFatSlice = false;
1218 if ( mh->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) {
1219 const struct fat_header* fh = (struct fat_header*)p;
1220 const struct fat_arch* archs = (struct fat_arch*)(p + sizeof(struct fat_header));
1221 if ( (uint32_t)sPreferredArch == 0xFFFFFFFF ) {
1222 // just dump first slice of fat .o file
1223 if ( OSSwapBigToHostInt32(fh->nfat_arch) > 0 ) {
1224 p = p + OSSwapBigToHostInt32(archs[0].offset);
1225 mh = (struct mach_header*)p;
1226 fileLen = OSSwapBigToHostInt32(archs[0].size);
1227 sPreferredArch = OSSwapBigToHostInt32(archs[0].cputype);
1228 sPreferredSubArch = OSSwapBigToHostInt32(archs[0].cpusubtype);
1229 foundFatSlice = true;
1230 }
1231 }
1232 else {
1233 for (unsigned long i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) {
1234 if ( OSSwapBigToHostInt32(archs[i].cputype) == (uint32_t)sPreferredArch ) {
1235 if ( ((uint32_t)sPreferredSubArch == 0xFFFFFFFF) || ((uint32_t)sPreferredSubArch == OSSwapBigToHostInt32(archs[i].cpusubtype)) ) {
1236 p = p + OSSwapBigToHostInt32(archs[i].offset);
1237 mh = (struct mach_header*)p;
1238 fileLen = OSSwapBigToHostInt32(archs[i].size);
1239 foundFatSlice = true;
1240 break;
1241 }
1242 }
1243 }
1244 }
1245 }
1246
1247 mach_o::relocatable::ParserOptions objOpts;
1248 objOpts.architecture = sPreferredArch;
1249 objOpts.objSubtypeMustMatch = false;
1250 objOpts.logAllFiles = false;
1251 objOpts.warnUnwindConversionProblems = true;
1252 objOpts.keepDwarfUnwind = false;
1253 objOpts.forceDwarfConversion = false;
1254 objOpts.verboseOptimizationHints = true;
1255 objOpts.armUsesZeroCostExceptions = true;
1256 objOpts.subType = sPreferredSubArch;
1257 objOpts.treateBitcodeAsData = false;
1258 objOpts.usingBitcode = true;
1259#if 1
1260 if ( ! foundFatSlice ) {
1261 cpu_type_t archOfObj;
1262 cpu_subtype_t subArchOfObj;
1263 ld::Platform platform;
1264 uint32_t minOS;
1265 if ( mach_o::relocatable::isObjectFile(p, &archOfObj, &subArchOfObj, &platform, &minOS) ) {
1266 objOpts.architecture = archOfObj;
1267 objOpts.subType = subArchOfObj;
1268 }
1269 }
1270
1271 ld::relocatable::File* objResult = mach_o::relocatable::parse(p, fileLen, path, stat_buf.st_mtime, ld::File::Ordinal::NullOrdinal(), objOpts);
1272 if ( objResult != NULL )
1273 return objResult;
1274
1275 // see if it is an llvm object file
1276 objResult = lto::parse(p, fileLen, path, stat_buf.st_mtime, ld::File::Ordinal::NullOrdinal(), sPreferredArch, sPreferredSubArch, false, true);
1277 if ( objResult != NULL )
1278 return objResult;
1279
1280 throwf("not a mach-o object file: %s", path);
1281#else
1282 // for peformance testing
1283 for (int i=0; i < 500; ++i ) {
1284 ld::relocatable::File* objResult = mach_o::relocatable::parse(p, fileLen, path, stat_buf.st_mtime, 0, objOpts);
1285 delete objResult;
1286 }
1287 exit(0);
1288#endif
1289}
1290
1291static
1292void
1293usage()
1294{
1295 fprintf(stderr, "ObjectDump options:\n"
1296 "\t-no_content\tdon't dump contents\n"
1297 "\t-no_section\tdon't dump section name\n"
1298 "\t-no_defintion\tdon't dump definition kind\n"
1299 "\t-no_combine\tdon't dump combine mode\n"
1300 "\t-stabs\t\tdump stabs\n"
1301 "\t-arch aaa\tonly dump info about arch aaa\n"
1302 "\t-only sym\tonly dump info about sym\n"
1303 "\t-align\t\tonly print alignment info\n"
1304 "\t-name\t\tonly print symbol names\n"
1305 );
1306}
1307
1308int main(int argc, const char* argv[])
1309{
1310 if(argc<2) {
1311 usage();
1312 return 0;
1313 }
1314
1315 try {
1316 for(int i=1; i < argc; ++i) {
1317 const char* arg = argv[i];
1318 if ( arg[0] == '-' ) {
1319 if ( strcmp(arg, "-no_content") == 0 ) {
1320 sDumpContent = false;
1321 }
1322 else if ( strcmp(arg, "-nm") == 0 ) {
1323 sNMmode = true;
1324 }
1325 else if ( strcmp(arg, "-stabs") == 0 ) {
1326 sDumpStabs = true;
1327 }
1328 else if ( strcmp(arg, "-no_sort") == 0 ) {
1329 sSort = false;
1330 }
1331 else if ( strcmp(arg, "-no_section") == 0 ) {
1332 sShowSection = false;
1333 }
1334 else if ( strcmp(arg, "-no_definition") == 0 ) {
1335 sShowDefinitionKind = false;
1336 }
1337 else if ( strcmp(arg, "-no_combine") == 0 ) {
1338 sShowCombineKind = false;
1339 }
1340 else if ( strcmp(arg, "-no_line_info") == 0 ) {
1341 sShowLineInfo = false;
1342 }
1343 else if ( strcmp(arg, "-arch") == 0 ) {
1344 const char* archName = argv[++i];
1345 if ( archName == NULL )
1346 throw "-arch missing architecture name";
1347 bool found = false;
1348 for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) {
1349 if ( strcmp(t->archName,archName) == 0 ) {
1350 sPreferredArch = t->cpuType;
1351 if ( t->isSubType )
1352 sPreferredSubArch = t->cpuSubType;
1353 found = true;
1354 }
1355 }
1356 if ( !found )
1357 throwf("unknown architecture %s", archName);
1358 }
1359 else if ( strcmp(arg, "-only") == 0 ) {
1360 sMatchName = ++i<argc? argv[i]: NULL;
1361 }
1362 else if ( strcmp(arg, "-align") == 0 ) {
1363 sPrintRestrict = true;
1364 sPrintAlign = true;
1365 }
1366 else if ( strcmp(arg, "-name") == 0 ) {
1367 sPrintRestrict = true;
1368 sPrintName = true;
1369 }
1370 else {
1371 usage();
1372 throwf("unknown option: %s\n", arg);
1373 }
1374 }
1375 else {
1376 ld::relocatable::File* reader = createReader(arg);
1377 dumpFile(reader);
1378 }
1379 }
1380 }
1381 catch (const char* msg) {
1382 fprintf(stderr, "ObjDump failed: %s\n", msg);
1383 return 1;
1384 }
1385
1386 return 0;
1387}