summaryrefslogtreecommitdiffstats
path: root/lib/MC/MCDisassembler
diff options
context:
space:
mode:
Diffstat (limited to 'lib/MC/MCDisassembler')
-rw-r--r--lib/MC/MCDisassembler/CMakeLists.txt3
-rw-r--r--lib/MC/MCDisassembler/Disassembler.cpp171
-rw-r--r--lib/MC/MCDisassembler/Disassembler.h96
-rw-r--r--lib/MC/MCDisassembler/EDDisassembler.cpp19
-rw-r--r--lib/MC/MCDisassembler/EDDisassembler.h9
-rw-r--r--lib/MC/MCDisassembler/EDInfo.h4
-rw-r--r--lib/MC/MCDisassembler/EDInst.cpp3
-rw-r--r--lib/MC/MCDisassembler/EDOperand.cpp13
8 files changed, 306 insertions, 12 deletions
diff --git a/lib/MC/MCDisassembler/CMakeLists.txt b/lib/MC/MCDisassembler/CMakeLists.txt
index 5fa7b70..0ce359d 100644
--- a/lib/MC/MCDisassembler/CMakeLists.txt
+++ b/lib/MC/MCDisassembler/CMakeLists.txt
@@ -1,7 +1,8 @@
add_llvm_library(LLVMMCDisassembler
+ Disassembler.cpp
EDDisassembler.cpp
- EDOperand.cpp
EDInst.cpp
+ EDOperand.cpp
EDToken.cpp
)
diff --git a/lib/MC/MCDisassembler/Disassembler.cpp b/lib/MC/MCDisassembler/Disassembler.cpp
new file mode 100644
index 0000000..ced57e8
--- /dev/null
+++ b/lib/MC/MCDisassembler/Disassembler.cpp
@@ -0,0 +1,171 @@
+//===-- lib/MC/Disassembler.cpp - Disassembler Public C Interface -*- C -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "Disassembler.h"
+#include <stdio.h>
+#include "llvm-c/Disassembler.h"
+
+#include <string>
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Target/TargetAsmInfo.h" // FIXME.
+#include "llvm/Target/TargetMachine.h" // FIXME.
+#include "llvm/Target/TargetSelect.h"
+#include "llvm/Support/MemoryObject.h"
+
+namespace llvm {
+class Target;
+} // namespace llvm
+using namespace llvm;
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+//
+// LLVMCreateDisasm() creates a disassembler for the TripleName. Symbolic
+// disassembly is supported by passing a block of information in the DisInfo
+// parameter and specifing the TagType and call back functions as described in
+// the header llvm-c/Disassembler.h . The pointer to the block and the
+// functions can all be passed as NULL. If successful this returns a
+// disassembler context if not it returns NULL.
+//
+LLVMDisasmContextRef LLVMCreateDisasm(const char *TripleName, void *DisInfo,
+ int TagType, LLVMOpInfoCallback GetOpInfo,
+ LLVMSymbolLookupCallback SymbolLookUp) {
+ // Initialize targets and assembly printers/parsers.
+ llvm::InitializeAllTargetInfos();
+ // FIXME: We shouldn't need to initialize the Target(Machine)s.
+ llvm::InitializeAllTargets();
+ llvm::InitializeAllAsmPrinters();
+ llvm::InitializeAllAsmParsers();
+ llvm::InitializeAllDisassemblers();
+
+ // Get the target.
+ std::string Error;
+ const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
+ assert(TheTarget && "Unable to create target!");
+
+ // Get the assembler info needed to setup the MCContext.
+ const MCAsmInfo *MAI = TheTarget->createAsmInfo(TripleName);
+ assert(MAI && "Unable to create target asm info!");
+
+ // Package up features to be passed to target/subtarget
+ std::string FeaturesStr;
+
+ // FIXME: We shouldn't need to do this (and link in codegen).
+ // When we split this out, we should do it in a way that makes
+ // it straightforward to switch subtargets on the fly.
+ TargetMachine *TM = TheTarget->createTargetMachine(TripleName, FeaturesStr);
+ assert(TM && "Unable to create target machine!");
+
+ // Get the target assembler info needed to setup the context.
+ const TargetAsmInfo *tai = new TargetAsmInfo(*TM);
+ assert(tai && "Unable to create target assembler!");
+
+ // Set up the MCContext for creating symbols and MCExpr's.
+ MCContext *Ctx = new MCContext(*MAI, tai);
+ assert(Ctx && "Unable to create MCContext!");
+
+ // Set up disassembler.
+ MCDisassembler *DisAsm = TheTarget->createMCDisassembler();
+ assert(DisAsm && "Unable to create disassembler!");
+ DisAsm->setupForSymbolicDisassembly(GetOpInfo, DisInfo, Ctx);
+
+ // Set up the instruction printer.
+ int AsmPrinterVariant = MAI->getAssemblerDialect();
+ MCInstPrinter *IP = TheTarget->createMCInstPrinter(*TM, AsmPrinterVariant,
+ *MAI);
+ assert(IP && "Unable to create instruction printer!");
+
+ LLVMDisasmContext *DC = new LLVMDisasmContext(TripleName, DisInfo, TagType,
+ GetOpInfo, SymbolLookUp,
+ TheTarget, MAI, TM, tai, Ctx,
+ DisAsm, IP);
+ assert(DC && "Allocation failure!");
+ return DC;
+}
+
+//
+// LLVMDisasmDispose() disposes of the disassembler specified by the context.
+//
+void LLVMDisasmDispose(LLVMDisasmContextRef DCR){
+ LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ delete DC;
+}
+
+namespace {
+//
+// The memory object created by LLVMDisasmInstruction().
+//
+class DisasmMemoryObject : public MemoryObject {
+private:
+ uint8_t *Bytes;
+ uint64_t Size;
+ uint64_t BasePC;
+public:
+ DisasmMemoryObject(uint8_t *bytes, uint64_t size, uint64_t basePC) :
+ Bytes(bytes), Size(size), BasePC(basePC) {}
+
+ uint64_t getBase() const { return BasePC; }
+ uint64_t getExtent() const { return Size; }
+
+ int readByte(uint64_t Addr, uint8_t *Byte) const {
+ if (Addr - BasePC >= Size)
+ return -1;
+ *Byte = Bytes[Addr - BasePC];
+ return 0;
+ }
+};
+} // namespace
+
+//
+// LLVMDisasmInstruction() disassembles a single instruction using the
+// disassembler context specified in the parameter DC. The bytes of the
+// instruction are specified in the parameter Bytes, and contains at least
+// BytesSize number of bytes. The instruction is at the address specified by
+// the PC parameter. If a valid instruction can be disassembled its string is
+// returned indirectly in OutString which whos size is specified in the
+// parameter OutStringSize. This function returns the number of bytes in the
+// instruction or zero if there was no valid instruction. If this function
+// returns zero the caller will have to pick how many bytes they want to step
+// over by printing a .byte, .long etc. to continue.
+//
+size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes,
+ uint64_t BytesSize, uint64_t PC, char *OutString,
+ size_t OutStringSize){
+ LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ // Wrap the pointer to the Bytes, BytesSize and PC in a MemoryObject.
+ DisasmMemoryObject MemoryObject(Bytes, BytesSize, PC);
+
+ uint64_t Size;
+ MCInst Inst;
+ const MCDisassembler *DisAsm = DC->getDisAsm();
+ MCInstPrinter *IP = DC->getIP();
+ if (!DisAsm->getInstruction(Inst, Size, MemoryObject, PC, /*REMOVE*/ nulls()))
+ return 0;
+
+ std::string InsnStr;
+ raw_string_ostream OS(InsnStr);
+ IP->printInst(&Inst, OS);
+ OS.flush();
+
+ size_t OutputSize = std::min(OutStringSize-1, InsnStr.size());
+ std::memcpy(OutString, InsnStr.data(), OutputSize);
+ OutString[OutputSize] = '\0'; // Terminate string.
+
+ return Size;
+}
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
diff --git a/lib/MC/MCDisassembler/Disassembler.h b/lib/MC/MCDisassembler/Disassembler.h
new file mode 100644
index 0000000..f0ec42a
--- /dev/null
+++ b/lib/MC/MCDisassembler/Disassembler.h
@@ -0,0 +1,96 @@
+//===------------- Disassembler.h - LLVM Disassembler -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface for the Disassembly library's disassembler
+// context. The disassembler is responsible for producing strings for
+// individual instructions according to a given architecture and disassembly
+// syntax.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_DISASSEMBLER_H
+#define LLVM_MC_DISASSEMBLER_H
+
+#include "llvm-c/Disassembler.h"
+#include <string>
+#include "llvm/ADT/OwningPtr.h"
+
+namespace llvm {
+class TargetAsmInfo;
+class MCContext;
+class MCAsmInfo;
+class MCDisassembler;
+class MCInstPrinter;
+class Target;
+class TargetMachine;
+
+//
+// This is the disassembler context returned by LLVMCreateDisasm().
+//
+class LLVMDisasmContext {
+private:
+ //
+ // The passed parameters when the disassembler context is created.
+ //
+ // The TripleName for this disassembler.
+ std::string TripleName;
+ // The pointer to the caller's block of symbolic information.
+ void *DisInfo;
+ // The Triple specific symbolic information type returned by GetOpInfo.
+ int TagType;
+ // The function to get the symbolic information for operands.
+ LLVMOpInfoCallback GetOpInfo;
+ // The function to look up a symbol name.
+ LLVMSymbolLookupCallback SymbolLookUp;
+ //
+ // The objects created and saved by LLVMCreateDisasm() then used by
+ // LLVMDisasmInstruction().
+ //
+ // The LLVM target corresponding to the disassembler.
+ // FIXME: using llvm::OwningPtr<const llvm::Target> causes a malloc error
+ // when this LLVMDisasmContext is deleted.
+ const Target *TheTarget;
+ // The assembly information for the target architecture.
+ llvm::OwningPtr<const llvm::MCAsmInfo> MAI;
+ // The target machine instance.
+ llvm::OwningPtr<llvm::TargetMachine> TM;
+ // The disassembler for the target architecture.
+ // FIXME: using llvm::OwningPtr<const llvm::TargetAsmInfo> causes a malloc
+ // error when this LLVMDisasmContext is deleted.
+ const TargetAsmInfo *Tai;
+ // The assembly context for creating symbols and MCExprs.
+ llvm::OwningPtr<const llvm::MCContext> Ctx;
+ // The disassembler for the target architecture.
+ llvm::OwningPtr<const llvm::MCDisassembler> DisAsm;
+ // The instruction printer for the target architecture.
+ llvm::OwningPtr<llvm::MCInstPrinter> IP;
+
+public:
+ LLVMDisasmContext(std::string tripleName, void *disInfo, int tagType,
+ LLVMOpInfoCallback getOpInfo,
+ LLVMSymbolLookupCallback symbolLookUp,
+ const Target *theTarget, const MCAsmInfo *mAI,
+ llvm::TargetMachine *tM, const TargetAsmInfo *tai,
+ llvm::MCContext *ctx, const MCDisassembler *disAsm,
+ MCInstPrinter *iP) : TripleName(tripleName),
+ DisInfo(disInfo), TagType(tagType), GetOpInfo(getOpInfo),
+ SymbolLookUp(symbolLookUp), TheTarget(theTarget), Tai(tai) {
+ TM.reset(tM);
+ MAI.reset(mAI);
+ Ctx.reset(ctx);
+ DisAsm.reset(disAsm);
+ IP.reset(iP);
+ }
+ const MCDisassembler *getDisAsm() const { return DisAsm.get(); }
+ MCInstPrinter *getIP() { return IP.get(); }
+};
+
+} // namespace llvm
+
+#endif
diff --git a/lib/MC/MCDisassembler/EDDisassembler.cpp b/lib/MC/MCDisassembler/EDDisassembler.cpp
index 2fd14db..91c5284 100644
--- a/lib/MC/MCDisassembler/EDDisassembler.cpp
+++ b/lib/MC/MCDisassembler/EDDisassembler.cpp
@@ -193,7 +193,8 @@ EDDisassembler::EDDisassembler(CPUKey &key) :
InstString.reset(new std::string);
InstStream.reset(new raw_string_ostream(*InstString));
- InstPrinter.reset(Tgt->createMCInstPrinter(LLVMSyntaxVariant, *AsmInfo));
+ InstPrinter.reset(Tgt->createMCInstPrinter(*TargetMachine, LLVMSyntaxVariant,
+ *AsmInfo));
if (!InstPrinter)
return;
@@ -253,9 +254,11 @@ EDInst *EDDisassembler::createInst(EDByteReaderCallback byteReader,
delete inst;
return NULL;
} else {
- const llvm::EDInstInfo *thisInstInfo;
+ const llvm::EDInstInfo *thisInstInfo = NULL;
- thisInstInfo = &InstInfos[inst->getOpcode()];
+ if (InstInfos) {
+ thisInstInfo = &InstInfos[inst->getOpcode()];
+ }
EDInst* sdInst = new EDInst(inst, byteSize, *this, thisInstInfo);
return sdInst;
@@ -331,6 +334,15 @@ int EDDisassembler::printInst(std::string &str, MCInst &inst) {
return 0;
}
+static void diag_handler(const SMDiagnostic &diag,
+ void *context)
+{
+ if (context) {
+ EDDisassembler *disassembler = static_cast<EDDisassembler*>(context);
+ diag.Print("", disassembler->ErrorStream);
+ }
+}
+
int EDDisassembler::parseInst(SmallVectorImpl<MCParsedAsmOperand*> &operands,
SmallVectorImpl<AsmToken> &tokens,
const std::string &str) {
@@ -353,6 +365,7 @@ int EDDisassembler::parseInst(SmallVectorImpl<MCParsedAsmOperand*> &operands,
SMLoc instLoc;
SourceMgr sourceMgr;
+ sourceMgr.setDiagHandler(diag_handler, static_cast<void*>(this));
sourceMgr.AddNewSourceBuffer(buf, SMLoc()); // ownership of buf handed over
MCContext context(*AsmInfo, NULL);
OwningPtr<MCStreamer> streamer(createNullStreamer(context));
diff --git a/lib/MC/MCDisassembler/EDDisassembler.h b/lib/MC/MCDisassembler/EDDisassembler.h
index 71e45f0..2fcc09d 100644
--- a/lib/MC/MCDisassembler/EDDisassembler.h
+++ b/lib/MC/MCDisassembler/EDDisassembler.h
@@ -87,13 +87,8 @@ struct EDDisassembler {
/// operator< - Less-than operator
bool operator<(const CPUKey &key) const {
- if(Arch > key.Arch)
- return false;
- else if (Arch == key.Arch) {
- if(Syntax > key.Syntax)
- return false;
- }
- return true;
+ return ((Arch < key.Arch) ||
+ ((Arch == key.Arch) && Syntax < (key.Syntax)));
}
};
diff --git a/lib/MC/MCDisassembler/EDInfo.h b/lib/MC/MCDisassembler/EDInfo.h
index 627c066..ad57282 100644
--- a/lib/MC/MCDisassembler/EDInfo.h
+++ b/lib/MC/MCDisassembler/EDInfo.h
@@ -35,6 +35,7 @@ enum OperandTypes {
kOperandTypeARMAddrMode5,
kOperandTypeARMAddrMode6,
kOperandTypeARMAddrMode6Offset,
+ kOperandTypeARMAddrMode7,
kOperandTypeARMAddrModePC,
kOperandTypeARMRegisterList,
kOperandTypeARMTBAddrMode,
@@ -51,7 +52,8 @@ enum OperandTypes {
kOperandTypeThumb2AddrModeImm12,
kOperandTypeThumb2AddrModeSoReg,
kOperandTypeThumb2AddrModeImm8s4,
- kOperandTypeThumb2AddrModeImm8s4Offset
+ kOperandTypeThumb2AddrModeImm8s4Offset,
+ kOperandTypeThumb2AddrModeReg
};
enum OperandFlags {
diff --git a/lib/MC/MCDisassembler/EDInst.cpp b/lib/MC/MCDisassembler/EDInst.cpp
index 63b049f..6057e16 100644
--- a/lib/MC/MCDisassembler/EDInst.cpp
+++ b/lib/MC/MCDisassembler/EDInst.cpp
@@ -165,6 +165,9 @@ int EDInst::getOperand(EDOperand *&operand, unsigned int index) {
int EDInst::tokenize() {
if (TokenizeResult.valid())
return TokenizeResult.result();
+
+ if (ThisInstInfo == NULL)
+ return TokenizeResult.setResult(-1);
if (stringify())
return TokenizeResult.setResult(-1);
diff --git a/lib/MC/MCDisassembler/EDOperand.cpp b/lib/MC/MCDisassembler/EDOperand.cpp
index 2b0c73e..492bb08 100644
--- a/lib/MC/MCDisassembler/EDOperand.cpp
+++ b/lib/MC/MCDisassembler/EDOperand.cpp
@@ -73,6 +73,8 @@ EDOperand::EDOperand(const EDDisassembler &disassembler,
case kOperandTypeThumb2AddrModeImm8Offset:
case kOperandTypeARMTBAddrMode:
case kOperandTypeThumb2AddrModeImm8s4Offset:
+ case kOperandTypeARMAddrMode7:
+ case kOperandTypeThumb2AddrModeReg:
numMCOperands = 1;
break;
case kOperandTypeThumb2SoReg:
@@ -196,15 +198,24 @@ int EDOperand::evaluate(uint64_t &result,
default:
return -1;
case kOperandTypeImmediate:
+ if (!Inst.Inst->getOperand(MCOpIndex).isImm())
+ return -1;
+
result = Inst.Inst->getOperand(MCOpIndex).getImm();
return 0;
case kOperandTypeRegister:
{
+ if (!Inst.Inst->getOperand(MCOpIndex).isReg())
+ return -1;
+
unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg();
return callback(&result, reg, arg);
}
case kOperandTypeARMBranchTarget:
{
+ if (!Inst.Inst->getOperand(MCOpIndex).isImm())
+ return -1;
+
int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm();
uint64_t pcVal;
@@ -256,6 +267,7 @@ int EDOperand::isMemory() {
case kOperandTypeARMAddrMode4:
case kOperandTypeARMAddrMode5:
case kOperandTypeARMAddrMode6:
+ case kOperandTypeARMAddrMode7:
case kOperandTypeARMAddrModePC:
case kOperandTypeARMBranchTarget:
case kOperandTypeThumbAddrModeS1:
@@ -269,6 +281,7 @@ int EDOperand::isMemory() {
case kOperandTypeThumb2AddrModeImm12:
case kOperandTypeThumb2AddrModeSoReg:
case kOperandTypeThumb2AddrModeImm8s4:
+ case kOperandTypeThumb2AddrModeReg:
return 1;
}
}
OpenPOWER on IntegriCloud