blob: 161a9427fa7887e10c521f73fb158ff40255c354 [file] [log] [blame]
// Copyright 2012 Google Inc. All Rights Reserved.
//
// 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.
//
// Utility functions for use with disassembler callbacks.
#ifndef SYZYGY_CORE_DISASSEMBLER_UTIL_H_
#define SYZYGY_CORE_DISASSEMBLER_UTIL_H_
#include <stdint.h>
#include <string>
#include "syzygy/assm/register.h"
#include "distorm.h" // NOLINT
#include "mnemonics.h" // NOLINT
namespace core {
using assm::Register;
using assm::RegisterId;
// Wrapper for the distorm_decompose function to patch a bug in distorm.
// @param ci Structure containing some information about the code to decompose
// (code origin, code data, code length, decoding mode and features).
// @param result Array of type _DecodeInst which will be used by this function
// in order to return the disassembled instructions.
// @param max_instructions The maximum number of entries in the result array
// that you pass to this function, so it won't exceed its bound.
// @param used_instructions_count Number of the instruction that successfully
// were disassembled and written to the result array.
// @returns DECRES_SUCCESS on success (no more to disassemble), DECRES_INPUTERR
// on input error (null code buffer, invalid decoding mode, etc...),
// DECRES_MEMORYERR when there are not enough entries to use in the result
// array, BUT YOU STILL have to check for usedInstructionsCount!
_DecodeResult DistormDecompose(_CodeInfo* ci,
_DInst result[],
unsigned int max_instructions,
unsigned int* used_instructions_count);
// Decodes exactly one instruction from the given buffer.
// @param address the address of the instruction, as an absolute address
// consistent with the image's base address. If this is not provided a
// fake address of 0x10000000 will be used.
// @param buffer the buffer containing the data to decode.
// @param length the length of the buffer.
// @returns true if an instruction was decoded, false otherwise.
bool DecodeOneInstruction(uint32_t address,
const uint8_t* buffer,
size_t length,
_DInst* instruction);
bool DecodeOneInstruction(const uint8_t* buffer,
size_t length,
_DInst* instruction);
// Dump text representation of exactly one instruction to a std::string.
// @param instruction the instruction to dump.
// @param data points to the raw byte sequences.
// @param code_length the size of the raw representation.
// @param buffer receives the text representation.
// @returns true if @p instruction was successfully dumped, false otherwise.
bool InstructionToString(const _DInst& instruction,
const uint8_t* data,
int code_length,
std::string* buffer);
// Determines if the given instruction is a recognized no-op. We only recognize
// those instructions that we see generated by the MSVS toolchain.
// @param instruction the instruction to evaluate.
// @returns true if @p instruction is a recognized no-op, false otherwise.
bool IsNop(const _DInst& instruction);
// Determines if the given instruction is a CALL.
// @param instruction the instruction to evaluate.
// @returns true if @p instruction is a call, false otherwise.
bool IsCall(const _DInst& instruction);
// Determines if the given instruction is a RET.
// @param instruction the instruction to evaluate.
// @returns true if @p instruction is a return, false otherwise.
bool IsReturn(const _DInst& instruction);
// Determines if the given instruction is a SYS.
// @param instruction the instruction to evaluate.
// @returns true if @p instruction is a return, false otherwise.
bool IsSystemCall(const _DInst& instruction);
// Determines if the given instruction is a conditional branch.
// @param instruction the instruction to evaluate.
// @returns true if @p instruction is a conditional branch, false otherwise.
bool IsConditionalBranch(const _DInst& instruction);
// Determines if the given instruction is a unconditional branch.
// @param instruction the instruction to evaluate.
// @returns true if @p instruction is a unconditional branch, false otherwise.
bool IsUnconditionalBranch(const _DInst& instruction);
// Determines if the given instruction is a branch or any kind
// @param instruction the instruction to evaluate.
// @returns true if @p instruction is a branch, false otherwise.
bool IsBranch(const _DInst& instruction);
// Determines if the given instruction has a PC-relative operand at the
// given operand index.
// @param instruction the instruction to evaluate.
// @param operand_index the operand index to evaluate.
// @returns true if @p instruction has a PC-relative operand at the given index.
bool HasPcRelativeOperand(const _DInst& instruction, int operand_index);
// Determines if the given instruction is a control-flow instruction.
// @param instruction the instruction to evaluate.
// @returns true if @p instruction is a control-flow instruction, false
// otherwise.
bool IsControlFlow(const _DInst& instruction);
// Determines if the given instruction is an implicit control-flow instruction.
// @param instruction the instruction to evaluate.
// @returns true if @p instruction is an implicit control-flow instruction
// (we can't explicitly compute the target due to the addressing mode)
// false otherwise.
bool IsImplicitControlFlow(const _DInst& instruction);
// Determines if the given instruction is an interrupt instruction.
// @param instruction the instruction to evaluate.
// @returns true if @p instruction is an interrupt instruction, false otherwise.
bool IsInterrupt(const _DInst& instruction);
// Determines if the given instruction is the debug interrupt instruction.
// @param instruction the instruction to evaluate.
// @returns true if @p instruction is the debug interrupt instruction, false
// otherwise.
bool IsDebugInterrupt(const _DInst& instruction);
// @name Distorm _RegisterType conversion.
// @{
// Converts from a register to a Distorm _RegisterType.
// @param reg The register object whose type we wish to retrieve.
// @returns the Distorm register type.
_RegisterType GetRegisterType(const Register& reg);
// Converts from a register id to a Distorm _RegisterType.
// @param reg_id The register id to to convert to a _RegisterType.
// @returns the Distorm register type.
_RegisterType GetRegisterType(RegisterId reg_id);
// Given a Distorm register type, converts to a RegisterId.
// @param distorm_reg_type The Distorm register type to be converted.
// @returns the id of the register.
RegisterId GetRegisterId(uint32_t distorm_reg_type);
// Given a Distorm register type, returns the associated register object.
// @param distorm_reg_type The Distorm register type to be converted.
// @returns a const reference to the register object.
const Register& GetRegister(uint32_t distorm_reg_type);
// @}
} // namespace core
#endif // SYZYGY_CORE_DISASSEMBLER_UTIL_H_