Disassembler.cpp revision 5b948190e3b311d06526addbb8f0e77a76da2467
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/DebugHelper.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_X86_CODEGEN) 73 LLVMInitializeX86Disassembler(); 74#endif 75} 76 77void Disassemble(char const *OutputFileName, 78 llvm::Target const *Target, 79 llvm::TargetMachine *TM, 80 std::string const &Name, 81 unsigned char const *Func, 82 size_t FuncSize) { 83 84 std::string ErrorInfo; 85 86 // Open the disassembler output file 87 llvm::raw_fd_ostream OS(OutputFileName, ErrorInfo, 88 llvm::raw_fd_ostream::F_Append); 89 90 if (!ErrorInfo.empty()) { 91 ALOGE("Unable to open disassembler output file: %s\n", OutputFileName); 92 return; 93 } 94 95 // Disassemble the given function 96 OS << "Disassembled code: " << Name << "\n"; 97 98 const llvm::MCAsmInfo *AsmInfo; 99 const llvm::MCSubtargetInfo *SubtargetInfo; 100 const llvm::MCDisassembler *Disassmbler; 101 llvm::MCInstPrinter *IP; 102 103 AsmInfo = Target->createMCAsmInfo(TM->getTargetTriple()); 104 SubtargetInfo = Target->createMCSubtargetInfo(TM->getTargetTriple(), 105 TM->getTargetCPU(), 106 TM->getTargetFeatureString()); 107 Disassmbler = Target->createMCDisassembler(*SubtargetInfo); 108 IP = Target->createMCInstPrinter(AsmInfo->getAssemblerDialect(), 109 *AsmInfo, *SubtargetInfo); 110 111 const BufferMemoryObject *BufferMObj = new BufferMemoryObject(Func, FuncSize); 112 113 uint64_t Size; 114 uint64_t Index; 115 116 for (Index = 0; Index < FuncSize; Index += Size) { 117 llvm::MCInst Inst; 118 119 if (Disassmbler->getInstruction(Inst, Size, *BufferMObj, Index, 120 /* REMOVED */ llvm::nulls(), llvm::nulls())) { 121 OS.indent(4); 122 OS.write("0x", 2); 123 OS.write_hex((uint32_t)Func + Index); 124 OS.write(": 0x", 4); 125 OS.write_hex(*(uint32_t *)(Func + Index)); 126 IP->printInst(&Inst, OS, ""); 127 OS << "\n"; 128 } else { 129 if (Size == 0) 130 Size = 1; // skip illegible bytes 131 } 132 } 133 134 OS << "\n"; 135 136 delete BufferMObj; 137 138 delete AsmInfo; 139 delete Disassmbler; 140 delete IP; 141 142 OS.close(); 143} 144 145} // namespace bcc 146 147#endif // USE_DISASSEMBLER 148