Disassembler.cpp revision 9cb69f6bd3b537e895f74325c931c989f3df042e
1/* 2 * Copyright 2011-2012, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "bcc/Support/Disassembler.h" 18 19#include <llvm/LLVMContext.h> 20 21#include <llvm/MC/MCAsmInfo.h> 22#include <llvm/MC/MCDisassembler.h> 23#include <llvm/MC/MCInst.h> 24#include <llvm/MC/MCInstPrinter.h> 25 26#include <llvm/Support/MemoryObject.h> 27#include <llvm/Support/TargetRegistry.h> 28#include <llvm/Support/TargetSelect.h> 29#include <llvm/Support/raw_ostream.h> 30 31#include <llvm/Target/TargetData.h> 32#include <llvm/Target/TargetMachine.h> 33#include <llvm/Target/TargetOptions.h> 34 35#include "bcc/Config/Config.h" 36#include "bcc/Support/Log.h" 37 38#if USE_DISASSEMBLER 39 40namespace { 41 42class BufferMemoryObject : public llvm::MemoryObject { 43private: 44 const uint8_t *mBytes; 45 uint64_t mLength; 46 47public: 48 BufferMemoryObject(const uint8_t *Bytes, uint64_t Length) 49 : mBytes(Bytes), mLength(Length) { 50 } 51 52 virtual uint64_t getBase() const { return 0; } 53 virtual uint64_t getExtent() const { return mLength; } 54 55 virtual int readByte(uint64_t Addr, uint8_t *Byte) const { 56 if (Addr > getExtent()) 57 return -1; 58 *Byte = mBytes[Addr]; 59 return 0; 60 } 61}; 62 63} // namespace anonymous 64 65namespace bcc { 66 67void InitializeDisassembler() { 68#if defined(PROVIDE_ARM_CODEGEN) 69 LLVMInitializeARMDisassembler(); 70#endif 71 72#if defined(PROVIDE_MIPS_CODEGEN) 73 LLVMInitializeMipsDisassembler(); 74#endif 75 76#if defined(PROVIDE_X86_CODEGEN) 77 LLVMInitializeX86Disassembler(); 78#endif 79} 80 81void Disassemble(char const *OutputFileName, 82 llvm::Target const *Target, 83 llvm::TargetMachine *TM, 84 std::string const &Name, 85 unsigned char const *Func, 86 size_t FuncSize) { 87 88 std::string ErrorInfo; 89 90 // Open the disassembler output file 91 llvm::raw_fd_ostream OS(OutputFileName, ErrorInfo, 92 llvm::raw_fd_ostream::F_Append); 93 94 if (!ErrorInfo.empty()) { 95 ALOGE("Unable to open disassembler output file: %s\n", OutputFileName); 96 return; 97 } 98 99 ALOGI("Writing LLVM disassembly to file: %s\n", OutputFileName); 100 // Disassemble the given function 101 OS << "Disassembled code: " << Name << "\n"; 102 103 const llvm::MCAsmInfo *AsmInfo; 104 const llvm::MCSubtargetInfo *SubtargetInfo; 105 const llvm::MCDisassembler *Disassembler; 106 llvm::MCInstPrinter *IP; 107 108 const std::string& TripleName(Compiler::getTargetTriple()); 109 110 AsmInfo = Target->createMCAsmInfo(Compiler::getTargetTriple()); 111 SubtargetInfo = Target->createMCSubtargetInfo(TripleName, "", ""); 112 Disassembler = Target->createMCDisassembler(*SubtargetInfo); 113 114 const llvm::MCInstrInfo *MII = Target->createMCInstrInfo(); 115 const llvm::MCRegisterInfo *MRI = Target->createMCRegInfo(TripleName); 116 117 IP = Target->createMCInstPrinter(AsmInfo->getAssemblerDialect(), 118 *AsmInfo, 119 *MII, 120 *MRI, 121 *SubtargetInfo); 122 123 const BufferMemoryObject *BufferMObj = new BufferMemoryObject(Func, FuncSize); 124 125 uint64_t Size; 126 uint64_t Index; 127 128 for (Index = 0; Index < FuncSize; Index += Size) { 129 llvm::MCInst Inst; 130 131 if (Disassembler->getInstruction(Inst, Size, *BufferMObj, Index, 132 /* REMOVED */ llvm::nulls(), llvm::nulls())) { 133 OS.indent(4); 134 OS.write("0x", 2); 135 OS.write_hex((uint32_t)Func + Index); 136 OS.write(": 0x", 4); 137 OS.write_hex(*(uint32_t *)(Func + Index)); 138 IP->printInst(&Inst, OS, ""); 139 OS << "\n"; 140 } else { 141 if (Size == 0) 142 Size = 1; // skip illegible bytes 143 } 144 } 145 146 OS << "\n"; 147 148 delete BufferMObj; 149 150 delete AsmInfo; 151 delete Disassembler; 152 delete IP; 153 154 OS.close(); 155} 156 157} // namespace bcc 158 159#endif // USE_DISASSEMBLER 160