diff options
Diffstat (limited to 'tools/llvm-mc/Disassembler.cpp')
| -rw-r--r-- | tools/llvm-mc/Disassembler.cpp | 271 | 
1 files changed, 234 insertions, 37 deletions
diff --git a/tools/llvm-mc/Disassembler.cpp b/tools/llvm-mc/Disassembler.cpp index 9fe07909284c..9234a14bc1bf 100644 --- a/tools/llvm-mc/Disassembler.cpp +++ b/tools/llvm-mc/Disassembler.cpp @@ -15,6 +15,7 @@  #include "Disassembler.h"  #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/Triple.h"  #include "llvm/MC/MCAsmInfo.h"  #include "llvm/MC/MCDisassembler.h"  #include "llvm/MC/MCInst.h" @@ -24,6 +25,9 @@  #include "llvm/Support/MemoryObject.h"  #include "llvm/Support/raw_ostream.h"  #include "llvm/Support/SourceMgr.h" + +#include "llvm-c/EnhancedDisassembly.h" +  using namespace llvm;  typedef std::vector<std::pair<unsigned char, const char*> > ByteArrayTy; @@ -64,8 +68,7 @@ static bool PrintInsts(const MCDisassembler &DisAsm,                                 /*REMOVE*/ nulls())) {        Printer.printInst(&Inst, outs());        outs() << "\n"; -    } -    else { +    } else {        SM.PrintMessage(SMLoc::getFromPointer(Bytes[Index].second),                        "invalid instruction encoding", "warning");        if (Size == 0) @@ -76,37 +79,9 @@ static bool PrintInsts(const MCDisassembler &DisAsm,    return false;  } -int Disassembler::disassemble(const Target &T, const std::string &Triple, -                              MemoryBuffer &Buffer) { -  // Set up disassembler. -  OwningPtr<const MCAsmInfo> AsmInfo(T.createAsmInfo(Triple)); -   -  if (!AsmInfo) { -    errs() << "error: no assembly info for target " << Triple << "\n"; -    return -1; -  } -   -  OwningPtr<const MCDisassembler> DisAsm(T.createMCDisassembler()); -  if (!DisAsm) { -    errs() << "error: no disassembler for target " << Triple << "\n"; -    return -1; -  } -   -  OwningPtr<MCInstPrinter> IP(T.createMCInstPrinter(0, *AsmInfo)); -  if (!IP) { -    errs() << "error: no instruction printer for target " << Triple << '\n'; -    return -1; -  } -   -  bool ErrorOccurred = false; -   -  SourceMgr SM; -  SM.AddNewSourceBuffer(&Buffer, SMLoc()); -   -  // Convert the input to a vector for disassembly. -  ByteArrayTy ByteArray; -   -  StringRef Str = Buffer.getBuffer(); +static bool ByteArrayFromString(ByteArrayTy &ByteArray,  +                                StringRef &Str,  +                                SourceMgr &SM) {    while (!Str.empty()) {      // Strip horizontal whitespace.      if (size_t Pos = Str.find_first_not_of(" \t\r")) { @@ -119,9 +94,9 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple,      if (Str[0] == '\n' || Str[0] == '#') {        // Strip to the end of line if we already processed any bytes on this        // line.  This strips the comment and/or the \n. -      if (Str[0] == '\n') +      if (Str[0] == '\n') {          Str = Str.substr(1); -      else { +      } else {          Str = Str.substr(Str.find_first_of('\n'));          if (!Str.empty())            Str = Str.substr(1); @@ -138,8 +113,7 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple,      if (Value.getAsInteger(0, ByteVal) || ByteVal > 255) {        // If we have an error, print it and skip to the end of line.        SM.PrintMessage(SMLoc::getFromPointer(Value.data()), -                                 "invalid input token", "error"); -      ErrorOccurred = true; +                      "invalid input token", "error");        Str = Str.substr(Str.find('\n'));        ByteArray.clear();        continue; @@ -149,8 +123,231 @@ int Disassembler::disassemble(const Target &T, const std::string &Triple,      Str = Str.substr(Next);    } +  return false; +} + +int Disassembler::disassemble(const Target &T, const std::string &Triple, +                              MemoryBuffer &Buffer) { +  // Set up disassembler. +  OwningPtr<const MCAsmInfo> AsmInfo(T.createAsmInfo(Triple)); +   +  if (!AsmInfo) { +    errs() << "error: no assembly info for target " << Triple << "\n"; +    return -1; +  } +   +  OwningPtr<const MCDisassembler> DisAsm(T.createMCDisassembler()); +  if (!DisAsm) { +    errs() << "error: no disassembler for target " << Triple << "\n"; +    return -1; +  } +   +  int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); +  OwningPtr<MCInstPrinter> IP(T.createMCInstPrinter(AsmPrinterVariant, +                                                    *AsmInfo)); +  if (!IP) { +    errs() << "error: no instruction printer for target " << Triple << '\n'; +    return -1; +  } +   +  bool ErrorOccurred = false; +   +  SourceMgr SM; +  SM.AddNewSourceBuffer(&Buffer, SMLoc()); +   +  // Convert the input to a vector for disassembly. +  ByteArrayTy ByteArray; +  StringRef Str = Buffer.getBuffer(); +   +  ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM); +      if (!ByteArray.empty())      ErrorOccurred |= PrintInsts(*DisAsm, *IP, ByteArray, SM);    return ErrorOccurred;  } + +static int byteArrayReader(uint8_t *B, uint64_t A, void *Arg) { +  ByteArrayTy &ByteArray = *((ByteArrayTy*)Arg); +   +  if (A >= ByteArray.size()) +    return -1; +   +  *B = ByteArray[A].first; +   +  return 0; +} + +static int verboseEvaluator(uint64_t *V, unsigned R, void *Arg) { +  EDDisassemblerRef &disassembler = *((EDDisassemblerRef*)Arg); +   +  const char *regName; +   +  if (!EDGetRegisterName(®Name, +                        disassembler, +                        R)) +    outs() << "[" << regName << "/" << R << "]"; +  if (EDRegisterIsStackPointer(disassembler, R)) +    outs() << "(sp)"; +  if (EDRegisterIsProgramCounter(disassembler, R)) +    outs() << "(pc)"; +   +  *V = 0; +   +  return 0; +} + +int Disassembler::disassembleEnhanced(const std::string &TS,  +                                      MemoryBuffer &Buffer) { +  ByteArrayTy ByteArray; +  StringRef Str = Buffer.getBuffer(); +  SourceMgr SM; +   +  SM.AddNewSourceBuffer(&Buffer, SMLoc()); +   +  if (ByteArrayFromString(ByteArray, Str, SM)) { +    return -1; +  } +   +  EDDisassemblerRef disassembler; +   +  Triple T(TS); +  EDAssemblySyntax_t AS; +   +  switch (T.getArch()) { +  default: +    errs() << "error: no default assembly syntax for " << TS.c_str() << "\n"; +    return -1; +  case Triple::arm: +  case Triple::thumb: +    AS = kEDAssemblySyntaxARMUAL; +    break; +  case Triple::x86: +  case Triple::x86_64: +    AS = kEDAssemblySyntaxX86ATT; +    break; +  } +   +  if (EDGetDisassembler(&disassembler,  +                        TS.c_str(), +                        AS)) { +    errs() << "error: couldn't get disassembler for " << TS.c_str() << "\n"; +    return -1; +  } +   +  EDInstRef inst; +   +  if (EDCreateInsts(&inst, 1, disassembler, byteArrayReader, 0,&ByteArray)  +      != 1) { +    errs() << "error: Didn't get an instruction\n"; +    return -1; +  } +   +  int numTokens = EDNumTokens(inst); +   +  if (numTokens < 0) { +    errs() << "error: Couldn't count the instruction's tokens\n"; +    return -1; +  } +   +  int tokenIndex; +   +  for (tokenIndex = 0; tokenIndex < numTokens; ++tokenIndex) { +    EDTokenRef token; +     +    if (EDGetToken(&token, inst, tokenIndex)) { +      errs() << "error: Couldn't get token\n"; +      return -1; +    } +     +    const char *buf; +     +    if (EDGetTokenString(&buf, token)) { +      errs() << "error: Couldn't get string for token\n"; +      return -1; +    } +     +    outs() << "["; +     +    int operandIndex = EDOperandIndexForToken(token); +     +    if (operandIndex >= 0) +      outs() << operandIndex << "-"; +     +    if (EDTokenIsWhitespace(token)) { +      outs() << "w"; +    } else if (EDTokenIsPunctuation(token)) { +      outs() << "p"; +    } else if (EDTokenIsOpcode(token)) { +      outs() << "o"; +    } else if (EDTokenIsLiteral(token)) { +      outs() << "l"; +    } else if (EDTokenIsRegister(token)) { +      outs() << "r"; +    } else { +      outs() << "?"; +    } +     +    outs() << ":" << buf; +   +    if (EDTokenIsLiteral(token)) { +      outs() << "="; +      if (EDTokenIsNegativeLiteral(token)) +        outs() << "-"; +      uint64_t absoluteValue; +      if (EDLiteralTokenAbsoluteValue(&absoluteValue, token)) { +        errs() << "error: Couldn't get the value of a literal token\n"; +        return -1; +      } +      outs() << absoluteValue; +    } else if (EDTokenIsRegister(token)) { +      outs() << "="; +      unsigned regID; +      if (EDRegisterTokenValue(®ID, token)) { +        errs() << "error: Couldn't get the ID of a register token\n"; +        return -1; +      } +      outs() << "r" << regID; +    } +     +    outs() << "]"; +  } +   +  outs() << " "; +   +  int numOperands = EDNumOperands(inst); +   +  if (numOperands < 0) { +    errs() << "error: Couldn't count operands\n"; +    return -1; +  } +   +  int operandIndex; +   +  for (operandIndex = 0; operandIndex < numOperands; ++operandIndex) { +    outs() << operandIndex << ":"; +     +    EDOperandRef operand; +     +    if (EDGetOperand(&operand, +                     inst, +                     operandIndex)) { +      errs() << "error: Couldn't get operand\n"; +      return -1; +    } +     +    uint64_t evaluatedResult; +     +    EDEvaluateOperand(&evaluatedResult,  +                      operand,  +                      verboseEvaluator,  +                      &disassembler); +     +    outs() << " "; +  } +   +  outs() << "\n"; +   +  return 0; +} +  | 
