mirror of https://github.com/x64dbg/zydis
Minor bugfixes and CustomDataSource demo
* fixed 64 bit compilation error * added VERSIONINFO resource * added CustomDataSource demo (disassembles hex input from the console)
This commit is contained in:
parent
a49d70e4a7
commit
335f6bd81e
|
@ -16,7 +16,7 @@ if (NOT CONFIGURED_ONCE)
|
||||||
set(compiler_specific "-Werror")
|
set(compiler_specific "-Werror")
|
||||||
set(compiler_specific_cxx "-std=c++14")
|
set(compiler_specific_cxx "-std=c++14")
|
||||||
elseif (MSVC)
|
elseif (MSVC)
|
||||||
set(compiler_specific "/WX /W4 /D_CRT_SECURE_NO_WARNINGS")
|
set(compiler_specific "/WX /W4 /D_CRT_SECURE_NO_WARNINGS /GR-")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${compiler_specific} ${compiler_specific_cxx}"
|
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
|
# 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.
|
# 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
|
set(manipulated_vars
|
||||||
CMAKE_CXX_FLAGS_DEBUG
|
CMAKE_CXX_FLAGS_DEBUG
|
||||||
CMAKE_CXX_FLAGS_MINSIZEREL
|
CMAKE_CXX_FLAGS_MINSIZEREL
|
||||||
|
@ -58,6 +58,11 @@ set(sources
|
||||||
"Zydis/ZydisSymbolResolver.cpp"
|
"Zydis/ZydisSymbolResolver.cpp"
|
||||||
"Zydis/ZydisUtils.cpp")
|
"Zydis/ZydisUtils.cpp")
|
||||||
|
|
||||||
|
if (BUILD_SHARED_LIBS AND WIN32)
|
||||||
|
set(sources ${sources}
|
||||||
|
"Zydis/Zydis.rc")
|
||||||
|
endif ()
|
||||||
|
|
||||||
if (BUILD_C_BINDINGS)
|
if (BUILD_C_BINDINGS)
|
||||||
set(headers ${headers}
|
set(headers ${headers}
|
||||||
"Zydis/ZydisAPI.h")
|
"Zydis/ZydisAPI.h")
|
||||||
|
@ -66,6 +71,7 @@ if (BUILD_C_BINDINGS)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
add_library("Zydis" ${headers} ${sources})
|
add_library("Zydis" ${headers} ${sources})
|
||||||
|
set_target_properties("Zydis" PROPERTIES COMPILE_DEFINITIONS "Zydis_EXPORTS")
|
||||||
generate_export_header(
|
generate_export_header(
|
||||||
"Zydis"
|
"Zydis"
|
||||||
BASE_NAME "ZYDIS"
|
BASE_NAME "ZYDIS"
|
||||||
|
@ -78,6 +84,8 @@ if (BUILD_EXAMPLES)
|
||||||
|
|
||||||
add_executable("SimpleDemo_CPP" "Examples/CPP/SimpleDemo/SimpleDemo.cpp")
|
add_executable("SimpleDemo_CPP" "Examples/CPP/SimpleDemo/SimpleDemo.cpp")
|
||||||
target_link_libraries("SimpleDemo_CPP" "Zydis")
|
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)
|
if (BUILD_C_BINDINGS)
|
||||||
add_executable("SimpleDemo_C" "Examples/C/SimpleDemo/SimpleDemo.c")
|
add_executable("SimpleDemo_C" "Examples/C/SimpleDemo/SimpleDemo.c")
|
||||||
|
|
|
@ -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 << " ";
|
<< info.instrAddress << " ";
|
||||||
if (info.flags & Zydis::IF_ERROR_MASK)
|
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
|
} else
|
||||||
{
|
{
|
||||||
std::cout << formatter.formatInstruction(info) << std::endl;
|
std::cout << formatter.formatInstruction(info) << std::endl;
|
||||||
|
@ -97,7 +97,7 @@ int main()
|
||||||
<< info.instrAddress << " ";
|
<< info.instrAddress << " ";
|
||||||
if (info.flags & Zydis::IF_ERROR_MASK)
|
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
|
} else
|
||||||
{
|
{
|
||||||
std::cout << formatter.formatInstruction(info) << std::endl;
|
std::cout << formatter.formatInstruction(info) << std::endl;
|
||||||
|
|
Binary file not shown.
|
@ -85,6 +85,7 @@ private:
|
||||||
using FullClassT = ZydisClassEx<ZydisClassT>;
|
using FullClassT = ZydisClassEx<ZydisClassT>;
|
||||||
public:
|
public:
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
|
uint32_t align;
|
||||||
std::conditional_t<std::is_abstract<ZydisClassT>::value, char, ZydisClassT> instance;
|
std::conditional_t<std::is_abstract<ZydisClassT>::value, char, ZydisClassT> instance;
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
@ -99,6 +100,7 @@ public:
|
||||||
typename... InstanceCtorArgsT>
|
typename... InstanceCtorArgsT>
|
||||||
ZydisClassEx(uint32_t classType, InstanceCtorArgsT... args)
|
ZydisClassEx(uint32_t classType, InstanceCtorArgsT... args)
|
||||||
: type(classType)
|
: type(classType)
|
||||||
|
, align(0)
|
||||||
, instance(args...) { };
|
, instance(args...) { };
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
@ -126,7 +128,9 @@ public:
|
||||||
static FullClassT* fromInstance(ZydisClassT* instance)
|
static FullClassT* fromInstance(ZydisClassT* instance)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<FullClassT*>(
|
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)
|
#pragma pack(pop)
|
||||||
|
|
|
@ -31,8 +31,6 @@
|
||||||
#ifndef _ZYDIS_API_H_
|
#ifndef _ZYDIS_API_H_
|
||||||
#define _ZYDIS_API_H_
|
#define _ZYDIS_API_H_
|
||||||
|
|
||||||
#define Zydis_EXPORTS
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
|
@ -61,7 +61,7 @@ bool InstructionDecoder::decodeRegisterOperand(InstructionInfo& info,
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
// TODO: Only REX? Or VEX too?
|
// 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)
|
if (registerId >= 4)
|
||||||
{
|
{
|
||||||
|
@ -88,7 +88,7 @@ bool InstructionDecoder::decodeRegisterOperand(InstructionInfo& info,
|
||||||
break;
|
break;
|
||||||
case RegisterClass::MMX:
|
case RegisterClass::MMX:
|
||||||
reg = static_cast<Register>(
|
reg = static_cast<Register>(
|
||||||
static_cast<uint16_t>(Register::MM0) + (registerId& 0x07));
|
static_cast<uint16_t>(Register::MM0) + (registerId & 0x07));
|
||||||
break;
|
break;
|
||||||
case RegisterClass::CONTROL:
|
case RegisterClass::CONTROL:
|
||||||
reg = static_cast<Register>(static_cast<uint16_t>(Register::CR0) + registerId);
|
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);
|
reg = static_cast<Register>(static_cast<uint16_t>(Register::DR0) + registerId);
|
||||||
break;
|
break;
|
||||||
case RegisterClass::SEGMENT:
|
case RegisterClass::SEGMENT:
|
||||||
if ((registerId& 7) > 5)
|
if ((registerId & 7) > 5)
|
||||||
{
|
{
|
||||||
info.flags |= IF_ERROR_OPERAND;
|
info.flags |= IF_ERROR_OPERAND;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
reg = static_cast<Register>(
|
reg = static_cast<Register>(
|
||||||
static_cast<uint16_t>(Register::ES) + (registerId& 0x07));
|
static_cast<uint16_t>(Register::ES) + (registerId & 0x07));
|
||||||
break;
|
break;
|
||||||
case RegisterClass::XMM:
|
case RegisterClass::XMM:
|
||||||
reg = static_cast<Register>(registerId + static_cast<uint16_t>(
|
reg = static_cast<Register>(registerId + static_cast<uint16_t>(
|
||||||
|
@ -125,7 +125,7 @@ bool InstructionDecoder::decodeRegisterMemoryOperand(InstructionInfo& info,
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
assert(info.flags& IF_MODRM);
|
assert(info.flags & IF_MODRM);
|
||||||
// Decode register operand
|
// Decode register operand
|
||||||
if (info.modrm_mod == 3)
|
if (info.modrm_mod == 3)
|
||||||
{
|
{
|
||||||
|
@ -147,10 +147,10 @@ bool InstructionDecoder::decodeRegisterMemoryOperand(InstructionInfo& info,
|
||||||
Register::SI, Register::DI, Register::SI, Register::DI,
|
Register::SI, Register::DI, Register::SI, Register::DI,
|
||||||
Register::NONE, Register::NONE, Register::NONE,
|
Register::NONE, Register::NONE, Register::NONE,
|
||||||
Register::NONE };
|
Register::NONE };
|
||||||
operand.base = static_cast<Register>(bases[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.index = static_cast<Register>(indices[info.modrm_rm_ext & 0x07]);
|
||||||
operand.scale = 0;
|
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;
|
offset = 16;
|
||||||
operand.base = Register::NONE;
|
operand.base = Register::NONE;
|
||||||
} else if (info.modrm_mod == 1) {
|
} else if (info.modrm_mod == 1) {
|
||||||
|
@ -181,7 +181,7 @@ bool InstructionDecoder::decodeRegisterMemoryOperand(InstructionInfo& info,
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
if ((info.modrm_rm_ext& 0x07) == 4)
|
if ((info.modrm_rm_ext & 0x07) == 4)
|
||||||
{
|
{
|
||||||
if (!decodeSIB(info))
|
if (!decodeSIB(info))
|
||||||
{
|
{
|
||||||
|
@ -193,7 +193,7 @@ bool InstructionDecoder::decodeRegisterMemoryOperand(InstructionInfo& info,
|
||||||
operand.index =
|
operand.index =
|
||||||
static_cast<Register>(static_cast<uint16_t>(Register::EAX) +
|
static_cast<Register>(static_cast<uint16_t>(Register::EAX) +
|
||||||
info.sib_index_ext);
|
info.sib_index_ext);
|
||||||
operand.scale = (1 << info.sib_scale)& ~1;
|
operand.scale = (1 << info.sib_scale) & ~1;
|
||||||
if (operand.index == Register::ESP)
|
if (operand.index == Register::ESP)
|
||||||
{
|
{
|
||||||
operand.index = Register::NONE;
|
operand.index = Register::NONE;
|
||||||
|
@ -225,7 +225,7 @@ bool InstructionDecoder::decodeRegisterMemoryOperand(InstructionInfo& info,
|
||||||
switch (info.modrm_mod)
|
switch (info.modrm_mod)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
if ((info.modrm_rm_ext& 0x07) == 5)
|
if ((info.modrm_rm_ext & 0x07) == 5)
|
||||||
{
|
{
|
||||||
info.flags |= IF_RELATIVE;
|
info.flags |= IF_RELATIVE;
|
||||||
operand.base = Register::RIP;
|
operand.base = Register::RIP;
|
||||||
|
@ -241,7 +241,7 @@ bool InstructionDecoder::decodeRegisterMemoryOperand(InstructionInfo& info,
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
if ((info.modrm_rm_ext& 0x07) == 4)
|
if ((info.modrm_rm_ext & 0x07) == 4)
|
||||||
{
|
{
|
||||||
if (!decodeSIB(info))
|
if (!decodeSIB(info))
|
||||||
{
|
{
|
||||||
|
@ -259,7 +259,7 @@ bool InstructionDecoder::decodeRegisterMemoryOperand(InstructionInfo& info,
|
||||||
operand.scale = 0;
|
operand.scale = 0;
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
operand.scale = (1 << info.sib_scale)& ~1;
|
operand.scale = (1 << info.sib_scale) & ~1;
|
||||||
}
|
}
|
||||||
if ((operand.base == Register::RBP) || (operand.base == Register::R13))
|
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
|
// TODO: Maybe return false instead of assert
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
if (!operand.lval.uqword&& (info.flags& IF_ERROR_MASK))
|
if (!operand.lval.uqword && (info.flags & IF_ERROR_MASK))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -350,7 +350,7 @@ bool InstructionDecoder::decodeDisplacement(InstructionInfo& info,
|
||||||
// TODO: Maybe return false instead of assert
|
// TODO: Maybe return false instead of assert
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
if (!operand.lval.uqword&& (info.flags& IF_ERROR_MASK))
|
if (!operand.lval.uqword && (info.flags & IF_ERROR_MASK))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -359,17 +359,17 @@ bool InstructionDecoder::decodeDisplacement(InstructionInfo& info,
|
||||||
|
|
||||||
bool InstructionDecoder::decodeModrm(InstructionInfo& info)
|
bool InstructionDecoder::decodeModrm(InstructionInfo& info)
|
||||||
{
|
{
|
||||||
if (!(info.flags& IF_MODRM))
|
if (!(info.flags & IF_MODRM))
|
||||||
{
|
{
|
||||||
info.modrm = inputNext(info);
|
info.modrm = inputNext(info);
|
||||||
if (!info.modrm&& (info.flags& IF_ERROR_MASK))
|
if (!info.modrm && (info.flags & IF_ERROR_MASK))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
info.flags |= IF_MODRM;
|
info.flags |= IF_MODRM;
|
||||||
info.modrm_mod = (info.modrm >> 6)& 0x03;
|
info.modrm_mod = (info.modrm >> 6) & 0x03;
|
||||||
info.modrm_reg = (info.modrm >> 3)& 0x07;
|
info.modrm_reg = (info.modrm >> 3) & 0x07;
|
||||||
info.modrm_rm = (info.modrm >> 0)& 0x07;
|
info.modrm_rm = (info.modrm >> 0) & 0x07;
|
||||||
}
|
}
|
||||||
// The @c decodeModrm method might get called multiple times during the opcode- and the
|
// 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
|
// 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)
|
bool InstructionDecoder::decodeSIB(InstructionInfo& info)
|
||||||
{
|
{
|
||||||
assert(info.flags& IF_MODRM);
|
assert(info.flags & IF_MODRM);
|
||||||
assert((info.modrm_rm& 0x7) == 4);
|
assert((info.modrm_rm & 0x7) == 4);
|
||||||
if (!(info.flags& IF_SIB))
|
if (!(info.flags & IF_SIB))
|
||||||
{
|
{
|
||||||
info.sib = inputNext(info);
|
info.sib = inputNext(info);
|
||||||
if (!info.sib&& (info.flags& IF_ERROR_MASK))
|
if (!info.sib && (info.flags & IF_ERROR_MASK))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
info.flags |= IF_SIB;
|
info.flags |= IF_SIB;
|
||||||
info.sib_scale = (info.sib >> 6)& 0x03;
|
info.sib_scale = (info.sib >> 6) & 0x03;
|
||||||
info.sib_index = (info.sib >> 3)& 0x07;
|
info.sib_index = (info.sib >> 3) & 0x07;
|
||||||
info.sib_base = (info.sib >> 0)& 0x07;
|
info.sib_base = (info.sib >> 0) & 0x07;
|
||||||
// The @c decodeSib method is only called during the operand decoding, so updating the
|
// The @c decodeSib method is only called during the operand decoding, so updating the
|
||||||
// extended values at this point should be safe.
|
// extended values at this point should be safe.
|
||||||
info.sib_index_ext = (info.eff_rexvex_x << 3) | info.sib_index;
|
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)
|
bool InstructionDecoder::decodeVex(InstructionInfo& info)
|
||||||
{
|
{
|
||||||
if (!(info.flags& IF_PREFIX_VEX))
|
if (!(info.flags & IF_PREFIX_VEX))
|
||||||
{
|
{
|
||||||
info.vex_op = inputCurrent();
|
info.vex_op = inputCurrent();
|
||||||
switch (info.vex_op)
|
switch (info.vex_op)
|
||||||
{
|
{
|
||||||
case 0xC4:
|
case 0xC4:
|
||||||
info.vex_b1 = inputNext(info);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
info.vex_b2 = inputNext(info);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
info.vex_r = (info.vex_b1 >> 7)& 0x01;
|
info.vex_r = (info.vex_b1 >> 7) & 0x01;
|
||||||
info.vex_x = (info.vex_b1 >> 6)& 0x01;
|
info.vex_x = (info.vex_b1 >> 6) & 0x01;
|
||||||
info.vex_b = (info.vex_b1 >> 5)& 0x01;
|
info.vex_b = (info.vex_b1 >> 5) & 0x01;
|
||||||
info.vex_m_mmmm = (info.vex_b1 >> 0)& 0x1F;
|
info.vex_m_mmmm = (info.vex_b1 >> 0) & 0x1F;
|
||||||
info.vex_w = (info.vex_b2 >> 7)& 0x01;
|
info.vex_w = (info.vex_b2 >> 7) & 0x01;
|
||||||
info.vex_vvvv = (info.vex_b2 >> 3)& 0x0F;
|
info.vex_vvvv = (info.vex_b2 >> 3) & 0x0F;
|
||||||
info.vex_l = (info.vex_b2 >> 2)& 0x01;
|
info.vex_l = (info.vex_b2 >> 2) & 0x01;
|
||||||
info.vex_pp = (info.vex_b2 >> 0)& 0x03;
|
info.vex_pp = (info.vex_b2 >> 0) & 0x03;
|
||||||
break;
|
break;
|
||||||
case 0xC5:
|
case 0xC5:
|
||||||
info.vex_b1 = inputNext(info);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
info.vex_r = (info.vex_b1 >> 7)& 0x01;
|
info.vex_r = (info.vex_b1 >> 7) & 0x01;
|
||||||
info.vex_x = 1;
|
info.vex_x = 1;
|
||||||
info.vex_b = 1;
|
info.vex_b = 1;
|
||||||
info.vex_m_mmmm = 1;
|
info.vex_m_mmmm = 1;
|
||||||
info.vex_w = 0;
|
info.vex_w = 0;
|
||||||
info.vex_vvvv = (info.vex_b1 >> 3)& 0x0F;
|
info.vex_vvvv = (info.vex_b1 >> 3) & 0x0F;
|
||||||
info.vex_l = (info.vex_b1 >> 2)& 0x01;
|
info.vex_l = (info.vex_b1 >> 2) & 0x01;
|
||||||
info.vex_pp = (info.vex_b1 >> 0)& 0x03;
|
info.vex_pp = (info.vex_b1 >> 0) & 0x03;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
|
@ -513,19 +513,19 @@ bool InstructionDecoder::decodeOperands(InstructionInfo& info)
|
||||||
info.operand[i].access_mode = OperandAccessMode::READ;
|
info.operand[i].access_mode = OperandAccessMode::READ;
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
if (info.instrDefinition->flags& IDF_OPERAND1_WRITE)
|
if (info.instrDefinition->flags & IDF_OPERAND1_WRITE)
|
||||||
{
|
{
|
||||||
info.operand[0].access_mode = OperandAccessMode::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;
|
info.operand[0].access_mode = OperandAccessMode::READWRITE;
|
||||||
}
|
}
|
||||||
} else if (i == 1)
|
} 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;
|
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;
|
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.off = inputNext<uint32_t>(info);
|
||||||
operand.lval.ptr.seg = inputNext<uint16_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;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -596,7 +596,7 @@ bool InstructionDecoder::decodeOperand(InstructionInfo& info, OperandInfo& opera
|
||||||
info.modrm_reg_ext, operandSize);
|
info.modrm_reg_ext, operandSize);
|
||||||
case DefinedOperandType::H:
|
case DefinedOperandType::H:
|
||||||
assert(info.vex_op != 0);
|
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);
|
operandSize);
|
||||||
case DefinedOperandType::sI:
|
case DefinedOperandType::sI:
|
||||||
operand.signed_lval = true;
|
operand.signed_lval = true;
|
||||||
|
@ -619,12 +619,12 @@ bool InstructionDecoder::decodeOperand(InstructionInfo& info, OperandInfo& opera
|
||||||
{
|
{
|
||||||
assert(info.vex_op != 0);
|
assert(info.vex_op != 0);
|
||||||
uint8_t imm = inputNext(info);
|
uint8_t imm = inputNext(info);
|
||||||
if (!imm&& (info.flags& IF_ERROR_MASK))
|
if (!imm && (info.flags & IF_ERROR_MASK))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
uint8_t mask = (m_disassemblerMode == DisassemblerMode::M64BIT) ? 0xF : 0x7;
|
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);
|
operandSize);
|
||||||
}
|
}
|
||||||
case DefinedOperandType::MR:
|
case DefinedOperandType::MR:
|
||||||
|
@ -729,7 +729,7 @@ bool InstructionDecoder::decodeOperand(InstructionInfo& info, OperandInfo& opera
|
||||||
case DefinedOperandType::GS:
|
case DefinedOperandType::GS:
|
||||||
if (m_disassemblerMode == DisassemblerMode::M64BIT)
|
if (m_disassemblerMode == DisassemblerMode::M64BIT)
|
||||||
{
|
{
|
||||||
if ((operandType != DefinedOperandType::FS)&&
|
if ((operandType != DefinedOperandType::FS) &&
|
||||||
(operandType != DefinedOperandType::GS))
|
(operandType != DefinedOperandType::GS))
|
||||||
{
|
{
|
||||||
info.flags |= IF_ERROR_OPERAND;
|
info.flags |= IF_ERROR_OPERAND;
|
||||||
|
@ -768,25 +768,25 @@ void InstructionDecoder::resolveOperandAndAddressMode(InstructionInfo& info) con
|
||||||
switch (m_disassemblerMode)
|
switch (m_disassemblerMode)
|
||||||
{
|
{
|
||||||
case DisassemblerMode::M16BIT:
|
case DisassemblerMode::M16BIT:
|
||||||
info.operand_mode = (info.flags& IF_PREFIX_OPERAND_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;
|
info.address_mode = (info.flags & IF_PREFIX_ADDRESS_SIZE) ? 32 : 16;
|
||||||
break;
|
break;
|
||||||
case DisassemblerMode::M32BIT:
|
case DisassemblerMode::M32BIT:
|
||||||
info.operand_mode = (info.flags& IF_PREFIX_OPERAND_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;
|
info.address_mode = (info.flags & IF_PREFIX_ADDRESS_SIZE) ? 16 : 32;
|
||||||
break;
|
break;
|
||||||
case DisassemblerMode::M64BIT:
|
case DisassemblerMode::M64BIT:
|
||||||
if (info.eff_rexvex_w)
|
if (info.eff_rexvex_w)
|
||||||
{
|
{
|
||||||
info.operand_mode = 64;
|
info.operand_mode = 64;
|
||||||
} else if ((info.flags& IF_PREFIX_OPERAND_SIZE))
|
} else if ((info.flags & IF_PREFIX_OPERAND_SIZE))
|
||||||
{
|
{
|
||||||
info.operand_mode = 16;
|
info.operand_mode = 16;
|
||||||
} else
|
} 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;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
|
@ -797,26 +797,26 @@ void InstructionDecoder::calculateEffectiveRexVexValues(InstructionInfo& info) c
|
||||||
{
|
{
|
||||||
assert(info.instrDefinition);
|
assert(info.instrDefinition);
|
||||||
uint8_t rex = info.rex;
|
uint8_t rex = info.rex;
|
||||||
if (info.flags& IF_PREFIX_VEX)
|
if (info.flags & IF_PREFIX_VEX)
|
||||||
{
|
{
|
||||||
switch (info.vex_op)
|
switch (info.vex_op)
|
||||||
{
|
{
|
||||||
case 0xC4:
|
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;
|
break;
|
||||||
case 0xC5:
|
case 0xC5:
|
||||||
rex = (~(info.vex_b1 >> 5))& 4;
|
rex = (~(info.vex_b1 >> 5)) & 4;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rex &= (info.instrDefinition->flags& 0x000F);
|
rex &= (info.instrDefinition->flags & 0x000F);
|
||||||
info.eff_rexvex_w = (rex >> 3)& 0x01;
|
info.eff_rexvex_w = (rex >> 3) & 0x01;
|
||||||
info.eff_rexvex_r = (rex >> 2)& 0x01;
|
info.eff_rexvex_r = (rex >> 2) & 0x01;
|
||||||
info.eff_rexvex_x = (rex >> 1)& 0x01;
|
info.eff_rexvex_x = (rex >> 1) & 0x01;
|
||||||
info.eff_rexvex_b = (rex >> 0)& 0x01;
|
info.eff_rexvex_b = (rex >> 0) & 0x01;
|
||||||
info.eff_vex_l = info.vex_l&& (info.instrDefinition->flags& IDF_ACCEPTS_VEXL);
|
info.eff_vex_l = info.vex_l && (info.instrDefinition->flags & IDF_ACCEPTS_VEXL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InstructionDecoder::decodePrefixes(InstructionInfo& info)
|
bool InstructionDecoder::decodePrefixes(InstructionInfo& info)
|
||||||
|
@ -870,8 +870,8 @@ bool InstructionDecoder::decodePrefixes(InstructionInfo& info)
|
||||||
info.flags |= IF_PREFIX_ADDRESS_SIZE;
|
info.flags |= IF_PREFIX_ADDRESS_SIZE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if ((m_disassemblerMode == DisassemblerMode::M64BIT)&&
|
if ((m_disassemblerMode == DisassemblerMode::M64BIT) &&
|
||||||
(inputCurrent()& 0xF0) == 0x40)
|
(inputCurrent() & 0xF0) == 0x40)
|
||||||
{
|
{
|
||||||
info.flags |= IF_PREFIX_REX;
|
info.flags |= IF_PREFIX_REX;
|
||||||
info.rex = inputCurrent();
|
info.rex = inputCurrent();
|
||||||
|
@ -884,7 +884,7 @@ bool InstructionDecoder::decodePrefixes(InstructionInfo& info)
|
||||||
// Increase the input offset, if a prefix was found
|
// Increase the input offset, if a prefix was found
|
||||||
if (!done)
|
if (!done)
|
||||||
{
|
{
|
||||||
if (!inputNext(info)&& (info.flags& IF_ERROR_MASK))
|
if (!inputNext(info) && (info.flags & IF_ERROR_MASK))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -892,12 +892,12 @@ bool InstructionDecoder::decodePrefixes(InstructionInfo& info)
|
||||||
} while (!done);
|
} while (!done);
|
||||||
// TODO: Check for multiple prefixes of the same group
|
// TODO: Check for multiple prefixes of the same group
|
||||||
// Parse REX Prefix
|
// Parse REX Prefix
|
||||||
if (info.flags& IF_PREFIX_REX)
|
if (info.flags & IF_PREFIX_REX)
|
||||||
{
|
{
|
||||||
info.rex_w = (info.rex >> 3)& 0x01;
|
info.rex_w = (info.rex >> 3) & 0x01;
|
||||||
info.rex_r = (info.rex >> 2)& 0x01;
|
info.rex_r = (info.rex >> 2) & 0x01;
|
||||||
info.rex_x = (info.rex >> 1)& 0x01;
|
info.rex_x = (info.rex >> 1) & 0x01;
|
||||||
info.rex_b = (info.rex >> 0)& 0x01;
|
info.rex_b = (info.rex >> 0) & 0x01;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -906,7 +906,7 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
||||||
{
|
{
|
||||||
using namespace Internal;
|
using namespace Internal;
|
||||||
// Read first opcode byte
|
// Read first opcode byte
|
||||||
if (!inputNext(info)&& (info.flags& IF_ERROR_MASK))
|
if (!inputNext(info) && (info.flags & IF_ERROR_MASK))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -934,8 +934,8 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
||||||
const InstructionDefinition *instrDefinition =
|
const InstructionDefinition *instrDefinition =
|
||||||
GetInstructionDefinition(node);
|
GetInstructionDefinition(node);
|
||||||
// Check for invalid 64 bit instruction
|
// Check for invalid 64 bit instruction
|
||||||
if ((m_disassemblerMode == DisassemblerMode::M64BIT)&&
|
if ((m_disassemblerMode == DisassemblerMode::M64BIT) &&
|
||||||
(instrDefinition->flags& IDF_INVALID_64))
|
(instrDefinition->flags & IDF_INVALID_64))
|
||||||
{
|
{
|
||||||
info.flags |= IF_ERROR_INVALID_64;
|
info.flags |= IF_ERROR_INVALID_64;
|
||||||
return false;
|
return false;
|
||||||
|
@ -956,12 +956,12 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
||||||
return true;
|
return true;
|
||||||
case OpcodeTreeNodeType::TABLE:
|
case OpcodeTreeNodeType::TABLE:
|
||||||
// Read next opcode byte
|
// Read next opcode byte
|
||||||
if (!inputNext(info)&& (info.flags& IF_ERROR_MASK))
|
if (!inputNext(info) && (info.flags & IF_ERROR_MASK))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Update instruction info
|
// 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[info.opcode_length] = inputCurrent();
|
||||||
info.opcode_length++;
|
info.opcode_length++;
|
||||||
// Set child node index for next iteration
|
// Set child node index for next iteration
|
||||||
|
@ -993,13 +993,13 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
||||||
break;
|
break;
|
||||||
case OpcodeTreeNodeType::MANDATORY:
|
case OpcodeTreeNodeType::MANDATORY:
|
||||||
// Check if there are any prefixes present
|
// Check if there are any prefixes present
|
||||||
if (info.flags& IF_PREFIX_REP)
|
if (info.flags & IF_PREFIX_REP)
|
||||||
{
|
{
|
||||||
index = 1; // F2
|
index = 1; // F2
|
||||||
} else if (info.flags& IF_PREFIX_REPNE)
|
} else if (info.flags & IF_PREFIX_REPNE)
|
||||||
{
|
{
|
||||||
index = 2; // F3
|
index = 2; // F3
|
||||||
} else if (info.flags& IF_PREFIX_OPERAND_SIZE)
|
} else if (info.flags & IF_PREFIX_OPERAND_SIZE)
|
||||||
{
|
{
|
||||||
index = 3; // 66
|
index = 3; // 66
|
||||||
}
|
}
|
||||||
|
@ -1007,7 +1007,7 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
||||||
{
|
{
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
if (index&& (GetOpcodeTreeChild(node, index) != 0))
|
if (index && (GetOpcodeTreeChild(node, index) != 0))
|
||||||
{
|
{
|
||||||
// Remove REP and REPNE prefix
|
// Remove REP and REPNE prefix
|
||||||
info.flags &= ~IF_PREFIX_REP;
|
info.flags &= ~IF_PREFIX_REP;
|
||||||
|
@ -1032,13 +1032,13 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
||||||
switch (m_disassemblerMode)
|
switch (m_disassemblerMode)
|
||||||
{
|
{
|
||||||
case DisassemblerMode::M16BIT:
|
case DisassemblerMode::M16BIT:
|
||||||
index = (info.flags& IF_PREFIX_ADDRESS_SIZE) ? 1 : 0;
|
index = (info.flags & IF_PREFIX_ADDRESS_SIZE) ? 1 : 0;
|
||||||
break;
|
break;
|
||||||
case DisassemblerMode::M32BIT:
|
case DisassemblerMode::M32BIT:
|
||||||
index = (info.flags& IF_PREFIX_ADDRESS_SIZE) ? 0 : 1;
|
index = (info.flags & IF_PREFIX_ADDRESS_SIZE) ? 0 : 1;
|
||||||
break;
|
break;
|
||||||
case DisassemblerMode::M64BIT:
|
case DisassemblerMode::M64BIT:
|
||||||
index = (info.flags& IF_PREFIX_ADDRESS_SIZE) ? 1 : 2;
|
index = (info.flags & IF_PREFIX_ADDRESS_SIZE) ? 1 : 2;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
|
@ -1048,13 +1048,13 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
||||||
switch (m_disassemblerMode)
|
switch (m_disassemblerMode)
|
||||||
{
|
{
|
||||||
case DisassemblerMode::M16BIT:
|
case DisassemblerMode::M16BIT:
|
||||||
index = (info.flags& IF_PREFIX_OPERAND_SIZE) ? 1 : 0;
|
index = (info.flags & IF_PREFIX_OPERAND_SIZE) ? 1 : 0;
|
||||||
break;
|
break;
|
||||||
case DisassemblerMode::M32BIT:
|
case DisassemblerMode::M32BIT:
|
||||||
index = (info.flags& IF_PREFIX_OPERAND_SIZE) ? 0 : 1;
|
index = (info.flags & IF_PREFIX_OPERAND_SIZE) ? 0 : 1;
|
||||||
break;
|
break;
|
||||||
case DisassemblerMode::M64BIT:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
|
@ -1100,7 +1100,7 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
||||||
}
|
}
|
||||||
// Read the actual 3dnow opcode
|
// Read the actual 3dnow opcode
|
||||||
info.opcode[2] = inputNext(info);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1125,20 +1125,20 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
||||||
}
|
}
|
||||||
if (info.operand[0].type != OperandType::NONE)
|
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;
|
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;
|
info.operand[0].access_mode = OperandAccessMode::READWRITE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (info.operand[1].type != OperandType::NONE)
|
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;
|
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;
|
info.operand[1].access_mode = OperandAccessMode::READWRITE;
|
||||||
}
|
}
|
||||||
|
@ -1148,7 +1148,7 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
||||||
}
|
}
|
||||||
case OpcodeTreeNodeType::VEX:
|
case OpcodeTreeNodeType::VEX:
|
||||||
if ((m_disassemblerMode == DisassemblerMode::M64BIT) ||
|
if ((m_disassemblerMode == DisassemblerMode::M64BIT) ||
|
||||||
(((inputCurrent() >> 6)& 0x03) == 0x03))
|
(((inputCurrent() >> 6) & 0x03) == 0x03))
|
||||||
{
|
{
|
||||||
// Decode vex prefix
|
// Decode vex prefix
|
||||||
if (!decodeVex(info))
|
if (!decodeVex(info))
|
||||||
|
@ -1181,11 +1181,11 @@ bool InstructionDecoder::decodeOpcode(InstructionInfo& info)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OpcodeTreeNodeType::VEXW:
|
case OpcodeTreeNodeType::VEXW:
|
||||||
assert(info.flags& IF_PREFIX_VEX);
|
assert(info.flags & IF_PREFIX_VEX);
|
||||||
index = info.vex_w;
|
index = info.vex_w;
|
||||||
break;
|
break;
|
||||||
case OpcodeTreeNodeType::VEXL:
|
case OpcodeTreeNodeType::VEXL:
|
||||||
assert(info.flags& IF_PREFIX_VEX);
|
assert(info.flags & IF_PREFIX_VEX);
|
||||||
index = info.vex_l;
|
index = info.vex_l;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1243,7 +1243,7 @@ bool InstructionDecoder::decodeInstruction(InstructionInfo& info)
|
||||||
goto DecodeError;
|
goto DecodeError;
|
||||||
}
|
}
|
||||||
// SWAPGS is only valid in 64 bit mode
|
// SWAPGS is only valid in 64 bit mode
|
||||||
if ((info.mnemonic == InstructionMnemonic::SWAPGS)&&
|
if ((info.mnemonic == InstructionMnemonic::SWAPGS) &&
|
||||||
(m_disassemblerMode != DisassemblerMode::M64BIT))
|
(m_disassemblerMode != DisassemblerMode::M64BIT))
|
||||||
{
|
{
|
||||||
info.flags &= IF_ERROR_INVALID;
|
info.flags &= IF_ERROR_INVALID;
|
||||||
|
@ -1252,13 +1252,13 @@ bool InstructionDecoder::decodeInstruction(InstructionInfo& info)
|
||||||
// Handle aliases
|
// Handle aliases
|
||||||
if (info.mnemonic == InstructionMnemonic::XCHG)
|
if (info.mnemonic == InstructionMnemonic::XCHG)
|
||||||
{
|
{
|
||||||
if ((info.operand[0].type == OperandType::REGISTER&&
|
if ((info.operand[0].type == OperandType::REGISTER &&
|
||||||
info.operand[0].base == Register::AX&&
|
info.operand[0].base == Register::AX &&
|
||||||
info.operand[1].type == OperandType::REGISTER&&
|
info.operand[1].type == OperandType::REGISTER &&
|
||||||
info.operand[1].base == Register::AX) ||
|
info.operand[1].base == Register::AX) ||
|
||||||
(info.operand[0].type == OperandType::REGISTER&&
|
(info.operand[0].type == OperandType::REGISTER &&
|
||||||
info.operand[0].base == Register::EAX&&
|
info.operand[0].base == Register::EAX &&
|
||||||
info.operand[1].type == OperandType::REGISTER&&
|
info.operand[1].type == OperandType::REGISTER &&
|
||||||
info.operand[1].base == Register::EAX))
|
info.operand[1].base == Register::EAX))
|
||||||
{
|
{
|
||||||
info.mnemonic = InstructionMnemonic::NOP;
|
info.mnemonic = InstructionMnemonic::NOP;
|
||||||
|
@ -1268,7 +1268,7 @@ bool InstructionDecoder::decodeInstruction(InstructionInfo& info)
|
||||||
info.operand[1].access_mode = OperandAccessMode::NA;
|
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.mnemonic = InstructionMnemonic::PAUSE;
|
||||||
info.flags &= ~IF_PREFIX_REP;
|
info.flags &= ~IF_PREFIX_REP;
|
||||||
|
@ -1282,7 +1282,7 @@ DecodeError:
|
||||||
// Increment instruction pointer.
|
// Increment instruction pointer.
|
||||||
m_instructionPointer += 1;
|
m_instructionPointer += 1;
|
||||||
// Backup all error flags, the instruction length and the instruction address
|
// 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 length = info.length;
|
||||||
uint8_t firstByte = info.data[0];
|
uint8_t firstByte = info.data[0];
|
||||||
uint64_t instrAddress = info.instrAddress;
|
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
|
// Return with error, if the end of the input source was reached while decoding the
|
||||||
// invalid instruction
|
// invalid instruction
|
||||||
if (info.flags& IF_ERROR_END_OF_INPUT)
|
if (info.flags & IF_ERROR_END_OF_INPUT)
|
||||||
{
|
{
|
||||||
info.length = 0;
|
info.length = 0;
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in New Issue