/* * Copyright 2011, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "Disassembler.h" #include "Config.h" #include "DebugHelper.h" #include "ExecutionEngine/Compiler.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCDisassembler.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstPrinter.h" #include "llvm/Support/MemoryObject.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Target/TargetSelect.h" #include "llvm/LLVMContext.h" #if USE_DISASSEMBLER namespace { class BufferMemoryObject : public llvm::MemoryObject { private: const uint8_t *mBytes; uint64_t mLength; public: BufferMemoryObject(const uint8_t *Bytes, uint64_t Length) : mBytes(Bytes), mLength(Length) { } virtual uint64_t getBase() const { return 0; } virtual uint64_t getExtent() const { return mLength; } virtual int readByte(uint64_t Addr, uint8_t *Byte) const { if (Addr > getExtent()) return -1; *Byte = mBytes[Addr]; return 0; } }; } // namespace anonymous namespace bcc { void InitializeDisassembler() { #if defined(DEFAULT_ARM_CODEGEN) || defined(PROVIDE_ARM_CODEGEN) LLVMInitializeARMDisassembler(); #endif #if defined(DEFAULT_X86_CODEGEN) || defined(PROVIDE_X86_CODEGEN) || \ defined(DEFAULT_X64_CODEGEN) || defined(PROVIDE_X64_CODEGEN) LLVMInitializeX86Disassembler(); #endif } void Disassemble(char const *OutputFileName, llvm::Target const *Target, llvm::TargetMachine *TM, std::string const &Name, unsigned char const *Func, size_t FuncSize) { std::string ErrorInfo; // Open the disassembler output file llvm::raw_fd_ostream OS(OutputFileName, ErrorInfo, llvm::raw_fd_ostream::F_Append); if (!ErrorInfo.empty()) { LOGE("Unable to open disassembler output file: %s\n", OutputFileName); return; } // Disassemble the given function OS << "Disassembled code: " << Name << "\n"; const llvm::MCAsmInfo *AsmInfo; const llvm::MCDisassembler *Disassmbler; llvm::MCInstPrinter *IP; AsmInfo = Target->createMCAsmInfo(Compiler::getTargetTriple()); Disassmbler = Target->createMCDisassembler(); IP = Target->createMCInstPrinter(AsmInfo->getAssemblerDialect(), *AsmInfo); const BufferMemoryObject *BufferMObj = new BufferMemoryObject(Func, FuncSize); uint64_t Size; uint64_t Index; for (Index = 0; Index < FuncSize; Index += Size) { llvm::MCInst Inst; if (Disassmbler->getInstruction(Inst, Size, *BufferMObj, Index, /* REMOVED */ llvm::nulls())) { OS.indent(4); OS.write("0x", 2); OS.write_hex((uint32_t)Func + Index); OS.write(": 0x", 4); OS.write_hex(*(uint32_t *)(Func + Index)); IP->printInst(&Inst, OS); OS << "\n"; } else { if (Size == 0) Size = 1; // skip illegible bytes } } OS << "\n"; delete BufferMObj; delete AsmInfo; delete Disassmbler; delete IP; OS.close(); } } // namespace bcc #endif // USE_DISASSEMBLER