Skip to content
Snippets Groups Projects
Commit 064efd12 authored by jdh8d's avatar jdh8d
Browse files

added getAddress and hasRepPrefix support to capstone

Former-commit-id: c974a46d07b4fcdb1364f3bc23fae3a88e450032
parent 4b25a161
No related branches found
No related tags found
No related merge requests found
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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
......
......@@ -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
{
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment