Disassembler.cpp revision d374087be5360a353a4239a155b1227057145f48
1a3dcfb130044f306632a5fab43854eda4095a09cChris Lattner//===- Disassembler.cpp - Disassembler for hex strings --------------------===//
2ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan//
3ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan//                     The LLVM Compiler Infrastructure
4ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan//
5ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan// This file is distributed under the University of Illinois Open Source
6ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan// License. See LICENSE.TXT for details.
7ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan//
8ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan//===----------------------------------------------------------------------===//
9ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan//
10ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan// This class implements the disassembler of strings of bytes written in
11ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan// hexadecimal, from standard input or from a file.
12ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan//
13ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan//===----------------------------------------------------------------------===//
14ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan
15a3dcfb130044f306632a5fab43854eda4095a09cChris Lattner#include "Disassembler.h"
16ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan
17ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan#include "llvm/ADT/OwningPtr.h"
18ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan#include "llvm/MC/MCAsmInfo.h"
19ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan#include "llvm/MC/MCDisassembler.h"
20ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan#include "llvm/MC/MCInst.h"
21ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan#include "llvm/MC/MCInstPrinter.h"
22ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan#include "llvm/Target/TargetRegistry.h"
23ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan#include "llvm/Support/MemoryBuffer.h"
24ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan#include "llvm/Support/MemoryObject.h"
25ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan#include "llvm/Support/raw_ostream.h"
26c3de94fabf3858ad57373171fa6bda407f2224c9Chris Lattner#include "llvm/Support/SourceMgr.h"
27ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callananusing namespace llvm;
28ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan
29665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattnertypedef std::vector<std::pair<unsigned char, const char*> > ByteArrayTy;
30665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner
31665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattnernamespace {
32ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callananclass VectorMemoryObject : public MemoryObject {
33ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callananprivate:
34665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner  const ByteArrayTy &Bytes;
35ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callananpublic:
36665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner  VectorMemoryObject(const ByteArrayTy &bytes) : Bytes(bytes) {}
37ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan
38665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner  uint64_t getBase() const { return 0; }
39665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner  uint64_t getExtent() const { return Bytes.size(); }
40ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan
41665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner  int readByte(uint64_t Addr, uint8_t *Byte) const {
42665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner    if (Addr > getExtent())
43ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan      return -1;
44665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner    *Byte = Bytes[Addr].first;
45ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan    return 0;
46ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan  }
47ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan};
48665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner}
49ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan
50c6ab1901f922c854c84e9e055cbc83601df80addDaniel Dunbarstatic bool PrintInsts(const MCDisassembler &DisAsm,
51d374087be5360a353a4239a155b1227057145f48Chris Lattner                       MCInstPrinter &Printer, const ByteArrayTy &Bytes,
52d374087be5360a353a4239a155b1227057145f48Chris Lattner                       SourceMgr &SM) {
53ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan  // Wrap the vector in a MemoryObject.
54665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner  VectorMemoryObject memoryObject(Bytes);
55ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan
562e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan  // Disassemble it to strings.
57665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner  uint64_t Size;
582e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan  uint64_t Index;
59ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan
602e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan  for (Index = 0; Index < Bytes.size(); Index += Size) {
612e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan    MCInst Inst;
622e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan
632e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan    if (DisAsm.getInstruction(Inst, Size, memoryObject, Index,
642e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan                               /*REMOVE*/ nulls())) {
65d374087be5360a353a4239a155b1227057145f48Chris Lattner      Printer.printInst(&Inst, outs());
662e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan      outs() << "\n";
672e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan    }
682e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan    else {
692e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan      SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second),
702e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan                      "invalid instruction encoding", "warning");
712e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan      if (Size == 0)
722e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan        Size = 1; // skip illegible bytes
732e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan    }
74ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan  }
75665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner
76665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner  return false;
77ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan}
78ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan
79a3dcfb130044f306632a5fab43854eda4095a09cChris Lattnerint Disassembler::disassemble(const Target &T, const std::string &Triple,
80c6ab1901f922c854c84e9e055cbc83601df80addDaniel Dunbar                              MemoryBuffer &Buffer) {
81222af464822c9c47b2859e813912ed6ba5339217Chris Lattner  // Set up disassembler.
82c6ab1901f922c854c84e9e055cbc83601df80addDaniel Dunbar  OwningPtr<const MCAsmInfo> AsmInfo(T.createAsmInfo(Triple));
83ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan
84222af464822c9c47b2859e813912ed6ba5339217Chris Lattner  if (!AsmInfo) {
85222af464822c9c47b2859e813912ed6ba5339217Chris Lattner    errs() << "error: no assembly info for target " << Triple << "\n";
86ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan    return -1;
87ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan  }
88ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan
89c6ab1901f922c854c84e9e055cbc83601df80addDaniel Dunbar  OwningPtr<const MCDisassembler> DisAsm(T.createMCDisassembler());
90222af464822c9c47b2859e813912ed6ba5339217Chris Lattner  if (!DisAsm) {
91222af464822c9c47b2859e813912ed6ba5339217Chris Lattner    errs() << "error: no disassembler for target " << Triple << "\n";
92ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan    return -1;
93ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan  }
94ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan
95d374087be5360a353a4239a155b1227057145f48Chris Lattner  OwningPtr<MCInstPrinter> IP(T.createMCInstPrinter(0, *AsmInfo));
96c6ab1901f922c854c84e9e055cbc83601df80addDaniel Dunbar  if (!IP) {
97665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner    errs() << "error: no instruction printer for target " << Triple << '\n';
98ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan    return -1;
99ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan  }
100ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan
101665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner  bool ErrorOccurred = false;
102665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner
103665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner  SourceMgr SM;
104665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner  SM.AddNewSourceBuffer(&Buffer, SMLoc());
105c3de94fabf3858ad57373171fa6bda407f2224c9Chris Lattner
106ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan  // Convert the input to a vector for disassembly.
107665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner  ByteArrayTy ByteArray;
108ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan
109222af464822c9c47b2859e813912ed6ba5339217Chris Lattner  StringRef Str = Buffer.getBuffer();
110222af464822c9c47b2859e813912ed6ba5339217Chris Lattner  while (!Str.empty()) {
1112adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner    // Strip horizontal whitespace.
1122adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner    if (size_t Pos = Str.find_first_not_of(" \t\r")) {
1132adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner      Str = Str.substr(Pos);
1142adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner      continue;
1152adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner    }
1162adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner
1172e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan    // If this is the end of a line or start of a comment, remove the rest of
1182e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan    // the line.
1192adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner    if (Str[0] == '\n' || Str[0] == '#') {
1202adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner      // Strip to the end of line if we already processed any bytes on this
1212adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner      // line.  This strips the comment and/or the \n.
1222adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner      if (Str[0] == '\n')
1232adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner        Str = Str.substr(1);
1242adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner      else {
1252adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner        Str = Str.substr(Str.find_first_of('\n'));
1262adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner        if (!Str.empty())
1272adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner          Str = Str.substr(1);
1282adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner      }
1292adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner      continue;
130ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan    }
131ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan
132ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan    // Get the current token.
1332adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner    size_t Next = Str.find_first_of(" \t\n\r#");
1342adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner    StringRef Value = Str.substr(0, Next);
135ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan
136ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan    // Convert to a byte and add to the byte vector.
137222af464822c9c47b2859e813912ed6ba5339217Chris Lattner    unsigned ByteVal;
138222af464822c9c47b2859e813912ed6ba5339217Chris Lattner    if (Value.getAsInteger(0, ByteVal) || ByteVal > 255) {
139c3de94fabf3858ad57373171fa6bda407f2224c9Chris Lattner      // If we have an error, print it and skip to the end of line.
140665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner      SM.PrintMessage(SMLoc::getFromPointer(Value.data()),
141c3de94fabf3858ad57373171fa6bda407f2224c9Chris Lattner                                 "invalid input token", "error");
142665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner      ErrorOccurred = true;
143c3de94fabf3858ad57373171fa6bda407f2224c9Chris Lattner      Str = Str.substr(Str.find('\n'));
144c3de94fabf3858ad57373171fa6bda407f2224c9Chris Lattner      ByteArray.clear();
145c3de94fabf3858ad57373171fa6bda407f2224c9Chris Lattner      continue;
146ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan    }
147c3de94fabf3858ad57373171fa6bda407f2224c9Chris Lattner
148665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner    ByteArray.push_back(std::make_pair((unsigned char)ByteVal, Value.data()));
149222af464822c9c47b2859e813912ed6ba5339217Chris Lattner    Str = Str.substr(Next);
150ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan  }
151ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan
152222af464822c9c47b2859e813912ed6ba5339217Chris Lattner  if (!ByteArray.empty())
153c6ab1901f922c854c84e9e055cbc83601df80addDaniel Dunbar    ErrorOccurred |= PrintInsts(*DisAsm, *IP, ByteArray, SM);
154ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan
155665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner  return ErrorOccurred;
156ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan}
157