| // 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_ |