/* -*- 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@
*
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
-#include <fcntl.h>
-
-#include "MachOReaderRelocatable.hpp"
+#include <mach-o/nlist.h>
+#include <mach-o/stab.h>
+#include <mach-o/fat.h>
+#include <mach-o/loader.h>
-#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, ...)
{
fprintf(stderr, "\n");
}
-static void dumpStabs(std::vector<ObjectFile::Reader::Stab>* stabs)
+static void dumpStabs(const std::vector<ld::relocatable::File::Stab>* stabs)
{
// debug info
printf("stabs: (%lu)\n", stabs->size());
- for (std::vector<ObjectFile::Reader::Stab>::iterator it = stabs->begin(); it != stabs->end(); ++it ) {
- ObjectFile::Reader::Stab& stab = *it;
+ for (std::vector<ld::relocatable::File::Stab>::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:
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:
}
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:
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:
// 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:
}
// 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");
// 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)
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<ObjectFile::Reference*>& references = atom->getReferences();
printf(" %s\n", ref->getDescription());
}
}
-
+#endif
// line info
if(!sPrintRestrict) {
- std::vector<ObjectFile::LineInfo>* lineInfo = atom->getLineInfo();
- if ( (lineInfo != NULL) && (lineInfo->size() > 0) ) {
- printf("line info: (%lu)\n", lineInfo->size());
- for (std::vector<ObjectFile::LineInfo>::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);
}
}
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<const ld::Atom*> _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<const ld::Atom*>::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<const ld::Atom*>::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<ObjectFile::Reader::Stab>* stabs = reader->getStabs();
+ if ( sDumpStabs && (file->debugInfo() == ld::relocatable::File::kDebugInfoStabs) ) {
+ const std::vector<ld::relocatable::File::Stab>* stabs = file->stabs();
if ( stabs != NULL )
dumpStabs(stabs);
}
-
+ // dump atoms
+ dumper d;
+ file->forEachAtom(d);
+ d.dump();
+
+#if 0
// get all atoms
std::vector<ObjectFile::Atom*> atoms = reader->getAtoms();
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;
::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<x86>::validFile(p) )
- return new mach_o::relocatable::Reader<x86>::Reader(p, path, 0, options, 0);
- else if ( mach_o::relocatable::Reader<ppc>::validFile(p) )
- return new mach_o::relocatable::Reader<ppc>::Reader(p, path, 0, options, 0);
- else if ( mach_o::relocatable::Reader<ppc64>::validFile(p) )
- return new mach_o::relocatable::Reader<ppc64>::Reader(p, path, 0, options, 0);
- else if ( mach_o::relocatable::Reader<x86_64>::validFile(p) )
- return new mach_o::relocatable::Reader<x86_64>::Reader(p, path, 0, options, 0);
- else if ( mach_o::relocatable::Reader<arm>::validFile(p) )
- return new mach_o::relocatable::Reader<arm>::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
{
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"
return 0;
}
- ObjectFile::ReaderOptions options;
- options.fAddCompactUnwindEncoding = true;
try {
for(int i=1; i < argc; ++i) {
const char* arg = argv[i];
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<argc? argv[i]: "";
if ( strcmp(arch, "ppc64") == 0 )
sPreferredArch = CPU_TYPE_X86_64;
else if ( strcmp(arch, "arm") == 0 )
sPreferredArch = CPU_TYPE_ARM;
- else if ( strcmp(arch, "armv6") == 0 )
+ else if ( strcmp(arch, "armv4t") == 0 ) {
+ sPreferredArch = CPU_TYPE_ARM;
+ sPreferredSubArch = CPU_SUBTYPE_ARM_V4T;
+ }
+ else if ( strcmp(arch, "armv5") == 0 ) {
+ sPreferredArch = CPU_TYPE_ARM;
+ sPreferredSubArch = CPU_SUBTYPE_ARM_V5TEJ;
+ }
+ else if ( strcmp(arch, "armv6") == 0 ) {
+ sPreferredArch = CPU_TYPE_ARM;
+ sPreferredSubArch = CPU_SUBTYPE_ARM_V6;
+ }
+ else if ( strcmp(arch, "armv7") == 0 ) {
sPreferredArch = CPU_TYPE_ARM;
+ sPreferredSubArch = CPU_SUBTYPE_ARM_V7;
+ }
else
throwf("unknown architecture %s", arch);
}
}
}
else {
- ObjectFile::Reader* reader = createReader(arg, options);
+ ld::relocatable::File* reader = createReader(arg);
dumpFile(reader);
}
}