diff --git a/libIRDB/include/decode/decode_bea.hpp b/libIRDB/include/decode/decode_bea.hpp index 2cc64e6f2fb71d6b9a74ed78e822bb1179ac5f30..388eedbd2aee10f770a476c92c607f37f3e9120e 100644 --- a/libIRDB/include/decode/decode_bea.hpp +++ b/libIRDB/include/decode/decode_bea.hpp @@ -38,9 +38,9 @@ class DecodedInstructionBea_t virtual_offset_t getAddress() const; bool setsStackPointer() const; uint32_t getPrefixCount() const; - bool hasRepPrefix() const; - bool hasRepnePrefix() const; - bool hasOperandSizePrefix() const; + bool hasRelevantRepPrefix() const; + bool hasRelevantRepnePrefix() const; + bool hasRelevantOperandSizePrefix() const; bool hasRexWPrefix() const; bool hasImplicitlyModifiedRegs() const; virtual_offset_t getMemoryDisplacementOffset(const DecodedOperandBea_t& t) const; diff --git a/libIRDB/include/decode/decode_cs.hpp b/libIRDB/include/decode/decode_cs.hpp index f52688a36b4e3bd5909b6a457aec0637b895df5a..462aa5d9c8db76e9e948c8279c49c55703d86668 100644 --- a/libIRDB/include/decode/decode_cs.hpp +++ b/libIRDB/include/decode/decode_cs.hpp @@ -39,9 +39,9 @@ class DecodedInstructionCapstone_t virtual_offset_t getAddress() const; bool setsStackPointer() const; uint32_t getPrefixCount() const; - bool hasRepPrefix() const; - bool hasRepnePrefix() const; - bool hasOperandSizePrefix() const; + bool hasRelevantRepPrefix() const; + bool hasRelevantRepnePrefix() const; + bool hasRelevantOperandSizePrefix() const; bool hasRexWPrefix() const; bool hasImplicitlyModifiedRegs() const; virtual_offset_t getMemoryDisplacementOffset(const DecodedOperandCapstone_t& t) const; diff --git a/libIRDB/include/decode/decode_meta.hpp b/libIRDB/include/decode/decode_meta.hpp index 98db299c3bd674bc175835495a10c311cfcfb816..468cddbc4a501e5e38ba96cece675e66660ea19f 100644 --- a/libIRDB/include/decode/decode_meta.hpp +++ b/libIRDB/include/decode/decode_meta.hpp @@ -42,9 +42,9 @@ class DecodedInstructionMeta_t virtual_offset_t getAddress() const; bool setsStackPointer() const; uint32_t getPrefixCount() const; - bool hasRepPrefix() const; - bool hasRepnePrefix() const; - bool hasOperandSizePrefix() const; + bool hasRelevantRepPrefix() const; + bool hasRelevantRepnePrefix() const; + bool hasRelevantOperandSizePrefix() const; bool hasRexWPrefix() const; bool hasImplicitlyModifiedRegs() const; virtual_offset_t getMemoryDisplacementOffset(const DecodedOperandMeta_t& t) const; diff --git a/libIRDB/src/decode/decode_bea.cpp b/libIRDB/src/decode/decode_bea.cpp index f7ced5e55c7096c83b4451fae738bf7ab93550cf..d98da4dc8da575ab55fde5d654f0ec7120329c97 100644 --- a/libIRDB/src/decode/decode_bea.cpp +++ b/libIRDB/src/decode/decode_bea.cpp @@ -246,19 +246,19 @@ virtual_offset_t DecodedInstructionBea_t::getMemoryDisplacementOffset(const Deco } -bool DecodedInstructionBea_t::hasRepPrefix() const +bool DecodedInstructionBea_t::hasRelevantRepPrefix() const { DISASM* d=static_cast<DISASM*>(disasm_data); - return d->Prefix.RepnePrefix!=NotUsedPrefix; + return d->Prefix.RepPrefix==InUsePrefix; } -bool DecodedInstructionBea_t::hasRepnePrefix() const +bool DecodedInstructionBea_t::hasRelevantRepnePrefix() const { DISASM* d=static_cast<DISASM*>(disasm_data); - return d->Prefix.RepPrefix!=NotUsedPrefix; + return d->Prefix.RepnePrefix==InUsePrefix; } -bool DecodedInstructionBea_t::hasOperandSizePrefix() const +bool DecodedInstructionBea_t::hasRelevantOperandSizePrefix() const { DISASM* d=static_cast<DISASM*>(disasm_data); return d->Prefix.OperandSize!=NotUsedPrefix; diff --git a/libIRDB/src/decode/decode_cs.cpp b/libIRDB/src/decode/decode_cs.cpp index 0dc7b42a0c3f083b9ab433759013b1b55e3eb7ba..788f252360e6e54cd330841752d013647a263609 100644 --- a/libIRDB/src/decode/decode_cs.cpp +++ b/libIRDB/src/decode/decode_cs.cpp @@ -15,14 +15,24 @@ using namespace std; // static helpers -static bool isJmp(cs_insn* the_insn) +static inline bool hasPrefix(const cs_insn* the_insn, const x86_prefix desired_pref) { - const auto grp_it=find(ALLOF(the_insn->detail->groups), X86_GRP_JUMP); + const auto count=count_if(ALLOF(the_insn->detail->x86.prefix), [&](const uint8_t actual_pref) { return actual_pref==desired_pref; } ) ; + return count!=0; +} + +static bool isPartOfGroup(const cs_insn* the_insn, const x86_insn_group the_grp) +{ + const auto grp_it=find(ALLOF(the_insn->detail->groups), the_grp); return grp_it!=end(the_insn->detail->groups); } -// shared code +static bool isJmp(cs_insn* the_insn) +{ + return isPartOfGroup(the_insn,X86_GRP_JUMP); +} + class CapstoneHandle_t { public: @@ -50,6 +60,26 @@ class CapstoneHandle_t }; static CapstoneHandle_t *cs_handle=NULL; +template<class type> +static inline type insnToImmedHelper(cs_insn* the_insn) +{ + const auto count = cs_op_count(cs_handle->getHandle(), the_insn, X86_OP_IMM); + const auto x86 = &(the_insn->detail->x86); + + if (count==0) + return 0; /* no immediate is the same as an immediate of 0, i guess? */ + else if (count==1) + { + const auto index = cs_op_index(cs_handle->getHandle(), the_insn, X86_OP_IMM, 1); + return x86->operands[index].imm; + } + else + throw std::logic_error(string("Called ")+__FUNCTION__+" with number of immedaites not equal 1"); +} + + + +// shared code // constructors, destructors, operators. void DecodedInstructionCapstone_t::Disassemble(const virtual_offset_t start_addr, const void *data, const uint32_t max_len) @@ -213,8 +243,6 @@ uint32_t DecodedInstructionCapstone_t::length() const return the_insn->size; } - - bool DecodedInstructionCapstone_t::isBranch() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); @@ -227,8 +255,7 @@ bool DecodedInstructionCapstone_t::isCall() const if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); const auto the_insn=static_cast<cs_insn*>(my_insn.get()); - const auto grp_it=find(ALLOF(the_insn->detail->groups), X86_GRP_CALL); - return grp_it!=end(the_insn->detail->groups); + return isPartOfGroup(the_insn,X86_GRP_CALL); } bool DecodedInstructionCapstone_t::isUnconditionalBranch() const @@ -250,8 +277,7 @@ bool DecodedInstructionCapstone_t::isReturn() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); const auto the_insn=static_cast<cs_insn*>(my_insn.get()); - const auto grp_it=find(ALLOF(the_insn->detail->groups), X86_GRP_RET); - return grp_it!=end(the_insn->detail->groups); + return isPartOfGroup(the_insn,X86_GRP_RET); } bool DecodedInstructionCapstone_t::hasOperand(const int op_num) const @@ -260,7 +286,6 @@ bool DecodedInstructionCapstone_t::hasOperand(const int op_num) const return false; } - // 0-based. first operand is numbered 0. DecodedOperandCapstone_t DecodedInstructionCapstone_t::getOperand(const int op_num) const { @@ -274,7 +299,6 @@ DecodedOperandCapstoneVector_t DecodedInstructionCapstone_t::getOperands() const assert(0); } - string DecodedInstructionCapstone_t::getMnemonic() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); @@ -323,6 +347,7 @@ string DecodedInstructionCapstone_t::getMnemonic() const } + int64_t DecodedInstructionCapstone_t::getImmediate() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); @@ -333,25 +358,36 @@ int64_t DecodedInstructionCapstone_t::getImmediate() const if(isCall() || isJmp(the_insn)) return 0; - const auto count = cs_op_count(cs_handle->getHandle(), the_insn, X86_OP_IMM); + return insnToImmedHelper<int64_t>(the_insn); +} + + +virtual_offset_t DecodedInstructionCapstone_t::getAddress() const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + + if(isCall() || isJmp(the_insn)) + return insnToImmedHelper<virtual_offset_t>(the_insn); + + + const auto count = cs_op_count(cs_handle->getHandle(), the_insn, X86_OP_MEM); const auto x86 = &(the_insn->detail->x86); if (count==0) return 0; /* no immediate is the same as an immediate of 0, i guess? */ else if (count==1) { - const auto index = cs_op_index(cs_handle->getHandle(), the_insn, X86_OP_IMM, 1); - return x86->operands[index].imm; + const auto index = cs_op_index(cs_handle->getHandle(), the_insn, X86_OP_MEM, 1); + if(x86->operands[index].mem.base==X86_REG_RIP) + return X86_REL_ADDR(*the_insn); + if(getMnemonic()=="lea") + return 0; + return x86->operands[index].mem.disp; } else - throw std::logic_error(string("Called ")+__FUNCTION__+" with number of immedaites not equal 1"); -} - - -virtual_offset_t DecodedInstructionCapstone_t::getAddress() const -{ - if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); - return 0; + return 0; } @@ -364,7 +400,12 @@ bool DecodedInstructionCapstone_t::setsStackPointer() const uint32_t DecodedInstructionCapstone_t::getPrefixCount() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); - return false; + + + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto count=count_if(ALLOF(the_insn->detail->x86.prefix), [](const uint8_t pref) { return pref!=0x0; } ) ; + const auto count_with_rex = the_insn->detail->x86.rex == 0 ? count : count + 1; + return count_with_rex; } virtual_offset_t DecodedInstructionCapstone_t::getMemoryDisplacementOffset(const DecodedOperandCapstone_t& t) const @@ -374,28 +415,33 @@ virtual_offset_t DecodedInstructionCapstone_t::getMemoryDisplacementOffset(const } -bool DecodedInstructionCapstone_t::hasRepPrefix() const + +bool DecodedInstructionCapstone_t::hasRelevantRepPrefix() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); - return false; + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + return hasPrefix(the_insn,X86_PREFIX_REP); } -bool DecodedInstructionCapstone_t::hasRepnePrefix() const +bool DecodedInstructionCapstone_t::hasRelevantRepnePrefix() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); - return false; + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + return hasPrefix(the_insn,X86_PREFIX_REPNE); } -bool DecodedInstructionCapstone_t::hasOperandSizePrefix() const +bool DecodedInstructionCapstone_t::hasRelevantOperandSizePrefix() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); - return false; + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + return hasPrefix(the_insn,X86_PREFIX_OPSIZE); } bool DecodedInstructionCapstone_t::hasRexWPrefix() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); - return false; + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + return (the_insn->detail->x86.rex & 0x7) == 0x1; } bool DecodedInstructionCapstone_t::hasImplicitlyModifiedRegs() const diff --git a/libIRDB/src/decode/decode_meta.cpp b/libIRDB/src/decode/decode_meta.cpp index 09b62262b209a2321d3774a3cac32dcb99d08549..2be068b0daea8b776ab465b98cf5eb5ff13c207f 100644 --- a/libIRDB/src/decode/decode_meta.cpp +++ b/libIRDB/src/decode/decode_meta.cpp @@ -41,6 +41,8 @@ DecodedInstructionMeta_t& DecodedInstructionMeta_t::operator=(const DecodedInstr } +void do_breakpoint(const char* s) { (void)s; } + #define passthrough_to_bea(ret_type, method_name) \ ret_type DecodedInstructionMeta_t::method_name() const \ @@ -48,6 +50,7 @@ DecodedInstructionMeta_t& DecodedInstructionMeta_t::operator=(const DecodedInstr return bea.method_name(); \ } + #define compare_decoders(ret_type, method_name) \ ret_type DecodedInstructionMeta_t::method_name() const \ { \ @@ -57,7 +60,10 @@ DecodedInstructionMeta_t& DecodedInstructionMeta_t::operator=(const DecodedInstr { \ cerr<<"Bea/Capstone miscompare: bea='"<<bea_res<<"'" \ <<" cs='"<<cs_res <<"'"; \ - cerr<<"In "<<bea.getDisassembly()<<" at " <<__FUNCTION__<<endl; \ + cerr<<" in bea="<<bea.getDisassembly(); \ + cerr<<" or cs="<<bea.getDisassembly(); \ + cerr<<" at " <<__FUNCTION__<<endl; \ + do_breakpoint(__FUNCTION__); \ } \ return cs_res; \ } @@ -71,7 +77,9 @@ DecodedInstructionMeta_t& DecodedInstructionMeta_t::operator=(const DecodedInstr { \ cerr<<"Bea/Capstone miscompare: bea='"<<bea_res<<"'" \ <<" cs='"<<cs_res <<"'"<<endl; \ - cerr<<"In "<<bea.getDisassembly()<<" at " <<__FUNCTION__<<endl; \ + cerr<<" in bea="<<bea.getDisassembly(); \ + cerr<<" or cs="<<bea.getDisassembly(); \ + cerr<<" at " <<__FUNCTION__<<endl; \ abort(); \ } \ return cs_res; \ @@ -86,7 +94,7 @@ DecodedInstructionMeta_t& DecodedInstructionMeta_t::operator=(const DecodedInstr // public methods -passthrough_to_cs(string,getDisassembly); +/* demonstrating things are the same */ compare_decoders_assert(bool, valid); compare_decoders_assert(uint32_t, length); compare_decoders_assert(bool, isBranch); @@ -94,24 +102,33 @@ compare_decoders_assert(bool, isCall); compare_decoders_assert(bool, isUnconditionalBranch); compare_decoders_assert(bool, isConditionalBranch); compare_decoders_assert(bool, isReturn); +compare_decoders_assert(uint32_t, getPrefixCount); +compare_decoders_assert(bool, hasRexWPrefix); + +/* demonstrating when capstone is better */ passthrough_to_cs(string, getMnemonic); +passthrough_to_cs(string,getDisassembly); +passthrough_to_cs(virtual_offset_t, getAddress); // bea sometimes calcs this wrong. way wrong. + +// demonstrating they different and trying to determine which is better. compare_decoders(int64_t, getImmediate); -passthrough_to_bea(virtual_offset_t, getAddress); +compare_decoders(bool, hasRelevantRepPrefix); +compare_decoders(bool, hasRelevantRepnePrefix); +compare_decoders(bool, hasRelevantOperandSizePrefix); + +// not yet completed passthrough_to_bea(bool, setsStackPointer); -passthrough_to_bea(uint32_t, getPrefixCount); -passthrough_to_bea(bool, hasRepPrefix); -passthrough_to_bea(bool, hasRepnePrefix); -passthrough_to_bea(bool, hasOperandSizePrefix); -passthrough_to_bea(bool, hasRexWPrefix); passthrough_to_bea(bool, hasImplicitlyModifiedRegs); +// needs more complicated impl. + + bool DecodedInstructionMeta_t::hasOperand(const int op_num) const { return bea.hasOperand(op_num); } - // 0-based. first operand is numbered 0. DecodedOperandMeta_t DecodedInstructionMeta_t::getOperand(const int op_num) const {