diff options
author | dim <dim@FreeBSD.org> | 2012-02-05 23:56:22 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2012-02-05 23:56:22 +0000 |
commit | eb8951e7f7015d193e6640deb0ebde32f01b72d8 (patch) | |
tree | 8052b8010f619e8d40e5e3b37482591f537e0ca0 /contrib/llvm/tools/llvm-objdump/MachODump.cpp | |
parent | 4de4d315e465f872a81f448b1788cc017f2d2033 (diff) | |
parent | 07637c87f826cdf411f0673595e9bc92ebd793f2 (diff) | |
download | FreeBSD-src-eb8951e7f7015d193e6640deb0ebde32f01b72d8.zip FreeBSD-src-eb8951e7f7015d193e6640deb0ebde32f01b72d8.tar.gz |
Add a WITH_CLANG_EXTRAS option for src.conf(5), disabled by default,
that builds the following additional llvm/clang tools:
- bugpoint
- llc
- lli
- llvm-ar
- llvm-as
- llvm-bcanalyzer
- llvm-diff
- llvm-dis
- llvm-extract
- llvm-ld
- llvm-link
- llvm-mc
- llvm-nm
- llvm-objdump
- llvm-prof
- llvm-ranlib
- llvm-rtdyld
- llvm-stub
- macho-dump
- opt
These tools are mainly useful for people that want to manipulate llvm
bitcode (.bc) and llvm assembly language (.ll) files, or want to tinker
with llvm and clang themselves.
MFC after: 2 weeks
Diffstat (limited to 'contrib/llvm/tools/llvm-objdump/MachODump.cpp')
-rw-r--r-- | contrib/llvm/tools/llvm-objdump/MachODump.cpp | 617 |
1 files changed, 617 insertions, 0 deletions
diff --git a/contrib/llvm/tools/llvm-objdump/MachODump.cpp b/contrib/llvm/tools/llvm-objdump/MachODump.cpp new file mode 100644 index 0000000..3f44b29 --- /dev/null +++ b/contrib/llvm/tools/llvm-objdump/MachODump.cpp @@ -0,0 +1,617 @@ +//===-- MachODump.cpp - Object file dumping utility for llvm --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the MachO-specific dumper for llvm-objdump. +// +//===----------------------------------------------------------------------===// + +#include "llvm-objdump.h" +#include "MCFunction.h" +#include "llvm/Support/MachO.h" +#include "llvm/Object/MachOObject.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCInstrAnalysis.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/GraphWriter.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" +#include <algorithm> +#include <cstring> +using namespace llvm; +using namespace object; + +static cl::opt<bool> + CFG("cfg", cl::desc("Create a CFG for every symbol in the object file and" + "write it to a graphviz file (MachO-only)")); + +static cl::opt<bool> + UseDbg("g", cl::desc("Print line information from debug info if available")); + +static cl::opt<std::string> + DSYMFile("dsym", cl::desc("Use .dSYM file for debug info")); + +static const Target *GetTarget(const MachOObject *MachOObj) { + // Figure out the target triple. + llvm::Triple TT("unknown-unknown-unknown"); + switch (MachOObj->getHeader().CPUType) { + case llvm::MachO::CPUTypeI386: + TT.setArch(Triple::ArchType(Triple::x86)); + break; + case llvm::MachO::CPUTypeX86_64: + TT.setArch(Triple::ArchType(Triple::x86_64)); + break; + case llvm::MachO::CPUTypeARM: + TT.setArch(Triple::ArchType(Triple::arm)); + break; + case llvm::MachO::CPUTypePowerPC: + TT.setArch(Triple::ArchType(Triple::ppc)); + break; + case llvm::MachO::CPUTypePowerPC64: + TT.setArch(Triple::ArchType(Triple::ppc64)); + break; + } + + TripleName = TT.str(); + + // Get the target specific parser. + std::string Error; + const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); + if (TheTarget) + return TheTarget; + + errs() << "llvm-objdump: error: unable to get target for '" << TripleName + << "', see --version and --triple.\n"; + return 0; +} + +struct Section { + char Name[16]; + uint64_t Address; + uint64_t Size; + uint32_t Offset; + uint32_t NumRelocs; + uint64_t RelocTableOffset; +}; + +struct Symbol { + uint64_t Value; + uint32_t StringIndex; + uint8_t SectionIndex; + bool operator<(const Symbol &RHS) const { return Value < RHS.Value; } +}; + +template <typename T> +static Section copySection(const T &Sect) { + Section S; + memcpy(S.Name, Sect->Name, 16); + S.Address = Sect->Address; + S.Size = Sect->Size; + S.Offset = Sect->Offset; + S.NumRelocs = Sect->NumRelocationTableEntries; + S.RelocTableOffset = Sect->RelocationTableOffset; + return S; +} + +template <typename T> +static Symbol copySymbol(const T &STE) { + Symbol S; + S.StringIndex = STE->StringIndex; + S.SectionIndex = STE->SectionIndex; + S.Value = STE->Value; + return S; +} + +// Print additional information about an address, if available. +static void DumpAddress(uint64_t Address, ArrayRef<Section> Sections, + MachOObject *MachOObj, raw_ostream &OS) { + for (unsigned i = 0; i != Sections.size(); ++i) { + uint64_t addr = Address-Sections[i].Address; + if (Sections[i].Address <= Address && + Sections[i].Address + Sections[i].Size > Address) { + StringRef bytes = MachOObj->getData(Sections[i].Offset, + Sections[i].Size); + // Print constant strings. + if (!strcmp(Sections[i].Name, "__cstring")) + OS << '"' << bytes.substr(addr, bytes.find('\0', addr)) << '"'; + // Print constant CFStrings. + if (!strcmp(Sections[i].Name, "__cfstring")) + OS << "@\"" << bytes.substr(addr, bytes.find('\0', addr)) << '"'; + } + } +} + +typedef std::map<uint64_t, MCFunction*> FunctionMapTy; +typedef SmallVector<MCFunction, 16> FunctionListTy; +static void createMCFunctionAndSaveCalls(StringRef Name, + const MCDisassembler *DisAsm, + MemoryObject &Object, uint64_t Start, + uint64_t End, + MCInstrAnalysis *InstrAnalysis, + uint64_t Address, + raw_ostream &DebugOut, + FunctionMapTy &FunctionMap, + FunctionListTy &Functions) { + SmallVector<uint64_t, 16> Calls; + MCFunction f = + MCFunction::createFunctionFromMC(Name, DisAsm, Object, Start, End, + InstrAnalysis, DebugOut, Calls); + Functions.push_back(f); + FunctionMap[Address] = &Functions.back(); + + // Add the gathered callees to the map. + for (unsigned i = 0, e = Calls.size(); i != e; ++i) + FunctionMap.insert(std::make_pair(Calls[i], (MCFunction*)0)); +} + +// Write a graphviz file for the CFG inside an MCFunction. +static void emitDOTFile(const char *FileName, const MCFunction &f, + MCInstPrinter *IP) { + // Start a new dot file. + std::string Error; + raw_fd_ostream Out(FileName, Error); + if (!Error.empty()) { + errs() << "llvm-objdump: warning: " << Error << '\n'; + return; + } + + Out << "digraph " << f.getName() << " {\n"; + Out << "graph [ rankdir = \"LR\" ];\n"; + for (MCFunction::iterator i = f.begin(), e = f.end(); i != e; ++i) { + bool hasPreds = false; + // Only print blocks that have predecessors. + // FIXME: Slow. + for (MCFunction::iterator pi = f.begin(), pe = f.end(); pi != pe; + ++pi) + if (pi->second.contains(i->first)) { + hasPreds = true; + break; + } + + if (!hasPreds && i != f.begin()) + continue; + + Out << '"' << i->first << "\" [ label=\"<a>"; + // Print instructions. + for (unsigned ii = 0, ie = i->second.getInsts().size(); ii != ie; + ++ii) { + // Escape special chars and print the instruction in mnemonic form. + std::string Str; + raw_string_ostream OS(Str); + IP->printInst(&i->second.getInsts()[ii].Inst, OS, ""); + Out << DOT::EscapeString(OS.str()) << '|'; + } + Out << "<o>\" shape=\"record\" ];\n"; + + // Add edges. + for (MCBasicBlock::succ_iterator si = i->second.succ_begin(), + se = i->second.succ_end(); si != se; ++si) + Out << i->first << ":o -> " << *si <<":a\n"; + } + Out << "}\n"; +} + +static void getSectionsAndSymbols(const macho::Header &Header, + MachOObject *MachOObj, + InMemoryStruct<macho::SymtabLoadCommand> *SymtabLC, + std::vector<Section> &Sections, + std::vector<Symbol> &Symbols, + SmallVectorImpl<uint64_t> &FoundFns) { + // Make a list of all symbols in the object file. + for (unsigned i = 0; i != Header.NumLoadCommands; ++i) { + const MachOObject::LoadCommandInfo &LCI = MachOObj->getLoadCommandInfo(i); + if (LCI.Command.Type == macho::LCT_Segment) { + InMemoryStruct<macho::SegmentLoadCommand> SegmentLC; + MachOObj->ReadSegmentLoadCommand(LCI, SegmentLC); + + // Store the sections in this segment. + for (unsigned SectNum = 0; SectNum != SegmentLC->NumSections; ++SectNum) { + InMemoryStruct<macho::Section> Sect; + MachOObj->ReadSection(LCI, SectNum, Sect); + Sections.push_back(copySection(Sect)); + + } + } else if (LCI.Command.Type == macho::LCT_Segment64) { + InMemoryStruct<macho::Segment64LoadCommand> Segment64LC; + MachOObj->ReadSegment64LoadCommand(LCI, Segment64LC); + + // Store the sections in this segment. + for (unsigned SectNum = 0; SectNum != Segment64LC->NumSections; + ++SectNum) { + InMemoryStruct<macho::Section64> Sect64; + MachOObj->ReadSection64(LCI, SectNum, Sect64); + Sections.push_back(copySection(Sect64)); + } + } else if (LCI.Command.Type == macho::LCT_FunctionStarts) { + // We found a function starts segment, parse the addresses for later + // consumption. + InMemoryStruct<macho::LinkeditDataLoadCommand> LLC; + MachOObj->ReadLinkeditDataLoadCommand(LCI, LLC); + + MachOObj->ReadULEB128s(LLC->DataOffset, FoundFns); + } + } + // Store the symbols. + if (SymtabLC) { + for (unsigned i = 0; i != (*SymtabLC)->NumSymbolTableEntries; ++i) { + if (MachOObj->is64Bit()) { + InMemoryStruct<macho::Symbol64TableEntry> STE; + MachOObj->ReadSymbol64TableEntry((*SymtabLC)->SymbolTableOffset, i, + STE); + Symbols.push_back(copySymbol(STE)); + } else { + InMemoryStruct<macho::SymbolTableEntry> STE; + MachOObj->ReadSymbolTableEntry((*SymtabLC)->SymbolTableOffset, i, + STE); + Symbols.push_back(copySymbol(STE)); + } + } + } +} + +void llvm::DisassembleInputMachO(StringRef Filename) { + OwningPtr<MemoryBuffer> Buff; + + if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) { + errs() << "llvm-objdump: " << Filename << ": " << ec.message() << "\n"; + return; + } + + OwningPtr<MachOObject> MachOObj(MachOObject::LoadFromBuffer(Buff.take())); + + const Target *TheTarget = GetTarget(MachOObj.get()); + if (!TheTarget) { + // GetTarget prints out stuff. + return; + } + OwningPtr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo()); + OwningPtr<MCInstrAnalysis> + InstrAnalysis(TheTarget->createMCInstrAnalysis(InstrInfo.get())); + + // Set up disassembler. + OwningPtr<const MCAsmInfo> AsmInfo(TheTarget->createMCAsmInfo(TripleName)); + OwningPtr<const MCSubtargetInfo> + STI(TheTarget->createMCSubtargetInfo(TripleName, "", "")); + OwningPtr<const MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI)); + int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); + OwningPtr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( + AsmPrinterVariant, *AsmInfo, *STI)); + + if (!InstrAnalysis || !AsmInfo || !STI || !DisAsm || !IP) { + errs() << "error: couldn't initialize disassembler for target " + << TripleName << '\n'; + return; + } + + outs() << '\n' << Filename << ":\n\n"; + + const macho::Header &Header = MachOObj->getHeader(); + + const MachOObject::LoadCommandInfo *SymtabLCI = 0; + // First, find the symbol table segment. + for (unsigned i = 0; i != Header.NumLoadCommands; ++i) { + const MachOObject::LoadCommandInfo &LCI = MachOObj->getLoadCommandInfo(i); + if (LCI.Command.Type == macho::LCT_Symtab) { + SymtabLCI = &LCI; + break; + } + } + + // Read and register the symbol table data. + InMemoryStruct<macho::SymtabLoadCommand> SymtabLC; + MachOObj->ReadSymtabLoadCommand(*SymtabLCI, SymtabLC); + MachOObj->RegisterStringTable(*SymtabLC); + + std::vector<Section> Sections; + std::vector<Symbol> Symbols; + SmallVector<uint64_t, 8> FoundFns; + + getSectionsAndSymbols(Header, MachOObj.get(), &SymtabLC, Sections, Symbols, + FoundFns); + + // Make a copy of the unsorted symbol list. FIXME: duplication + std::vector<Symbol> UnsortedSymbols(Symbols); + // Sort the symbols by address, just in case they didn't come in that way. + array_pod_sort(Symbols.begin(), Symbols.end()); + +#ifndef NDEBUG + raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls(); +#else + raw_ostream &DebugOut = nulls(); +#endif + + StringRef DebugAbbrevSection, DebugInfoSection, DebugArangesSection, + DebugLineSection, DebugStrSection; + OwningPtr<DIContext> diContext; + OwningPtr<MachOObject> DSYMObj; + MachOObject *DbgInfoObj = MachOObj.get(); + // Try to find debug info and set up the DIContext for it. + if (UseDbg) { + ArrayRef<Section> DebugSections = Sections; + std::vector<Section> DSYMSections; + + // A separate DSym file path was specified, parse it as a macho file, + // get the sections and supply it to the section name parsing machinery. + if (!DSYMFile.empty()) { + OwningPtr<MemoryBuffer> Buf; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(DSYMFile.c_str(), Buf)) { + errs() << "llvm-objdump: " << Filename << ": " << ec.message() << '\n'; + return; + } + DSYMObj.reset(MachOObject::LoadFromBuffer(Buf.take())); + const macho::Header &Header = DSYMObj->getHeader(); + + std::vector<Symbol> Symbols; + SmallVector<uint64_t, 8> FoundFns; + getSectionsAndSymbols(Header, DSYMObj.get(), 0, DSYMSections, Symbols, + FoundFns); + DebugSections = DSYMSections; + DbgInfoObj = DSYMObj.get(); + } + + // Find the named debug info sections. + for (unsigned SectIdx = 0; SectIdx != DebugSections.size(); SectIdx++) { + if (!strcmp(DebugSections[SectIdx].Name, "__debug_abbrev")) + DebugAbbrevSection = DbgInfoObj->getData(DebugSections[SectIdx].Offset, + DebugSections[SectIdx].Size); + else if (!strcmp(DebugSections[SectIdx].Name, "__debug_info")) + DebugInfoSection = DbgInfoObj->getData(DebugSections[SectIdx].Offset, + DebugSections[SectIdx].Size); + else if (!strcmp(DebugSections[SectIdx].Name, "__debug_aranges")) + DebugArangesSection = DbgInfoObj->getData(DebugSections[SectIdx].Offset, + DebugSections[SectIdx].Size); + else if (!strcmp(DebugSections[SectIdx].Name, "__debug_line")) + DebugLineSection = DbgInfoObj->getData(DebugSections[SectIdx].Offset, + DebugSections[SectIdx].Size); + else if (!strcmp(DebugSections[SectIdx].Name, "__debug_str")) + DebugStrSection = DbgInfoObj->getData(DebugSections[SectIdx].Offset, + DebugSections[SectIdx].Size); + } + + // Setup the DIContext. + diContext.reset(DIContext::getDWARFContext(DbgInfoObj->isLittleEndian(), + DebugInfoSection, + DebugAbbrevSection, + DebugArangesSection, + DebugLineSection, + DebugStrSection)); + } + + FunctionMapTy FunctionMap; + FunctionListTy Functions; + + for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) { + if (strcmp(Sections[SectIdx].Name, "__text")) + continue; // Skip non-text sections + + // Insert the functions from the function starts segment into our map. + uint64_t VMAddr = Sections[SectIdx].Address - Sections[SectIdx].Offset; + for (unsigned i = 0, e = FoundFns.size(); i != e; ++i) + FunctionMap.insert(std::make_pair(FoundFns[i]+VMAddr, (MCFunction*)0)); + + StringRef Bytes = MachOObj->getData(Sections[SectIdx].Offset, + Sections[SectIdx].Size); + StringRefMemoryObject memoryObject(Bytes); + bool symbolTableWorked = false; + + // Parse relocations. + std::vector<std::pair<uint64_t, uint32_t> > Relocs; + for (unsigned j = 0; j != Sections[SectIdx].NumRelocs; ++j) { + InMemoryStruct<macho::RelocationEntry> RE; + MachOObj->ReadRelocationEntry(Sections[SectIdx].RelocTableOffset, j, RE); + Relocs.push_back(std::make_pair(RE->Word0, RE->Word1 & 0xffffff)); + } + array_pod_sort(Relocs.begin(), Relocs.end()); + + // Disassemble symbol by symbol. + for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) { + // Make sure the symbol is defined in this section. + if ((unsigned)Symbols[SymIdx].SectionIndex - 1 != SectIdx) + continue; + + // Start at the address of the symbol relative to the section's address. + uint64_t Start = Symbols[SymIdx].Value - Sections[SectIdx].Address; + // Stop disassembling either at the beginning of the next symbol or at + // the end of the section. + uint64_t End = (SymIdx+1 == Symbols.size() || + Symbols[SymIdx].SectionIndex != Symbols[SymIdx+1].SectionIndex) ? + Sections[SectIdx].Size : + Symbols[SymIdx+1].Value - Sections[SectIdx].Address; + uint64_t Size; + + if (Start >= End) + continue; + + symbolTableWorked = true; + + if (!CFG) { + // Normal disassembly, print addresses, bytes and mnemonic form. + outs() << MachOObj->getStringAtIndex(Symbols[SymIdx].StringIndex) + << ":\n"; + DILineInfo lastLine; + for (uint64_t Index = Start; Index < End; Index += Size) { + MCInst Inst; + + if (DisAsm->getInstruction(Inst, Size, memoryObject, Index, + DebugOut, nulls())) { + outs() << format("%8llx:\t", Sections[SectIdx].Address + Index); + DumpBytes(StringRef(Bytes.data() + Index, Size)); + IP->printInst(&Inst, outs(), ""); + + // Print debug info. + if (diContext) { + DILineInfo dli = + diContext->getLineInfoForAddress(Sections[SectIdx].Address + + Index); + // Print valid line info if it changed. + if (dli != lastLine && dli.getLine() != 0) + outs() << "\t## " << dli.getFileName() << ':' + << dli.getLine() << ':' << dli.getColumn(); + lastLine = dli; + } + outs() << "\n"; + } else { + errs() << "llvm-objdump: warning: invalid instruction encoding\n"; + if (Size == 0) + Size = 1; // skip illegible bytes + } + } + } else { + // Create CFG and use it for disassembly. + createMCFunctionAndSaveCalls( + MachOObj->getStringAtIndex(Symbols[SymIdx].StringIndex), + DisAsm.get(), memoryObject, Start, End, InstrAnalysis.get(), + Start, DebugOut, FunctionMap, Functions); + } + } + + if (CFG) { + if (!symbolTableWorked) { + // Reading the symbol table didn't work, create a big __TEXT symbol. + createMCFunctionAndSaveCalls("__TEXT", DisAsm.get(), memoryObject, + 0, Sections[SectIdx].Size, + InstrAnalysis.get(), + Sections[SectIdx].Offset, DebugOut, + FunctionMap, Functions); + } + for (std::map<uint64_t, MCFunction*>::iterator mi = FunctionMap.begin(), + me = FunctionMap.end(); mi != me; ++mi) + if (mi->second == 0) { + // Create functions for the remaining callees we have gathered, + // but we didn't find a name for them. + SmallVector<uint64_t, 16> Calls; + MCFunction f = + MCFunction::createFunctionFromMC("unknown", DisAsm.get(), + memoryObject, mi->first, + Sections[SectIdx].Size, + InstrAnalysis.get(), DebugOut, + Calls); + Functions.push_back(f); + mi->second = &Functions.back(); + for (unsigned i = 0, e = Calls.size(); i != e; ++i) { + std::pair<uint64_t, MCFunction*> p(Calls[i], (MCFunction*)0); + if (FunctionMap.insert(p).second) + mi = FunctionMap.begin(); + } + } + + DenseSet<uint64_t> PrintedBlocks; + for (unsigned ffi = 0, ffe = Functions.size(); ffi != ffe; ++ffi) { + MCFunction &f = Functions[ffi]; + for (MCFunction::iterator fi = f.begin(), fe = f.end(); fi != fe; ++fi){ + if (!PrintedBlocks.insert(fi->first).second) + continue; // We already printed this block. + + // We assume a block has predecessors when it's the first block after + // a symbol. + bool hasPreds = FunctionMap.find(fi->first) != FunctionMap.end(); + + // See if this block has predecessors. + // FIXME: Slow. + for (MCFunction::iterator pi = f.begin(), pe = f.end(); pi != pe; + ++pi) + if (pi->second.contains(fi->first)) { + hasPreds = true; + break; + } + + // No predecessors, this is a data block. Print as .byte directives. + if (!hasPreds) { + uint64_t End = llvm::next(fi) == fe ? Sections[SectIdx].Size : + llvm::next(fi)->first; + outs() << "# " << End-fi->first << " bytes of data:\n"; + for (unsigned pos = fi->first; pos != End; ++pos) { + outs() << format("%8x:\t", Sections[SectIdx].Address + pos); + DumpBytes(StringRef(Bytes.data() + pos, 1)); + outs() << format("\t.byte 0x%02x\n", (uint8_t)Bytes[pos]); + } + continue; + } + + if (fi->second.contains(fi->first)) // Print a header for simple loops + outs() << "# Loop begin:\n"; + + DILineInfo lastLine; + // Walk over the instructions and print them. + for (unsigned ii = 0, ie = fi->second.getInsts().size(); ii != ie; + ++ii) { + const MCDecodedInst &Inst = fi->second.getInsts()[ii]; + + // If there's a symbol at this address, print its name. + if (FunctionMap.find(Sections[SectIdx].Address + Inst.Address) != + FunctionMap.end()) + outs() << FunctionMap[Sections[SectIdx].Address + Inst.Address]-> + getName() << ":\n"; + + outs() << format("%8llx:\t", Sections[SectIdx].Address + + Inst.Address); + DumpBytes(StringRef(Bytes.data() + Inst.Address, Inst.Size)); + + if (fi->second.contains(fi->first)) // Indent simple loops. + outs() << '\t'; + + IP->printInst(&Inst.Inst, outs(), ""); + + // Look for relocations inside this instructions, if there is one + // print its target and additional information if available. + for (unsigned j = 0; j != Relocs.size(); ++j) + if (Relocs[j].first >= Sections[SectIdx].Address + Inst.Address && + Relocs[j].first < Sections[SectIdx].Address + Inst.Address + + Inst.Size) { + outs() << "\t# " + << MachOObj->getStringAtIndex( + UnsortedSymbols[Relocs[j].second].StringIndex) + << ' '; + DumpAddress(UnsortedSymbols[Relocs[j].second].Value, Sections, + MachOObj.get(), outs()); + } + + // If this instructions contains an address, see if we can evaluate + // it and print additional information. + uint64_t targ = InstrAnalysis->evaluateBranch(Inst.Inst, + Inst.Address, + Inst.Size); + if (targ != -1ULL) + DumpAddress(targ, Sections, MachOObj.get(), outs()); + + // Print debug info. + if (diContext) { + DILineInfo dli = + diContext->getLineInfoForAddress(Sections[SectIdx].Address + + Inst.Address); + // Print valid line info if it changed. + if (dli != lastLine && dli.getLine() != 0) + outs() << "\t## " << dli.getFileName() << ':' + << dli.getLine() << ':' << dli.getColumn(); + lastLine = dli; + } + + outs() << '\n'; + } + } + + emitDOTFile((f.getName().str() + ".dot").c_str(), f, IP.get()); + } + } + } +} |