Disassembler.cpp revision 276365dd4bc0c2160f91fd8062ae1fc90c86c324
1//===-- lib/MC/Disassembler.cpp - Disassembler Public C Interface -*- C -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "Disassembler.h" 11#include "llvm-c/Disassembler.h" 12 13#include "llvm/MC/MCAsmInfo.h" 14#include "llvm/MC/MCDisassembler.h" 15#include "llvm/MC/MCInst.h" 16#include "llvm/MC/MCInstPrinter.h" 17#include "llvm/MC/MCContext.h" 18#include "llvm/Target/TargetRegistry.h" 19#include "llvm/Target/TargetAsmInfo.h" // FIXME. 20#include "llvm/Target/TargetMachine.h" // FIXME. 21#include "llvm/Target/TargetSelect.h" 22#include "llvm/Support/MemoryObject.h" 23 24namespace llvm { 25class Target; 26} // namespace llvm 27using namespace llvm; 28 29// LLVMCreateDisasm() creates a disassembler for the TripleName. Symbolic 30// disassembly is supported by passing a block of information in the DisInfo 31// parameter and specifying the TagType and callback functions as described in 32// the header llvm-c/Disassembler.h . The pointer to the block and the 33// functions can all be passed as NULL. If successful, this returns a 34// disassembler context. If not, it returns NULL. 35// 36LLVMDisasmContextRef LLVMCreateDisasm(const char *TripleName, void *DisInfo, 37 int TagType, LLVMOpInfoCallback GetOpInfo, 38 LLVMSymbolLookupCallback SymbolLookUp) { 39 // Initialize targets and assembly printers/parsers. 40 llvm::InitializeAllTargetInfos(); 41 // FIXME: We shouldn't need to initialize the Target(Machine)s. 42 llvm::InitializeAllTargets(); 43 llvm::InitializeAllAsmPrinters(); 44 llvm::InitializeAllAsmParsers(); 45 llvm::InitializeAllDisassemblers(); 46 47 // Get the target. 48 std::string Error; 49 const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); 50 assert(TheTarget && "Unable to create target!"); 51 52 // Get the assembler info needed to setup the MCContext. 53 const MCAsmInfo *MAI = TheTarget->createAsmInfo(TripleName); 54 assert(MAI && "Unable to create target asm info!"); 55 56 // Package up features to be passed to target/subtarget 57 std::string FeaturesStr; 58 std::string CPU; 59 60 // FIXME: We shouldn't need to do this (and link in codegen). 61 // When we split this out, we should do it in a way that makes 62 // it straightforward to switch subtargets on the fly. 63 TargetMachine *TM = TheTarget->createTargetMachine(TripleName, CPU, 64 FeaturesStr); 65 assert(TM && "Unable to create target machine!"); 66 67 // Get the target assembler info needed to setup the context. 68 const TargetAsmInfo *tai = new TargetAsmInfo(*TM); 69 assert(tai && "Unable to create target assembler!"); 70 71 // Set up the MCContext for creating symbols and MCExpr's. 72 MCContext *Ctx = new MCContext(*MAI, tai); 73 assert(Ctx && "Unable to create MCContext!"); 74 75 // Set up disassembler. 76 MCDisassembler *DisAsm = TheTarget->createMCDisassembler(); 77 assert(DisAsm && "Unable to create disassembler!"); 78 DisAsm->setupForSymbolicDisassembly(GetOpInfo, DisInfo, Ctx); 79 80 // Set up the instruction printer. 81 int AsmPrinterVariant = MAI->getAssemblerDialect(); 82 MCInstPrinter *IP = TheTarget->createMCInstPrinter(*TM, AsmPrinterVariant, 83 *MAI); 84 assert(IP && "Unable to create instruction printer!"); 85 86 LLVMDisasmContext *DC = new LLVMDisasmContext(TripleName, DisInfo, TagType, 87 GetOpInfo, SymbolLookUp, 88 TheTarget, MAI, TM, tai, Ctx, 89 DisAsm, IP); 90 assert(DC && "Allocation failure!"); 91 return DC; 92} 93 94// 95// LLVMDisasmDispose() disposes of the disassembler specified by the context. 96// 97void LLVMDisasmDispose(LLVMDisasmContextRef DCR){ 98 LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR; 99 delete DC; 100} 101 102namespace { 103// 104// The memory object created by LLVMDisasmInstruction(). 105// 106class DisasmMemoryObject : public MemoryObject { 107 uint8_t *Bytes; 108 uint64_t Size; 109 uint64_t BasePC; 110public: 111 DisasmMemoryObject(uint8_t *bytes, uint64_t size, uint64_t basePC) : 112 Bytes(bytes), Size(size), BasePC(basePC) {} 113 114 uint64_t getBase() const { return BasePC; } 115 uint64_t getExtent() const { return Size; } 116 117 int readByte(uint64_t Addr, uint8_t *Byte) const { 118 if (Addr - BasePC >= Size) 119 return -1; 120 *Byte = Bytes[Addr - BasePC]; 121 return 0; 122 } 123}; 124} // end anonymous namespace 125 126// 127// LLVMDisasmInstruction() disassembles a single instruction using the 128// disassembler context specified in the parameter DC. The bytes of the 129// instruction are specified in the parameter Bytes, and contains at least 130// BytesSize number of bytes. The instruction is at the address specified by 131// the PC parameter. If a valid instruction can be disassembled its string is 132// returned indirectly in OutString which whos size is specified in the 133// parameter OutStringSize. This function returns the number of bytes in the 134// instruction or zero if there was no valid instruction. If this function 135// returns zero the caller will have to pick how many bytes they want to step 136// over by printing a .byte, .long etc. to continue. 137// 138size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes, 139 uint64_t BytesSize, uint64_t PC, char *OutString, 140 size_t OutStringSize){ 141 LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR; 142 // Wrap the pointer to the Bytes, BytesSize and PC in a MemoryObject. 143 DisasmMemoryObject MemoryObject(Bytes, BytesSize, PC); 144 145 uint64_t Size; 146 MCInst Inst; 147 const MCDisassembler *DisAsm = DC->getDisAsm(); 148 MCInstPrinter *IP = DC->getIP(); 149 if (!DisAsm->getInstruction(Inst, Size, MemoryObject, PC, /*REMOVE*/ nulls())) 150 return 0; 151 152 SmallVector<char, 64> InsnStr; 153 raw_svector_ostream OS(InsnStr); 154 IP->printInst(&Inst, OS); 155 OS.flush(); 156 157 assert(OutStringSize != 0 && "Output buffer cannot be zero size"); 158 size_t OutputSize = std::min(OutStringSize-1, InsnStr.size()); 159 std::memcpy(OutString, InsnStr.data(), OutputSize); 160 OutString[OutputSize] = '\0'; // Terminate string. 161 162 return Size; 163} 164