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" 16f010c464a11444733ec67e31aace8bcebeaf2588Chandler Carruth#include "llvm/ADT/OwningPtr.h" 17f010c464a11444733ec67e31aace8bcebeaf2588Chandler Carruth#include "llvm/ADT/Triple.h" 18ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan#include "llvm/MC/MCDisassembler.h" 19ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan#include "llvm/MC/MCInst.h" 20d0c478d95f440b4db76279fe47d6cf734a28fa9aRichard Barton#include "llvm/MC/MCStreamer.h" 21b950585cc5a0d665e9accfe5ce490cd269756f2eJames Molloy#include "llvm/MC/MCSubtargetInfo.h" 22ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan#include "llvm/Support/MemoryBuffer.h" 23ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan#include "llvm/Support/MemoryObject.h" 24c3de94fabf3858ad57373171fa6bda407f2224c9Chris Lattner#include "llvm/Support/SourceMgr.h" 253e74d6fdd248e20a280f1dff3da9a6c689c2c4c3Evan Cheng#include "llvm/Support/TargetRegistry.h" 263e74d6fdd248e20a280f1dff3da9a6c689c2c4c3Evan Cheng#include "llvm/Support/raw_ostream.h" 27d0c478d95f440b4db76279fe47d6cf734a28fa9aRichard Barton 28ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callananusing namespace llvm; 29ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan 30665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattnertypedef std::vector<std::pair<unsigned char, const char*> > ByteArrayTy; 31665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner 32665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattnernamespace { 33ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callananclass VectorMemoryObject : public MemoryObject { 34ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callananprivate: 35665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner const ByteArrayTy &Bytes; 36ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callananpublic: 37665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner VectorMemoryObject(const ByteArrayTy &bytes) : Bytes(bytes) {} 38f5bf3cf7e2a0ff1ca884a83a8b56b5a57f8a5c80Jim Grosbach 39665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner uint64_t getBase() const { return 0; } 40adef06a71458ded0716935a61b3d43d164d4df12Derek Schuff uint64_t getExtent() const { return Bytes.size(); } 41ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan 42adef06a71458ded0716935a61b3d43d164d4df12Derek Schuff int readByte(uint64_t Addr, uint8_t *Byte) const { 432f867a63daf99dc27830d4442a574a790e02f27eRafael Espindola if (Addr >= getExtent()) 44ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan return -1; 45665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner *Byte = Bytes[Addr].first; 46ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan return 0; 47ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan } 48ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan}; 49665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner} 50ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan 51c6ab1901f922c854c84e9e055cbc83601df80addDaniel Dunbarstatic bool PrintInsts(const MCDisassembler &DisAsm, 52d0c478d95f440b4db76279fe47d6cf734a28fa9aRichard Barton const ByteArrayTy &Bytes, 53d0c478d95f440b4db76279fe47d6cf734a28fa9aRichard Barton SourceMgr &SM, raw_ostream &Out, 54d0c478d95f440b4db76279fe47d6cf734a28fa9aRichard Barton MCStreamer &Streamer) { 55ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan // Wrap the vector in a MemoryObject. 56665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner VectorMemoryObject memoryObject(Bytes); 57f5bf3cf7e2a0ff1ca884a83a8b56b5a57f8a5c80Jim Grosbach 582e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan // Disassemble it to strings. 59665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner uint64_t Size; 602e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan uint64_t Index; 61f5bf3cf7e2a0ff1ca884a83a8b56b5a57f8a5c80Jim Grosbach 622e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan for (Index = 0; Index < Bytes.size(); Index += Size) { 632e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan MCInst Inst; 64f5bf3cf7e2a0ff1ca884a83a8b56b5a57f8a5c80Jim Grosbach 6583e3f67fb68d497b600da83a62f000fcce7868a9Owen Anderson MCDisassembler::DecodeStatus S; 6683e3f67fb68d497b600da83a62f000fcce7868a9Owen Anderson S = DisAsm.getInstruction(Inst, Size, memoryObject, Index, 6798c5ddabca1debf935a07d14d0cbc9732374bdb8Owen Anderson /*REMOVE*/ nulls(), nulls()); 6883e3f67fb68d497b600da83a62f000fcce7868a9Owen Anderson switch (S) { 6983e3f67fb68d497b600da83a62f000fcce7868a9Owen Anderson case MCDisassembler::Fail: 702e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second), 713f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner SourceMgr::DK_Warning, 723f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner "invalid instruction encoding"); 732e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan if (Size == 0) 742e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan Size = 1; // skip illegible bytes 7583e3f67fb68d497b600da83a62f000fcce7868a9Owen Anderson break; 7683e3f67fb68d497b600da83a62f000fcce7868a9Owen Anderson 7783e3f67fb68d497b600da83a62f000fcce7868a9Owen Anderson case MCDisassembler::SoftFail: 7883e3f67fb68d497b600da83a62f000fcce7868a9Owen Anderson SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second), 793f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner SourceMgr::DK_Warning, 803f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner "potentially undefined instruction encoding"); 8183e3f67fb68d497b600da83a62f000fcce7868a9Owen Anderson // Fall through 8283e3f67fb68d497b600da83a62f000fcce7868a9Owen Anderson 8383e3f67fb68d497b600da83a62f000fcce7868a9Owen Anderson case MCDisassembler::Success: 84d0c478d95f440b4db76279fe47d6cf734a28fa9aRichard Barton Streamer.EmitInstruction(Inst); 8583e3f67fb68d497b600da83a62f000fcce7868a9Owen Anderson break; 862e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan } 87ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan } 88f5bf3cf7e2a0ff1ca884a83a8b56b5a57f8a5c80Jim Grosbach 89665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner return false; 90ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan} 91ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan 92f5bf3cf7e2a0ff1ca884a83a8b56b5a57f8a5c80Jim Grosbachstatic bool ByteArrayFromString(ByteArrayTy &ByteArray, 93f5bf3cf7e2a0ff1ca884a83a8b56b5a57f8a5c80Jim Grosbach StringRef &Str, 94668b15467be158a5f0e0c4a5e1ec232da021892cSean Callanan SourceMgr &SM) { 95222af464822c9c47b2859e813912ed6ba5339217Chris Lattner while (!Str.empty()) { 962adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner // Strip horizontal whitespace. 972adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner if (size_t Pos = Str.find_first_not_of(" \t\r")) { 982adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner Str = Str.substr(Pos); 992adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner continue; 1002adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner } 101f5bf3cf7e2a0ff1ca884a83a8b56b5a57f8a5c80Jim Grosbach 1022e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan // If this is the end of a line or start of a comment, remove the rest of 1032e235a826d2f65a064b2a39b27c775d0adf8b7c3Sean Callanan // the line. 1042adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner if (Str[0] == '\n' || Str[0] == '#') { 1052adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner // Strip to the end of line if we already processed any bytes on this 1062adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner // line. This strips the comment and/or the \n. 107668b15467be158a5f0e0c4a5e1ec232da021892cSean Callanan if (Str[0] == '\n') { 1082adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner Str = Str.substr(1); 109668b15467be158a5f0e0c4a5e1ec232da021892cSean Callanan } else { 1102adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner Str = Str.substr(Str.find_first_of('\n')); 1112adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner if (!Str.empty()) 1122adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner Str = Str.substr(1); 1132adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner } 1142adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner continue; 115ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan } 116f5bf3cf7e2a0ff1ca884a83a8b56b5a57f8a5c80Jim Grosbach 117ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan // Get the current token. 1182adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner size_t Next = Str.find_first_of(" \t\n\r#"); 1192adbef06a637b367f724d0a46f7fa78d5827ec64Chris Lattner StringRef Value = Str.substr(0, Next); 120f5bf3cf7e2a0ff1ca884a83a8b56b5a57f8a5c80Jim Grosbach 121ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan // Convert to a byte and add to the byte vector. 122222af464822c9c47b2859e813912ed6ba5339217Chris Lattner unsigned ByteVal; 123222af464822c9c47b2859e813912ed6ba5339217Chris Lattner if (Value.getAsInteger(0, ByteVal) || ByteVal > 255) { 124c3de94fabf3858ad57373171fa6bda407f2224c9Chris Lattner // If we have an error, print it and skip to the end of line. 1253f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner SM.PrintMessage(SMLoc::getFromPointer(Value.data()), SourceMgr::DK_Error, 1263f2d5f60b31fd057c10f77b2e607b23a8c94f6d3Chris Lattner "invalid input token"); 127c3de94fabf3858ad57373171fa6bda407f2224c9Chris Lattner Str = Str.substr(Str.find('\n')); 128c3de94fabf3858ad57373171fa6bda407f2224c9Chris Lattner ByteArray.clear(); 129c3de94fabf3858ad57373171fa6bda407f2224c9Chris Lattner continue; 130ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan } 131f5bf3cf7e2a0ff1ca884a83a8b56b5a57f8a5c80Jim Grosbach 132665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner ByteArray.push_back(std::make_pair((unsigned char)ByteVal, Value.data())); 133222af464822c9c47b2859e813912ed6ba5339217Chris Lattner Str = Str.substr(Next); 134ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan } 135f5bf3cf7e2a0ff1ca884a83a8b56b5a57f8a5c80Jim Grosbach 136668b15467be158a5f0e0c4a5e1ec232da021892cSean Callanan return false; 137668b15467be158a5f0e0c4a5e1ec232da021892cSean Callanan} 138668b15467be158a5f0e0c4a5e1ec232da021892cSean Callanan 139b262799d49891b036daa00eddf51947487346c98Evan Chengint Disassembler::disassemble(const Target &T, 140a5c177e70a42f48e4885075c4c48aad0816a2817Bill Wendling const std::string &Triple, 141d0c478d95f440b4db76279fe47d6cf734a28fa9aRichard Barton MCSubtargetInfo &STI, 142d0c478d95f440b4db76279fe47d6cf734a28fa9aRichard Barton MCStreamer &Streamer, 143d5826a33a5a7c298a8934541d11cda042028be3bDan Gohman MemoryBuffer &Buffer, 144d0c478d95f440b4db76279fe47d6cf734a28fa9aRichard Barton SourceMgr &SM, 145d5826a33a5a7c298a8934541d11cda042028be3bDan Gohman raw_ostream &Out) { 146d0c478d95f440b4db76279fe47d6cf734a28fa9aRichard Barton OwningPtr<const MCDisassembler> DisAsm(T.createMCDisassembler(STI)); 147668b15467be158a5f0e0c4a5e1ec232da021892cSean Callanan if (!DisAsm) { 148668b15467be158a5f0e0c4a5e1ec232da021892cSean Callanan errs() << "error: no disassembler for target " << Triple << "\n"; 149668b15467be158a5f0e0c4a5e1ec232da021892cSean Callanan return -1; 150668b15467be158a5f0e0c4a5e1ec232da021892cSean Callanan } 151f5bf3cf7e2a0ff1ca884a83a8b56b5a57f8a5c80Jim Grosbach 152d0c478d95f440b4db76279fe47d6cf734a28fa9aRichard Barton // Set up initial section manually here 153d0c478d95f440b4db76279fe47d6cf734a28fa9aRichard Barton Streamer.InitSections(); 154f5bf3cf7e2a0ff1ca884a83a8b56b5a57f8a5c80Jim Grosbach 155668b15467be158a5f0e0c4a5e1ec232da021892cSean Callanan bool ErrorOccurred = false; 156f5bf3cf7e2a0ff1ca884a83a8b56b5a57f8a5c80Jim Grosbach 157668b15467be158a5f0e0c4a5e1ec232da021892cSean Callanan // Convert the input to a vector for disassembly. 158668b15467be158a5f0e0c4a5e1ec232da021892cSean Callanan ByteArrayTy ByteArray; 159668b15467be158a5f0e0c4a5e1ec232da021892cSean Callanan StringRef Str = Buffer.getBuffer(); 160f5bf3cf7e2a0ff1ca884a83a8b56b5a57f8a5c80Jim Grosbach 161668b15467be158a5f0e0c4a5e1ec232da021892cSean Callanan ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM); 162f5bf3cf7e2a0ff1ca884a83a8b56b5a57f8a5c80Jim Grosbach 163222af464822c9c47b2859e813912ed6ba5339217Chris Lattner if (!ByteArray.empty()) 164d0c478d95f440b4db76279fe47d6cf734a28fa9aRichard Barton ErrorOccurred |= PrintInsts(*DisAsm, ByteArray, SM, Out, Streamer); 165f5bf3cf7e2a0ff1ca884a83a8b56b5a57f8a5c80Jim Grosbach 166665e947740bb1909f9c3dc60927e8b9620d644e5Chris Lattner return ErrorOccurred; 167ba847da571354e13f1caa3699ee06b2d57df9fe9Sean Callanan} 168