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