1 //===-- lib/MC/Disassembler.cpp - Disassembler Public C Interface ---------===// 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/MCContext.h" 15 #include "llvm/MC/MCDisassembler.h" 16 #include "llvm/MC/MCInst.h" 17 #include "llvm/MC/MCInstPrinter.h" 18 #include "llvm/MC/MCRegisterInfo.h" 19 #include "llvm/Support/MemoryObject.h" 20 #include "llvm/Support/TargetRegistry.h" 21 #include "llvm/Support/TargetSelect.h" 22 #include "llvm/Support/ErrorHandling.h" 23 24 namespace llvm { 25 class Target; 26 } // namespace llvm 27 using 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 // 36 LLVMDisasmContextRef LLVMCreateDisasm(const char *TripleName, void *DisInfo, 37 int TagType, LLVMOpInfoCallback GetOpInfo, 38 LLVMSymbolLookupCallback SymbolLookUp) { 39 // Initialize targets and assembly printers/parsers. 40 // FIXME: Clients are responsible for initializing the targets. And this 41 // would be done by calling routines in "llvm-c/Target.h" which are static 42 // line functions. But the current use of LLVMCreateDisasm() is to dynamically 43 // load libLTO with dlopen() and then lookup the symbols using dlsym(). 44 // And since these initialize routines are static that does not work which 45 // is why the call to them in this 'C' library API was added back. 46 llvm::InitializeAllTargetInfos(); 47 llvm::InitializeAllTargetMCs(); 48 llvm::InitializeAllAsmParsers(); 49 llvm::InitializeAllDisassemblers(); 50 51 // Get the target. 52 std::string Error; 53 const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); 54 assert(TheTarget && "Unable to create target!"); 55 56 // Get the assembler info needed to setup the MCContext. 57 const MCAsmInfo *MAI = TheTarget->createMCAsmInfo(TripleName); 58 assert(MAI && "Unable to create target asm info!"); 59 60 const MCInstrInfo *MII = TheTarget->createMCInstrInfo(); 61 assert(MII && "Unable to create target instruction info!"); 62 63 const MCRegisterInfo *MRI = TheTarget->createMCRegInfo(TripleName); 64 assert(MRI && "Unable to create target register info!"); 65 66 // Package up features to be passed to target/subtarget 67 std::string FeaturesStr; 68 std::string CPU; 69 70 const MCSubtargetInfo *STI = TheTarget->createMCSubtargetInfo(TripleName, CPU, 71 FeaturesStr); 72 assert(STI && "Unable to create subtarget info!"); 73 74 // Set up the MCContext for creating symbols and MCExpr's. 75 MCContext *Ctx = new MCContext(*MAI, *MRI, 0); 76 assert(Ctx && "Unable to create MCContext!"); 77 78 // Set up disassembler. 79 MCDisassembler *DisAsm = TheTarget->createMCDisassembler(*STI); 80 assert(DisAsm && "Unable to create disassembler!"); 81 DisAsm->setupForSymbolicDisassembly(GetOpInfo, SymbolLookUp, DisInfo, Ctx); 82 83 // Set up the instruction printer. 84 int AsmPrinterVariant = MAI->getAssemblerDialect(); 85 MCInstPrinter *IP = TheTarget->createMCInstPrinter(AsmPrinterVariant, 86 *MAI, *MII, *MRI, *STI); 87 assert(IP && "Unable to create instruction printer!"); 88 89 LLVMDisasmContext *DC = new LLVMDisasmContext(TripleName, DisInfo, TagType, 90 GetOpInfo, SymbolLookUp, 91 TheTarget, MAI, MRI, 92 Ctx, DisAsm, IP); 93 assert(DC && "Allocation failure!"); 94 95 return DC; 96 } 97 98 // 99 // LLVMDisasmDispose() disposes of the disassembler specified by the context. 100 // 101 void LLVMDisasmDispose(LLVMDisasmContextRef DCR){ 102 LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR; 103 delete DC; 104 } 105 106 namespace { 107 // 108 // The memory object created by LLVMDisasmInstruction(). 109 // 110 class DisasmMemoryObject : public MemoryObject { 111 uint8_t *Bytes; 112 uint64_t Size; 113 uint64_t BasePC; 114 public: 115 DisasmMemoryObject(uint8_t *bytes, uint64_t size, uint64_t basePC) : 116 Bytes(bytes), Size(size), BasePC(basePC) {} 117 118 uint64_t getBase() const { return BasePC; } 119 uint64_t getExtent() const { return Size; } 120 121 int readByte(uint64_t Addr, uint8_t *Byte) const { 122 if (Addr - BasePC >= Size) 123 return -1; 124 *Byte = Bytes[Addr - BasePC]; 125 return 0; 126 } 127 }; 128 } // end anonymous namespace 129 130 // 131 // LLVMDisasmInstruction() disassembles a single instruction using the 132 // disassembler context specified in the parameter DC. The bytes of the 133 // instruction are specified in the parameter Bytes, and contains at least 134 // BytesSize number of bytes. The instruction is at the address specified by 135 // the PC parameter. If a valid instruction can be disassembled its string is 136 // returned indirectly in OutString which whos size is specified in the 137 // parameter OutStringSize. This function returns the number of bytes in the 138 // instruction or zero if there was no valid instruction. If this function 139 // returns zero the caller will have to pick how many bytes they want to step 140 // over by printing a .byte, .long etc. to continue. 141 // 142 size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes, 143 uint64_t BytesSize, uint64_t PC, char *OutString, 144 size_t OutStringSize){ 145 LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR; 146 // Wrap the pointer to the Bytes, BytesSize and PC in a MemoryObject. 147 DisasmMemoryObject MemoryObject(Bytes, BytesSize, PC); 148 149 uint64_t Size; 150 MCInst Inst; 151 const MCDisassembler *DisAsm = DC->getDisAsm(); 152 MCInstPrinter *IP = DC->getIP(); 153 MCDisassembler::DecodeStatus S; 154 S = DisAsm->getInstruction(Inst, Size, MemoryObject, PC, 155 /*REMOVE*/ nulls(), DC->CommentStream); 156 switch (S) { 157 case MCDisassembler::Fail: 158 case MCDisassembler::SoftFail: 159 // FIXME: Do something different for soft failure modes? 160 return 0; 161 162 case MCDisassembler::Success: { 163 DC->CommentStream.flush(); 164 StringRef Comments = DC->CommentsToEmit.str(); 165 166 SmallVector<char, 64> InsnStr; 167 raw_svector_ostream OS(InsnStr); 168 IP->printInst(&Inst, OS, Comments); 169 OS.flush(); 170 171 // Tell the comment stream that the vector changed underneath it. 172 DC->CommentsToEmit.clear(); 173 DC->CommentStream.resync(); 174 175 assert(OutStringSize != 0 && "Output buffer cannot be zero size"); 176 size_t OutputSize = std::min(OutStringSize-1, InsnStr.size()); 177 std::memcpy(OutString, InsnStr.data(), OutputSize); 178 OutString[OutputSize] = '\0'; // Terminate string. 179 180 return Size; 181 } 182 } 183 llvm_unreachable("Invalid DecodeStatus!"); 184 } 185