Home | History | Annotate | Download | only in llvm-mc
      1 //===- Disassembler.cpp - Disassembler for hex strings --------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This class implements the disassembler of strings of bytes written in
     11 // hexadecimal, from standard input or from a file.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "Disassembler.h"
     16 #include "llvm/ADT/OwningPtr.h"
     17 #include "llvm/ADT/Triple.h"
     18 #include "llvm/MC/MCDisassembler.h"
     19 #include "llvm/MC/MCInst.h"
     20 #include "llvm/MC/MCStreamer.h"
     21 #include "llvm/MC/MCSubtargetInfo.h"
     22 #include "llvm/Support/MemoryBuffer.h"
     23 #include "llvm/Support/MemoryObject.h"
     24 #include "llvm/Support/SourceMgr.h"
     25 #include "llvm/Support/TargetRegistry.h"
     26 #include "llvm/Support/raw_ostream.h"
     27 
     28 using namespace llvm;
     29 
     30 typedef std::vector<std::pair<unsigned char, const char*> > ByteArrayTy;
     31 
     32 namespace {
     33 class VectorMemoryObject : public MemoryObject {
     34 private:
     35   const ByteArrayTy &Bytes;
     36 public:
     37   VectorMemoryObject(const ByteArrayTy &bytes) : Bytes(bytes) {}
     38 
     39   uint64_t getBase() const { return 0; }
     40   uint64_t getExtent() const { return Bytes.size(); }
     41 
     42   int readByte(uint64_t Addr, uint8_t *Byte) const {
     43     if (Addr >= getExtent())
     44       return -1;
     45     *Byte = Bytes[Addr].first;
     46     return 0;
     47   }
     48 };
     49 }
     50 
     51 static bool PrintInsts(const MCDisassembler &DisAsm,
     52                        const ByteArrayTy &Bytes,
     53                        SourceMgr &SM, raw_ostream &Out,
     54                        MCStreamer &Streamer) {
     55   // Wrap the vector in a MemoryObject.
     56   VectorMemoryObject memoryObject(Bytes);
     57 
     58   // Disassemble it to strings.
     59   uint64_t Size;
     60   uint64_t Index;
     61 
     62   for (Index = 0; Index < Bytes.size(); Index += Size) {
     63     MCInst Inst;
     64 
     65     MCDisassembler::DecodeStatus S;
     66     S = DisAsm.getInstruction(Inst, Size, memoryObject, Index,
     67                               /*REMOVE*/ nulls(), nulls());
     68     switch (S) {
     69     case MCDisassembler::Fail:
     70       SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second),
     71                       SourceMgr::DK_Warning,
     72                       "invalid instruction encoding");
     73       if (Size == 0)
     74         Size = 1; // skip illegible bytes
     75       break;
     76 
     77     case MCDisassembler::SoftFail:
     78       SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second),
     79                       SourceMgr::DK_Warning,
     80                       "potentially undefined instruction encoding");
     81       // Fall through
     82 
     83     case MCDisassembler::Success:
     84       Streamer.EmitInstruction(Inst);
     85       break;
     86     }
     87   }
     88 
     89   return false;
     90 }
     91 
     92 static bool ByteArrayFromString(ByteArrayTy &ByteArray,
     93                                 StringRef &Str,
     94                                 SourceMgr &SM) {
     95   while (!Str.empty()) {
     96     // Strip horizontal whitespace.
     97     if (size_t Pos = Str.find_first_not_of(" \t\r")) {
     98       Str = Str.substr(Pos);
     99       continue;
    100     }
    101 
    102     // If this is the end of a line or start of a comment, remove the rest of
    103     // the line.
    104     if (Str[0] == '\n' || Str[0] == '#') {
    105       // Strip to the end of line if we already processed any bytes on this
    106       // line.  This strips the comment and/or the \n.
    107       if (Str[0] == '\n') {
    108         Str = Str.substr(1);
    109       } else {
    110         Str = Str.substr(Str.find_first_of('\n'));
    111         if (!Str.empty())
    112           Str = Str.substr(1);
    113       }
    114       continue;
    115     }
    116 
    117     // Get the current token.
    118     size_t Next = Str.find_first_of(" \t\n\r#");
    119     StringRef Value = Str.substr(0, Next);
    120 
    121     // Convert to a byte and add to the byte vector.
    122     unsigned ByteVal;
    123     if (Value.getAsInteger(0, ByteVal) || ByteVal > 255) {
    124       // If we have an error, print it and skip to the end of line.
    125       SM.PrintMessage(SMLoc::getFromPointer(Value.data()), SourceMgr::DK_Error,
    126                       "invalid input token");
    127       Str = Str.substr(Str.find('\n'));
    128       ByteArray.clear();
    129       continue;
    130     }
    131 
    132     ByteArray.push_back(std::make_pair((unsigned char)ByteVal, Value.data()));
    133     Str = Str.substr(Next);
    134   }
    135 
    136   return false;
    137 }
    138 
    139 int Disassembler::disassemble(const Target &T,
    140                               const std::string &Triple,
    141                               MCSubtargetInfo &STI,
    142                               MCStreamer &Streamer,
    143                               MemoryBuffer &Buffer,
    144                               SourceMgr &SM,
    145                               raw_ostream &Out) {
    146   OwningPtr<const MCDisassembler> DisAsm(T.createMCDisassembler(STI));
    147   if (!DisAsm) {
    148     errs() << "error: no disassembler for target " << Triple << "\n";
    149     return -1;
    150   }
    151 
    152   // Set up initial section manually here
    153   Streamer.InitSections();
    154 
    155   bool ErrorOccurred = false;
    156 
    157   // Convert the input to a vector for disassembly.
    158   ByteArrayTy ByteArray;
    159   StringRef Str = Buffer.getBuffer();
    160 
    161   ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM);
    162 
    163   if (!ByteArray.empty())
    164     ErrorOccurred |= PrintInsts(*DisAsm, ByteArray, SM, Out, Streamer);
    165 
    166   return ErrorOccurred;
    167 }
    168