mirror of https://github.com/x64dbg/zydis
Merge branch 'develop'
This commit is contained in:
commit
5bab2410fc
|
@ -16,7 +16,7 @@ if (NOT CONFIGURED_ONCE)
|
|||
set(compiler_specific "-Werror")
|
||||
set(compiler_specific_cxx "-std=c++14")
|
||||
elseif (MSVC)
|
||||
set(compiler_specific "/WX /W4 /D_CRT_SECURE_NO_WARNINGS")
|
||||
set(compiler_specific "/WX /W4 /D_CRT_SECURE_NO_WARNINGS /GR-")
|
||||
endif ()
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${compiler_specific} ${compiler_specific_cxx}"
|
||||
|
@ -27,7 +27,7 @@ endif ()
|
|||
|
||||
# CMake always orders MSVC to build with a shared CRT. Hack CMake variables in order
|
||||
# to generate with a statically linked CRT when we build as a static library.
|
||||
if (MSVC AND NOT BUILD_SHARED_LIBS AND NOT FORCE_SHARED_CRT)
|
||||
if (MSVC AND NOT FORCE_SHARED_CRT)
|
||||
set(manipulated_vars
|
||||
CMAKE_CXX_FLAGS_DEBUG
|
||||
CMAKE_CXX_FLAGS_MINSIZEREL
|
||||
|
@ -58,6 +58,11 @@ set(sources
|
|||
"Zydis/ZydisSymbolResolver.cpp"
|
||||
"Zydis/ZydisUtils.cpp")
|
||||
|
||||
if (BUILD_SHARED_LIBS AND WIN32)
|
||||
set(sources ${sources}
|
||||
"Zydis/VersionInfo.rc")
|
||||
endif ()
|
||||
|
||||
if (BUILD_C_BINDINGS)
|
||||
set(headers ${headers}
|
||||
"Zydis/ZydisAPI.h")
|
||||
|
@ -66,6 +71,7 @@ if (BUILD_C_BINDINGS)
|
|||
endif ()
|
||||
|
||||
add_library("Zydis" ${headers} ${sources})
|
||||
set_target_properties("Zydis" PROPERTIES COMPILE_DEFINITIONS "Zydis_EXPORTS")
|
||||
generate_export_header(
|
||||
"Zydis"
|
||||
BASE_NAME "ZYDIS"
|
||||
|
@ -78,6 +84,8 @@ if (BUILD_EXAMPLES)
|
|||
|
||||
add_executable("SimpleDemo_CPP" "Examples/CPP/SimpleDemo/SimpleDemo.cpp")
|
||||
target_link_libraries("SimpleDemo_CPP" "Zydis")
|
||||
add_executable("CustomDataSource_CPP" "Examples/CPP/CustomDataSource/CustomDataSource.cpp")
|
||||
target_link_libraries("CustomDataSource_CPP" "Zydis")
|
||||
|
||||
if (BUILD_C_BINDINGS)
|
||||
add_executable("SimpleDemo_C" "Examples/C/SimpleDemo/SimpleDemo.c")
|
||||
|
|
|
@ -154,7 +154,7 @@ int main()
|
|||
puts("64 bit test ...\n\n");
|
||||
while (ZydisDecodeInstruction(decoder, &info))
|
||||
{
|
||||
printf("%016"PRIu64"X ", info.instrAddress);
|
||||
printf("%016"PRIX64" ", info.instrAddress);
|
||||
if (info.flags & ZYDIS_IF_ERROR_MASK)
|
||||
{
|
||||
printf("db %02X", info.data[0]);
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
/***************************************************************************************************
|
||||
|
||||
Zyan Disassembler Engine
|
||||
Version 1.0
|
||||
|
||||
Remarks : Freeware, Copyright must be included
|
||||
|
||||
Original Author : Florian Bernd
|
||||
Modifications : Joel Höner
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <Zydis.hpp>
|
||||
|
||||
class ZydisStdinInput : public Zydis::BaseInput
|
||||
{
|
||||
private:
|
||||
std::vector<uint8_t> m_buffer;
|
||||
uint32_t m_position = 0;
|
||||
uint64_t m_globalPosition = 0;
|
||||
private:
|
||||
void gatherInput();
|
||||
protected:
|
||||
uint8_t internalInputPeek() override;
|
||||
uint8_t internalInputNext() override;
|
||||
public:
|
||||
bool isEndOfInput() const override;
|
||||
uint64_t getPosition() const override;
|
||||
bool setPosition(uint64_t position) override;
|
||||
};
|
||||
|
||||
void ZydisStdinInput::gatherInput()
|
||||
{
|
||||
if (m_position != m_buffer.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
std::vector<uint8_t> buffer;
|
||||
bool valid;
|
||||
do
|
||||
{
|
||||
valid = true;
|
||||
buffer.clear();
|
||||
std::string input;
|
||||
std::getline(std::cin, input);
|
||||
if (input.empty())
|
||||
{
|
||||
valid = false;
|
||||
continue;
|
||||
}
|
||||
std::istringstream ss(input);
|
||||
uint32_t x;
|
||||
do
|
||||
{
|
||||
ss >> std::hex >> x;
|
||||
if (ss.fail())
|
||||
{
|
||||
std::cout << std::endl << "# Error: Invalid hex input." << std::endl << std::endl;
|
||||
ss.ignore();
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
if (buffer.size() == buffer.capacity())
|
||||
{
|
||||
buffer.reserve(buffer.capacity() + 512);
|
||||
}
|
||||
if (x > 255)
|
||||
{
|
||||
std::cout << std::endl << "# Warning: 0x"
|
||||
<< std::hex << std::setw(8) << std::setfill('0') << std::uppercase << x
|
||||
<< " converted to uint8_t. Possible data loss." << std::endl << std::endl;
|
||||
}
|
||||
buffer.resize(buffer.size() + 1);
|
||||
buffer[buffer.size() - 1] = static_cast<uint8_t>(x);
|
||||
} while (!ss.eof());
|
||||
} while (!valid);
|
||||
m_buffer = buffer;
|
||||
m_position = 0;
|
||||
}
|
||||
|
||||
uint8_t ZydisStdinInput::internalInputPeek()
|
||||
{
|
||||
gatherInput();
|
||||
return m_buffer[m_position];
|
||||
}
|
||||
|
||||
uint8_t ZydisStdinInput::internalInputNext()
|
||||
{
|
||||
gatherInput();
|
||||
m_globalPosition++;
|
||||
return m_buffer[m_position++];
|
||||
}
|
||||
|
||||
bool ZydisStdinInput::isEndOfInput() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t ZydisStdinInput::getPosition() const
|
||||
{
|
||||
return m_globalPosition;
|
||||
}
|
||||
|
||||
bool ZydisStdinInput::setPosition(uint64_t position)
|
||||
{
|
||||
if (position > m_globalPosition)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int64_t delta = m_globalPosition - position;
|
||||
if (delta > m_position)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_position = m_position - static_cast<int32_t>(delta);
|
||||
m_globalPosition = position;
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
Zydis::InstructionInfo info;
|
||||
Zydis::InstructionDecoder decoder;
|
||||
Zydis::IntelInstructionFormatter formatter;
|
||||
ZydisStdinInput input;
|
||||
|
||||
decoder.setDisassemblerMode(Zydis::DisassemblerMode::M32BIT);
|
||||
decoder.setDataSource(&input);
|
||||
decoder.setInstructionPointer(0x00000000);
|
||||
|
||||
while (decoder.decodeInstruction(info))
|
||||
{
|
||||
std::cout << std::hex << std::setw(8) << std::setfill('0') << std::uppercase
|
||||
<< info.instrAddress << " ";
|
||||
if (info.flags & Zydis::IF_ERROR_MASK)
|
||||
{
|
||||
std::cout << "db " << std::setw(2) << static_cast<int>(info.data[0]) << std::endl;
|
||||
} else
|
||||
{
|
||||
std::cout << formatter.formatInstruction(info) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -78,7 +78,7 @@ int main()
|
|||
<< info.instrAddress << " ";
|
||||
if (info.flags & Zydis::IF_ERROR_MASK)
|
||||
{
|
||||
std::cout << "db " << std::setw(2) << info.data[0];
|
||||
std::cout << "db " << std::setw(2) << static_cast<int>(info.data[0]) << std::endl;
|
||||
} else
|
||||
{
|
||||
std::cout << formatter.formatInstruction(info) << std::endl;
|
||||
|
@ -97,7 +97,7 @@ int main()
|
|||
<< info.instrAddress << " ";
|
||||
if (info.flags & Zydis::IF_ERROR_MASK)
|
||||
{
|
||||
std::cout << "db " << std::setw(2) << info.data[0];
|
||||
std::cout << "db " << std::setw(2) << static_cast<int>(info.data[0]) << std::endl;
|
||||
} else
|
||||
{
|
||||
std::cout << formatter.formatInstruction(info) << std::endl;
|
||||
|
|
17
README.md
17
README.md
|
@ -1,5 +1,5 @@
|
|||
Zyan Disassembler Engine (Zydis)
|
||||
==================================
|
||||
Zyan Disassembler Engine (Zydis) [![Build Status](https://travis-ci.org/zyantific/zyan-disassembler-engine.svg?branch=master)](https://travis-ci.org/zyantific/zyan-disassembler-engine)
|
||||
================================
|
||||
|
||||
Fast and lightweight x86/x86-64 disassembler library.
|
||||
|
||||
|
@ -20,7 +20,7 @@ Fast and lightweight x86/x86-64 disassembler library.
|
|||
|
||||
The following example program uses Zydis to disassemble a given memory buffer and prints the output to the console.
|
||||
|
||||
```C++
|
||||
```c++
|
||||
#include <tchar.h>
|
||||
#include <iostream>
|
||||
#include <stdint.h>
|
||||
|
@ -35,7 +35,7 @@ int _tmain(int argc, _TCHAR* argv[])
|
|||
Zydis::MemoryInput input(&data[0], sizeof(data));
|
||||
Zydis::InstructionInfo info;
|
||||
Zydis::InstructionDecoder decoder;
|
||||
decoder.setDisassemblerMode(Zydis::ZydisMode::M32BIT);
|
||||
decoder.setDisassemblerMode(Zydis::DisassemblerMode::M32BIT);
|
||||
decoder.setDataSource(&input);
|
||||
decoder.setInstructionPointer(0);
|
||||
Zydis::IntelInstructionFormatter formatter;
|
||||
|
@ -47,8 +47,13 @@ int _tmain(int argc, _TCHAR* argv[])
|
|||
```
|
||||
|
||||
## Compilation ##
|
||||
|
||||
|
||||
Zydis builds cleanly on most platforms without any external dependencies. You can use CMake to generate project files for your favorite C++14 compiler.
|
||||
|
||||
|
||||
## Documentation ##
|
||||
|
||||
[The HTML Doxygen documentation](https://www.zyantific.com/doc/zydis/index.html) is automatically built from master every 12 hours.
|
||||
|
||||
## License ##
|
||||
|
||||
Zyan Disassembler Engine is licensed under the MIT License. Dependencies are under their respective licenses.
|
||||
|
|
Binary file not shown.
|
@ -28,12 +28,73 @@
|
|||
|
||||
***************************************************************************************************/
|
||||
|
||||
#ifndef _ZYDIS_DISASSEMBLER_HPP_
|
||||
#define _ZYDIS_DISASSEMBLER_HPP_
|
||||
/**
|
||||
* @file
|
||||
* @brief C++ API include file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @mainpage Zyan Disassembler Engine (Zydis)
|
||||
*
|
||||
* Zydis is a fast and lightweight x86/x86-64 disassembler library.
|
||||
*
|
||||
* @section Features
|
||||
* - Supports all x86 and x86-64 (AMD64) General purpose and System instructions.
|
||||
* - Supported ISA extensions:
|
||||
* - MMX, FPU (x87), AMD 3DNow
|
||||
* - SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AES,
|
||||
* - AMD-V, INTEL-VMX, SMX
|
||||
* - Optimized for high performance
|
||||
* - Very small overhead compared to other common disassembler libraries (about 60KiB)
|
||||
* - Abstract formatter and symbol-resolver classes for custom syntax implementations.
|
||||
* - Intel syntax is implemented by default
|
||||
* - Complete doxygen documentation
|
||||
*
|
||||
* @section Quick Example
|
||||
* The following example program uses Zydis to disassemble a given memory buffer and prints the
|
||||
* output to the console.
|
||||
*
|
||||
* @code
|
||||
* #include <tchar.h>
|
||||
* #include <iostream>
|
||||
* #include <stdint.h>
|
||||
* #include "Zydis.hpp"
|
||||
*
|
||||
* int _tmain(int argc, _TCHAR* argv[])
|
||||
* {
|
||||
* uint8_t data[] =
|
||||
* {
|
||||
* 0x90, 0xE9, 0x00, 0x00, 0x00, 0x00, 0xC3
|
||||
* };
|
||||
* Zydis::MemoryInput input(&data[0], sizeof(data));
|
||||
* Zydis::InstructionInfo info;
|
||||
* Zydis::InstructionDecoder decoder;
|
||||
* decoder.setDisassemblerMode(Zydis::DisassemblerMode::M32BIT);
|
||||
* decoder.setDataSource(&input);
|
||||
* decoder.setInstructionPointer(0);
|
||||
* Zydis::IntelInstructionFormatter formatter;
|
||||
* while (decoder.decodeInstruction(info))
|
||||
* {
|
||||
* std::cout << formatter.formatInstruction(info) << std::endl;
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @section Compilation
|
||||
* Zydis builds cleanly on most platforms without any external dependencies. You can use CMake
|
||||
* to generate project files for your favorite C++14 compiler.
|
||||
*
|
||||
* @section License
|
||||
* Zyan Disassembler Engine is licensed under the MIT License. Dependencies are under their
|
||||
* respective licenses.
|
||||
*/
|
||||
|
||||
#ifndef _ZYDIS_HPP_
|
||||
#define _ZYDIS_HPP_
|
||||
|
||||
#include "ZydisInstructionDecoder.hpp"
|
||||
#include "ZydisInstructionFormatter.hpp"
|
||||
#include "ZydisSymbolResolver.hpp"
|
||||
#include "ZydisUtils.hpp"
|
||||
|
||||
#endif /*_ZYDIS_DISASSEMBLER_HPP_ */
|
||||
#endif /*_ZYDIS_HPP_ */
|
|
@ -85,6 +85,7 @@ private:
|
|||
using FullClassT = ZydisClassEx<ZydisClassT>;
|
||||
public:
|
||||
uint32_t type;
|
||||
uint32_t align;
|
||||
std::conditional_t<std::is_abstract<ZydisClassT>::value, char, ZydisClassT> instance;
|
||||
public:
|
||||
/**
|
||||
|
@ -99,6 +100,7 @@ public:
|
|||
typename... InstanceCtorArgsT>
|
||||
ZydisClassEx(uint32_t classType, InstanceCtorArgsT... args)
|
||||
: type(classType)
|
||||
, align(0)
|
||||
, instance(args...) { };
|
||||
public:
|
||||
/**
|
||||
|
@ -126,7 +128,9 @@ public:
|
|||
static FullClassT* fromInstance(ZydisClassT* instance)
|
||||
{
|
||||
return reinterpret_cast<FullClassT*>(
|
||||
reinterpret_cast<uintptr_t>(instance) - sizeof(std::declval<FullClassT>().type));
|
||||
reinterpret_cast<uintptr_t>(instance)
|
||||
- sizeof(std::declval<FullClassT>().type)
|
||||
- sizeof(std::declval<FullClassT>().align));
|
||||
}
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
|
@ -28,11 +28,14 @@
|
|||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief C API for Zydis.
|
||||
*/
|
||||
|
||||
#ifndef _ZYDIS_API_H_
|
||||
#define _ZYDIS_API_H_
|
||||
|
||||
#define Zydis_EXPORTS
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
|
|
@ -61,7 +61,7 @@ bool InstructionDecoder::decodeRegisterOperand(InstructionInfo& info,
|
|||
break;
|
||||
case 8:
|
||||
// TODO: Only REX? Or VEX too?
|
||||
if (m_disassemblerMode == DisassemblerMode::M64BIT&& (info.flags& IF_PREFIX_REX))
|
||||
if (m_disassemblerMode == DisassemblerMode::M64BIT && (info.flags & IF_PREFIX_REX))
|
||||
{
|
||||
if (registerId >= 4)
|
||||
{
|
||||
|
@ -88,7 +88,7 @@ bool InstructionDecoder::decodeRegisterOperand(InstructionInfo& info,
|
|||
break;
|
||||
case RegisterClass::MMX:
|
||||
reg = static_cast<Register>(
|
||||
static_cast<uint16_t>(Register::MM0) + (registerId& 0x07));
|
||||
static_cast<uint16_t>(Register::MM0) + (registerId & 0x07));
|
||||
break;
|
||||
case RegisterClass::CONTROL:
|
||||
reg = static_cast<Register>(static_cast<uint16_t>(Register::CR0) + registerId);
|
||||
|
@ -97,13 +97,13 @@ bool InstructionDecoder::decodeRegisterOperand(InstructionInfo& info,
|
|||
reg = static_cast<Register>(static_cast<uint16_t>(Register::DR0) + registerId);
|
||||
break;
|
||||
case RegisterClass::SEGMENT:
|
||||
if ((registerId& 7) > 5)
|
||||
if ((registerId & 7) > 5)
|
||||
{
|
||||
info.flags |= IF_ERROR_OPERAND;
|
||||
return false;
|
||||
}
|
||||
reg = static_cast<Register>(
|
||||
static_cast<uint16_t>(Register::ES) + (registerId& 0x07));
|
||||
static_cast<uint16_t>(Register::ES) + (registerId & 0x07));
|
||||
break;
|
||||
case RegisterClass::XMM:
|
||||
reg = static_cast<Register>(registerId + static_cast<uint16_t>(
|
||||
|
@ -125,7 +125,7 @@ bool InstructionDecoder::decodeRegisterMemoryOperand(InstructionInfo& info,
|
|||
{
|
||||
return false;
|
||||
}
|
||||
assert(info.flags& IF_MODRM);
|
||||
assert(info.flags & IF_MODRM);
|
||||
// Decode register operand
|
||||
if (info.modrm_mod == 3)
|
||||
{
|
||||
|
@ -147,10 +147,10 @@ bool InstructionDecoder::decodeRegisterMemoryOperand(InstructionInfo& info,
|
|||
Register::SI, Register::DI, Register::SI, Register::DI,
|
||||
Register::NONE, Register::NONE, Register::NONE,
|
||||
Register::NONE };
|
||||
operand.base = static_cast<Register>(bases[info.modrm_rm_ext& 0x07]);
|
||||
operand.index = static_cast<Register>(indices[info.modrm_rm_ext& 0x07]);
|
||||
operand.base = static_cast<Register>(bases[info.modrm_rm_ext & 0x07]);
|
||||
operand.index = static_cast<Register>(indices[info.modrm_rm_ext & 0x07]);
|
||||
operand.scale = 0;
|
||||
if (info.modrm_mod == 0&& info.modrm_rm_ext == 6) {
|
||||
if (info.modrm_mod == 0 && info.modrm_rm_ext == 6) {
|
||||
offset = 16;
|
||||
operand.base = Register::NONE;
|
||||
} else if (info.modrm_mod == 1) {
|
||||
|
@ -181,7 +181,7 @@ bool InstructionDecoder::decodeRegisterMemoryOperand(InstructionInfo& info,
|
|||
default:
|
||||
assert(0);
|
||||
}
|
||||
if ((info.modrm_rm_ext& 0x07) == 4)
|
||||
if ((info.modrm_rm_ext & 0x07) == 4)
|
||||
{
|
||||
if (!decodeSIB(info))
|
||||
{
|
||||
|
@ -193,7 +193,7 @@ bool InstructionDecoder::decodeRegisterMemoryOperand(InstructionInfo& info,
|
|||
operand.index =
|
||||
static_cast<Register>(static_cast<uint16_t>(Register::EAX) +
|
||||
info.sib_index_ext);
|
||||
operand.scale = (1 << info.sib_scale)& ~1;
|
||||
operand.scale = (1 << info.sib_scale) & ~1;
|
||||
if (operand.index == Register::ESP)
|
||||
{
|
||||
operand.index = Register::NONE;
|
||||
|
@ -225,7 +225,7 @@ bool InstructionDecoder::decodeRegisterMemoryOperand(InstructionInfo& info,
|
|||
switch (info.modrm_mod)
|
||||
{
|
||||
case 0:
|
||||
if ((info.modrm_rm_ext& 0x07) == 5)
|
||||
if ((info.modrm_rm_ext & 0x07) == 5)
|
||||
{
|
||||
info.flags |= IF_RELATIVE;
|
||||
operand.base = Register::RIP;
|
||||
|
@ -241,7 +241,7 @@ bool InstructionDecoder::decodeRegisterMemoryOperand(InstructionInfo& info,
|
|||
default:
|
||||
assert(0);
|
||||
}
|
||||
if ((info.modrm_rm_ext& 0x07) == 4)
|
||||
if ((info.modrm_rm_ext & 0x07) == 4)
|
||||
{
|
||||
if (!decodeSIB(info))
|
||||
{
|
||||
|
@ -259,7 +259,7 @@ bool InstructionDecoder::decodeRegisterMemoryOperand(InstructionInfo& info,
|
|||
operand.scale = 0;
|
||||
} else
|
||||
{
|
||||
operand.scale = (1 << info.sib_scale)& ~1;
|
||||
operand.scale = (1 << info.sib_scale) & ~1;
|
||||
}
|
||||
if ((operand.base == Register::RBP) || (operand.base == Register::R13))
|
||||
{
|
||||
|
@ -318,7 +318,7 @@ bool InstructionDecoder::decodeImmediate(InstructionInfo& info, OperandInfo& ope
|
|||
// TODO: Maybe return false instead of assert
|
||||
assert(0);
|
||||
}
|
||||
if (!operand.lval.uqword&& (info.flags& IF_ERROR_MASK))
|
||||
if (!operand.lval.uqword && (info.flags & IF_ERROR_MASK))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -350,7 +350,7 @@ bool InstructionDecoder::decodeDisplacement(InstructionInfo& info,
|
|||
// TODO: Maybe return false instead of assert
|
||||
assert(0);
|
||||
}
|
||||
if (!operand.lval.uqword&& (info.flags& IF_ERROR_MASK))
|
||||
if (!operand.lval.uqword && (info.flags & IF_ERROR_MASK))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -359,17 +359,17 @@ bool InstructionDecoder::decodeDisplacement(InstructionInfo& info,
|
|||
|
||||
bool InstructionDecoder::decodeModrm(InstructionInfo& info)
|
||||
{
|
||||
if (!(info.flags& IF_MODRM))
|
||||
if (!(info.flags & IF_MODRM))
|
||||
{
|
||||
info.modrm = inputNext(info);
|
||||
if (!info.modrm&& (info.flags& IF_ERROR_MASK))
|
||||
if (!info.modrm && (info.flags & IF_ERROR_MASK))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
info.flags |= IF_MODRM;
|
||||
info.modrm_mod = (info.modrm >> 6)& 0x03;
|
||||
info.modrm_reg = (info.modrm >> 3)& 0x07;
|
||||
info.modrm_rm = (info.modrm >> 0)& 0x07;
|
||||
info.modrm_mod = (info.modrm >> 6) & 0x03;
|
||||
info.modrm_reg = (info.modrm >> 3) & 0x07;
|
||||
info.modrm_rm = (info.modrm >> 0) & 0x07;
|
||||
}
|
||||
// The @c decodeModrm method might get called multiple times during the opcode- and the
|
||||
// operand decoding, but the effective REX/VEX fields are not initialized before the end of
|
||||
|
@ -382,19 +382,19 @@ bool InstructionDecoder::decodeModrm(InstructionInfo& info)
|
|||
|
||||
bool InstructionDecoder::decodeSIB(InstructionInfo& info)
|
||||
{
|
||||
assert(info.flags& IF_MODRM);
|
||||
assert((info.modrm_rm& 0x7) == 4);
|
||||
if (!(info.flags& IF_SIB))
|
||||
assert(info.flags & IF_MODRM);
|
||||
assert((info.modrm_rm & 0x7) == 4);
|
||||
if (!(info.flags & IF_SIB))
|
||||
{
|
||||
info.sib = inputNext(info);
|
||||
if (!info.sib&& (info.flags& IF_ERROR_MASK))
|
||||
if (!info.sib && (info.flags & IF_ERROR_MASK))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
info.flags |= IF_SIB;
|
||||
info.sib_scale = (info.sib >> 6)& 0x03;
|
||||
info.sib_index = (info.sib >> 3)& 0x07;
|
||||
info.sib_base = (info.sib >> 0)& 0x07;
|
||||
info.sib_scale = (info.sib >> 6) & 0x03;
|
||||
info.sib_index = (info.sib >> 3) & 0x07;
|
||||
info.sib_base = (info.sib >> 0) & 0x07;
|
||||
// The @c decodeSib method is only called during the operand decoding, so updating the
|
||||
// extended values at this point should be safe.
|
||||
info.sib_index_ext = (info.eff_rexvex_x << 3) | info.sib_index;
|
||||
|
@ -405,45 +405,45 @@ bool InstructionDecoder::decodeSIB(InstructionInfo& info)
|
|||
|
||||
bool InstructionDecoder::decodeVex(InstructionInfo& info)
|
||||
{
|
||||
if (!(info.flags& IF_PREFIX_VEX))
|
||||
if (!(info.flags & IF_PREFIX_VEX))
|
||||
{
|
||||
info.vex_op = inputCurrent();
|
||||
switch (info.vex_op)
|
||||
{
|
||||
case 0xC4:
|
||||
info.vex_b1 = inputNext(info);
|
||||
if (!info.vex_b1 || (info.flags& IF_ERROR_MASK))
|
||||
if (!info.vex_b1 || (info.flags & IF_ERROR_MASK))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
info.vex_b2 = inputNext(info);
|
||||
if (!info.vex_b2 || (info.flags& IF_ERROR_MASK))
|
||||
if (!info.vex_b2 || (info.flags & IF_ERROR_MASK))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
info.vex_r = (info.vex_b1 >> 7)& 0x01;
|
||||
info.vex_x = (info.vex_b1 >> 6)& 0x01;
|
||||
info.vex_b = (info.vex_b1 >> 5)& 0x01;
|
||||
info.vex_m_mmmm = (info.vex_b1 >> 0)& 0x1F;
|
||||
info.vex_w = (info.vex_b2 >> 7)& 0x01;
|
||||
info.vex_vvvv = (info.vex_b2 >> 3)& 0x0F;
|
||||
info.vex_l = (info.vex_b2 >> 2)& 0x01;
|
||||
info.vex_pp = (info.vex_b2 >> 0)& 0x03;
|
||||
info.vex_r = (info.vex_b1 >> 7) & 0x01;
|
||||
info.vex_x = (info.vex_b1 >> 6) & 0x01;
|
||||
info.vex_b = (info.vex_b1 >> 5) & 0x01;
|
||||
info.vex_m_mmmm = (info.vex_b1 >> 0) & 0x1F;
|
||||
info.vex_w = (info.vex_b2 >> 7) & 0x01;
|
||||
info.vex_vvvv = (info.vex_b2 >> 3) & 0x0F;
|
||||
info.vex_l = (info.vex_b2 >> 2) & 0x01;
|
||||
info.vex_pp = (info.vex_b2 >> 0) & 0x03;
|
||||
break;
|
||||
case 0xC5:
|
||||
info.vex_b1 = inputNext(info);
|
||||
if (!info.vex_b1 || (info.flags& IF_ERROR_MASK))
|
||||
if (!info.vex_b1 || (info.flags & IF_ERROR_MASK))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
info.vex_r = (info.vex_b1 >> 7)& 0x01;
|
||||
info.vex_r = (info.vex_b1 >> 7) & 0x01;
|
||||
info.vex_x = 1;
|
||||
info.vex_b = 1;
|
||||
info.vex_m_mmmm = 1;
|
||||
info.vex_w = 0;
|
||||
info.vex_vvvv = (info.vex_b1 >> 3)& 0x0F;
|
||||
info.vex_l = (info.vex_b1 >> 2)& 0x01;
|
||||
info.vex_pp = (info.vex_b1 >> 0)& 0x03;
|
||||
info.vex_vvvv = (info.vex_b1 >> 3) & 0x0F;
|
||||
info.vex_l = (info.vex_b1 >> 2) & 0x01;
|
||||
info.vex_pp = (info.vex_b1 >> 0) & 0x03;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
|
@ -513,19 +513,19 @@ bool InstructionDecoder::decodeOperands(InstructionInfo& info)
|
|||
info.operand[i].access_mode = OperandAccessMode::READ;
|
||||
if (i == 0)
|
||||
{
|
||||
if (info.instrDefinition->flags& IDF_OPERAND1_WRITE)
|
||||
if (info.instrDefinition->flags & IDF_OPERAND1_WRITE)
|
||||
{
|
||||
info.operand[0].access_mode = OperandAccessMode::WRITE;
|
||||
} else if (info.instrDefinition->flags& IDF_OPERAND1_READWRITE)
|
||||
} else if (info.instrDefinition->flags & IDF_OPERAND1_READWRITE)
|
||||
{
|
||||
info.operand[0].access_mode = OperandAccessMode::READWRITE;
|
||||
}
|
||||
} else if (i == 1)
|
||||
{
|
||||
if (info.instrDefinition->flags& IDF_OPERAND2_WRITE)
|
||||
if (info.instrDefinition->flags & IDF_OPERAND2_WRITE)
|
||||
{
|
||||
info.operand[1].access_mode = OperandAccessMode::WRITE;
|
||||
} else if (info.instrDefinition->flags& IDF_OPERAND2_READWRITE)
|
||||
} else if (info.instrDefinition->flags & IDF_OPERAND2_READWRITE)
|
||||
{
|
||||
info.operand[1].access_mode = OperandAccessMode::READWRITE;
|
||||
}
|
||||
|
@ -556,7 +556,7 @@ bool InstructionDecoder::decodeOperand(InstructionInfo& info, OperandInfo& opera
|
|||
operand.lval.ptr.off = inputNext<uint32_t>(info);
|
||||
operand.lval.ptr.seg = inputNext<uint16_t>(info);
|
||||
}
|
||||
if ((!operand.lval.ptr.off || !operand.lval.ptr.seg)&& (info.flags& IF_ERROR_MASK))
|
||||
if ((!operand.lval.ptr.off || !operand.lval.ptr.seg) && (info.flags & IF_ERROR_MASK))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -596,7 +596,7 @@ bool InstructionDecoder::decodeOperand(InstructionInfo& info, OperandInfo& opera
|
|||
info.modrm_reg_ext, operandSize);
|
||||
case DefinedOperandType::H:
|
||||
assert(info.vex_op != 0);
|
||||
return decodeRegisterOperand(info, operand, RegisterClass::XMM, (0xF& ~info.vex_vvvv),
|
||||
return decodeRegisterOperand(info, operand, RegisterClass::XMM, (0xF & ~info.vex_vvvv),
|
||||
operandSize);
|
||||
case DefinedOperandType::sI:
|
||||
operand.signed_lval = true;
|
||||
|
@ -619,12 +619,12 @@ bool InstructionDecoder::decodeOperand(InstructionInfo& info, OperandInfo& opera
|
|||
{
|
||||
assert(info.vex_op != 0);
|
||||
uint8_t imm = inputNext(info);
|
||||
if (!imm&& (info.flags& IF_ERROR_MASK))
|
||||
if (!imm && (info.flags & IF_ERROR_MASK))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
uint8_t mask = (m_disassemblerMode == DisassemblerMode::M64BIT) ? 0xF : 0x7;
|
||||
return decodeRegisterOperand(info, operand, RegisterClass::XMM, mask& (imm >> 4),
|
||||
return decodeRegisterOperand(info, operand, RegisterClass::XMM, mask & (imm >> 4),
|
||||
operandSize);
|
||||
}
|
||||
case DefinedOperandType::MR:
|
||||
|
@ -729,7 +729,7 @@ bool InstructionDecoder::decodeOperand(InstructionInfo& info, OperandInfo& opera
|
|||
case DefinedOperandType::GS:
|
||||
if (m_disassemblerMode == DisassemblerMode::M64BIT)
|
||||
{
|
||||
if ((operandType != DefinedOperandType::FS)&&
|
||||
if ((operandType != DefinedOperandType::FS) &&
|
||||
(operandType != DefinedOperandType::GS))
|
||||
{
|
||||
info.flags |= IF_ERROR_OPERAND;
|
||||
|
@ -768,25 +768,25 @@ void InstructionDecoder::resolveOperandAndAddressMode(InstructionInfo& info) con
|
|||
switch (m_disassemblerMode)
|
||||
{
|
||||
case DisassemblerMode::M16BIT:
|
||||
info.operand_mode = (info.flags& IF_PREFIX_OPERAND_SIZE) ? 32 : 16;
|
||||
info.address_mode = (info.flags& IF_PREFIX_ADDRESS_SIZE) ? 32 : 16;
|
||||
info.operand_mode = (info.flags & IF_PREFIX_OPERAND_SIZE) ? 32 : 16;
|
||||
info.address_mode = (info.flags & IF_PREFIX_ADDRESS_SIZE) ? 32 : 16;
|
||||
break;
|
||||
case DisassemblerMode::M32BIT:
|
||||
info.operand_mode = (info.flags& IF_PREFIX_OPERAND_SIZE) ? 16 : 32;
|
||||
info.address_mode = (info.flags& IF_PREFIX_ADDRESS_SIZE) ? 16 : 32;
|
||||
info.operand_mode = (info.flags & IF_PREFIX_OPERAND_SIZE) ? 16 : 32;
|
||||
info.address_mode = (info.flags & IF_PREFIX_ADDRESS_SIZE) ? 16 : 32;
|
||||
break;
|
||||
case DisassemblerMode::M64BIT:
|
||||
if (info.eff_rexvex_w)
|
||||
{
|
||||
info.operand_mode = 64;
|
||||
} else if ((info.flags& IF_PREFIX_OPERAND_SIZE))
|
||||
} else if ((info.flags & IF_PREFIX_OPERAND_SIZE))
|
||||
{
|
||||
info.operand_mode = 16;
|
||||
} else
|
||||
{
|
||||
info.operand_mode = (info.instrDefinition->flags& IDF_DEFAULT_64) ? 64 : 32;
|
||||
info.operand_mode = (info.instrDefinition->flags & IDF_DEFAULT_64) ? 64 : 32;
|
||||
}
|
||||
info.address_mode = (info.flags& IF_PREFIX_ADDRESS_SIZE) ? 32 : 64;
|
||||
info.address_mode = (info.flags & IF_PREFIX_ADDRESS_SIZE) ? 32 : 64;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
|
@ -797,26 +797,26 @@ void InstructionDecoder::calculateEffectiveRexVexValues(InstructionInfo& info) c
|
|||
{
|
||||
assert(info.instrDefinition);
|
||||
uint8_t rex = info.rex;
|
||||
if (info.flags& IF_PREFIX_VEX)
|
||||
if (info.flags & IF_PREFIX_VEX)
|
||||
{
|
||||
switch (info.vex_op)
|
||||
{
|
||||
case 0xC4:
|
||||
rex = ((~(info.vex_b1 >> 5)& 0x07) | ((info.vex_b2 >> 4)& 0x08));
|
||||
rex = ((~(info.vex_b1 >> 5) & 0x07) | ((info.vex_b2 >> 4) & 0x08));
|
||||
break;
|
||||
case 0xC5:
|
||||
rex = (~(info.vex_b1 >> 5))& 4;
|
||||
rex = (~(info.vex_b1 >> 5)) & 4;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
rex &= (info.instrDefinition->flags& 0x000F);
|
||||
info.eff_rexvex_w = (rex >> 3)& 0x01;
|
||||
info.eff_rexvex_r = (rex >> 2)& 0x01;
|
||||
info.eff_rexvex_x = (rex >> 1)& 0x01;
|
||||
info.eff_rexvex_b = (rex >> 0)& 0x01;
|
||||
info.eff_vex_l = info.vex_l&& (info.instrDefinition->flags& IDF_ACCEPTS_VEXL);
|
||||
rex &= (info.instrDefinition->flags & 0x000F);
|
||||
info.eff_rexvex_w = (rex >> 3) & 0x01;
|
||||
info.eff_rexvex_r = (rex >> 2) & 0x01;
|
||||
info.eff_rexvex_x = (rex >> 1) & 0x01;
|
||||
info.eff_rexvex_b = (rex >> 0) & 0x01;
|
||||
info.eff_vex_l = info.vex_l && (info.instrDefinition->flags & IDF_ACCEPTS_VEXL);
|
||||
}
|
||||
|
||||
bool InstructionDecoder::decodePrefixes(InstructionInfo& info)
|
||||
|
@ -870,8 +870,8 @@ bool InstructionDecoder::decodePrefixes(InstructionInfo& info)
|
|||
info.flags |= IF_PREFIX_ADDRESS_SIZE;
|
||||
break;
|
||||
default:
|
||||
if ((m_disassemblerMode == DisassemblerMode::M64BIT)&&
|
||||
(inputCurrent()& 0xF0) == 0x40)
|
||||
if ((m_disassemblerMode == DisassemblerMode::M64BIT) &&
|
||||
(inputCurrent() & 0xF0) == 0x40)
|
||||
{
|
||||
info.flags |= IF_PREFIX_REX;
|
||||
info.rex = inputCurrent();
|
||||
|
@ -884,7 +884,7 @@ bool InstructionDecoder::decodePrefixes(InstructionInfo& info)
|
|||
// Increase the input offset, if a prefix was found
|
||||
if (!done)
|
||||
{
|
||||
if (!inputNext(info)&& (info.flags& IF_ERROR_MASK))
|
||||
if (!inputNext(info) && (info.flags & IF_ERROR_MASK))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -892,12 +892,12 @@ bool InstructionDecoder::decodePrefixes(InstructionInfo& info)
|
|||
} while (!done);
|
||||
// TODO: Check for multiple prefixes of the same group
|
||||
// Parse REX Prefix
|
||||
if (info.flags& IF_PREFIX_REX)
|
||||
if (info.flags & IF_PREFIX_REX)
|
||||
{
|
||||
info.rex_w = (info.rex >> 3)& 0x01;
|
||||
info.rex_r = (info.rex >> 2)& 0x01;
|
||||
info.rex_x = (info.rex >> 1)& 0x01;
|
||||
info.rex_b = (info.rex >> 0)& 0x01;
|
||||
info.rex_w = (info.rex >> 3) & 0x01;
|
||||
info.rex_r = (info.rex >> 2) & 0x01;
|
||||
info.rex_x = (info.rex >> 1) & 0x01;
|
||||
info.rex_b = (info.rex >> 0) & 0x01;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -906,7 +906,7 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
|||
{
|
||||
using namespace Internal;
|
||||
// Read first opcode byte
|
||||
if (!inputNext(info)&& (info.flags& IF_ERROR_MASK))
|
||||
if (!inputNext(info) && (info.flags & IF_ERROR_MASK))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -934,8 +934,8 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
|||
const InstructionDefinition *instrDefinition =
|
||||
GetInstructionDefinition(node);
|
||||
// Check for invalid 64 bit instruction
|
||||
if ((m_disassemblerMode == DisassemblerMode::M64BIT)&&
|
||||
(instrDefinition->flags& IDF_INVALID_64))
|
||||
if ((m_disassemblerMode == DisassemblerMode::M64BIT) &&
|
||||
(instrDefinition->flags & IDF_INVALID_64))
|
||||
{
|
||||
info.flags |= IF_ERROR_INVALID_64;
|
||||
return false;
|
||||
|
@ -956,12 +956,12 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
|||
return true;
|
||||
case OpcodeTreeNodeType::TABLE:
|
||||
// Read next opcode byte
|
||||
if (!inputNext(info)&& (info.flags& IF_ERROR_MASK))
|
||||
if (!inputNext(info) && (info.flags & IF_ERROR_MASK))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Update instruction info
|
||||
assert((info.opcode_length > 0)&& (info.opcode_length < 3));
|
||||
assert((info.opcode_length > 0) && (info.opcode_length < 3));
|
||||
info.opcode[info.opcode_length] = inputCurrent();
|
||||
info.opcode_length++;
|
||||
// Set child node index for next iteration
|
||||
|
@ -993,13 +993,13 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
|||
break;
|
||||
case OpcodeTreeNodeType::MANDATORY:
|
||||
// Check if there are any prefixes present
|
||||
if (info.flags& IF_PREFIX_REP)
|
||||
if (info.flags & IF_PREFIX_REP)
|
||||
{
|
||||
index = 1; // F2
|
||||
} else if (info.flags& IF_PREFIX_REPNE)
|
||||
} else if (info.flags & IF_PREFIX_REPNE)
|
||||
{
|
||||
index = 2; // F3
|
||||
} else if (info.flags& IF_PREFIX_OPERAND_SIZE)
|
||||
} else if (info.flags & IF_PREFIX_OPERAND_SIZE)
|
||||
{
|
||||
index = 3; // 66
|
||||
}
|
||||
|
@ -1007,7 +1007,7 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
|||
{
|
||||
index = 0;
|
||||
}
|
||||
if (index&& (GetOpcodeTreeChild(node, index) != 0))
|
||||
if (index && (GetOpcodeTreeChild(node, index) != 0))
|
||||
{
|
||||
// Remove REP and REPNE prefix
|
||||
info.flags &= ~IF_PREFIX_REP;
|
||||
|
@ -1032,13 +1032,13 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
|||
switch (m_disassemblerMode)
|
||||
{
|
||||
case DisassemblerMode::M16BIT:
|
||||
index = (info.flags& IF_PREFIX_ADDRESS_SIZE) ? 1 : 0;
|
||||
index = (info.flags & IF_PREFIX_ADDRESS_SIZE) ? 1 : 0;
|
||||
break;
|
||||
case DisassemblerMode::M32BIT:
|
||||
index = (info.flags& IF_PREFIX_ADDRESS_SIZE) ? 0 : 1;
|
||||
index = (info.flags & IF_PREFIX_ADDRESS_SIZE) ? 0 : 1;
|
||||
break;
|
||||
case DisassemblerMode::M64BIT:
|
||||
index = (info.flags& IF_PREFIX_ADDRESS_SIZE) ? 1 : 2;
|
||||
index = (info.flags & IF_PREFIX_ADDRESS_SIZE) ? 1 : 2;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
|
@ -1048,13 +1048,13 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
|||
switch (m_disassemblerMode)
|
||||
{
|
||||
case DisassemblerMode::M16BIT:
|
||||
index = (info.flags& IF_PREFIX_OPERAND_SIZE) ? 1 : 0;
|
||||
index = (info.flags & IF_PREFIX_OPERAND_SIZE) ? 1 : 0;
|
||||
break;
|
||||
case DisassemblerMode::M32BIT:
|
||||
index = (info.flags& IF_PREFIX_OPERAND_SIZE) ? 0 : 1;
|
||||
index = (info.flags & IF_PREFIX_OPERAND_SIZE) ? 0 : 1;
|
||||
break;
|
||||
case DisassemblerMode::M64BIT:
|
||||
index = (info.rex_w) ? 2 : ((info.flags& IF_PREFIX_OPERAND_SIZE) ? 0 : 1);
|
||||
index = (info.rex_w) ? 2 : ((info.flags & IF_PREFIX_OPERAND_SIZE) ? 0 : 1);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
|
@ -1100,7 +1100,7 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
|||
}
|
||||
// Read the actual 3dnow opcode
|
||||
info.opcode[2] = inputNext(info);
|
||||
if (!info.opcode[2]&& (info.flags& IF_ERROR_MASK))
|
||||
if (!info.opcode[2] && (info.flags & IF_ERROR_MASK))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1125,20 +1125,20 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
|||
}
|
||||
if (info.operand[0].type != OperandType::NONE)
|
||||
{
|
||||
if (info.instrDefinition->flags& IDF_OPERAND1_WRITE)
|
||||
if (info.instrDefinition->flags & IDF_OPERAND1_WRITE)
|
||||
{
|
||||
info.operand[0].access_mode = OperandAccessMode::WRITE;
|
||||
} else if (info.instrDefinition->flags& IDF_OPERAND1_READWRITE)
|
||||
} else if (info.instrDefinition->flags & IDF_OPERAND1_READWRITE)
|
||||
{
|
||||
info.operand[0].access_mode = OperandAccessMode::READWRITE;
|
||||
}
|
||||
}
|
||||
if (info.operand[1].type != OperandType::NONE)
|
||||
{
|
||||
if (info.instrDefinition->flags& IDF_OPERAND2_WRITE)
|
||||
if (info.instrDefinition->flags & IDF_OPERAND2_WRITE)
|
||||
{
|
||||
info.operand[1].access_mode = OperandAccessMode::WRITE;
|
||||
} else if (info.instrDefinition->flags& IDF_OPERAND2_READWRITE)
|
||||
} else if (info.instrDefinition->flags & IDF_OPERAND2_READWRITE)
|
||||
{
|
||||
info.operand[1].access_mode = OperandAccessMode::READWRITE;
|
||||
}
|
||||
|
@ -1148,7 +1148,7 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
|||
}
|
||||
case OpcodeTreeNodeType::VEX:
|
||||
if ((m_disassemblerMode == DisassemblerMode::M64BIT) ||
|
||||
(((inputCurrent() >> 6)& 0x03) == 0x03))
|
||||
(((inputCurrent() >> 6) & 0x03) == 0x03))
|
||||
{
|
||||
// Decode vex prefix
|
||||
if (!decodeVex(info))
|
||||
|
@ -1181,11 +1181,11 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
|||
}
|
||||
break;
|
||||
case OpcodeTreeNodeType::VEXW:
|
||||
assert(info.flags& IF_PREFIX_VEX);
|
||||
assert(info.flags & IF_PREFIX_VEX);
|
||||
index = info.vex_w;
|
||||
break;
|
||||
case OpcodeTreeNodeType::VEXL:
|
||||
assert(info.flags& IF_PREFIX_VEX);
|
||||
assert(info.flags & IF_PREFIX_VEX);
|
||||
index = info.vex_l;
|
||||
break;
|
||||
default:
|
||||
|
@ -1243,7 +1243,7 @@ bool InstructionDecoder::decodeInstruction(InstructionInfo& info)
|
|||
goto DecodeError;
|
||||
}
|
||||
// SWAPGS is only valid in 64 bit mode
|
||||
if ((info.mnemonic == InstructionMnemonic::SWAPGS)&&
|
||||
if ((info.mnemonic == InstructionMnemonic::SWAPGS) &&
|
||||
(m_disassemblerMode != DisassemblerMode::M64BIT))
|
||||
{
|
||||
info.flags &= IF_ERROR_INVALID;
|
||||
|
@ -1252,13 +1252,13 @@ bool InstructionDecoder::decodeInstruction(InstructionInfo& info)
|
|||
// Handle aliases
|
||||
if (info.mnemonic == InstructionMnemonic::XCHG)
|
||||
{
|
||||
if ((info.operand[0].type == OperandType::REGISTER&&
|
||||
info.operand[0].base == Register::AX&&
|
||||
info.operand[1].type == OperandType::REGISTER&&
|
||||
if ((info.operand[0].type == OperandType::REGISTER &&
|
||||
info.operand[0].base == Register::AX &&
|
||||
info.operand[1].type == OperandType::REGISTER &&
|
||||
info.operand[1].base == Register::AX) ||
|
||||
(info.operand[0].type == OperandType::REGISTER&&
|
||||
info.operand[0].base == Register::EAX&&
|
||||
info.operand[1].type == OperandType::REGISTER&&
|
||||
(info.operand[0].type == OperandType::REGISTER &&
|
||||
info.operand[0].base == Register::EAX &&
|
||||
info.operand[1].type == OperandType::REGISTER &&
|
||||
info.operand[1].base == Register::EAX))
|
||||
{
|
||||
info.mnemonic = InstructionMnemonic::NOP;
|
||||
|
@ -1268,7 +1268,7 @@ bool InstructionDecoder::decodeInstruction(InstructionInfo& info)
|
|||
info.operand[1].access_mode = OperandAccessMode::NA;
|
||||
}
|
||||
}
|
||||
if ((info.mnemonic == InstructionMnemonic::NOP)&& (info.flags& IF_PREFIX_REP))
|
||||
if ((info.mnemonic == InstructionMnemonic::NOP) && (info.flags & IF_PREFIX_REP))
|
||||
{
|
||||
info.mnemonic = InstructionMnemonic::PAUSE;
|
||||
info.flags &= ~IF_PREFIX_REP;
|
||||
|
@ -1282,7 +1282,7 @@ DecodeError:
|
|||
// Increment instruction pointer.
|
||||
m_instructionPointer += 1;
|
||||
// Backup all error flags, the instruction length and the instruction address
|
||||
uint32_t flags = info.flags& (IF_ERROR_MASK | 0x00000007);
|
||||
uint32_t flags = info.flags & (IF_ERROR_MASK | 0x00000007);
|
||||
uint8_t length = info.length;
|
||||
uint8_t firstByte = info.data[0];
|
||||
uint64_t instrAddress = info.instrAddress;
|
||||
|
@ -1303,7 +1303,7 @@ DecodeError:
|
|||
}
|
||||
// Return with error, if the end of the input source was reached while decoding the
|
||||
// invalid instruction
|
||||
if (info.flags& IF_ERROR_END_OF_INPUT)
|
||||
if (info.flags & IF_ERROR_END_OF_INPUT)
|
||||
{
|
||||
info.length = 0;
|
||||
return false;
|
||||
|
|
|
@ -28,6 +28,11 @@
|
|||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Instruction decoder classes.
|
||||
*/
|
||||
|
||||
#ifndef _ZYDIS_INSTRUCTIONDECODER_HPP_
|
||||
#define _ZYDIS_INSTRUCTIONDECODER_HPP_
|
||||
|
||||
|
@ -45,34 +50,10 @@ namespace Zydis
|
|||
*/
|
||||
class BaseInput
|
||||
{
|
||||
friend class InstructionDecoder;
|
||||
private:
|
||||
uint8_t m_currentInput;
|
||||
protected:
|
||||
/**
|
||||
* @brief Override this method in your custom data source implementations.
|
||||
* Reads the next byte from the data source. This method increases the current
|
||||
* input position by one.
|
||||
* @return The current input byte.
|
||||
*/
|
||||
virtual uint8_t internalInputPeek() = 0;
|
||||
/**
|
||||
* @brief Override this method in your custom data source implementations.
|
||||
* Reads the next byte from the data source. This method does NOT increase the
|
||||
* current input position.
|
||||
* @return The current input byte.
|
||||
*/
|
||||
virtual uint8_t internalInputNext() = 0;
|
||||
protected:
|
||||
/**
|
||||
* @brief Default constructor.
|
||||
*/
|
||||
BaseInput() { };
|
||||
public:
|
||||
/**
|
||||
* @brief Destructor.
|
||||
*/
|
||||
virtual ~BaseInput() { };
|
||||
public:
|
||||
private:
|
||||
/**
|
||||
* @brief Reads the next byte from the data source. This method does NOT increase the
|
||||
* current input position or the @c length field of the @c info parameter.
|
||||
|
@ -111,6 +92,31 @@ public:
|
|||
* @return The current input byte.
|
||||
*/
|
||||
uint8_t inputCurrent() const;
|
||||
protected:
|
||||
/**
|
||||
* @brief Override this method in your custom data source implementations.
|
||||
* Reads the next byte from the data source. This method increases the current
|
||||
* input position by one.
|
||||
* @return The current input byte.
|
||||
*/
|
||||
virtual uint8_t internalInputPeek() = 0;
|
||||
/**
|
||||
* @brief Override this method in your custom data source implementations.
|
||||
* Reads the next byte from the data source. This method does NOT increase the
|
||||
* current input position.
|
||||
* @return The current input byte.
|
||||
*/
|
||||
virtual uint8_t internalInputNext() = 0;
|
||||
protected:
|
||||
/**
|
||||
* @brief Default constructor.
|
||||
*/
|
||||
BaseInput() { };
|
||||
public:
|
||||
/**
|
||||
* @brief Destructor.
|
||||
*/
|
||||
virtual ~BaseInput() { };
|
||||
public:
|
||||
/**
|
||||
* @brief Override this method in your custom data source implementations.
|
||||
|
@ -175,7 +181,7 @@ inline T BaseInput::inputNext(InstructionInfo& info)
|
|||
for (unsigned i = 0; i < (sizeof(T) / sizeof(uint8_t)); ++i)
|
||||
{
|
||||
T b = inputNext(info);
|
||||
if (!b&& (info.flags& IF_ERROR_MASK))
|
||||
if (!b && (info.flags & IF_ERROR_MASK))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace Zydis
|
|||
|
||||
/* BaseInstructionFormatter ================================================================ */
|
||||
|
||||
const char *BaseInstructionFormatter::m_registerStrings[] =
|
||||
const char* BaseInstructionFormatter::m_registerStrings[] =
|
||||
{
|
||||
/* 8 bit general purpose registers */
|
||||
"al", "cl", "dl", "bl",
|
||||
|
@ -238,13 +238,13 @@ void BaseInstructionFormatter::outputAppendAddress(const InstructionInfo& info,
|
|||
}
|
||||
} else
|
||||
{
|
||||
if (info.flags& IF_DISASSEMBLER_MODE_16)
|
||||
if (info.flags & IF_DISASSEMBLER_MODE_16)
|
||||
{
|
||||
outputAppendFormatted("%.4X", address);
|
||||
} else if (info.flags& IF_DISASSEMBLER_MODE_32)
|
||||
} else if (info.flags & IF_DISASSEMBLER_MODE_32)
|
||||
{
|
||||
outputAppendFormatted("%.8lX", address);
|
||||
} else if (info.flags& IF_DISASSEMBLER_MODE_64)
|
||||
} else if (info.flags & IF_DISASSEMBLER_MODE_64)
|
||||
{
|
||||
outputAppendFormatted("%.16llX", address);
|
||||
} else
|
||||
|
@ -294,7 +294,7 @@ void BaseInstructionFormatter::outputAppendImmediate(const InstructionInfo& info
|
|||
}
|
||||
}
|
||||
uint64_t offset = 0;
|
||||
const char *name = nullptr;
|
||||
const char* name = nullptr;
|
||||
if (resolveSymbols)
|
||||
{
|
||||
name = resolveSymbol(info, value, offset);
|
||||
|
@ -317,7 +317,7 @@ void BaseInstructionFormatter::outputAppendImmediate(const InstructionInfo& info
|
|||
void BaseInstructionFormatter::outputAppendDisplacement(const OperandInfo& operand)
|
||||
{
|
||||
assert(operand.offset > 0);
|
||||
if ((operand.base == Register::NONE)&& (operand.index == Register::NONE))
|
||||
if ((operand.base == Register::NONE) && (operand.index == Register::NONE))
|
||||
{
|
||||
// Assume the displacement value is unsigned
|
||||
assert(operand.scale == 0);
|
||||
|
@ -409,7 +409,7 @@ void IntelInstructionFormatter::formatOperand(const InstructionInfo& info,
|
|||
outputAppend(registerToString(operand.base));
|
||||
break;
|
||||
case OperandType::MEMORY:
|
||||
if (info.flags& IF_PREFIX_SEGMENT)
|
||||
if (info.flags & IF_PREFIX_SEGMENT)
|
||||
{
|
||||
outputAppendFormatted("%s:", registerToString(info.segment));
|
||||
}
|
||||
|
@ -481,14 +481,14 @@ void IntelInstructionFormatter::formatOperand(const InstructionInfo& info,
|
|||
void IntelInstructionFormatter::internalFormatInstruction(const InstructionInfo& info)
|
||||
{
|
||||
// Append string prefixes
|
||||
if (info.flags& IF_PREFIX_LOCK)
|
||||
if (info.flags & IF_PREFIX_LOCK)
|
||||
{
|
||||
outputAppend("lock ");
|
||||
}
|
||||
if (info.flags& IF_PREFIX_REP)
|
||||
if (info.flags & IF_PREFIX_REP)
|
||||
{
|
||||
outputAppend("rep ");
|
||||
} else if (info.flags& IF_PREFIX_REPNE)
|
||||
} else if (info.flags & IF_PREFIX_REPNE)
|
||||
{
|
||||
outputAppend("repne ");
|
||||
}
|
||||
|
@ -507,7 +507,7 @@ void IntelInstructionFormatter::internalFormatInstruction(const InstructionInfo&
|
|||
(info.operand[0].size != info.operand[1].size))
|
||||
{
|
||||
cast = true;
|
||||
} else if (info.operand[1].type == OperandType::REGISTER&&
|
||||
} else if (info.operand[1].type == OperandType::REGISTER &&
|
||||
info.operand[1].base == Register::CL)
|
||||
{
|
||||
switch (info.mnemonic)
|
||||
|
@ -537,14 +537,14 @@ void IntelInstructionFormatter::internalFormatInstruction(const InstructionInfo&
|
|||
{
|
||||
outputAppend(", ");
|
||||
bool cast = false;
|
||||
if (info.operand[1].type == OperandType::MEMORY&&
|
||||
info.operand[0].size != info.operand[1].size&&
|
||||
if (info.operand[1].type == OperandType::MEMORY &&
|
||||
info.operand[0].size != info.operand[1].size &&
|
||||
((info.operand[0].type != OperandType::REGISTER) ||
|
||||
((info.operand[0].base != Register::ES)&&
|
||||
(info.operand[0].base != Register::CS)&&
|
||||
(info.operand[0].base != Register::SS)&&
|
||||
(info.operand[0].base != Register::DS)&&
|
||||
(info.operand[0].base != Register::FS)&&
|
||||
((info.operand[0].base != Register::ES) &&
|
||||
(info.operand[0].base != Register::CS) &&
|
||||
(info.operand[0].base != Register::SS) &&
|
||||
(info.operand[0].base != Register::DS) &&
|
||||
(info.operand[0].base != Register::FS) &&
|
||||
(info.operand[0].base != Register::GS))))
|
||||
{
|
||||
cast = true;
|
||||
|
@ -560,7 +560,7 @@ void IntelInstructionFormatter::internalFormatInstruction(const InstructionInfo&
|
|||
{
|
||||
outputAppend(", ");
|
||||
bool cast = false;
|
||||
if (info.operand[2].type == OperandType::MEMORY&&
|
||||
if (info.operand[2].type == OperandType::MEMORY &&
|
||||
(info.operand[2].size != info.operand[1].size))
|
||||
{
|
||||
cast = true;
|
||||
|
|
|
@ -28,6 +28,11 @@
|
|||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Instruction formatting classes.
|
||||
*/
|
||||
|
||||
#ifndef _ZYDIS_INSTRUCTIONFORMATTER_HPP_
|
||||
#define _ZYDIS_INSTRUCTIONFORMATTER_HPP_
|
||||
|
||||
|
|
|
@ -28,6 +28,11 @@
|
|||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief The opcode table definition, mostly internal stuff.
|
||||
*/
|
||||
|
||||
#ifndef _ZYDIS_OPCODETABLE_HPP_
|
||||
#define _ZYDIS_OPCODETABLE_HPP_
|
||||
|
||||
|
@ -1607,7 +1612,7 @@ extern const char* instrMnemonicStrings[];
|
|||
*/
|
||||
inline OpcodeTreeNodeType GetOpcodeNodeType(OpcodeTreeNode node)
|
||||
{
|
||||
return static_cast<OpcodeTreeNodeType>((node >> 12)& 0x0F);
|
||||
return static_cast<OpcodeTreeNodeType>((node >> 12) & 0x0F);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1617,7 +1622,7 @@ inline OpcodeTreeNodeType GetOpcodeNodeType(OpcodeTreeNode node)
|
|||
*/
|
||||
inline uint16_t GetOpcodeNodeValue(OpcodeTreeNode node)
|
||||
{
|
||||
return (node& 0x0FFF);
|
||||
return (node & 0x0FFF);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1698,7 +1703,7 @@ inline OpcodeTreeNode GetOpcodeTreeChild(OpcodeTreeNode parent, uint16_t index)
|
|||
inline const InstructionDefinition* GetInstructionDefinition(OpcodeTreeNode node)
|
||||
{
|
||||
assert(GetOpcodeNodeType(node) == OpcodeTreeNodeType::INSTRUCTION_DEFINITION);
|
||||
return& instrDefinitions[node& 0x0FFF];
|
||||
return& instrDefinitions[node & 0x0FFF];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1735,7 +1740,7 @@ inline uint16_t GetSimpleOperandSize(DefinedOperandSize operandSize)
|
|||
*/
|
||||
inline DefinedOperandSize GetComplexOperandMemSize(DefinedOperandSize operandSize)
|
||||
{
|
||||
return static_cast<DefinedOperandSize>(static_cast<uint8_t>(operandSize)& 0x0F);
|
||||
return static_cast<DefinedOperandSize>(static_cast<uint8_t>(operandSize) & 0x0F);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1745,7 +1750,7 @@ inline DefinedOperandSize GetComplexOperandMemSize(DefinedOperandSize operandSiz
|
|||
*/
|
||||
inline DefinedOperandSize GetComplexOperandRegSize(DefinedOperandSize operandSize)
|
||||
{
|
||||
return static_cast<DefinedOperandSize>((static_cast<uint8_t>(operandSize) >> 4)& 0x0F);
|
||||
return static_cast<DefinedOperandSize>((static_cast<uint8_t>(operandSize) >> 4) & 0x0F);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,6 +28,11 @@
|
|||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Classes for symbol resolving in the disassembly.
|
||||
*/
|
||||
|
||||
#ifndef _ZYDIS_SYMBOLRESOLVER_HPP_
|
||||
#define _ZYDIS_SYMBOLRESOLVER_HPP_
|
||||
|
||||
|
|
|
@ -37,33 +37,33 @@ namespace Zydis
|
|||
uint64_t CalcAbsoluteTarget(const InstructionInfo& info, const OperandInfo& operand)
|
||||
{
|
||||
assert((operand.type == OperandType::REL_IMMEDIATE) ||
|
||||
((operand.type == OperandType::MEMORY)&& (operand.base == Register::RIP)));
|
||||
((operand.type == OperandType::MEMORY) && (operand.base == Register::RIP)));
|
||||
|
||||
uint64_t truncMask = 0xFFFFFFFFFFFFFFFFull;
|
||||
if (!(info.flags& IF_DISASSEMBLER_MODE_64))
|
||||
if (!(info.flags & IF_DISASSEMBLER_MODE_64))
|
||||
{
|
||||
truncMask >>= (64 - info.operand_mode);
|
||||
}
|
||||
uint16_t size = operand.size;
|
||||
if ((operand.type == OperandType::MEMORY)&& (operand.base == Register::RIP))
|
||||
if ((operand.type == OperandType::MEMORY) && (operand.base == Register::RIP))
|
||||
{
|
||||
size = operand.offset;
|
||||
}
|
||||
switch (size)
|
||||
{
|
||||
case 8:
|
||||
return (info.instrPointer + operand.lval.sbyte)& truncMask;
|
||||
return (info.instrPointer + operand.lval.sbyte) & truncMask;
|
||||
case 16:
|
||||
{
|
||||
uint32_t delta = operand.lval.sword& truncMask;
|
||||
uint32_t delta = operand.lval.sword & truncMask;
|
||||
if ((info.instrPointer + delta) > 0xFFFF)
|
||||
{
|
||||
return (info.instrPointer& 0xF0000) + ((info.instrPointer + delta)& 0xFFFF);
|
||||
return (info.instrPointer& 0xF0000) + ((info.instrPointer + delta) & 0xFFFF);
|
||||
}
|
||||
return info.instrPointer + delta;
|
||||
}
|
||||
case 32:
|
||||
return (info.instrPointer + operand.lval.sdword)& truncMask;
|
||||
return (info.instrPointer + operand.lval.sdword) & truncMask;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,11 @@
|
|||
|
||||
***************************************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Utility functions.
|
||||
*/
|
||||
|
||||
#ifndef _ZYDIS_UTILS_HPP_
|
||||
#define _ZYDIS_UTILS_HPP_
|
||||
|
||||
|
|
Loading…
Reference in New Issue