From 7bb8e091ab33bcf51712be0b9e4c9bd5efc7408b Mon Sep 17 00:00:00 2001 From: Jason Hiser <jdhiser@gmail.com> Date: Tue, 18 Dec 2018 14:44:14 -0500 Subject: [PATCH] first, sorta-working ARM64 version Former-commit-id: 689b64ef83a0b5cd584a30ab1b15b43f52d377d1 --- libIRDB/include/core/decode_base.hpp | 7 + libIRDB/include/core/decode_csarm.hpp | 22 +-- libIRDB/include/core/decode_dispatch.hpp | 2 +- libIRDB/include/core/fileir.hpp | 1 + libIRDB/include/core/operand_csarm.hpp | 10 +- libIRDB/include/core/operand_dispatch.hpp | 2 +- libIRDB/src/core/SConscript | 1 + libIRDB/src/core/decode_base.cpp | 39 ++++ libIRDB/src/core/decode_csarm.cpp | 75 ++++---- libIRDB/src/core/decode_dispatch.cpp | 14 +- libIRDB/src/core/operand_csarm.cpp | 215 ++++++++++++++++------ libIRDB/src/core/operand_dispatch.cpp | 9 +- libehp | 2 +- xform/rewriter.cpp | 4 + 14 files changed, 278 insertions(+), 125 deletions(-) create mode 100644 libIRDB/src/core/decode_base.cpp diff --git a/libIRDB/include/core/decode_base.hpp b/libIRDB/include/core/decode_base.hpp index 4e53bef9c..f3aaf2e60 100644 --- a/libIRDB/include/core/decode_base.hpp +++ b/libIRDB/include/core/decode_base.hpp @@ -12,6 +12,7 @@ using namespace libIRDB; using namespace std; class DecodedOperandCapstone_t; +class DecodedInstructionDispatcher_t; typedef std::vector<shared_ptr<DecodedOperandCapstone_t> > DecodedOperandCapstoneVector_t; class DecodedInstructionCapstone_t @@ -44,6 +45,12 @@ class DecodedInstructionCapstone_t private: + static std::shared_ptr<DecodedInstructionCapstone_t> factory(const libIRDB::Instruction_t* i); + static std::shared_ptr<DecodedInstructionCapstone_t> factory(const virtual_offset_t start_addr, const void *data, uint32_t max_len); + static std::shared_ptr<DecodedInstructionCapstone_t> factory(const virtual_offset_t start_addr, const void *data, const void* endptr); + + friend class DecodedInstructionDispatcher_t; + }; } diff --git a/libIRDB/include/core/decode_csarm.hpp b/libIRDB/include/core/decode_csarm.hpp index 356386e0d..9a1201357 100644 --- a/libIRDB/include/core/decode_csarm.hpp +++ b/libIRDB/include/core/decode_csarm.hpp @@ -13,18 +13,18 @@ namespace libIRDB using namespace libIRDB; using namespace std; -class DecodedOperandCapstoneARM_t; -class DecodedInstructionCapstoneARM_t : public DecodedInstructionCapstone_t +class DecodedOperandCapstoneARM64_t; +class DecodedInstructionCapstoneARM64_t : public DecodedInstructionCapstone_t { public: - DecodedInstructionCapstoneARM_t()=delete; - DecodedInstructionCapstoneARM_t(const Instruction_t*); - DecodedInstructionCapstoneARM_t(const virtual_offset_t start_addr, const void *data, uint32_t max_len); - DecodedInstructionCapstoneARM_t(const virtual_offset_t start_addr, const void *data, const void* endptr); - DecodedInstructionCapstoneARM_t(const DecodedInstructionCapstoneARM_t& copy); - DecodedInstructionCapstoneARM_t& operator=(const DecodedInstructionCapstoneARM_t& copy); + DecodedInstructionCapstoneARM64_t()=delete; + DecodedInstructionCapstoneARM64_t(const Instruction_t*); + DecodedInstructionCapstoneARM64_t(const virtual_offset_t start_addr, const void *data, uint32_t max_len); + DecodedInstructionCapstoneARM64_t(const virtual_offset_t start_addr, const void *data, const void* endptr); + DecodedInstructionCapstoneARM64_t(const DecodedInstructionCapstoneARM64_t& copy); + DecodedInstructionCapstoneARM64_t& operator=(const DecodedInstructionCapstoneARM64_t& copy); - virtual ~DecodedInstructionCapstoneARM_t(); + virtual ~DecodedInstructionCapstoneARM64_t(); virtual string getDisassembly() const override; virtual bool valid() const override; @@ -70,9 +70,9 @@ class DecodedInstructionCapstoneARM_t : public DecodedInstructionCapstone_t static CapstoneHandle_t *cs_handle; - friend class DecodedOperandCapstoneARM_t; + friend class DecodedOperandCapstoneARM64_t; - DecodedInstructionCapstoneARM_t(const shared_ptr<void> &my_insn); + DecodedInstructionCapstoneARM64_t(const shared_ptr<void> &my_insn); }; diff --git a/libIRDB/include/core/decode_dispatch.hpp b/libIRDB/include/core/decode_dispatch.hpp index 1a5ef9f05..2e4e64b7f 100644 --- a/libIRDB/include/core/decode_dispatch.hpp +++ b/libIRDB/include/core/decode_dispatch.hpp @@ -56,7 +56,7 @@ class DecodedInstructionDispatcher_t private: - std::shared_ptr<DecodedInstructionCapstoneX86_t> cs; + std::shared_ptr<DecodedInstructionCapstone_t> cs; }; diff --git a/libIRDB/include/core/fileir.hpp b/libIRDB/include/core/fileir.hpp index c61fe787f..be61b6b23 100644 --- a/libIRDB/include/core/fileir.hpp +++ b/libIRDB/include/core/fileir.hpp @@ -94,6 +94,7 @@ class FileIR_t : public BaseObj_t static int GetArchitectureBitWidth() ; static void SetArchitecture(const int width, const ADMachineType_t mt); void SetArchitecture(); + static const ArchitectureDescription_t* GetArchitecture() { return archdesc; } // Lookup a scoop by address DataScoop_t* FindScoop(const libIRDB::virtual_offset_t &addr); diff --git a/libIRDB/include/core/operand_csarm.hpp b/libIRDB/include/core/operand_csarm.hpp index ad57f58f8..c7bbe8529 100644 --- a/libIRDB/include/core/operand_csarm.hpp +++ b/libIRDB/include/core/operand_csarm.hpp @@ -12,11 +12,11 @@ using namespace std; using namespace libIRDB; -class DecodedOperandCapstoneARM_t : public DecodedOperandCapstone_t +class DecodedOperandCapstoneARM64_t : public DecodedOperandCapstone_t { public: - DecodedOperandCapstoneARM_t() =delete; - virtual ~DecodedOperandCapstoneARM_t(); + DecodedOperandCapstoneARM64_t() =delete; + virtual ~DecodedOperandCapstoneARM64_t(); virtual bool isConstant() const override; virtual uint64_t getConstant() const override; @@ -51,12 +51,12 @@ class DecodedOperandCapstoneARM_t : public DecodedOperandCapstone_t private: - DecodedOperandCapstoneARM_t( const shared_ptr<void> &my_insn, uint8_t op_num); + DecodedOperandCapstoneARM64_t( const shared_ptr<void> &my_insn, uint8_t op_num); shared_ptr<void> my_insn; uint8_t op_num; - friend class DecodedInstructionCapstoneARM_t; + friend class DecodedInstructionCapstoneARM64_t; }; diff --git a/libIRDB/include/core/operand_dispatch.hpp b/libIRDB/include/core/operand_dispatch.hpp index 78cf5b167..e7edd8c9c 100644 --- a/libIRDB/include/core/operand_dispatch.hpp +++ b/libIRDB/include/core/operand_dispatch.hpp @@ -51,7 +51,7 @@ class DecodedOperandDispatcher_t private: DecodedOperandDispatcher_t(const shared_ptr<DecodedOperandCapstone_t> in); - std::shared_ptr<DecodedOperandCapstoneX86_t> cs; + std::shared_ptr<DecodedOperandCapstone_t> cs; friend class DecodedInstructionDispatcher_t; diff --git a/libIRDB/src/core/SConscript b/libIRDB/src/core/SConscript index 9a0381744..af03160b9 100644 --- a/libIRDB/src/core/SConscript +++ b/libIRDB/src/core/SConscript @@ -29,6 +29,7 @@ files= ''' operand_csarm.cpp IRDB_Objects.cpp decode_dispatch.cpp + decode_base.cpp operand_dispatch.cpp ''' unused_files=''' diff --git a/libIRDB/src/core/decode_base.cpp b/libIRDB/src/core/decode_base.cpp new file mode 100644 index 000000000..09a3b6aaa --- /dev/null +++ b/libIRDB/src/core/decode_base.cpp @@ -0,0 +1,39 @@ + +#include <libIRDB-core.hpp> +#include <core/decode_base.hpp> +#include <core/operand_base.hpp> +#include <core/decode_csx86.hpp> +#include <core/operand_csx86.hpp> +#include <core/decode_csarm.hpp> +#include <core/operand_csarm.hpp> +#include <exception> + +using namespace std; +using namespace libIRDB; + + +std::shared_ptr<DecodedInstructionCapstone_t> DecodedInstructionCapstone_t::factory(const libIRDB::Instruction_t* i) +{ + auto op=FileIR_t::GetArchitecture()->getMachineType()==admtAarch64 ? (DecodedInstructionCapstone_t*)new DecodedInstructionCapstoneARM64_t(i) : + FileIR_t::GetArchitecture()->getMachineType()==admtX86_64 ? (DecodedInstructionCapstone_t*)new DecodedInstructionCapstoneX86_t (i) : + FileIR_t::GetArchitecture()->getMachineType()==admtI386 ? (DecodedInstructionCapstone_t*)new DecodedInstructionCapstoneX86_t (i) : + throw invalid_argument("Unknown machine type"); + return shared_ptr<DecodedInstructionCapstone_t>(op); +} +std::shared_ptr<DecodedInstructionCapstone_t> DecodedInstructionCapstone_t::factory(const virtual_offset_t start_addr, const void *data, uint32_t max_len) +{ + auto op=FileIR_t::GetArchitecture()->getMachineType()==admtAarch64 ? (DecodedInstructionCapstone_t*)new DecodedInstructionCapstoneARM64_t(start_addr,data,max_len) : + FileIR_t::GetArchitecture()->getMachineType()==admtX86_64 ? (DecodedInstructionCapstone_t*)new DecodedInstructionCapstoneX86_t (start_addr,data,max_len) : + FileIR_t::GetArchitecture()->getMachineType()==admtI386 ? (DecodedInstructionCapstone_t*)new DecodedInstructionCapstoneX86_t (start_addr,data,max_len) : + throw invalid_argument("Unknown machine type"); + return shared_ptr<DecodedInstructionCapstone_t>(op); +} +std::shared_ptr<DecodedInstructionCapstone_t> DecodedInstructionCapstone_t::factory(const virtual_offset_t start_addr, const void *data, const void* endptr) +{ + auto op=FileIR_t::GetArchitecture()->getMachineType()==admtAarch64 ? (DecodedInstructionCapstone_t*)new DecodedInstructionCapstoneARM64_t(start_addr,data,endptr) : + FileIR_t::GetArchitecture()->getMachineType()==admtX86_64 ? (DecodedInstructionCapstone_t*)new DecodedInstructionCapstoneX86_t (start_addr,data,endptr) : + FileIR_t::GetArchitecture()->getMachineType()==admtI386 ? (DecodedInstructionCapstone_t*)new DecodedInstructionCapstoneX86_t (start_addr,data,endptr) : + throw invalid_argument("Unknown machine type"); + return shared_ptr<DecodedInstructionCapstone_t>(op); +} + diff --git a/libIRDB/src/core/decode_csarm.cpp b/libIRDB/src/core/decode_csarm.cpp index 00fc4ce30..f056121f4 100644 --- a/libIRDB/src/core/decode_csarm.cpp +++ b/libIRDB/src/core/decode_csarm.cpp @@ -14,9 +14,9 @@ using namespace std; #define ALLOF(a) begin(a),end(a) -DecodedInstructionCapstoneARM_t::CapstoneHandle_t* DecodedInstructionCapstoneARM_t::cs_handle=NULL ; +DecodedInstructionCapstoneARM64_t::CapstoneHandle_t* DecodedInstructionCapstoneARM64_t::cs_handle=NULL ; -DecodedInstructionCapstoneARM_t::CapstoneHandle_t::CapstoneHandle_t(FileIR_t* firp) +DecodedInstructionCapstoneARM64_t::CapstoneHandle_t::CapstoneHandle_t(FileIR_t* firp) { const auto mode = CS_MODE_LITTLE_ENDIAN; static_assert(sizeof(csh)==sizeof(handle), "Capstone handle size is unexpected. Has CS changed?"); @@ -53,7 +53,7 @@ template<class type> static inline type insnToImmedHelper(cs_insn* the_insn, csh handle) { const auto count = cs_op_count(handle, the_insn, ARM64_OP_IMM); - const auto arm = &(the_insn->detail->arm); + const auto arm = &(the_insn->detail->arm64); if (count==0) return 0; /* no immediate is the same as an immediate of 0, i guess? */ @@ -71,7 +71,7 @@ static inline type insnToImmedHelper(cs_insn* the_insn, csh handle) // shared code // constructors, destructors, operators. -void DecodedInstructionCapstoneARM_t::Disassemble(const virtual_offset_t start_addr, const void *data, const uint32_t max_len) +void DecodedInstructionCapstoneARM64_t::Disassemble(const virtual_offset_t start_addr, const void *data, const uint32_t max_len) { using namespace std::placeholders; auto insn=cs_malloc(cs_handle->getHandle()); @@ -92,7 +92,7 @@ void DecodedInstructionCapstoneARM_t::Disassemble(const virtual_offset_t start_a my_insn.reset(insn,cs_freer); } -DecodedInstructionCapstoneARM_t::DecodedInstructionCapstoneARM_t(const Instruction_t* i) +DecodedInstructionCapstoneARM64_t::DecodedInstructionCapstoneARM64_t(const Instruction_t* i) { if(!cs_handle) cs_handle=new CapstoneHandle_t(NULL); if(!i) throw std::invalid_argument("No instruction given to DecodedInstruction_t(Instruction_t*)"); @@ -106,35 +106,35 @@ DecodedInstructionCapstoneARM_t::DecodedInstructionCapstoneARM_t(const Instructi if(!valid()) throw std::invalid_argument("The Instruction_t::GetDataBits field is not a valid instruction."); } -DecodedInstructionCapstoneARM_t::DecodedInstructionCapstoneARM_t(const virtual_offset_t start_addr, const void *data, uint32_t max_len) +DecodedInstructionCapstoneARM64_t::DecodedInstructionCapstoneARM64_t(const virtual_offset_t start_addr, const void *data, uint32_t max_len) { if(!cs_handle) cs_handle=new CapstoneHandle_t(NULL); Disassemble(start_addr, data, max_len); } -DecodedInstructionCapstoneARM_t::DecodedInstructionCapstoneARM_t(const virtual_offset_t start_addr, const void *data, const void* endptr) +DecodedInstructionCapstoneARM64_t::DecodedInstructionCapstoneARM64_t(const virtual_offset_t start_addr, const void *data, const void* endptr) { if(!cs_handle) cs_handle=new CapstoneHandle_t(NULL); const auto length=(char*)endptr-(char*)data; Disassemble(start_addr,data,length); } -DecodedInstructionCapstoneARM_t::DecodedInstructionCapstoneARM_t(const DecodedInstructionCapstoneARM_t& copy) +DecodedInstructionCapstoneARM64_t::DecodedInstructionCapstoneARM64_t(const DecodedInstructionCapstoneARM64_t& copy) { *this=copy; } -DecodedInstructionCapstoneARM_t::DecodedInstructionCapstoneARM_t(const shared_ptr<void> &p_my_insn) +DecodedInstructionCapstoneARM64_t::DecodedInstructionCapstoneARM64_t(const shared_ptr<void> &p_my_insn) : my_insn(p_my_insn) { } -DecodedInstructionCapstoneARM_t::~DecodedInstructionCapstoneARM_t() +DecodedInstructionCapstoneARM64_t::~DecodedInstructionCapstoneARM64_t() { // no need to cs_free(my_insn) because shared pointer will do that for us! } -DecodedInstructionCapstoneARM_t& DecodedInstructionCapstoneARM_t::operator=(const DecodedInstructionCapstoneARM_t& copy) +DecodedInstructionCapstoneARM64_t& DecodedInstructionCapstoneARM64_t::operator=(const DecodedInstructionCapstoneARM64_t& copy) { my_insn=copy.my_insn; return *this; @@ -142,7 +142,7 @@ DecodedInstructionCapstoneARM_t& DecodedInstructionCapstoneARM_t::operator=(cons // public methods -string DecodedInstructionCapstoneARM_t::getDisassembly() const +string DecodedInstructionCapstoneARM64_t::getDisassembly() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); @@ -152,27 +152,27 @@ string DecodedInstructionCapstoneARM_t::getDisassembly() const return full_str; } -bool DecodedInstructionCapstoneARM_t::valid() const +bool DecodedInstructionCapstoneARM64_t::valid() const { const auto the_insn=static_cast<cs_insn*>(my_insn.get()); return the_insn->size!=0; } -uint32_t DecodedInstructionCapstoneARM_t::length() const +uint32_t DecodedInstructionCapstoneARM64_t::length() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); const auto the_insn=static_cast<cs_insn*>(my_insn.get()); return the_insn->size; } -bool DecodedInstructionCapstoneARM_t::isBranch() const +bool DecodedInstructionCapstoneARM64_t::isBranch() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); const auto the_insn=static_cast<cs_insn*>(my_insn.get()); return isCall() || isReturn() || isJmp(the_insn); } -bool DecodedInstructionCapstoneARM_t::isCall() const +bool DecodedInstructionCapstoneARM64_t::isCall() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); @@ -180,7 +180,7 @@ bool DecodedInstructionCapstoneARM_t::isCall() const return isPartOfGroup(the_insn,ARM64_GRP_CALL); } -bool DecodedInstructionCapstoneARM_t::isUnconditionalBranch() const +bool DecodedInstructionCapstoneARM64_t::isUnconditionalBranch() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); const auto the_insn=static_cast<cs_insn*>(my_insn.get()); @@ -188,39 +188,39 @@ bool DecodedInstructionCapstoneARM_t::isUnconditionalBranch() const return isJmp(the_insn) && !isConditionalBranch(); } -bool DecodedInstructionCapstoneARM_t::isConditionalBranch() const +bool DecodedInstructionCapstoneARM64_t::isConditionalBranch() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); const auto the_insn=static_cast<cs_insn*>(my_insn.get()); - return isJmp(the_insn) && getMnemonic()!="jmp"; + return isJmp(the_insn) && getMnemonic()!="br"; } -bool DecodedInstructionCapstoneARM_t::isReturn() const +bool DecodedInstructionCapstoneARM64_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()); return isPartOfGroup(the_insn,ARM64_GRP_RET); } -bool DecodedInstructionCapstoneARM_t::hasOperand(const int op_num) const +bool DecodedInstructionCapstoneARM64_t::hasOperand(const int op_num) const { if(op_num<0) throw std::logic_error(string("Called ")+ __FUNCTION__+" with opnum="+to_string(op_num)); const auto the_insn=static_cast<cs_insn*>(my_insn.get()); - const auto &arm = (the_insn->detail->arm); + const auto &arm = (the_insn->detail->arm64); return 0 <= op_num && op_num < arm.op_count; } // 0-based. first operand is numbered 0. -shared_ptr<DecodedOperandCapstone_t> DecodedInstructionCapstoneARM_t::getOperand(const int op_num) const +shared_ptr<DecodedOperandCapstone_t> DecodedInstructionCapstoneARM64_t::getOperand(const int op_num) const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); if(!hasOperand(op_num)) throw std::logic_error(string("Called ")+__FUNCTION__+" on without hasOperand()==true"); - return shared_ptr<DecodedOperandCapstone_t>(new DecodedOperandCapstoneARM_t(my_insn,(uint8_t)op_num)); + return shared_ptr<DecodedOperandCapstone_t>(new DecodedOperandCapstoneARM64_t(my_insn,(uint8_t)op_num)); } -DecodedOperandCapstoneVector_t DecodedInstructionCapstoneARM_t::getOperands() const +DecodedOperandCapstoneVector_t DecodedInstructionCapstoneARM64_t::getOperands() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); const auto the_insn=static_cast<cs_insn*>(my_insn.get()); @@ -235,7 +235,7 @@ DecodedOperandCapstoneVector_t DecodedInstructionCapstoneARM_t::getOperands() co return ret_val; } -string DecodedInstructionCapstoneARM_t::getMnemonic() const +string DecodedInstructionCapstoneARM64_t::getMnemonic() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); @@ -247,7 +247,7 @@ string DecodedInstructionCapstoneARM_t::getMnemonic() const } -int64_t DecodedInstructionCapstoneARM_t::getImmediate() const +int64_t DecodedInstructionCapstoneARM64_t::getImmediate() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); @@ -261,28 +261,31 @@ int64_t DecodedInstructionCapstoneARM_t::getImmediate() const } -virtual_offset_t DecodedInstructionCapstoneARM_t::getAddress() const +virtual_offset_t DecodedInstructionCapstoneARM64_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<int64_t>(the_insn, cs_handle->getHandle()); assert(0); } -bool DecodedInstructionCapstoneARM_t::setsStackPointer() const +bool DecodedInstructionCapstoneARM64_t::setsStackPointer() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); assert (0); } -uint32_t DecodedInstructionCapstoneARM_t::getPrefixCount() const +uint32_t DecodedInstructionCapstoneARM64_t::getPrefixCount() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); return 0; } -virtual_offset_t DecodedInstructionCapstoneARM_t::getMemoryDisplacementOffset(const DecodedOperandCapstone_t& t, const Instruction_t* insn) const +virtual_offset_t DecodedInstructionCapstoneARM64_t::getMemoryDisplacementOffset(const DecodedOperandCapstone_t& t, const Instruction_t* insn) const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); assert(0); @@ -290,31 +293,31 @@ virtual_offset_t DecodedInstructionCapstoneARM_t::getMemoryDisplacementOffset(co -bool DecodedInstructionCapstoneARM_t::hasRelevantRepPrefix() const +bool DecodedInstructionCapstoneARM64_t::hasRelevantRepPrefix() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); return false; } -bool DecodedInstructionCapstoneARM_t::hasRelevantRepnePrefix() const +bool DecodedInstructionCapstoneARM64_t::hasRelevantRepnePrefix() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); return false; } -bool DecodedInstructionCapstoneARM_t::hasRelevantOperandSizePrefix() const +bool DecodedInstructionCapstoneARM64_t::hasRelevantOperandSizePrefix() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); return false; } -bool DecodedInstructionCapstoneARM_t::hasRexWPrefix() const +bool DecodedInstructionCapstoneARM64_t::hasRexWPrefix() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); return false; } -bool DecodedInstructionCapstoneARM_t::hasImplicitlyModifiedRegs() const +bool DecodedInstructionCapstoneARM64_t::hasImplicitlyModifiedRegs() const { if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); return false; diff --git a/libIRDB/src/core/decode_dispatch.cpp b/libIRDB/src/core/decode_dispatch.cpp index 4e2c237b7..ad7fd9f87 100644 --- a/libIRDB/src/core/decode_dispatch.cpp +++ b/libIRDB/src/core/decode_dispatch.cpp @@ -10,23 +10,22 @@ using namespace std; DecodedInstructionDispatcher_t::DecodedInstructionDispatcher_t(const Instruction_t* i) { - cs.reset(new DecodedInstructionCapstoneX86_t(i)); + cs=DecodedInstructionCapstone_t::factory(i); } DecodedInstructionDispatcher_t::DecodedInstructionDispatcher_t(const virtual_offset_t start_addr, const void *data, uint32_t max_len) { - cs.reset(new DecodedInstructionCapstoneX86_t(start_addr,data,max_len)); + cs=DecodedInstructionCapstone_t::factory(start_addr,data,max_len); } DecodedInstructionDispatcher_t::DecodedInstructionDispatcher_t(const virtual_offset_t start_addr, const void *data, const void* endptr) { - cs.reset(new DecodedInstructionCapstoneX86_t(start_addr,data,endptr)); + cs=DecodedInstructionCapstone_t::factory(start_addr,data,endptr); } DecodedInstructionDispatcher_t::DecodedInstructionDispatcher_t(const DecodedInstructionDispatcher_t& copy) { - const auto copy_cs_casted=dynamic_cast<DecodedInstructionCapstoneX86_t*>(copy.cs.get()); - cs.reset(new DecodedInstructionCapstoneX86_t(*copy_cs_casted)); + cs=copy.cs; } DecodedInstructionDispatcher_t::~DecodedInstructionDispatcher_t() @@ -35,15 +34,14 @@ DecodedInstructionDispatcher_t::~DecodedInstructionDispatcher_t() DecodedInstructionDispatcher_t& DecodedInstructionDispatcher_t::operator=(const DecodedInstructionDispatcher_t& copy) { - const auto copy_cs_casted=dynamic_cast<DecodedInstructionCapstoneX86_t*>(copy.cs.get()); - cs.reset(new DecodedInstructionCapstoneX86_t(*copy_cs_casted)); + cs=copy.cs; return *this; } #define passthrough_to_cs(ret_type, method_name) \ - ret_type DecodedInstructionDispatcher_t::method_name() const \ + ret_type DecodedInstructionDispatcher_t::method_name() const \ { \ return cs->method_name(); \ } diff --git a/libIRDB/src/core/operand_csarm.cpp b/libIRDB/src/core/operand_csarm.cpp index 4ff216a5f..41be6b281 100644 --- a/libIRDB/src/core/operand_csarm.cpp +++ b/libIRDB/src/core/operand_csarm.cpp @@ -1,8 +1,8 @@ #include <libIRDB-core.hpp> #include <memory> -#include <core/operand_csx86.hpp> -#include <core/decode_csx86.hpp> +#include <core/operand_csarm.hpp> +#include <core/decode_csarm.hpp> using namespace std; using namespace libIRDB; @@ -11,7 +11,7 @@ using namespace libIRDB; -DecodedOperandCapstoneARM_t::DecodedOperandCapstoneARM_t( const shared_ptr<void> & p_my_insn, uint8_t p_op_num) +DecodedOperandCapstoneARM64_t::DecodedOperandCapstoneARM64_t( const shared_ptr<void> & p_my_insn, uint8_t p_op_num) : my_insn(p_my_insn), op_num(p_op_num) @@ -19,169 +19,272 @@ DecodedOperandCapstoneARM_t::DecodedOperandCapstoneARM_t( const shared_ptr<void> } -DecodedOperandCapstoneARM_t::~DecodedOperandCapstoneARM_t() +DecodedOperandCapstoneARM64_t::~DecodedOperandCapstoneARM64_t() { } -bool DecodedOperandCapstoneARM_t::isConstant() const +bool DecodedOperandCapstoneARM64_t::isConstant() const { const auto the_insn=static_cast<cs_insn*>(my_insn.get()); - const auto &op = (the_insn->detail->arm.operands[op_num]); - - return op.type==ARM_OP_IMM; + const auto &op = (the_insn->detail->arm64.operands[op_num]); + return op.type==ARM64_OP_IMM; } -uint64_t DecodedOperandCapstoneARM_t::getConstant() const +uint64_t DecodedOperandCapstoneARM64_t::getConstant() const { if(!isConstant()) throw std::logic_error(string("Cannot ")+__FUNCTION__+" of non-constant operand"); const auto the_insn=static_cast<cs_insn*>(my_insn.get()); - const auto &op = (the_insn->detail->arm.operands[op_num]); + const auto &op = (the_insn->detail->arm64.operands[op_num]); return op.imm; } -string DecodedOperandCapstoneARM_t::getString() const +string DecodedOperandCapstoneARM64_t::getString() const { - assert(0); + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->arm64.operands[op_num]); + const auto handle=DecodedInstructionCapstoneARM64_t::cs_handle->getHandle(); + + switch(op.type) + { + case ARM64_OP_REG: + return string(cs_reg_name(handle, op.reg)); + case ARM64_OP_IMM: + return to_string(op.imm); + case ARM64_OP_MEM: + { + string ret_val; + if (op.mem.base != ARM64_REG_INVALID) + ret_val+=cs_reg_name(handle, op.mem.base); + + if (op.mem.index != ARM64_REG_INVALID) + ret_val+=string(" + ") +cs_reg_name(handle, op.mem.index); + + if (op.mem.disp != 0) + ret_val+=" + "+ to_string(op.mem.disp); + + if(ret_val=="") + return "0"; + + return ret_val; + } + default: + assert(0); + } } -bool DecodedOperandCapstoneARM_t::isRegister() const +bool DecodedOperandCapstoneARM64_t::isRegister() const { - assert(0); + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->arm64.operands[op_num]); + return op.type==ARM64_OP_REG; } -bool DecodedOperandCapstoneARM_t::isGeneralPurposeRegister() const +bool DecodedOperandCapstoneARM64_t::isGeneralPurposeRegister() const { - assert(0); + const auto gp_regs=set<arm64_reg>({ + ARM64_REG_X29, ARM64_REG_X30, ARM64_REG_SP, ARM64_REG_WSP, ARM64_REG_WZR, ARM64_REG_XZR, + ARM64_REG_W0, ARM64_REG_W1, ARM64_REG_W2, ARM64_REG_W3, ARM64_REG_W4, ARM64_REG_W5, ARM64_REG_W6, ARM64_REG_W7, + ARM64_REG_W8, ARM64_REG_W9, ARM64_REG_W10, ARM64_REG_W11, ARM64_REG_W12, ARM64_REG_W13, ARM64_REG_W14, ARM64_REG_W15, + ARM64_REG_W16, ARM64_REG_W17, ARM64_REG_W18, ARM64_REG_W19, ARM64_REG_W20, ARM64_REG_W21, ARM64_REG_W22, ARM64_REG_W23, + ARM64_REG_W24, ARM64_REG_W25, ARM64_REG_W26, ARM64_REG_W27, ARM64_REG_W28, ARM64_REG_W29, ARM64_REG_W30, + ARM64_REG_X0, ARM64_REG_X1, ARM64_REG_X2, ARM64_REG_X3, ARM64_REG_X4, ARM64_REG_X5, ARM64_REG_X6, ARM64_REG_X7, + ARM64_REG_X8, ARM64_REG_X9, ARM64_REG_X10, ARM64_REG_X11, ARM64_REG_X12, ARM64_REG_X13, ARM64_REG_X14, ARM64_REG_X15, + ARM64_REG_X16, ARM64_REG_X17, ARM64_REG_X18, ARM64_REG_X19, ARM64_REG_X20, ARM64_REG_X21, ARM64_REG_X22, ARM64_REG_X23, + ARM64_REG_X24, ARM64_REG_X25, ARM64_REG_X26, ARM64_REG_X27, ARM64_REG_X28, + }); + + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->arm64.operands[op_num]); + return isRegister() && gp_regs.find(op.reg)!=end(gp_regs); + } -bool DecodedOperandCapstoneARM_t::isMmxRegister() const +bool DecodedOperandCapstoneARM64_t::isMmxRegister() const { return false; } -bool DecodedOperandCapstoneARM_t::isFpuRegister() const +bool DecodedOperandCapstoneARM64_t::isFpuRegister() const { - return false; + const auto fpu_regs=set<arm64_reg>({ + ARM64_REG_B0, ARM64_REG_B1, ARM64_REG_B2, ARM64_REG_B3, ARM64_REG_B4, ARM64_REG_B5, ARM64_REG_B6, ARM64_REG_B7, + ARM64_REG_B8, ARM64_REG_B9, ARM64_REG_B10, ARM64_REG_B11, ARM64_REG_B12, ARM64_REG_B13, ARM64_REG_B14, ARM64_REG_B15, + ARM64_REG_B16, ARM64_REG_B17, ARM64_REG_B18, ARM64_REG_B19, ARM64_REG_B20, ARM64_REG_B21, ARM64_REG_B22, ARM64_REG_B23, + ARM64_REG_B24, ARM64_REG_B25, ARM64_REG_B26, ARM64_REG_B27, ARM64_REG_B28, ARM64_REG_B29, ARM64_REG_B30, ARM64_REG_B31, + ARM64_REG_H0, ARM64_REG_H1, ARM64_REG_H2, ARM64_REG_H3, ARM64_REG_H4, ARM64_REG_H5, ARM64_REG_H6, ARM64_REG_H7, + ARM64_REG_H8, ARM64_REG_H9, ARM64_REG_H10, ARM64_REG_H11, ARM64_REG_H12, ARM64_REG_H13, ARM64_REG_H14, ARM64_REG_H15, + ARM64_REG_H16, ARM64_REG_H17, ARM64_REG_H18, ARM64_REG_H19, ARM64_REG_H20, ARM64_REG_H21, ARM64_REG_H22, ARM64_REG_H23, + ARM64_REG_H24, ARM64_REG_H25, ARM64_REG_H26, ARM64_REG_H27, ARM64_REG_H28, ARM64_REG_H29, ARM64_REG_H30, ARM64_REG_H31, + ARM64_REG_D0, ARM64_REG_D1, ARM64_REG_D2, ARM64_REG_D3, ARM64_REG_D4, ARM64_REG_D5, ARM64_REG_D6, ARM64_REG_D7, + ARM64_REG_D8, ARM64_REG_D9, ARM64_REG_D10, ARM64_REG_D11, ARM64_REG_D12, ARM64_REG_D13, ARM64_REG_D14, ARM64_REG_D15, + ARM64_REG_D16, ARM64_REG_D17, ARM64_REG_D18, ARM64_REG_D19, ARM64_REG_D20, ARM64_REG_D21, ARM64_REG_D22, ARM64_REG_D23, + ARM64_REG_D24, ARM64_REG_D25, ARM64_REG_D26, ARM64_REG_D27, ARM64_REG_D28, ARM64_REG_D29, ARM64_REG_D30, ARM64_REG_D31, + ARM64_REG_H0, ARM64_REG_H1, ARM64_REG_H2, ARM64_REG_H3, ARM64_REG_H4, ARM64_REG_H5, ARM64_REG_H6, ARM64_REG_H7, + ARM64_REG_H8, ARM64_REG_H9, ARM64_REG_H10, ARM64_REG_H11, ARM64_REG_H12, ARM64_REG_H13, ARM64_REG_H14, ARM64_REG_H15, + ARM64_REG_H16, ARM64_REG_H17, ARM64_REG_H18, ARM64_REG_H19, ARM64_REG_H20, ARM64_REG_H21, ARM64_REG_H22, ARM64_REG_H23, + ARM64_REG_H24, ARM64_REG_H25, ARM64_REG_H26, ARM64_REG_H27, ARM64_REG_H28, ARM64_REG_H29, ARM64_REG_H30, ARM64_REG_H31, + ARM64_REG_Q0, ARM64_REG_Q1, ARM64_REG_Q2, ARM64_REG_Q3, ARM64_REG_Q4, ARM64_REG_Q5, ARM64_REG_Q6, ARM64_REG_Q7, + ARM64_REG_Q8, ARM64_REG_Q9, ARM64_REG_Q10, ARM64_REG_Q11, ARM64_REG_Q12, ARM64_REG_Q13, ARM64_REG_Q14, ARM64_REG_Q15, + ARM64_REG_Q16, ARM64_REG_Q17, ARM64_REG_Q18, ARM64_REG_Q19, ARM64_REG_Q20, ARM64_REG_Q21, ARM64_REG_Q22, ARM64_REG_Q23, + ARM64_REG_Q24, ARM64_REG_Q25, ARM64_REG_Q26, ARM64_REG_Q27, ARM64_REG_Q28, ARM64_REG_Q29, ARM64_REG_Q30, ARM64_REG_Q31, + ARM64_REG_S0, ARM64_REG_S1, ARM64_REG_S2, ARM64_REG_S3, ARM64_REG_S4, ARM64_REG_S5, ARM64_REG_S6, ARM64_REG_S7, + ARM64_REG_S8, ARM64_REG_S9, ARM64_REG_S10, ARM64_REG_S11, ARM64_REG_S12, ARM64_REG_S13, ARM64_REG_S14, ARM64_REG_S15, + ARM64_REG_S16, ARM64_REG_S17, ARM64_REG_S18, ARM64_REG_S19, ARM64_REG_S20, ARM64_REG_S21, ARM64_REG_S22, ARM64_REG_S23, + ARM64_REG_S24, ARM64_REG_S25, ARM64_REG_S26, ARM64_REG_S27, ARM64_REG_S28, ARM64_REG_S29, ARM64_REG_S30, ARM64_REG_S31, + }); + + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->arm64.operands[op_num]); + return isRegister() && fpu_regs.find(op.reg)!=end(fpu_regs); } -bool DecodedOperandCapstoneARM_t::isSseRegister() const +bool DecodedOperandCapstoneARM64_t::isSseRegister() const { return false; } -bool DecodedOperandCapstoneARM_t::isAvxRegister() const +bool DecodedOperandCapstoneARM64_t::isAvxRegister() const { return false; } -bool DecodedOperandCapstoneARM_t::isZmmRegister() const +bool DecodedOperandCapstoneARM64_t::isZmmRegister() const { return false; } -bool DecodedOperandCapstoneARM_t::isSpecialRegister() const +bool DecodedOperandCapstoneARM64_t::isSpecialRegister() const { + const auto special_regs=set<arm64_reg>({ + ARM64_REG_NZCV, + }); + + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->arm64.operands[op_num]); + return isRegister() && special_regs.find(op.reg)!=end(special_regs); return false; } -bool DecodedOperandCapstoneARM_t::isSegmentRegister() const +bool DecodedOperandCapstoneARM64_t::isSegmentRegister() const { return false; } -uint32_t DecodedOperandCapstoneARM_t::getRegNumber() const +uint32_t DecodedOperandCapstoneARM64_t::getRegNumber() const { - assert(0); + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->arm64.operands[op_num]); + return op.reg; } -bool DecodedOperandCapstoneARM_t::isMemory() const +bool DecodedOperandCapstoneARM64_t::isMemory() const { - assert(0); + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->arm64.operands[op_num]); + return op.type==ARM64_OP_MEM; + } -bool DecodedOperandCapstoneARM_t::hasBaseRegister() const +bool DecodedOperandCapstoneARM64_t::hasBaseRegister() const { - assert(0); + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->arm64.operands[op_num]); + return isMemory() && op.mem.base!=ARM64_REG_INVALID; + } -bool DecodedOperandCapstoneARM_t::hasIndexRegister() const +bool DecodedOperandCapstoneARM64_t::hasIndexRegister() const { - assert(0); + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->arm64.operands[op_num]); + return isMemory() && op.mem.index!=ARM64_REG_INVALID; } -uint32_t DecodedOperandCapstoneARM_t::getBaseRegister() const +uint32_t DecodedOperandCapstoneARM64_t::getBaseRegister() const { - assert(0); + if(!isMemory()) throw std::logic_error(string("Cannot ")+__FUNCTION__+" of non-memory operand"); + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->arm64.operands[op_num]); + return op.mem.base; } -uint32_t DecodedOperandCapstoneARM_t::getIndexRegister() const +uint32_t DecodedOperandCapstoneARM64_t::getIndexRegister() const { - assert(0); + if(!isMemory()) throw std::logic_error(string("Cannot ")+__FUNCTION__+" of non-memory operand"); + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->arm64.operands[op_num]); + return op.mem.index; } -uint32_t DecodedOperandCapstoneARM_t::getScaleValue() const +uint32_t DecodedOperandCapstoneARM64_t::getScaleValue() const { assert(0); } -bool DecodedOperandCapstoneARM_t::hasMemoryDisplacement() const +bool DecodedOperandCapstoneARM64_t::hasMemoryDisplacement() const { - assert(0); + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->arm64.operands[op_num]); + return op.mem.disp!=0; -} // end of DecodedOperandCapstoneARM_t::hasMemoryDisplacement() +} // end of DecodedOperandCapstoneARM64_t::hasMemoryDisplacement() -virtual_offset_t DecodedOperandCapstoneARM_t::getMemoryDisplacement() const +virtual_offset_t DecodedOperandCapstoneARM64_t::getMemoryDisplacement() const { - assert(0); + if(!isMemory()) throw std::logic_error(string("Cannot ")+__FUNCTION__+" of non-memory operand"); + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->arm64.operands[op_num]); + return op.mem.disp; } -bool DecodedOperandCapstoneARM_t::isPcrel() const +bool DecodedOperandCapstoneARM64_t::isPcrel() const { - assert(0); + if(!isMemory()) return false; + return false; // no PC as general purpose reg. } /* in bytes */ -uint32_t DecodedOperandCapstoneARM_t::getMemoryDisplacementEncodingSize() const +uint32_t DecodedOperandCapstoneARM64_t::getMemoryDisplacementEncodingSize() const { if(!isMemory()) throw std::logic_error(string("Cannot ")+__FUNCTION__+" of non-memory operand"); assert(0); } -uint32_t DecodedOperandCapstoneARM_t::getArgumentSizeInBytes() const +uint32_t DecodedOperandCapstoneARM64_t::getArgumentSizeInBytes() const { - assert(0); + return false; } -uint32_t DecodedOperandCapstoneARM_t::getArgumentSizeInBits() const +uint32_t DecodedOperandCapstoneARM64_t::getArgumentSizeInBits() const { - assert(0); + return getArgumentSizeInBytes()*8; } -bool DecodedOperandCapstoneARM_t::hasSegmentRegister() const +bool DecodedOperandCapstoneARM64_t::hasSegmentRegister() const { return false; } -uint32_t DecodedOperandCapstoneARM_t::getSegmentRegister() const +uint32_t DecodedOperandCapstoneARM64_t::getSegmentRegister() const { - assert(0); + throw std::logic_error(string("Cannot ")+__FUNCTION__+" on ARM architecture"); } -bool DecodedOperandCapstoneARM_t::isRead() const +bool DecodedOperandCapstoneARM64_t::isRead() const { const auto the_insn=static_cast<cs_insn*>(my_insn.get()); - const auto &op = (the_insn->detail->arm.operands[op_num]); + const auto &op = (the_insn->detail->arm64.operands[op_num]); return (op.access & CS_AC_READ)!=0; } -bool DecodedOperandCapstoneARM_t::isWritten() const +bool DecodedOperandCapstoneARM64_t::isWritten() const { // default: use capstone's advice. const auto the_insn=static_cast<cs_insn*>(my_insn.get()); - const auto &op = (the_insn->detail->x86.operands[op_num]); + const auto &op = (the_insn->detail->arm64.operands[op_num]); return (op.access & CS_AC_WRITE)!=0; } diff --git a/libIRDB/src/core/operand_dispatch.cpp b/libIRDB/src/core/operand_dispatch.cpp index 3c37b8222..bf6c75146 100644 --- a/libIRDB/src/core/operand_dispatch.cpp +++ b/libIRDB/src/core/operand_dispatch.cpp @@ -10,14 +10,12 @@ using namespace libIRDB; DecodedOperandDispatcher_t::DecodedOperandDispatcher_t(const shared_ptr<DecodedOperandCapstone_t> copy_cs) { - const auto copy_cs_casted=dynamic_cast<DecodedOperandCapstoneX86_t*>(copy_cs.get()); - cs.reset(new DecodedOperandCapstoneX86_t(*copy_cs_casted)); + cs=copy_cs; } DecodedOperandDispatcher_t::DecodedOperandDispatcher_t(const DecodedOperandDispatcher_t& copy) { - const auto copy_cs_casted=dynamic_cast<DecodedOperandCapstoneX86_t*>(copy.cs.get()); - cs.reset(new DecodedOperandCapstoneX86_t(*copy_cs_casted)); + cs=copy.cs; } DecodedOperandDispatcher_t::~DecodedOperandDispatcher_t() @@ -26,8 +24,7 @@ DecodedOperandDispatcher_t::~DecodedOperandDispatcher_t() DecodedOperandDispatcher_t& DecodedOperandDispatcher_t::operator=(const DecodedOperandDispatcher_t& copy) { - const auto copy_cs_casted=dynamic_cast<DecodedOperandCapstoneX86_t*>(copy.cs.get()); - cs.reset(new DecodedOperandCapstoneX86_t(*copy_cs_casted)); + cs=copy.cs; return *this; } diff --git a/libehp b/libehp index 844394fef..bd396bff6 160000 --- a/libehp +++ b/libehp @@ -1 +1 @@ -Subproject commit 844394fefeb8197007510824e71c905dafb0e5d9 +Subproject commit bd396bff642ca89bc4c169749f721d8652ec8b79 diff --git a/xform/rewriter.cpp b/xform/rewriter.cpp index e31f2d9c5..fed74f5a9 100644 --- a/xform/rewriter.cpp +++ b/xform/rewriter.cpp @@ -639,6 +639,7 @@ void Rewriter::readElfFile(char p_filename[]) if(!objdump) objdump=strdup("objdump"); sprintf(buf, "%s -d --prefix-addresses %s | grep \"^[0-9]\"", objdump, p_filename); + printf("Running objdump, like so: %s\n", buf); FILE* pin=popen(buf, "r"); app_iaddr_t addr; @@ -652,7 +653,10 @@ void Rewriter::readElfFile(char p_filename[]) do { if(m_instructions[addr]==NULL) + { + cout<<"Found instruction from objdump at "<<hex<<addr<<endl; m_instructions[addr]=new wahoo::Instruction(addr,-1,NULL); + } ignore_result(fscanf(pin,"%p", &tmp)); addr=(app_iaddr_t)tmp; ignore_result(fgets(buf,sizeof(buf),pin)); -- GitLab