From 335f6bd81ed4e4cb69a8bd2a6aff8534803ad160 Mon Sep 17 00:00:00 2001 From: flobernd Date: Thu, 21 May 2015 01:07:19 +0200 Subject: [PATCH 1/5] Minor bugfixes and CustomDataSource demo * fixed 64 bit compilation error * added VERSIONINFO resource * added CustomDataSource demo (disassembles hex input from the console) --- CMakeLists.txt | 12 +- .../CPP/CustomDataSource/CustomDataSource.cpp | 169 ++++++++++++++ Examples/CPP/SimpleDemo/SimpleDemo.cpp | 4 +- Zydis/Zydis.rc | Bin 0 -> 4660 bytes Zydis/ZydisAPI.cpp | 6 +- Zydis/ZydisAPI.h | 2 - Zydis/ZydisInstructionDecoder.cpp | 218 +++++++++--------- 7 files changed, 295 insertions(+), 116 deletions(-) create mode 100644 Examples/CPP/CustomDataSource/CustomDataSource.cpp create mode 100644 Zydis/Zydis.rc diff --git a/CMakeLists.txt b/CMakeLists.txt index a9e521d..b1c6b2e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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") diff --git a/Examples/CPP/CustomDataSource/CustomDataSource.cpp b/Examples/CPP/CustomDataSource/CustomDataSource.cpp new file mode 100644 index 0000000..fcb6ba0 --- /dev/null +++ b/Examples/CPP/CustomDataSource/CustomDataSource.cpp @@ -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 +#include +#include +#include +#include +#include +#include + +class ZydisStdinInput : public Zydis::BaseInput +{ +private: + std::vector 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 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(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(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(info.data[0]) << std::endl; + } else + { + std::cout << formatter.formatInstruction(info) << std::endl; + } + } + + return 0; +} \ No newline at end of file diff --git a/Examples/CPP/SimpleDemo/SimpleDemo.cpp b/Examples/CPP/SimpleDemo/SimpleDemo.cpp index 2bf03fb..f1e7341 100644 --- a/Examples/CPP/SimpleDemo/SimpleDemo.cpp +++ b/Examples/CPP/SimpleDemo/SimpleDemo.cpp @@ -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(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(info.data[0]) << std::endl; } else { std::cout << formatter.formatInstruction(info) << std::endl; diff --git a/Zydis/Zydis.rc b/Zydis/Zydis.rc new file mode 100644 index 0000000000000000000000000000000000000000..b436f07008559a430b33d1a82bd954fb39446b54 GIT binary patch literal 4660 zcmds*O>Y}V42I`ip#Nc^UfLkAr8K?dCV$ClWXX_arRgP*tq;4kEkTl#`X}`d_Sp7) z$Q{k@T4-t)y#&H~cV@_!%ccCg4`YqTCA+;`6MsjN$wE_dYaz|Gk_ESW zW25Ul_C292CGSZ1d7|~P>`ZlCN@}e;k;X_s`B5_yvv3^#&>9$t+ZU2JwYgjA!fND- zQ6_(opD3aSjb?f#4{ObgjfbhN675`GWb)!l5=%)sPixI*ri1>%&{pOn8W%zu$>N<| zGm`|vx%C|3p<~02dj-N&x-lbeVQl)uFc$`_xu2PQW#(QPnwa;Asm!>ehKTlCX%KN1 zYT>M6qZYoih&>`QO5T!>M3HUutJ;}-y|&f4dQg`Q_+5#!o4bSjW)xMDw z8H2y5o2;j*TopWY(*P2?Gyw~E#)>A|9esg%Wqe5TW2|H{^pjox2aM2@-INL~to zO7wZEW*l~9h3aPZro^86a;U-!^Dpw9JVu#VNmEG?>)dka*(6%{Ab+uA-)u6KYHE;I z<4Ek!!$(<2-H~#f32Saha9-pl_DkZY*x_X@GD}6X7j56ayfVT6=iGUQsTeB6_Y1la zn71nE(vv*n@ zgk#B_>z?HpeaUq-ey^539sOc-iMgh6LQeV{UU}2@r9A=43?L{21odU6hlzGI^looA2?H09Tc z<>WxmC%W)E=8#M}=1Fy!mL5|_vE2wCl z>V$Em$P1%bIWXR{C=zqAirp5d(IdA@&Wk?9>W?|t)=Q2OEAZU>dF&}CvP1a@OH?*o zdhT5_`B?2%?`+n;jPvTQbsF(}qdh&n!P${(`QFb-YNh_T(hQPZLvi-OI)qyGs`+3X zQo&he1#X!~lMbfSy}y!n78S>F{8)MHcv9r-zph<;?9LvHDqv+!1y>*2TX zz0OV@Lnq>?-e(j2%@hqa!4B7|_?eI#p|R2DJiw`-99LDoUXb_q=d_~1PUYCI<)i=H z$HW%<;;B4zxmP)6T0fKLd*Y}l6)m&Vv@ARBsedi7=k&xY%y4q_QyuU6BQeA2vaO2X zB;a|E-x%A`(rOX49%4kV^=7SCkdn?e|Ke)A53OU*jf0x}=3KO}H}!++YoyUc`0PHl z&9@gP75~mC#}F~&y^I~>KM>+d=Oa!ni_QDLYUAI2-#y2J^0#2L>|ca@74E2Oo`Oq8 z`M%(U$k}EaZ+=SNQD<;sdJ1|+$TPzwJLNCU==; public: uint32_t type; + uint32_t align; std::conditional_t::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( - reinterpret_cast(instance) - sizeof(std::declval().type)); + reinterpret_cast(instance) + - sizeof(std::declval().type) + - sizeof(std::declval().align)); } }; #pragma pack(pop) diff --git a/Zydis/ZydisAPI.h b/Zydis/ZydisAPI.h index 359a87b..3cff446 100644 --- a/Zydis/ZydisAPI.h +++ b/Zydis/ZydisAPI.h @@ -31,8 +31,6 @@ #ifndef _ZYDIS_API_H_ #define _ZYDIS_API_H_ -#define Zydis_EXPORTS - #include #include #include diff --git a/Zydis/ZydisInstructionDecoder.cpp b/Zydis/ZydisInstructionDecoder.cpp index 0a1f34d..de0bb9c 100644 --- a/Zydis/ZydisInstructionDecoder.cpp +++ b/Zydis/ZydisInstructionDecoder.cpp @@ -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( - static_cast(Register::MM0) + (registerId& 0x07)); + static_cast(Register::MM0) + (registerId & 0x07)); break; case RegisterClass::CONTROL: reg = static_cast(static_cast(Register::CR0) + registerId); @@ -97,13 +97,13 @@ bool InstructionDecoder::decodeRegisterOperand(InstructionInfo& info, reg = static_cast(static_cast(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( - static_cast(Register::ES) + (registerId& 0x07)); + static_cast(Register::ES) + (registerId & 0x07)); break; case RegisterClass::XMM: reg = static_cast(registerId + static_cast( @@ -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(bases[info.modrm_rm_ext& 0x07]); - operand.index = static_cast(indices[info.modrm_rm_ext& 0x07]); + operand.base = static_cast(bases[info.modrm_rm_ext & 0x07]); + operand.index = static_cast(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(static_cast(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(info); operand.lval.ptr.seg = inputNext(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; From 9572b08daf676e0c4a1d99f832736dd74fca47c7 Mon Sep 17 00:00:00 2001 From: athre0z Date: Thu, 21 May 2015 17:35:26 +0200 Subject: [PATCH 2/5] fixed formatted printing --- Examples/C/SimpleDemo/SimpleDemo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/C/SimpleDemo/SimpleDemo.c b/Examples/C/SimpleDemo/SimpleDemo.c index bf992af..bf10f55 100644 --- a/Examples/C/SimpleDemo/SimpleDemo.c +++ b/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]); From 02d0d84c68fd9a97402a251e319c2a8c9a451bf8 Mon Sep 17 00:00:00 2001 From: flobernd Date: Thu, 21 May 2015 21:42:06 +0200 Subject: [PATCH 3/5] Minor bugfixes --- CMakeLists.txt | 8 ++-- Zydis/{Zydis.rc => VersionInfo.rc} | Bin Zydis/ZydisInstructionDecoder.hpp | 55 ++++++++++++++-------------- Zydis/ZydisInstructionFormatter.cpp | 38 +++++++++---------- Zydis/ZydisOpcodeTable.hpp | 10 ++--- Zydis/ZydisUtils.cpp | 14 +++---- 6 files changed, 63 insertions(+), 62 deletions(-) rename Zydis/{Zydis.rc => VersionInfo.rc} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index b1c6b2e..03cf2c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,10 +58,10 @@ set(sources "Zydis/ZydisSymbolResolver.cpp" "Zydis/ZydisUtils.cpp") - if (BUILD_SHARED_LIBS AND WIN32) - set(sources ${sources} - "Zydis/Zydis.rc") - endif () +if (BUILD_SHARED_LIBS AND WIN32) + set(sources ${sources} + "Zydis/VersionInfo.rc") +endif () if (BUILD_C_BINDINGS) set(headers ${headers} diff --git a/Zydis/Zydis.rc b/Zydis/VersionInfo.rc similarity index 100% rename from Zydis/Zydis.rc rename to Zydis/VersionInfo.rc diff --git a/Zydis/ZydisInstructionDecoder.hpp b/Zydis/ZydisInstructionDecoder.hpp index 84f9355..19a1d07 100644 --- a/Zydis/ZydisInstructionDecoder.hpp +++ b/Zydis/ZydisInstructionDecoder.hpp @@ -45,34 +45,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 +87,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 +176,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; } diff --git a/Zydis/ZydisInstructionFormatter.cpp b/Zydis/ZydisInstructionFormatter.cpp index 5866609..fd48e07 100644 --- a/Zydis/ZydisInstructionFormatter.cpp +++ b/Zydis/ZydisInstructionFormatter.cpp @@ -39,7 +39,7 @@ namespace Zydis /* BaseInstructionFormatter ================================================================ */ -const char *BaseInstructionFormatter::m_registerStrings[] = +const char* BaseInstructionFormatter::m_registerStrings[] = { /* 8 bit general purpose registers */ "al", "cl", "dl", "bl", @@ -237,13 +237,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 @@ -293,7 +293,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); @@ -316,7 +316,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); @@ -408,7 +408,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)); } @@ -480,14 +480,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 "); } @@ -506,7 +506,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) @@ -536,14 +536,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; @@ -559,7 +559,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; diff --git a/Zydis/ZydisOpcodeTable.hpp b/Zydis/ZydisOpcodeTable.hpp index 1b1d14a..ae1d101 100644 --- a/Zydis/ZydisOpcodeTable.hpp +++ b/Zydis/ZydisOpcodeTable.hpp @@ -1607,7 +1607,7 @@ extern const char* instrMnemonicStrings[]; */ inline OpcodeTreeNodeType GetOpcodeNodeType(OpcodeTreeNode node) { - return static_cast((node >> 12)& 0x0F); + return static_cast((node >> 12) & 0x0F); } /** @@ -1617,7 +1617,7 @@ inline OpcodeTreeNodeType GetOpcodeNodeType(OpcodeTreeNode node) */ inline uint16_t GetOpcodeNodeValue(OpcodeTreeNode node) { - return (node& 0x0FFF); + return (node & 0x0FFF); } /** @@ -1698,7 +1698,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 +1735,7 @@ inline uint16_t GetSimpleOperandSize(DefinedOperandSize operandSize) */ inline DefinedOperandSize GetComplexOperandMemSize(DefinedOperandSize operandSize) { - return static_cast(static_cast(operandSize)& 0x0F); + return static_cast(static_cast(operandSize) & 0x0F); } /** @@ -1745,7 +1745,7 @@ inline DefinedOperandSize GetComplexOperandMemSize(DefinedOperandSize operandSiz */ inline DefinedOperandSize GetComplexOperandRegSize(DefinedOperandSize operandSize) { - return static_cast((static_cast(operandSize) >> 4)& 0x0F); + return static_cast((static_cast(operandSize) >> 4) & 0x0F); } } diff --git a/Zydis/ZydisUtils.cpp b/Zydis/ZydisUtils.cpp index 85d6c86..a451a47 100644 --- a/Zydis/ZydisUtils.cpp +++ b/Zydis/ZydisUtils.cpp @@ -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); } From 1e51b9a69d76a06edf7230cb66963a82b98a6873 Mon Sep 17 00:00:00 2001 From: flobernd Date: Thu, 21 May 2015 22:59:24 +0200 Subject: [PATCH 4/5] Fixed readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d6bf326..1544355 100644 --- a/README.md +++ b/README.md @@ -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; From 2070b7a427e21415d293171e5cef30a6b18aac19 Mon Sep 17 00:00:00 2001 From: athre0z Date: Fri, 22 May 2015 17:23:32 +0200 Subject: [PATCH 5/5] improved documentation and README.md --- README.md | 15 ++++--- Zydis/Zydis.hpp | 67 +++++++++++++++++++++++++++-- Zydis/ZydisAPI.h | 5 +++ Zydis/ZydisInstructionDecoder.hpp | 5 +++ Zydis/ZydisInstructionFormatter.hpp | 5 +++ Zydis/ZydisOpcodeTable.hpp | 5 +++ Zydis/ZydisSymbolResolver.hpp | 5 +++ Zydis/ZydisUtils.hpp | 5 +++ 8 files changed, 104 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 1544355..af62520 100644 --- a/README.md +++ b/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 #include #include @@ -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. diff --git a/Zydis/Zydis.hpp b/Zydis/Zydis.hpp index 4c77299..f6a3fd9 100644 --- a/Zydis/Zydis.hpp +++ b/Zydis/Zydis.hpp @@ -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 + * #include + * #include + * #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_ */ \ No newline at end of file +#endif /*_ZYDIS_HPP_ */ \ No newline at end of file diff --git a/Zydis/ZydisAPI.h b/Zydis/ZydisAPI.h index 3cff446..a4807ab 100644 --- a/Zydis/ZydisAPI.h +++ b/Zydis/ZydisAPI.h @@ -28,6 +28,11 @@ ***************************************************************************************************/ +/** + * @file + * @brief C API for Zydis. + */ + #ifndef _ZYDIS_API_H_ #define _ZYDIS_API_H_ diff --git a/Zydis/ZydisInstructionDecoder.hpp b/Zydis/ZydisInstructionDecoder.hpp index 19a1d07..426e7b8 100644 --- a/Zydis/ZydisInstructionDecoder.hpp +++ b/Zydis/ZydisInstructionDecoder.hpp @@ -28,6 +28,11 @@ ***************************************************************************************************/ +/** + * @file + * @brief Instruction decoder classes. + */ + #ifndef _ZYDIS_INSTRUCTIONDECODER_HPP_ #define _ZYDIS_INSTRUCTIONDECODER_HPP_ diff --git a/Zydis/ZydisInstructionFormatter.hpp b/Zydis/ZydisInstructionFormatter.hpp index d2d8789..6077010 100644 --- a/Zydis/ZydisInstructionFormatter.hpp +++ b/Zydis/ZydisInstructionFormatter.hpp @@ -28,6 +28,11 @@ ***************************************************************************************************/ +/** + * @file + * @brief Instruction formatting classes. + */ + #ifndef _ZYDIS_INSTRUCTIONFORMATTER_HPP_ #define _ZYDIS_INSTRUCTIONFORMATTER_HPP_ diff --git a/Zydis/ZydisOpcodeTable.hpp b/Zydis/ZydisOpcodeTable.hpp index ae1d101..a9c7887 100644 --- a/Zydis/ZydisOpcodeTable.hpp +++ b/Zydis/ZydisOpcodeTable.hpp @@ -28,6 +28,11 @@ ***************************************************************************************************/ +/** + * @file + * @brief The opcode table definition, mostly internal stuff. + */ + #ifndef _ZYDIS_OPCODETABLE_HPP_ #define _ZYDIS_OPCODETABLE_HPP_ diff --git a/Zydis/ZydisSymbolResolver.hpp b/Zydis/ZydisSymbolResolver.hpp index e3d2a2e..d7c4d53 100644 --- a/Zydis/ZydisSymbolResolver.hpp +++ b/Zydis/ZydisSymbolResolver.hpp @@ -28,6 +28,11 @@ ***************************************************************************************************/ +/** + * @file + * @brief Classes for symbol resolving in the disassembly. + */ + #ifndef _ZYDIS_SYMBOLRESOLVER_HPP_ #define _ZYDIS_SYMBOLRESOLVER_HPP_ diff --git a/Zydis/ZydisUtils.hpp b/Zydis/ZydisUtils.hpp index 81c5398..9641b7e 100644 --- a/Zydis/ZydisUtils.hpp +++ b/Zydis/ZydisUtils.hpp @@ -28,6 +28,11 @@ ***************************************************************************************************/ +/** + * @file + * @brief Utility functions. + */ + #ifndef _ZYDIS_UTILS_HPP_ #define _ZYDIS_UTILS_HPP_