mini_disassembler.h revision 5821806d5e7f356e8fa4b058a389a808ea183019
1/* Copyright (c) 2007, Google Inc. 2 * All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * --- 31 * Author: Joi Sigurdsson 32 * 33 * Definition of MiniDisassembler. 34 */ 35 36#ifndef GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H_ 37#define GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H_ 38 39#include "config.h" 40#include <windows.h> 41#include "mini_disassembler_types.h" 42 43// compatibility shim 44#include "base/logging.h" 45#define SIDESTEP_ASSERT(cond) RAW_DCHECK(cond, #cond) 46#define SIDESTEP_LOG(msg) RAW_VLOG(1, msg) 47 48namespace sidestep { 49 50// This small disassembler is very limited 51// in its functionality, and in fact does only the bare minimum required by the 52// preamble patching utility. It may be useful for other purposes, however. 53// 54// The limitations include at least the following: 55// -# No support for coprocessor opcodes, MMX, etc. 56// -# No machine-readable identification of opcodes or decoding of 57// assembly parameters. The name of the opcode (as a string) is given, 58// however, to aid debugging. 59// 60// You may ask what this little disassembler actually does, then? The answer is 61// that it does the following, which is exactly what the patching utility needs: 62// -# Indicates if opcode is a jump (any kind) or a return (any kind) 63// because this is important for the patching utility to determine if 64// a function is too short or there are jumps too early in it for it 65// to be preamble patched. 66// -# The opcode length is always calculated, so that the patching utility 67// can figure out where the next instruction starts, and whether it 68// already has enough instructions to replace with the absolute jump 69// to the patching code. 70// 71// The usage is quite simple; just create a MiniDisassembler and use its 72// Disassemble() method. 73// 74// If you would like to extend this disassembler, please refer to the 75// IA-32 Intel® Architecture Software Developer's Manual Volume 2: 76// Instruction Set Reference for information about operand decoding 77// etc. 78class PERFTOOLS_DLL_DECL MiniDisassembler { 79 public: 80 81 // Creates a new instance and sets defaults. 82 // 83 // @param operand_default_32_bits If true, the default operand size is 84 // set to 32 bits, which is the default under Win32. Otherwise it is 16 bits. 85 // @param address_default_32_bits If true, the default address size is 86 // set to 32 bits, which is the default under Win32. Otherwise it is 16 bits. 87 MiniDisassembler(bool operand_default_32_bits, 88 bool address_default_32_bits); 89 90 // Equivalent to MiniDisassembler(true, true); 91 MiniDisassembler(); 92 93 // Attempts to disassemble a single instruction starting from the 94 // address in memory it is pointed to. 95 // 96 // @param start Address where disassembly should start. 97 // @param instruction_bytes Variable that will be <b>incremented</b> by 98 // the length in bytes of the instruction. 99 // @return enItJump, enItReturn or enItGeneric on success. enItUnknown 100 // if unable to disassemble, enItUnused if this seems to be an unused 101 // opcode. In the last two (error) cases, cbInstruction will be set 102 // to 0xffffffff. 103 // 104 // @post This instance of the disassembler is ready to be used again, 105 // with unchanged defaults from creation time. 106 InstructionType Disassemble(unsigned char* start, unsigned int& instruction_bytes); 107 108 private: 109 110 // Makes the disassembler ready for reuse. 111 void Initialize(); 112 113 // Sets the flags for address and operand sizes. 114 // @return Number of prefix bytes. 115 InstructionType ProcessPrefixes(unsigned char* start, unsigned int& size); 116 117 // Sets the flag for whether we have ModR/M, and increments 118 // operand_bytes_ if any are specifies by the opcode directly. 119 // @return Number of opcode bytes. 120 InstructionType ProcessOpcode(unsigned char* start, 121 unsigned int table, 122 unsigned int& size); 123 124 // Checks the type of the supplied operand. Increments 125 // operand_bytes_ if it directly indicates an immediate etc. 126 // operand. Asserts have_modrm_ if the operand specifies 127 // a ModR/M byte. 128 bool ProcessOperand(int flag_operand); 129 130 // Increments operand_bytes_ by size specified by ModR/M and 131 // by SIB if present. 132 // @return 0 in case of error, 1 if there is just a ModR/M byte, 133 // 2 if there is a ModR/M byte and a SIB byte. 134 bool ProcessModrm(unsigned char* start, unsigned int& size); 135 136 // Processes the SIB byte that it is pointed to. 137 // @param start Pointer to the SIB byte. 138 // @param mod The mod field from the ModR/M byte. 139 // @return 1 to indicate success (indicates 1 SIB byte) 140 bool ProcessSib(unsigned char* start, unsigned char mod, unsigned int& size); 141 142 // The instruction type we have decoded from the opcode. 143 InstructionType instruction_type_; 144 145 // Counts the number of bytes that is occupied by operands in 146 // the current instruction (note: we don't care about how large 147 // operands stored in registers etc. are). 148 unsigned int operand_bytes_; 149 150 // True iff there is a ModR/M byte in this instruction. 151 bool have_modrm_; 152 153 // True iff we need to decode the ModR/M byte (sometimes it just 154 // points to a register, we can tell by the addressing mode). 155 bool should_decode_modrm_; 156 157 // Current operand size is 32 bits if true, 16 bits if false. 158 bool operand_is_32_bits_; 159 160 // Default operand size is 32 bits if true, 16 bits if false. 161 bool operand_default_is_32_bits_; 162 163 // Current address size is 32 bits if true, 16 bits if false. 164 bool address_is_32_bits_; 165 166 // Default address size is 32 bits if true, 16 bits if false. 167 bool address_default_is_32_bits_; 168 169 // Determines if 64 bit operands are supported (x64). 170 bool operand_default_support_64_bits_; 171 172 // Current operand size is 64 bits if true, 32 bits if false. 173 bool operand_is_64_bits_; 174 175 // Huge big opcode table based on the IA-32 manual, defined 176 // in Ia32OpcodeMap.cc 177 static const OpcodeTable s_ia32_opcode_map_[]; 178 179 // Somewhat smaller table to help with decoding ModR/M bytes 180 // when 16-bit addressing mode is being used. Defined in 181 // Ia32ModrmMap.cc 182 static const ModrmEntry s_ia16_modrm_map_[]; 183 184 // Somewhat smaller table to help with decoding ModR/M bytes 185 // when 32-bit addressing mode is being used. Defined in 186 // Ia32ModrmMap.cc 187 static const ModrmEntry s_ia32_modrm_map_[]; 188 189 // Indicators of whether we got certain prefixes that certain 190 // silly Intel instructions depend on in nonstandard ways for 191 // their behaviors. 192 bool got_f2_prefix_, got_f3_prefix_, got_66_prefix_; 193}; 194 195}; // namespace sidestep 196 197#endif // GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H_ 198