diff --git a/SConscript b/SConscript index 34ced56d3f98c6f75632d0efb441f0fb03a4e6a9..65f9d965e8023c3dca4117234a3a4b0015f43107 100644 --- a/SConscript +++ b/SConscript @@ -25,9 +25,6 @@ if not os.path.isfile("manifest.txt.config"): libirdb= SConscript("irdb-libs/SConscript") libsmpsa= SConscript("SMPStaticAnalyzer/SConscript") -# specify some explicit dependencies to make sure these build in order -Depends(libsmpsa,libirdb) - # now finish building irdb-libs once stars is setup libirdbdeep=SConscript("irdb-libs/SConscript.deep") Depends(libirdbdeep,libsmpsa) diff --git a/SMPStaticAnalyzer b/SMPStaticAnalyzer index 99ca54f01ec147cb30aaeec1b03f0158b4c5e370..8c405f65d2a77cb76d9239e8829594a71ffeb8ac 160000 --- a/SMPStaticAnalyzer +++ b/SMPStaticAnalyzer @@ -1 +1 @@ -Subproject commit 99ca54f01ec147cb30aaeec1b03f0158b4c5e370 +Subproject commit 8c405f65d2a77cb76d9239e8829594a71ffeb8ac diff --git a/irdb-libs/libEXEIO/include/exeio.h b/irdb-libs/libEXEIO/include/exeio.h index 1bb3a06d56c6f2f7ddf745f014f2c5c8ffb02fb2..f9057d3dc64f1a8002dcfaaffcd8f9fd0e73c751 100644 --- a/irdb-libs/libEXEIO/include/exeio.h +++ b/irdb-libs/libEXEIO/include/exeio.h @@ -13,7 +13,7 @@ namespace EXEIO class exeio_t; // forward decl typedef enum { ELF64, ELF32, PE32, PE64 } execlass_t; - typedef enum { mtX86_64, mtI386, mtArm32, mtAarch64 } MachineType_t; + typedef enum { mtX86_64, mtI386, mtArm32, mtAarch64, mtMips32, mtMips64 } MachineType_t; typedef uintptr_t virtual_offset_t; diff --git a/irdb-libs/libEXEIO/src/exeio_elf.h b/irdb-libs/libEXEIO/src/exeio_elf.h index cd2230b757b674a77aff6ab723d9ccdd1327a76d..fcd07c6b5d786cce3e9ab224f1373952f4686f2f 100644 --- a/irdb-libs/libEXEIO/src/exeio_elf.h +++ b/irdb-libs/libEXEIO/src/exeio_elf.h @@ -98,6 +98,7 @@ namespace EXEIO assert(e); switch(e->get_machine()) { + case EM_MIPS : return mtMips32; case EM_ARM : return mtArm32; case EM_AARCH64 : return mtAarch64; case EM_386 : return mtI386; diff --git a/irdb-libs/libIRDB-core/include/decode_csmips.hpp b/irdb-libs/libIRDB-core/include/decode_csmips.hpp new file mode 100644 index 0000000000000000000000000000000000000000..cfad0e36e22b77a628edb1e879524ad609c7a477 --- /dev/null +++ b/irdb-libs/libIRDB-core/include/decode_csmips.hpp @@ -0,0 +1,143 @@ + +namespace libIRDB +{ + + using namespace libIRDB; + using namespace std; + + class DecodedOperandCapstoneMIPS_t; + class DecodedInstructionCapstoneMIPS_t : virtual public IRDB_SDK::DecodedInstruction_t + { + public: + DecodedInstructionCapstoneMIPS_t& operator=(const DecodedInstructionCapstoneMIPS_t& copy) + { + my_insn = copy.my_insn; + return *this; + } + + virtual ~DecodedInstructionCapstoneMIPS_t() { } + + protected: + DecodedInstructionCapstoneMIPS_t() + { + if(!cs_handle) cs_handle=new CapstoneHandle_t(NULL); + } + + shared_ptr<void> my_insn; + + class CapstoneHandle_t + { + public: + CapstoneHandle_t(FileIR_t* firp=NULL); + inline unsigned long getHandle() { return handle; } + + private: + // csh handle; # this is the real type, but it's an alias and I don't want to export capstone values. + unsigned long handle; + }; + static CapstoneHandle_t *cs_handle; + + friend class IRDB_SDK::DecodedInstruction_t; + friend class DecodedOperandCapstoneMIPS_t; + }; + + class DecodedOperandCapstoneMIPS32_t; + class DecodedInstructionCapstoneMIPS32_t : public DecodedInstructionCapstoneMIPS_t + { + public: + DecodedInstructionCapstoneMIPS32_t()=delete; + DecodedInstructionCapstoneMIPS32_t& operator=(const DecodedInstructionCapstoneMIPS32_t& copy); + + virtual ~DecodedInstructionCapstoneMIPS32_t(); + + virtual string getDisassembly() const override; + virtual bool valid() const override; + virtual uint32_t length() const override; + virtual bool isBranch() const override; + virtual bool isCall() const override; + virtual bool isUnconditionalBranch() const override; + virtual bool isConditionalBranch() const override; + virtual bool isReturn() const override; + virtual string getMnemonic() const override; + virtual int64_t getImmediate() const override; + virtual virtual_offset_t getAddress() const override; + virtual bool setsStackPointer() const override; + virtual uint32_t getPrefixCount() const override; + virtual bool hasRelevantRepPrefix() const override; + virtual bool hasRelevantRepnePrefix() const override; + virtual bool hasRelevantOperandSizePrefix() const override; + virtual bool hasRexWPrefix() const override; + virtual bool hasImplicitlyModifiedRegs() const override; + virtual IRDB_SDK::VirtualOffset_t getMemoryDisplacementOffset(const DecodedOperand_t* t, const IRDB_SDK::Instruction_t* insn) const override; + + // 0-based. first operand is numbered 0. + virtual bool hasOperand(const int op_num) const override; + virtual std::shared_ptr<DecodedOperand_t> getOperand(const int op_num) const override; + virtual DecodedOperandVector_t getOperands() const override; + + protected: + + void Disassemble(const virtual_offset_t start_addr, const void *data, const uint32_t max_len); + + private: + DecodedInstructionCapstoneMIPS32_t(const shared_ptr<void> &my_insn) ; + DecodedInstructionCapstoneMIPS32_t(const Instruction_t* my_insn) ; + DecodedInstructionCapstoneMIPS32_t(const virtual_offset_t sa, const void *data, uint32_t max_len ) ; + DecodedInstructionCapstoneMIPS32_t(const virtual_offset_t sa, const void *data, const void* endptr) ; + DecodedInstructionCapstoneMIPS32_t(const DecodedInstructionCapstoneMIPS32_t& copy) ; + + friend class IRDB_SDK::DecodedInstruction_t; + friend class DecodedOperandCapstoneMIPS32_t; + }; + + class DecodedOperandCapstoneMIPS64_t; + class DecodedInstructionCapstoneMIPS64_t : public DecodedInstructionCapstoneMIPS_t + { + public: + DecodedInstructionCapstoneMIPS64_t()=delete; + DecodedInstructionCapstoneMIPS64_t& operator=(const DecodedInstructionCapstoneMIPS64_t& copy); + + virtual ~DecodedInstructionCapstoneMIPS64_t(); + + virtual string getDisassembly() const override; + virtual bool valid() const override; + virtual uint32_t length() const override; + virtual bool isBranch() const override; + virtual bool isCall() const override; + virtual bool isUnconditionalBranch() const override; + virtual bool isConditionalBranch() const override; + virtual bool isReturn() const override; + virtual string getMnemonic() const override; + virtual int64_t getImmediate() const override; + virtual virtual_offset_t getAddress() const override; + virtual bool setsStackPointer() const override; + virtual uint32_t getPrefixCount() const override; + virtual bool hasRelevantRepPrefix() const override; + virtual bool hasRelevantRepnePrefix() const override; + virtual bool hasRelevantOperandSizePrefix() const override; + virtual bool hasRexWPrefix() const override; + virtual bool hasImplicitlyModifiedRegs() const override; + virtual IRDB_SDK::VirtualOffset_t getMemoryDisplacementOffset(const DecodedOperand_t* t, const IRDB_SDK::Instruction_t* insn) const override; + + // 0-based. first operand is numbered 0. + virtual bool hasOperand(const int op_num) const override; + virtual std::shared_ptr<DecodedOperand_t> getOperand(const int op_num) const override; + virtual DecodedOperandVector_t getOperands() const override; + + protected: + + void Disassemble(const virtual_offset_t start_addr, const void *data, const uint32_t max_len); + + private: + DecodedInstructionCapstoneMIPS64_t(const shared_ptr<void> &my_insn) ; + DecodedInstructionCapstoneMIPS64_t(const Instruction_t*) ; + DecodedInstructionCapstoneMIPS64_t(const virtual_offset_t sa, const void *data, uint32_t max_len ) ; + DecodedInstructionCapstoneMIPS64_t(const virtual_offset_t sa, const void *data, const void* endptr) ; + DecodedInstructionCapstoneMIPS64_t(const DecodedInstructionCapstoneMIPS64_t& copy) ; + + friend class IRDB_SDK::DecodedInstruction_t; + friend class DecodedOperandCapstoneMIPS64_t; + }; + +} + diff --git a/irdb-libs/libIRDB-core/include/operand_csmips.hpp b/irdb-libs/libIRDB-core/include/operand_csmips.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6df2bf2cf6d28838f48f3f91742418d9435d3141 --- /dev/null +++ b/irdb-libs/libIRDB-core/include/operand_csmips.hpp @@ -0,0 +1,107 @@ + +namespace libIRDB +{ + + using namespace std; + using namespace libIRDB; + + class DecodedOperandCapstoneMIPS_t : virtual public IRDB_SDK::DecodedOperand_t + { + public: + DecodedOperandCapstoneMIPS_t() =delete; + virtual ~DecodedOperandCapstoneMIPS_t() { } + + protected: + + DecodedOperandCapstoneMIPS_t( const shared_ptr<void> &p_my_insn, uint8_t p_op_num) + : my_insn(p_my_insn), op_num(p_op_num) + { + } + + shared_ptr<void> my_insn; + uint8_t op_num; + + friend class DecodedInstructionCapstoneMIPS_t; + }; + + class DecodedOperandCapstoneMIPS32_t : public DecodedOperandCapstoneMIPS_t + { + public: + DecodedOperandCapstoneMIPS32_t() =delete; + virtual ~DecodedOperandCapstoneMIPS32_t(); + virtual bool isConstant() const override; + virtual uint64_t getConstant() const override; + virtual string getString() const override; + virtual bool isRegister() const override; + virtual bool isGeneralPurposeRegister() const override; + virtual bool isMmxRegister() const override; + virtual bool isFpuRegister() const override; + virtual bool isSseRegister() const override; + virtual bool isAvxRegister() const override; + virtual bool isZmmRegister() const override; + virtual bool isSpecialRegister() const override; + virtual bool isSegmentRegister() const override; + virtual uint32_t getRegNumber() const override; + virtual bool isMemory() const override; + virtual bool hasSegmentRegister() const override; + virtual uint32_t getSegmentRegister() const override; + virtual bool hasBaseRegister() const override; + virtual bool hasIndexRegister() const override; + virtual uint32_t getBaseRegister() const override; + virtual uint32_t getIndexRegister() const override; + virtual bool hasMemoryDisplacement() const override; + virtual virtual_offset_t getMemoryDisplacement() const override; + virtual bool isPcrel() const override; + virtual uint32_t getScaleValue() const override; + virtual uint32_t getMemoryDisplacementEncodingSize() const override; + virtual uint32_t getArgumentSizeInBytes() const override; + virtual uint32_t getArgumentSizeInBits() const override; + virtual bool isRead() const override; + virtual bool isWritten() const override; + private: + DecodedOperandCapstoneMIPS32_t( const shared_ptr<void> &p_my_insn, uint8_t p_op_num); + friend class DecodedInstructionCapstoneMIPS32_t; + + + }; + + class DecodedOperandCapstoneMIPS64_t : public DecodedOperandCapstoneMIPS_t + { + public: + DecodedOperandCapstoneMIPS64_t() =delete; + virtual ~DecodedOperandCapstoneMIPS64_t(); + virtual bool isConstant() const override; + virtual uint64_t getConstant() const override; + virtual string getString() const override; + virtual bool isRegister() const override; + virtual bool isGeneralPurposeRegister() const override; + virtual bool isMmxRegister() const override; + virtual bool isFpuRegister() const override; + virtual bool isSseRegister() const override; + virtual bool isAvxRegister() const override; + virtual bool isZmmRegister() const override; + virtual bool isSpecialRegister() const override; + virtual bool isSegmentRegister() const override; + virtual uint32_t getRegNumber() const override; + virtual bool isMemory() const override; + virtual bool hasSegmentRegister() const override; + virtual uint32_t getSegmentRegister() const override; + virtual bool hasBaseRegister() const override; + virtual bool hasIndexRegister() const override; + virtual uint32_t getBaseRegister() const override; + virtual uint32_t getIndexRegister() const override; + virtual bool hasMemoryDisplacement() const override; + virtual virtual_offset_t getMemoryDisplacement() const override; + virtual bool isPcrel() const override; + virtual uint32_t getScaleValue() const override; + virtual uint32_t getMemoryDisplacementEncodingSize() const override; + virtual uint32_t getArgumentSizeInBytes() const override; + virtual uint32_t getArgumentSizeInBits() const override; + virtual bool isRead() const override; + virtual bool isWritten() const override; + + private: + DecodedOperandCapstoneMIPS64_t( const shared_ptr<void> &p_my_insn, uint8_t p_op_num); + friend class DecodedInstructionCapstoneMIPS64_t; + }; +} diff --git a/irdb-libs/libIRDB-core/src/SConscript b/irdb-libs/libIRDB-core/src/SConscript index 8e67fe4f1c16b57fd27ecbb2c931535b5b98d458..2ebee5283f22a3f2345194b85ed2bf0e9bcddbbd 100644 --- a/irdb-libs/libIRDB-core/src/SConscript +++ b/irdb-libs/libIRDB-core/src/SConscript @@ -24,9 +24,11 @@ files= ''' eh.cpp reloc.cpp decode_csx86.cpp - operand_csx86.cpp + decode_csmips32.cpp decode_csarm32.cpp decode_csarm64.cpp + operand_csx86.cpp + operand_csmips32.cpp operand_csarm32.cpp operand_csarm64.cpp IRDB_Objects.cpp diff --git a/irdb-libs/libIRDB-core/src/decode_base.cpp b/irdb-libs/libIRDB-core/src/decode_base.cpp index 3790cc0e12245c9111455a5931127507bc593422..23e83fd440c3555b166af72b1afd8e2e7c2b32d3 100644 --- a/irdb-libs/libIRDB-core/src/decode_base.cpp +++ b/irdb-libs/libIRDB-core/src/decode_base.cpp @@ -6,6 +6,8 @@ #include <operand_csx86.hpp> #include <decode_csarm.hpp> #include <operand_csarm.hpp> +#include <decode_csmips.hpp> +#include <operand_csmips.hpp> #include <exception> using namespace std; @@ -16,30 +18,36 @@ unique_ptr<IRDB_SDK::DecodedInstruction_t> IRDB_SDK::DecodedInstruction_t::facto { const auto i=dynamic_cast<const libIRDB::Instruction_t*>(p_i); assert(i); - auto op = IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtArm32 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneARM32_t(i) : - IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtAarch64 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneARM64_t(i) : - IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtX86_64 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneX86_t (i) : - IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtI386 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneX86_t (i) : + auto op = + IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtMips32 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneMIPS32_t(i) : + IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtArm32 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneARM32_t (i) : + IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtAarch64 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneARM64_t (i) : + IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtX86_64 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneX86_t (i) : + IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtI386 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneX86_t (i) : throw invalid_argument("Unknown machine type"); return unique_ptr<DecodedInstruction_t>(op); } unique_ptr<IRDB_SDK::DecodedInstruction_t> IRDB_SDK::DecodedInstruction_t::factory(const IRDB_SDK::VirtualOffset_t start_addr, const void *data, uint32_t max_len) { - auto op = IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtArm32 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneARM32_t(start_addr,data,max_len) : - IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtAarch64 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneARM64_t(start_addr,data,max_len) : - IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtX86_64 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneX86_t (start_addr,data,max_len) : - IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtI386 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneX86_t (start_addr,data,max_len) : + auto op = + IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtMips32 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneMIPS32_t(start_addr,data,max_len) : + IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtArm32 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneARM32_t (start_addr,data,max_len) : + IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtAarch64 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneARM64_t (start_addr,data,max_len) : + IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtX86_64 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneX86_t (start_addr,data,max_len) : + IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtI386 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneX86_t (start_addr,data,max_len) : throw invalid_argument("Unknown machine type"); return unique_ptr<DecodedInstruction_t>(op); } unique_ptr<IRDB_SDK::DecodedInstruction_t> IRDB_SDK::DecodedInstruction_t::factory(const IRDB_SDK::VirtualOffset_t start_addr, const void *data, const void* endptr) { - auto op = IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtArm32 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneARM32_t(start_addr,data,endptr) : - IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtAarch64 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneARM64_t(start_addr,data,endptr) : - IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtX86_64 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneX86_t (start_addr,data,endptr) : - IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtI386 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneX86_t (start_addr,data,endptr) : + auto op = + IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtMips32 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneMIPS32_t(start_addr,data,endptr) : + IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtArm32 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneARM32_t (start_addr,data,endptr) : + IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtAarch64 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneARM64_t (start_addr,data,endptr) : + IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtX86_64 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneX86_t (start_addr,data,endptr) : + IRDB_SDK::FileIR_t::getArchitecture()->getMachineType()==IRDB_SDK::admtI386 ? (IRDB_SDK::DecodedInstruction_t*)new DecodedInstructionCapstoneX86_t (start_addr,data,endptr) : throw invalid_argument("Unknown machine type"); return unique_ptr<DecodedInstruction_t>(op); } diff --git a/irdb-libs/libIRDB-core/src/decode_csmips32.cpp b/irdb-libs/libIRDB-core/src/decode_csmips32.cpp new file mode 100644 index 0000000000000000000000000000000000000000..45a1fe84928e7d7d4942a26abfcd54058eaadb79 --- /dev/null +++ b/irdb-libs/libIRDB-core/src/decode_csmips32.cpp @@ -0,0 +1,304 @@ + +#include <libIRDB-core.hpp> +#include <decode_base.hpp> +#include <decode_csmips.hpp> +#include <operand_base.hpp> +#include <operand_csmips.hpp> + + +#include <capstone.h> +#include <mips.h> +#include <string> +#include <functional> +#include <set> +#include <algorithm> +#include <stdexcept> + +using namespace libIRDB; +using namespace std; + +#define ALLOF(a) begin(a),end(a) + +static bool isPartOfGroup(const cs_insn* the_insn, const mips_insn_group the_grp) +{ + const auto grp_it=find(ALLOF(the_insn->detail->groups), the_grp); + return grp_it!=end(the_insn->detail->groups); +} + +template<class type> +static inline type mips32InsnToImmedHelper(cs_insn* the_insn, csh handle) +{ + const auto count = cs_op_count(handle, the_insn, ARM_OP_IMM); + const auto mips = &(the_insn->detail->mips); + + 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(handle, the_insn, MIPS_OP_IMM, 1); + return mips->operands[index].imm; + } + else + throw std::logic_error(string("Called ")+__FUNCTION__+" with number of immedaites not equal 1"); +} + + +// shared code +// constructors, destructors, operators. + +void DecodedInstructionCapstoneMIPS32_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()); + auto address=(uint64_t)start_addr; + auto size=(size_t)max_len; + const uint8_t* code=(uint8_t*)data; + const auto ok = cs_disasm_iter(cs_handle->getHandle(), &code, &size, &address, insn); + if(!ok) + insn->size=0; + + const auto cs_freer=[](cs_insn * insn) -> void + { + cs_free(insn,1); + } ; + my_insn.reset(insn,cs_freer); +} + +DecodedInstructionCapstoneMIPS32_t::DecodedInstructionCapstoneMIPS32_t(const Instruction_t* i) +{ + if(!i) throw std::invalid_argument("No instruction given to DecodedInstruction_t(Instruction_t*)"); + + const auto length=i->getDataBits().size(); + const auto &databits=i->getDataBits(); + const auto data=databits.data(); + const auto address=i->getAddress()->getVirtualOffset(); + Disassemble(address,data,length); + + if(!valid()) throw std::invalid_argument("The Instruction_t::getDataBits field is not a valid instruction."); +} + +DecodedInstructionCapstoneMIPS32_t::DecodedInstructionCapstoneMIPS32_t(const virtual_offset_t start_addr, const void *data, uint32_t max_len) +{ + Disassemble(start_addr, data, max_len); +} + +DecodedInstructionCapstoneMIPS32_t::DecodedInstructionCapstoneMIPS32_t(const virtual_offset_t start_addr, const void *data, const void* endptr) +{ + const auto length=(char*)endptr-(char*)data; + Disassemble(start_addr,data,length); +} + +DecodedInstructionCapstoneMIPS32_t::DecodedInstructionCapstoneMIPS32_t(const DecodedInstructionCapstoneMIPS32_t& copy) +{ + *this=copy; +} + +DecodedInstructionCapstoneMIPS32_t::DecodedInstructionCapstoneMIPS32_t(const shared_ptr<void> &p_my_insn) +{ + my_insn = p_my_insn; +} + +DecodedInstructionCapstoneMIPS32_t::~DecodedInstructionCapstoneMIPS32_t() +{ + // no need to cs_free(my_insn) because shared pointer will do that for us! +} + +DecodedInstructionCapstoneMIPS32_t& DecodedInstructionCapstoneMIPS32_t::operator=(const DecodedInstructionCapstoneMIPS32_t& copy) +{ + my_insn=copy.my_insn; + return *this; +} + +// public methods + +string DecodedInstructionCapstoneMIPS32_t::getDisassembly() const +{ + + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + auto full_str=getMnemonic()+" "+the_insn->op_str; + + return full_str; +} + +bool DecodedInstructionCapstoneMIPS32_t::valid() const +{ + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + return the_insn->size!=0; +} + +uint32_t DecodedInstructionCapstoneMIPS32_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 DecodedInstructionCapstoneMIPS32_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() || isPartOfGroup(the_insn,MIPS_GRP_JUMP); +} + +bool DecodedInstructionCapstoneMIPS32_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()); + assert(the_insn); + return isPartOfGroup(the_insn, MIPS_GRP_CALL); + +} + +bool DecodedInstructionCapstoneMIPS32_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()); + return isPartOfGroup(the_insn, MIPS_GRP_JUMP) && getMnemonic()=="b"; +} + +bool DecodedInstructionCapstoneMIPS32_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()); + assert(the_insn); + return isPartOfGroup(the_insn, MIPS_GRP_JUMP) && !isUnconditionalBranch(); +} + +bool DecodedInstructionCapstoneMIPS32_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()); + assert(the_insn); + return isPartOfGroup(the_insn, MIPS_GRP_RET); +} + +bool DecodedInstructionCapstoneMIPS32_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 &mips = (the_insn->detail->mips); + return 0 <= op_num && op_num < mips.op_count; +} + +// 0-based. first operand is numbered 0. +shared_ptr<DecodedOperand_t> DecodedInstructionCapstoneMIPS32_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<DecodedOperand_t>(new DecodedOperandCapstoneMIPS32_t(my_insn,(uint8_t)op_num)); + +} + +DecodedOperandVector_t DecodedInstructionCapstoneMIPS32_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()); + const auto &mips = (the_insn->detail->mips); + const auto opcount=mips.op_count; + + auto ret_val=DecodedOperandVector_t(); + + for(auto i=0;i<opcount;i++) + ret_val.push_back(getOperand(i)); + + return ret_val; +} + +string DecodedInstructionCapstoneMIPS32_t::getMnemonic() const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + + // return the new string. + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + return the_insn->mnemonic; + + +} + + +int64_t DecodedInstructionCapstoneMIPS32_t::getImmediate() const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + + // direct calls and jumps have a "immediate" which is really an address" those are returned by getAddress + if(isCall() || isPartOfGroup(the_insn, MIPS_GRP_JUMP) ) + return 0; + + return mips32InsnToImmedHelper<int64_t>(the_insn, cs_handle->getHandle()); +} + + +virtual_offset_t DecodedInstructionCapstoneMIPS32_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() || isPartOfGroup(the_insn, MIPS_GRP_JUMP) ) + { + const auto mnemonic=getMnemonic(); + if( mnemonic=="tbnz" || mnemonic=="tbz") + return getOperand(2)->getConstant(); + return mips32InsnToImmedHelper<int64_t>(the_insn, cs_handle->getHandle()); + } + return 0; + +} + + +bool DecodedInstructionCapstoneMIPS32_t::setsStackPointer() const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + + if(!hasOperand(0)) return false; + + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &mips = (the_insn->detail->mips); + return (mips.operands[0].type==MIPS_OP_REG && mips.operands[0].reg==MIPS_REG_SP); +} + +uint32_t DecodedInstructionCapstoneMIPS32_t::getPrefixCount() const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + return 0; +} + +IRDB_SDK::VirtualOffset_t DecodedInstructionCapstoneMIPS32_t::getMemoryDisplacementOffset(const IRDB_SDK::DecodedOperand_t* t, const IRDB_SDK::Instruction_t* insn) const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + assert(0); +} + +bool DecodedInstructionCapstoneMIPS32_t::hasRelevantRepPrefix() const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + return false; +} + +bool DecodedInstructionCapstoneMIPS32_t::hasRelevantRepnePrefix() const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + return false; +} + +bool DecodedInstructionCapstoneMIPS32_t::hasRelevantOperandSizePrefix() const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + return false; +} + +bool DecodedInstructionCapstoneMIPS32_t::hasRexWPrefix() const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + return false; +} + +bool DecodedInstructionCapstoneMIPS32_t::hasImplicitlyModifiedRegs() const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + return false; +} + +DecodedInstructionCapstoneMIPS_t::CapstoneHandle_t* DecodedInstructionCapstoneMIPS_t::cs_handle=nullptr; diff --git a/irdb-libs/libIRDB-core/src/decode_csmips64.cpp b/irdb-libs/libIRDB-core/src/decode_csmips64.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fcf7282e0a6f98142ca799f4e56c1abbfb4caec0 --- /dev/null +++ b/irdb-libs/libIRDB-core/src/decode_csmips64.cpp @@ -0,0 +1,355 @@ + +#include <libIRDB-core.hpp> +#include <decode_base.hpp> +#include <decode_csmips.hpp> +#include <operand_base.hpp> +#include <operand_csmips.hpp> + + +#include <capstone.h> +#include <mips64.h> +#include <string> +#include <functional> +#include <set> +#include <algorithm> +#include <stdexcept> + +using namespace libIRDB; +using namespace std; + +#define ALLOF(a) begin(a),end(a) +static const auto MIPS64_REG_PC=(mips64_reg)(MIPS64_REG_ENDING+1); + + +DecodedInstructionCapstoneMIPS_t::CapstoneHandle_t* DecodedInstructionCapstoneMIPS_t::cs_handle=nullptr; + +DecodedInstructionCapstoneMIPS_t::CapstoneHandle_t::CapstoneHandle_t(FileIR_t* firp) +{ + static_assert(sizeof(csh)==sizeof(handle), "Capstone handle size is unexpected. Has CS changed?"); + + const auto mode = CS_MODE_LITTLE_ENDIAN; + const auto arch = + firp->getArchitectureBitWidth() == 64 ? CS_ARCH_MIPS64 : + firp->getArchitectureBitWidth() == 32 ? CS_ARCH_MIPS : + throw invalid_argument("Unknown bit width: "+to_string(firp->getArchitectureBitWidth())); + const auto err = cs_open(arch, mode, (csh*)&handle); + if (err) + { + const auto s=string("Failed on cs_open() with error returned: ")+to_string(err)+"\n"; + throw std::runtime_error(s); + } + cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); + cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL); +} + +static bool isPartOfGroup(const cs_insn* the_insn, const mips64_insn_group the_grp) +{ + const auto grp_it=find(ALLOF(the_insn->detail->groups), the_grp); + return grp_it!=end(the_insn->detail->groups); +} + +static bool isArm64Jmp(cs_insn* the_insn) +{ + return isPartOfGroup(the_insn,MIPS64_GRP_JUMP); +} + +template<class type> +static inline type mips64InsnToImmedHelper(cs_insn* the_insn, csh handle) +{ + const auto count = cs_op_count(handle, the_insn, MIPS64_OP_IMM); + const auto mips = &(the_insn->detail->mips64); + + 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(handle, the_insn, MIPS64_OP_IMM, 1); + return mips->operands[index].imm; + } + else + throw std::logic_error(string("Called ")+__FUNCTION__+" with number of immedaites not equal 1"); +} + + +// shared code +// constructors, destructors, operators. + +void DecodedInstructionCapstoneMIPS64_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()); + auto address=(uint64_t)start_addr; + auto size=(size_t)max_len; + const uint8_t* code=(uint8_t*)data; + const auto ok = cs_disasm_iter(cs_handle->getHandle(), &code, &size, &address, insn); + if(!ok) + insn->size=0; + + auto &op0 = (insn->detail->mips64.operands[0]); // might change these. + auto &op1 = (insn->detail->mips64.operands[1]); + + const auto mnemonic=string(insn->mnemonic); + const auto is_ldr_type = mnemonic=="ldr" || mnemonic=="ldrsw" ; + if(is_ldr_type && op1.type==MIPS64_OP_IMM) + { + // no, this is a pcrel load. + const auto imm=op1.imm; + op1.type=MIPS64_OP_MEM; + op1.mem.base=MIPS64_REG_PC; + op1.mem.index=MIPS64_REG_INVALID; + op1.mem.disp=imm; + } + if(mnemonic=="prfm" && op0.type==MIPS64_OP_IMM) + { + // no, this is a pcrel load. + const auto imm=op0.imm; + op0.type=MIPS64_OP_MEM; + op0.mem.base=MIPS64_REG_PC; + op0.mem.index=MIPS64_REG_INVALID; + op0.mem.disp=imm; + } + + + const auto cs_freer=[](cs_insn * insn) -> void + { + cs_free(insn,1); + } ; + my_insn.reset(insn,cs_freer); +} + +DecodedInstructionCapstoneMIPS64_t::DecodedInstructionCapstoneMIPS64_t(const Instruction_t* i) +{ + if(!i) throw std::invalid_argument("No instruction given to DecodedInstruction_t(Instruction_t*)"); + + const auto length=i->getDataBits().size(); + const auto &databits=i->getDataBits(); + const auto data=databits.data(); + const auto address=i->getAddress()->getVirtualOffset(); + Disassemble(address,data,length); + + if(!valid()) throw std::invalid_argument("The Instruction_t::getDataBits field is not a valid instruction."); +} + +DecodedInstructionCapstoneMIPS64_t::DecodedInstructionCapstoneMIPS64_t(const virtual_offset_t start_addr, const void *data, uint32_t max_len) +{ + Disassemble(start_addr, data, max_len); +} + +DecodedInstructionCapstoneMIPS64_t::DecodedInstructionCapstoneMIPS64_t(const virtual_offset_t start_addr, const void *data, const void* endptr) +{ + const auto length=(char*)endptr-(char*)data; + Disassemble(start_addr,data,length); +} + +DecodedInstructionCapstoneMIPS64_t::DecodedInstructionCapstoneMIPS64_t(const DecodedInstructionCapstoneMIPS64_t& copy) +{ + *this=copy; +} + +DecodedInstructionCapstoneMIPS64_t::DecodedInstructionCapstoneMIPS64_t(const shared_ptr<void> &p_my_insn) +{ + my_insn = p_my_insn; +} + +DecodedInstructionCapstoneMIPS64_t::~DecodedInstructionCapstoneMIPS64_t() +{ + // no need to cs_free(my_insn) because shared pointer will do that for us! +} + +DecodedInstructionCapstoneMIPS64_t& DecodedInstructionCapstoneMIPS64_t::operator=(const DecodedInstructionCapstoneMIPS64_t& copy) +{ + my_insn=copy.my_insn; + return *this; +} + +// public methods + +string DecodedInstructionCapstoneMIPS64_t::getDisassembly() const +{ + + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + auto full_str=getMnemonic()+" "+the_insn->op_str; + + return full_str; +} + +bool DecodedInstructionCapstoneMIPS64_t::valid() const +{ + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + return the_insn->size!=0; +} + +uint32_t DecodedInstructionCapstoneMIPS64_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 DecodedInstructionCapstoneMIPS64_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() || isArm64Jmp(the_insn); +} + +bool DecodedInstructionCapstoneMIPS64_t::isCall() const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + + const auto mnemonic=getMnemonic(); + return mnemonic=="bl" || mnemonic=="blr"; +} + +bool DecodedInstructionCapstoneMIPS64_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()); + + return isArm64Jmp(the_insn) && + (getMnemonic()=="b" || getMnemonic()=="br"); +} + +bool DecodedInstructionCapstoneMIPS64_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 isArm64Jmp(the_insn) && !isUnconditionalBranch(); +} + +bool DecodedInstructionCapstoneMIPS64_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,MIPS64_GRP_RET); +} + +bool DecodedInstructionCapstoneMIPS64_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 &mips = (the_insn->detail->mips64); + return 0 <= op_num && op_num < mips.op_count; +} + +// 0-based. first operand is numbered 0. +shared_ptr<DecodedOperand_t> DecodedInstructionCapstoneMIPS64_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<DecodedOperand_t>(new DecodedOperandCapstoneMIPS64_t(my_insn,(uint8_t)op_num)); + +} + +DecodedOperandVector_t DecodedInstructionCapstoneMIPS64_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()); + const auto &mips = (the_insn->detail->mips64); + const auto opcount=mips.op_count; + + auto ret_val=DecodedOperandVector_t(); + + for(auto i=0;i<opcount;i++) + ret_val.push_back(getOperand(i)); + + return ret_val; +} + +string DecodedInstructionCapstoneMIPS64_t::getMnemonic() const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + + // return the new string. + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + return the_insn->mnemonic; + + +} + + +int64_t DecodedInstructionCapstoneMIPS64_t::getImmediate() const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + + // direct calls and jumps have a "immediate" which is really an address" those are returned by getAddress + if(isCall() || isArm64Jmp(the_insn)) + return 0; + + return mips64InsnToImmedHelper<int64_t>(the_insn, cs_handle->getHandle()); +} + + +virtual_offset_t DecodedInstructionCapstoneMIPS64_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() || isArm64Jmp(the_insn)) + { + const auto mnemonic=getMnemonic(); + if( mnemonic=="tbnz" || mnemonic=="tbz") + return getOperand(2)->getConstant(); + return mips64InsnToImmedHelper<int64_t>(the_insn, cs_handle->getHandle()); + } + assert(0); + +} + + +bool DecodedInstructionCapstoneMIPS64_t::setsStackPointer() const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + + if(!hasOperand(0)) return false; + + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &mips = (the_insn->detail->mips64); + return (mips.operands[0].type==MIPS64_OP_REG && mips.operands[0].reg==MIPS64_REG_SP); +} + +uint32_t DecodedInstructionCapstoneMIPS64_t::getPrefixCount() const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + return 0; +} + +IRDB_SDK::VirtualOffset_t DecodedInstructionCapstoneMIPS64_t::getMemoryDisplacementOffset(const IRDB_SDK::DecodedOperand_t* t, const IRDB_SDK::Instruction_t* insn) const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + assert(0); +} + +bool DecodedInstructionCapstoneMIPS64_t::hasRelevantRepPrefix() const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + return false; +} + +bool DecodedInstructionCapstoneMIPS64_t::hasRelevantRepnePrefix() const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + return false; +} + +bool DecodedInstructionCapstoneMIPS64_t::hasRelevantOperandSizePrefix() const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + return false; +} + +bool DecodedInstructionCapstoneMIPS64_t::hasRexWPrefix() const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + return false; +} + +bool DecodedInstructionCapstoneMIPS64_t::hasImplicitlyModifiedRegs() const +{ + if(!valid()) throw std::logic_error(string("Called ")+__FUNCTION__+" on invalid instruction"); + return false; +} + diff --git a/irdb-libs/libIRDB-core/src/operand_csmips32.cpp b/irdb-libs/libIRDB-core/src/operand_csmips32.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4a2266d52d244025b2d7ce7ed961ff799118bf0c --- /dev/null +++ b/irdb-libs/libIRDB-core/src/operand_csmips32.cpp @@ -0,0 +1,334 @@ + +#include <libIRDB-core.hpp> +#include <memory> +#include <decode_base.hpp> +#include <decode_csmips.hpp> +#include <operand_base.hpp> +#include <operand_csmips.hpp> + + +using namespace std; +using namespace libIRDB; + +#include <capstone.h> + +DecodedOperandCapstoneMIPS32_t::DecodedOperandCapstoneMIPS32_t( const shared_ptr<void> & p_my_insn, uint8_t p_op_num) + : DecodedOperandCapstoneMIPS_t(p_my_insn,p_op_num) +{ + +} + +DecodedOperandCapstoneMIPS32_t::~DecodedOperandCapstoneMIPS32_t() +{ +} + + +bool DecodedOperandCapstoneMIPS32_t::isConstant() const +{ + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips.operands[op_num]); + return op.type==MIPS_OP_IMM; +} + +uint64_t DecodedOperandCapstoneMIPS32_t::getConstant() const +{ + if(!isConstant()) throw 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->mips.operands[op_num]); + return op.imm; +} + +string DecodedOperandCapstoneMIPS32_t::getString() const +{ + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips.operands[op_num]); + const auto handle=DecodedInstructionCapstoneMIPS32_t::cs_handle->getHandle(); + + switch(op.type) + { + case MIPS_OP_REG: + return string(cs_reg_name(handle, op.reg)); + case MIPS_OP_IMM: + return to_string(op.imm); + case MIPS_OP_MEM: + { + string ret_val; + if (op.mem.base != MIPS_REG_INVALID) + ret_val+=cs_reg_name(handle, op.mem.base); + + if (op.mem.disp != 0) + ret_val+=" + "+ to_string(op.mem.disp); + + ret_val += " lsl/ror? ?? "; + + return ret_val; + } + default: + assert(0); + } +} + +bool DecodedOperandCapstoneMIPS32_t::isRegister() const +{ + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips.operands[op_num]); + return op.type==MIPS_OP_REG; +} + +bool DecodedOperandCapstoneMIPS32_t::isGeneralPurposeRegister() const +{ + const auto gp_regs=set<mips_reg>({ + MIPS_REG_0, + MIPS_REG_1, + MIPS_REG_2, + MIPS_REG_3, + MIPS_REG_4, + MIPS_REG_5, + MIPS_REG_6, + MIPS_REG_7, + MIPS_REG_8, + MIPS_REG_9, + MIPS_REG_10, + MIPS_REG_11, + MIPS_REG_12, + MIPS_REG_13, + MIPS_REG_14, + MIPS_REG_15, + MIPS_REG_16, + MIPS_REG_17, + MIPS_REG_18, + MIPS_REG_19, + MIPS_REG_20, + MIPS_REG_21, + MIPS_REG_22, + MIPS_REG_23, + MIPS_REG_24, + MIPS_REG_25, + MIPS_REG_26, + MIPS_REG_27, + MIPS_REG_28, + MIPS_REG_29, + MIPS_REG_30, + MIPS_REG_31, + }); + + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips.operands[op_num]); + return isRegister() && gp_regs.find((mips_reg)op.reg)!=end(gp_regs); + +} + +bool DecodedOperandCapstoneMIPS32_t::isMmxRegister() const +{ + return false; +} + +bool DecodedOperandCapstoneMIPS32_t::isFpuRegister() const +{ + const auto fpu_regs=set<mips_reg>({ + MIPS_REG_F0, + MIPS_REG_F1, + MIPS_REG_F2, + MIPS_REG_F3, + MIPS_REG_F4, + MIPS_REG_F5, + MIPS_REG_F6, + MIPS_REG_F7, + MIPS_REG_F8, + MIPS_REG_F9, + MIPS_REG_F10, + MIPS_REG_F11, + MIPS_REG_F12, + MIPS_REG_F13, + MIPS_REG_F14, + MIPS_REG_F15, + MIPS_REG_F16, + MIPS_REG_F17, + MIPS_REG_F18, + MIPS_REG_F19, + MIPS_REG_F20, + MIPS_REG_F21, + MIPS_REG_F22, + MIPS_REG_F23, + MIPS_REG_F24, + MIPS_REG_F25, + MIPS_REG_F26, + MIPS_REG_F27, + MIPS_REG_F28, + MIPS_REG_F29, + MIPS_REG_F30, + MIPS_REG_F31, + }); + + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips.operands[op_num]); + return isRegister() && fpu_regs.find((mips_reg)op.reg)!=end(fpu_regs); +} + +bool DecodedOperandCapstoneMIPS32_t::isSseRegister() const +{ + return false; +} + +bool DecodedOperandCapstoneMIPS32_t::isAvxRegister() const +{ + return false; +} + +bool DecodedOperandCapstoneMIPS32_t::isZmmRegister() const +{ + return false; +} + +bool DecodedOperandCapstoneMIPS32_t::isSpecialRegister() const +{ + const auto special_regs=set<mips_reg>({ + MIPS_REG_AC0, + MIPS_REG_AC1, + MIPS_REG_AC2, + MIPS_REG_AC3, + MIPS_REG_CC0, + MIPS_REG_CC1, + MIPS_REG_CC2, + MIPS_REG_CC3, + MIPS_REG_CC4, + MIPS_REG_CC5, + MIPS_REG_CC6, + MIPS_REG_CC7, + + }); + + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips.operands[op_num]); + return isRegister() && special_regs.find((mips_reg)op.reg)!=end(special_regs); + return false; +} + +bool DecodedOperandCapstoneMIPS32_t::isSegmentRegister() const +{ + return false; +} + + + +uint32_t DecodedOperandCapstoneMIPS32_t::getRegNumber() const +{ + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips.operands[op_num]); + return op.reg; +} + +bool DecodedOperandCapstoneMIPS32_t::isMemory() const +{ + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips.operands[op_num]); + return op.type==MIPS_OP_MEM; + +} + +bool DecodedOperandCapstoneMIPS32_t::hasBaseRegister() const +{ + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips.operands[op_num]); + return isMemory() && op.mem.base!=MIPS_REG_INVALID; + +} + +bool DecodedOperandCapstoneMIPS32_t::hasIndexRegister() const +{ + return false; +} + +uint32_t DecodedOperandCapstoneMIPS32_t::getBaseRegister() const +{ + if(!isMemory()) throw 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->mips.operands[op_num]); + return op.mem.base; +} + +uint32_t DecodedOperandCapstoneMIPS32_t::getIndexRegister() const +{ + throw logic_error(string("Cannot ")+__FUNCTION__+" of operand with no index register"); +} + +uint32_t DecodedOperandCapstoneMIPS32_t::getScaleValue() const +{ + assert(0); +} + +bool DecodedOperandCapstoneMIPS32_t::hasMemoryDisplacement() const +{ + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips.operands[op_num]); + return op.mem.disp!=0; + +} // end of DecodedOperandCapstoneMIPS32_t::hasMemoryDisplacement() + +virtual_offset_t DecodedOperandCapstoneMIPS32_t::getMemoryDisplacement() const +{ + if(!isMemory()) throw 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->mips.operands[op_num]); + return op.mem.disp; +} + +bool DecodedOperandCapstoneMIPS32_t::isPcrel() const +{ + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips.operands[op_num]); + + // covers ldr, ldrsw, prfm + // note: capstone's reports ldr, ldrsw, and prfm as using an imm, when they actually access memory. + // jdh fixed this in the IRDB's Disassemble routine + if(isMemory() && op.mem.base==MIPS_REG_PC) + return true; + + return isRegister() && getRegNumber()==MIPS_REG_PC; // check to see if it's actually the pc + +} + +/* in bytes */ +uint32_t DecodedOperandCapstoneMIPS32_t::getMemoryDisplacementEncodingSize() const +{ + if(!isMemory()) throw logic_error(string("Cannot ")+__FUNCTION__+" of non-memory operand"); + assert(0); +} + +uint32_t DecodedOperandCapstoneMIPS32_t::getArgumentSizeInBytes() const +{ + return false; +} + +uint32_t DecodedOperandCapstoneMIPS32_t::getArgumentSizeInBits() const +{ + return getArgumentSizeInBytes()*8; +} + +bool DecodedOperandCapstoneMIPS32_t::hasSegmentRegister() const +{ + return false; +} + +uint32_t DecodedOperandCapstoneMIPS32_t::getSegmentRegister() const +{ + throw logic_error(string("Cannot ")+__FUNCTION__+" on MIPS architecture"); +} + +bool DecodedOperandCapstoneMIPS32_t::isRead() const +{ + //const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + // const auto &op = (the_insn->detail->mips.operands[op_num]); + // return (op.access & CS_AC_READ)!=0; + return op_num > 0; +} + +bool DecodedOperandCapstoneMIPS32_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->mips.operands[op_num]); + //return (op.access & CS_AC_WRITE)!=0; + return op_num == 0; +} diff --git a/irdb-libs/libIRDB-core/src/operand_csmips64.cpp b/irdb-libs/libIRDB-core/src/operand_csmips64.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8d4f0b8f3664c2167d898fa3b0d42bb2ab9f1448 --- /dev/null +++ b/irdb-libs/libIRDB-core/src/operand_csmips64.cpp @@ -0,0 +1,308 @@ + +#include <libIRDB-core.hpp> +#include <memory> +#include <decode_base.hpp> +#include <decode_csmips.hpp> +#include <operand_base.hpp> +#include <operand_csmips.hpp> + + +using namespace std; +using namespace libIRDB; + +#include <capstone.h> +static const auto MIPS64_REG_PC=(mips64_reg)(MIPS64_REG_ENDING+1); + + +DecodedOperandCapstoneMIPS64_t::DecodedOperandCapstoneMIPS64_t( const shared_ptr<void> & p_my_insn, uint8_t p_op_num) + : DecodedOperandCapstoneMIPS_t(p_my_insn,p_op_num) +{ + +} + +DecodedOperandCapstoneMIPS64_t::~DecodedOperandCapstoneMIPS64_t() +{ +} + + +bool DecodedOperandCapstoneMIPS64_t::isConstant() const +{ + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips64.operands[op_num]); + return op.type==MIPS64_OP_IMM; +} + +uint64_t DecodedOperandCapstoneMIPS64_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->mips64.operands[op_num]); + return op.imm; +} + +string DecodedOperandCapstoneMIPS64_t::getString() const +{ + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips64.operands[op_num]); + const auto handle=DecodedInstructionCapstoneMIPS64_t::cs_handle->getHandle(); + + switch(op.type) + { + case MIPS64_OP_REG: + return string(cs_reg_name(handle, op.reg)); + case MIPS64_OP_REG_MRS: + case MIPS64_OP_REG_MSR: + case MIPS64_OP_FP: + return string("fpcr"); + case MIPS64_OP_IMM: + return to_string(op.imm); + case MIPS64_OP_MEM: + { + string ret_val; + if (op.mem.base != MIPS64_REG_INVALID) + ret_val+=cs_reg_name(handle, op.mem.base); + + if (op.mem.index != MIPS64_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 DecodedOperandCapstoneMIPS64_t::isRegister() const +{ + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips64.operands[op_num]); + return op.type==MIPS64_OP_REG; +} + +bool DecodedOperandCapstoneMIPS64_t::isGeneralPurposeRegister() const +{ + const auto gp_regs=set<mips64_reg>({ + MIPS64_REG_X29, MIPS64_REG_X30, MIPS64_REG_SP, MIPS64_REG_WSP, MIPS64_REG_WZR, MIPS64_REG_XZR, + MIPS64_REG_W0, MIPS64_REG_W1, MIPS64_REG_W2, MIPS64_REG_W3, MIPS64_REG_W4, MIPS64_REG_W5, MIPS64_REG_W6, MIPS64_REG_W7, + MIPS64_REG_W8, MIPS64_REG_W9, MIPS64_REG_W10, MIPS64_REG_W11, MIPS64_REG_W12, MIPS64_REG_W13, MIPS64_REG_W14, MIPS64_REG_W15, + MIPS64_REG_W16, MIPS64_REG_W17, MIPS64_REG_W18, MIPS64_REG_W19, MIPS64_REG_W20, MIPS64_REG_W21, MIPS64_REG_W22, MIPS64_REG_W23, + MIPS64_REG_W24, MIPS64_REG_W25, MIPS64_REG_W26, MIPS64_REG_W27, MIPS64_REG_W28, MIPS64_REG_W29, MIPS64_REG_W30, + MIPS64_REG_X0, MIPS64_REG_X1, MIPS64_REG_X2, MIPS64_REG_X3, MIPS64_REG_X4, MIPS64_REG_X5, MIPS64_REG_X6, MIPS64_REG_X7, + MIPS64_REG_X8, MIPS64_REG_X9, MIPS64_REG_X10, MIPS64_REG_X11, MIPS64_REG_X12, MIPS64_REG_X13, MIPS64_REG_X14, MIPS64_REG_X15, + MIPS64_REG_X16, MIPS64_REG_X17, MIPS64_REG_X18, MIPS64_REG_X19, MIPS64_REG_X20, MIPS64_REG_X21, MIPS64_REG_X22, MIPS64_REG_X23, + MIPS64_REG_X24, MIPS64_REG_X25, MIPS64_REG_X26, MIPS64_REG_X27, MIPS64_REG_X28, + }); + + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips64.operands[op_num]); + return isRegister() && gp_regs.find(op.reg)!=end(gp_regs); + +} + +bool DecodedOperandCapstoneMIPS64_t::isMmxRegister() const +{ + return false; +} + +bool DecodedOperandCapstoneMIPS64_t::isFpuRegister() const +{ + const auto fpu_regs=set<mips64_reg>({ + MIPS64_REG_B0, MIPS64_REG_B1, MIPS64_REG_B2, MIPS64_REG_B3, MIPS64_REG_B4, MIPS64_REG_B5, MIPS64_REG_B6, MIPS64_REG_B7, + MIPS64_REG_B8, MIPS64_REG_B9, MIPS64_REG_B10, MIPS64_REG_B11, MIPS64_REG_B12, MIPS64_REG_B13, MIPS64_REG_B14, MIPS64_REG_B15, + MIPS64_REG_B16, MIPS64_REG_B17, MIPS64_REG_B18, MIPS64_REG_B19, MIPS64_REG_B20, MIPS64_REG_B21, MIPS64_REG_B22, MIPS64_REG_B23, + MIPS64_REG_B24, MIPS64_REG_B25, MIPS64_REG_B26, MIPS64_REG_B27, MIPS64_REG_B28, MIPS64_REG_B29, MIPS64_REG_B30, MIPS64_REG_B31, + MIPS64_REG_H0, MIPS64_REG_H1, MIPS64_REG_H2, MIPS64_REG_H3, MIPS64_REG_H4, MIPS64_REG_H5, MIPS64_REG_H6, MIPS64_REG_H7, + MIPS64_REG_H8, MIPS64_REG_H9, MIPS64_REG_H10, MIPS64_REG_H11, MIPS64_REG_H12, MIPS64_REG_H13, MIPS64_REG_H14, MIPS64_REG_H15, + MIPS64_REG_H16, MIPS64_REG_H17, MIPS64_REG_H18, MIPS64_REG_H19, MIPS64_REG_H20, MIPS64_REG_H21, MIPS64_REG_H22, MIPS64_REG_H23, + MIPS64_REG_H24, MIPS64_REG_H25, MIPS64_REG_H26, MIPS64_REG_H27, MIPS64_REG_H28, MIPS64_REG_H29, MIPS64_REG_H30, MIPS64_REG_H31, + MIPS64_REG_D0, MIPS64_REG_D1, MIPS64_REG_D2, MIPS64_REG_D3, MIPS64_REG_D4, MIPS64_REG_D5, MIPS64_REG_D6, MIPS64_REG_D7, + MIPS64_REG_D8, MIPS64_REG_D9, MIPS64_REG_D10, MIPS64_REG_D11, MIPS64_REG_D12, MIPS64_REG_D13, MIPS64_REG_D14, MIPS64_REG_D15, + MIPS64_REG_D16, MIPS64_REG_D17, MIPS64_REG_D18, MIPS64_REG_D19, MIPS64_REG_D20, MIPS64_REG_D21, MIPS64_REG_D22, MIPS64_REG_D23, + MIPS64_REG_D24, MIPS64_REG_D25, MIPS64_REG_D26, MIPS64_REG_D27, MIPS64_REG_D28, MIPS64_REG_D29, MIPS64_REG_D30, MIPS64_REG_D31, + MIPS64_REG_H0, MIPS64_REG_H1, MIPS64_REG_H2, MIPS64_REG_H3, MIPS64_REG_H4, MIPS64_REG_H5, MIPS64_REG_H6, MIPS64_REG_H7, + MIPS64_REG_H8, MIPS64_REG_H9, MIPS64_REG_H10, MIPS64_REG_H11, MIPS64_REG_H12, MIPS64_REG_H13, MIPS64_REG_H14, MIPS64_REG_H15, + MIPS64_REG_H16, MIPS64_REG_H17, MIPS64_REG_H18, MIPS64_REG_H19, MIPS64_REG_H20, MIPS64_REG_H21, MIPS64_REG_H22, MIPS64_REG_H23, + MIPS64_REG_H24, MIPS64_REG_H25, MIPS64_REG_H26, MIPS64_REG_H27, MIPS64_REG_H28, MIPS64_REG_H29, MIPS64_REG_H30, MIPS64_REG_H31, + MIPS64_REG_Q0, MIPS64_REG_Q1, MIPS64_REG_Q2, MIPS64_REG_Q3, MIPS64_REG_Q4, MIPS64_REG_Q5, MIPS64_REG_Q6, MIPS64_REG_Q7, + MIPS64_REG_Q8, MIPS64_REG_Q9, MIPS64_REG_Q10, MIPS64_REG_Q11, MIPS64_REG_Q12, MIPS64_REG_Q13, MIPS64_REG_Q14, MIPS64_REG_Q15, + MIPS64_REG_Q16, MIPS64_REG_Q17, MIPS64_REG_Q18, MIPS64_REG_Q19, MIPS64_REG_Q20, MIPS64_REG_Q21, MIPS64_REG_Q22, MIPS64_REG_Q23, + MIPS64_REG_Q24, MIPS64_REG_Q25, MIPS64_REG_Q26, MIPS64_REG_Q27, MIPS64_REG_Q28, MIPS64_REG_Q29, MIPS64_REG_Q30, MIPS64_REG_Q31, + MIPS64_REG_S0, MIPS64_REG_S1, MIPS64_REG_S2, MIPS64_REG_S3, MIPS64_REG_S4, MIPS64_REG_S5, MIPS64_REG_S6, MIPS64_REG_S7, + MIPS64_REG_S8, MIPS64_REG_S9, MIPS64_REG_S10, MIPS64_REG_S11, MIPS64_REG_S12, MIPS64_REG_S13, MIPS64_REG_S14, MIPS64_REG_S15, + MIPS64_REG_S16, MIPS64_REG_S17, MIPS64_REG_S18, MIPS64_REG_S19, MIPS64_REG_S20, MIPS64_REG_S21, MIPS64_REG_S22, MIPS64_REG_S23, + MIPS64_REG_S24, MIPS64_REG_S25, MIPS64_REG_S26, MIPS64_REG_S27, MIPS64_REG_S28, MIPS64_REG_S29, MIPS64_REG_S30, MIPS64_REG_S31, + }); + + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips64.operands[op_num]); + return isRegister() && fpu_regs.find(op.reg)!=end(fpu_regs); +} + +bool DecodedOperandCapstoneMIPS64_t::isSseRegister() const +{ + return false; +} + +bool DecodedOperandCapstoneMIPS64_t::isAvxRegister() const +{ + return false; +} + +bool DecodedOperandCapstoneMIPS64_t::isZmmRegister() const +{ + return false; +} + +bool DecodedOperandCapstoneMIPS64_t::isSpecialRegister() const +{ + const auto special_regs=set<mips64_reg>({ + MIPS64_REG_NZCV, + }); + + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips64.operands[op_num]); + return isRegister() && special_regs.find(op.reg)!=end(special_regs); + return false; +} + +bool DecodedOperandCapstoneMIPS64_t::isSegmentRegister() const +{ + return false; +} + + + +uint32_t DecodedOperandCapstoneMIPS64_t::getRegNumber() const +{ + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips64.operands[op_num]); + return op.reg; +} + +bool DecodedOperandCapstoneMIPS64_t::isMemory() const +{ + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips64.operands[op_num]); + return op.type==MIPS64_OP_MEM; + +} + +bool DecodedOperandCapstoneMIPS64_t::hasBaseRegister() const +{ + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips64.operands[op_num]); + return isMemory() && op.mem.base!=MIPS64_REG_INVALID; + +} + +bool DecodedOperandCapstoneMIPS64_t::hasIndexRegister() const +{ + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips64.operands[op_num]); + return isMemory() && op.mem.index!=MIPS64_REG_INVALID; +} + +uint32_t DecodedOperandCapstoneMIPS64_t::getBaseRegister() const +{ + 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->mips64.operands[op_num]); + return op.mem.base; +} + +uint32_t DecodedOperandCapstoneMIPS64_t::getIndexRegister() const +{ + 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->mips64.operands[op_num]); + return op.mem.index; +} + +uint32_t DecodedOperandCapstoneMIPS64_t::getScaleValue() const +{ + assert(0); +} + +bool DecodedOperandCapstoneMIPS64_t::hasMemoryDisplacement() const +{ + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips64.operands[op_num]); + return op.mem.disp!=0; + +} // end of DecodedOperandCapstoneMIPS64_t::hasMemoryDisplacement() + +virtual_offset_t DecodedOperandCapstoneMIPS64_t::getMemoryDisplacement() const +{ + 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->mips64.operands[op_num]); + return op.mem.disp; +} + +bool DecodedOperandCapstoneMIPS64_t::isPcrel() const +{ + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips64.operands[op_num]); + + // covers ldr, ldrsw, prfm + // note: capstone's reports ldr, ldrsw, and prfm as using an imm, when they actually access memory. + // jdh fixed this in the IRDB's Disassemble routine + if(isMemory() && op.mem.base==MIPS64_REG_PC) + return true; + + const auto mnemonic=string(the_insn->mnemonic); + const auto is_adr_type= mnemonic=="adr" || mnemonic=="adrp"; + if(is_adr_type && op.type==MIPS64_OP_IMM) + return true; + + return false; // no PC as general purpose reg. +} + +/* in bytes */ +uint32_t DecodedOperandCapstoneMIPS64_t::getMemoryDisplacementEncodingSize() const +{ + if(!isMemory()) throw std::logic_error(string("Cannot ")+__FUNCTION__+" of non-memory operand"); + assert(0); +} + +uint32_t DecodedOperandCapstoneMIPS64_t::getArgumentSizeInBytes() const +{ + return false; +} + +uint32_t DecodedOperandCapstoneMIPS64_t::getArgumentSizeInBits() const +{ + return getArgumentSizeInBytes()*8; +} + +bool DecodedOperandCapstoneMIPS64_t::hasSegmentRegister() const +{ + return false; +} + +uint32_t DecodedOperandCapstoneMIPS64_t::getSegmentRegister() const +{ + throw std::logic_error(string("Cannot ")+__FUNCTION__+" on MIPS architecture"); +} + +bool DecodedOperandCapstoneMIPS64_t::isRead() const +{ + const auto the_insn=static_cast<cs_insn*>(my_insn.get()); + const auto &op = (the_insn->detail->mips64.operands[op_num]); + return (op.access & CS_AC_READ)!=0; +} + +bool DecodedOperandCapstoneMIPS64_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->mips64.operands[op_num]); + return (op.access & CS_AC_WRITE)!=0; +} diff --git a/irdb-libs/meds2pdb/elfreader.cpp b/irdb-libs/meds2pdb/elfreader.cpp index 7c5f8ae323275eb59e5075fc687a2aedac26aa55..a284cfa7367a36f733f2b48b515791aa29142b8c 100644 --- a/irdb-libs/meds2pdb/elfreader.cpp +++ b/irdb-libs/meds2pdb/elfreader.cpp @@ -31,45 +31,12 @@ using namespace EXEIO; ElfReader::ElfReader(char *p_elfFile) { -// m_reader=new elfio; m_reader=new EXEIO::exeio(p_elfFile); assert(m_reader); EXEIO::dump::header(cout, *m_reader); EXEIO::dump::section_headers(cout, *m_reader); - // Initialize it -/* - bool ok = m_reader->load( p_elfFile ); - if ( ! ok ) { - std::cerr << "Can't open file:" << p_elfFile << std::endl; - assert(0); - exit(-1); - } - - - if(m_reader->get_class() == ELFCLASS32) - std::cout << "Input file is ELF32" << std::endl; - else - std::cout << "Input file is ELF64" << std::endl; - - - // List all sections of the file - int i; - ELFIO::Elf_Half nSecNo = m_reader->sections.size(); - for ( i = 0; i < nSecNo; ++i ) - { // For all sections - section* psec = m_reader->sections[i]; - m_sections.push_back(psec); - std::cout << " [" << i << "] " - << psec->get_name() - << "\t" - << psec->get_size() - << std::endl; - - } - std::cout << std::endl; -*/ } ElfReader::~ElfReader() @@ -151,6 +118,8 @@ void ElfReader::SetArchitecture() m_reader->getMachineType() == EXEIO::mtX86_64 ? IRDB_SDK::admtX86_64 : m_reader->getMachineType() == EXEIO::mtAarch64 ? IRDB_SDK::admtAarch64 : m_reader->getMachineType() == EXEIO::mtArm32 ? IRDB_SDK::admtArm32 : + m_reader->getMachineType() == EXEIO::mtMips32 ? IRDB_SDK::admtMips32 : + m_reader->getMachineType() == EXEIO::mtMips64 ? IRDB_SDK::admtMips64 : throw std::invalid_argument("Unknown architecture."); libIRDB::FileIR_t::setArchitecture(width,mt);