diff options
Diffstat (limited to 'contrib/llvm/tools/llvm-objdump')
-rw-r--r-- | contrib/llvm/tools/llvm-objdump/COFFDump.cpp | 50 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-objdump/ELFDump.cpp | 30 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-objdump/MCFunction.cpp | 138 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-objdump/MCFunction.h | 100 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-objdump/MachODump.cpp | 456 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp | 246 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-objdump/llvm-objdump.h | 22 |
7 files changed, 415 insertions, 627 deletions
diff --git a/contrib/llvm/tools/llvm-objdump/COFFDump.cpp b/contrib/llvm/tools/llvm-objdump/COFFDump.cpp index 2ada683..5f0bcbb 100644 --- a/contrib/llvm/tools/llvm-objdump/COFFDump.cpp +++ b/contrib/llvm/tools/llvm-objdump/COFFDump.cpp @@ -178,7 +178,7 @@ static error_code resolveSymbol(const std::vector<RelocationRef> &Rels, uint64_t Ofs; if (error_code ec = I->getOffset(Ofs)) return ec; if (Ofs == Offset) { - if (error_code ec = I->getSymbol(Sym)) return ec; + Sym = *I->getSymbol(); break; } } @@ -227,9 +227,51 @@ static void printCOFFSymbolAddress(llvm::raw_ostream &Out, Out << format(" + 0x%04x", Disp); } +// Prints import tables. The import table is a table containing the list of +// DLL name and symbol names which will be linked by the loader. +static void printImportTables(const COFFObjectFile *Obj) { + outs() << "The Import Tables:\n"; + error_code ec; + for (import_directory_iterator i = Obj->import_directory_begin(), + e = Obj->import_directory_end(); + i != e; i = i.increment(ec)) { + if (ec) + return; + + const import_directory_table_entry *Dir; + StringRef Name; + if (i->getImportTableEntry(Dir)) return; + if (i->getName(Name)) return; + + outs() << format(" lookup %08x time %08x fwd %08x name %08x addr %08x\n\n", + static_cast<uint32_t>(Dir->ImportLookupTableRVA), + static_cast<uint32_t>(Dir->TimeDateStamp), + static_cast<uint32_t>(Dir->ForwarderChain), + static_cast<uint32_t>(Dir->NameRVA), + static_cast<uint32_t>(Dir->ImportAddressTableRVA)); + outs() << " DLL Name: " << Name << "\n"; + outs() << " Hint/Ord Name\n"; + const import_lookup_table_entry32 *entry; + if (i->getImportLookupEntry(entry)) + return; + for (; entry->data; ++entry) { + if (entry->isOrdinal()) { + outs() << format(" % 6d\n", entry->getOrdinal()); + continue; + } + uint16_t Hint; + StringRef Name; + if (Obj->getHintName(entry->getHintNameRVA(), Hint, Name)) + return; + outs() << format(" % 6d ", Hint) << Name << "\n"; + } + outs() << "\n"; + } +} + void llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) { const coff_file_header *Header; - if (error(Obj->getHeader(Header))) return; + if (error(Obj->getCOFFHeader(Header))) return; if (Header->Machine != COFF::IMAGE_FILE_MACHINE_AMD64) { errs() << "Unsupported image machine type " @@ -353,3 +395,7 @@ void llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) { } } } + +void llvm::printCOFFFileHeader(const object::ObjectFile *Obj) { + printImportTables(dyn_cast<const COFFObjectFile>(Obj)); +} diff --git a/contrib/llvm/tools/llvm-objdump/ELFDump.cpp b/contrib/llvm/tools/llvm-objdump/ELFDump.cpp index bd15231..9c091a4 100644 --- a/contrib/llvm/tools/llvm-objdump/ELFDump.cpp +++ b/contrib/llvm/tools/llvm-objdump/ELFDump.cpp @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm-objdump.h" -#include "llvm/Object/ELF.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" @@ -21,10 +21,8 @@ using namespace llvm; using namespace llvm::object; -template<class ELFT> -void printProgramHeaders( - const ELFObjectFile<ELFT> *o) { - typedef ELFObjectFile<ELFT> ELFO; +template <class ELFT> void printProgramHeaders(const ELFFile<ELFT> *o) { + typedef ELFFile<ELFT> ELFO; outs() << "Program Header:\n"; for (typename ELFO::Elf_Phdr_Iter pi = o->begin_program_headers(), pe = o->end_program_headers(); @@ -63,7 +61,7 @@ void printProgramHeaders( << format(Fmt, (uint64_t)pi->p_vaddr) << "paddr " << format(Fmt, (uint64_t)pi->p_paddr) - << format("align 2**%u\n", CountTrailingZeros_64(pi->p_align)) + << format("align 2**%u\n", countTrailingZeros<uint64_t>(pi->p_align)) << " filesz " << format(Fmt, (uint64_t)pi->p_filesz) << "memsz " @@ -79,22 +77,18 @@ void printProgramHeaders( void llvm::printELFFileHeader(const object::ObjectFile *Obj) { // Little-endian 32-bit - if (const ELFObjectFile<ELFType<support::little, 4, false> > *ELFObj = - dyn_cast<ELFObjectFile<ELFType<support::little, 4, false> > >(Obj)) - printProgramHeaders(ELFObj); + if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) + printProgramHeaders(ELFObj->getELFFile()); // Big-endian 32-bit - if (const ELFObjectFile<ELFType<support::big, 4, false> > *ELFObj = - dyn_cast<ELFObjectFile<ELFType<support::big, 4, false> > >(Obj)) - printProgramHeaders(ELFObj); + if (const ELF32BEObjectFile *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) + printProgramHeaders(ELFObj->getELFFile()); // Little-endian 64-bit - if (const ELFObjectFile<ELFType<support::little, 8, true> > *ELFObj = - dyn_cast<ELFObjectFile<ELFType<support::little, 8, true> > >(Obj)) - printProgramHeaders(ELFObj); + if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) + printProgramHeaders(ELFObj->getELFFile()); // Big-endian 64-bit - if (const ELFObjectFile<ELFType<support::big, 8, true> > *ELFObj = - dyn_cast<ELFObjectFile<ELFType<support::big, 8, true> > >(Obj)) - printProgramHeaders(ELFObj); + if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) + printProgramHeaders(ELFObj->getELFFile()); } diff --git a/contrib/llvm/tools/llvm-objdump/MCFunction.cpp b/contrib/llvm/tools/llvm-objdump/MCFunction.cpp deleted file mode 100644 index 5c67f1b..0000000 --- a/contrib/llvm/tools/llvm-objdump/MCFunction.cpp +++ /dev/null @@ -1,138 +0,0 @@ -//===-- MCFunction.cpp ----------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the algorithm to break down a region of machine code -// into basic blocks and try to reconstruct a CFG from it. -// -//===----------------------------------------------------------------------===// - -#include "MCFunction.h" -#include "llvm/ADT/STLExtras.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/Support/MemoryObject.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/system_error.h" -#include <set> -using namespace llvm; - -MCFunction -MCFunction::createFunctionFromMC(StringRef Name, const MCDisassembler *DisAsm, - const MemoryObject &Region, uint64_t Start, - uint64_t End, const MCInstrAnalysis *Ana, - raw_ostream &DebugOut, - SmallVectorImpl<uint64_t> &Calls) { - std::vector<MCDecodedInst> Instructions; - std::set<uint64_t> Splits; - Splits.insert(Start); - uint64_t Size; - - MCFunction f(Name); - - { - DenseSet<uint64_t> VisitedInsts; - SmallVector<uint64_t, 16> WorkList; - WorkList.push_back(Start); - // Disassemble code and gather basic block split points. - while (!WorkList.empty()) { - uint64_t Index = WorkList.pop_back_val(); - if (VisitedInsts.find(Index) != VisitedInsts.end()) - continue; // Already visited this location. - - for (;Index < End; Index += Size) { - VisitedInsts.insert(Index); - - MCInst Inst; - if (DisAsm->getInstruction(Inst, Size, Region, Index, DebugOut, nulls())){ - Instructions.push_back(MCDecodedInst(Index, Size, Inst)); - if (Ana->isBranch(Inst)) { - uint64_t targ = Ana->evaluateBranch(Inst, Index, Size); - if (targ != -1ULL && targ == Index+Size) - continue; // Skip nop jumps. - - // If we could determine the branch target, make a note to start a - // new basic block there and add the target to the worklist. - if (targ != -1ULL) { - Splits.insert(targ); - WorkList.push_back(targ); - WorkList.push_back(Index+Size); - } - Splits.insert(Index+Size); - break; - } else if (Ana->isReturn(Inst)) { - // Return instruction. This basic block ends here. - Splits.insert(Index+Size); - break; - } else if (Ana->isCall(Inst)) { - uint64_t targ = Ana->evaluateBranch(Inst, Index, Size); - // Add the call to the call list if the destination is known. - if (targ != -1ULL && targ != Index+Size) - Calls.push_back(targ); - } - } else { - errs().write_hex(Index) << ": warning: invalid instruction encoding\n"; - if (Size == 0) - Size = 1; // skip illegible bytes - } - } - } - } - - // Make sure the instruction list is sorted. - std::sort(Instructions.begin(), Instructions.end()); - - // Create basic blocks. - unsigned ii = 0, ie = Instructions.size(); - for (std::set<uint64_t>::iterator spi = Splits.begin(), - spe = llvm::prior(Splits.end()); spi != spe; ++spi) { - MCBasicBlock BB; - uint64_t BlockEnd = *llvm::next(spi); - // Add instructions to the BB. - for (; ii != ie; ++ii) { - if (Instructions[ii].Address < *spi || - Instructions[ii].Address >= BlockEnd) - break; - BB.addInst(Instructions[ii]); - } - f.addBlock(*spi, BB); - } - - std::sort(f.Blocks.begin(), f.Blocks.end()); - - // Calculate successors of each block. - for (MCFunction::iterator i = f.begin(), e = f.end(); i != e; ++i) { - MCBasicBlock &BB = const_cast<MCBasicBlock&>(i->second); - if (BB.getInsts().empty()) continue; - const MCDecodedInst &Inst = BB.getInsts().back(); - - if (Ana->isBranch(Inst.Inst)) { - uint64_t targ = Ana->evaluateBranch(Inst.Inst, Inst.Address, Inst.Size); - if (targ == -1ULL) { - // Indirect branch. Bail and add all blocks of the function as a - // successor. - for (MCFunction::iterator i = f.begin(), e = f.end(); i != e; ++i) - BB.addSucc(i->first); - } else if (targ != Inst.Address+Inst.Size) - BB.addSucc(targ); - // Conditional branches can also fall through to the next block. - if (Ana->isConditionalBranch(Inst.Inst) && llvm::next(i) != e) - BB.addSucc(llvm::next(i)->first); - } else { - // No branch. Fall through to the next block. - if (!Ana->isReturn(Inst.Inst) && llvm::next(i) != e) - BB.addSucc(llvm::next(i)->first); - } - } - - return f; -} diff --git a/contrib/llvm/tools/llvm-objdump/MCFunction.h b/contrib/llvm/tools/llvm-objdump/MCFunction.h deleted file mode 100644 index 6d3a548..0000000 --- a/contrib/llvm/tools/llvm-objdump/MCFunction.h +++ /dev/null @@ -1,100 +0,0 @@ -//===-- MCFunction.h ------------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the data structures to hold a CFG reconstructed from -// machine code. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECTDUMP_MCFUNCTION_H -#define LLVM_OBJECTDUMP_MCFUNCTION_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/MC/MCInst.h" -#include <map> - -namespace llvm { - -class MCDisassembler; -class MCInstrAnalysis; -class MemoryObject; -class raw_ostream; - -/// MCDecodedInst - Small container to hold an MCInst and associated info like -/// address and size. -struct MCDecodedInst { - uint64_t Address; - uint64_t Size; - MCInst Inst; - - MCDecodedInst() {} - MCDecodedInst(uint64_t Address, uint64_t Size, MCInst Inst) - : Address(Address), Size(Size), Inst(Inst) {} - - bool operator<(const MCDecodedInst &RHS) const { - return Address < RHS.Address; - } -}; - -/// MCBasicBlock - Consists of multiple MCDecodedInsts and a list of successing -/// MCBasicBlocks. -class MCBasicBlock { - std::vector<MCDecodedInst> Insts; - typedef DenseSet<uint64_t> SetTy; - SetTy Succs; -public: - ArrayRef<MCDecodedInst> getInsts() const { return Insts; } - - typedef SetTy::const_iterator succ_iterator; - succ_iterator succ_begin() const { return Succs.begin(); } - succ_iterator succ_end() const { return Succs.end(); } - - bool contains(uint64_t Addr) const { return Succs.count(Addr); } - - void addInst(const MCDecodedInst &Inst) { Insts.push_back(Inst); } - void addSucc(uint64_t Addr) { Succs.insert(Addr); } - - bool operator<(const MCBasicBlock &RHS) const { - return Insts.size() < RHS.Insts.size(); - } -}; - -/// MCFunction - Represents a named function in machine code, containing -/// multiple MCBasicBlocks. -class MCFunction { - const StringRef Name; - // Keep BBs sorted by address. - typedef std::vector<std::pair<uint64_t, MCBasicBlock> > MapTy; - MapTy Blocks; -public: - MCFunction(StringRef Name) : Name(Name) {} - - // Create an MCFunction from a region of binary machine code. - static MCFunction - createFunctionFromMC(StringRef Name, const MCDisassembler *DisAsm, - const MemoryObject &Region, uint64_t Start, uint64_t End, - const MCInstrAnalysis *Ana, raw_ostream &DebugOut, - SmallVectorImpl<uint64_t> &Calls); - - typedef MapTy::const_iterator iterator; - iterator begin() const { return Blocks.begin(); } - iterator end() const { return Blocks.end(); } - - StringRef getName() const { return Name; } - - MCBasicBlock &addBlock(uint64_t Address, const MCBasicBlock &BB) { - Blocks.push_back(std::make_pair(Address, BB)); - return Blocks.back().second; - } -}; - -} - -#endif diff --git a/contrib/llvm/tools/llvm-objdump/MachODump.cpp b/contrib/llvm/tools/llvm-objdump/MachODump.cpp index 6797e2d..86923fd 100644 --- a/contrib/llvm/tools/llvm-objdump/MachODump.cpp +++ b/contrib/llvm/tools/llvm-objdump/MachODump.cpp @@ -12,9 +12,9 @@ //===----------------------------------------------------------------------===// #include "llvm-objdump.h" -#include "MCFunction.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Triple.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/MC/MCAsmInfo.h" @@ -44,10 +44,6 @@ 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> @@ -91,105 +87,73 @@ struct SymbolSorter { } }; -// Print additional information about an address, if available. -static void DumpAddress(uint64_t Address, ArrayRef<SectionRef> Sections, - const MachOObjectFile *MachOObj, raw_ostream &OS) { - for (unsigned i = 0; i != Sections.size(); ++i) { - uint64_t SectAddr = 0, SectSize = 0; - Sections[i].getAddress(SectAddr); - Sections[i].getSize(SectSize); - uint64_t addr = SectAddr; - if (SectAddr <= Address && - SectAddr + SectSize > Address) { - StringRef bytes, name; - Sections[i].getContents(bytes); - Sections[i].getName(name); - // Print constant strings. - if (!name.compare("__cstring")) - OS << '"' << bytes.substr(addr, bytes.find('\0', addr)) << '"'; - // Print constant CFStrings. - if (!name.compare("__cfstring")) - OS << "@\"" << bytes.substr(addr, bytes.find('\0', addr)) << '"'; - } - } -} +// Types for the storted data in code table that is built before disassembly +// and the predicate function to sort them. +typedef std::pair<uint64_t, DiceRef> DiceTableEntry; +typedef std::vector<DiceTableEntry> DiceTable; +typedef DiceTable::iterator dice_table_iterator; -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)); +static bool +compareDiceTableEntries(const DiceTableEntry i, + const DiceTableEntry j) { + return i.first == j.first; } -// 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()) << '|'; +static void DumpDataInCode(const char *bytes, uint64_t Size, + unsigned short Kind) { + uint64_t Value; + + switch (Kind) { + case MachO::DICE_KIND_DATA: + switch (Size) { + case 4: + Value = bytes[3] << 24 | + bytes[2] << 16 | + bytes[1] << 8 | + bytes[0]; + outs() << "\t.long " << Value; + break; + case 2: + Value = bytes[1] << 8 | + bytes[0]; + outs() << "\t.short " << Value; + break; + case 1: + Value = bytes[0]; + outs() << "\t.byte " << Value; + break; } - 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"; + outs() << "\t@ KIND_DATA\n"; + break; + case MachO::DICE_KIND_JUMP_TABLE8: + Value = bytes[0]; + outs() << "\t.byte " << Value << "\t@ KIND_JUMP_TABLE8"; + break; + case MachO::DICE_KIND_JUMP_TABLE16: + Value = bytes[1] << 8 | + bytes[0]; + outs() << "\t.short " << Value << "\t@ KIND_JUMP_TABLE16"; + break; + case MachO::DICE_KIND_JUMP_TABLE32: + Value = bytes[3] << 24 | + bytes[2] << 16 | + bytes[1] << 8 | + bytes[0]; + outs() << "\t.long " << Value << "\t@ KIND_JUMP_TABLE32"; + break; + default: + outs() << "\t@ data in code kind = " << Kind << "\n"; + break; } - Out << "}\n"; } static void -getSectionsAndSymbols(const macho::Header Header, +getSectionsAndSymbols(const MachO::mach_header Header, MachOObjectFile *MachOObj, std::vector<SectionRef> &Sections, std::vector<SymbolRef> &Symbols, - SmallVectorImpl<uint64_t> &FoundFns) { + SmallVectorImpl<uint64_t> &FoundFns, + uint64_t &BaseSegmentAddress) { error_code ec; for (symbol_iterator SI = MachOObj->begin_symbols(), SE = MachOObj->end_symbols(); SI != SE; SI.increment(ec)) @@ -205,17 +169,27 @@ getSectionsAndSymbols(const macho::Header Header, MachOObjectFile::LoadCommandInfo Command = MachOObj->getFirstLoadCommandInfo(); + bool BaseSegmentAddressSet = false; for (unsigned i = 0; ; ++i) { - if (Command.C.Type == macho::LCT_FunctionStarts) { + if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) { // We found a function starts segment, parse the addresses for later // consumption. - macho::LinkeditDataLoadCommand LLC = + MachO::linkedit_data_command LLC = MachOObj->getLinkeditDataLoadCommand(Command); - MachOObj->ReadULEB128s(LLC.DataOffset, FoundFns); + MachOObj->ReadULEB128s(LLC.dataoff, FoundFns); + } + else if (Command.C.cmd == MachO::LC_SEGMENT) { + MachO::segment_command SLC = + MachOObj->getSegmentLoadCommand(Command); + StringRef SegName = SLC.segname; + if(!BaseSegmentAddressSet && SegName != "__PAGEZERO") { + BaseSegmentAddressSet = true; + BaseSegmentAddress = SLC.vmaddr; + } } - if (i == Header.NumLoadCommands - 1) + if (i == Header.ncmds - 1) break; else Command = MachOObj->getNextLoadCommandInfo(Command); @@ -251,11 +225,12 @@ static void DisassembleInputMachO2(StringRef Filename, InstrAnalysis(TheTarget->createMCInstrAnalysis(InstrInfo.get())); // Set up disassembler. - OwningPtr<const MCAsmInfo> AsmInfo(TheTarget->createMCAsmInfo(TripleName)); + OwningPtr<const MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); + OwningPtr<const MCAsmInfo> AsmInfo( + TheTarget->createMCAsmInfo(*MRI, TripleName)); OwningPtr<const MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(TripleName, "", "")); OwningPtr<const MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI)); - OwningPtr<const MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); OwningPtr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *InstrInfo, @@ -269,19 +244,41 @@ static void DisassembleInputMachO2(StringRef Filename, outs() << '\n' << Filename << ":\n\n"; - macho::Header Header = MachOOF->getHeader(); + MachO::mach_header Header = MachOOF->getHeader(); + // FIXME: FoundFns isn't used anymore. Using symbols/LC_FUNCTION_STARTS to + // determine function locations will eventually go in MCObjectDisassembler. + // FIXME: Using the -cfg command line option, this code used to be able to + // annotate relocations with the referenced symbol's name, and if this was + // inside a __[cf]string section, the data it points to. This is now replaced + // by the upcoming MCSymbolizer, which needs the appropriate setup done above. std::vector<SectionRef> Sections; std::vector<SymbolRef> Symbols; SmallVector<uint64_t, 8> FoundFns; + uint64_t BaseSegmentAddress; - getSectionsAndSymbols(Header, MachOOF, Sections, Symbols, FoundFns); + getSectionsAndSymbols(Header, MachOOF, Sections, Symbols, FoundFns, + BaseSegmentAddress); - // Make a copy of the unsorted symbol list. FIXME: duplication - std::vector<SymbolRef> UnsortedSymbols(Symbols); // Sort the symbols by address, just in case they didn't come in that way. std::sort(Symbols.begin(), Symbols.end(), SymbolSorter()); + // Build a data in code table that is sorted on by the address of each entry. + uint64_t BaseAddress = 0; + if (Header.filetype == MachO::MH_OBJECT) + Sections[0].getAddress(BaseAddress); + else + BaseAddress = BaseSegmentAddress; + DiceTable Dices; + error_code ec; + for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices(); + DI != DE; DI.increment(ec)){ + uint32_t Offset; + DI->getOffset(Offset); + Dices.push_back(std::make_pair(BaseAddress + Offset, *DI)); + } + array_pod_sort(Dices.begin(), Dices.end()); + #ifndef NDEBUG raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls(); #else @@ -296,7 +293,7 @@ static void DisassembleInputMachO2(StringRef Filename, // 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)) { + if (error_code ec = MemoryBuffer::getFileOrSTDIN(DSYMFile, Buf)) { errs() << "llvm-objdump: " << Filename << ": " << ec.message() << '\n'; return; } @@ -307,31 +304,24 @@ static void DisassembleInputMachO2(StringRef Filename, diContext.reset(DIContext::getDWARFContext(DbgObj)); } - FunctionMapTy FunctionMap; - FunctionListTy Functions; - for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) { + + bool SectIsText = false; + Sections[SectIdx].isText(SectIsText); + if (SectIsText == false) + continue; + StringRef SectName; if (Sections[SectIdx].getName(SectName) || SectName != "__text") continue; // Skip non-text sections DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl(); + StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR); if (SegmentName != "__TEXT") continue; - // Insert the functions from the function starts segment into our map. - uint64_t VMAddr; - Sections[SectIdx].getAddress(VMAddr); - for (unsigned i = 0, e = FoundFns.size(); i != e; ++i) { - StringRef SectBegin; - Sections[SectIdx].getContents(SectBegin); - uint64_t Offset = (uint64_t)SectBegin.data(); - FunctionMap.insert(std::make_pair(VMAddr + FoundFns[i]-Offset, - (MCFunction*)0)); - } - StringRef Bytes; Sections[SectIdx].getContents(Bytes); StringRefMemoryObject memoryObject(Bytes); @@ -347,10 +337,9 @@ static void DisassembleInputMachO2(StringRef Filename, Sections[SectIdx].getAddress(SectionAddress); RelocOffset -= SectionAddress; - SymbolRef RelocSym; - RI->getSymbol(RelocSym); + symbol_iterator RelocSym = RI->getSymbol(); - Relocs.push_back(std::make_pair(RelocOffset, RelocSym)); + Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); } array_pod_sort(Relocs.begin(), Relocs.end()); @@ -402,52 +391,56 @@ static void DisassembleInputMachO2(StringRef Filename, symbolTableWorked = true; - if (!CFG) { - // Normal disassembly, print addresses, bytes and mnemonic form. - StringRef SymName; - Symbols[SymIdx].getName(SymName); - - outs() << SymName << ":\n"; - DILineInfo lastLine; - for (uint64_t Index = Start; Index < End; Index += Size) { - MCInst Inst; - - if (DisAsm->getInstruction(Inst, Size, memoryObject, Index, - DebugOut, nulls())) { - uint64_t SectAddress = 0; - Sections[SectIdx].getAddress(SectAddress); - outs() << format("%8" PRIx64 ":\t", SectAddress + Index); - - DumpBytes(StringRef(Bytes.data() + Index, Size)); - IP->printInst(&Inst, outs(), ""); - - // Print debug info. - if (diContext) { - DILineInfo dli = - diContext->getLineInfoForAddress(SectAddress + 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 + outs() << SymName << ":\n"; + DILineInfo lastLine; + for (uint64_t Index = Start; Index < End; Index += Size) { + MCInst Inst; + + uint64_t SectAddress = 0; + Sections[SectIdx].getAddress(SectAddress); + outs() << format("%8" PRIx64 ":\t", SectAddress + Index); + + // Check the data in code table here to see if this is data not an + // instruction to be disassembled. + DiceTable Dice; + Dice.push_back(std::make_pair(SectAddress + Index, DiceRef())); + dice_table_iterator DTI = std::search(Dices.begin(), Dices.end(), + Dice.begin(), Dice.end(), + compareDiceTableEntries); + if (DTI != Dices.end()){ + uint16_t Length; + DTI->second.getLength(Length); + DumpBytes(StringRef(Bytes.data() + Index, Length)); + uint16_t Kind; + DTI->second.getKind(Kind); + DumpDataInCode(Bytes.data() + Index, Length, Kind); + continue; + } + + if (DisAsm->getInstruction(Inst, Size, memoryObject, Index, + DebugOut, nulls())) { + DumpBytes(StringRef(Bytes.data() + Index, Size)); + IP->printInst(&Inst, outs(), ""); + + // Print debug info. + if (diContext) { + DILineInfo dli = + diContext->getLineInfoForAddress(SectAddress + 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. - StringRef SymName; - Symbols[SymIdx].getName(SymName); - createMCFunctionAndSaveCalls( - SymName, DisAsm.get(), memoryObject, Start, End, - InstrAnalysis.get(), Start, DebugOut, FunctionMap, Functions); } } - if (!CFG && !symbolTableWorked) { + if (!symbolTableWorked) { // Reading the symbol table didn't work, disassemble the whole section. uint64_t SectAddress; Sections[SectIdx].getAddress(SectAddress); @@ -470,142 +463,5 @@ static void DisassembleInputMachO2(StringRef Filename, } } } - - if (CFG) { - if (!symbolTableWorked) { - // Reading the symbol table didn't work, create a big __TEXT symbol. - uint64_t SectSize = 0, SectAddress = 0; - Sections[SectIdx].getSize(SectSize); - Sections[SectIdx].getAddress(SectAddress); - createMCFunctionAndSaveCalls("__TEXT", DisAsm.get(), memoryObject, - 0, SectSize, - InstrAnalysis.get(), - SectAddress, 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. - uint64_t SectSize = 0; - Sections[SectIdx].getSize(SectSize); - - SmallVector<uint64_t, 16> Calls; - MCFunction f = - MCFunction::createFunctionFromMC("unknown", DisAsm.get(), - memoryObject, mi->first, - SectSize, - 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; - } - - uint64_t SectSize = 0, SectAddress; - Sections[SectIdx].getSize(SectSize); - Sections[SectIdx].getAddress(SectAddress); - - // No predecessors, this is a data block. Print as .byte directives. - if (!hasPreds) { - uint64_t End = llvm::next(fi) == fe ? SectSize : - llvm::next(fi)->first; - outs() << "# " << End-fi->first << " bytes of data:\n"; - for (unsigned pos = fi->first; pos != End; ++pos) { - outs() << format("%8x:\t", SectAddress + 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(SectAddress + Inst.Address) != - FunctionMap.end()) - outs() << FunctionMap[SectAddress + Inst.Address]-> getName() - << ":\n"; - - outs() << format("%8" PRIx64 ":\t", SectAddress + 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 >= SectAddress + Inst.Address && - Relocs[j].first < SectAddress + Inst.Address + Inst.Size) { - StringRef SymName; - uint64_t Addr; - Relocs[j].second.getAddress(Addr); - Relocs[j].second.getName(SymName); - - outs() << "\t# " << SymName << ' '; - DumpAddress(Addr, Sections, MachOOF, 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, MachOOF, outs()); - - // Print debug info. - if (diContext) { - DILineInfo dli = - diContext->getLineInfoForAddress(SectAddress + 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()); - } - } } } diff --git a/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp index 247b90f..9bc092e 100644 --- a/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -17,17 +17,26 @@ //===----------------------------------------------------------------------===// #include "llvm-objdump.h" -#include "MCFunction.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Triple.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCAtom.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCFunction.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCInstrAnalysis.h" #include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCModule.h" +#include "llvm/MC/MCModuleYAML.h" +#include "llvm/MC/MCObjectDisassembler.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCObjectSymbolizer.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCRelocationInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Object/Archive.h" #include "llvm/Object/COFF.h" @@ -53,6 +62,7 @@ #include <algorithm> #include <cctype> #include <cstring> + using namespace llvm; using namespace object; @@ -123,6 +133,20 @@ static cl::alias PrivateHeadersShort("p", cl::desc("Alias for --private-headers"), cl::aliasopt(PrivateHeaders)); +static cl::opt<bool> +Symbolize("symbolize", cl::desc("When disassembling instructions, " + "try to symbolize operands.")); + +static cl::opt<bool> +CFG("cfg", cl::desc("Create a CFG for every function found in the object" + " and write it to a graphviz file")); + +// FIXME: Does it make sense to have a dedicated tool for yaml cfg output? +static cl::opt<std::string> +YAMLCFG("yaml-cfg", + cl::desc("Create a CFG and write it as a YAML MCModule."), + cl::value_desc("yaml output file")); + static StringRef ToolName; bool llvm::error(error_code ec) { @@ -137,8 +161,13 @@ static const Target *getTarget(const ObjectFile *Obj = NULL) { // Figure out the target triple. llvm::Triple TheTriple("unknown-unknown-unknown"); if (TripleName.empty()) { - if (Obj) + if (Obj) { TheTriple.setArch(Triple::ArchType(Obj->getArch())); + // TheTriple defaults to ELF, and COFF doesn't have an environment: + // the best we can do here is indicate that it is mach-o. + if (Obj->isMachO()) + TheTriple.setEnvironment(Triple::MachO); + } } else TheTriple.setTriple(Triple::normalize(TripleName)); @@ -156,7 +185,52 @@ static const Target *getTarget(const ObjectFile *Obj = NULL) { return TheTarget; } -void llvm::StringRefMemoryObject::anchor() { } +// Write a graphviz file for the CFG inside an MCFunction. +// FIXME: Use GraphWriter +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::const_iterator i = f.begin(), e = f.end(); i != e; ++i) { + // Only print blocks that have predecessors. + bool hasPreds = (*i)->pred_begin() != (*i)->pred_end(); + + if (!hasPreds && i != f.begin()) + continue; + + Out << '"' << (*i)->getInsts()->getBeginAddr() << "\" [ label=\"<a>"; + // Print instructions. + for (unsigned ii = 0, ie = (*i)->getInsts()->size(); ii != ie; + ++ii) { + if (ii != 0) // Not the first line, start a new row. + Out << '|'; + if (ii + 1 == ie) // Last line, add an end id. + Out << "<o>"; + + // Escape special chars and print the instruction in mnemonic form. + std::string Str; + raw_string_ostream OS(Str); + IP->printInst(&(*i)->getInsts()->at(ii).Inst, OS, ""); + Out << DOT::EscapeString(OS.str()); + } + Out << "\" shape=\"record\" ];\n"; + + // Add edges. + for (MCBasicBlock::succ_const_iterator si = (*i)->succ_begin(), + se = (*i)->succ_end(); si != se; ++si) + Out << (*i)->getInsts()->getBeginAddr() << ":o -> " + << (*si)->getInsts()->getBeginAddr() << ":a\n"; + } + Out << "}\n"; +} void llvm::DumpBytes(StringRef bytes) { static const char hex_rep[] = "0123456789abcdef"; @@ -207,6 +281,107 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { FeaturesStr = Features.getString(); } + OwningPtr<const MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); + if (!MRI) { + errs() << "error: no register info for target " << TripleName << "\n"; + return; + } + + // Set up disassembler. + OwningPtr<const MCAsmInfo> AsmInfo( + TheTarget->createMCAsmInfo(*MRI, TripleName)); + if (!AsmInfo) { + errs() << "error: no assembly info for target " << TripleName << "\n"; + return; + } + + OwningPtr<const MCSubtargetInfo> STI( + TheTarget->createMCSubtargetInfo(TripleName, "", FeaturesStr)); + if (!STI) { + errs() << "error: no subtarget info for target " << TripleName << "\n"; + return; + } + + OwningPtr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo()); + if (!MII) { + errs() << "error: no instruction info for target " << TripleName << "\n"; + return; + } + + OwningPtr<MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI)); + if (!DisAsm) { + errs() << "error: no disassembler for target " << TripleName << "\n"; + return; + } + + OwningPtr<const MCObjectFileInfo> MOFI; + OwningPtr<MCContext> Ctx; + + if (Symbolize) { + MOFI.reset(new MCObjectFileInfo); + Ctx.reset(new MCContext(AsmInfo.get(), MRI.get(), MOFI.get())); + OwningPtr<MCRelocationInfo> RelInfo( + TheTarget->createMCRelocationInfo(TripleName, *Ctx.get())); + if (RelInfo) { + OwningPtr<MCSymbolizer> Symzer( + MCObjectSymbolizer::createObjectSymbolizer(*Ctx.get(), RelInfo, Obj)); + if (Symzer) + DisAsm->setSymbolizer(Symzer); + } + } + + OwningPtr<const MCInstrAnalysis> + MIA(TheTarget->createMCInstrAnalysis(MII.get())); + + int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); + OwningPtr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( + AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI)); + if (!IP) { + errs() << "error: no instruction printer for target " << TripleName + << '\n'; + return; + } + + if (CFG || !YAMLCFG.empty()) { + OwningPtr<MCObjectDisassembler> OD( + new MCObjectDisassembler(*Obj, *DisAsm, *MIA)); + OwningPtr<MCModule> Mod(OD->buildModule(/* withCFG */ true)); + for (MCModule::const_atom_iterator AI = Mod->atom_begin(), + AE = Mod->atom_end(); + AI != AE; ++AI) { + outs() << "Atom " << (*AI)->getName() << ": \n"; + if (const MCTextAtom *TA = dyn_cast<MCTextAtom>(*AI)) { + for (MCTextAtom::const_iterator II = TA->begin(), IE = TA->end(); + II != IE; + ++II) { + IP->printInst(&II->Inst, outs(), ""); + outs() << "\n"; + } + } + } + if (CFG) { + for (MCModule::const_func_iterator FI = Mod->func_begin(), + FE = Mod->func_end(); + FI != FE; ++FI) { + static int filenum = 0; + emitDOTFile((Twine((*FI)->getName()) + "_" + + utostr(filenum) + ".dot").str().c_str(), + **FI, IP.get()); + ++filenum; + } + } + if (!YAMLCFG.empty()) { + std::string Error; + raw_fd_ostream YAMLOut(YAMLCFG.c_str(), Error); + if (!Error.empty()) { + errs() << ToolName << ": warning: " << Error << '\n'; + return; + } + mcmodule2yaml(YAMLOut, *Mod, *MII, *MRI); + } + } + + error_code ec; for (section_iterator i = Obj->begin_sections(), e = Obj->end_sections(); @@ -272,53 +447,13 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { if (Symbols.empty()) Symbols.push_back(std::make_pair(0, name)); - // Set up disassembler. - OwningPtr<const MCAsmInfo> AsmInfo(TheTarget->createMCAsmInfo(TripleName)); - - if (!AsmInfo) { - errs() << "error: no assembly info for target " << TripleName << "\n"; - return; - } - - OwningPtr<const MCSubtargetInfo> STI( - TheTarget->createMCSubtargetInfo(TripleName, "", FeaturesStr)); - if (!STI) { - errs() << "error: no subtarget info for target " << TripleName << "\n"; - return; - } - - OwningPtr<const MCDisassembler> DisAsm( - TheTarget->createMCDisassembler(*STI)); - if (!DisAsm) { - errs() << "error: no disassembler for target " << TripleName << "\n"; - return; - } - - OwningPtr<const MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); - if (!MRI) { - errs() << "error: no register info for target " << TripleName << "\n"; - return; - } - - OwningPtr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo()); - if (!MII) { - errs() << "error: no instruction info for target " << TripleName << "\n"; - return; - } - - int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); - OwningPtr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( - AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI)); - if (!IP) { - errs() << "error: no instruction printer for target " << TripleName - << '\n'; - return; - } + SmallString<40> Comments; + raw_svector_ostream CommentStream(Comments); StringRef Bytes; if (error(i->getContents(Bytes))) break; - StringRefMemoryObject memoryObject(Bytes); + StringRefMemoryObject memoryObject(Bytes, SectionAddr); uint64_t Size; uint64_t Index; uint64_t SectSize; @@ -352,14 +487,17 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { for (Index = Start; Index < End; Index += Size) { MCInst Inst; - if (DisAsm->getInstruction(Inst, Size, memoryObject, Index, - DebugOut, nulls())) { + if (DisAsm->getInstruction(Inst, Size, memoryObject, + SectionAddr + Index, + DebugOut, CommentStream)) { outs() << format("%8" PRIx64 ":", SectionAddr + Index); if (!NoShowRawInsn) { outs() << "\t"; DumpBytes(StringRef(Bytes.data() + Index, Size)); } IP->printInst(&Inst, outs(), ""); + outs() << CommentStream.str(); + Comments.clear(); outs() << "\n"; } else { errs() << ToolName << ": warning: invalid instruction encoding\n"; @@ -632,6 +770,14 @@ static void PrintUnwindInfo(const ObjectFile *o) { } } +static void printPrivateFileHeader(const ObjectFile *o) { + if (o->isELF()) { + printELFFileHeader(o); + } else if (o->isCOFF()) { + printCOFFFileHeader(o); + } +} + static void DumpObject(const ObjectFile *o) { outs() << '\n'; outs() << o->getFileName() @@ -649,8 +795,8 @@ static void DumpObject(const ObjectFile *o) { PrintSymbolTable(o); if (UnwindInfo) PrintUnwindInfo(o); - if (PrivateHeaders && o->isELF()) - printELFFileHeader(o); + if (PrivateHeaders) + printPrivateFileHeader(o); } /// @brief Dump each object file in \a a; diff --git a/contrib/llvm/tools/llvm-objdump/llvm-objdump.h b/contrib/llvm/tools/llvm-objdump/llvm-objdump.h index ca7bced..b716a26 100644 --- a/contrib/llvm/tools/llvm-objdump/llvm-objdump.h +++ b/contrib/llvm/tools/llvm-objdump/llvm-objdump.h @@ -13,7 +13,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/DataTypes.h" -#include "llvm/Support/MemoryObject.h" +#include "llvm/Support/StringRefMemoryObject.h" namespace llvm { @@ -34,24 +34,8 @@ void DumpBytes(StringRef bytes); void DisassembleInputMachO(StringRef Filename); void printCOFFUnwindInfo(const object::COFFObjectFile* o); void printELFFileHeader(const object::ObjectFile *o); +void printCOFFFileHeader(const object::ObjectFile *o); -class StringRefMemoryObject : public MemoryObject { - virtual void anchor(); - StringRef Bytes; -public: - StringRefMemoryObject(StringRef bytes) : Bytes(bytes) {} - - uint64_t getBase() const { return 0; } - uint64_t getExtent() const { return Bytes.size(); } - - int readByte(uint64_t Addr, uint8_t *Byte) const { - if (Addr >= getExtent()) - return -1; - *Byte = Bytes[Addr]; - return 0; - } -}; - -} +} // end namespace llvm #endif |