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_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/Zydis.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")
|
||||
|
|
|
@ -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;
|
||||
|
|
Binary file not shown.
|
@ -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)
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
#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;
|
||||
|
|
Loading…
Reference in New Issue