#include "Error.h"
#include "ObjDumper.h"
#include "StreamWriter.h"
-
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Object/MachO.h"
#include "llvm/Support/Casting.h"
class MachODumper : public ObjDumper {
public:
- MachODumper(const llvm::object::MachOObjectFileBase *Obj, StreamWriter& Writer)
+ MachODumper(const MachOObjectFile *Obj, StreamWriter& Writer)
: ObjDumper(Writer)
, Obj(Obj) { }
- virtual void printFileHeaders() LLVM_OVERRIDE;
- virtual void printSections() LLVM_OVERRIDE;
- virtual void printRelocations() LLVM_OVERRIDE;
- virtual void printSymbols() LLVM_OVERRIDE;
- virtual void printDynamicSymbols() LLVM_OVERRIDE;
- virtual void printUnwindInfo() LLVM_OVERRIDE;
+ void printFileHeaders() override;
+ void printSections() override;
+ void printRelocations() override;
+ void printSymbols() override;
+ void printDynamicSymbols() override;
+ void printUnwindInfo() override;
private:
- void printSymbol(symbol_iterator SymI);
+ void printSymbol(const SymbolRef &Symbol);
+
+ void printRelocation(const RelocationRef &Reloc);
- void printRelocation(section_iterator SecI, relocation_iterator RelI);
+ void printRelocation(const MachOObjectFile *Obj, const RelocationRef &Reloc);
- const llvm::object::MachOObjectFileBase *Obj;
+ void printSections(const MachOObjectFile *Obj);
+
+ const MachOObjectFile *Obj;
};
} // namespace
namespace llvm {
-error_code createMachODumper(const object::ObjectFile *Obj,
- StreamWriter& Writer,
- OwningPtr<ObjDumper> &Result) {
- const MachOObjectFileBase *MachOObj = dyn_cast<MachOObjectFileBase>(Obj);
+std::error_code createMachODumper(const object::ObjectFile *Obj,
+ StreamWriter &Writer,
+ std::unique_ptr<ObjDumper> &Result) {
+ const MachOObjectFile *MachOObj = dyn_cast<MachOObjectFile>(Obj);
if (!MachOObj)
return readobj_error::unsupported_obj_file_format;
static const EnumEntry<unsigned> MachOSymbolTypes[] = {
{ "Undef", 0x0 },
- { "External", 0x1 },
{ "Abs", 0x2 },
{ "Indirect", 0xA },
{ "PreboundUndef", 0xC },
- { "Section", 0xE },
- { "PrivateExternal", 0x10 }
+ { "Section", 0xE }
};
namespace {
- enum {
- N_STAB = 0xE0
- };
-
struct MachOSection {
ArrayRef<char> Name;
ArrayRef<char> SegmentName;
};
}
-static void getSection(const MachOObjectFileBase *Obj,
- DataRefImpl DRI,
+static void getSection(const MachOObjectFile *Obj,
+ DataRefImpl Sec,
MachOSection &Section) {
- if (const MachOObjectFile64Le *O = dyn_cast<MachOObjectFile64Le>(Obj)) {
- const MachOObjectFile64Le::Section *Sect = O->getSection(DRI);
-
- Section.Address = Sect->Address;
- Section.Size = Sect->Size;
- Section.Offset = Sect->Offset;
- Section.Alignment = Sect->Align;
- Section.RelocationTableOffset = Sect->RelocationTableOffset;
- Section.NumRelocationTableEntries = Sect->NumRelocationTableEntries;
- Section.Flags = Sect->Flags;
- Section.Reserved1 = Sect->Reserved1;
- Section.Reserved2 = Sect->Reserved2;
- } else {
- const MachOObjectFile32Le *O2 = cast<MachOObjectFile32Le>(Obj);
- const MachOObjectFile32Le::Section *Sect = O2->getSection(DRI);
-
- Section.Address = Sect->Address;
- Section.Size = Sect->Size;
- Section.Offset = Sect->Offset;
- Section.Alignment = Sect->Align;
- Section.RelocationTableOffset = Sect->RelocationTableOffset;
- Section.NumRelocationTableEntries = Sect->NumRelocationTableEntries;
- Section.Flags = Sect->Flags;
- Section.Reserved1 = Sect->Reserved1;
- Section.Reserved2 = Sect->Reserved2;
+ if (!Obj->is64Bit()) {
+ MachO::section Sect = Obj->getSection(Sec);
+ Section.Address = Sect.addr;
+ Section.Size = Sect.size;
+ Section.Offset = Sect.offset;
+ Section.Alignment = Sect.align;
+ Section.RelocationTableOffset = Sect.reloff;
+ Section.NumRelocationTableEntries = Sect.nreloc;
+ Section.Flags = Sect.flags;
+ Section.Reserved1 = Sect.reserved1;
+ Section.Reserved2 = Sect.reserved2;
+ return;
}
+ MachO::section_64 Sect = Obj->getSection64(Sec);
+ Section.Address = Sect.addr;
+ Section.Size = Sect.size;
+ Section.Offset = Sect.offset;
+ Section.Alignment = Sect.align;
+ Section.RelocationTableOffset = Sect.reloff;
+ Section.NumRelocationTableEntries = Sect.nreloc;
+ Section.Flags = Sect.flags;
+ Section.Reserved1 = Sect.reserved1;
+ Section.Reserved2 = Sect.reserved2;
}
-static void getSymbol(const MachOObjectFileBase *Obj,
+
+static void getSymbol(const MachOObjectFile *Obj,
DataRefImpl DRI,
MachOSymbol &Symbol) {
- if (const MachOObjectFile64Le *O = dyn_cast<MachOObjectFile64Le>(Obj)) {
- const MachOObjectFile64Le::SymbolTableEntry *Entry =
- O->getSymbolTableEntry(DRI);
- Symbol.StringIndex = Entry->StringIndex;
- Symbol.Type = Entry->Type;
- Symbol.SectionIndex = Entry->SectionIndex;
- Symbol.Flags = Entry->Flags;
- Symbol.Value = Entry->Value;
- } else {
- const MachOObjectFile32Le *O2 = cast<MachOObjectFile32Le>(Obj);
- const MachOObjectFile32Le::SymbolTableEntry *Entry =
- O2->getSymbolTableEntry(DRI);
- Symbol.StringIndex = Entry->StringIndex;
- Symbol.Type = Entry->Type;
- Symbol.SectionIndex = Entry->SectionIndex;
- Symbol.Flags = Entry->Flags;
- Symbol.Value = Entry->Value;
+ if (!Obj->is64Bit()) {
+ MachO::nlist Entry = Obj->getSymbolTableEntry(DRI);
+ Symbol.StringIndex = Entry.n_strx;
+ Symbol.Type = Entry.n_type;
+ Symbol.SectionIndex = Entry.n_sect;
+ Symbol.Flags = Entry.n_desc;
+ Symbol.Value = Entry.n_value;
+ return;
}
+ MachO::nlist_64 Entry = Obj->getSymbol64TableEntry(DRI);
+ Symbol.StringIndex = Entry.n_strx;
+ Symbol.Type = Entry.n_type;
+ Symbol.SectionIndex = Entry.n_sect;
+ Symbol.Flags = Entry.n_desc;
+ Symbol.Value = Entry.n_value;
}
void MachODumper::printFileHeaders() {
}
void MachODumper::printSections() {
+ return printSections(Obj);
+}
+
+void MachODumper::printSections(const MachOObjectFile *Obj) {
ListScope Group(W, "Sections");
int SectionIndex = -1;
- error_code EC;
- for (section_iterator SecI = Obj->begin_sections(),
- SecE = Obj->end_sections();
- SecI != SecE; SecI.increment(EC)) {
- if (error(EC)) break;
-
+ for (const SectionRef &Section : Obj->sections()) {
++SectionIndex;
- MachOSection Section;
- getSection(Obj, SecI->getRawDataRefImpl(), Section);
- DataRefImpl DR = SecI->getRawDataRefImpl();
+ MachOSection MOSection;
+ getSection(Obj, Section.getRawDataRefImpl(), MOSection);
+ DataRefImpl DR = Section.getRawDataRefImpl();
StringRef Name;
- if (error(SecI->getName(Name)))
- Name = "";
+ if (error(Section.getName(Name)))
+ Name = "";
ArrayRef<char> RawName = Obj->getSectionRawName(DR);
StringRef SegmentName = Obj->getSectionFinalSegmentName(DR);
W.printNumber("Index", SectionIndex);
W.printBinary("Name", Name, RawName);
W.printBinary("Segment", SegmentName, RawSegmentName);
- W.printHex ("Address", Section.Address);
- W.printHex ("Size", Section.Size);
- W.printNumber("Offset", Section.Offset);
- W.printNumber("Alignment", Section.Alignment);
- W.printHex ("RelocationOffset", Section.RelocationTableOffset);
- W.printNumber("RelocationCount", Section.NumRelocationTableEntries);
- W.printEnum ("Type", Section.Flags & 0xFF,
- makeArrayRef(MachOSectionAttributes));
- W.printFlags ("Attributes", Section.Flags >> 8,
- makeArrayRef(MachOSectionAttributes));
- W.printHex ("Reserved1", Section.Reserved1);
- W.printHex ("Reserved2", Section.Reserved2);
+ W.printHex("Address", MOSection.Address);
+ W.printHex("Size", MOSection.Size);
+ W.printNumber("Offset", MOSection.Offset);
+ W.printNumber("Alignment", MOSection.Alignment);
+ W.printHex("RelocationOffset", MOSection.RelocationTableOffset);
+ W.printNumber("RelocationCount", MOSection.NumRelocationTableEntries);
+ W.printEnum("Type", MOSection.Flags & 0xFF,
+ makeArrayRef(MachOSectionAttributes));
+ W.printFlags("Attributes", MOSection.Flags >> 8,
+ makeArrayRef(MachOSectionAttributes));
+ W.printHex("Reserved1", MOSection.Reserved1);
+ W.printHex("Reserved2", MOSection.Reserved2);
if (opts::SectionRelocations) {
ListScope D(W, "Relocations");
- for (relocation_iterator RelI = SecI->begin_relocations(),
- RelE = SecI->end_relocations();
- RelI != RelE; RelI.increment(EC)) {
- if (error(EC)) break;
-
- printRelocation(SecI, RelI);
- }
+ for (const RelocationRef &Reloc : Section.relocations())
+ printRelocation(Reloc);
}
if (opts::SectionSymbols) {
ListScope D(W, "Symbols");
- for (symbol_iterator SymI = Obj->begin_symbols(),
- SymE = Obj->end_symbols();
- SymI != SymE; SymI.increment(EC)) {
- if (error(EC)) break;
-
+ for (const SymbolRef &Symbol : Obj->symbols()) {
bool Contained = false;
- if (SecI->containsSymbol(*SymI, Contained) || !Contained)
+ if (Section.containsSymbol(Symbol, Contained) || !Contained)
continue;
- printSymbol(SymI);
+ printSymbol(Symbol);
}
}
if (opts::SectionData) {
- StringRef Data;
- if (error(SecI->getContents(Data))) break;
-
- W.printBinaryBlock("SectionData", Data);
+ bool IsBSS;
+ if (error(Section.isBSS(IsBSS)))
+ break;
+ if (!IsBSS) {
+ StringRef Data;
+ if (error(Section.getContents(Data)))
+ break;
+
+ W.printBinaryBlock("SectionData", Data);
+ }
}
}
}
void MachODumper::printRelocations() {
ListScope D(W, "Relocations");
- error_code EC;
- for (section_iterator SecI = Obj->begin_sections(),
- SecE = Obj->end_sections();
- SecI != SecE; SecI.increment(EC)) {
- if (error(EC)) break;
-
+ std::error_code EC;
+ for (const SectionRef &Section : Obj->sections()) {
StringRef Name;
- if (error(SecI->getName(Name)))
+ if (error(Section.getName(Name)))
continue;
bool PrintedGroup = false;
- for (relocation_iterator RelI = SecI->begin_relocations(),
- RelE = SecI->end_relocations();
- RelI != RelE; RelI.increment(EC)) {
- if (error(EC)) break;
-
+ for (const RelocationRef &Reloc : Section.relocations()) {
if (!PrintedGroup) {
W.startLine() << "Section " << Name << " {\n";
W.indent();
PrintedGroup = true;
}
- printRelocation(SecI, RelI);
+ printRelocation(Reloc);
}
if (PrintedGroup) {
}
}
-void MachODumper::printRelocation(section_iterator SecI,
- relocation_iterator RelI) {
+void MachODumper::printRelocation(const RelocationRef &Reloc) {
+ return printRelocation(Obj, Reloc);
+}
+
+void MachODumper::printRelocation(const MachOObjectFile *Obj,
+ const RelocationRef &Reloc) {
uint64_t Offset;
SmallString<32> RelocName;
- int64_t Info;
- StringRef SymbolName;
- SymbolRef Symbol;
- if (error(RelI->getOffset(Offset))) return;
- if (error(RelI->getTypeName(RelocName))) return;
- if (error(RelI->getAdditionalInfo(Info))) return;
- if (error(RelI->getSymbol(Symbol))) return;
- if (error(Symbol.getName(SymbolName))) return;
-
- raw_ostream& OS = W.startLine();
- OS << W.hex(Offset)
- << " " << RelocName
- << " " << (SymbolName.size() > 0 ? SymbolName : "-")
- << " " << W.hex(Info)
- << "\n";
+ if (error(Reloc.getOffset(Offset)))
+ return;
+ if (error(Reloc.getTypeName(RelocName)))
+ return;
+
+ DataRefImpl DR = Reloc.getRawDataRefImpl();
+ MachO::any_relocation_info RE = Obj->getRelocation(DR);
+ bool IsScattered = Obj->isRelocationScattered(RE);
+ SmallString<32> SymbolNameOrOffset("0x");
+ if (IsScattered) {
+ // Scattered relocations don't really have an associated symbol
+ // for some reason, even if one exists in the symtab at the correct address.
+ SymbolNameOrOffset += utohexstr(Obj->getScatteredRelocationValue(RE));
+ } else {
+ symbol_iterator Symbol = Reloc.getSymbol();
+ if (Symbol != Obj->symbol_end()) {
+ StringRef SymbolName;
+ if (error(Symbol->getName(SymbolName)))
+ return;
+ SymbolNameOrOffset = SymbolName;
+ } else
+ SymbolNameOrOffset += utohexstr(Obj->getPlainRelocationSymbolNum(RE));
+ }
+
+ if (opts::ExpandRelocs) {
+ DictScope Group(W, "Relocation");
+ W.printHex("Offset", Offset);
+ W.printNumber("PCRel", Obj->getAnyRelocationPCRel(RE));
+ W.printNumber("Length", Obj->getAnyRelocationLength(RE));
+ if (IsScattered)
+ W.printString("Extern", StringRef("N/A"));
+ else
+ W.printNumber("Extern", Obj->getPlainRelocationExternal(RE));
+ W.printNumber("Type", RelocName, Obj->getAnyRelocationType(RE));
+ W.printString("Symbol", SymbolNameOrOffset);
+ W.printNumber("Scattered", IsScattered);
+ } else {
+ raw_ostream& OS = W.startLine();
+ OS << W.hex(Offset)
+ << " " << Obj->getAnyRelocationPCRel(RE)
+ << " " << Obj->getAnyRelocationLength(RE);
+ if (IsScattered)
+ OS << " n/a";
+ else
+ OS << " " << Obj->getPlainRelocationExternal(RE);
+ OS << " " << RelocName
+ << " " << IsScattered
+ << " " << SymbolNameOrOffset
+ << "\n";
+ }
}
void MachODumper::printSymbols() {
ListScope Group(W, "Symbols");
- error_code EC;
- for (symbol_iterator SymI = Obj->begin_symbols(),
- SymE = Obj->end_symbols();
- SymI != SymE; SymI.increment(EC)) {
- if (error(EC)) break;
-
- printSymbol(SymI);
+ for (const SymbolRef &Symbol : Obj->symbols()) {
+ printSymbol(Symbol);
}
}
ListScope Group(W, "DynamicSymbols");
}
-void MachODumper::printSymbol(symbol_iterator SymI) {
- error_code EC;
-
+void MachODumper::printSymbol(const SymbolRef &Symbol) {
StringRef SymbolName;
- if (SymI->getName(SymbolName))
+ if (Symbol.getName(SymbolName))
SymbolName = "";
- MachOSymbol Symbol;
- getSymbol(Obj, SymI->getRawDataRefImpl(), Symbol);
+ MachOSymbol MOSymbol;
+ getSymbol(Obj, Symbol.getRawDataRefImpl(), MOSymbol);
- StringRef SectionName;
- section_iterator SecI(Obj->end_sections());
- if (error(SymI->getSection(SecI)) ||
- error(SecI->getName(SectionName)))
- SectionName = "";
+ StringRef SectionName = "";
+ section_iterator SecI(Obj->section_begin());
+ if (!error(Symbol.getSection(SecI)) && SecI != Obj->section_end())
+ error(SecI->getName(SectionName));
DictScope D(W, "Symbol");
- W.printNumber("Name", SymbolName, Symbol.StringIndex);
- if (Symbol.Type & N_STAB) {
- W.printHex ("Type", "SymDebugTable", Symbol.Type);
+ W.printNumber("Name", SymbolName, MOSymbol.StringIndex);
+ if (MOSymbol.Type & MachO::N_STAB) {
+ W.printHex("Type", "SymDebugTable", MOSymbol.Type);
} else {
- W.printEnum("Type", Symbol.Type, makeArrayRef(MachOSymbolTypes));
+ if (MOSymbol.Type & MachO::N_PEXT)
+ W.startLine() << "PrivateExtern\n";
+ if (MOSymbol.Type & MachO::N_EXT)
+ W.startLine() << "Extern\n";
+ W.printEnum("Type", uint8_t(MOSymbol.Type & MachO::N_TYPE),
+ makeArrayRef(MachOSymbolTypes));
}
- W.printHex ("Section", SectionName, Symbol.SectionIndex);
- W.printEnum ("RefType", static_cast<uint16_t>(Symbol.Flags & 0xF),
- makeArrayRef(MachOSymbolRefTypes));
- W.printFlags ("Flags", static_cast<uint16_t>(Symbol.Flags & ~0xF),
- makeArrayRef(MachOSymbolFlags));
- W.printHex ("Value", Symbol.Value);
+ W.printHex("Section", SectionName, MOSymbol.SectionIndex);
+ W.printEnum("RefType", static_cast<uint16_t>(MOSymbol.Flags & 0xF),
+ makeArrayRef(MachOSymbolRefTypes));
+ W.printFlags("Flags", static_cast<uint16_t>(MOSymbol.Flags & ~0xF),
+ makeArrayRef(MachOSymbolFlags));
+ W.printHex("Value", MOSymbol.Value);
}
void MachODumper::printUnwindInfo() {