15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Definition of MiniDisassembler. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SANDBOX_SRC_SIDESTEP_MINI_DISASSEMBLER_H__ 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SANDBOX_SRC_SIDESTEP_MINI_DISASSEMBLER_H__ 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/sidestep/mini_disassembler_types.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sidestep { 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This small disassembler is very limited 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in its functionality, and in fact does only the bare minimum required by the 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// preamble patching utility. It may be useful for other purposes, however. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The limitations include at least the following: 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -# No support for coprocessor opcodes, MMX, etc. 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -# No machine-readable identification of opcodes or decoding of 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// assembly parameters. The name of the opcode (as a string) is given, 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// however, to aid debugging. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// You may ask what this little disassembler actually does, then? The answer is 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that it does the following, which is exactly what the patching utility needs: 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -# Indicates if opcode is a jump (any kind) or a return (any kind) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// because this is important for the patching utility to determine if 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a function is too short or there are jumps too early in it for it 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to be preamble patched. 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -# The opcode length is always calculated, so that the patching utility 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// can figure out where the next instruction starts, and whether it 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// already has enough instructions to replace with the absolute jump 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to the patching code. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The usage is quite simple; just create a MiniDisassembler and use its 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Disassemble() method. 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If you would like to extend this disassembler, please refer to the 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IA-32 Intel Architecture Software Developer's Manual Volume 2: 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Instruction Set Reference for information about operand decoding 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// etc. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MiniDisassembler { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates a new instance and sets defaults. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // operand_default_32_bits: If true, the default operand size is 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // set to 32 bits, which is the default under Win32. Otherwise it is 16 bits. 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // address_default_32_bits: If true, the default address size is 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // set to 32 bits, which is the default under Win32. Otherwise it is 16 bits. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MiniDisassembler(bool operand_default_32_bits, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool address_default_32_bits); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Equivalent to MiniDisassembler(true, true); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MiniDisassembler(); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Attempts to disassemble a single instruction starting from the 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // address in memory it is pointed to. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // start: Address where disassembly should start. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instruction_bytes: Variable that will be incremented by 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the length in bytes of the instruction. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns enItJump, enItReturn or enItGeneric on success. enItUnknown 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if unable to disassemble, enItUnused if this seems to be an unused 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // opcode. In the last two (error) cases, cbInstruction will be set 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to 0xffffffff. 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Postcondition: This instance of the disassembler is ready to be used again, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with unchanged defaults from creation time. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstructionType Disassemble(unsigned char* start, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int* instruction_bytes); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Makes the disassembler ready for reuse. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Initialize(); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets the flags for address and operand sizes. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns Number of prefix bytes. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstructionType ProcessPrefixes(unsigned char* start, unsigned int* size); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets the flag for whether we have ModR/M, and increments 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // operand_bytes_ if any are specifies by the opcode directly. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns Number of opcode bytes. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstructionType ProcessOpcode(unsigned char* start, 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int table, 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int* size); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Checks the type of the supplied operand. Increments 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // operand_bytes_ if it directly indicates an immediate etc. 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // operand. Asserts have_modrm_ if the operand specifies 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a ModR/M byte. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ProcessOperand(int flag_operand); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Increments operand_bytes_ by size specified by ModR/M and 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by SIB if present. 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns 0 in case of error, 1 if there is just a ModR/M byte, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2 if there is a ModR/M byte and a SIB byte. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ProcessModrm(unsigned char* start, unsigned int* size); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Processes the SIB byte that it is pointed to. 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // start: Pointer to the SIB byte. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mod: The mod field from the ModR/M byte. 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns 1 to indicate success (indicates 1 SIB byte) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ProcessSib(unsigned char* start, unsigned char mod, unsigned int* size); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The instruction type we have decoded from the opcode. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstructionType instruction_type_; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Counts the number of bytes that is occupied by operands in 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the current instruction (note: we don't care about how large 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // operands stored in registers etc. are). 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int operand_bytes_; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // True iff there is a ModR/M byte in this instruction. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool have_modrm_; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // True iff we need to decode the ModR/M byte (sometimes it just 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // points to a register, we can tell by the addressing mode). 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool should_decode_modrm_; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Current operand size is 32 bits if true, 16 bits if false. 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool operand_is_32_bits_; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Default operand size is 32 bits if true, 16 bits if false. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool operand_default_is_32_bits_; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Current address size is 32 bits if true, 16 bits if false. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool address_is_32_bits_; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Default address size is 32 bits if true, 16 bits if false. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool address_default_is_32_bits_; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Huge big opcode table based on the IA-32 manual, defined 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in Ia32OpcodeMap.cpp 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const OpcodeTable s_ia32_opcode_map_[]; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Somewhat smaller table to help with decoding ModR/M bytes 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when 16-bit addressing mode is being used. Defined in 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ia32ModrmMap.cpp 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const ModrmEntry s_ia16_modrm_map_[]; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Somewhat smaller table to help with decoding ModR/M bytes 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when 32-bit addressing mode is being used. Defined in 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ia32ModrmMap.cpp 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const ModrmEntry s_ia32_modrm_map_[]; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicators of whether we got certain prefixes that certain 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // silly Intel instructions depend on in nonstandard ways for 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // their behaviors. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool got_f2_prefix_, got_f3_prefix_, got_66_prefix_; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; // namespace sidestep 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // SANDBOX_SRC_SIDESTEP_MINI_DISASSEMBLER_H__ 157