Remove MCObjectDisassembler.cpp as it is untested and unused.
[oota-llvm.git] / tools / llvm-objdump / MachODump.cpp
index 1ee3e42dab7f40178e12d1be0c1c2d0a610b0fcc..1c893ea3fad94f0364f02013ce5bce3d2108aa74 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #include "llvm-objdump.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"
+#include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCDisassembler.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCInstPrinter.h"
@@ -37,9 +37,9 @@
 #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>
+#include <system_error>
 using namespace llvm;
 using namespace object;
 
@@ -65,7 +65,7 @@ static const Target *GetTarget(const MachOObjectFile *MachOObj) {
 
   errs() << "llvm-objdump: error: unable to get target for '" << TripleName
          << "', see --version and --triple.\n";
-  return 0;
+  return nullptr;
 }
 
 struct SymbolSorter {
@@ -87,38 +87,104 @@ struct SymbolSorter {
   }
 };
 
-static void
-getSectionsAndSymbols(const macho::Header Header,
-                      MachOObjectFile *MachOObj,
-                      std::vector<SectionRef> &Sections,
-                      std::vector<SymbolRef> &Symbols,
-                      SmallVectorImpl<uint64_t> &FoundFns) {
-  error_code ec;
-  for (symbol_iterator SI = MachOObj->begin_symbols(),
-       SE = MachOObj->end_symbols(); SI != SE; SI.increment(ec))
-    Symbols.push_back(*SI);
-
-  for (section_iterator SI = MachOObj->begin_sections(),
-       SE = MachOObj->end_sections(); SI != SE; SI.increment(ec)) {
-    SectionRef SR = *SI;
+// 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;
+
+static bool
+compareDiceTableEntries(const DiceTableEntry i,
+                        const DiceTableEntry j) {
+  return i.first == j.first;
+}
+
+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;
+    }
+    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;
+  }
+}
+
+static void getSectionsAndSymbols(const MachO::mach_header Header,
+                                  MachOObjectFile *MachOObj,
+                                  std::vector<SectionRef> &Sections,
+                                  std::vector<SymbolRef> &Symbols,
+                                  SmallVectorImpl<uint64_t> &FoundFns,
+                                  uint64_t &BaseSegmentAddress) {
+  for (const SymbolRef &Symbol : MachOObj->symbols())
+    Symbols.push_back(Symbol);
+
+  for (const SectionRef &Section : MachOObj->sections()) {
     StringRef SectName;
-    SR.getName(SectName);
-    Sections.push_back(*SI);
+    Section.getName(SectName);
+    Sections.push_back(Section);
   }
 
   MachOObjectFile::LoadCommandInfo Command =
-    MachOObj->getFirstLoadCommandInfo();
+      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);
@@ -129,15 +195,15 @@ static void DisassembleInputMachO2(StringRef Filename,
                                    MachOObjectFile *MachOOF);
 
 void llvm::DisassembleInputMachO(StringRef Filename) {
-  OwningPtr<MemoryBuffer> Buff;
-
-  if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
-    errs() << "llvm-objdump: " << Filename << ": " << ec.message() << "\n";
+  ErrorOr<std::unique_ptr<MemoryBuffer>> Buff =
+      MemoryBuffer::getFileOrSTDIN(Filename);
+  if (std::error_code EC = Buff.getError()) {
+    errs() << "llvm-objdump: " << Filename << ": " << EC.message() << "\n";
     return;
   }
 
-  OwningPtr<MachOObjectFile> MachOOF(static_cast<MachOObjectFile*>(
-        ObjectFile::createMachOObjectFile(Buff.take())));
+  std::unique_ptr<MachOObjectFile> MachOOF =
+    std::move(ObjectFile::createMachOObjectFile(Buff.get()).get());
 
   DisassembleInputMachO2(Filename, MachOOF.get());
 }
@@ -149,21 +215,23 @@ static void DisassembleInputMachO2(StringRef Filename,
     // GetTarget prints out stuff.
     return;
   }
-  OwningPtr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo());
-  OwningPtr<MCInstrAnalysis>
-    InstrAnalysis(TheTarget->createMCInstrAnalysis(InstrInfo.get()));
+  std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo());
+  std::unique_ptr<MCInstrAnalysis> InstrAnalysis(
+      TheTarget->createMCInstrAnalysis(InstrInfo.get()));
 
   // Set up disassembler.
-  OwningPtr<const MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
-  OwningPtr<const MCAsmInfo> AsmInfo(
+  std::unique_ptr<const MCRegisterInfo> MRI(
+      TheTarget->createMCRegInfo(TripleName));
+  std::unique_ptr<const MCAsmInfo> AsmInfo(
       TheTarget->createMCAsmInfo(*MRI, TripleName));
-  OwningPtr<const MCSubtargetInfo>
-    STI(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
-  OwningPtr<const MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI));
+  std::unique_ptr<const MCSubtargetInfo> STI(
+      TheTarget->createMCSubtargetInfo(TripleName, "", ""));
+  MCContext Ctx(AsmInfo.get(), MRI.get(), nullptr);
+  std::unique_ptr<const MCDisassembler> DisAsm(
+    TheTarget->createMCDisassembler(*STI, Ctx));
   int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
-  OwningPtr<MCInstPrinter>
-    IP(TheTarget->createMCInstPrinter(AsmPrinterVariant, *AsmInfo, *InstrInfo,
-                                      *MRI, *STI));
+  std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
+      AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI, *STI));
 
   if (!InstrAnalysis || !AsmInfo || !STI || !DisAsm || !IP) {
     errs() << "error: couldn't initialize disassembler for target "
@@ -173,7 +241,7 @@ 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.
@@ -184,37 +252,53 @@ static void DisassembleInputMachO2(StringRef Filename,
   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;
+  for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices();
+       DI != DE; ++DI) {
+    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
   raw_ostream &DebugOut = nulls();
 #endif
 
-  OwningPtr<DIContext> diContext;
+  std::unique_ptr<DIContext> diContext;
   ObjectFile *DbgObj = MachOOF;
   // Try to find debug info and set up the DIContext for it.
   if (UseDbg) {
     // 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';
+      ErrorOr<std::unique_ptr<MemoryBuffer>> Buf =
+          MemoryBuffer::getFileOrSTDIN(DSYMFile);
+      if (std::error_code EC = Buf.getError()) {
+        errs() << "llvm-objdump: " << Filename << ": " << EC.message() << '\n';
         return;
       }
-      DbgObj = ObjectFile::createMachOObjectFile(Buf.take());
+      DbgObj = ObjectFile::createMachOObjectFile(Buf.get()).get().release();
     }
 
     // Setup the DIContext
-    diContext.reset(DIContext::getDWARFContext(DbgObj));
+    diContext.reset(DIContext::getDWARFContext(*DbgObj));
   }
 
   for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) {
@@ -241,16 +325,14 @@ static void DisassembleInputMachO2(StringRef Filename,
     bool symbolTableWorked = false;
 
     // Parse relocations.
-    std::vector<std::pair<uint64_t, SymbolRef> > Relocs;
-    error_code ec;
-    for (relocation_iterator RI = Sections[SectIdx].begin_relocations(),
-         RE = Sections[SectIdx].end_relocations(); RI != RE; RI.increment(ec)) {
+    std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
+    for (const RelocationRef &Reloc : Sections[SectIdx].relocations()) {
       uint64_t RelocOffset, SectionAddress;
-      RI->getOffset(RelocOffset);
+      Reloc.getOffset(RelocOffset);
       Sections[SectIdx].getAddress(SectionAddress);
       RelocOffset -= SectionAddress;
 
-      symbol_iterator RelocSym = RI->getSymbol();
+      symbol_iterator RelocSym = Reloc.getSymbol();
 
       Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
     }
@@ -309,12 +391,29 @@ static void DisassembleInputMachO2(StringRef Filename,
       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())) {
-          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(), "");
 
@@ -323,9 +422,9 @@ static void DisassembleInputMachO2(StringRef Filename,
             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();
+            if (dli != lastLine && dli.Line != 0)
+              outs() << "\t## " << dli.FileName << ':' << dli.Line << ':'
+                     << dli.Column;
             lastLine = dli;
           }
           outs() << "\n";