summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/MC/MCDisassembler
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/MC/MCDisassembler')
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp223
-rw-r--r--contrib/llvm/lib/MC/MCDisassembler/Disassembler.h121
2 files changed, 344 insertions, 0 deletions
diff --git a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp
new file mode 100644
index 0000000..4766b37
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.cpp
@@ -0,0 +1,223 @@
+//===-- lib/MC/Disassembler.cpp - Disassembler Public C Interface ---------===//
+//
+// 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 "llvm-c/Disassembler.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MemoryObject.h"
+#include "llvm/Support/TargetRegistry.h"
+
+namespace llvm {
+class Target;
+} // namespace llvm
+using namespace llvm;
+
+// LLVMCreateDisasm() creates a disassembler for the TripleName. Symbolic
+// disassembly is supported by passing a block of information in the DisInfo
+// parameter and specifying the TagType and callback 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 LLVMCreateDisasmCPU(const char *Triple, const char *CPU,
+ void *DisInfo, int TagType,
+ LLVMOpInfoCallback GetOpInfo,
+ LLVMSymbolLookupCallback SymbolLookUp){
+ // Get the target.
+ std::string Error;
+ const Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error);
+ assert(TheTarget && "Unable to create target!");
+
+ // Get the assembler info needed to setup the MCContext.
+ const MCAsmInfo *MAI = TheTarget->createMCAsmInfo(Triple);
+ if (!MAI)
+ return 0;
+
+ const MCInstrInfo *MII = TheTarget->createMCInstrInfo();
+ if (!MII)
+ return 0;
+
+ const MCRegisterInfo *MRI = TheTarget->createMCRegInfo(Triple);
+ if (!MRI)
+ return 0;
+
+ // Package up features to be passed to target/subtarget
+ std::string FeaturesStr;
+
+ const MCSubtargetInfo *STI = TheTarget->createMCSubtargetInfo(Triple, CPU,
+ FeaturesStr);
+ if (!STI)
+ return 0;
+
+ // Set up the MCContext for creating symbols and MCExpr's.
+ MCContext *Ctx = new MCContext(*MAI, *MRI, 0);
+ if (!Ctx)
+ return 0;
+
+ // Set up disassembler.
+ MCDisassembler *DisAsm = TheTarget->createMCDisassembler(*STI);
+ if (!DisAsm)
+ return 0;
+ DisAsm->setupForSymbolicDisassembly(GetOpInfo, SymbolLookUp, DisInfo, Ctx);
+
+ // Set up the instruction printer.
+ int AsmPrinterVariant = MAI->getAssemblerDialect();
+ MCInstPrinter *IP = TheTarget->createMCInstPrinter(AsmPrinterVariant,
+ *MAI, *MII, *MRI, *STI);
+ if (!IP)
+ return 0;
+
+ LLVMDisasmContext *DC = new LLVMDisasmContext(Triple, DisInfo, TagType,
+ GetOpInfo, SymbolLookUp,
+ TheTarget, MAI, MRI,
+ STI, MII, Ctx, DisAsm, IP);
+ if (!DC)
+ return 0;
+
+ return DC;
+}
+
+LLVMDisasmContextRef LLVMCreateDisasm(const char *Triple, void *DisInfo,
+ int TagType, LLVMOpInfoCallback GetOpInfo,
+ LLVMSymbolLookupCallback SymbolLookUp) {
+ return LLVMCreateDisasmCPU(Triple, "", DisInfo, TagType, GetOpInfo,
+ SymbolLookUp);
+}
+
+//
+// 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 {
+ 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;
+ }
+};
+} // end anonymous 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();
+ MCDisassembler::DecodeStatus S;
+ S = DisAsm->getInstruction(Inst, Size, MemoryObject, PC,
+ /*REMOVE*/ nulls(), DC->CommentStream);
+ switch (S) {
+ case MCDisassembler::Fail:
+ case MCDisassembler::SoftFail:
+ // FIXME: Do something different for soft failure modes?
+ return 0;
+
+ case MCDisassembler::Success: {
+ DC->CommentStream.flush();
+ StringRef Comments = DC->CommentsToEmit.str();
+
+ SmallVector<char, 64> InsnStr;
+ raw_svector_ostream OS(InsnStr);
+ IP->printInst(&Inst, OS, Comments);
+ OS.flush();
+
+ // Tell the comment stream that the vector changed underneath it.
+ DC->CommentsToEmit.clear();
+ DC->CommentStream.resync();
+
+ assert(OutStringSize != 0 && "Output buffer cannot be zero size");
+ size_t OutputSize = std::min(OutStringSize-1, InsnStr.size());
+ std::memcpy(OutString, InsnStr.data(), OutputSize);
+ OutString[OutputSize] = '\0'; // Terminate string.
+
+ return Size;
+ }
+ }
+ llvm_unreachable("Invalid DecodeStatus!");
+}
+
+//
+// LLVMSetDisasmOptions() sets the disassembler's options. It returns 1 if it
+// can set all the Options and 0 otherwise.
+//
+int LLVMSetDisasmOptions(LLVMDisasmContextRef DCR, uint64_t Options){
+ if (Options & LLVMDisassembler_Option_UseMarkup){
+ LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ MCInstPrinter *IP = DC->getIP();
+ IP->setUseMarkup(1);
+ Options &= ~LLVMDisassembler_Option_UseMarkup;
+ }
+ if (Options & LLVMDisassembler_Option_PrintImmHex){
+ LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ MCInstPrinter *IP = DC->getIP();
+ IP->setPrintImmHex(1);
+ Options &= ~LLVMDisassembler_Option_PrintImmHex;
+ }
+ if (Options & LLVMDisassembler_Option_AsmPrinterVariant){
+ LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR;
+ // Try to set up the new instruction printer.
+ const MCAsmInfo *MAI = DC->getAsmInfo();
+ const MCInstrInfo *MII = DC->getInstrInfo();
+ const MCRegisterInfo *MRI = DC->getRegisterInfo();
+ const MCSubtargetInfo *STI = DC->getSubtargetInfo();
+ int AsmPrinterVariant = MAI->getAssemblerDialect();
+ AsmPrinterVariant = AsmPrinterVariant == 0 ? 1 : 0;
+ MCInstPrinter *IP = DC->getTarget()->createMCInstPrinter(
+ AsmPrinterVariant, *MAI, *MII, *MRI, *STI);
+ if (IP) {
+ DC->setIP(IP);
+ Options &= ~LLVMDisassembler_Option_AsmPrinterVariant;
+ }
+ }
+ return (Options == 0);
+}
diff --git a/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h
new file mode 100644
index 0000000..6eb59d0
--- /dev/null
+++ b/contrib/llvm/lib/MC/MCDisassembler/Disassembler.h
@@ -0,0 +1,121 @@
+//===------------- 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 "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+
+namespace llvm {
+class MCContext;
+class MCAsmInfo;
+class MCDisassembler;
+class MCInstPrinter;
+class MCInstrInfo;
+class MCRegisterInfo;
+class MCSubtargetInfo;
+class Target;
+
+//
+// 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 register information for the target architecture.
+ llvm::OwningPtr<const llvm::MCRegisterInfo> MRI;
+ // The subtarget information for the target architecture.
+ llvm::OwningPtr<const llvm::MCSubtargetInfo> MSI;
+ // The instruction information for the target architecture.
+ llvm::OwningPtr<const llvm::MCInstrInfo> MII;
+ // 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:
+ // Comment stream and backing vector.
+ SmallString<128> CommentsToEmit;
+ raw_svector_ostream CommentStream;
+
+ LLVMDisasmContext(std::string tripleName, void *disInfo, int tagType,
+ LLVMOpInfoCallback getOpInfo,
+ LLVMSymbolLookupCallback symbolLookUp,
+ const Target *theTarget, const MCAsmInfo *mAI,
+ const MCRegisterInfo *mRI,
+ const MCSubtargetInfo *mSI,
+ const MCInstrInfo *mII,
+ llvm::MCContext *ctx, const MCDisassembler *disAsm,
+ MCInstPrinter *iP) : TripleName(tripleName),
+ DisInfo(disInfo), TagType(tagType), GetOpInfo(getOpInfo),
+ SymbolLookUp(symbolLookUp), TheTarget(theTarget),
+ CommentStream(CommentsToEmit) {
+ MAI.reset(mAI);
+ MRI.reset(mRI);
+ MSI.reset(mSI);
+ MII.reset(mII);
+ Ctx.reset(ctx);
+ DisAsm.reset(disAsm);
+ IP.reset(iP);
+ }
+ const std::string &getTripleName() const { return TripleName; }
+ void *getDisInfo() const { return DisInfo; }
+ int getTagType() const { return TagType; }
+ LLVMOpInfoCallback getGetOpInfo() const { return GetOpInfo; }
+ LLVMSymbolLookupCallback getSymbolLookupCallback() const {
+ return SymbolLookUp;
+ }
+ const Target *getTarget() const { return TheTarget; }
+ const MCDisassembler *getDisAsm() const { return DisAsm.get(); }
+ const MCAsmInfo *getAsmInfo() const { return MAI.get(); }
+ const MCInstrInfo *getInstrInfo() const { return MII.get(); }
+ const MCRegisterInfo *getRegisterInfo() const { return MRI.get(); }
+ const MCSubtargetInfo *getSubtargetInfo() const { return MSI.get(); }
+ MCInstPrinter *getIP() { return IP.get(); }
+ void setIP(MCInstPrinter *NewIP) { IP.reset(NewIP); }
+};
+
+} // namespace llvm
+
+#endif
OpenPOWER on IntegriCloud