X-Git-Url: https://git.saurik.com/apple/ld64.git/blobdiff_plain/55e3d2f687f4ed9653982dbda92c6a055b0a8350..a645023da60d22e86be13f7b4d97adeff8bc6665:/src/other/ObjectDump.cpp diff --git a/src/other/ObjectDump.cpp b/src/other/ObjectDump.cpp index c2ae578..abf7162 100644 --- a/src/other/ObjectDump.cpp +++ b/src/other/ObjectDump.cpp @@ -1,6 +1,6 @@ /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- * - * Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2005-2010 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -26,27 +26,30 @@ #include #include #include -#include - -#include "MachOReaderRelocatable.hpp" +#include +#include +#include +#include -#define LTO_SUPPORT 1 - -#if LTO_SUPPORT - #include "LTOReader.hpp" -#endif +#include "MachOFileAbstraction.hpp" +#include "parsers/macho_relocatable_file.h" +#include "parsers/lto_file.h" static bool sDumpContent= true; static bool sDumpStabs = false; static bool sSort = true; static bool sNMmode = false; -static cpu_type_t sPreferredArch = CPU_TYPE_POWERPC64; -static const char* sMatchName; +static bool sShowSection = true; +static bool sShowDefinitionKind = true; +static bool sShowCombineKind = true; + +static cpu_type_t sPreferredArch = CPU_TYPE_I386; +static cpu_subtype_t sPreferredSubArch = 0xFFFFFFFF; +static const char* sMatchName = NULL; static int sPrintRestrict; static int sPrintAlign; static int sPrintName; - __attribute__((noreturn)) void throwf(const char* format, ...) { @@ -70,12 +73,12 @@ void warning(const char* format, ...) fprintf(stderr, "\n"); } -static void dumpStabs(std::vector* stabs) +static void dumpStabs(const std::vector* stabs) { // debug info printf("stabs: (%lu)\n", stabs->size()); - for (std::vector::iterator it = stabs->begin(); it != stabs->end(); ++it ) { - ObjectFile::Reader::Stab& stab = *it; + for (std::vector::const_iterator it = stabs->begin(); it != stabs->end(); ++it ) { + const ld::relocatable::File::Stab& stab = *it; const char* code = "?????"; switch (stab.type) { case N_GSYM: @@ -163,24 +166,24 @@ static void dumpStabs(std::vector* stabs) code = "LENG"; break; } - printf(" [atom=%20s] %02X %04X %s %s\n", ((stab.atom != NULL) ? stab.atom->getDisplayName() : ""), stab.other, stab.desc, code, stab.string); + printf(" [atom=%20s] %02X %04X %s %s\n", ((stab.atom != NULL) ? stab.atom->name() : ""), stab.other, stab.desc, code, stab.string); } } - -static void dumpAtomLikeNM(ObjectFile::Atom* atom) +#if 0 +static void dumpAtomLikeNM(ld::Atom* atom) { - uint32_t size = atom->getSize(); + uint32_t size = atom->size(); const char* visibility; - switch ( atom->getScope() ) { - case ObjectFile::Atom::scopeTranslationUnit: + switch ( atom->scope() ) { + case ld::Atom::scopeTranslationUnit: visibility = "internal"; break; - case ObjectFile::Atom::scopeLinkageUnit: + case ld::Atom::scopeLinkageUnit: visibility = "hidden "; break; - case ObjectFile::Atom::scopeGlobal: + case ld::Atom::scopeGlobal: visibility = "global "; break; default: @@ -189,17 +192,17 @@ static void dumpAtomLikeNM(ObjectFile::Atom* atom) } const char* kind; - switch ( atom->getDefinitionKind() ) { - case ObjectFile::Atom::kRegularDefinition: + switch ( atom->definitionKind() ) { + case ld::Atom::kRegularDefinition: kind = "regular "; break; - case ObjectFile::Atom::kTentativeDefinition: + case ld::Atom::kTentativeDefinition: kind = "tentative"; break; - case ObjectFile::Atom::kWeakDefinition: + case ld::Atom::kWeakDefinition: kind = "weak "; break; - case ObjectFile::Atom::kAbsoluteSymbol: + case ld::Atom::kAbsoluteSymbol: kind = "absolute "; break; default: @@ -207,31 +210,31 @@ static void dumpAtomLikeNM(ObjectFile::Atom* atom) break; } - printf("0x%08X %s %s %s\n", size, visibility, kind, atom->getDisplayName()); + printf("0x%08X %s %s %s\n", size, visibility, kind, atom->name()); } -static void dumpAtom(ObjectFile::Atom* atom) +static void dumpAtom(ld::Atom* atom) { - if(sMatchName && strcmp(sMatchName, atom->getDisplayName())) + if(sMatchName && strcmp(sMatchName, atom->name())) return; //printf("atom: %p\n", atom); // name if(!sPrintRestrict || sPrintName) - printf("name: %s\n", atom->getDisplayName()); + printf("name: %s\n", atom->name()); // scope if(!sPrintRestrict) - switch ( atom->getScope() ) { - case ObjectFile::Atom::scopeTranslationUnit: + switch ( atom->scope() ) { + case ld::Atom::scopeTranslationUnit: printf("scope: translation unit\n"); break; - case ObjectFile::Atom::scopeLinkageUnit: + case ld::Atom::scopeLinkageUnit: printf("scope: linkage unit\n"); break; - case ObjectFile::Atom::scopeGlobal: + case ld::Atom::scopeGlobal: printf("scope: global\n"); break; default: @@ -240,23 +243,23 @@ static void dumpAtom(ObjectFile::Atom* atom) // kind if(!sPrintRestrict) - switch ( atom->getDefinitionKind() ) { - case ObjectFile::Atom::kRegularDefinition: + switch ( atom->definitionKind() ) { + case ld::Atom::kRegularDefinition: printf("kind: regular\n"); break; - case ObjectFile::Atom::kWeakDefinition: + case ld::Atom::kWeakDefinition: printf("kind: weak\n"); break; - case ObjectFile::Atom::kTentativeDefinition: + case ld::Atom::kTentativeDefinition: printf("kind: tentative\n"); break; - case ObjectFile::Atom::kExternalDefinition: + case ld::Atom::kExternalDefinition: printf("kind: import\n"); break; - case ObjectFile::Atom::kExternalWeakDefinition: + case ld::Atom::kExternalWeakDefinition: printf("kind: weak import\n"); break; - case ObjectFile::Atom::kAbsoluteSymbol: + case ld::Atom::kAbsoluteSymbol: printf("kind: absolute symbol\n"); break; default: @@ -264,16 +267,14 @@ static void dumpAtom(ObjectFile::Atom* atom) } // segment and section - if(!sPrintRestrict && (atom->getSectionName() != NULL) ) - printf("section: %s,%s\n", atom->getSegment().getName(), atom->getSectionName()); + if(!sPrintRestrict && (atom->section().sectionName() != NULL) ) + printf("section: %s,%s\n", atom->section().segmentName(), atom->section().sectionName()); // attributes if(!sPrintRestrict) { printf("attrs: "); if ( atom->dontDeadStrip() ) printf("dont-dead-strip "); - if ( atom->isZeroFill() ) - printf("zero-fill "); if ( atom->isThumb() ) printf("thumb "); printf("\n"); @@ -281,20 +282,20 @@ static void dumpAtom(ObjectFile::Atom* atom) // size if(!sPrintRestrict) - printf("size: 0x%012llX\n", atom->getSize()); + printf("size: 0x%012llX\n", atom->size()); // alignment if(!sPrintRestrict || sPrintAlign) - printf("align: %u mod %u\n", atom->getAlignment().modulus, (1 << atom->getAlignment().powerOf2) ); + printf("align: %u mod %u\n", atom->alignment().modulus, (1 << atom->alignment().powerOf2) ); // content if (!sPrintRestrict && sDumpContent ) { - uint64_t size = atom->getSize(); + uint64_t size = atom->size(); if ( size < 4096 ) { uint8_t content[size]; atom->copyRawContent(content); printf("content: "); - if ( atom->getContentType() == ObjectFile::Atom::kCStringType ) { + if ( atom->contentType() == ld::Atom::typeCString ) { printf("\""); for (unsigned int i=0; i < size; ++i) { if(content[i]<'!' || content[i]>=127) @@ -316,12 +317,12 @@ static void dumpAtom(ObjectFile::Atom* atom) if(!sPrintRestrict) { if ( atom->beginUnwind() != atom->endUnwind() ) { printf("unwind encodings:\n"); - for (ObjectFile::UnwindInfo::iterator it = atom->beginUnwind(); it != atom->endUnwind(); ++it) { + for (ld::Atom::UnwindInfo::iterator it = atom->beginUnwind(); it != atom->endUnwind(); ++it) { printf("\t 0x%04X 0x%08X\n", it->startOffset, it->unwindInfo); } } } - +#if 0 // references if(!sPrintRestrict) { std::vector& references = atom->getReferences(); @@ -332,13 +333,12 @@ static void dumpAtom(ObjectFile::Atom* atom) printf(" %s\n", ref->getDescription()); } } - +#endif // line info if(!sPrintRestrict) { - std::vector* lineInfo = atom->getLineInfo(); - if ( (lineInfo != NULL) && (lineInfo->size() > 0) ) { - printf("line info: (%lu)\n", lineInfo->size()); - for (std::vector::iterator it = lineInfo->begin(); it != lineInfo->end(); ++it) { + if ( atom->beginLineInfo() != atom->endLineInfo() ) { + printf("line info:\n"); + for (ld::Atom::LineInfo::iterator it = atom->beginLineInfo(); it != atom->endLineInfo(); ++it) { printf(" offset 0x%04X, line %d, file %s\n", it->atomOffset, it->lineNumber, it->fileName); } } @@ -347,31 +347,711 @@ static void dumpAtom(ObjectFile::Atom* atom) if(!sPrintRestrict) printf("\n"); } - +#endif struct AtomSorter { - bool operator()(const ObjectFile::Atom* left, const ObjectFile::Atom* right) + bool operator()(const ld::Atom* left, const ld::Atom* right) { if ( left == right ) return false; - int name = strcmp(left->getDisplayName(), right->getDisplayName()); - if ( name == 0 ) - return (left->getSize() < right->getSize()); - else - return ( name < 0); + // first sort by segment name + int diff = strcmp(left->section().segmentName(), right->section().segmentName()); + if ( diff != 0 ) + return (diff > 0); + + // then sort by section name + diff = strcmp(left->section().sectionName(), right->section().sectionName()); + if ( diff != 0 ) + return (diff < 0); + + // then sort by atom name + diff = strcmp(left->name(), right->name()); + if ( diff != 0 ) + return (diff < 0); + + // if cstring, sort by content + if ( left->contentType() == ld::Atom::typeCString ) { + diff = strcmp((char*)left->rawContentPointer(), (char*)right->rawContentPointer()); + if ( diff != 0 ) + return (diff < 0); + } + else if ( left->section().type() == ld::Section::typeCStringPointer ) { + // if pointer to c-string sort by name + const char* leftString = NULL; + assert(left->fixupsBegin() != left->fixupsEnd()); + for (ld::Fixup::iterator fit = left->fixupsBegin(); fit != left->fixupsEnd(); ++fit) { + if ( fit->binding == ld::Fixup::bindingByContentBound ) { + const ld::Atom* cstringAtom = fit->u.target; + assert(cstringAtom->contentType() == ld::Atom::typeCString); + leftString = (char*)cstringAtom->rawContentPointer(); + } + } + const char* rightString = NULL; + assert(right->fixupsBegin() != right->fixupsEnd()); + for (ld::Fixup::iterator fit = right->fixupsBegin(); fit != right->fixupsEnd(); ++fit) { + if ( fit->binding == ld::Fixup::bindingByContentBound ) { + const ld::Atom* cstringAtom = fit->u.target; + assert(cstringAtom->contentType() == ld::Atom::typeCString); + rightString = (char*)cstringAtom->rawContentPointer(); + } + } + assert(leftString != NULL); + assert(rightString != NULL); + diff = strcmp(leftString, rightString); + if ( diff != 0 ) + return (diff < 0); + } + else if ( left->section().type() == ld::Section::typeLiteral4 ) { + // if literal sort by content + uint32_t leftValue = *(uint32_t*)left->rawContentPointer(); + uint32_t rightValue = *(uint32_t*)right->rawContentPointer(); + diff = (leftValue - rightValue); + if ( diff != 0 ) + return (diff < 0); + } + else if ( left->section().type() == ld::Section::typeCFI ) { + // if __he_frame sort by address + diff = (left->objectAddress() - right->objectAddress()); + if ( diff != 0 ) + return (diff < 0); + } + else if ( left->section().type() == ld::Section::typeNonLazyPointer ) { + // if non-lazy-pointer sort by name + const char* leftString = NULL; + assert(left->fixupsBegin() != left->fixupsEnd()); + for (ld::Fixup::iterator fit = left->fixupsBegin(); fit != left->fixupsEnd(); ++fit) { + if ( fit->binding == ld::Fixup::bindingByNameUnbound ) { + leftString = fit->u.name; + } + else if ( fit->binding == ld::Fixup::bindingDirectlyBound ) { + leftString = fit->u.target->name(); + } + } + const char* rightString = NULL; + assert(right->fixupsBegin() != right->fixupsEnd()); + for (ld::Fixup::iterator fit = right->fixupsBegin(); fit != right->fixupsEnd(); ++fit) { + if ( fit->binding == ld::Fixup::bindingByNameUnbound ) { + rightString = fit->u.name; + } + else if ( fit->binding == ld::Fixup::bindingDirectlyBound ) { + rightString = fit->u.target->name(); + } + } + assert(leftString != NULL); + assert(rightString != NULL); + diff = strcmp(leftString, rightString); + if ( diff != 0 ) + return (diff < 0); + } + + // else sort by size + return (left->size() < right->size()); } }; -static void dumpFile(ObjectFile::Reader* reader) +class dumper : public ld::File::AtomHandler +{ +public: + void dump(); + virtual void doAtom(const ld::Atom&); + virtual void doFile(const ld::File&) {} +private: + void dumpAtom(const ld::Atom& atom); + const char* scopeString(const ld::Atom&); + const char* definitionString(const ld::Atom&); + const char* combineString(const ld::Atom&); + const char* inclusionString(const ld::Atom&); + const char* attributeString(const ld::Atom&); + const char* makeName(const ld::Atom& atom); + const char* referenceTargetAtomName(const ld::Fixup* ref); + void dumpFixup(const ld::Fixup* ref); + + uint64_t addressOfFirstAtomInSection(const ld::Section&); + + std::vector _atoms; +}; + +const char* dumper::scopeString(const ld::Atom& atom) +{ + switch ( (ld::Atom::Scope)atom.scope() ) { + case ld::Atom::scopeTranslationUnit: + return "translation-unit"; + case ld::Atom::scopeLinkageUnit: + return "hidden"; + case ld::Atom::scopeGlobal: + if ( atom.autoHide() ) + return "global but automatically hidden"; + else + return "global"; + } + return "UNKNOWN"; +} + +const char* dumper::definitionString(const ld::Atom& atom) +{ + switch ( (ld::Atom::Definition)atom.definition() ) { + case ld::Atom::definitionRegular: + return "regular"; + case ld::Atom::definitionTentative: + return "tentative"; + case ld::Atom::definitionAbsolute: + return "absolute"; + case ld::Atom::definitionProxy: + return "proxy"; + } + return "UNKNOWN"; +} + +const char* dumper::combineString(const ld::Atom& atom) +{ + switch ( (ld::Atom::Combine)atom.combine() ) { + case ld::Atom::combineNever: + return "never"; + case ld::Atom::combineByName: + return "by-name"; + case ld::Atom::combineByNameAndContent: + return "by-name-and-content"; + case ld::Atom::combineByNameAndReferences: + return "by-name-and-references"; + } + return "UNKNOWN"; +} + +const char* dumper::inclusionString(const ld::Atom& atom) +{ + switch ( (ld::Atom::SymbolTableInclusion)atom.symbolTableInclusion() ) { + case ld::Atom::symbolTableNotIn: + return "not in"; + case ld::Atom::symbolTableNotInFinalLinkedImages: + return "not in final linked images"; + case ld::Atom::symbolTableIn: + return "in"; + case ld::Atom::symbolTableInAndNeverStrip: + return "in and never strip"; + case ld::Atom::symbolTableInAsAbsolute: + return "in as absolute"; + case ld::Atom::symbolTableInWithRandomAutoStripLabel: + return "in as random auto-strip label"; + } + return "UNKNOWN"; +} + + + +const char* dumper::attributeString(const ld::Atom& atom) +{ + static char buffer[256]; + buffer[0] = '\0'; + + if ( atom.dontDeadStrip() ) + strcat(buffer, "dont-dead-strip "); + + if ( atom.isThumb() ) + strcat(buffer, "thumb "); + + if ( atom.isAlias() ) + strcat(buffer, "alias "); + + if ( atom.contentType() == ld::Atom::typeResolver ) + strcat(buffer, "resolver "); + + return buffer; +} + +const char* dumper::makeName(const ld::Atom& atom) +{ + static char buffer[4096]; + strcpy(buffer, "???"); + switch ( atom.symbolTableInclusion() ) { + case ld::Atom::symbolTableNotIn: + if ( atom.contentType() == ld::Atom::typeCString ) { + strcpy(buffer, "cstring="); + strlcat(buffer, (char*)atom.rawContentPointer(), 4096); + } + else if ( atom.section().type() == ld::Section::typeLiteral4 ) { + char temp[16]; + strcpy(buffer, "literal4="); + uint32_t value = *(uint32_t*)atom.rawContentPointer(); + sprintf(temp, "0x%08X", value); + strcat(buffer, temp); + } + else if ( atom.section().type() == ld::Section::typeLiteral8 ) { + char temp[32]; + strcpy(buffer, "literal8="); + uint32_t value1 = *(uint32_t*)atom.rawContentPointer(); + uint32_t value2 = ((uint32_t*)atom.rawContentPointer())[1]; + sprintf(temp, "0x%08X%08X", value1, value2); + strcat(buffer, temp); + } + else if ( atom.section().type() == ld::Section::typeLiteral16 ) { + char temp[64]; + strcpy(buffer, "literal16="); + uint32_t value1 = *(uint32_t*)atom.rawContentPointer(); + uint32_t value2 = ((uint32_t*)atom.rawContentPointer())[1]; + uint32_t value3 = ((uint32_t*)atom.rawContentPointer())[2]; + uint32_t value4 = ((uint32_t*)atom.rawContentPointer())[3]; + sprintf(temp, "0x%08X%08X%08X%08X", value1, value2, value3, value4); + strcat(buffer, temp); + } + else if ( atom.section().type() == ld::Section::typeCStringPointer ) { + assert(atom.fixupsBegin() != atom.fixupsEnd()); + for (ld::Fixup::iterator fit = atom.fixupsBegin(); fit != atom.fixupsEnd(); ++fit) { + if ( fit->binding == ld::Fixup::bindingByContentBound ) { + const ld::Atom* cstringAtom = fit->u.target; + if ( (cstringAtom != NULL) && (cstringAtom->contentType() == ld::Atom::typeCString) ) { + strlcpy(buffer, atom.name(), 4096); + strlcat(buffer, "=", 4096); + strlcat(buffer, (char*)cstringAtom->rawContentPointer(), 4096); + } + } + } + } + else if ( atom.section().type() == ld::Section::typeNonLazyPointer ) { + assert(atom.fixupsBegin() != atom.fixupsEnd()); + for (ld::Fixup::iterator fit = atom.fixupsBegin(); fit != atom.fixupsEnd(); ++fit) { + if ( fit->binding == ld::Fixup::bindingByNameUnbound ) { + strcpy(buffer, "non-lazy-pointer-to:"); + strlcat(buffer, fit->u.name, 4096); + return buffer; + } + else if ( fit->binding == ld::Fixup::bindingDirectlyBound ) { + strcpy(buffer, "non-lazy-pointer-to-local:"); + strlcat(buffer, fit->u.target->name(), 4096); + return buffer; + } + } + strlcpy(buffer, atom.name(), 4096); + } + else { + uint64_t sectAddr = addressOfFirstAtomInSection(atom.section()); + sprintf(buffer, "%s@%s+0x%08llX", atom.name(), atom.section().sectionName(), atom.objectAddress()-sectAddr); + } + break; + case ld::Atom::symbolTableNotInFinalLinkedImages: + case ld::Atom::symbolTableIn: + case ld::Atom::symbolTableInAndNeverStrip: + case ld::Atom::symbolTableInAsAbsolute: + case ld::Atom::symbolTableInWithRandomAutoStripLabel: + strlcpy(buffer, atom.name(), 4096); + break; + } + return buffer; +} + +const char* dumper::referenceTargetAtomName(const ld::Fixup* ref) +{ + static char buffer[4096]; + switch ( ref->binding ) { + case ld::Fixup::bindingNone: + return "NO BINDING"; + case ld::Fixup::bindingByNameUnbound: + strcpy(buffer, "by-name("); + strlcat(buffer, ref->u.name, 4096); + strlcat(buffer, ")", 4096); + return buffer; + //return ref->u.name; + case ld::Fixup::bindingByContentBound: + strcpy(buffer, "by-content("); + strlcat(buffer, makeName(*ref->u.target), 4096); + strlcat(buffer, ")", 4096); + return buffer; + case ld::Fixup::bindingDirectlyBound: + strcpy(buffer, "direct("); + strlcat(buffer, makeName(*ref->u.target), 4096); + strlcat(buffer, ")", 4096); + return buffer; + case ld::Fixup::bindingsIndirectlyBound: + return "BOUND INDIRECTLY"; + } + return "BAD BINDING"; +} + + +void dumper::dumpFixup(const ld::Fixup* ref) +{ + if ( ref->weakImport ) { + printf("weak_import "); + } + switch ( (ld::Fixup::Kind)(ref->kind) ) { + case ld::Fixup::kindNone: + printf("none"); + break; + case ld::Fixup::kindNoneFollowOn: + printf("followed by %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindNoneGroupSubordinate: + printf("group subordinate %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindNoneGroupSubordinateFDE: + printf("group subordinate FDE %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindNoneGroupSubordinateLSDA: + printf("group subordinate LSDA %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindNoneGroupSubordinatePersonality: + printf("group subordinate personality %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindSetTargetAddress: + printf("%s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindSubtractTargetAddress: + printf(" - %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindAddAddend: + printf(" + 0x%llX", ref->u.addend); + break; + case ld::Fixup::kindSubtractAddend: + printf(" - 0x%llX", ref->u.addend); + break; + case ld::Fixup::kindSetTargetImageOffset: + printf("imageOffset(%s)", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindSetTargetSectionOffset: + printf("sectionOffset(%s)", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindStore8: + printf(", then store byte"); + break; + case ld::Fixup::kindStoreLittleEndian16: + printf(", then store 16-bit little endian"); + break; + case ld::Fixup::kindStoreLittleEndianLow24of32: + printf(", then store low 24-bit little endian"); + break; + case ld::Fixup::kindStoreLittleEndian32: + printf(", then store 32-bit little endian"); + break; + case ld::Fixup::kindStoreLittleEndian64: + printf(", then store 64-bit little endian"); + break; + case ld::Fixup::kindStoreBigEndian16: + printf(", then store 16-bit big endian"); + break; + case ld::Fixup::kindStoreBigEndianLow24of32: + printf(", then store low 24-bit big endian"); + break; + case ld::Fixup::kindStoreBigEndian32: + printf(", then store 32-bit big endian"); + break; + case ld::Fixup::kindStoreBigEndian64: + printf(", then store 64-bit big endian"); + break; + case ld::Fixup::kindStorePPCBranch24: + printf(", then store as PPC branch24"); + break; + case ld::Fixup::kindStorePPCBranch14: + printf(", then store as PPC branch14"); + break; + case ld::Fixup::kindStorePPCPicLow14: + printf(", then store as PPC low14 pic"); + break; + case ld::Fixup::kindStorePPCPicLow16: + printf(", then store as PPC low14 pic"); + break; + case ld::Fixup::kindStorePPCPicHigh16AddLow: + printf(", then store as PPC high16 pic"); + break; + case ld::Fixup::kindStorePPCAbsLow14: + printf(", then store as PPC low14 abs"); + break; + case ld::Fixup::kindStorePPCAbsLow16: + printf(", then store as PPC low14 abs"); + break; + case ld::Fixup::kindStorePPCAbsHigh16AddLow: + printf(", then store as PPC high16 abs"); + break; + case ld::Fixup::kindStorePPCAbsHigh16: + printf(", then store as PPC high16 abs, no carry"); + break; + case ld::Fixup::kindStoreX86BranchPCRel8: + printf(", then store as x86 8-bit pcrel branch"); + break; + case ld::Fixup::kindStoreX86BranchPCRel32: + printf(", then store as x86 32-bit pcrel branch"); + break; + case ld::Fixup::kindStoreX86PCRel8: + printf(", then store as x86 8-bit pcrel"); + break; + case ld::Fixup::kindStoreX86PCRel16: + printf(", then store as x86 16-bit pcrel"); + break; + case ld::Fixup::kindStoreX86PCRel32: + printf(", then store as x86 32-bit pcrel"); + break; + case ld::Fixup::kindStoreX86PCRel32_1: + printf(", then store as x86 32-bit pcrel from +1"); + break; + case ld::Fixup::kindStoreX86PCRel32_2: + printf(", then store as x86 32-bit pcrel from +2"); + break; + case ld::Fixup::kindStoreX86PCRel32_4: + printf(", then store as x86 32-bit pcrel from +4"); + break; + case ld::Fixup::kindStoreX86PCRel32GOTLoad: + printf(", then store as x86 32-bit pcrel GOT load"); + break; + case ld::Fixup::kindStoreX86PCRel32GOTLoadNowLEA: + printf(", then store as x86 32-bit pcrel GOT load -> LEA"); + break; + case ld::Fixup::kindStoreX86PCRel32GOT: + printf(", then store as x86 32-bit pcrel GOT access"); + break; + case ld::Fixup::kindStoreX86PCRel32TLVLoad: + printf(", then store as x86 32-bit pcrel TLV load"); + break; + case ld::Fixup::kindStoreX86PCRel32TLVLoadNowLEA: + printf(", then store as x86 32-bit pcrel TLV load"); + break; + case ld::Fixup::kindStoreX86Abs32TLVLoad: + printf(", then store as x86 32-bit absolute TLV load"); + break; + case ld::Fixup::kindStoreX86Abs32TLVLoadNowLEA: + printf(", then store as x86 32-bit absolute TLV load -> LEA"); + break; + case ld::Fixup::kindStoreARMBranch24: + printf(", then store as ARM 24-bit pcrel branch"); + break; + case ld::Fixup::kindStoreThumbBranch22: + printf(", then store as Thumb 22-bit pcrel branch"); + break; + case ld::Fixup::kindStoreARMLoad12: + printf(", then store as ARM 12-bit pcrel load"); + break; + case ld::Fixup::kindStoreARMLow16: + printf(", then store low-16 in ARM movw"); + break; + case ld::Fixup::kindStoreARMHigh16: + printf(", then store high-16 in ARM movt"); + break; + case ld::Fixup::kindStoreThumbLow16: + printf(", then store low-16 in Thumb movw"); + break; + case ld::Fixup::kindStoreThumbHigh16: + printf(", then store high-16 in Thumb movt"); + break; + case ld::Fixup::kindDtraceExtra: + printf("dtrace static probe extra info"); + break; + case ld::Fixup::kindStoreX86DtraceCallSiteNop: + printf("x86 dtrace static probe site"); + break; + case ld::Fixup::kindStoreX86DtraceIsEnableSiteClear: + printf("x86 dtrace static is-enabled site"); + break; + case ld::Fixup::kindStorePPCDtraceCallSiteNop: + printf("ppc dtrace static probe site"); + break; + case ld::Fixup::kindStorePPCDtraceIsEnableSiteClear: + printf("ppc dtrace static is-enabled site"); + break; + case ld::Fixup::kindStoreARMDtraceCallSiteNop: + printf("ARM dtrace static probe site"); + break; + case ld::Fixup::kindStoreARMDtraceIsEnableSiteClear: + printf("ARM dtrace static is-enabled site"); + break; + case ld::Fixup::kindStoreThumbDtraceCallSiteNop: + printf("Thumb dtrace static probe site"); + break; + case ld::Fixup::kindStoreThumbDtraceIsEnableSiteClear: + printf("Thumb dtrace static is-enabled site"); + break; + case ld::Fixup::kindLazyTarget: + printf("lazy reference to external symbol %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindSetLazyOffset: + printf("offset of lazy binding info for %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindStoreTargetAddressLittleEndian32: + printf("store 32-bit little endian address of %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindStoreTargetAddressLittleEndian64: + printf("store 64-bit little endian address of %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindStoreTargetAddressBigEndian32: + printf("store 32-bit big endian address of %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindStoreTargetAddressBigEndian64: + printf("store 64-bit big endian address of %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindStoreTargetAddressX86PCRel32: + printf("x86 store 32-bit pc-rel address of %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindStoreTargetAddressX86BranchPCRel32: + printf("x86 store 32-bit pc-rel branch to %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad: + printf("x86 store 32-bit pc-rel GOT load of %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoadNowLEA: + printf("x86 store 32-bit pc-rel lea of %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad: + printf("x86 store 32-bit pc-rel TLV load of %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoadNowLEA: + printf("x86 store 32-bit pc-rel TLV lea of %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoad: + printf("x86 store 32-bit absolute TLV load of %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoadNowLEA: + printf("x86 store 32-bit absolute TLV lea of %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindStoreTargetAddressARMBranch24: + printf("ARM store 24-bit pc-rel branch to %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindStoreTargetAddressThumbBranch22: + printf("Thumb store 22-bit pc-rel branch to %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindStoreTargetAddressARMLoad12: + printf("ARM store 12-bit pc-rel branch to %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindStoreTargetAddressPPCBranch24: + printf("PowerPC store 24-bit pc-rel load of %s", referenceTargetAtomName(ref)); + break; + case ld::Fixup::kindSetTargetTLVTemplateOffset: + case ld::Fixup::kindSetTargetTLVTemplateOffsetLittleEndian32: + case ld::Fixup::kindSetTargetTLVTemplateOffsetLittleEndian64: + printf("tlv template offset of %s", referenceTargetAtomName(ref)); + //default: + // printf("unknown fixup"); + // break; + } +} + +uint64_t dumper::addressOfFirstAtomInSection(const ld::Section& sect) +{ + uint64_t lowestAddr = (uint64_t)(-1); + for (std::vector::iterator it=_atoms.begin(); it != _atoms.end(); ++it) { + const ld::Atom* atom = *it; + if ( &atom->section() == § ) { + if ( atom->objectAddress() < lowestAddr ) + lowestAddr = atom->objectAddress(); + } + } + return lowestAddr; +} + +void dumper::doAtom(const ld::Atom& atom) +{ + if ( (sMatchName != NULL) && (strcmp(sMatchName, atom.name()) != 0) ) + return; + _atoms.push_back(&atom); +} + +void dumper::dump() +{ + if ( sSort ) + std::sort(_atoms.begin(), _atoms.end(), AtomSorter()); + + for (std::vector::iterator it=_atoms.begin(); it != _atoms.end(); ++it) { + this->dumpAtom(**it); + } +} + +void dumper::dumpAtom(const ld::Atom& atom) +{ + printf("name: %s\n", makeName(atom)); + printf("size: 0x%0llX\n", atom.size()); + printf("align: %u mod %u\n", atom.alignment().modulus, (1 << atom.alignment().powerOf2) ); + printf("scope: %s\n", scopeString(atom)); + if ( sShowDefinitionKind ) + printf("def: %s\n", definitionString(atom)); + if ( sShowCombineKind ) + printf("combine: %s\n", combineString(atom)); + printf("symbol: %s\n", inclusionString(atom)); + printf("attrs: %s\n", attributeString(atom)); + if ( sShowSection ) + printf("section: %s,%s\n", atom.section().segmentName(), atom.section().sectionName()); + if ( atom.beginUnwind() != atom.endUnwind() ) { + printf("unwind: 0x%08X\n", atom.beginUnwind()->unwindInfo); + } + if ( atom.contentType() == ld::Atom::typeCString ) { + uint8_t buffer[atom.size()+2]; + atom.copyRawContent(buffer); + buffer[atom.size()] = '\0'; + printf("content: \"%s\"\n", buffer); + } + if ( atom.fixupsBegin() != atom.fixupsEnd() ) { + printf("fixups:\n"); + for (unsigned int off=0; off < atom.size()+1; ++off) { + for (ld::Fixup::iterator it = atom.fixupsBegin(); it != atom.fixupsEnd(); ++it) { + if ( it->offsetInAtom == off ) { + switch ( it->clusterSize ) { + case ld::Fixup::k1of1: + printf(" 0x%04X ", it->offsetInAtom); + dumpFixup(it); + break; + case ld::Fixup::k1of2: + printf(" 0x%04X ", it->offsetInAtom); + dumpFixup(it); + ++it; + dumpFixup(it); + break; + case ld::Fixup::k1of3: + printf(" 0x%04X ", it->offsetInAtom); + dumpFixup(it); + ++it; + dumpFixup(it); + ++it; + dumpFixup(it); + break; + case ld::Fixup::k1of4: + printf(" 0x%04X ", it->offsetInAtom); + dumpFixup(it); + ++it; + dumpFixup(it); + ++it; + dumpFixup(it); + ++it; + dumpFixup(it); + break; + case ld::Fixup::k1of5: + printf(" 0x%04X ", it->offsetInAtom); + dumpFixup(it); + ++it; + dumpFixup(it); + ++it; + dumpFixup(it); + ++it; + dumpFixup(it); + ++it; + dumpFixup(it); + break; + default: + printf(" BAD CLUSTER SIZE: cluster=%d\n", it->clusterSize); + } + printf("\n"); + } + } + } + } + if ( atom.beginLineInfo() != atom.endLineInfo() ) { + printf("line info:\n"); + for (ld::Atom::LineInfo::iterator it = atom.beginLineInfo(); it != atom.endLineInfo(); ++it) { + printf(" offset 0x%04X, line %d, file %s\n", it->atomOffset, it->lineNumber, it->fileName); + } + } + + printf("\n"); +} + +static void dumpFile(ld::relocatable::File* file) { // stabs debug info - if ( sDumpStabs && (reader->getDebugInfoKind() == ObjectFile::Reader::kDebugInfoStabs) ) { - std::vector* stabs = reader->getStabs(); + if ( sDumpStabs && (file->debugInfo() == ld::relocatable::File::kDebugInfoStabs) ) { + const std::vector* stabs = file->stabs(); if ( stabs != NULL ) dumpStabs(stabs); } - + // dump atoms + dumper d; + file->forEachAtom(d); + d.dump(); + +#if 0 // get all atoms std::vector atoms = reader->getAtoms(); @@ -386,10 +1066,11 @@ static void dumpFile(ObjectFile::Reader* reader) else dumpAtom(*it); } +#endif } -static ObjectFile::Reader* createReader(const char* path, const ObjectFile::ReaderOptions& options) +static ld::relocatable::File* createReader(const char* path) { struct stat stat_buf; @@ -399,34 +1080,61 @@ static ObjectFile::Reader* createReader(const char* path, const ObjectFile::Read ::fstat(fd, &stat_buf); uint8_t* p = (uint8_t*)::mmap(NULL, stat_buf.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0); ::close(fd); + if ( p == (uint8_t*)(-1) ) + throwf("cannot mmap file: %s", path); const mach_header* mh = (mach_header*)p; + uint64_t fileLen = stat_buf.st_size; + bool foundFatSlice = false; if ( mh->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) { const struct fat_header* fh = (struct fat_header*)p; const struct fat_arch* archs = (struct fat_arch*)(p + sizeof(struct fat_header)); for (unsigned long i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) { if ( OSSwapBigToHostInt32(archs[i].cputype) == (uint32_t)sPreferredArch ) { - p = p + OSSwapBigToHostInt32(archs[i].offset); - mh = (struct mach_header*)p; + if ( ((uint32_t)sPreferredSubArch == 0xFFFFFFFF) || ((uint32_t)sPreferredSubArch == OSSwapBigToHostInt32(archs[i].cpusubtype)) ) { + p = p + OSSwapBigToHostInt32(archs[i].offset); + mh = (struct mach_header*)p; + fileLen = OSSwapBigToHostInt32(archs[i].size); + foundFatSlice = true; + break; + } } } } - if ( mach_o::relocatable::Reader::validFile(p) ) - return new mach_o::relocatable::Reader::Reader(p, path, 0, options, 0); - else if ( mach_o::relocatable::Reader::validFile(p) ) - return new mach_o::relocatable::Reader::Reader(p, path, 0, options, 0); - else if ( mach_o::relocatable::Reader::validFile(p) ) - return new mach_o::relocatable::Reader::Reader(p, path, 0, options, 0); - else if ( mach_o::relocatable::Reader::validFile(p) ) - return new mach_o::relocatable::Reader::Reader(p, path, 0, options, 0); - else if ( mach_o::relocatable::Reader::validFile(p) ) - return new mach_o::relocatable::Reader::Reader(p, path, 0, options, 0); -#if LTO_SUPPORT - if ( lto::Reader::validFile(p, stat_buf.st_size, 0) ) { - return new lto::Reader(p, stat_buf.st_size, path, 0, options, 0); + + mach_o::relocatable::ParserOptions objOpts; + objOpts.architecture = sPreferredArch; + objOpts.objSubtypeMustMatch = false; + objOpts.logAllFiles = false; + objOpts.convertUnwindInfo = true; + objOpts.subType = sPreferredSubArch; +#if 1 + if ( ! foundFatSlice ) { + cpu_type_t archOfObj; + cpu_subtype_t subArchOfObj; + if ( mach_o::relocatable::isObjectFile(p, &archOfObj, &subArchOfObj) ) { + objOpts.architecture = archOfObj; + objOpts.subType = subArchOfObj; + } } -#endif - + + ld::relocatable::File* objResult = mach_o::relocatable::parse(p, fileLen, path, stat_buf.st_mtime, 0, objOpts); + if ( objResult != NULL ) + return objResult; + + // see if it is an llvm object file + objResult = lto::parse(p, fileLen, path, stat_buf.st_mtime, 0, sPreferredArch, sPreferredSubArch, false); + if ( objResult != NULL ) + return objResult; + throwf("not a mach-o object file: %s", path); +#else + // for peformance testing + for (int i=0; i < 500; ++i ) { + ld::relocatable::File* objResult = mach_o::relocatable::parse(p, fileLen, path, stat_buf.st_mtime, 0, objOpts); + delete objResult; + } + exit(0); +#endif } static @@ -435,6 +1143,9 @@ usage() { fprintf(stderr, "ObjectDump options:\n" "\t-no_content\tdon't dump contents\n" + "\t-no_section\tdon't dump section name\n" + "\t-no_defintion\tdon't dump definition kind\n" + "\t-no_combine\tdon't dump combine mode\n" "\t-stabs\t\tdump stabs\n" "\t-arch aaa\tonly dump info about arch aaa\n" "\t-only sym\tonly dump info about sym\n" @@ -450,8 +1161,6 @@ int main(int argc, const char* argv[]) return 0; } - ObjectFile::ReaderOptions options; - options.fAddCompactUnwindEncoding = true; try { for(int i=1; i < argc; ++i) { const char* arg = argv[i]; @@ -468,6 +1177,15 @@ int main(int argc, const char* argv[]) else if ( strcmp(arg, "-no_sort") == 0 ) { sSort = false; } + else if ( strcmp(arg, "-no_section") == 0 ) { + sShowSection = false; + } + else if ( strcmp(arg, "-no_definition") == 0 ) { + sShowDefinitionKind = false; + } + else if ( strcmp(arg, "-no_combine") == 0 ) { + sShowCombineKind = false; + } else if ( strcmp(arg, "-arch") == 0 ) { const char* arch = ++i