Disassembler.cpp revision fce15a42406e17de62b5b6f0734e4eefba6642c2
19347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien/* 2c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang * Copyright 2011-2012, The Android Open Source Project 39347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien * 49347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien * Licensed under the Apache License, Version 2.0 (the "License"); 59347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien * you may not use this file except in compliance with the License. 69347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien * You may obtain a copy of the License at 79347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien * 89347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien * http://www.apache.org/licenses/LICENSE-2.0 99347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien * 109347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien * Unless required by applicable law or agreed to in writing, software 119347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien * distributed under the License is distributed on an "AS IS" BASIS, 129347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien * See the License for the specific language governing permissions and 149347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien * limitations under the License. 159347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien */ 169347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 17c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include "bcc/Support/Disassembler.h" 189347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 19388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao#include "bcc/Config/Config.h" 20388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao#if USE_DISASSEMBLER 21388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 22388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao#include <string> 23388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 24fce15a42406e17de62b5b6f0734e4eefba6642c2Stephen Hines#include <llvm/IR/LLVMContext.h> 259347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 26c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include <llvm/MC/MCAsmInfo.h> 27c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include <llvm/MC/MCDisassembler.h> 28c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include <llvm/MC/MCInst.h> 29c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include <llvm/MC/MCInstPrinter.h> 30388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao#include <llvm/MC/MCInstrInfo.h> 31388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao#include <llvm/MC/MCRegisterInfo.h> 32388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao#include <llvm/MC/MCSubtargetInfo.h> 339347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 34c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include <llvm/Support/MemoryObject.h> 35c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include <llvm/Support/TargetRegistry.h> 36c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include <llvm/Support/raw_ostream.h> 379347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 38388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao#include "bcc/Support/OutputFile.h" 39ef73a242762bcd8113b9b65ceccbe7d909b5acbcZonr Chang#include "bcc/Support/Log.h" 409347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 419347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chiennamespace { 429347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 439347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chienclass BufferMemoryObject : public llvm::MemoryObject { 449347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chienprivate: 459347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien const uint8_t *mBytes; 469347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien uint64_t mLength; 479347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 489347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chienpublic: 49388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao BufferMemoryObject(const uint8_t *pBytes, uint64_t pLength) 50388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao : mBytes(pBytes), mLength(pLength) { 519347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien } 529347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 539347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien virtual uint64_t getBase() const { return 0; } 549347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien virtual uint64_t getExtent() const { return mLength; } 559347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 56388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao virtual int readByte(uint64_t pAddr, uint8_t *pByte) const { 57388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao if (pAddr > getExtent()) 589347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien return -1; 59388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao *pByte = mBytes[pAddr]; 609347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien return 0; 619347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien } 629347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien}; 639347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 649347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien} // namespace anonymous 659347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 669347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chiennamespace bcc { 679347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 68388fec12e6bbf5798281d266cac63630bcaba333Shih-wei LiaoDisassembleResult Disassemble(llvm::raw_ostream &pOutput, const char *pTriple, 69388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao const char *pFuncName, const uint8_t *pFunc, 70388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao size_t pFuncSize) { 71388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao DisassembleResult result = kDisassembleSuccess; 72388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao uint64_t i = 0; 73388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 74388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao const llvm::MCSubtargetInfo *subtarget_info = NULL; 75388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao const llvm::MCDisassembler *disassembler = NULL; 76388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao const llvm::MCInstrInfo *mc_inst_info = NULL; 77388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao const llvm::MCRegisterInfo *mc_reg_info = NULL; 78388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao const llvm::MCAsmInfo *asm_info = NULL; 79388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao llvm::MCInstPrinter *inst_printer = NULL; 80388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 81388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao BufferMemoryObject *input_function = NULL; 82388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 83388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao std::string error; 84388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao const llvm::Target* target = 85388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao llvm::TargetRegistry::lookupTarget(pTriple, error); 86388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 87388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao if (target == NULL) { 88388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao ALOGE("Invalid target triple for disassembler: %s (%s)!", 89388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao pTriple, error.c_str()); 90388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao return kDisassembleUnknownTarget; 91388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao } 929347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 93388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao subtarget_info = 94388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao target->createMCSubtargetInfo(pTriple, /* CPU */"", /* Features */"");; 959cb69f6bd3b537e895f74325c931c989f3df042eShih-wei Liao 96388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao if (subtarget_info == NULL) { 97388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao result = kDisassembleFailedSetup; 98388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao goto bail; 99388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao } 100388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 101388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao disassembler = target->createMCDisassembler(*subtarget_info); 102388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 103388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao mc_inst_info = target->createMCInstrInfo(); 104388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 105388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao mc_reg_info = target->createMCRegInfo(pTriple); 106388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 107388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao asm_info = target->createMCAsmInfo(pTriple); 1089347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 109388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao if ((disassembler == NULL) || (mc_inst_info == NULL) || 110388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao (mc_reg_info == NULL) || (asm_info == NULL)) { 111388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao result = kDisassembleFailedSetup; 112388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao goto bail; 113388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao } 114388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 115388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao inst_printer = target->createMCInstPrinter(asm_info->getAssemblerDialect(), 116388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao *asm_info, *mc_inst_info, 117388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao *mc_reg_info, *subtarget_info); 1189347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 119388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao if (inst_printer == NULL) { 120388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao result = kDisassembleFailedSetup; 121388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao goto bail; 122388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao } 1239347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 124388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao input_function = new (std::nothrow) BufferMemoryObject(pFunc, pFuncSize); 125f11da3081765d3323381b16f2867b2f1df2b9cbaLogan Chien 126388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao if (input_function == NULL) { 127388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao result = kDisassembleOutOfMemory; 128388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao goto bail; 1299347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien } 1309347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 131f11da3081765d3323381b16f2867b2f1df2b9cbaLogan Chien // Disassemble the given function 132388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao pOutput << "Disassembled code: " << pFuncName << "\n"; 133388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 134388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao while (i < pFuncSize) { 135388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao llvm::MCInst inst; 136388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao uint64_t inst_size; 137388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 138388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao llvm::MCDisassembler::DecodeStatus decode_result = 139388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao disassembler->getInstruction(inst, inst_size, *input_function, i, 140388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao llvm::nulls(), llvm::nulls()); 141388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 142388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao switch (decode_result) { 143388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao case llvm::MCDisassembler::Fail: { 144388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao ALOGW("Invalid instruction encoding encountered at %llu of function %s " 145388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao "under %s.", i, pFuncName, pTriple); 146388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao i++; 147388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao break; 148388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao } 149388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao case llvm::MCDisassembler::SoftFail: { 150388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao ALOGW("Potentially undefined instruction encoding encountered at %llu " 151388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao "of function %s under %s.", i, pFuncName, pTriple); 152388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao // fall-through 153388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao } 154388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao case llvm::MCDisassembler::Success : { 155388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao const uint8_t *inst_addr = pFunc + i; 156388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 157388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao pOutput.indent(4); 158388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao pOutput << "0x"; 159388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao pOutput.write_hex(reinterpret_cast<uintptr_t>(inst_addr)); 160388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao pOutput << ": 0x"; 161388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao pOutput.write_hex(*reinterpret_cast<const uint32_t *>(inst_addr)); 162388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao inst_printer->printInst(&inst, pOutput, /* Annot */""); 163388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao pOutput << "\n"; 164388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 165388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao i += inst_size; 166388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao break; 167388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao } 1689347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien } 1699347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien } 1709347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 171388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao pOutput << "\n"; 172388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 173388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liaobail: 174388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao // Clean up 175388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao delete input_function; 176388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao delete inst_printer; 177388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao delete asm_info; 178388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao delete mc_reg_info; 179388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao delete mc_inst_info; 180388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao delete disassembler; 181388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao delete subtarget_info; 182f11da3081765d3323381b16f2867b2f1df2b9cbaLogan Chien 183388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao return result; 184388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao} 185388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 186388fec12e6bbf5798281d266cac63630bcaba333Shih-wei LiaoDisassembleResult Disassemble(OutputFile &pOutput, const char *pTriple, 187388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao const char *pFuncName, const uint8_t *pFunc, 188388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao size_t FuncSize) { 189388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao // Check the state of the specified output file. 190388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao if (pOutput.hasError()) { 191388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao return kDisassembleInvalidOutput; 192388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao } 1939347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 194388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao // Open the output file decorated in llvm::raw_ostream. 195388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao llvm::raw_ostream *output = pOutput.dup(); 196388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao if (output == NULL) { 197388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao return kDisassembleFailedPrepareOutput; 198388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao } 1999347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 200388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao // Delegate the request. 201388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao DisassembleResult result = 202388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao Disassemble(*output, pTriple, pFuncName, pFunc, FuncSize); 203388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 204388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao // Close the output before return. 205388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao delete output; 206388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 207388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao return result; 2089347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien} 2099347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 2109347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien} // namespace bcc 2119347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien 212388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao#else 213388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 214388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liaobcc::DisassembleResult Disassemble(llvm::raw_ostream &pOutput, 215388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao const char *pTriple, const char *pFuncName, 216388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao const uint8_t *pFunc, size_t pFuncSize) { 217388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao return bcc::kDisassemblerNotAvailable; 218388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao} 219388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 220388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liaobcc::DisassembleResult bcc::Disassemble(OutputFile &pOutput, 221388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao const char *pTriple, 222388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao const char *pFuncName, 223388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao const uint8_t *pFunc, 224388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao size_t pFuncSize) { 225388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao return bcc::kDisassemblerNotAvailable; 226388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao} 227388fec12e6bbf5798281d266cac63630bcaba333Shih-wei Liao 2289347e0bdf9d9cb691c3681ea06c87716b6251af4Logan Chien#endif // USE_DISASSEMBLER 229