1201360Srdivacky//===- Disassembler.cpp - Disassembler for hex strings --------------------===// 2201360Srdivacky// 3201360Srdivacky// The LLVM Compiler Infrastructure 4201360Srdivacky// 5201360Srdivacky// This file is distributed under the University of Illinois Open Source 6201360Srdivacky// License. See LICENSE.TXT for details. 7201360Srdivacky// 8201360Srdivacky//===----------------------------------------------------------------------===// 9201360Srdivacky// 10201360Srdivacky// This class implements the disassembler of strings of bytes written in 11201360Srdivacky// hexadecimal, from standard input or from a file. 12201360Srdivacky// 13201360Srdivacky//===----------------------------------------------------------------------===// 14201360Srdivacky 15201360Srdivacky#include "Disassembler.h" 16249423Sdim#include "llvm/ADT/OwningPtr.h" 17249423Sdim#include "llvm/ADT/Triple.h" 18201360Srdivacky#include "llvm/MC/MCDisassembler.h" 19201360Srdivacky#include "llvm/MC/MCInst.h" 20234982Sdim#include "llvm/MC/MCStreamer.h" 21226584Sdim#include "llvm/MC/MCSubtargetInfo.h" 22201360Srdivacky#include "llvm/Support/MemoryBuffer.h" 23201360Srdivacky#include "llvm/Support/MemoryObject.h" 24226584Sdim#include "llvm/Support/SourceMgr.h" 25226584Sdim#include "llvm/Support/TargetRegistry.h" 26201360Srdivacky#include "llvm/Support/raw_ostream.h" 27234982Sdim 28201360Srdivackyusing namespace llvm; 29201360Srdivacky 30201360Srdivackytypedef std::vector<std::pair<unsigned char, const char*> > ByteArrayTy; 31201360Srdivacky 32201360Srdivackynamespace { 33201360Srdivackyclass VectorMemoryObject : public MemoryObject { 34201360Srdivackyprivate: 35201360Srdivacky const ByteArrayTy &Bytes; 36201360Srdivackypublic: 37201360Srdivacky VectorMemoryObject(const ByteArrayTy &bytes) : Bytes(bytes) {} 38223013Sdim 39201360Srdivacky uint64_t getBase() const { return 0; } 40201360Srdivacky uint64_t getExtent() const { return Bytes.size(); } 41201360Srdivacky 42201360Srdivacky int readByte(uint64_t Addr, uint8_t *Byte) const { 43218885Sdim if (Addr >= getExtent()) 44201360Srdivacky return -1; 45201360Srdivacky *Byte = Bytes[Addr].first; 46201360Srdivacky return 0; 47201360Srdivacky } 48201360Srdivacky}; 49201360Srdivacky} 50201360Srdivacky 51205407Srdivackystatic bool PrintInsts(const MCDisassembler &DisAsm, 52234982Sdim const ByteArrayTy &Bytes, 53234982Sdim SourceMgr &SM, raw_ostream &Out, 54263508Sdim MCStreamer &Streamer, bool InAtomicBlock) { 55201360Srdivacky // Wrap the vector in a MemoryObject. 56201360Srdivacky VectorMemoryObject memoryObject(Bytes); 57223013Sdim 58203954Srdivacky // Disassemble it to strings. 59201360Srdivacky uint64_t Size; 60203954Srdivacky uint64_t Index; 61223013Sdim 62203954Srdivacky for (Index = 0; Index < Bytes.size(); Index += Size) { 63203954Srdivacky MCInst Inst; 64223013Sdim 65226584Sdim MCDisassembler::DecodeStatus S; 66226584Sdim S = DisAsm.getInstruction(Inst, Size, memoryObject, Index, 67226584Sdim /*REMOVE*/ nulls(), nulls()); 68226584Sdim switch (S) { 69226584Sdim case MCDisassembler::Fail: 70203954Srdivacky SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second), 71234353Sdim SourceMgr::DK_Warning, 72234353Sdim "invalid instruction encoding"); 73263508Sdim // Don't try to resynchronise the stream in a block 74263508Sdim if (InAtomicBlock) 75263508Sdim return true; 76263508Sdim 77203954Srdivacky if (Size == 0) 78203954Srdivacky Size = 1; // skip illegible bytes 79263508Sdim 80226584Sdim break; 81226584Sdim 82226584Sdim case MCDisassembler::SoftFail: 83226584Sdim SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second), 84234353Sdim SourceMgr::DK_Warning, 85234353Sdim "potentially undefined instruction encoding"); 86226584Sdim // Fall through 87226584Sdim 88226584Sdim case MCDisassembler::Success: 89234982Sdim Streamer.EmitInstruction(Inst); 90226584Sdim break; 91203954Srdivacky } 92201360Srdivacky } 93223013Sdim 94201360Srdivacky return false; 95201360Srdivacky} 96201360Srdivacky 97263508Sdimstatic bool SkipToToken(StringRef &Str) { 98263508Sdim while (!Str.empty() && Str.find_first_not_of(" \t\r\n#,") != 0) { 99263508Sdim // Strip horizontal whitespace and commas. 100263508Sdim if (size_t Pos = Str.find_first_not_of(" \t\r,")) { 101201360Srdivacky Str = Str.substr(Pos); 102201360Srdivacky } 103223013Sdim 104203954Srdivacky // If this is the end of a line or start of a comment, remove the rest of 105203954Srdivacky // the line. 106201360Srdivacky if (Str[0] == '\n' || Str[0] == '#') { 107201360Srdivacky // Strip to the end of line if we already processed any bytes on this 108201360Srdivacky // line. This strips the comment and/or the \n. 109207618Srdivacky if (Str[0] == '\n') { 110201360Srdivacky Str = Str.substr(1); 111207618Srdivacky } else { 112201360Srdivacky Str = Str.substr(Str.find_first_of('\n')); 113201360Srdivacky if (!Str.empty()) 114201360Srdivacky Str = Str.substr(1); 115201360Srdivacky } 116201360Srdivacky continue; 117201360Srdivacky } 118263508Sdim } 119223013Sdim 120263508Sdim return !Str.empty(); 121263508Sdim} 122263508Sdim 123263508Sdim 124263508Sdimstatic bool ByteArrayFromString(ByteArrayTy &ByteArray, 125263508Sdim StringRef &Str, 126263508Sdim SourceMgr &SM) { 127263508Sdim while (SkipToToken(Str)) { 128263508Sdim // Handled by higher level 129263508Sdim if (Str[0] == '[' || Str[0] == ']') 130263508Sdim return false; 131263508Sdim 132201360Srdivacky // Get the current token. 133263508Sdim size_t Next = Str.find_first_of(" \t\n\r,#[]"); 134201360Srdivacky StringRef Value = Str.substr(0, Next); 135223013Sdim 136201360Srdivacky // Convert to a byte and add to the byte vector. 137201360Srdivacky unsigned ByteVal; 138201360Srdivacky if (Value.getAsInteger(0, ByteVal) || ByteVal > 255) { 139201360Srdivacky // If we have an error, print it and skip to the end of line. 140234353Sdim SM.PrintMessage(SMLoc::getFromPointer(Value.data()), SourceMgr::DK_Error, 141234353Sdim "invalid input token"); 142201360Srdivacky Str = Str.substr(Str.find('\n')); 143201360Srdivacky ByteArray.clear(); 144201360Srdivacky continue; 145201360Srdivacky } 146223013Sdim 147201360Srdivacky ByteArray.push_back(std::make_pair((unsigned char)ByteVal, Value.data())); 148201360Srdivacky Str = Str.substr(Next); 149201360Srdivacky } 150223013Sdim 151207618Srdivacky return false; 152207618Srdivacky} 153207618Srdivacky 154224133Sdimint Disassembler::disassemble(const Target &T, 155221337Sdim const std::string &Triple, 156234982Sdim MCSubtargetInfo &STI, 157234982Sdim MCStreamer &Streamer, 158212793Sdim MemoryBuffer &Buffer, 159234982Sdim SourceMgr &SM, 160212793Sdim raw_ostream &Out) { 161234982Sdim OwningPtr<const MCDisassembler> DisAsm(T.createMCDisassembler(STI)); 162207618Srdivacky if (!DisAsm) { 163207618Srdivacky errs() << "error: no disassembler for target " << Triple << "\n"; 164207618Srdivacky return -1; 165207618Srdivacky } 166223013Sdim 167234982Sdim // Set up initial section manually here 168234982Sdim Streamer.InitSections(); 169234353Sdim 170207618Srdivacky bool ErrorOccurred = false; 171223013Sdim 172207618Srdivacky // Convert the input to a vector for disassembly. 173207618Srdivacky ByteArrayTy ByteArray; 174207618Srdivacky StringRef Str = Buffer.getBuffer(); 175263508Sdim bool InAtomicBlock = false; 176223013Sdim 177263508Sdim while (SkipToToken(Str)) { 178263508Sdim ByteArray.clear(); 179223013Sdim 180263508Sdim if (Str[0] == '[') { 181263508Sdim if (InAtomicBlock) { 182263508Sdim SM.PrintMessage(SMLoc::getFromPointer(Str.data()), SourceMgr::DK_Error, 183263508Sdim "nested atomic blocks make no sense"); 184263508Sdim ErrorOccurred = true; 185263508Sdim } 186263508Sdim InAtomicBlock = true; 187263508Sdim Str = Str.drop_front(); 188263508Sdim continue; 189263508Sdim } else if (Str[0] == ']') { 190263508Sdim if (!InAtomicBlock) { 191263508Sdim SM.PrintMessage(SMLoc::getFromPointer(Str.data()), SourceMgr::DK_Error, 192263508Sdim "attempt to close atomic block without opening"); 193263508Sdim ErrorOccurred = true; 194263508Sdim } 195263508Sdim InAtomicBlock = false; 196263508Sdim Str = Str.drop_front(); 197263508Sdim continue; 198263508Sdim } 199223013Sdim 200263508Sdim // It's a real token, get the bytes and emit them 201263508Sdim ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM); 202263508Sdim 203263508Sdim if (!ByteArray.empty()) 204263508Sdim ErrorOccurred |= PrintInsts(*DisAsm, ByteArray, SM, Out, Streamer, 205263508Sdim InAtomicBlock); 206263508Sdim } 207263508Sdim 208263508Sdim if (InAtomicBlock) { 209263508Sdim SM.PrintMessage(SMLoc::getFromPointer(Str.data()), SourceMgr::DK_Error, 210263508Sdim "unclosed atomic block"); 211263508Sdim ErrorOccurred = true; 212263508Sdim } 213263508Sdim 214201360Srdivacky return ErrorOccurred; 215201360Srdivacky} 216