15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Copyright (c) 2007, Google Inc. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * modification, are permitted provided that the following conditions are 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * met: 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * * Redistributions of source code must retain the above copyright 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * notice, this list of conditions and the following disclaimer. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * * Redistributions in binary form must reproduce the above 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in the documentation and/or other materials provided with the 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * distribution. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * * Neither the name of Google Inc. nor the names of its 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * contributors may be used to endorse or promote products derived from 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this software without specific prior written permission. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * --- 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Author: Joi Sigurdsson 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Definition of MiniDisassembler. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H_ 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H_ 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "config.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "mini_disassembler_types.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// compatibility shim 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SIDESTEP_ASSERT(cond) RAW_DCHECK(cond, #cond) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SIDESTEP_LOG(msg) RAW_VLOG(1, msg) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sidestep { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This small disassembler is very limited 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in its functionality, and in fact does only the bare minimum required by the 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// preamble patching utility. It may be useful for other purposes, however. 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The limitations include at least the following: 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -# No support for coprocessor opcodes, MMX, etc. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -# No machine-readable identification of opcodes or decoding of 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// assembly parameters. The name of the opcode (as a string) is given, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// however, to aid debugging. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// You may ask what this little disassembler actually does, then? The answer is 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that it does the following, which is exactly what the patching utility needs: 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -# Indicates if opcode is a jump (any kind) or a return (any kind) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// because this is important for the patching utility to determine if 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a function is too short or there are jumps too early in it for it 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to be preamble patched. 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -# The opcode length is always calculated, so that the patching utility 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// can figure out where the next instruction starts, and whether it 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// already has enough instructions to replace with the absolute jump 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to the patching code. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The usage is quite simple; just create a MiniDisassembler and use its 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Disassemble() method. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If you would like to extend this disassembler, please refer to the 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IA-32 Intel® Architecture Software Developer's Manual Volume 2: 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Instruction Set Reference for information about operand decoding 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// etc. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PERFTOOLS_DLL_DECL MiniDisassembler { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates a new instance and sets defaults. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // @param operand_default_32_bits If true, the default operand size is 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // set to 32 bits, which is the default under Win32. Otherwise it is 16 bits. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // @param address_default_32_bits If true, the default address size is 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // set to 32 bits, which is the default under Win32. Otherwise it is 16 bits. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MiniDisassembler(bool operand_default_32_bits, 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool address_default_32_bits); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Equivalent to MiniDisassembler(true, true); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MiniDisassembler(); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Attempts to disassemble a single instruction starting from the 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // address in memory it is pointed to. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // @param start Address where disassembly should start. 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // @param instruction_bytes Variable that will be <b>incremented</b> by 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the length in bytes of the instruction. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // @return enItJump, enItReturn or enItGeneric on success. enItUnknown 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if unable to disassemble, enItUnused if this seems to be an unused 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // opcode. In the last two (error) cases, cbInstruction will be set 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to 0xffffffff. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // @post This instance of the disassembler is ready to be used again, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with unchanged defaults from creation time. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstructionType Disassemble(unsigned char* start, unsigned int& instruction_bytes); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Makes the disassembler ready for reuse. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Initialize(); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets the flags for address and operand sizes. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // @return Number of prefix bytes. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstructionType ProcessPrefixes(unsigned char* start, unsigned int& size); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets the flag for whether we have ModR/M, and increments 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // operand_bytes_ if any are specifies by the opcode directly. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // @return Number of opcode bytes. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstructionType ProcessOpcode(unsigned char* start, 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int table, 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int& size); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Checks the type of the supplied operand. Increments 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // operand_bytes_ if it directly indicates an immediate etc. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // operand. Asserts have_modrm_ if the operand specifies 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a ModR/M byte. 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ProcessOperand(int flag_operand); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Increments operand_bytes_ by size specified by ModR/M and 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by SIB if present. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // @return 0 in case of error, 1 if there is just a ModR/M byte, 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2 if there is a ModR/M byte and a SIB byte. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ProcessModrm(unsigned char* start, unsigned int& size); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Processes the SIB byte that it is pointed to. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // @param start Pointer to the SIB byte. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // @param mod The mod field from the ModR/M byte. 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // @return 1 to indicate success (indicates 1 SIB byte) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ProcessSib(unsigned char* start, unsigned char mod, unsigned int& size); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The instruction type we have decoded from the opcode. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstructionType instruction_type_; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Counts the number of bytes that is occupied by operands in 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the current instruction (note: we don't care about how large 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // operands stored in registers etc. are). 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int operand_bytes_; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // True iff there is a ModR/M byte in this instruction. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool have_modrm_; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // True iff we need to decode the ModR/M byte (sometimes it just 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // points to a register, we can tell by the addressing mode). 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool should_decode_modrm_; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Current operand size is 32 bits if true, 16 bits if false. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool operand_is_32_bits_; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Default operand size is 32 bits if true, 16 bits if false. 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool operand_default_is_32_bits_; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Current address size is 32 bits if true, 16 bits if false. 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool address_is_32_bits_; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Default address size is 32 bits if true, 16 bits if false. 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool address_default_is_32_bits_; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Determines if 64 bit operands are supported (x64). 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool operand_default_support_64_bits_; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Current operand size is 64 bits if true, 32 bits if false. 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool operand_is_64_bits_; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Huge big opcode table based on the IA-32 manual, defined 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in Ia32OpcodeMap.cc 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const OpcodeTable s_ia32_opcode_map_[]; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Somewhat smaller table to help with decoding ModR/M bytes 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when 16-bit addressing mode is being used. Defined in 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ia32ModrmMap.cc 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const ModrmEntry s_ia16_modrm_map_[]; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Somewhat smaller table to help with decoding ModR/M bytes 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when 32-bit addressing mode is being used. Defined in 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ia32ModrmMap.cc 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const ModrmEntry s_ia32_modrm_map_[]; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicators of whether we got certain prefixes that certain 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // silly Intel instructions depend on in nonstandard ways for 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // their behaviors. 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool got_f2_prefix_, got_f3_prefix_, got_66_prefix_; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; // namespace sidestep 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H_ 198